大家好,欢迎来到IT知识分享网。
自己的实现
unsigned int component(png_const_bytep row, png_uint_32 x, unsigned int c, unsigned int bit_depth, unsigned int channels) { png_uint_32 bit_offset_hi = bit_depth * ((x >> 6) * channels); png_uint_32 bit_offset_lo = bit_depth * ((x & 0x3f) * channels + c); row = (png_const_bytep)(((PNG_CONST png_byte(*)[8])row) + bit_offset_hi); row += bit_offset_lo >> 3; bit_offset_lo &= 0x07; switch (bit_depth) { case 1: return (row[0] >> (7 - bit_offset_lo)) & 0x01; case 2: return (row[0] >> (6 - bit_offset_lo)) & 0x03; case 4: return (row[0] >> (4 - bit_offset_lo)) & 0x0f; case 8: return row[0]; case 16: return (row[0] << 8) + row[1]; default: fprintf(stderr, "pixel_component: invalid bit depth %u\n", bit_depth); return row[0]; } } void readPixel(png_const_bytep row, png_uint_32 x, png_uint_32 bit_depth, png_uint_32 color_type, BitmapPixel *pPixel) { unsigned int channels = PNG_COLOR_TYPE_RGB_ALPHA ? 4 : 3; pPixel->r = component(row, x, 0, bit_depth, channels); pPixel->g = component(row, x, 1, bit_depth, channels); pPixel->b = component(row, x, 2, bit_depth, channels); pPixel->a = color_type == PNG_COLOR_TYPE_RGB_ALPHA ? component(row, x, 3, bit_depth, channels) : 0xFF; } BitmapData* PNG_ARGB8888(FILE *pngFile) { BitmapData *pData; png_structp png_ptr; png_infop info_ptr; png_bytepp pRow = NULL; png_uint_32 width, height, ystart, xstart, ystep, xstep, px, ppx, py, count; png_int_32 bit_depth, color_type, interlace_method, passes, pass; if (!pngFile) { return NULL; } if (!(png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) { LETV_LOGE("ERROR PNG_ARGB8888: out of memory allocating png_struct!\n"); return NULL; } if (!(info_ptr = png_create_info_struct(png_ptr))) { LETV_LOGE("ERROR PNG_ARGB8888: out of memory allocating png_info!\n"); png_destroy_read_struct(&png_ptr, NULL, NULL); return NULL; } if (setjmp(png_jmpbuf(png_ptr))) { LETV_LOGE("ERROR PNG_ARGB8888: setjmp png_ptr failed!\n"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } png_init_io(png_ptr, pngFile); png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0); color_type = png_get_color_type(png_ptr, info_ptr); if (!(color_type & PNG_COLOR_TYPE_RGB)) { LETV_LOGE("ERROR PNG_ARGB8888: PNG_COLOR_TYPE unsupported!\n"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } interlace_method = png_get_interlace_type(png_ptr, info_ptr); switch (interlace_method) { case PNG_INTERLACE_NONE: passes = 1; break; case PNG_INTERLACE_ADAM7: passes = PNG_INTERLACE_ADAM7_PASSES; break; default: LETV_LOGE("ERROR PNG_ARGB8888: png unknown interlace!\n"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } pData = (BitmapData*)LETV_MEM_MALLOC(sizeof(BitmapData)); if (!pData) { LETV_LOGE("ERROR PNG_ARGB8888: allocate memory for bitmap data failed!\n"); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } width = png_get_image_width(png_ptr, info_ptr); height = png_get_image_height(png_ptr, info_ptr); bit_depth = png_get_bit_depth(png_ptr, info_ptr); pRow = png_get_rows(png_ptr, info_ptr); for (pass = 0; pass < passes; ++pass) { if (interlace_method == PNG_INTERLACE_ADAM7) { if (PNG_PASS_COLS(width, pass) == 0) continue; xstart = PNG_PASS_START_COL(pass); ystart = PNG_PASS_START_ROW(pass); xstep = PNG_PASS_COL_OFFSET(pass); ystep = PNG_PASS_ROW_OFFSET(pass); } else { ystart = xstart = 0; ystep = xstep = 1; } pData->infoHeader.width = width / xstep; pData->infoHeader.height = height / ystep; pData->fileHeader.size = sizeof(BitmapPixel) * pData->infoHeader.width * pData->infoHeader.height; pData->pPixels = (BitmapPixel*)LETV_MEM_MALLOC(pData->fileHeader.size); if (!pData->pPixels) { LETV_LOGE("ERROR PNG_ARGB8888: allocate memory for bitmap pixels failed!\n"); break; } count = 0; for (py = ystart; py < ystart + height; py += ystep) { for (px = xstart, ppx = 0; px < xstart + width; px += xstep, ppx++) { readPixel(*(pRow + py), ppx, bit_depth, color_type, pData->pPixels + count); count++; } } break; } png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return pData; }
转自:【C】libpng的使用 – 技术宅的结界 – Powered by Discuz!
1 png_structp png_ptr=NULL;//libpng的结构体 2 png_infop info_ptr=NULL;//libpng的信息
1 int iRetVal; 2 png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); 3 if(!png_ptr) 4 goto 错误处理; 5 info_ptr=png_create_info_struct(png_ptr); 6 if(!info_ptr) 7 { 8 png_destroy_write_struct(&png_ptr,NULL); 9 goto 错误处理; 10 } 11 iRetVal=setjmp(png_jmpbuf(png_ptr));//安装错误处理跳转点 12 //当libpng内部出现错误的时候,libpng会调用longjmp直接跳转到这里运行。 13 if(iRetVal)//setjmp的返回值就是libpng跳转后提供的错误代码(貌似总是1,但是还是请大家看libpng的官方文档) 14 { 15 fprintf(stderr,"错误码:%d\n",iRetVal); 16 goto 错误处理; 17 }
1 png_destroy_write_struct(&png_ptr,&info_ptr);
1 FILE*fp=fopen("C:\\TEST.PNG","wb"); 2 if(!fp) 3 goto 错误处理;
打开了文件以后,你要让libpng和这个文件流绑定起来,因此你需要调用png_init_io来完成绑定。
1 png_init_io(png_ptr,fp);
接下来就是关键的部分了:设置PNG文件的属性、写入PNG文件头、写入PNG文件。
1 //设置PNG文件头 2 png_set_IHDR(png_ptr,info_ptr, 3 图像宽度,图像高度,//尺寸 4 8,//颜色深度,也就是每个颜色成分占用位数(8表示8位红8位绿8位蓝,如果有透明通道则还会有8位不透明度) 5 PNG_COLOR_TYPE_RGB,//颜色类型,PNG_COLOR_TYPE_RGB表示24位真彩深色,PNG_COLOR_TYPE_RGBA表示32位带透明通道真彩色 6 PNG_INTERLACE_NONE,//不交错。PNG_INTERLACE_ADAM7表示这个PNG文件是交错格式。交错格式的PNG文件在网络传输的时候能以最快速度显示出图像的大致样子。 7 PNG_COMPRESSION_TYPE_BASE,//压缩方式 8 PNG_FILTER_TYPE_BASE);//这个不知道,总之填写PNG_FILTER_TYPE_BASE即可。 9 png_set_packing(png_ptr);//设置打包信息 10 png_write_info(png_ptr,info_ptr);//写入文件头
1 png_structp png_ptr=NULL;//libpng的结构体 2 png_infop info_ptr=NULL;//libpng的信息
你可以把上面的结构体指针定义为全局变量使用。
1 int iRetVal; 2 png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); 3 if(!png_ptr) 4 goto 错误处理; 5 info_ptr=png_create_info_struct(png_ptr); 6 if(!info_ptr) 7 { 8 png_destroy_read_struct(&png_ptr,NULL,NULL); 9 goto 错误处理; 10 } 11 iRetVal=setjmp(png_jmpbuf(png_ptr));//安装错误处理跳转点 12 //当libpng内部出现错误的时候,libpng会调用longjmp直接跳转到这里运行。 13 if(iRetVal)//setjmp的返回值就是libpng跳转后提供的错误代码(貌似总是1,但是还是请大家看libpng的官方文档) 14 { 15 fprintf(stderr,"错误码:%d\n",iRetVal); 16 goto 错误处理; 17 }
1 png_destroy_read_struct(&png_ptr,&info_ptr,NULL);
1 FILE*fp=fopen("C:\\TEST.PNG","rb"); 2 if(!fp) 3 goto 错误处理;
打开了文件以后,你要让libpng和这个文件流绑定起来,因此你需要调用png_init_io来完成绑定。绑定之后,你还需要获取PNG的文件头信息。因此你需要调用png_read_info(png_ptr, info_ptr);
1 png_init_io(png_ptr,fp); 2 png_read_info(png_ptr, info_ptr);
读取了文件头,你就能获取文件头的信息。比如文件尺寸、位深度等。代码如下:
1 png_get_IHDR(png_ptr,info_ptr,&width,&height,&bit_depth,&color_type,NULL,NULL,NULL);
有些PNG文件是有背景色的,因此你需要处理这些背景色信息。我们可以用png_get_valid来判断这个PNG是否有背景色信息。png_get_valid(png_ptr,info_ptr,PNG_INFO_bKGD)返回0表示没有背景色信息,返回非零表示有背景色信息。然后我们调用png_get_bKGD来读取背景色。
1 png_color_16p pBackground; 2 png_get_bKGD(png_ptr,info_ptr,&pBackground);
大家可以看看png_color_16p的原型:
1 typedef struct png_color_16_struct 2 { 3 png_byte index; 4 png_uint_16 red; 5 png_uint_16 green; 6 png_uint_16 blue; 7 png_uint_16 gray; 8 } png_color_16;
if(colortype==PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr);//要求转换索引颜色到RGB if(colortype==PNG_COLOR_TYPE_GRAY && bit_depth<8) png_set_expand_gray_1_2_4_to_8(png_ptr);//要求位深度强制8bit if(bit_depth==16) png_set_strip_16(png_ptr);//要求位深度强制8bit if(png_get_valid(png_ptr,info_ptr,PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); if(colortype == PNG_COLOR_TYPE_GRAY || colortype == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr);//灰度必须转换成RGB
1 ppLinePtrs=(COLORREF)malloc(g_dwHeight*sizeof(COLORREF*));//列指针 2 if(!ppLinePtrs) 3 goto Error; 4 i=g_dwHeight; 5 y=0; 6 while(i--)//逆行序读取,因为位图是底到上型 7 ppLinePtrs[y++]=(COLORREF*)&g_pBits[i*g_dwWidth];
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/111200.html
