You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
172 lines
3.9 KiB
172 lines
3.9 KiB
4 years ago
|
#include <config.h>
|
||
|
#include <setjmp.h>
|
||
|
#include "gdk_imlib.h"
|
||
|
#include "gdk_imlib_private.h"
|
||
|
|
||
|
#ifdef HAVE_LIBJPEG
|
||
|
#include <jpeglib.h>
|
||
|
|
||
|
/**
|
||
|
* This error handling is broken beyond belief, but oh well it works
|
||
|
**/
|
||
|
|
||
|
struct ImLib_JPEG_error_mgr
|
||
|
{
|
||
|
struct jpeg_error_mgr pub;
|
||
|
sigjmp_buf setjmp_buffer;
|
||
|
};
|
||
|
|
||
|
typedef struct ImLib_JPEG_error_mgr *emptr;
|
||
|
|
||
|
static void
|
||
|
g_JPEGFatalErrorHandler(j_common_ptr cinfo)
|
||
|
{
|
||
|
/* FIXME:
|
||
|
* We should somehow signal what error occurred to the caller so the
|
||
|
* caller can handle the error message */
|
||
|
emptr errmgr;
|
||
|
|
||
|
errmgr = (emptr) cinfo->err;
|
||
|
cinfo->err->output_message(cinfo);
|
||
|
siglongjmp(errmgr->setjmp_buffer, 1);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
unsigned char *
|
||
|
loader_jpeg (FILE * f, int *w, int *h, int *t)
|
||
|
{
|
||
|
struct jpeg_decompress_struct cinfo;
|
||
|
struct ImLib_JPEG_error_mgr jerr;
|
||
|
unsigned char *data, *line[16], *ptr;
|
||
|
int x, y, i;
|
||
|
|
||
|
*t = 0;
|
||
|
cinfo.err = jpeg_std_error(&(jerr.pub));
|
||
|
jerr.pub.error_exit = g_JPEGFatalErrorHandler;
|
||
|
|
||
|
/* error handler to longjmp to, we want to preserve signals */
|
||
|
if (sigsetjmp(jerr.setjmp_buffer, 1))
|
||
|
{
|
||
|
/* Whoops there was a jpeg error */
|
||
|
jpeg_destroy_decompress(&cinfo);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
jpeg_create_decompress(&cinfo);
|
||
|
jpeg_stdio_src(&cinfo, f);
|
||
|
jpeg_read_header(&cinfo, TRUE);
|
||
|
cinfo.do_fancy_upsampling = FALSE;
|
||
|
cinfo.do_block_smoothing = FALSE;
|
||
|
jpeg_start_decompress(&cinfo);
|
||
|
*w = cinfo.output_width;
|
||
|
*h = cinfo.output_height;
|
||
|
data = _gdk_malloc_image(*w, *h);
|
||
|
if (!data)
|
||
|
{
|
||
|
jpeg_destroy_decompress(&cinfo);
|
||
|
return NULL;
|
||
|
}
|
||
|
ptr = data;
|
||
|
|
||
|
if (cinfo.rec_outbuf_height > 16)
|
||
|
{
|
||
|
fprintf(stderr, "gdk_imlib ERROR: JPEG uses line buffers > 16. Cannot load.\n");
|
||
|
return NULL;
|
||
|
}
|
||
|
if (cinfo.output_components == 3)
|
||
|
{
|
||
|
for (y = 0; y < *h; y += cinfo.rec_outbuf_height)
|
||
|
{
|
||
|
for (i = 0; i < cinfo.rec_outbuf_height; i++)
|
||
|
{
|
||
|
line[i] = ptr;
|
||
|
ptr += *w * 3;
|
||
|
}
|
||
|
jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
|
||
|
}
|
||
|
}
|
||
|
else if (cinfo.output_components == 1)
|
||
|
{
|
||
|
for (i = 0; i < cinfo.rec_outbuf_height; i++)
|
||
|
{
|
||
|
if ((line[i] = malloc(*w)) == NULL)
|
||
|
{
|
||
|
int t = 0;
|
||
|
|
||
|
for (t = 0; t < i; t++)
|
||
|
free(line[t]);
|
||
|
jpeg_destroy_decompress(&cinfo);
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
for (y = 0; y < *h; y += cinfo.rec_outbuf_height)
|
||
|
{
|
||
|
jpeg_read_scanlines(&cinfo, line, cinfo.rec_outbuf_height);
|
||
|
for (i = 0; i < cinfo.rec_outbuf_height; i++)
|
||
|
{
|
||
|
for (x = 0; x < *w; x++)
|
||
|
{
|
||
|
*ptr++ = line[i][x];
|
||
|
*ptr++ = line[i][x];
|
||
|
*ptr++ = line[i][x];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
for (i = 0; i < cinfo.rec_outbuf_height; i++)
|
||
|
free(line[i]);
|
||
|
}
|
||
|
jpeg_finish_decompress(&cinfo);
|
||
|
jpeg_destroy_decompress(&cinfo);
|
||
|
|
||
|
return data;
|
||
|
}
|
||
|
|
||
|
gint
|
||
|
saver_jpeg (GdkImlibImage *im, char *file, GdkImlibSaveInfo *info)
|
||
|
{
|
||
|
struct jpeg_compress_struct cinfo;
|
||
|
struct jpeg_error_mgr jerr;
|
||
|
JSAMPROW row_pointer[1];
|
||
|
int row_stride;
|
||
|
FILE *f;
|
||
|
|
||
|
f = fopen(file, "wb");
|
||
|
if (f)
|
||
|
{
|
||
|
cinfo.err = jpeg_std_error(&jerr);
|
||
|
jpeg_create_compress(&cinfo);
|
||
|
jpeg_stdio_dest(&cinfo, f);
|
||
|
cinfo.image_width = im->rgb_width;
|
||
|
cinfo.image_height = im->rgb_height;
|
||
|
cinfo.input_components = 3;
|
||
|
cinfo.in_color_space = JCS_RGB;
|
||
|
jpeg_set_defaults(&cinfo);
|
||
|
jpeg_set_quality(&cinfo, (100 * info->quality) >> 8, TRUE);
|
||
|
jpeg_start_compress(&cinfo, TRUE);
|
||
|
row_stride = cinfo.image_width * 3;
|
||
|
while (cinfo.next_scanline < cinfo.image_height)
|
||
|
{
|
||
|
row_pointer[0] = im->rgb_data + (cinfo.next_scanline * row_stride);
|
||
|
jpeg_write_scanlines(&cinfo, row_pointer, 1);
|
||
|
}
|
||
|
jpeg_finish_compress(&cinfo);
|
||
|
fclose(f);
|
||
|
return 1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
unsigned char *
|
||
|
loader_jpeg (FILE * f, int *w, int *h, int *t)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
gint
|
||
|
saver_jpeg (GdkImlibImage *im, char *file, GdkImlibSaveInfo *info)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
#endif
|