Adding png support. The decompressors (Jpeg and Png) are in separate files.

merge-requests/213/head
Thierry HUCHARD 2019-12-25 00:39:04 +01:00
rodzic 92308130f4
commit 5c15d37248
7 zmienionych plików z 562 dodań i 229 usunięć

Wyświetl plik

@ -437,13 +437,13 @@ EXTRA_DIST += dmc.conf.in
if have_libavahi
if have_libcurl
if have_libxml2
libescl_la_SOURCES = escl/escl.c escl/escl_capabilities.c escl/escl_devices.c escl/escl.h escl/escl_newjob.c escl/escl_reset.c escl/escl_scan.c escl/escl_status.c
libescl_la_CPPFLAGS = $(AM_CPPFLAGS) $(JPEG_CFLAGS) $(XML_CFLAGS) $(libcurl_CFLAGS) $(AVAHI_CFLAGS) -DBACKEND_NAME=escl
libescl_la_SOURCES = escl/escl.c escl/escl_capabilities.c escl/escl_devices.c escl/escl.h escl/escl_newjob.c escl/escl_reset.c escl/escl_scan.c escl/escl_status.c escl/escl_jpeg.c escl/escl_png.c
libescl_la_CPPFLAGS = $(AM_CPPFLAGS) $(JPEG_CFLAGS) $(PNG_CFLAGS) $(XML_CFLAGS) $(libcurl_CFLAGS) $(AVAHI_CFLAGS) -DBACKEND_NAME=escl
nodist_libsane_escl_la_SOURCES = escl-s.c
libsane_escl_la_CPPFLAGS = $(AM_CPPFLAGS) $(JPEG_CFLAGS) $(XML_CFLAGS) $(libcurl_CFLAGS) $(AVAHI_CFLAGS) -DBACKEND_NAME=escl
libsane_escl_la_CPPFLAGS = $(AM_CPPFLAGS) $(JPEG_CFLAGS) $(PNG_CFLAGS) $(XML_CFLAGS) $(libcurl_CFLAGS) $(AVAHI_CFLAGS) -DBACKEND_NAME=escl
libsane_escl_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
libsane_escl_la_LIBADD = $(COMMON_LIBS) libescl.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(JPEG_LIBS) $(XML_LIBS) $(libcurl_LIBS) $(AVAHI_LIBS)
libsane_escl_la_LIBADD = $(COMMON_LIBS) libescl.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo $(JPEG_LIBS) $(PNG_LIBS) $(XML_LIBS) $(libcurl_LIBS) $(AVAHI_LIBS)
endif
endif
endif

Wyświetl plik

@ -27,7 +27,7 @@
#include <stdlib.h>
#include <string.h>
#include <jpeglib.h>
#include <png.h>
#include <setjmp.h>
#include "../include/sane/saneopts.h"
@ -54,9 +54,6 @@ typedef struct Handled {
capabilities_t *scanner;
SANE_Range x_range;
SANE_Range y_range;
unsigned char *img_data;
long img_size;
long img_read;
SANE_Bool cancel;
SANE_Bool write_scan_data;
SANE_Bool decompress_scan_data;
@ -64,19 +61,6 @@ typedef struct Handled {
SANE_Parameters ps;
} escl_sane_t;
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 SANE_Status escl_add_in_list(ESCL_Device *current)
* \brief Function that adds all the element needed to my list :
@ -607,43 +591,6 @@ sane_control_option(SANE_Handle h, SANE_Int n, SANE_Action a, void *v, SANE_Int
return (SANE_STATUS_GOOD);
}
#if(defined HAVE_LIBJPEG)
static void
error_exit(j_common_ptr cinfo)
{
longjmp(cinfo->client_data, 1);
}
/**
* \fn static void get_JPEG_dimension(FILE *fp, int *w, int *h)
* \brief Function that aims to get the dimensions of the jpeg image wich will be scanned.
* This function is called in the "sane_start" function.
*/
static void
get_JPEG_dimension(FILE *fp, int *w, int *h)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
jmp_buf env;
cinfo.err = jpeg_std_error(&jerr);
jerr.error_exit = error_exit;
cinfo.client_data = env;
if (setjmp(env))
return;
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, fp);
jpeg_read_header(&cinfo, TRUE);
cinfo.out_color_space = JCS_RGB;
jpeg_start_decompress(&cinfo);
*w = cinfo.output_width;
*h = cinfo.output_height;
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fseek(fp, SEEK_SET, 0);
}
#endif
/**
* \fn SANE_Status sane_start(SANE_Handle h)
* \brief Function that initiates aquisition of an image from the device represented by handle 'h'.
@ -659,6 +606,7 @@ sane_start(SANE_Handle h)
escl_sane_t *handler = h;
int w = 0;
int he = 0;
int bps = 0;
if (handler->name == NULL)
return (SANE_STATUS_INVAL);
@ -699,12 +647,26 @@ sane_start(SANE_Handle h)
if (status != SANE_STATUS_GOOD)
return (status);
status = escl_scan(handler->scanner, handler->name, handler->result);
get_JPEG_dimension(handler->scanner->tmp, &w, &he);
fprintf(stderr, "DIM : [%s]\n", handler->scanner->default_format);
if (!strncmp(handler->scanner->default_format, "image/jpeg", 10))
{
get_JPEG_dimension(handler->scanner->tmp, &w, &he, &bps);
fprintf(stderr, "JPEG DIM : [%s]\n", handler->scanner->default_format);
}
else
{
get_PNG_dimension(handler->scanner->tmp, &w, &he, &bps);
fprintf(stderr, "PNG DIM : [%s]\n", handler->scanner->default_format);
}
fprintf(stderr, "SIZE [%dx%dx%d]\n", w, he, bps);
if (bps == 0)
return SANE_STATUS_INVAL;
fprintf(stderr, "2-SIZE [%dx%dx%d]\n", w, he, bps);
fseek(handler->scanner->tmp, SEEK_SET, 0);
handler->ps.depth = 8;
handler->ps.pixels_per_line = w;
handler->ps.lines = he;
handler->ps.bytes_per_line = w * 3;
handler->ps.bytes_per_line = w * bps;
handler->ps.last_frame = SANE_TRUE;
handler->ps.format = SANE_FRAME_RGB;
return (status);
@ -733,162 +695,14 @@ sane_get_parameters(SANE_Handle h, SANE_Parameters *p)
p->format = SANE_FRAME_RGB;
p->pixels_per_line = handler->ps.pixels_per_line;
p->lines = handler->ps.lines;
p->bytes_per_line = handler->ps.pixels_per_line * 3;
p->bytes_per_line = handler->ps.bytes_per_line;
fprintf(stderr, "GET SIZE [%dx%dx%d]\n", p->pixels_per_line,
p->lines,
(p->bytes_per_line / p->pixels_per_line));
}
return (status);
}
#if(defined HAVE_LIBJPEG)
/**
* \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
escl_sane_decompressor(escl_sane_t *handler)
{
int start = 0;
struct jpeg_decompress_struct cinfo;
JSAMPROW rowptr[1];
unsigned char *surface = NULL;
struct my_error_mgr jerr;
int lineSize = 0;
if (handler->scanner->tmp == NULL)
return (SANE_STATUS_INVAL);
fseek(handler->scanner->tmp, SEEK_SET, 0);
start = ftell(handler->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, handler->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(handler->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);
}
handler->img_data = surface;
handler->img_size = lineSize * cinfo.output_height;
handler->img_read = 0;
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(handler->scanner->tmp);
handler->scanner->tmp = NULL;
return (SANE_STATUS_GOOD);
}
#endif
/**
* \fn SANE_Status sane_read(SANE_Handle h, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *len)
@ -916,32 +730,40 @@ sane_read(SANE_Handle h, SANE_Byte *buf, SANE_Int maxlen, SANE_Int *len)
if (!handler->decompress_scan_data) {
if (handler->scanner->tmp == NULL)
return (SANE_STATUS_INVAL);
status = escl_sane_decompressor(handler);
fprintf(stderr, "READ : [%s]\n", handler->scanner->default_format);
if (!strncmp(handler->scanner->default_format, "image/jpeg", 10)){
fprintf(stderr, "JPEG READ : [%s]\n", handler->scanner->default_format);
status = get_JPEG_data(handler->scanner);
}
else{
fprintf(stderr, "PNG READ : [%s]\n", handler->scanner->default_format);
status = get_PNG_data(handler->scanner);
}
if (status != SANE_STATUS_GOOD)
return (status);
handler->decompress_scan_data = SANE_TRUE;
}
if (handler->img_data == NULL)
if (handler->scanner->img_data == NULL)
return (SANE_STATUS_INVAL);
if (!handler->end_read) {
readbyte = min((handler->img_size - handler->img_read), maxlen);
memcpy(buf, handler->img_data + handler->img_read, readbyte);
handler->img_read = handler->img_read + readbyte;
readbyte = min((handler->scanner->img_size - handler->scanner->img_read), maxlen);
memcpy(buf, handler->scanner->img_data + handler->scanner->img_read, readbyte);
handler->scanner->img_read = handler->scanner->img_read + readbyte;
*len = readbyte;
if (handler->img_read == handler->img_size)
if (handler->scanner->img_read == handler->scanner->img_size)
handler->end_read = SANE_TRUE;
else if (handler->img_read > handler->img_size) {
else if (handler->scanner->img_read > handler->scanner->img_size) {
*len = 0;
handler->end_read = SANE_TRUE;
free(handler->img_data);
handler->img_data = NULL;
free(handler->scanner->img_data);
handler->scanner->img_data = NULL;
return (SANE_STATUS_INVAL);
}
}
else {
*len = 0;
free(handler->img_data);
handler->img_data = NULL;
free(handler->scanner->img_data);
handler->scanner->img_data = NULL;
return (SANE_STATUS_EOF);
}
return (SANE_STATUS_GOOD);

Wyświetl plik

@ -40,6 +40,12 @@
#error "The escl backend currently requires libjpeg"
#endif
#ifndef HAVE_LIBPNG
/* FIXME: Make PNG support optional.
*/
#warning "The escl backend recommends libpng"
#endif
#include "../include/sane/sane.h"
#include <stdio.h>
@ -78,7 +84,7 @@ typedef struct capabilities
int pos_x;
int pos_y;
SANE_String default_color;
SANE_String_Const default_format;
SANE_String default_format;
SANE_Int default_resolution;
int MinWidth;
int MaxWidth;
@ -102,6 +108,9 @@ typedef struct capabilities
int RiskyTopMargin;
int RiskyBottomMargin;
FILE *tmp;
unsigned char *img_data;
long img_size;
long img_read;
int format_ext;
} capabilities_t;
@ -143,4 +152,12 @@ char *escl_newjob(capabilities_t *scanner, SANE_String_Const name, SANE_Status *
SANE_Status escl_scan(capabilities_t *scanner, SANE_String_Const name, char *result);
void escl_scanner(SANE_String_Const name, char *result);
# JPEG
void get_JPEG_dimension(FILE *fp, int *w, int *h, int *bps);
SANE_Status get_JPEG_data(capabilities_t *scanner);
# PNG
void get_PNG_dimension(FILE *fp, int *w, int *h, int *bps);
SANE_Status get_PNG_data(capabilities_t *scanner);
#endif

Wyświetl plik

@ -181,7 +181,30 @@ find_valor_of_array_variables(xmlNode *node, capabilities_t *scanner)
else if (strcmp(name, "ContentType") == 0)
scanner->ContentTypes = char_to_array(scanner->ContentTypes, &scanner->ContentTypesSize, (SANE_String_Const)xmlNodeGetContent(node), 0);
else if (strcmp(name, "DocumentFormat") == 0)
{
int i = 0;
scanner->DocumentFormats = char_to_array(scanner->DocumentFormats, &scanner->DocumentFormatsSize, (SANE_String_Const)xmlNodeGetContent(node), 0);
for(; i < scanner->DocumentFormatsSize; i++)
{
if (scanner->default_format == NULL && !strncmp(scanner->DocumentFormats[i], "image/jpeg", 10))
{
scanner->default_format = strdup("image/jpeg");
#if(defined HAVE_LIBPNG)
}
else if(!strncmp(scanner->DocumentFormats[i], "image/png", 9))
{
if (scanner->default_format)
free(scanner->default_format);
scanner->default_format = strdup("image/png");
break;
}
#else
break;
}
#endif
}
fprintf(stderr, "Capability : [%s]\n", scanner->default_format);
}
else if (strcmp(name, "DocumentFormatExt") == 0)
scanner->format_ext = 1;
else if (strcmp(name, "Intent") == 0)

Wyświetl plik

@ -0,0 +1,231 @@
#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;
static void
error_exit(j_common_ptr cinfo)
{
longjmp(cinfo->client_data, 1);
}
/**
* \fn static void get_JPEG_dimension(FILE *fp, int *w, int *h)
* \brief Function that aims to get the dimensions of the jpeg image wich will be scanned.
* This function is called in the "sane_start" function.
*/
void
get_JPEG_dimension(FILE *fp, int *w, int *h, int *bps)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
jmp_buf env;
cinfo.err = jpeg_std_error(&jerr);
jerr.error_exit = error_exit;
cinfo.client_data = env;
if (setjmp(env))
return;
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, fp);
jpeg_read_header(&cinfo, TRUE);
cinfo.out_color_space = JCS_RGB;
jpeg_start_decompress(&cinfo);
*w = cinfo.output_width;
*h = cinfo.output_height;
*bps = 3;
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fseek(fp, SEEK_SET, 0);
}
/**
* \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
get_JPEG_data(capabilities_t *scanner)
{
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;
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(scanner->tmp);
scanner->tmp = NULL;
return (SANE_STATUS_GOOD);
}
#else
void
get_JPEG_dimension(FILE __sane_unused__ *fp, int __sane_unused__ *w,
int __sane_unused__ *h, int __sane_unused__ *bps)
{
}
SANE_Status
get_JPEG_data(capabilities_t __sane_unused__ *scanner)
{
}
#endif

Wyświetl plik

@ -54,7 +54,7 @@ static const char settings[] =
" <pwg:YOffset>%d</pwg:YOffset>" \
" </pwg:ScanRegion>" \
" </pwg:ScanRegions>" \
" <pwg:DocumentFormat>image/jpeg</pwg:DocumentFormat>" \
" <pwg:DocumentFormat>%s</pwg:DocumentFormat>" \
"%s" \
" <scan:ColorMode>%s</scan:ColorMode>" \
" <scan:XResolution>%d</scan:XResolution>" \
@ -62,9 +62,12 @@ static const char settings[] =
" <pwg:InputSource>Platen</pwg:InputSource>" \
"</scan:ScanSettings>";
static const char formatExt[] =
static char formatExtJPEG[] =
" <scan:DocumentFormatExt>image/jpeg</scan:DocumentFormatExt>";
static char formatExtPNG[] =
" <scan:DocumentFormatExt>image/png</scan:DocumentFormatExt>";
/**
* \fn static size_t download_callback(void *str, size_t size, size_t nmemb, void *userp)
* \brief Callback function that stocks in memory the content of the 'job'. Example below :
@ -127,6 +130,8 @@ escl_newjob (capabilities_t *scanner, SANE_String_Const name, SANE_Status *statu
char *location = NULL;
char *result = NULL;
char *temporary = NULL;
char *f_ext = "";
char *format_ext = NULL;
*status = SANE_STATUS_GOOD;
if (name == NULL || scanner == NULL) {
@ -146,11 +151,20 @@ escl_newjob (capabilities_t *scanner, SANE_String_Const name, SANE_Status *statu
}
curl_global_init(CURL_GLOBAL_ALL);
curl_handle = curl_easy_init();
if (scanner->format_ext == 1)
{
if (!strncmp(scanner->default_format, "image/jpeg", 10))
format_ext = formatExtJPEG;
else
format_ext = formatExtPNG;
}
else
format_ext = f_ext;
if (curl_handle != NULL) {
snprintf(cap_data, sizeof(cap_data), settings, scanner->height, scanner->width, 0, 0,
(scanner->format_ext == 1 ? formatExt : ""),
snprintf(cap_data, sizeof(cap_data), settings, scanner->height, scanner->width, 0, 0, scanner->default_format,
format_ext,
scanner->default_color, scanner->default_resolution, scanner->default_resolution);
//fprintf(stderr, "CAP_DATA = %s\n", cap_data);
fprintf(stderr, "CAP_DATA = %s\n", cap_data);
upload->read_data = strdup(cap_data);
upload->size = strlen(cap_data);
download->memory = malloc(1);

Wyświetl plik

@ -0,0 +1,226 @@
#include "escl.h"
#include "../include/sane/sanei.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if(defined HAVE_LIBPNG)
#include <png.h>
#endif
#include <setjmp.h>
#if(defined HAVE_LIBPNG)
/**
* \fn static void get_PNG_dimension(FILE *fp, int *w, int *h)
* \brief Function that aims to get the dimensions of the png image wich will be scanned.
* This function is called in the "sane_start" function.
*/
void
get_PNG_dimension(FILE *fp, int *w, int *h, int *bps)
{
unsigned int width, height;
png_byte magic[8];
fread (magic, 1, sizeof (magic), fp);
/* check for valid magic number */
if (!png_check_sig (magic, sizeof (magic)))
{
fprintf (stderr, "error: is not a valid PNG image!\n");
return;
}
/* create a png read struct */
png_structp png_ptr = png_create_read_struct
(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr)
{
return;
}
/* create a png info struct */
png_infop info_ptr = png_create_info_struct (png_ptr);
if (!info_ptr)
{
png_destroy_read_struct (&png_ptr, NULL, NULL);
return;
}
/* initialize the setjmp for returning properly after a libpng
error occured */
if (setjmp (png_jmpbuf (png_ptr)))
{
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
return;
}
/* setup libpng for using standard C fread() function
with our FILE pointer */
png_init_io (png_ptr, fp);
/* tell libpng that we have already read the magic number */
png_set_sig_bytes (png_ptr, sizeof (magic));
/* read png info */
png_read_info (png_ptr, info_ptr);
int bit_depth, color_type;
/* get some usefull information from header */
bit_depth = png_get_bit_depth (png_ptr, info_ptr);
color_type = png_get_color_type (png_ptr, info_ptr);
/* convert index color images to RGB images */
if (color_type == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb (png_ptr);
else if (color_type != PNG_COLOR_TYPE_RGB && color_type != PNG_COLOR_TYPE_RGB_ALPHA)
{
fprintf(stderr, "Format non pris en charge.\n");
return;
}
if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
*bps = 4;
else
*bps = 3;
if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
png_set_tRNS_to_alpha (png_ptr);
if (bit_depth == 16)
png_set_strip_16 (png_ptr);
else if (bit_depth < 8)
png_set_packing (png_ptr);
/* update info structure to apply transformations */
png_read_update_info (png_ptr, info_ptr);
/* retrieve updated information */
png_get_IHDR (png_ptr, info_ptr,
(png_uint_32*)(&width),
(png_uint_32*)(&height),
&bit_depth, &color_type,
NULL, NULL, NULL);
*w = (int)width;
*h = (int)height;
/* finish decompression and release memory */
png_read_end (png_ptr, NULL);
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
fseek(fp, SEEK_SET, 0);
}
/**
* \fn SANE_Status escl_sane_decompressor(escl_sane_t *handler)
* \brief Function that aims to decompress the png 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
get_PNG_data(capabilities_t *scanner)
{
unsigned int width = 0; /* largeur */
unsigned int height = 0; /* hauteur */
int bps = 3; /* composantes d'un texel */
unsigned char *texels = NULL; /* données de l'image */
unsigned int i = 0;
png_byte magic[8];
// read magic number
fread (magic, 1, sizeof (magic), scanner->tmp);
// check for valid magic number
if (!png_check_sig (magic, sizeof (magic)))
{
fprintf(stderr,"PNG error: is not a valid PNG image!\n");
return (SANE_STATUS_INVAL);
}
// create a png read struct
png_structp png_ptr = png_create_read_struct
(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr)
{
return (SANE_STATUS_INVAL);
}
// create a png info struct
png_infop info_ptr = png_create_info_struct (png_ptr);
if (!info_ptr)
{
png_destroy_read_struct (&png_ptr, NULL, NULL);
return (SANE_STATUS_INVAL);
}
// initialize the setjmp for returning properly after a libpng
// error occured
if (setjmp (png_jmpbuf (png_ptr)))
{
png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
if (texels)
free (texels);
fprintf(stderr,"PNG read error.\n");
return (SANE_STATUS_INVAL);
}
// setup libpng for using standard C fread() function
// with our FILE pointer
png_init_io (png_ptr, scanner->tmp);
// tell libpng that we have already read the magic number
png_set_sig_bytes (png_ptr, sizeof (magic));
// read png info
png_read_info (png_ptr, info_ptr);
int bit_depth, color_type;
// get some usefull information from header
bit_depth = png_get_bit_depth (png_ptr, info_ptr);
color_type = png_get_color_type (png_ptr, info_ptr);
// convert index color images to RGB images
if (color_type == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb (png_ptr);
else if (color_type != PNG_COLOR_TYPE_RGB && color_type != PNG_COLOR_TYPE_RGB_ALPHA)
{
fprintf(stderr,"PNG format not supported.\n");
return (SANE_STATUS_INVAL);
}
if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
bps = 4;
else
bps = 3;
if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
png_set_tRNS_to_alpha (png_ptr);
if (bit_depth == 16)
png_set_strip_16 (png_ptr);
else if (bit_depth < 8)
png_set_packing (png_ptr);
// update info structure to apply transformations
png_read_update_info (png_ptr, info_ptr);
// retrieve updated information
png_get_IHDR (png_ptr, info_ptr,
(png_uint_32*)(&width),
(png_uint_32*)(&height),
&bit_depth, &color_type,
NULL, NULL, NULL);
// we can now allocate memory for storing pixel data
texels = (unsigned char *)malloc (sizeof (unsigned char) * width
* height * bps);
png_bytep *row_pointers;
// setup a pointer array. Each one points at the begening of a row.
row_pointers = (png_bytep *)malloc (sizeof (png_bytep) * height);
for (i = 0; i < height; ++i)
{
row_pointers[i] = (png_bytep)(texels +
((height - (i + 1)) * width * bps));
}
// read pixel data using row pointers
png_read_image (png_ptr, row_pointers);
// we don't need row pointers anymore
scanner->img_data = texels;
scanner->img_size = (int)(width * height * bps);
scanner->img_read = 0;
free (row_pointers);
fclose(scanner->tmp);
scanner->tmp = NULL;
return (SANE_STATUS_GOOD);
}
#else
void
get_PNG_dimension(FILE __sane_unused__ *fp, int __sane_unused__ *w,
int __sane_unused__ *h, int __sane_unused__ *bps)
{
}
SANE_Status
get_PNG_data(capabilities_t __sane_unused__ *scanner)
{
}
#endif