Поддержка JPEG с ijg - получение нарушения доступа - PullRequest
3 голосов
/ 24 декабря 2008

Я недавно пытался обновить мою игру для хранения графики в сжатых форматах (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 (ntdll.dll) в JPEGTest.exe: 0xC0000005: Запись о нарушении доступа местоположение 0x00000010.

У кого-нибудь есть идеи, что я могу делать не так?

Ответы [ 7 ]

7 голосов
/ 05 марта 2009

Я только что столкнулся с той же проблемой (хотя я пытался кодировать изображение). Очевидно, FILE * не переносимы между DLL, поэтому вы не можете использовать любой API libjpeg, который принимает FILE * в качестве параметра.

Существует несколько решений, но все они сводятся к необходимости перестраивать библиотеку:

  • Создайте библиотеку как статическую библиотеку и свяжите ее с вашим приложением. Это то, что я сделал, и это решило мою проблему.
  • Переместите обработчики источника / назначения из libjpeg в ваше приложение. Затем вы можете создать libjpeg либо как статическую библиотеку, либо как DLL, в зависимости от того, что вам подходит. Я не уверен, будет ли это работать, но это предлагаемое решение в файле "install.doc", распространяемом с исходным кодом.
4 голосов
/ 25 декабря 2008

Я согласен с Эрнаном. Это не очень хороший интерфейс (я думаю, что сам внутренний код, вероятно, хорош), если только вам действительно не нужно работать на низком уровне (а может, даже тогда) Я думаю, что ImageMagick, вероятно, лучше. У них есть интерфейс «MagickWand» C более высокого уровня, не говоря уже о том, что он поддерживает гораздо больше форматов.

Однако мне было любопытно узнать интерфейс libjpeg, поэтому я получил тестовую программу, работающую на мое удовлетворение, основанную на вашей программе-примере, а также libjpeg.doc , пример IJG и ИСПОЛЬЗУЯ БИБЛИОТЕКУ JPEG IJG . Во всяком случае, вот код. Он просто распечатывает размеры и 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 голосов
/ 03 октября 2012

Вот обходной путь без необходимости перестраивать библиотеку: выполните замену функций ввода-вывода, как сказал Андре Карон, но в них нет ничего, кроме стандартных функций 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: «Эй, не используйте функции записи из MSVCR, на которые указывает ваш .dll, используйте те, которые приходят из MSVCR, который я использую в моей программе, fwrite и fflush». Вы видите, что это в основном проблема совместимости.

Я надеюсь, что это или что-то подобное решит проблему.

1 голос
/ 26 декабря 2008

Трудно увидеть причину нарушения прав доступа из приведенного примера кода. Если вы можете включить трассировку стека (с символами), которая поможет определить проблему. Необходимо проверить, что параметры выравнивания для проектов .LIB и .EXE непротиворечивы, что часто приводит к неприятным проблемам, поскольку члены struct / class находятся не там, где их ожидает компилятор.

0 голосов
/ 15 ноября 2018

Этот вопрос уже почти 10 лет, но то же самое, что опубликовал автор, случилось со мной сегодня (я использую Visual Studio 2013).

Первоначально я пытался использовать библиотеку libjpeg из GnuWin32: http://gnuwin32.sourceforge.net/packages/jpeg.htm и получал ту же ошибку. Затем заметил, что это "версия 6b" libJpeg, которая довольно старая (2005) Для меня работала установка libJpeg через менеджер nuget pacakge:

Install-Package libjpeg -Version 9.2.0.1

0 голосов
/ 19 марта 2016

вот проверенная функция

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);
}
0 голосов
/ 25 декабря 2008

Для работы с изображениями в нескольких форматах позвольте мне порекомендовать вам 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
  • .sgi
  • .tga
  • .tif
  • .wal
  • .act
  • .pal
  • .hdr
  • Doom graphics

Поддерживает сохранение:

  • .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-изображений).
  • Проверка изображений.
  • Поддержка слоев.
  • Поддержка мипмапов.
  • Поддержка анимации.
  • Указанный пользователем чистый цвет.
  • Может загрузить изображение по умолчанию, если загрузка не удалась.
  • Пользовательские подсказки.
  • Использование основных цветов.
  • Поддержка наложения изображения поверх другого.
  • Позволяет пользователю указывать свои собственные обратные вызовы загрузки и сохранения, даже переопределяя стандартные обратные вызовы.
  • Поддержка пользовательских функций чтения и записи.
  • Поддержка Delphi.
  • Поддержка Visual Basic.
  • Поддержка Linux.
  • Может выбирать, какие функции будут использоваться для создания небольших библиотек.
  • Выберите, использовать ли библиотеку Intel Jpeg или libjpeg.
  • Целый ряд эффектов и фильтров для применения к изображениям, таких как тиснение и обнаружение краев.
  • Изображения могут быть изменены или даже помещены на больший фон (увеличенный холст).
  • Поддержка OpenGL, Allegro, Windows GDI и DirectX API.
...