从内存加载png时libpng错误无效的块类型

时间:2014-03-22 13:28:03

标签: c++ buffer libpng

我试图从内存缓冲区加载PNG,这样我就可以访问ImageData而无需先将其保存为文件。

内存缓冲区包含一个有效的png文件,当使用fwrite将其保存为磁盘上的文件时,我得到以下图像:https://dl.dropboxusercontent.com/u/13077624/test.png

这表示Kinect传感器接收的深度图像,对于那些你想知道的人来说。

这是给出错误的代码:

struct mem_encode
{
    char *buffer;
    png_uint_32 size;
    png_uint_32 current_pos;
};

void handle_data(const boost::system::error_code& error,
    size_t bytes_transferred)
{
    if (!error)
    {
        cout<<"Saving as file: "<<determinePathExtension(PNGFrame,"png");
        FILE* fp=fopen("test.png","wb");
        fwrite(data_,bytes_transferred,1,fp);
        fclose(fp);
        //get PNG file info struct (memory is allocated by libpng)
        png_structp png_ptr = NULL;
        png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
        if (!png_ptr) {

             std::cerr << "ERROR: Couldn't initialize png read struct" << std::endl;
             cin.get();
            return; //Do your own error recovery/handling here
        }
        // get PNG image data info struct (memory is allocated by libpng)
        png_infop info_ptr = NULL;
        info_ptr = png_create_info_struct(png_ptr);
        if (!info_ptr) {
         std::cerr << "ERROR: Couldn't initialize png info struct" << std::endl;
         cin.get();
         png_destroy_read_struct(&png_ptr, (png_infopp)0, (png_infopp)0);
         return; //Do your own error recovery/handling here
        }

        struct mem_encode pngdata;
        pngdata.buffer=data_;

        pngdata.size=(png_uint_32)bytes_transferred;
        pngdata.current_pos=0;
        png_set_read_fn(png_ptr,&pngdata, ReadData);
        //Start reading the png header
        png_set_sig_bytes(png_ptr, 8);
        png_read_info(png_ptr,info_ptr);
        //... Program crashes here
    }
    else
    {
        cout<<error.message()<<" Bytes received: "<<bytes_transferred<<endl;
        delete this;
    }
}


static void ReadData(png_structp png_ptr, png_bytep outBytes,
    png_size_t byteCountToRead){
        struct mem_encode* p=(struct mem_encode*)png_get_io_ptr(png_ptr);
        size_t nsize=p->size + byteCountToRead;

        if(byteCountToRead>(p->size-p->current_pos)) png_error(png_ptr,"read error in read_data_memory (loadpng)");

        /* copy new bytes */
        memcpy(outBytes,p->buffer + p->size,byteCountToRead);
        p->current_pos+=byteCountToRead;
}

调用该方法会导致程序崩溃并出现以下错误:

libpng error: [00][00][00][00]: invalid chunk type

data_表示存储PNG图像的数据缓冲区,并且是char *。 任何帮助将不胜感激。

我使用的来源:

这可能是由网络字节被严重翻译引起的吗?

2 个答案:

答案 0 :(得分:0)

我想你忘了阅读PNG签名字节。使用

if (png_sig_cmp(data, 0, 8)
   png_error(png_ptr, "it's not a PNG file");

然后你的

png_set_sig_bytes(png_ptr,8);

让libpng知道你已经阅读了签名。

或者,您可以使用png_set_sig_bytes(png_ptr, 0);和 让libpng为你做检查。

答案 1 :(得分:0)

您确定ReadData功能是否正确?为什么从地址memcpy开始p->buffer + p->size - 它不是缓冲区的末尾? nsize做了什么?