3

我最近尝试更新我的游戏以存储压缩格式(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()失败并出现访问冲突:

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

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

4

7 回答 7

7

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

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

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

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

但是,我对 libjpeg 的界面很好奇,所以我得到了一个令我满意的测试程序,它基于您的示例程序以及libjpeg.docIJG 示例USING 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;
}
于 2008-12-25T10:33:10.150 回答
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”。你看这基本上是一个兼容性问题。

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

于 2012-10-03T13:59:52.743 回答
1

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

于 2008-12-26T05:12:06.600 回答
0

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

功能列表:

支持加载:

  • .bmp
  • 。切
  • .dcx
  • .dds
  • .exr
  • .ico
  • .icns
  • .gif
  • .jpg
  • .jp2
  • .磅
  • .lif
  • .mdl
  • .pcd
  • .pcx
  • .pic
  • .png
  • .pnm
  • .psd
  • .psp
  • 。生的
  • .sgi
  • .tga
  • .tif
  • .wal
  • 。行为
  • 。朋友
  • .hdr
  • 厄运图形

支持保存:

  • .bmp
  • .dds
  • .jpg
  • .pcx
  • .png
  • .pnm
  • 。生的
  • .sgi
  • .tga
  • .tif
  • 。朋友

库功能

  • 便携,支持 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 支持。
于 2008-12-25T06:48:53.223 回答
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);
}
于 2016-03-19T16:45:06.997 回答
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

于 2018-11-15T12:04:24.463 回答