使用ijg支持JPEG - 获取访问冲突

时间:2008-12-24 17:42:58

标签: c++ c jpeg ijg

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

虽然我最终选择了另一个库,但我最初的尝试是将ijg与JPEG解压缩结合起来。但是,我甚至无法使最简单的控制台应用程序工作,我想知道是否有人能够阐明原因。

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

#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。

有没有人有任何想法我可能做错了什么?

7 个答案:

答案 0 :(得分:7)

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

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

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

答案 1 :(得分:4)

我同意Hernán。这不是一个好的界面(我认为内部代码本身可能很好),除非你真的需要低级工作(甚至可能不是那么)。我认为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;
}

答案 2 :(得分:2)

这是一个解决方法,无需重建库:更换I / O函数,正如AndréCaron所说,但除了标准的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”。你看它基本上是一个兼容性问题。

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

答案 3 :(得分:1)

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

答案 4 :(得分:0)

要处理多种格式的图片,我建议您将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
  • 名为.act
  • .PAL
  • .HDR
  • 末日图形

支持保存:

  • .BMP
  • 的.dds
  • .JPG
  • .PCX
  • .PNG
  • .pnm
  • .RAW
  • .sgi
  • 的.tga
  • .TIF
  • .pal

图书馆功能

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

答案 5 :(得分:0)

这是一个经过测试的功能

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

答案 6 :(得分:0)

这个问题现在差不多已经有10年了,但是今天作者发给我的东西却完全一样(我使用的是Visual Studio 2013)。

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

  

安装软件包libjpeg-版本9.2.0.1