- 締切済み
カラー画像からグレースケール画像フォーマットの変換
カラー画像からグレースケール画像フォーマットの変換するプログラムなんですが、いまいち理解できていません。 プログラムは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); }
- みんなの回答 (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ならエラー終了を意味します.