使用libpng显示png图片

本文介绍了一种使用C++和libpng库加载并显示PNG图片的方法。通过详细代码示例展示了如何利用OPENFILENAMEA获取PNG文件路径,读取PNG文件头进行格式验证,并解析PNG图像数据,最终将其转换为适合显示的格式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二话不说,上代码先。

 

OPENFILENAMEA ofn = {0};

char szFilter[] ="PNG Files (*.PNG)\0*.png\0"

"All Files (*.*)\0*.*\0\0";

char filename[MAX_PATH]={0};

char file_title[MAX_PATH]={0};

ofn.lStructSize = sizeof(OPENFILENAMEA);

ofn.hwndOwner = m_hWnd;

ofn.hInstance = NULL;

ofn.lpstrFilter = szFilter;

ofn.lpstrCustomFilter = NULL;

ofn.nMaxCustFilter = 0;

ofn.nFilterIndex = 0;

ofn.lpstrFile = filename;

ofn.nMaxFile = MAX_PATH;

ofn.lpstrFileTitle = file_title;

ofn.nMaxFileTitle = MAX_PATH;

ofn.lpstrInitialDir = NULL;

ofn.lpstrTitle = NULL;

ofn.nFileOffset = 0;

ofn.nFileExtension = 0;

ofn.lpstrDefExt = "png";

ofn.lCustData = 0;

ofn.lpfnHook = NULL;

ofn.lpTemplateName = NULL;

ofn.Flags = OFN_HIDEREADONLY;

if (!GetOpenFileNameA(&ofn))

return;

char png_header[8];

png_structp png_ptr;

png_infop info_ptr;

int width, height, bit_depth, color_type;

FILE* file = fopen(ofn.lpstrFile, "rb");

fread(png_header, 1, 8, file);

if (png_sig_cmp((png_const_bytep)png_header, 0, 8))

{

fclose(file);

return;

}

png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

info_ptr = png_create_info_struct(png_ptr);

if (setjmp(png_jmpbuf(png_ptr)))

{

png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

fclose(file);

return;

}

png_init_io(png_ptr, file);

png_set_sig_bytes(png_ptr, 8);

 

png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, NULL);

png_bytep *row_pointers = png_get_rows(png_ptr, info_ptr);

 

png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *)&width, (png_uint_32 *)&height, &bit_depth, &color_type, NULL, NULL, NULL);

 

png_uint_32 ulRowBytes = png_get_rowbytes(png_ptr, info_ptr);

png_uint_32 ulChannels = png_get_channels(png_ptr, info_ptr);

 

DWORD wDIRowBytes = (WORD) ((3 * width + 3L) >> 2) << 2;

BYTE *pDib = (BYTE *) malloc (sizeof(BITMAPINFOHEADER) + wDIRowBytes * height);

BITMAPINFOHEADER *pbmih = (BITMAPINFOHEADER *) pDib;

memset(pbmih, 0, sizeof(BITMAPINFOHEADER));

pbmih->biSize=sizeof(BITMAPINFOHEADER);

pbmih->biWidth=width;

pbmih->biHeight=-height;

pbmih->biPlanes=1;

pbmih->biBitCount=24;

pbmih->biCompression=BI_RGB;

pbmih->biSizeImage=0;

pbmih->biXPelsPerMeter=0;

pbmih->biYPelsPerMeter=0;

pbmih->biClrUsed=0;

pbmih->biClrImportant=0;

BTYE *pDiData = pDib + sizeof(BITMAPINFOHEADER);

for (int j = 0; j < height; j++)

{

for (int i = 0; i < width; i++)//rgba

{

//should in bgr order

pDiData[3*j*width + 3*i] = row_pointers[j][ulChannels*i + 2];

pDiData[3*j*width + 3*i + 1] = row_pointers[j][ulChannels*i+1];

pDiData[3*j*width + 3*i + 2] = row_pointers[j][ulChannels*i];

}

}

//data is ready to display

SetDIBitsToDevice (hdc, 0, 0, width, height, 0, 0, 0, height, pDiData, (BITMAPINFO *) pDib, DIB_RGB_COLORS);

free(pDib);

png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

fclose(file);

--完--

如果需要完整源码的工程可以从这里http://download.youkuaiyun.com/detail/qiuchangyong/7504751下载,

也可以从这里http://www.pudn.com/downloads633/sourcecode/windows/bitmap/detail2570501.html下载到。

---------------------------------------------------------------------------------------------------------------------------------------------

补充:以上的两个链接都有些旧了,使用VS2015编译了改工程,基于libpng-1.6.37和zlib-1.2.11源码。所有的东西都在里面了,方便初学者参考,避免因缺少文件编译不通过带来的烦恼,不过打包后文件有点大。

下载地址:http://sifangyun.cn/download/PngViewer.rar

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值