近来在工作中用到libpng和libjpeg对图片做解析,要求解析出RGB数据,并能提供8位和24位2中借口,并要求能对图片进行缩放,结合网上各个朋友的文章,写出了我自己的代码,现在贴出来给大家参考。
1.从文件读取:
bool PngImage::loadFromFile(const char* Path, IMAGE_TYPE type)
{
// 重新初始化,防止load多个图片。
m_good = false;
m_width = 0;
m_height = 0;
if (m_bgra)
{
delete m_bgra;m_bgra = 0;//类成员变量,存储24位RGB数据。
}
if(m_8bit)
{
delete m_8bit;m_8bit=0;//类成员变量,存储8位数据。
}
if(type == IMAGE_PNG)
{
//对PNG文件的解析
// try to open file
FILE* file = fopen(Path, "rb");
// unable to open
if (file == 0) return false;
// create read struct
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
// check pointer
if (png_ptr == 0)
{
fclose(file);
return false;
}
// create info struct
png_infop info_ptr = png_create_info_struct(png_ptr);
// check pointer
if (info_ptr == 0)
{
png_destroy_read_struct(&png_ptr, 0, 0);
fclose(file);
return false;
}
// set error handling
if (setjmp(png_jmpbuf(png_ptr)))
{
png_destroy_read_struct(&png_ptr, &info_ptr, 0);
fclose(file);
return false;
}
// I/O initialization using standard C streams
png_init_io(png_ptr, file);
// read entire image , ignore alpha channel,如果你要使用alpha通道,请把PNG_TRANSFORM_STRIP_ALPHA去掉
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_STRIP_ALPHA, 0);
/*
PNG_TRANSFORM_EXPAND有下边几个处理:
1.Expand paletted colors into true RGB triplets
2.Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel
3.Expand paletted or RGB images with transparency to full alpha channels so the data will be available
as RGBA quartets。
PNG_TRANSFORM_STRIP_ALPHA:Strip alpha bytes from the input data without combining withthe background
*/
int width = m_width = info_ptr->width;
int height = m_height = info_ptr->height;
int color_type = info_ptr->color_type;
int bit_depth = info_ptr->pixel_depth;
png_bytep* row_pointers = png_get_rows(png_ptr,info_ptr);
int pos=0;
if(color_type == PNG_COLOR_TYPE_GRAY)
{//对灰度图的处理
m_8bit = new unsigned char[width*height];
memset(m_8bit,0,width*height);
for(int i=0;i<height;i++)
{
for(int j=0;j<width;j+=1)
{
m_8bit[pos++] = row_pointers[i][j];
}
}
}
else
{//对非灰度图的处理
m_bgra = new unsigned char[width*height*3];
memset(m_bgra,0,width*height*3);
for(int i=0;i<height;i++)
{
for(int j=0;j<3*width;j+=3)
{
m_bgra[pos++] = row_pointers[i][j+2];//BLUE
m_bgra[pos++] = row_pointers[i][j+1];//GREEN
m_bgra[pos++] = row_pointers[i][j];//RED
}
}
}
// free memory
png_destroy_read_struct(&png_ptr, &info_ptr, 0);
// close file
fclose(file);
}
else if(type == IMAGE_JPEG)
{//对JPEG图片的解析
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
FILE* infile;
if((infile=fopen(Path,"rb")) == NULL )
{
printf("Open file error!/n");
return false;
}
jpeg_stdio_src(&cinfo, infile);
jpeg_read_header(&cinfo, TRUE);
m_height = cinfo.image_height;
m_width = cinfo.image_width;
m_bgra = new unsigned char[cinfo.image_width*cinfo.image_height*cinfo.num_components];
jpeg_start_decompress(&cinfo);
JSAMPROW row_pointer[1];
while(cinfo.output_scanline < cinfo.output_height)
{
/*row_pointer[0] = &m_bgr[(cinfo.output_height-cinfo.output_scanline-1)
*cinfo.image_width*cinfo.num_components];*/
row_pointer[0]=&m_bgra[cinfo.output_scanline*cinfo.image_width*cinfo.num_components];
jpeg_read_scanlines(&cinfo, row_pointer, 1);
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(infile);
}
return TRUE;
}
2.从内存读取:
对于PNG格式,从内存读取要重设读取回调函数,然后用png_set_read_fn()函数指明读函数。
对于JPEG格式,只需用jpeg_mem_src()函数替代原来从文件读取的jpeg_stdio_src(&cinfo, infile)即可。
typedef struct
{
unsigned char* data;
int size;
int offset;
}ImageSource;
//从内存读取PNG图片的回调函数
static void pngReadCallback(png_structp png_ptr, png_bytep data, png_size_t length)
{
ImageSource* isource = (ImageSource*)png_get_io_ptr(png_ptr);
if(isource->offset + length <= isource->size)
{
memcpy(data, isource->data+isource->offset, length);
isource->offset += length;
}
else
png_error(png_ptr, "pngReaderCallback failed");
}
//从内存读取
bool PngImage::loadFromStream(unsigned char* data, const unsigned int dataSize, IMAGE_TYPE type)
{
m_good = false;
m_width = 0;
m_height = 0;
if(m_bgra)
{
delete m_bgra; m_bgra=0;
}
if(m_8bit)
{
delete m_8bit; m_8bit=0;
}
if(type == IMAGE_PNG)
{
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
if(png_ptr == 0)
return false;
png_infop info_ptr = png_create_info_struct(png_ptr);
if(info_ptr == 0)
{
png_destroy_read_struct(&png_ptr, 0, 0);
return false;
}
if(setjmp(png_jmpbuf(png_ptr)))
{
png_destroy_read_struct(&png_ptr, &info_ptr,0);
}
ImageSource imgsource;
imgsource.data = data;
imgsource.size = dataSize;
imgsource.offset = 0;
png_set_read_fn(png_ptr, &imgsource,pngReadCallback);
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_STRIP_ALPHA, 0);
int width = m_width = info_ptr->width;
int height = m_height = info_ptr->height;
int color_type = info_ptr->color_type;
int bit_depth = info_ptr->pixel_depth;
png_bytep* row_pointers = png_get_rows(png_ptr,info_ptr);
int pos=0;
if(color_type == PNG_COLOR_TYPE_GRAY)
{
m_8bit = new unsigned char[width*height];
memset(m_8bit,0,width*height);
for(int i=0;i<height;i++)
{
for(int j=0;j<width;j+=1)
{
m_8bit[pos++] = row_pointers[i][j];
}
}
}
else
{
m_bgra = new unsigned char[width*height*3];
memset(m_bgra,0,width*height*3);
for(int i=0;i<height;i++)
{
for(int j=0;j<3*width;j+=3)
{
m_bgra[pos++] = row_pointers[i][j+2];//BLUE
m_bgra[pos++] = row_pointers[i][j+1];//GREEN
m_bgra[pos++] = row_pointers[i][j];//RED
}
}
}
// free memory
png_destroy_read_struct(&png_ptr, &info_ptr, 0);
}
else if(type == IMAGE_JPEG)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
//从内存读取
jpeg_mem_src(&cinfo, data, dataSize);
jpeg_read_header(&cinfo, TRUE);
m_height = cinfo.image_height;
m_width = cinfo.image_width;
m_bgra = new unsigned char[cinfo.image_width*cinfo.image_height*cinfo.num_components];
jpeg_start_decompress(&cinfo);
JSAMPROW row_pointer[1];
while(cinfo.output_scanline < cinfo.output_height)
{
/*row_pointer[0] = &m_bgr[(cinfo.output_height-cinfo.output_scanline-1)
*cinfo.image_width*cinfo.num_components];*/
row_pointer[0]=&m_bgra[cinfo.output_scanline*cinfo.image_width*cinfo.num_components];
jpeg_read_scanlines(&cinfo, row_pointer, 1);
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
}
return /*(m_good = true)*/TRUE;
}
3. 对图片的缩放,是用的网上广为流传的插值算法。
传入的参数为:返回图片的宽度(w_Dest),返回图片的高度(h_Dest),返回图片的位深(bit_depth),源图片的RGB数据(src),源图片的宽度(w_Src),源图片的高度(h_Src).
unsigned char* PngImage::do_Stretch_Linear(int w_Dest,int h_Dest,int bit_depth,unsigned char *src,int w_Src,int h_Src)
{
int sw = w_Src-1, sh = h_Src-1, dw = w_Dest-1, dh = h_Dest-1;
int B, N, x, y;
int nPixelSize = bit_depth/8;
unsigned char *pLinePrev,*pLineNext;
unsigned char *pDest = new unsigned char[w_Dest*h_Dest*bit_depth/8];
unsigned char *tmp;
unsigned char *pA,*pB,*pC,*pD;
for(int i=0;i<=dh;++i)
{
tmp =pDest + i*w_Dest*nPixelSize;
y = i*sh/dh;
N = dh - i*sh%dh;
pLinePrev = src + (y++)*w_Src*nPixelSize;
//pLinePrev =(unsigned char *)aSrc->m_bitBuf+((y++)*aSrc->m_width*nPixelSize);
pLineNext = (N==dh) ? pLinePrev : src+y*w_Src*nPixelSize;
//pLineNext = ( N == dh ) ? pLinePrev : (unsigned char *)aSrc->m_bitBuf+(y*aSrc->m_width*nPixelSize);
for(int j=0;j<=dw;++j)
{
x = j*sw/dw*nPixelSize;
B = dw-j*sw%dw;
pA = pLinePrev+x;
pB = pA+nPixelSize;
pC = pLineNext + x;
pD = pC + nPixelSize;
if(B == dw)
{
pB=pA;
pD=pC;
}
for(int k=0;k<nPixelSize;++k)
{
*tmp++ = ( unsigned char )( int )(
( B * N * ( *pA++ - *pB - *pC + *pD ) + dw * N * *pB++
+ dh * B * *pC++ + ( dw * dh - dh * B - dw * N ) * *pD++
+ dw * dh / 2 ) / ( dw * dh ) );
}
}
}
return pDest;
}
如果大家发现有什么不完善的地方,欢迎大家交流。
分享到:
相关推荐
对应与文章Halide+VS2017+win10完整配置(包括libpng,zlib和libjpeg的编译)的文件
本文代码利用libpng库解码读取png图片,获取图片像素的颜色索引值,并将结果保存在opencv的Mat数据容器中。
Leptonica它依赖于开源的zlib、libjpeg、libpng、libtiff、giflib的源代码。 版本分别是: zlib-1.2.8 jpeg-9a libpng-1.6.19 tiff-4.0.6 giflib-5.1.1
64位libpng + zlib + libjpeg编译好的库,学习Halide必备!
libpng的库文件,lib文件,dll文件, png.lib libpngd.lib zlib.lib zlibd.lib libpng15d.dll zlib1d.dll png.h pngconf.h zconf.h zlib.h
simple_png_to_jpeg 使用 libpng 和 libjpeg 将 PNG 文件转换为 JPEG 文件的简单 C 函数。
libpng最新源码文件
png+libpng.lib+libpng16.dll+zlib.lib四个C语言使用libPNG开发需要用到的 一:libpng库的编译 环境:windows10 + VS2013 需要下载:libpng, zlib两个库 下载地址: libpng:...
opencv中的libpng.lib文件。希望对大家有用。
3、设置错误返回点 上文libjpeg解码jpeg图片中提到用setjmp/longjmp函数来处理异常 4、设置libpng的数据源 我在上文《图
libpng 安装php时必备的文件 版本为 1.2.8
之前在ubuntu18.04 LTS中安装某个软件之后,运行此软件时报错提示找不到libpng12的相关动态库文件,但是通过常规Linux软件安装方法也无法安装libpng12库。检查了其他版本libpng也提示安装了,但/usr/lib/libpng*没有...
zlib和libpng源码 zlib1.2.3.0 libpng1.2.35
代码主要功能是在windows系统Qt平台上使用libpng库完成读图片,双线性差值实现缩放图片,写图片的功能。代码高效可用。
libviso2中使用的libpng++库 ,费了一个小时一个一个复制粘贴过来的,网上下载不下来,所以就这样了。不过还好一次性复制修改正确的,使得libviso2代码可以完整的跑下来了。
libpng是一款C语言编写的比较底层的读写PNG文件的跨平台的库。借助它,你可以轻松读写PNG文件的每一行像素。 因为PNG文件是经过压缩而且格式...因此,通过使用libpng你就能直接使用现成的函数、程序来读写PNG文件了。
libharu 使用第三方libpng和zlib编译之后的文件dll和lib及使用方法
本程序借助libpng和libjpeg库 ,以C++类的方式实现linux下对png jpg和bmp常见类型的图像文件的读写。要在程序中显示图像可自行用opengl或其他方式完成。
使用VS调用libpng要用到的一些材料
能够将bmp图片读取并将rgb的值分别存储!很好用的