你好,欢迎来到电脑编程技巧与维护杂志社! 杂志社简介广告服务读者反馈编程社区  
合订本订阅
 
 
您的位置:杂志经典 / 图形图象处理与游戏编程
利用C++类实现PNG图像读写及显示(三)
 

 if (!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); pbImage=NULL; return FALSE; }

    Try

    {     

#if !defined(PNG_NO_STDIO)

        png_init_io(png_ptr, pfFile); //初始化png结构体

#else

        png_set_read_fn(png_ptr, (png_voidp)pfFile, png_read_data);

#endif

        png_set_sig_bytes(png_ptr, 8); //设置PNG文件署名

        png_read_info(png_ptr, info_ptr); //读取PNG信息     

        png_get_IHDR(png_ptr, info_ptr, (unsigned long *) &cxImgSize, (unsigned long *)&cyImgSize, &iBitDepth, &iColorType, NULL, NULL, NULL); //获取宽度、高度、颜色深度、颜色类型等信息

        //将图像数据扩展成每个像素由38比特组成      

        if (iBitDepth == 16)   png_set_strip_16(png_ptr);

        if (iColorType == PNG_COLOR_TYPE_PALETTE)  png_set_expand(png_ptr);

        if (iBitDepth < 8)  png_set_expand(png_ptr);

        if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))  png_set_expand(png_ptr);

        if (iColorType == PNG_COLOR_TYPE_GRAY || iColorType == PNG_COLOR_TYPE_GRAY_ALPHA)

            png_set_gray_to_rgb(png_ptr);

        if (png_get_bKGD(png_ptr, info_ptr, &pBackground)) //设置背景透明颜色,

        {   png_set_background(png_ptr, pBackground, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);

            bkgColor.red   = (byte) pBackground->red;

            bkgColor.green = (byte) pBackground->green;

            bkgColor.blue  = (byte) pBackground->blue;

        } else {bkgColor.red=0;bkgColor.green=0; bkgColor.blue =0; }  

//判断是否需要gamma转换

        if (png_get_gAMA(png_ptr, info_ptr, &dGamma))  png_set_gamma(png_ptr, (double) 2.2, dGamma);   

        png_read_update_info(png_ptr, info_ptr); //变换后,需要更新info_ptr      

        png_get_IHDR(png_ptr, info_ptr,(unsigned long *) &cxImgSize, (unsigned long *)&cyImgSize, &iBitDepth, &iColorType, NULL, NULL, NULL);  //获取宽度、高度、颜色类型、颜色深度等信息

        ulRowBytes = png_get_rowbytes(png_ptr, info_ptr); //行字节数

        ulChannels = png_get_channels(png_ptr, info_ptr);  //通道信息     

        cImgChannels = ulChannels;

           if (pbImage!=NULL)  { free(pbImage); pbImage=NULL;   }//空间已经存在,则先释放空间

        if ((pbImage = (png_byte *) malloc(ulRowBytes * cyImgSize  * sizeof(png_byte))) == NULL)

        { png_error(png_ptr, "Load PNG: Out of memory"); }    

        if ((ppbRowPointers = (png_bytepp) malloc(cyImgSize * sizeof(png_bytep))) == NULL) //分配内存空间  

        { png_error(png_ptr, "Load PNG: Out of memory");  }       

        for (i = 0; i < cyImgSize; i++)  ppbRowPointers[i] = pbImage + i * ulRowBytes; // 设置PNG图像的每行地址

        png_read_image(png_ptr, ppbRowPointers); //一次读入图像信息              

        png_read_end(png_ptr, NULL); //读取辅助块(additional chunks)信息       

        free (ppbRowPointers); //释放内存空间

        ppbRowPointers = NULL;

    } Catch (msg)

    {    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

           pbImage=NULL;       

        if(ppbRowPointers)  free (ppbRowPointers);

        fclose(pfFile);

        return FALSE;

    }

    fclose (pfFile);

FillBitmapInfo();   //填充Bitmap信息

bool ret=PngToBitmap(); //Png图像数据转换成位图数据  

    return ret;

}

PngSaveImage实现将内存图像数据保存为文件名为pstrFileNamePNG图像,如果执行成功,函数返回TRUE,失败则返回FALSE

BOOL MyPNG::PngSaveImage (const char * pstrFileName)

{

    const int  ciBitDepth = 8, ciChannels = 3;

    FILE   *pfFile;   png_uint_32    ulRowBytes;   static png_byte   **ppbRowPointers = NULL;

    int  i, iWidth,iHeight;

iWidth=cxImgSize;   iHeight=cyImgSize;

    if (!pstrFileName)    return FALSE;  // 文件指针为空则返回

    if (!(pfFile = fopen(pstrFileName, "wb")))  return FALSE; //创建文件

    // 创建标准的 PNG 结构信息

    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,

      (png_error_ptr)png_cexcept_error, (png_error_ptr)NULL);

    if (!png_ptr)  { fclose(pfFile); return FALSE; }

    info_ptr = png_create_info_struct(png_ptr);

    if (!info_ptr)  { fclose(pfFile);  png_destroy_write_struct(&png_ptr, (png_infopp) NULL);  return FALSE; }

    Try

    {

#if !defined(PNG_NO_STDIO)

        png_init_io(png_ptr, pfFile); //初始化 png 结构体信息  

#else

        png_set_write_fn(png_ptr, (png_voidp)pfFile, png_write_data, png_flush);

#endif  

        png_set_IHDR(png_ptr, info_ptr, iWidth, iHeight, ciBitDepth,

            PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,

            PNG_FILTER_TYPE_BASE); //写入每像素3比特的PNG图像

        png_write_info(png_ptr, info_ptr);  //写入文件头信息

        png_set_bgr(png_ptr);           //BGR次序转换为RGB次序

        ulRowBytes = iWidth * ciChannels;   // 每行的字节数     

        if ((ppbRowPointers = (png_bytepp) malloc(iHeight * sizeof(png_bytep))) == NULL)

            Throw "MyPNG: Out of memory"; //分配内存失败;

        //设置每行的指针地址

        for (i = 0; i < iHeight; i++)  ppbRowPointers[i] = pPixelBuffer + (iHeight-1-i) * (((ulRowBytes + 3) >> 2) << 2);              

        png_write_image (png_ptr, ppbRowPointers);   // 一次写入整幅图像             

        png_write_end(png_ptr, info_ptr);  // 写辅助块信息

        free (ppbRowPointers); //释放空间

        ppbRowPointers = NULL;       

        png_destroy_write_struct(&png_ptr, (png_infopp) NULL);    //写操作结束,释放空间   

    } Catch (msg)

    {   png_destroy_write_struct(&png_ptr, (png_infopp) NULL);

        if(ppbRowPointers)    free (ppbRowPointers);

        fclose(pfFile);

        return FALSE;

    }  

    fclose (pfFile);   

    return TRUE;

}

  推荐精品文章

·2024年12月目录 
·2024年11月目录 
·2024年10月目录 
·2024年9月目录 
·2024年8月目录 
·2024年7月目录 
·2024年6月目录 
·2024年5月目录 
·2024年4月目录 
·2024年3月目录 
·2024年2月目录 
·2024年1月目录
·2023年12月目录
·2023年11月目录

  联系方式
TEL:010-82561037
Fax: 010-82561614
QQ: 100164630
Mail:gaojian@comprg.com.cn

  友情链接
 
Copyright 2001-2010, www.comprg.com.cn, All Rights Reserved
京ICP备14022230号-1,电话/传真:010-82561037 82561614 ,Mail:gaojian@comprg.com.cn
地址:北京市海淀区远大路20号宝蓝大厦E座704,邮编:100089