ligpng 读取图像

来源:互联网 发布:风险投资知乎 编辑:程序博客网 时间:2024/05/20 07:37

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



 

原创粉丝点击