【问题标题】:JPEG support with ijg - getting access violation带 ijg 的 JPEG 支持 - 获取访问冲突
【发布时间】:2010-09-28 08:39:45
【问题描述】:

我最近尝试更新 my game 以以压缩格式(JPEG 和 PNG)存储图形。

虽然我最终选择了一个不同的库,但我最初的尝试是合并 ijg 来进行 JPEG 解压缩。但是,我什至无法让最简单的控制台应用程序工作,我想知道是否有人能够解释原因。

这是我的代码,它链接到 jpeg.lib,它是 ijg 包的一部分:

#include "stdafx.h"
#include <stdio.h>
#include <assert.h>
#include <jpeglib.h>

int _tmain(int argc, _TCHAR* argv[])
{
    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;
    JSAMPARRAY buffer;
    int row_stride;

    //initialize error handling
    cinfo.err = jpeg_std_error(&jerr);

    //initialize the decompression
    jpeg_create_decompress(&cinfo);

    FILE* infile;
    errno_t err = fopen_s(&infile, "..\\Sample.jpg", "rb");
    assert(err == 0);

    //specify the input
    jpeg_stdio_src(&cinfo, infile);

    //read headers
    (void) jpeg_read_header(&cinfo, TRUE);

    return 0;
}

问题是对jpeg_read_header() 的调用因访问冲突而失败:

0x7c91b1fa 处未处理的异常 JPEGTest.exe 中的 (ntdll.dll): 0xC0000005:访问冲突写入 位置 0x00000010。

有没有人知道我可能做错了什么?

【问题讨论】:

  • 1 个问题——为什么你初始化错误处理两次?
  • 我的错 - 将更新我的帖子。

标签: c++ c jpeg ijg


【解决方案1】:

这个问题到现在已经快 10 年了,但与作者今天发生在我身上的完全一样(我使用的是 Visual Studio 2013)。

最初我尝试使用 GnuWin32 中的 libjpeg 库:http://gnuwin32.sourceforge.net/packages/jpeg.htm 并遇到同样的错误。 然后注意到这是 libJpeg 的 "version 6b",现在已经很老了(2005 年) 对我有用的是通过 nuget pacakge manager 安装 libJpeg:

安装包 libjpeg -Version 9.2.0.1

【讨论】:

    【解决方案2】:

    这是一个测试过的函数

    void test(char FileName[])
    {
        unsigned long x, y;
        struct jpeg_decompress_struct info; //for our jpeg info
        struct jpeg_error_mgr err;           //the error handler
        JSAMPARRAY buffer;
        FILE* infile;
        //initialize error handling
        info.err = jpeg_std_error(& err);     
    
        infile = fopen(FileName, "rb");  //open the file
    
        //if the jpeg file doesn't load
        if(!infile) {
        fprintf(stderr, "Error reading JPEG file %s!", FileName);
            // printf("Error reading JPEG file %s!", FileName);
            //return 0;
        }
    
        //initialize the decompression
        jpeg_create_decompress(&info);
    
    
        //specify the input
        jpeg_stdio_src(&info, infile);    
    
        //read headers
        jpeg_read_header(&info, TRUE);   // read jpeg file header
    
        jpeg_start_decompress(&info);    // decompress the file
    
        //set width and height
        x = info.output_width;
        y = info.output_height;
    
        printf("x value is %ul", x);
        printf("x value is %ul", y);
    }
    

    【讨论】:

      【解决方案3】:

      这是一种无需重建库的解决方法:如 André Caron 所述,制作替换 I/O 函数,但其​​中除了标准 stdio 函数之外什么都没有。

      我过去编写的以下代码可能会有所帮助。 它是为 libpng 编写的,但我相信在 libjpeg 中也很容易做到这一点。

      我在代码中添加了这个:

          png_set_write_fn (png_ptr,file,replwrite,replflush);
      

      然后创建替换函数:

      void replwrite (png_structp png_ptr, png_bytep data, png_size_t length)
      {
          fwrite (data,1,length,(FILE*) png_get_io_ptr(png_ptr));
      }
      
      void replflush (png_structp png_ptr)
      {
          fflush ((FILE*) png_get_io_ptr(png_ptr));
      }
      

      它总是对我有用。我实际上在做的是告诉 libpng,“嘿,不要使用 .dll 指向的 MSVCR 中的写入函数,使用这些来自我在程序中使用的 MSVCR 的写入函数,fwrite 和 fflush”。你看这基本上是一个兼容性问题。

      我希望这个或类似的东西能解决问题。

      【讨论】:

        【解决方案4】:

        我刚刚遇到了同样的问题(尽管我试图对图像进行编码)。 显然,FILE* 在 DLL 之间不可移植,因此您不能使用任何将 FILE* 作为参数的 libjpeg API。

        有多种解决方案,但都归结为必须重建库:

        • 将该库构建为静态库,并将其链接到您的应用程序。这就是我所做的,它解决了我的问题。
        • 将源/目标处理程序移出 libjpeg 并移入您的应用程序。然后,您可以将 libjpeg 构建为静态库或 DLL,以适合您的方式。我不确定这是否可行,但这是随源代码分发的“install.doc”文件中建议的解决方案。

        【讨论】:

        • 对于后代,jpeglib 支持使用自定义 I/O 处理程序,这意味着您不必重建库。但是,这通常比一开始就重建库要困难。
        【解决方案5】:

        我同意埃尔南的观点。这不是一个好的接口(我认为内部代码本身可能很好),除非你真的需要在底层工作(甚至可能不需要)。我认为 ImageMagick 可能更好。他们有一个更高级的“MagickWand”C 接口,更不用说它支持更多的格式。

        但是,我对 libjpeg 的界面很好奇,所以我根据您的示例程序以及 libjpeg.docIJG exampleUSING THE IJG JPEG LIBRARY,得到了一个令我满意的测试程序。无论如何,这是代码。它只是打印出尺寸,以及每行第一个像素的 RGB。

        我很惊讶您的代码出现错误。它对我来说很好,并且编译时没有任何警告。其他人可以测试吗?

        #include <stdio.h>
        #include <assert.h>
        #include <jpeglib.h>
        
        int main(int argc, char* argv[])
        {
            struct jpeg_decompress_struct cinfo;
            struct jpeg_error_mgr jerr;
            JSAMPARRAY buffer;
            int row_stride;
        
            //initialize error handling
            cinfo.err = jpeg_std_error(&jerr);
        
            FILE* infile;
            infile = fopen("Sample.jpg", "rb");
            assert(infile != NULL);
        
            //initialize the decompression
            jpeg_create_decompress(&cinfo);
        
            //specify the input
            jpeg_stdio_src(&cinfo, infile);
        
            //read headers
            (void) jpeg_read_header(&cinfo, TRUE);
        
            jpeg_start_decompress(&cinfo);
        
            printf("width: %d, height: %d\n", cinfo.output_width, cinfo.output_height);
        
            row_stride = cinfo.output_width * cinfo.output_components;
        
            buffer = (*cinfo.mem->alloc_sarray)
                ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
        
            JSAMPLE firstRed, firstGreen, firstBlue; // first pixel of each row, recycled
            while (cinfo.output_scanline < cinfo.output_height)
            {
            (void)jpeg_read_scanlines(&cinfo, buffer, 1);
            firstRed = buffer[0][0];
            firstBlue = buffer[0][1];
            firstGreen = buffer[0][2];
            printf("R: %d, G: %d, B: %d\n", firstRed, firstBlue, firstGreen);
            }
        
            jpeg_finish_decompress(&cinfo);
        
            return 0;
        }
        

        【讨论】:

        • 我很欣赏 ijg 可能不是最好的库。正如我的问题所述,我已经选择了一个不同的图书馆。但是,我只是想了解这个问题。运行您的代码时,我仍然遇到同样的错误。
        【解决方案6】:

        从给出的代码示例中很难看出访问冲突的原因。如果您可以包含有助于识别问题的堆栈跟踪(带有符号)。 要验证的一件事是 .LIB 和 .EXE 项目的对齐设置是一致的,这通常会导致严重的问题,因为结构/类成员不在编译器期望的位置。

        【讨论】:

        • 对。 libjpeg 非常稳定,本身不会导致内存冲突。问题应该是 libjpeg 外部的。
        【解决方案7】:

        要处理多种格式的图像,我建议您将 DevIL 作为库 http://openil.sourceforge.net/。这是一个很好的选择,因为我已经多次使用它并取得了很好的效果。请注意,它的语法类似于 OpenGL。

        功能列表:

        支持加载:

        • .bmp
        • .cut
        • .dcx
        • .dds
        • .exr
        • .ico
        • .icns
        • .gif
        • .jpg
        • .jp2
        • .lbm
        • .lif
        • .mdl
        • .pcd
        • .pcx
        • .pic
        • .png
        • .pnm
        • .psd
        • .psp
        • .raw
        • .sgi
        • .tga
        • .tif
        • .wal
        • .行动
        • .pal
        • .hdr
        • 厄运图形

        支持保存:

        • .bmp
        • .dds
        • .jpg
        • .pcx
        • .png
        • .pnm
        • .raw
        • .sgi
        • .tga
        • .tif
        • .pal

        图书馆功能

        • 便携,支持 Windows、Mac OS X 和 *nix。
        • OpenGL 风格的语法。
        • 使用图像名称而不是丑陋的指针。
        • 从文件、文件流或内存“块”加载。
        • 通过 ilGetData() 和 ilSetData() 直接访问数据。
        • 支持亮度、rgb(a)、bgr(a) 和颜色索引图像。
        • 每个通道支持 3 种不同的位数。
        • 所有格式和数据类型(包括调色板)之间的转换。
        • 加载图像时,如果需要,用户定义的自动转换。
        • 如果需要,保存图像时自动转换。
        • 如果需要,可将彩色索引图像自动转换为真彩色图像。
        • 保存时可控制压缩。
        • 维护一个可以推送和弹出的状态堆栈。
        • 完全支持 3d 纹理体积(3d 图像)。
        • 图像验证。
        • 支持层。
        • 支持 mipmap。
        • 支持动画。
        • 用户指定的透明色。
        • 如果加载失败,可以加载默认图像。
        • 用户指定的提示。
        • 关键颜色的使用。
        • 支持将图像叠加到另一个图像之上。
        • 允许用户指定自己的加载和保存回调,甚至覆盖默认回调。
        • 支持用户指定的读写功能。
        • 德尔福支持。
        • Visual Basic 支持。
        • Linux 支持。
        • 可以挑选用于创建更小的 dll 的功能。
        • 选择是使用英特尔 Jpeg 库还是 libjpeg。
        • 适用于图像的一整套效果和滤镜,例如浮雕和边缘检测。
        • 图像可以调整大小,甚至可以放在更大的背景上(放大的画布)。
        • OpenGL、Allegro、Windows GDI 和 DirectX API 支持。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-10-07
          • 1970-01-01
          • 1970-01-01
          • 2010-10-02
          • 1970-01-01
          相关资源
          最近更新 更多