c – 尝试使用libpng加载映像时Windows上的运行时错误

我正在使用 pHash,该库使用 libpng.我有运行我的程序的问题,因为libpng无法加载PNG文件.

> libpng版本:1.4.19
>平台:Windows 10
>环境:Visual Studio 2015

不重要的

只要你想出了以下问题…

>图像的路径是否正确?是
>图像是否是有效的PNG文件?是

代码细节

图书馆pHash使用CImg,他们使用的CImg的版本有点老我认为:

#define cimg_version 148 // In CImg.h

我已经调试了库,并且问题出现在CImg.h中(包含在VCash VC项目中):

CImg<T>& _load_png(std::FILE *const file,const char *const filename) {
      if (!file && !filename)
        throw CImgArgumentException(_cimg_instance
                                    "load_png() : Specified filename is (null).",cimg_instance);
      // Open file and check for PNG validity
      if (Buffer) strcat(Buffer,"Checking PNG availability\r\n");
      const char *volatile nfilename = filename; // two 'volatile' here to remove a g++ warning due to 'setjmp'.
      std::FILE *volatile nfile = file?file:cimg::fopen(nfilename,"rb");

      unsigned char pngCheck[8] = { 0 };
      cimg::fread(pngCheck,8,(std::FILE*)nfile);
      if (png_sig_cmp(pngCheck,8)) {
        if (!file) cimg::fclose(nfile);
        throw CImgIOException(_cimg_instance
                              "load_png() : Invalid PNG file '%s'.",cimg_instance,nfilename?nfilename:"(FILE*)");
      }

      // Setup PNG structures for read
      png_voidp user_error_ptr = 0;
      png_error_ptr user_error_fn = 0,user_warning_fn = 0;
      png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,user_error_ptr,user_error_fn,user_warning_fn);

      if (!png_ptr) { // <-- PROBLEM HERE
        if (!file) cimg::fclose(nfile);
        throw CImgIOException(_cimg_instance
                              "load_png() : Failed to initialize 'png_ptr' structure for file '%s'.",nfilename?nfilename:"(FILE*)");
...
}

该片段显示了CImg T& T的第一部分_app_png(std :: FILE * const文件,const char * const filename),由phash使用的CImg库调用.

运行时问题

代码编译很好,但是我在运行时得到这个错误,我可以在调试器中看到:

CImgIOException: Failed to initialize ‘png_ptr’…

代码中指出的点.我不知道为什么,它加载图像失败.在CImg.h中调用png_create_read_struct时发生故障.该代码通过预处理器指令定义有点不明确.不清楚为什么它是失败的.

有任何想法吗?

解决方法

或者如果你自己包括libpng,或者如果另一个库包含和使用libpng,还有一些事情需要注意.

>您正在使用哪个版本的Visual Studio,libpng(dll或lib)文件必须与您的解决方链接的相同版本的Visual Studio构建.
>您正在使用32位或64位的平台是值得关注的.
>构建png库时的项目设置必须与当前项目的构建类型相匹配. (代码生成 – >运行时库)必须匹配.你的字符集也应该匹配.

告诉究竟是什么导致问题有点困难,但这些是一些需要看的东西.

我建议的一件事是去提供最新版本的libpng的网站并下载它.在计算机上设置一个文件夹,并通过Windows创建“系统环境变量”来指向您的库.在您正在使用的当前版本的VS中打开该库的解决方案,为静态lib和动态库(两种不同的解决方案)构建它,并将其构建为32位和64位,将生成文件保存到分离的文件夹中.然后进入依赖于这个的另一个库,尽可能地尝试切换dll或libs并链接到新的库.另外第三方库也应该尝试在同一版本的VS中打开解决方案,并尝试从那里做一个干净的构建.然后确保你正确连接一切.您可能还需要修改道具文件.

编辑

我不熟悉pHash或CImg,但我熟悉libpng.

我的一个项目中的一个功能是将png加载到纹理结构中.现在这一个依赖于许多其他类的类对象的一部分,但是您应该可以从这个代码片段中看到我正在使用libpng.

// ----------------------------------------------------------------------------
// loadpng()
bool TextureFileReader::loadpng( Texture* pTexture ) {
    struct PngFile {
        FILE*       fp;
        png_struct* pStruct;
        png_info*   pInfo;

        // --------------------------------------------------------------------
        PngFile() :
            fp( NULL ),pStruct( NULL ),pInfo( NULL )
        {} // PngFile

        // --------------------------------------------------------------------
        ~PngFile() {
            if ( NULL != fp ) {
                fclose( fp );
            }

            if ( NULL != pStruct ) {
                if ( NULL != pInfo ) {
                    png_destroy_read_struct( &pStruct,&pInfo,NULL );
                } else {
                    png_destroy_read_struct( &pStruct,NULL,NULL );
                }
            }
        } // ~PngFile
    } png;

    // Error Message Handling
    std::ostringstream strStream;
    strStream << __FUNCTION__ << " ";

    if ( fopen_s( &png.fp,m_strFilenameWithPath.c_str(),"rb" ) != 0 ) {
        strStream << "can not open file for reading";
        throwError( strStream );
    }

    // Test If File Is Actually A PNG Image
    const int NUM_HEADER_BYTES = 8;
    png_byte headerBytes[NUM_HEADER_BYTES];

    // Read The File Header
    if ( fread( headerBytes,1,NUM_HEADER_BYTES,png.fp ) != NUM_HEADER_BYTES ) {
        strStream << "error reading header";
        return false;
    }

    // Test Header
    if ( png_sig_cmp( headerBytes,NUM_HEADER_BYTES ) != 0 ) {
        return false; // Not A PNG FILE
    }

    // Init PNG Read Structure - Test PNG Version Compatibility
    png.pStruct = png_create_read_struct( PNG_LIBPNG_VER_STRING,NULL );
    if ( NULL == png.pStruct ) {
        strStream << "can not create struct for PNG file";
        throwError( strStream );
    }

    // Init PNG Info Structure - Allocate Memory For Image Info
    png.pInfo = png_create_info_struct( png.pStruct );
    if ( NULL == png.pInfo ) {
        strStream << "can not create info for PNG file";
        throwError( strStream );
    }

    // Prepare For Error Handling
    if ( setjmp( png_jmpbuf( png.pStruct ) ) ) {
        strStream << "can not init error handling for PNG file";
        throwError( strStream );
    }

    // Tell libPng Where The File Data Is
    png_init_io( png.pStruct,png.fp );

    // Tell libPng That You Have Already Read The Header Bytes
    png_set_sig_bytes( png.pStruct,NUM_HEADER_BYTES );

    // Read Image Data From The File
    png_read_png( png.pStruct,png.pInfo,PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_GRAY_TO_RGB,NULL );

    // Show Image Attributes
    png_byte colorType = png_get_color_type( png.pStruct,png.pInfo );
    switch( colorType ) {
        case PNG_COLOR_TYPE_RGB: 
        case PNG_COLOR_TYPE_RGBA: {
            break;
        }
        default: {
            strStream << "PNG is saved in an unsupported color type (" << colorType << ")";
            throwError( strStream );
        }
    }

    unsigned uHeight = png_get_image_height( png.pStruct,png.pInfo );
    unsigned uBytesPerRow = png_get_rowbytes( png.pStruct,png.pInfo );
    if ( 0 == uHeight || 0 == uBytesPerRow ) {
        strStream << "invalid image size. Height(" << uHeight << "),Bytes per row(" << uBytesPerRow << ")";
        throwError( strStream );
    }

    // Make Room For All Pixel Data
    unsigned uTotalNumBytes = uHeight * uBytesPerRow;
    pTexture->vPixelData.resize( uTotalNumBytes );

    // Get All Pixel Data From PNG Image
    png_bytepp ppPixelRow = png_get_rows( png.pStruct,png.pInfo );

    for ( unsigned int r = 0; r < uHeight; ++r ) {
        memcpy( &pTexture->vPixelData[ uBytesPerRow * ( uHeight - 1 - r ) ],ppPixelRow[r],uBytesPerRow );
    }

    // Store Other Values In Texture
    pTexture->uWidth            = png_get_image_width( png.pStruct,png.pInfo );
    pTexture->uHeight           = uHeight;
    pTexture->hasAlphaChannel   = ( colorType == PNG_COLOR_TYPE_RGBA );

    return true;
} // loadpng

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...