c++ - Compatibilidad con JPEG con ijg: violación de acceso
(6)
Recientemente intenté actualizar mi juego para almacenar gráficos en formatos comprimidos (JPEG y PNG).
Mientras que terminé estableciéndome en una biblioteca diferente, mi primer intento fue incorporar ijg para hacer descompresión JPEG. Sin embargo, no pude hacer funcionar siquiera la aplicación de consola más simple y me pregunto si alguien podría arrojar algo de luz sobre los motivos.
Aquí está mi código, que está vinculado al archivo jpeg.lib que forma parte de los paquetes 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;
}
El problema es que la llamada a jpeg_read_header()
falla con una violación de acceso:
Excepción no controlada en 0x7c91b1fa (ntdll.dll) en JPEGTest.exe: 0xC0000005: ubicación de escritura de violación de acceso 0x00000010.
¿Alguien tiene alguna idea de lo que podría estar haciendo mal?
Para trabajar con imágenes en múltiples formatos, permítame recomendarle DevIL como una biblioteca http://openil.sourceforge.net/ . Es una excelente opción, ya que la he usado muchas veces con excelentes resultados. Tenga en cuenta que su sintaxis es similar a OpenGL.
La lista de características:
Admite la carga de:
- .bmp
- .cortar
- .dcx
- .dds
- .exr
- .ico
- .icns
- .gif
- .jpg
- .jp2
- .lbm
- .lif
- .mdl
- .pcd
- .pcx
- .Foto
- .png
- .pnm
- .psd
- .psp
- .crudo
- .sgi
- .tga
- .tif
- .wal
- .acto
- .camarada
- .hdr
- Doom gráficos
Admite el ahorro de:
- .bmp
- .dds
- .jpg
- .pcx
- .png
- .pnm
- .crudo
- .sgi
- .tga
- .tif
- .camarada
Características de la biblioteca
- Portable, es compatible con Windows, Mac OS X y * nix.
- Sintaxis de estilo OpenGL
- Uso de nombres de imágenes en lugar de indicadores desagradables.
- Cargando desde archivos, secuencias de archivos o "bultos" de memoria.
- Acceso directo a los datos a través de ilGetData () e ilSetData ().
- Soporte para luminancia, rgb (a), bgr (a) e imágenes indexadas por color.
- Soporte para 3 números diferentes de bits por canal.
- Conversión entre todos los formatos y tipos de datos (incluidas las paletas).
- Conversiones automáticas definidas por el usuario si se desea al cargar imágenes.
- Conversión automática al guardar imágenes si es necesario.
- Conversión automática de imágenes indexadas por color a imágenes de color verdadero si se desea.
- Compresión controlable al guardar.
- Mantiene una pila de estado que puede ser empujada y reventada.
- Soporte completo para volúmenes de textura en 3D (imágenes en 3D).
- Validación de imágenes.
- Soporte para capas
- Soporte para mipmaps.
- Soporte para animaciones.
- Color claro especificado por el usuario.
- Puede cargar una imagen predeterminada si falla la carga.
- Indicaciones especificadas por el usuario.
- Uso de colores clave
- Soporte para superponer una imagen sobre otra.
- Permite al usuario especificar su propia carga y guardar devoluciones de llamadas, incluso anulando las predeterminadas.
- Soporte para funciones de lectura y escritura especificadas por el usuario.
- Soporte Delphi.
- Soporte de Visual Basic.
- Soporte de Linux.
- Puede escoger y elegir qué características se usarán para crear dlls más pequeños.
- Elija si desea usar la biblioteca Intel Jpeg o libjpeg.
- Una gran cantidad de efectos y filtros para aplicar a las imágenes, como el relieve y la detección de bordes.
- Las imágenes pueden redimensionarse o incluso colocarse en un fondo más grande (lienzo agrandado).
- Compatibilidad con OpenGL, Allegro, Windows GDI y DirectX API.
Es difícil ver la causa de la infracción de acceso de la muestra de código proporcionada. Si puede incluir un seguimiento de pila (con símbolos) que ayudaría a identificar el problema. Una cosa para verificar es que las configuraciones de alineación para los proyectos .LIB y .EXE son consistentes, esto a menudo conducirá a problemas desagradables ya que los miembros de struct / class no están donde el compilador espera que estén.
Estoy de acuerdo con Hernán. Esta no es una buena interfaz (creo que el código interno en sí mismo probablemente sea bueno), a menos que realmente necesite trabajar a bajo nivel (y tal vez ni siquiera entonces). Creo que ImageMagick es probablemente mejor. Tienen una interfaz C "MagickWand" que es de más alto nivel, sin mencionar que admite muchos formatos más.
Sin embargo, tenía curiosidad acerca de la interfaz de libjpeg, así que obtuve un programa de prueba que funcionaba a mi satisfacción, basado en su programa de ejemplo, así como en libjpeg.doc , el ejemplo de IJG y UTILIZANDO LA BIBLIOTECA IJG JPEG . De todos modos, aquí está el código. Simplemente imprime las dimensiones y el RGB del primer píxel de cada fila.
Estoy muy sorprendido de que obtengas un error con mi código. Funciona bien para mí y compila sin ninguna advertencia. ¿Alguien más puede probarlo?
#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;
}
Acabo de encontrar el mismo problema (aunque estaba tratando de codificar una imagen). Aparentemente, FILE * no es portátil entre las DLL, por lo que no puede usar ninguna API libjpeg que tome un FILE * como parámetro.
Hay varias soluciones, pero todas se reducen a tener que reconstruir la biblioteca:
- Cree la biblioteca como una lib estática y vincule a su aplicación. Esto es lo que hice, y resolvió mi problema.
- Mueva los manejadores de origen / destino de libjpeg a su aplicación. Entonces podría compilar libjpeg como una lib estática o una DLL, lo que más le convenga. No estoy seguro de si esto funcionaría, pero es la solución sugerida en el archivo "install.doc" distribuido con el código fuente.
Aquí hay una solución alternativa sin tener que reconstruir la biblioteca: realice funciones de E / S de reemplazo, como afirmó André Caron, pero no tiene nada en ellas excepto las funciones de stdio estándar.
El código a continuación que hice en el pasado podría ayudar. Está escrito para libpng, pero creo que es fácil hacer lo mismo en libjpeg.
Agregué esto al código:
png_set_write_fn (png_ptr,file,replwrite,replflush);
Luego creó las funciones de reemplazo:
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));
}
Siempre me funciona. Lo que estoy haciendo realmente es decir a libpng: "Oye, no uses las funciones de escritura del MSVCR a las que apunta tu .dll, usa estas, que vienen del MSVCR que uso en mi programa, fwrite y fflush". Ves que es básicamente un problema de compatibilidad.
Espero que esto o algo así resuelva el problema.
aquí hay una función probada
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);
}