2019-12-24 23:39:04 +00:00
|
|
|
#include "escl.h"
|
|
|
|
|
|
|
|
#include "../include/sane/sanei.h"
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#if(defined HAVE_LIBJPEG)
|
|
|
|
# include <jpeglib.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <setjmp.h>
|
|
|
|
|
|
|
|
#define INPUT_BUFFER_SIZE 4096
|
|
|
|
|
|
|
|
#if(defined HAVE_LIBJPEG)
|
|
|
|
struct my_error_mgr
|
|
|
|
{
|
|
|
|
struct jpeg_error_mgr errmgr;
|
|
|
|
jmp_buf escape;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
struct jpeg_source_mgr pub;
|
|
|
|
FILE *ctx;
|
|
|
|
unsigned char buffer[INPUT_BUFFER_SIZE];
|
|
|
|
} my_source_mgr;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \fn static boolean fill_input_buffer(j_decompress_ptr cinfo)
|
|
|
|
* \brief Called in the "skip_input_data" function.
|
|
|
|
*
|
|
|
|
* \return TRUE (everything is OK)
|
|
|
|
*/
|
|
|
|
static boolean
|
|
|
|
fill_input_buffer(j_decompress_ptr cinfo)
|
|
|
|
{
|
|
|
|
my_source_mgr *src = (my_source_mgr *) cinfo->src;
|
|
|
|
int nbytes = 0;
|
|
|
|
|
|
|
|
nbytes = fread(src->buffer, 1, INPUT_BUFFER_SIZE, src->ctx);
|
|
|
|
if (nbytes <= 0) {
|
|
|
|
src->buffer[0] = (unsigned char) 0xFF;
|
|
|
|
src->buffer[1] = (unsigned char) JPEG_EOI;
|
|
|
|
nbytes = 2;
|
|
|
|
}
|
|
|
|
src->pub.next_input_byte = src->buffer;
|
|
|
|
src->pub.bytes_in_buffer = nbytes;
|
|
|
|
return (TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \fn static void skip_input_data(j_decompress_ptr cinfo, long num_bytes)
|
|
|
|
* \brief Called in the "jpeg_RW_src" function.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
skip_input_data(j_decompress_ptr cinfo, long num_bytes)
|
|
|
|
{
|
|
|
|
my_source_mgr *src = (my_source_mgr *) cinfo->src;
|
|
|
|
|
|
|
|
if (num_bytes > 0) {
|
|
|
|
while (num_bytes > (long) src->pub.bytes_in_buffer) {
|
|
|
|
num_bytes -= (long) src->pub.bytes_in_buffer;
|
|
|
|
(void) src->pub.fill_input_buffer(cinfo);
|
|
|
|
}
|
|
|
|
src->pub.next_input_byte += (size_t) num_bytes;
|
|
|
|
src->pub.bytes_in_buffer -= (size_t) num_bytes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
term_source(j_decompress_ptr __sane_unused__ cinfo)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
init_source(j_decompress_ptr __sane_unused__ cinfo)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \fn static void jpeg_RW_src(j_decompress_ptr cinfo, FILE *ctx)
|
|
|
|
* \brief Called in the "escl_sane_decompressor" function.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
jpeg_RW_src(j_decompress_ptr cinfo, FILE *ctx)
|
|
|
|
{
|
|
|
|
my_source_mgr *src;
|
|
|
|
|
|
|
|
if (cinfo->src == NULL) {
|
|
|
|
cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)
|
|
|
|
((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(my_source_mgr));
|
|
|
|
src = (my_source_mgr *) cinfo->src;
|
|
|
|
}
|
|
|
|
src = (my_source_mgr *) cinfo->src;
|
|
|
|
src->pub.init_source = init_source;
|
|
|
|
src->pub.fill_input_buffer = fill_input_buffer;
|
|
|
|
src->pub.skip_input_data = skip_input_data;
|
|
|
|
src->pub.resync_to_restart = jpeg_resync_to_restart;
|
|
|
|
src->pub.term_source = term_source;
|
|
|
|
src->ctx = ctx;
|
|
|
|
src->pub.bytes_in_buffer = 0;
|
|
|
|
src->pub.next_input_byte = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
my_error_exit(j_common_ptr cinfo)
|
|
|
|
{
|
|
|
|
struct my_error_mgr *err = (struct my_error_mgr *)cinfo->err;
|
|
|
|
|
|
|
|
longjmp(err->escape, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
output_no_message(j_common_ptr __sane_unused__ cinfo)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \fn SANE_Status escl_sane_decompressor(escl_sane_t *handler)
|
|
|
|
* \brief Function that aims to decompress the jpeg image to SANE be able to read the image.
|
|
|
|
* This function is called in the "sane_read" function.
|
|
|
|
*
|
|
|
|
* \return SANE_STATUS_GOOD (if everything is OK, otherwise, SANE_STATUS_NO_MEM/SANE_STATUS_INVAL)
|
|
|
|
*/
|
|
|
|
SANE_Status
|
2019-12-25 17:36:23 +00:00
|
|
|
get_JPEG_data(capabilities_t *scanner, int *w, int *h, int *bps)
|
2019-12-24 23:39:04 +00:00
|
|
|
{
|
|
|
|
int start = 0;
|
|
|
|
struct jpeg_decompress_struct cinfo;
|
|
|
|
JSAMPROW rowptr[1];
|
|
|
|
unsigned char *surface = NULL;
|
|
|
|
struct my_error_mgr jerr;
|
|
|
|
int lineSize = 0;
|
|
|
|
|
|
|
|
if (scanner->tmp == NULL)
|
|
|
|
return (SANE_STATUS_INVAL);
|
|
|
|
fseek(scanner->tmp, SEEK_SET, 0);
|
|
|
|
start = ftell(scanner->tmp);
|
|
|
|
cinfo.err = jpeg_std_error(&jerr.errmgr);
|
|
|
|
jerr.errmgr.error_exit = my_error_exit;
|
|
|
|
jerr.errmgr.output_message = output_no_message;
|
|
|
|
if (setjmp(jerr.escape)) {
|
|
|
|
jpeg_destroy_decompress(&cinfo);
|
|
|
|
if (surface != NULL)
|
|
|
|
free(surface);
|
|
|
|
return (SANE_STATUS_INVAL);
|
|
|
|
}
|
|
|
|
jpeg_create_decompress(&cinfo);
|
|
|
|
jpeg_RW_src(&cinfo, scanner->tmp);
|
|
|
|
jpeg_read_header(&cinfo, TRUE);
|
|
|
|
cinfo.out_color_space = JCS_RGB;
|
|
|
|
cinfo.quantize_colors = FALSE;
|
|
|
|
jpeg_calc_output_dimensions(&cinfo);
|
|
|
|
surface = malloc(cinfo.output_width * cinfo.output_height * cinfo.output_components);
|
|
|
|
if (surface == NULL) {
|
|
|
|
jpeg_destroy_decompress(&cinfo);
|
|
|
|
fseek(scanner->tmp, start, SEEK_SET);
|
|
|
|
return (SANE_STATUS_NO_MEM);
|
|
|
|
}
|
|
|
|
lineSize = cinfo.output_width * cinfo.output_components;
|
|
|
|
jpeg_start_decompress(&cinfo);
|
|
|
|
while (cinfo.output_scanline < cinfo.output_height) {
|
|
|
|
rowptr[0] = (JSAMPROW)surface + (lineSize * cinfo.output_scanline);
|
|
|
|
jpeg_read_scanlines(&cinfo, rowptr, (JDIMENSION) 1);
|
|
|
|
}
|
|
|
|
scanner->img_data = surface;
|
|
|
|
scanner->img_size = lineSize * cinfo.output_height;
|
|
|
|
scanner->img_read = 0;
|
2019-12-25 17:36:23 +00:00
|
|
|
*w = cinfo.output_width;
|
|
|
|
*h = cinfo.output_height;
|
|
|
|
*bps = cinfo.output_components;
|
2019-12-24 23:39:04 +00:00
|
|
|
jpeg_finish_decompress(&cinfo);
|
|
|
|
jpeg_destroy_decompress(&cinfo);
|
|
|
|
fclose(scanner->tmp);
|
|
|
|
scanner->tmp = NULL;
|
|
|
|
return (SANE_STATUS_GOOD);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
|
|
|
|
SANE_Status
|
2019-12-25 17:36:23 +00:00
|
|
|
get_JPEG_data(capabilities_t __sane_unused__ *scanner,
|
|
|
|
int __sane_unused__ *w,
|
|
|
|
int __sane_unused__ *h,
|
|
|
|
int __sane_unused__ *bps)
|
2019-12-24 23:39:04 +00:00
|
|
|
{
|
2019-12-26 10:55:00 +00:00
|
|
|
return (SANE_STATUS_INVAL);
|
2019-12-24 23:39:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|