ページ 11

C言語による画像処理 画像サイズ変更

Posted: 2013年12月23日(月) 13:17
by Mr.beginner
C言語で,画像処理の勉強を行っています.画像サイズを変更するプログラムを作成しましたが,出力画像が添付した画像のように,X_SIZEが1/4になったのですが,残りの部分が黒くなってしまいました.
定義箇所をunsigned char screen[Y_SIZE][X_SIZE][3],compress[Y_SIZE][X_SIZE/4][3];,書き込みをfwrite(compress,1,(X_SIZE/4)*Y_SIZE*3,fp);としてみたのですが,保存されませんでした・・・

この黒色の部分を消したいのですが,どなたかご教授お願いします.

以下に,作成したプログラムを載せておきます.

コード:

#include <stdio.h>
#include <stdlib.h>
#define X_SIZE 1916/*画像の横サイズを定義*/
#define Y_SIZE 181/*画像の縦サイズを定義*/

unsigned char screen[Y_SIZE][X_SIZE][3],compress[Y_SIZE][X_SIZE][3];

int main() 
{
 FILE *fp;
 unsigned char header[54];
 char input_file[100],henkan_file[100];

 /*画像ファイル読み込み*/
 printf("処理を行う画像ファイル名:.(拡張子:bmp)\n---");
 scanf("%s",input_file);
 printf("処理を行う画像ファイル:「 %s 」.\n\n",input_file);
 fp=fopen(input_file,"rb"); 
 if((fp=fopen(input_file,"rb"))==NULL){
 printf("画像ファイルが正常に開けませんでした.\n");
 exit(1);
 }
 fread(header,1,54,fp);
 fread(screen,1,X_SIZE*Y_SIZE*3,fp);
 fclose(fp);

 /*サイズ変更*/
 int x,y,i;
 for(i=0;i<3;i++){
  for(y=0;y<Y_SIZE;y++){
   for(x=0;x<X_SIZE/4;x++){
    compress[y][x][i]= (screen[y][x*4+0][i] +screen[y][x*4+1][i] +screen[y][x*4+2][i] +screen[y][x*4+3][i]) /4;
   }
  }
 }
 /*画像ファイル保存*/
 printf("保存する画像ファイル名:.(拡張子:bmp)\n---");
 scanf("%s",henkan_file);
 fp=fopen(henkan_file,"wb");
 if((fp=fopen(henkan_file,"wb"))==NULL){
 printf("画像ファイルが正常に開けませんでした.\n");
 exit(1);
 } 
 fwrite(header,1,54,fp);
 fwrite(compress,1,X_SIZE*Y_SIZE*3,fp);
 fclose(fp);
 printf("画像ファイル「 %s 」を保存しました.\n",henkan_file);
 printf("全ての作業が終了しました.\n");
 
 return 0;
}

Re: C言語による画像処理 画像サイズ変更

Posted: 2013年12月23日(月) 14:11
by softya(ソフト屋)
X_SIZEが1/4になるのなら
compress[Y_SIZE][X_SIZE/4][3];
では無いでしょうか?
となると出力も
fwrite(compress,1,X_SIZE/4*Y_SIZE*3,fp);
なのでは?

あとインデントも綺麗に揃えて頂くと読みやすくなります。

コード:

#include <stdio.h>
#include <stdlib.h>
#define X_SIZE 1916/*画像の横サイズを定義*/
#define Y_SIZE 181/*画像の縦サイズを定義*/

unsigned char screen[Y_SIZE][X_SIZE][3], compress[Y_SIZE][X_SIZE][3];

int main() {
	FILE *fp;
	unsigned char header[54];
	char input_file[100], henkan_file[100];

	/*画像ファイル読み込み*/
	printf( "処理を行う画像ファイル名:.(拡張子:bmp)\n---" );
	scanf( "%s", input_file );
	printf( "処理を行う画像ファイル:「 %s 」.\n\n", input_file );
	fp = fopen( input_file, "rb" );
	if( ( fp = fopen( input_file, "rb" ) ) == NULL ) {
		printf( "画像ファイルが正常に開けませんでした.\n" );
		exit( 1 );
	}
	fread( header, 1, 54, fp );
	fread( screen, 1, X_SIZE * Y_SIZE * 3, fp );
	fclose( fp );

	/*サイズ変更*/
	int x, y, i;
	for( i = 0; i < 3; i++ ) {
		for( y = 0; y < Y_SIZE; y++ ) {
			for( x = 0; x < X_SIZE / 4; x++ ) {
				compress[y][x][i] = ( screen[y][x * 4 + 0][i] + screen[y][x * 4 + 1][i] + screen[y][x * 4 + 2][i] + screen[y][x * 4 + 3][i] ) / 4;
			}
		}
	}
	/*画像ファイル保存*/
	printf( "保存する画像ファイル名:.(拡張子:bmp)\n---" );
	scanf( "%s", henkan_file );
	fp = fopen( henkan_file, "wb" );
	if( ( fp = fopen( henkan_file, "wb" ) ) == NULL ) {
		printf( "画像ファイルが正常に開けませんでした.\n" );
		exit( 1 );
	}
	fwrite( header, 1, 54, fp );
	fwrite( compress, 1, X_SIZE * Y_SIZE * 3, fp );
	fclose( fp );
	printf( "画像ファイル「 %s 」を保存しました.\n", henkan_file );
	printf( "全ての作業が終了しました.\n" );

	return 0;
}

Re: C言語による画像処理 画像サイズ変更

Posted: 2013年12月23日(月) 14:14
by softya(ソフト屋)
あと忘れてました。headerのX_SIZEも1/4にする必要があります。
headerが構造体宣言されていないので、ちょっと面倒ですね。

headerは次のような構造をしています。
「bmp ファイルフォーマット」
http://www.kk.iij4u.or.jp/~kondo/bmp/

Re: C言語による画像処理 画像サイズ変更

Posted: 2013年12月23日(月) 16:14
by Mr.beginner
ご指摘いただいた箇所を修正し,実行したのですが,出力画像が添付した画像になりました...

コード:

#include <stdio.h>
#include <stdlib.h>
#define X_SIZE 1916/*画像の横サイズを定義*/
#define Y_SIZE 181/*画像の縦サイズを定義*/
 
unsigned char screen[Y_SIZE][X_SIZE][3], compress[Y_SIZE][X_SIZE/4][3];
 
int main() {
    FILE *fp;
    unsigned char header[54];
    char input_file[100], henkan_file[100];
 
    /*画像ファイル読み込み*/
    printf( "処理を行う画像ファイル名:.(拡張子:bmp)\n---" );
    scanf( "%s", input_file );
    printf( "処理を行う画像ファイル:「 %s 」.\n\n", input_file );
    fp = fopen( input_file, "rb" );
    if( ( fp = fopen( input_file, "rb" ) ) == NULL ) {
        printf( "画像ファイルが正常に開けませんでした.\n" );
        exit( 1 );
    }
    fread( header, 1, 54, fp );
    fread( screen, 1, X_SIZE/4 * Y_SIZE * 3, fp );
    fclose( fp );
 
    /*サイズ変更*/
    int x, y, i;
    for( i = 0; i < 3; i++ ) {
        for( y = 0; y < Y_SIZE; y++ ) {
            for( x = 0; x < X_SIZE / 4; x++ ) {
                compress[y][x][i] = ( screen[y][x * 4 + 0][i] + screen[y][x * 4 + 1][i] + screen[y][x * 4 + 2][i] + screen[y][x * 4 + 3][i] ) / 4;
            }
        }
	 }

    /*画像ファイル保存*/
    printf( "保存する画像ファイル名:.(拡張子:bmp)\n---" );
    scanf( "%s", henkan_file );
    fp = fopen( henkan_file, "wb" );
    if( ( fp = fopen( henkan_file, "wb" ) ) == NULL ) {
        printf( "画像ファイルが正常に開けませんでした.\n" );
        exit( 1 );
    }
    fwrite( header, 1, 54, fp );
    fwrite( compress, 1, X_SIZE/4 * Y_SIZE * 3, fp );
    fclose( fp );
    printf( "画像ファイル「 %s 」を保存しました.\n", henkan_file );
    printf( "全ての作業が終了しました.\n" );
 
    return 0;
}

Re: C言語による画像処理 画像サイズ変更

Posted: 2013年12月23日(月) 16:39
by softya(ソフト屋)
headerのxサイズ情報を修正されていないので、これが原因かもしれません。

【補足】上の方に参考サイトを書いてありますので見て下さいね。BITMAPINFOHEADERの所にあるbiWidthです。

Re: C言語による画像処理 画像サイズ変更

Posted: 2013年12月23日(月) 19:05
by ISLe
bmpはピクセルデータの水平サイズを4の倍数にそろえる必要があります。
変換後のサイズは詰め物が必要なので、3次元配列を使ったこのコードでは対応できないのではないかと。

Re: C言語による画像処理 画像サイズ変更

Posted: 2013年12月23日(月) 19:09
by softya(ソフト屋)
ISLe さんが書きました:bmpはピクセルデータの水平サイズを4の倍数にそろえる必要があります。
変換後のサイズは詰め物が必要なので、3次元配列を使ったこのコードでは対応できないのではないかと。
しまった。それを忘れていました。
それにサイズ固定なデータ限定なので可変長に対応 = 動的確保が必要になりそうですね。

Re: C言語による画像処理 画像サイズ変更

Posted: 2013年12月23日(月) 22:36
by ISLe
水平方向はRGB要素を展開したサイズで2次元配列にすれば、特に動的確保は必須とはならないかと。
添字の計算にひと手間加える必要がありますが。

Re: C言語による画像処理 画像サイズ変更

Posted: 2013年12月24日(火) 10:15
by usao
No4のline23:
>fread( screen, 1, X_SIZE/4 * Y_SIZE * 3, fp );

読むときはちゃんと全部読まないといかんのではないだろうか.
→ここではX_SIZE/4の/4は不要.
(あと,
 >bmpはピクセルデータの水平サイズを4の倍数にそろえる必要があります。
 これがあるので,画素データ部のサイズ計算は一般には(X_SIZE * Y_SIZE * 3)ではダメかと.
 今はたまたま #define X_SIZE 1916 なる4の倍数な横幅の画像を読んでいるためにこれでも読めるだろうけど.)