/* HDR(ハイダイナミックレンジ)合成 2010/05/11 宍戸 輝光 */ #include #include /* BMPファイルを読み込み画像データを返す 画像データは、先頭に横・高さを各32ビット整数、続いて32ビット形式のフレームバッファを格納 */ unsigned int * loadImage(char * path) { FILE * f; unsigned char * fileBuf; unsigned int * imageBuf; int fileSize; int pixelsOffset; int width, height; int lineLength; unsigned char * pixels; int i, j; int r, g, b; f = fopen(path, "rb"); fseek(f, 0, SEEK_END); fileSize = ftell(f) + 1; rewind(f); /* ファイル読み込みバッファ確保 */ fileBuf = (unsigned char *)malloc(fileSize); /* ファイル読み込み */ fread(fileBuf, 1, fileSize, f); fclose(f); /* BMPファイル先頭からピクセル列までのオフセット取得 */ pixelsOffset = *((int *)(fileBuf + 10)); /* ピクセル列の先頭アドレスを格納 */ pixels = fileBuf + pixelsOffset; /* 画像サイズ取得 */ width = (fileBuf[21] << 24) | (fileBuf[20] << 16) | (fileBuf[19] << 8) | fileBuf[18]; height = (fileBuf[25] << 24) | (fileBuf[24] << 16) | (fileBuf[23] << 8) | fileBuf[22]; /* ピクセル列の横一ラインのバイト数算出 */ if (width % 4 == 0) { lineLength = width * 3; } else { lineLength = width * 3 + (4 - (width * 3) % 4); } /* 画像データ用メモリ確保 */ imageBuf = (unsigned int *)calloc(2 + width * height, 4); /* 画像データに画像サイズ記録 */ imageBuf[0] = width; imageBuf[1] = height; /* 画像データに各ピクセル設定 */ for (i = 0;i < height;i++) { for (j = 0;j < width;j++) { r = pixels[((j * 3) + 2) + (i * lineLength)]; g = pixels[((j * 3) + 1) + (i * lineLength)]; b = pixels[(j * 3) + (i * lineLength)]; imageBuf[2 + j + i * width] = (r << 16) | (g << 8) | b; } } free(fileBuf); return imageBuf; } /* 画像データを24ビットBMPとして保存 */ void writeImage(char * path, unsigned int * image) { unsigned char * bmpBuf; FILE * f; int lineLength; int bmpSize; unsigned int i, j; if (image[0] % 4 == 0) { lineLength = image[0] * 3; } else { lineLength = image[0] * 3 + (4 - (image[0] * 3) % 4); } bmpSize = 54 + image[0] * lineLength; bmpBuf = (unsigned char *)calloc(bmpSize, 1); /* BITMAPFILEHEADER先頭に識別子記録 */ bmpBuf[0]='B'; bmpBuf[1]='M'; /* ファイルサイズ記録 */ bmpBuf[2] = (unsigned char)(bmpSize & 0xff); bmpBuf[3] = (unsigned char)((bmpSize >> 8) & 0xff); bmpBuf[4] = (unsigned char)((bmpSize >> 16) & 0xff); bmpBuf[5] = (unsigned char)((bmpSize >> 24) & 0xff); bmpBuf[6]=0; bmpBuf[7]=0; bmpBuf[8]=0; bmpBuf[9]=0; /* ピクセル列までのオフセット記録 */ bmpBuf[10]=54; bmpBuf[11]=0; bmpBuf[12]=0; bmpBuf[13]=0; /* BITMAPINFOHEADER */ bmpBuf[14]=40; bmpBuf[15]=0; bmpBuf[16]=0; bmpBuf[17]=0; /* 画像の横幅記録 */ bmpBuf[18] = (unsigned char)(image[0] & 0xff); bmpBuf[19] = (unsigned char)((image[0] >> 8) & 0xff); bmpBuf[20] = (unsigned char)((image[0] >> 16) & 0xff); bmpBuf[21] = (unsigned char)((image[0] >> 24) & 0xff); /* 画像の高さ記録 */ bmpBuf[22] = (unsigned char)(image[1] & 0xff); bmpBuf[23] = (unsigned char)((image[1] >> 8) & 0xff); bmpBuf[24] = (unsigned char)((image[1] >> 16) & 0xff); bmpBuf[25] = (unsigned char)((image[1] >> 24) & 0xff); /* 色形式設定 */ bmpBuf[26]=1; bmpBuf[27]=0; bmpBuf[28]=24; bmpBuf[29]=0; /* ピクセル列に各ピクセルのRGB成分書き込み */ for (i = 0;i < image[1];i++) { for (j = 0;j < image[0];j++) { /* 青成分 */ bmpBuf[54 + (j * 3) + (i * lineLength)] = image[2 + j + i * image[0]] & 0xff; /* 緑成分 */ bmpBuf[55 + (j * 3) + (i * lineLength)] = (image[2 + j + i * image[0]] >> 8) & 0xff; /* 赤成分 */ bmpBuf[56 + (j * 3) + (i * lineLength)] = (image[2 + j + i * image[0]] >> 16) & 0xff; } } /* ファイル書き込み */ f = fopen(path, "wb"); fwrite(bmpBuf, 1, bmpSize, f); fclose(f); free(bmpBuf); } int main(int argc, char * argv[]) { unsigned int * imageList[2]; unsigned int * compImage; int width, height; int i, j; int r1, g1, b1, r2, g2, b2; if (argc != 4) { printf("合成するBMPファイルを二つと保存先BMPファイルを指定してください"); exit(0); } for (i = 0;i < 2;i++) { imageList[i] = loadImage(argv[i + 1]); if (imageList[i] == 0) { printf("%sを読み込めませんでした。", argv[i + 1]); exit(0); } else { printf("%s:%d * %dピクセル\n", argv[i + 1], imageList[i][0], imageList[i][1]); } } if (imageList[0][0] != imageList[1][0] || imageList[0][1] != imageList[1][1]) { printf("同じ大きさの画像を指定してください。"); exit(0); } width = imageList[0][0]; height = imageList[0][1]; /* 合成画像用バッファ作成 */ compImage = (unsigned int *)calloc(2 + width * height, 4); /* 大きさ記録 */ compImage[0] = width; compImage[1] = height; /* 各ピクセルを合成 */ for (i = 0;i < height;i++) { for (j = 0;j < width;j++) { /* 一枚目の画像の各ピクセル色成分を記録 */ r1 = (imageList[0][2 + j + i * width] >> 16) & 0xff; g1 = (imageList[0][2 + j + i * width] >> 8) & 0xff; b1 = imageList[0][2 + j + i * width] & 0xff; /* 二枚目の画像の各ピクセル色成分を記録 */ r2 = (imageList[1][2 + j + i * width] >> 16) & 0xff; g2 = (imageList[1][2 + j + i * width] >> 8) & 0xff; b2 = imageList[1][2 + j + i * width] & 0xff; /* 一枚目と二枚目のピクセルを平均化し合成画像のピクセルに設定 */ compImage[2 + j + i * width] = (((r1 + r2) / 2) << 16) | (((g1 + g2) / 2) << 8) | ((b1 + b2) / 2); } } /* 合成画像をBMPに保存 */ writeImage(argv[3], compImage); for (i = 0;i < 2;i++) { free(imageList[i]); } free(compImage); return 0; }