Color scanning for Samsung models, which support JPEG Lossy compression.

Patch is submitted by Laxmeesh Onkar Markod <m.laxmeesh@samsung.com>

Patch to code is applied almost verbatim, except, insignificant
formatting fixes and making new functions static.

Also, new USB ids added and scanner support is changed as reported.
merge-requests/1/head
Alex Belkin 2016-05-07 22:33:03 +03:00
rodzic c8169b1e65
commit 926bfade54
6 zmienionych plików z 279 dodań i 14 usunięć

Wyświetl plik

@ -1104,7 +1104,7 @@ libxerox_mfp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=xerox_mfp
nodist_libsane_xerox_mfp_la_SOURCES = xerox_mfp-s.c nodist_libsane_xerox_mfp_la_SOURCES = xerox_mfp-s.c
libsane_xerox_mfp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=xerox_mfp libsane_xerox_mfp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=xerox_mfp
libsane_xerox_mfp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_xerox_mfp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
libsane_xerox_mfp_la_LIBADD = $(COMMON_LIBS) libxerox_mfp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_tcp.lo $(MATH_LIB) $(SOCKET_LIBS) $(USB_LIBS) $(RESMGR_LIBS) libsane_xerox_mfp_la_LIBADD = $(COMMON_LIBS) libxerox_mfp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo @SANEI_SANEI_JPEG_LO@ $(JPEG_LIBS) ../sanei/sanei_usb.lo ../sanei/sanei_tcp.lo $(MATH_LIB) $(SOCKET_LIBS) $(USB_LIBS) $(RESMGR_LIBS)
EXTRA_DIST += xerox_mfp.conf.in EXTRA_DIST += xerox_mfp.conf.in
libdll_preload_la_SOURCES = dll.c libdll_preload_la_SOURCES = dll.c

Wyświetl plik

@ -1422,9 +1422,10 @@ libsane_v4l_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
libsane_xerox_mfp_la_DEPENDENCIES = $(COMMON_LIBS) libxerox_mfp.la \ libsane_xerox_mfp_la_DEPENDENCIES = $(COMMON_LIBS) libxerox_mfp.la \
../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \ ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo \
../sanei/sanei_config.lo sane_strstatus.lo \ ../sanei/sanei_config.lo sane_strstatus.lo \
../sanei/sanei_usb.lo ../sanei/sanei_tcp.lo \ $(am__DEPENDENCIES_1) ../sanei/sanei_usb.lo \
../sanei/sanei_tcp.lo $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
nodist_libsane_xerox_mfp_la_OBJECTS = \ nodist_libsane_xerox_mfp_la_OBJECTS = \
libsane_xerox_mfp_la-xerox_mfp-s.lo libsane_xerox_mfp_la-xerox_mfp-s.lo
libsane_xerox_mfp_la_OBJECTS = $(nodist_libsane_xerox_mfp_la_OBJECTS) libsane_xerox_mfp_la_OBJECTS = $(nodist_libsane_xerox_mfp_la_OBJECTS)
@ -2694,7 +2695,7 @@ libxerox_mfp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=xerox_mfp
nodist_libsane_xerox_mfp_la_SOURCES = xerox_mfp-s.c nodist_libsane_xerox_mfp_la_SOURCES = xerox_mfp-s.c
libsane_xerox_mfp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=xerox_mfp libsane_xerox_mfp_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=xerox_mfp
libsane_xerox_mfp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS) libsane_xerox_mfp_la_LDFLAGS = $(DIST_SANELIBS_LDFLAGS)
libsane_xerox_mfp_la_LIBADD = $(COMMON_LIBS) libxerox_mfp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo ../sanei/sanei_usb.lo ../sanei/sanei_tcp.lo $(MATH_LIB) $(SOCKET_LIBS) $(USB_LIBS) $(RESMGR_LIBS) libsane_xerox_mfp_la_LIBADD = $(COMMON_LIBS) libxerox_mfp.la ../sanei/sanei_init_debug.lo ../sanei/sanei_constrain_value.lo ../sanei/sanei_config.lo sane_strstatus.lo @SANEI_SANEI_JPEG_LO@ $(JPEG_LIBS) ../sanei/sanei_usb.lo ../sanei/sanei_tcp.lo $(MATH_LIB) $(SOCKET_LIBS) $(USB_LIBS) $(RESMGR_LIBS)
libdll_preload_la_SOURCES = dll.c libdll_preload_la_SOURCES = dll.c
libdll_preload_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dll -DENABLE_PRELOAD libdll_preload_la_CPPFLAGS = $(AM_CPPFLAGS) -DBACKEND_NAME=dll -DENABLE_PRELOAD
libdll_la_SOURCES = dll.c libdll_la_SOURCES = dll.c

Wyświetl plik

@ -30,6 +30,7 @@
#include "../include/sane/sanei_usb.h" #include "../include/sane/sanei_usb.h"
#include "../include/sane/sanei_config.h" #include "../include/sane/sanei_config.h"
#include "../include/sane/sanei_backend.h" #include "../include/sane/sanei_backend.h"
#include <jpeglib.h>
#include "xerox_mfp.h" #include "xerox_mfp.h"
#define BACKEND_BUILD 13 #define BACKEND_BUILD 13
@ -87,6 +88,119 @@ static char *str_cmd(int cmd)
} }
#define MAX_DUMP 70 #define MAX_DUMP 70
const char *encTmpFileName = "/tmp/stmp_enc.tmp";
static int decompress(struct device *dev, const char *infilename)
{
int rc;
int row_stride, width, height, pixel_size;
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
unsigned long bmp_size = 0;
FILE *pInfile = NULL;
JSAMPARRAY buffer;
if ((pInfile = fopen(infilename, "rb")) == NULL) {
fprintf(stderr, "can't open %s\n", infilename);
return -1;
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, pInfile);
rc = jpeg_read_header(&cinfo, TRUE);
if (rc != 1) {
jpeg_destroy_decompress(&cinfo);
fclose(pInfile);
return -1;
}
jpeg_start_decompress(&cinfo);
width = cinfo.output_width;
height = cinfo.output_height;
pixel_size = cinfo.output_components;
bmp_size = width * height * pixel_size;
dev->decDataSize = bmp_size;
row_stride = width * pixel_size;
buffer = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
while (cinfo.output_scanline < cinfo.output_height) {
buffer[0] = dev->decData + \
(cinfo.output_scanline) * row_stride;
jpeg_read_scanlines(&cinfo, buffer, 1);
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(pInfile);
return 0;
}
static int copy_decompress_data(struct device *dev, unsigned char *pDest, int maxlen, int *destLen)
{
int data_size = 0;
size_t result = 0, retVal = 0;
if ( 0 == dev->decDataSize ) {
*destLen = 0;
return retVal;
}
data_size = dev->decDataSize - dev->currentDecDataIndex;
if ( data_size > maxlen ) {
data_size = maxlen;
}
memcpy(pDest, dev->decData+dev->currentDecDataIndex, data_size);
result = data_size;
*destLen = result;
dev->currentDecDataIndex += result;
retVal = result;
if ( dev->decDataSize == dev->currentDecDataIndex ) {
dev->currentDecDataIndex = 0;
dev->decDataSize = 0;
}
return retVal;
}
static int decompress_tempfile(struct device *dev)
{
decompress(dev, encTmpFileName);
remove(encTmpFileName);
return 0;
}
static int dump_to_tmp_file(struct device *dev)
{
unsigned char * pSrc = dev->data;
int srcLen = dev->datalen;
FILE * pInfile;
if ((pInfile = fopen(encTmpFileName, "a")) == NULL) {
fprintf(stderr, "can't open %s\n", encTmpFileName);
return 0;
}
fwrite(pSrc, 1, srcLen, pInfile);
fclose(pInfile);
return srcLen;
}
static int isSupportedDevice(struct device *dev)
{
/* Checking device which supports JPEG Lossy compression for color scanning*/
if ( dev->compressionTypes & (1 << 6) )
return 1;
else
return 0;
}
static void dbg_dump(struct device *dev) static void dbg_dump(struct device *dev)
{ {
int i; int i;
@ -510,9 +624,12 @@ static void set_parameters(struct device *dev)
#endif #endif
dev->para.pixels_per_line = dev->win_width / px_to_len; dev->para.pixels_per_line = dev->win_width / px_to_len;
dev->para.bytes_per_line = dev->para.pixels_per_line; dev->para.bytes_per_line = dev->para.pixels_per_line;
if ( !isSupportedDevice(dev) ) {
#if BETTER_BASEDPI #if BETTER_BASEDPI
px_to_len = 1213.9 / dev->val[OPT_RESOLUTION].w; px_to_len = 1213.9 / dev->val[OPT_RESOLUTION].w;
#endif #endif
}
dev->para.lines = dev->win_len / px_to_len; dev->para.lines = dev->win_len / px_to_len;
if (dev->composition == MODE_LINEART || if (dev->composition == MODE_LINEART ||
dev->composition == MODE_HALFTONE) { dev->composition == MODE_HALFTONE) {
@ -634,6 +751,13 @@ static int dev_set_window (struct device *dev)
cmd[0x11] = (SANE_Byte)floor(dev->win_off_y); cmd[0x11] = (SANE_Byte)floor(dev->win_off_y);
cmd[0x12] = (SANE_Byte)((dev->win_off_y - floor(dev->win_off_y)) * 100); cmd[0x12] = (SANE_Byte)((dev->win_off_y - floor(dev->win_off_y)) * 100);
cmd[0x13] = dev->composition; cmd[0x13] = dev->composition;
/* Set to JPEG Lossy Compression, if mode is color (only for supported model)...
* else go with Uncompressed (For backard compatibility with old models )*/
if (dev->composition == MODE_RGB24) {
if ( isSupportedDevice(dev) ) {
cmd[0x14] = 0x6;
}
}
cmd[0x16] = dev->threshold; cmd[0x16] = dev->threshold;
cmd[0x17] = dev->doc_source; cmd[0x17] = dev->doc_source;
@ -705,6 +829,7 @@ dev_inquiry (struct device *dev)
dev->res[0x3e] << 8 | dev->res[0x3e] << 8 |
dev->res[0x3f]; dev->res[0x3f];
dev->line_order = dev->res[0x31]; dev->line_order = dev->res[0x31];
dev->compressionTypes = dev->res[0x32];
dev->doc_loaded = (dev->res[0x35] == 0x02) && dev->doc_loaded = (dev->res[0x35] == 0x02) &&
(dev->res[0x26] & 0x03); (dev->res[0x26] & 0x03);
@ -803,6 +928,10 @@ dev_free (struct device *dev)
free (UNCONST(dev->sane.type)); free (UNCONST(dev->sane.type));
if (dev->data) if (dev->data)
free(dev->data); free(dev->data);
if (dev->decData) {
free(dev->decData);
dev->decData = NULL;
}
memset (dev, 0, sizeof (*dev)); memset (dev, 0, sizeof (*dev));
free (dev); free (dev);
} }
@ -1140,6 +1269,19 @@ sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * lenp)
/* if there is no data to read or output from buffer */ /* if there is no data to read or output from buffer */
if (!dev->blocklen && dev->datalen <= PADDING_SIZE) { if (!dev->blocklen && dev->datalen <= PADDING_SIZE) {
/* copying uncompressed data */
if ( dev->composition == MODE_RGB24 &&
isSupportedDevice(dev) &&
dev->decDataSize > 0) {
int diff = dev->total_img_size - dev->total_out_size;
int bufLen = (diff < maxlen) ? diff : maxlen;
if ( 0 < diff &&
0 < copy_decompress_data(dev, buf, bufLen, lenp) ) {
dev->total_out_size += *lenp;
return SANE_STATUS_GOOD;
}
}
/* and we don't need to acquire next block */ /* and we don't need to acquire next block */
if (dev->final_block) { if (dev->final_block) {
int slack = dev->total_img_size - dev->total_out_size; int slack = dev->total_img_size - dev->total_out_size;
@ -1155,7 +1297,10 @@ sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * lenp)
/* this will never happen */ /* this will never happen */
DBG(1, "image overflow %d bytes\n", dev->total_img_size - dev->total_out_size); DBG(1, "image overflow %d bytes\n", dev->total_img_size - dev->total_out_size);
} }
if ( isSupportedDevice(dev) &&
dev->composition == MODE_RGB24 ) {
remove(encTmpFileName);
}
/* that's all */ /* that's all */
dev_stop(dev); dev_stop(dev);
return SANE_STATUS_EOF; return SANE_STATUS_EOF;
@ -1206,10 +1351,19 @@ sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * lenp)
if (buf && lenp) { /* read mode */ if (buf && lenp) { /* read mode */
/* copy will do minimal of valid data */ /* copy will do minimal of valid data */
if (dev->para.format == SANE_FRAME_RGB && dev->line_order) if (dev->para.format == SANE_FRAME_RGB && dev->line_order) {
clrlen = copy_mix_bands_trim(dev, buf, maxlen, &olen); if (isSupportedDevice(dev)) {
else clrlen = dump_to_tmp_file(dev);
clrlen = copy_plain_trim(dev, buf, maxlen, &olen); /* decompress after reading entire block data*/
if ( 0 == dev->blocklen ) {
decompress_tempfile(dev);
}
copy_decompress_data(dev, buf, maxlen, &olen);
} else {
clrlen = copy_mix_bands_trim(dev, buf, maxlen, &olen);
}
} else
clrlen = copy_plain_trim(dev, buf, maxlen, &olen);
dev->datalen -= clrlen; dev->datalen -= clrlen;
dev->dataoff = (dev->dataoff + clrlen) & DATAMASK; dev->dataoff = (dev->dataoff + clrlen) & DATAMASK;
@ -1287,6 +1441,9 @@ sane_start (SANE_Handle h)
if (!dev->data && !(dev->data = malloc(DATASIZE))) if (!dev->data && !(dev->data = malloc(DATASIZE)))
return ret_cancel(dev, SANE_STATUS_NO_MEM); return ret_cancel(dev, SANE_STATUS_NO_MEM);
if (!dev->decData && !(dev->decData = malloc(POST_DATASIZE)))
return ret_cancel(dev, SANE_STATUS_NO_MEM);
if (!dev_acquire(dev)) if (!dev_acquire(dev))
return dev->state; return dev->state;
@ -1308,6 +1465,12 @@ sane_start (SANE_Handle h)
dev->total_img_size = dev->para.bytes_per_line * dev->para.lines; dev->total_img_size = dev->para.bytes_per_line * dev->para.lines;
if ( isSupportedDevice(dev) &&
dev->composition == MODE_RGB24 ) {
remove(encTmpFileName);
}
dev->currentDecDataIndex = 0;
return SANE_STATUS_GOOD; return SANE_STATUS_GOOD;
} }

Wyświetl plik

@ -5,6 +5,24 @@
### Samsung Models ### ### Samsung Models ###
###################### ######################
#Samsung X4300 Series
usb 0x04e8 0x3324
#Samsung K4350 Series
usb 0x04e8 0x3325
#Samsung X7600 Series
usb 0x04e8 0x3326
#Samsung K7600 Series
usb 0x04e8 0x3327
#Samsung K703 Series
usb 0x04e8 0x3331
#Samsung X703 Series
usb 0x04e8 0x3332
#Samsung SCX-4x16 Series #Samsung SCX-4x16 Series
usb 0x04e8 0x3409 usb 0x04e8 0x3409
@ -178,6 +196,24 @@ usb 0x04e8 0x3466
#Samsung C460 Series #Samsung C460 Series
usb 0x04e8 0x3468 usb 0x04e8 0x3468
#Samsung M458x Series
usb 0x04e8 0x346f
#Samsung M4370 5370 Series
usb 0x04e8 0x3471
#Samsung X401 Series
usb 0x04e8 0x3477
#Samsung K401 Series
usb 0x04e8 0x3478
#Samsung K3250 Series
usb 0x04e8 0x3481
#Samsung X3220 Series
usb 0x04e8 0x3482
#################### ####################
### Xerox Models ### ### Xerox Models ###
#################### ####################

Wyświetl plik

@ -71,6 +71,10 @@ struct device {
#define DATATAIL(dev) ((dev->dataoff + dev->datalen) & DATAMASK) #define DATATAIL(dev) ((dev->dataoff + dev->datalen) & DATAMASK)
#define DATAROOM(dev) dataroom(dev) #define DATAROOM(dev) dataroom(dev)
#define POST_DATASIZE 0xFFFFFF
SANE_Byte *decData;
int decDataSize;
int currentDecDataIndex;
/* data from CMD_INQUIRY: */ /* data from CMD_INQUIRY: */
int resolutions; /* supported resolution bitmask */ int resolutions; /* supported resolution bitmask */
int compositions; /* supported image compositions bitmask */ int compositions; /* supported image compositions bitmask */
@ -95,6 +99,7 @@ struct device {
int composition; /* MODE_ */ int composition; /* MODE_ */
int doc_source; /* document source */ int doc_source; /* document source */
int threshold; /* brightness */ int threshold; /* brightness */
int compressionTypes;
/* CMD_READ data. It is per block only, image could be in many blocks */ /* CMD_READ data. It is per block only, image could be in many blocks */
int blocklen; /* image data block len (padding incl.) */ int blocklen; /* image data block len (padding incl.) */

Wyświetl plik

@ -53,6 +53,36 @@
:mfg "Samsung" :mfg "Samsung"
:url "http://www.samsung.com" :url "http://www.samsung.com"
:model "X4300 Series"
:interface "USB"
:usbid "0x04e8" "0x3324"
:status :untested
:model "K4350 Series"
:interface "USB"
:usbid "0x04e8" "0x3325"
:status :untested
:model "X7600 Series"
:interface "USB"
:usbid "0x04e8" "0x3326"
:status :untested
:model "K7600 Series"
:interface "USB"
:usbid "0x04e8" "0x3327"
:status :untested
:model "K703 Series"
:interface "USB"
:usbid "0x04e8" "0x3331"
:status :untested
:model "X703 Series"
:interface "USB"
:usbid "0x04e8" "0x3332"
:status :untested
:model "SCX-4x16" :model "SCX-4x16"
:interface "USB" :interface "USB"
:usbid "0x04e8" "0x3409" :usbid "0x04e8" "0x3409"
@ -290,7 +320,7 @@
:model "SCX-3405W" :model "SCX-3405W"
:interface "Ethernet" :interface "Ethernet"
:status :basic :status :good
:model "SCX-3400" :model "SCX-3400"
:interface "USB" :interface "USB"
@ -305,17 +335,17 @@
:model "SCX-4729FD" :model "SCX-4729FD"
:interface "USB" :interface "USB"
:usbid "0x04e8" "0x3453" :usbid "0x04e8" "0x3453"
:status :basic :status :good
:model "CLX-6260" :model "CLX-6260"
:interface "USB" :interface "USB"
:usbid "0x04e8" "0x3455" :usbid "0x04e8" "0x3455"
:status :minimal :status :good
:model "CLX-3300 Series" :model "CLX-3300 Series"
:interface "USB" :interface "USB"
:usbid "0x04e8" "0x3456" :usbid "0x04e8" "0x3456"
:status :basic :status :good
:model "SCX-470x" :model "SCX-470x"
:interface "USB" :interface "USB"
@ -325,7 +355,7 @@
:model "CLX-4190" :model "CLX-4190"
:interface "USB" :interface "USB"
:usbid "0x04e8" "0x345a" :usbid "0x04e8" "0x345a"
:status :minimal :status :good
:model "SCX-4650 4x21S Series" :model "SCX-4650 4x21S Series"
:interface "USB" :interface "USB"
@ -352,3 +382,33 @@
:usbid "0x04e8" "0x3468" :usbid "0x04e8" "0x3468"
:status :untested :status :untested
:model "M458x Series"
:interface "USB"
:usbid "0x04e8" "0x346f"
:status :untested
:model "M4370 5370 Series"
:interface "USB"
:usbid "0x04e8" "0x3471"
:status :untested
:model "X401 Series"
:interface "USB"
:usbid "0x04e8" "0x3477"
:status :untested
:model "K401 Series"
:interface "USB"
:usbid "0x04e8" "0x3478"
:status :untested
:model "K3250 Series"
:interface "USB"
:usbid "0x04e8" "0x3481"
:status :untested
:model "X3220 Series"
:interface "USB"
:usbid "0x04e8" "0x3482"
:status :untested