dポイントプレゼントキャンペーン実施中!

libpngを用いて
PNGを24bppBMPに変換したいのですがうまくいきません。

#include "png.h"
#pragma comment(lib, "libpng.lib")
void PNGtoBMP(char *filename)
{
FILE *fpt,*fpt_output;
png_structp png_ptr;
png_infop info_ptr;
unsigned long width, height;
int bit_depth, color_type, interlace_type;
unsigned char **image;
int i,j;
MessageBox(NULL,"PNG End","PNG End",MB_OK);

fopen_s(&fpt,filename, "rb");
if(fpt==NULL)
{
MessageBox(NULL,"fopen_s error","error",MB_OK);

}
else
{
// まずファイルを開きます
fopen_s(&fpt_output,"PNG.bmp","wb");
png_structp png_ptr = png_create_read_struct (
PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, user_error_fn, user_warning_fn);




#if 0
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
#endif


#if 0
info_ptr = png_create_info_struct(png_ptr); // info_ptr構造体を確保・初期化します
png_init_io(png_ptr, fpt); // libpngにfpを知らせます
png_read_info(png_ptr, info_ptr); // PNGファイルのヘッダを読み込みます
png_get_IHDR(png_ptr, info_ptr, &width, &height, // IHDRチャンク情報を取得します
&bit_depth, &color_type, &interlace_type,
NULL, NULL);
image = (png_bytepp)malloc(height * sizeof(png_bytep)); // 以下3行は2次元配列を確保します
for (i = 0; i < height; i++)
image[i] = (png_bytep)malloc(png_get_rowbytes(png_ptr, info_ptr));
png_read_image(png_ptr, image); // 画像データを読み込みます


int campusline=(int)((width*24+31)/32.0)*4;//メモリ上の1Line(修正値も含む)
int modification=campusline-(int)((24/8.0)*width);

BITMAPINFOHEADER bmih;
BITMAPFILEHEADER bmfh;
//RGBQUAD rgbquad;

DWORD filesize,bmfhsize,bmihsize;
bmfhsize=sizeof(bmfh);
bmihsize=sizeof(bmih);
//rgbquadsize=sizeof(rgbquad);

filesize=bmfhsize+bmihsize+(3*width+modification)*height;
::ZeroMemory(&bmfh, bmfhsize);
::ZeroMemory(&bmih, bmihsize);

bmfh.bfType=0x4d42;
bmfh.bfSize=filesize;
bmfh.bfReserved1=0;
bmfh.bfReserved2=0;
bmfh.bfOffBits=bmfhsize+bmihsize;

bmih.biSize=bmihsize;
bmih.biWidth=width;
bmih.biHeight=height;
bmih.biPlanes=1;
bmih.biBitCount=24;
bmih.biClrUsed=0;
bmih.biCompression=BI_RGB;//無圧縮形式
bmih.biSizeImage=0;//BI_RGBをセットした場合、0が好ましいとMSDNに書いてあった。
bmih.biXPelsPerMeter=0;
bmih.biYPelsPerMeter=0;
bmih.biClrImportant=0;

//ヘッダファイルを書き込む
//fwrite(&bmfh,sizeof(unsigned char),bmfhsize,fpt_output);
//fwrite(&bmih,sizeof(unsigned char),bmihsize,fpt_output);

#if 0
//ここで最終的に書き込みを行う。
for(i=0;i<height;i++)
{
fwrite(&image[i][0],sizeof(unsigned char),3*width,fpt_output);

//修正値の代入
for(j=0;j<modification;j++)
{
fwrite("\x000",sizeof(unsigned char),1,fpt_output);
}
}
#endif


for (i = 0; i < height; i++) free(image[i]); // 以下2行は2次元配列を解放します
free(image);
png_destroy_read_struct( // 2つの構造体のメモリを解放します
&png_ptr, &info_ptr, (png_infopp)NULL);
#endif

fclose(fpt);
fclose(fpt_output);
}
}
*同一ディレクトリに、libpng.lib, libz.lib(zlib.libではない)
があります。また、libpng12.dllも要求されたので、同一
ディレクトリに配置しています。
バグは
png_structp png_ptr = png_create_read_struct (
PNG_LIBPNG_VER_STRING, (png_voidp)
の時点で起きていて これを書いてビルドして実行すると
エラーになり open.cででばっかが止まります。

お忙しい中恐縮ですがどなたかご教授お願いします。

A 回答 (1件)

 こんばんは。


 もっと色々な設定をしなければならないのでは。
 付け焼刃で書いたのでエラー処理がいい加減ですが、以下参考程度に。

#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;
}
    • good
    • 0
この回答へのお礼

お疲れ様です 参考コードありがとうございました
大変参考になりました。
あれからデバッグを繰り返したのですが
png_ptr = (png_structp)png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
のところで必ず動作が中止(実行時エラー)されてしまいます。
もしかするとVISTA SP1とlibpngの相性が悪いのかもしれません。

ご回答ありがとうございました。

お礼日時:2009/11/03 13:06

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!