ligpng 读取图像

1.从文件读取

转载自:http://blog.csdn.net/bigapple88/archive/2010/06/03/5644418.aspx

 

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;
}



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值