こんばんは。
もっと色々な設定をしなければならないのでは。
付け焼刃で書いたのでエラー処理がいい加減ですが、以下参考程度に。
#include<windows.h>
#include "png.h"
#pragma comment(lib, "libpng.lib")
#pragma comment(lib, "zlib.lib")
static void Save(FILE* fpOut, png_bytep image, png_uint_32 width, png_uint_32 height, png_uint_32 campusline)
{
const png_uint_32 imageSize = campusline * height;
BITMAPINFOHEADER bmih = {sizeof(bmih)};
BITMAPFILEHEADER bmfh = {0};
bmfh.bfType = 0x4d42;
bmfh.bfOffBits = sizeof(bmih) + sizeof(bmfh);
bmfh.bfSize = bmfh.bfOffBits + imageSize;
bmih.biWidth = width;
bmih.biHeight = height;
bmih.biPlanes = 1;
bmih.biBitCount = 24;
bmih.biCompression =BI_RGB;//無圧縮形式
bmih.biSizeImage =0;//BI_RGBをセットした場合、0が好ましいとMSDNに書いてあった。
//ヘッダファイルを書き込む
fwrite(&bmfh,sizeof(bmfh), 1, fpOut);
fwrite(&bmih,sizeof(bmih), 1, fpOut);
fwrite(image, imageSize, 1, fpOut);
}
png_uint_32 PNGtoBMP(const char* inFileName, const char* outFileName)
{
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
png_bytep image = NULL;
png_bytepp row = NULL;
png_uint_32 width = 0;
png_uint_32 height = 0;
png_uint_32 campusline = 0;
png_uint_32 y = 0;
png_int_32 bit_depth = 0;
png_int_32 color_type = 0;
png_int_32 interlace_type = 0;
png_uint_32 result = 0;
FILE* fpIn = fopen(inFileName, "rb");
FILE* fpOut = fopen(outFileName, "wb");
if(fpIn == NULL)
{
MessageBox(NULL,"fopen error", "in file error",MB_OK);
goto clean_up;
}
if(fpOut == NULL)
{
MessageBox(NULL,"fopen error", "out file error", MB_OK);
goto clean_up;
}
png_ptr = (png_structp)png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if(png_ptr == NULL)
{
MessageBox(NULL,"error", "png_ptr error", MB_OK);
goto clean_up;
}
// info_ptr構造体を確保・初期化します
info_ptr = png_create_info_struct(png_ptr);
if(info_ptr == NULL)
{
MessageBox(NULL,"error", "info_ptr error", MB_OK);
goto clean_up;
}
// libpngにfpを知らせます
png_init_io(png_ptr, fpIn);
// PNGファイルのヘッダを読み込みます
png_read_info(png_ptr, info_ptr);
// IHDRチャンク情報を取得します
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
//以下はその他フォーマットの違いを修正する為の設定です
if(color_type == PNG_COLOR_TYPE_PALETTE)
png_set_expand(png_ptr);
if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
png_set_expand(png_ptr);
if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
png_set_expand(png_ptr);
if(bit_depth > 8)
png_set_strip_16(png_ptr);
if(color_type & PNG_COLOR_MASK_ALPHA)
png_set_strip_alpha(png_ptr);
if(color_type == PNG_COLOR_TYPE_GRAY)
png_set_gray_to_rgb(png_ptr);
//設定を反映します
png_read_update_info(png_ptr, info_ptr);
//もう一度IHDRチャンク情報を取得します
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
//メモリ上の1Line(修正値も含む)
campusline = (int)((width * 24 + 31) / 32.0) * 4;
// 以下は2次元配列を確保します
image = (png_bytep)calloc(campusline, height);
if(image == NULL)
{
MessageBox(NULL,"error", "image out memory", MB_OK);
goto clean_up;
}
//縦の配列を確保します
row = calloc(sizeof(png_bytep), height);
if(row == NULL)
{
MessageBox(NULL,"error", "row out memory", MB_OK);
goto clean_up;
}
//y軸を逆転して代入します
for(y = 0; y < height; ++y)
{
const png_uint_32 pos = ((height - 1) - y) * campusline;
row[y] = &image[pos];
}
//rgb->bgrの並びにするように命じます
png_set_bgr(png_ptr);
// 画像データを読み込みます
png_read_image(png_ptr, row);
//終了です
png_read_end(png_ptr, info_ptr);
//ビットマップにセーブします
Save(fpOut, image, width, height, campusline);
result = 1;
clean_up:
// 後始末です
free(image);
free(row);
if(png_ptr && info_ptr)
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
else if(png_ptr && !info_ptr)
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
else
//此処に来る事があってはおかしい
if(fpIn)
fclose(fpIn);
if(fpOut)
fclose(fpOut);
return result;
}
int main()
{
PNGtoBMP("pngtest.png", "bitmap.bmp");
return 0;
}
お礼
お疲れ様です 参考コードありがとうございました 大変参考になりました。 あれからデバッグを繰り返したのですが png_ptr = (png_structp)png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); のところで必ず動作が中止(実行時エラー)されてしまいます。 もしかするとVISTA SP1とlibpngの相性が悪いのかもしれません。 ご回答ありがとうございました。