• 締切済み

カラー画像からグレースケール画像フォーマットの変換

カラー画像からグレースケール画像フォーマットの変換するプログラムなんですが、いまいち理解できていません。 プログラムはRGB構造体を使ってのものなんですが添削お願いいたします。 #include<stdio.h> #include<stdlib.h> typedef struct _RGB { unsigned char r; unsigned char g; unsigned char b; } RGB; int main(int argc, char *argv[]) { int x, y; unsigned char *in, *out; int i, j, Magic, level; unsigned char tmp[255]; RGB **pixels; int width = 255; int height = 255; int size = width * height; FILE *fin, *fout; if(argc != 3){ printf("Usage : %s input outpu \n", argv[0]); exit(1); } fin = fopen(argv[1], "rb"); fgets(tmp, 255, fin); if(tmp[0] != 'P'){ return 0; } sscanf(tmp, "P%d", &Magic); if(Magic < 1 || Magic > 6){ return 0; } do{ fgets(tmp, 255, fin); } while(tmp[0] == '#'); sscanf(tmp, "%d %d", &x, &y); if(x < 1 || y < 1){ return 0; } fgets(tmp, 255, fin); sscanf(tmp, "%d", &level); printf("P%d\n", &Magic); printf("%d %d\n", x, y); printf("%d\n", level); in = (unsigned char *)malloc(sizeof(unsigned char) *x*y); fread(in, sizeof(unsigned char), x*y, fin); pixels = (RGB**)malloc(width*sizeof(RGB*)); pixels[0] = (RGB* )malloc(size * sizeof(RGB)); for(i = 1; i < width; i++){ pixels[i] = pixels[i - 1] + height; } free(pixels[0]); for(i = 1; i < width * height * 3; i++){ out[i] = pixels[i][0].r * 0.299 + pixels[i][1].g * 0.587 + pixels[i][2].b * 0.114; } fout = fopen(argv[2], "wb"); fprintf(fout,"P%d\n",Magic); fprintf(fout,"# My new PGM\n"); fprintf(fout,"%d %d\n",x, y); fprintf(fout,"%d\n",level); fwrite(out, sizeof(unsigned char),x*y, fout); free(pixels); free(in); free(out); free(fin); free(fout); }

みんなの回答

noname#208507
noname#208507
回答No.1

PPM形式(カラー)からPGM形式(グレースケール)への変換ですね. いくつか気になったポイントを挙げます. 1. バイナリのPPM形式のマジックナンバーは P6 です.  つまり if(Magic < 1 || Magic > 6){  ではなく if(Magic != 6){  です. 2. 読み込むのはRGBカラーなので1画素3バイトですが,malloc()もfread()も1画素1バイトになっています.  まず   sscanf(tmp, "%d %d", &x, &y); を   sscanf(tmp, "%d %d", &width, &height); に,   if(x < 1 || y < 1){ を   if(width < 1 || height < 1){ に,   printf("%d %d\n", x, y); を   printf("%d %d\n", width, height); に  変更して,   in = (unsigned char *)malloc(sizeof(unsigned char) *x*y);   fread(in, sizeof(unsigned char), x*y, fin);  の部分を   size = width * height;   in = (unsigned char *)malloc(sizeof(unsigned char) * 3 * size);   fread(in, sizeof(unsigned char), size * 3, fin);  に直せばRGBカラーの画素列を読み込めます. 3. RGB構造体の使い方がおかしいです.  この場合は二次元配列にせず,幅✕高さの一次元配列がすっきりするでしょう.  RGB **pixels; を  RGB *pixels; に変更して,   pixels = (RGB**)malloc(width*sizeof(RGB*));   pixels[0] = (RGB* )malloc(size * sizeof(RGB));   for(i = 1; i < width; i++){    pixels[i] = pixels[i - 1] + height;   }   free(pixels[0]);   for(i = 1; i < width * height * 3; i++){    out[i] = pixels[i][0].r * 0.299 + pixels[i][1].g * 0.587 + pixels[i][2].b * 0.114;   }  の部分を   pixels = (RGB*)malloc(size * sizeof(RGB));   for(i = 0; i < size; i++){    pixels[i].r = in[i * 3];    pixels[i].g = in[i * 3 + 1];    pixels[i].b = in[i * 3 + 2];   }   out = (unsigned char *)malloc(sizeof(unsigned char) * size);   for(i = 0; i < size; i++){    out[i] = pixels[i].r * 0.299 + pixels[i].g * 0.587 + pixels[i].b * 0.114;   }  に直せばよいでしょう. 4. バイナリのPGM形式のマジックナンバーは P5 です.   fprintf(fout,"P%d\n",Magic);   fprintf(fout,"# My new PGM\n");   fprintf(fout,"%d %d\n",x, y);   fprintf(fout,"%d\n",level);   fwrite(out, sizeof(unsigned char),x*y, fout);  の部分を   fprintf(fout,"P5\n");   fprintf(fout,"# My new PGM\n");   fprintf(fout,"%d %d\n",width, height);   fprintf(fout,"%d\n",level);   fwrite(out, sizeof(unsigned char), size, fout);  に直せばよいでしょう. 5. ファイルポインタは free() ではなく fclose() で閉じます.  fin と fout の後片付けの部分です. 6. main関数の最後は return 0; で締めくくりましょう.  また,途中エラーでmain関数を終了する場合は return 1; にしましょう.  0でプログラムを終了すると正常終了,非0ならエラー終了を意味します.

関連するQ&A