質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

7278閲覧

C言語での画像の縮小について

shuppi

総合スコア47

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2016/11/29 02:46

すみません;;
このプログラムを何とか「画像を縮小して表示」に直していただけないでしょうか?
画像サイズは800×480でbmpです。

何ビットか飛ばして読み込めば?だかなんだか言われて色々試してみましたが、ズームみたいになったり、画像の一部だけ表示されたりと、まったくうまくいきませんでした。

縮小した画像は保存ではなくただ表示したいだけです。
Ubuntuでやってます。

よろしくお願いします。

C

1#include <stdio.h> 2#include <stdlib.h> 3#include <fcntl.h> 4#include <sys/mman.h> 5#include <string.h> 6 7#define SCREENWIDTH 800 8#define SCREENHEIGHT 480 9#define BYTES_PER_PIXCEL 4 10#define SCREENSIZE (SCREENWIDTH * SCREENHEIGHT * BYTES_PER_PIXCEL) 11#define RGB888(r, g, b) (((r) & 0xff) << 16 | \ 12 ((g) & 0xff) << 8 | \ 13 ((b) & 0xff)) 14 15typedef struct tagBITMAPFILEHEADER{ // ビットマップファイルヘッダ 16 unsigned short bfType; // 識別子0x4d42(‘B’,‘M’) 17 unsigned long bfSize; // ファイルサイズ 18 unsigned short bfReserved1; // 使わない 19 unsigned short bfReserved2; // 使わない 20 unsigned long bfOffBits; // ファイル内の画像データ開始位置 21} __attribute__((packed)) BITMAPFILEHEADER; 22 23typedef struct tagBITMAPINFOHEADER{ // ビットマップ情報ヘッダ 24 unsigned long biSize; // 情報ヘッダサイズ 25 long biWidth; // 画像の幅 26 long biHeight; // 画像の高さ 27 unsigned short biPlanes; // プレーン数(1に固定) 28 unsigned short biBitCount; // 1ピクセルあたりのビット数 29 unsigned long biCompression; // 圧縮タイプ 30 unsigned long biSizeImage; // 画像データサイズ 31 long biXPixPerMeter; // 横1mあたりのピクセル数 32 long biYPixPerMeter; // 縦1mあたりのピクセル数 33 unsigned long biClrUsed; // パレット数 34 unsigned long biClrImporant; // 重要パレット数 35} __attribute__((packed)) BITMAPINFOHEADER; 36 37/* 38 * draw_bmp - draw bitmap image on LCD screen 39 * pfb: pointer to the framebuffer 40 * x0: x coordinates of image 41 * y0: y coordinates of image 42 * w: image width 43 * h: image height 44 * bmpdata: pointer to the image data 45 */ 46void draw_bmp(unsigned int *pfb, int x0, int y0, int w, int h, unsigned char *bmpdata) 47{ 48 int x1 = x0 + w; 49 int y1 = y0 + h; 50 int padding = (w * 3) % 4; 51 int c = 0; 52 unsigned char r, g, b; 53 int x, y; 54 55 // 開始位置から画像を表示します。 56 // 最も下のラインから始まり、 57 // 最も上のラインに向かって1ラインずつ画像データを格納します。 58 for(y = y1 - 1; y >= y0; y--){ 59 for(x = x0; x < x1; x++){ 60 // 1pixelから、R,G,B各色のカラーデータを取得します。 61 b = bmpdata[c++]; 62 g = bmpdata[c++]; 63 r = bmpdata[c++]; 64 // LCDにカラーデータを表示します。 65 pfb[y * SCREENWIDTH + x] = RGB888(r, g, b); 66 } 67 68 //1ラインのデータサイズが4の倍数にならない時は、 69 //4の倍数になるようにラインデータの末尾に1つ以上の0を付加します。 70 c += padding; 71 } 72} 73 74int main(void) { 75 int fd_in, fd_fb; 76 unsigned int *pfb; 77 unsigned char *bmpdata; 78 int datasize; 79 int x, y; 80 81 struct bmpheader_t{ 82 BITMAPFILEHEADER fh; 83 BITMAPINFOHEADER ih; 84 } bmp; 85 86 87 // 引数に設定されたファイルをオープンします。 88 // オープンに失敗した場合はエラーで終了します。 89 if ((fd_in = open("hana.bmp", O_RDONLY)) < 0) { 90 perror("open(file)"); 91 return 1; 92 } 93 94 // ビットマップヘッダに、画像データを読み込みます。 95 // 読み込みに失敗した場合はエラーで終了します。 96 if (read(fd_in, &bmp, sizeof(bmp)) != sizeof(bmp)){ 97 perror("read(file)"); 98 return 1; 99 } 100 101 // 取得した画像データより、 102 // 識別子、1ピクセルあたりのビット数、圧縮タイプ、画像の高さをチェックします。 103 if (bmp.fh.bfType != 0x4d42 || bmp.ih.biBitCount != 24 104 || bmp.ih.biCompression != 0 || bmp.ih.biHeight < 0){ 105 fprintf(stderr, "unsupported bitmap format\n"); 106 return 1; 107 } 108 109 // 取得した画像データより、 110 // 画像データの幅と高さが画面サイズよりも大きい場合はエラーで終了します。 111 if (bmp.ih.biWidth > SCREENWIDTH || bmp.ih.biHeight > SCREENHEIGHT){ 112 fprintf(stderr, "image size too big\n"); 113 return 1; 114 } 115 116 // 画像データから、ビットマップファイルのヘッダ情報のデータサイズを引いた値を 117 // データサイズとして、メモリ領域を確保します。 118 datasize = bmp.fh.bfSize - sizeof(bmp); 119 // 必要なメモリ領域を確保できない場合はエラーで終了します。 120 if (!(bmpdata = malloc(datasize))){ 121 perror("malloc"); 122 return 1; 123 } 124 125 // 確保したメモリ領域に画像データを読み込みます。 126 // 読み込みに失敗した場合はエラーで終了します。 127 if (read(fd_in, bmpdata, datasize) != datasize){ 128 perror("read(file)"); 129 free(bmpdata); 130 return 1; 131 } 132 133 //画像ファイルをクローズします。 134 close(fd_in); 135 136 // フレームバッファをオープンします。 137 // オープンに失敗した場合はエラーで終了します。 138 if ((fd_fb = open("/dev/fb0", O_RDWR)) < 0) { 139 perror("open(fb)"); 140 free(bmpdata); 141 return 1; 142 } 143 144 // mmapによりバッファの先頭アドレスを取得します。 145 pfb = mmap(0, SCREENSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd_fb, 0); 146 // 取得に失敗した場合はエラーで終了します。 147 if (pfb == MAP_FAILED){ 148 perror("mmap"); 149 free(bmpdata); 150 return 1; 151 } 152 153 // LCDの画面表示を全て消去するために、 154 // 取得したアドレスから確保領域を0で初期化します。 155 memset(pfb, 0, SCREENSIZE); 156 157 // 画像がLCDの中央に表示されるようにx, yを設定します。 158 x = (SCREENWIDTH - bmp.ih.biWidth) / 2; 159 y = (SCREENHEIGHT - bmp.ih.biHeight) / 2; 160 161 // LCDに画像を表示します。 162 draw_bmp(pfb, x, y, bmp.ih.biWidth, bmp.ih.biHeight, bmpdata); 163 164 // フレームバッファのために確保した領域を開放します。 165 munmap(pfb, SCREENSIZE); 166 // フレームバッファをクローズします。 167 close(fd_fb); 168 // 画像表示に必要なメモリ領域を開放します。 169 free(bmpdata); 170 171 return 0; 172} 173

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ikedas

2016/11/29 14:42

提示されたプログラムはどなたか他の方の書いたものでしょうか。そうであれば、プログラムの出所 (書籍なら著者名・書名・ページ数、ウェブならURL) を教えて下さい。
guest

回答2

0

ベストアンサー

Q. 「ここに記載されたコード」で、どのような結果になりましたか? 一部表示ですか? それともスキマだらけ?

…ってのを書いてくださると答えやすいです。ここだけ見ても、どのようなコードを試して、どのような結果になったか分からないです。

まあ、それだけでは身も蓋もないので、ヒントを少々。Linuxのデバイス操作は詳しくないですが、要するに、2重forループの中で、画素の取得、描画をしていますね? ここをいじればいいのです。

まず、c, x, yなんて分かりにくい変数はやめます。i = x-x0, j = y-y0とします。
ループ条件は、i=0; i<w; i++j=h-1; j>=0; j--です。

C

1b = bmpdata[i*3 + j*(w*3+padding) + 0]; 2g = bmpdata[i*3 + j*(w*3+padding) + 1]; 3r = bmpdata[i*3 + j*(w*3+padding) + 2]; 4pfb[(j + y0) * SCREENWIDTH + (i + x0)] = RGB888(r, g, b); 5```です。これで好きな画素にアクセスできるようになりました。 6次に、描画を工夫します。例えば1ピクセルおきに描画するのであれば、 7```C 8pfb[(j / 2 + y0) * SCREENWIDTH + (i / 2 + x0)] = RGB888(r, g, b); 9```としたうえで、ループ変数の変化をi++やj--からi+=2やj-=2に変えてあげればピクセルを「飛ばす」ことができます。 10 11一応、参考になるサイトを書いておきます。 12http://ishidate.my.coocan.jp/vcpp10_g6/vcpp10_g6.htm 13以前はもっとC++に密着した、わかりやすく勉強になるページだったのですが…時代の流れですかね。まあ、10年経った今でも、エッセンスは残っているので読めばヒントになると思います。

投稿2016/11/30 07:03

編集2016/11/30 07:05
majiponi

総合スコア1720

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shuppi

2016/12/01 07:20

ありがとうございます。 とても助かりました。 画像が上下反転してしまいますが、縮小されて表示できました。 void draw_bmp(unsigned int *pfb, int x0, int y0, int w, int h, unsigned char *bmpdata) { int i = i - x0; int j = j - y0; int padding = (w * 3) % 4; unsigned char r, g, b; // 開始位置から画像を表示します。 // 最も下のラインから始まり、 // 最も上のラインに向かって1ラインずつ画像データを格納します。 for(j = h - 1; j >= 0; j -= 2){ for(i = 0; i < w; i += 2){ // 1pixelから、R,G,B各色のカラーデータを取得します。 b = bmpdata[i * 3 + j * (w * 3 + padding) + 0]; g = bmpdata[i * 3 + j * (w * 3 + padding) + 1]; r = bmpdata[i * 3 + j * (w * 3 + padding) + 2]; // LCDにカラーデータを表示します。 pfb[(j / 2 + y0) * SCREENWIDTH + (i / 2 + x0)] = RGB888(r, g, b); } } } たぶん、下のラインから取得した画素が描画する時に上のラインから描画されているから上下反転しているのではないかと思いました。 どこがおかしいのでしょうか。
guest

0

単純に間引いたりして縮小すると綺麗に表示されないです。

他力本願ですが
参考サイトです。
https://pokosho.com/t/image/10/

投稿2016/11/29 09:17

7L4QOI

総合スコア12

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問