kopia lustrzana https://gitlab.com/sane-project/backends
* backend/canon_dr.[ch]: backend v22
- add deinterlacing code for DR-2510C in duplex and colormerge-requests/1/head
rodzic
ce2fdfbfbe
commit
009c5cd33d
|
@ -1,3 +1,7 @@
|
|||
2009-03-25 m. allan noah <kitno455 a t gmail d o t com>
|
||||
* backend/canon_dr.[ch]: backend v22
|
||||
- add deinterlacing code for DR-2510C in duplex and color
|
||||
|
||||
2009-03-25 Pierre Willenbrock <pierre@pirsoft.dnsalias.org>
|
||||
* backend/genesys.c, backend/genesys_gl646.c,
|
||||
backend/genesys_gl841.c, backend/genesys_low.h: Add calibration cache
|
||||
|
|
|
@ -159,6 +159,8 @@
|
|||
v21 2009-03-24, MAN
|
||||
- correct rgb padding macro
|
||||
- skip send_panel and ssm_df commands for DR-20xx scanners
|
||||
v22 2009-03-25, MAN
|
||||
- add deinterlacing code for DR-2510C in duplex and color
|
||||
|
||||
SANE FLOW DIAGRAM
|
||||
|
||||
|
@ -219,7 +221,7 @@
|
|||
#include "canon_dr.h"
|
||||
|
||||
#define DEBUG 1
|
||||
#define BUILD 21
|
||||
#define BUILD 22
|
||||
|
||||
/* values for SANE_DEBUG_CANON_DR env var:
|
||||
- errors 5
|
||||
|
@ -1062,6 +1064,7 @@ init_model (struct scanner *s)
|
|||
s->unknown_byte2 = 0x80;
|
||||
s->has_counter = 1;
|
||||
s->head_interlace = HEAD_INTERLACE_2510;
|
||||
s->color_interlace = COLOR_INTERLACE_RGB;
|
||||
s->fixed_width = 1;
|
||||
}
|
||||
|
||||
|
@ -3578,22 +3581,18 @@ read_from_scanner(struct scanner *s, int side)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(inLen && !extra){
|
||||
copy_buffer (s, in, inLen, side);
|
||||
}
|
||||
}
|
||||
|
||||
/*non-jpeg, scrambled read-heads*/
|
||||
/*FIXME: color and duplex untested */
|
||||
else if(s->head_interlace == HEAD_INTERLACE_2510){
|
||||
if(inLen && !extra){
|
||||
if(s->params.format != SANE_FRAME_JPEG
|
||||
&& s->head_interlace == HEAD_INTERLACE_2510){
|
||||
copy_buffer_2510 (s, in, inLen, side);
|
||||
}
|
||||
}
|
||||
|
||||
/*normal data*/
|
||||
/*jpeg or normal data*/
|
||||
else {
|
||||
if(inLen && !extra){
|
||||
copy_buffer (s, in, inLen, side);
|
||||
}
|
||||
}
|
||||
|
@ -3611,7 +3610,7 @@ read_from_scanner(struct scanner *s, int side)
|
|||
}
|
||||
|
||||
/* cheaper scanners interlace duplex scans on a byte basis
|
||||
* this code splits that data into the front/back buffers */
|
||||
* this code requests double width lines from scanner */
|
||||
static SANE_Status
|
||||
read_from_scanner_duplex(struct scanner *s)
|
||||
{
|
||||
|
@ -3652,7 +3651,8 @@ read_from_scanner_duplex(struct scanner *s)
|
|||
inLen = bytes;
|
||||
in = malloc(inLen);
|
||||
if(!in){
|
||||
DBG(5, "read_from_scanner_duplex: not enough mem for buffer: %d\n",(int)inLen);
|
||||
DBG(5, "read_from_scanner_duplex: not enough mem for buffer: %d\n",
|
||||
(int)inLen);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
|
@ -3681,47 +3681,22 @@ read_from_scanner_duplex(struct scanner *s)
|
|||
ret = SANE_STATUS_GOOD;
|
||||
}
|
||||
else {
|
||||
DBG(5, "read_from_scanner_duplex: error reading data block status = %d\n",ret);
|
||||
DBG(5, "read_from_scanner_duplex: error reading data block status = %d\n",
|
||||
ret);
|
||||
inLen = 0;
|
||||
}
|
||||
|
||||
/* split the data between two buffers
|
||||
* assumes that first byte of buffer is frontside data
|
||||
* and that the buffer starts/ends on a wide line boundary */
|
||||
if(inLen && !extra){
|
||||
size_t i;
|
||||
int j;
|
||||
|
||||
/*frontside, just copy*/
|
||||
for(i=0; i<inLen; i+=2*s->params.bytes_per_line){
|
||||
for(j=0; j<2*s->params.bytes_per_line; j+=2){
|
||||
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = in[i+j];
|
||||
}
|
||||
/*non-jpeg, scrambled read-heads*/
|
||||
if(s->params.format != SANE_FRAME_JPEG
|
||||
&& s->head_interlace == HEAD_INTERLACE_2510){
|
||||
copy_buffer_duplex_2510(s,in,inLen);
|
||||
}
|
||||
|
||||
/*backside color: channels are in RGB order, but each is mirrored*/
|
||||
if(s->mode == MODE_COLOR){
|
||||
for(i=0; i<inLen; i+=2*s->params.bytes_per_line){
|
||||
for(j=s->params.pixels_per_line; j>0; j--){
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = in[i+j*2-1];
|
||||
}
|
||||
for(j=s->params.pixels_per_line; j>0; j--){
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++]
|
||||
= in[i+2*s->params.pixels_per_line+j*2-1];
|
||||
}
|
||||
for(j=s->params.pixels_per_line; j>0; j--){
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++]
|
||||
= in[i+4*s->params.pixels_per_line+j*2-1];
|
||||
}
|
||||
}
|
||||
}
|
||||
/*backside gray: single mirrored channel*/
|
||||
else{
|
||||
for(i=0; i<inLen; i+=2*s->params.bytes_per_line){
|
||||
for(j=2*s->params.bytes_per_line; j>0; j-=2){
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = in[i+j-1];
|
||||
}
|
||||
}
|
||||
/*jpeg or normal data*/
|
||||
else {
|
||||
copy_buffer_duplex(s,in,inLen);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3760,39 +3735,229 @@ copy_buffer_2510(struct scanner *s, unsigned char * buf, int len, int side)
|
|||
SANE_Status ret=SANE_STATUS_GOOD;
|
||||
int i, j;
|
||||
int bwidth = s->params.bytes_per_line;
|
||||
int twidth = bwidth/3;
|
||||
int qwidth = bwidth/4;
|
||||
int t = bwidth/3;
|
||||
int f = bwidth/4;
|
||||
int tw = bwidth/12;
|
||||
|
||||
DBG (10, "copy_buffer_2510: start\n");
|
||||
|
||||
if(s->mode == MODE_COLOR){
|
||||
|
||||
for(i=0; i<len; i+=bwidth){
|
||||
|
||||
/* first head in 'blue' channel, 1/3rd width, mirrored */
|
||||
for(j=0; j<twidth; j++){
|
||||
s->buffers[side][s->bytes_rx[side]++] = buf[i+(twidth-j)*3-1];
|
||||
/* first read head (third byte of every three) */
|
||||
for(j=t-1;j>=0;j-=3){
|
||||
s->buffers[side][s->bytes_rx[side]++] = buf[i+j];
|
||||
s->buffers[side][s->bytes_rx[side]++] = buf[i+t+j];
|
||||
s->buffers[side][s->bytes_rx[side]++] = buf[i+2*t+j];
|
||||
}
|
||||
|
||||
/* second head in 'red' channel, 1/4 width, mirrored, shifted left */
|
||||
for(j=0;j<qwidth;j++){
|
||||
s->buffers[side][s->bytes_rx[side]++] = buf[i+(qwidth-j)*3-3];
|
||||
/* second read head (first byte of every three) */
|
||||
for(j=f-3;j>=0;j-=3){
|
||||
s->buffers[side][s->bytes_rx[side]++] = buf[i+j];
|
||||
s->buffers[side][s->bytes_rx[side]++] = buf[i+t+j];
|
||||
s->buffers[side][s->bytes_rx[side]++] = buf[i+2*t+j];
|
||||
}
|
||||
|
||||
/* third head in 'green' channel, 1/3rd width, mirrored */
|
||||
for(j=0;j<twidth;j++){
|
||||
s->buffers[side][s->bytes_rx[side]++] = buf[i+(twidth-j)*3-2];
|
||||
/* third read head (second byte of every three) */
|
||||
for(j=t-2;j>=0;j-=3){
|
||||
s->buffers[side][s->bytes_rx[side]++] = buf[i+j];
|
||||
s->buffers[side][s->bytes_rx[side]++] = buf[i+t+j];
|
||||
s->buffers[side][s->bytes_rx[side]++] = buf[i+2*t+j];
|
||||
}
|
||||
|
||||
/* pad remainder (1/12th) with black */
|
||||
for(j=0;j<bwidth/12;j++){
|
||||
/* padding */
|
||||
for(j=0;j<tw;j++){
|
||||
s->buffers[side][s->bytes_rx[side]++] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
for(i=0; i<len; i+=bwidth){
|
||||
|
||||
/* first read head (third byte of every three) */
|
||||
for(j=bwidth-1;j>=0;j-=3){
|
||||
s->buffers[side][s->bytes_rx[side]++] = buf[i+j];
|
||||
}
|
||||
/* second read head (first byte of every three) */
|
||||
for(j=bwidth*3/4-3;j>=0;j-=3){
|
||||
s->buffers[side][s->bytes_rx[side]++] = buf[i+j];
|
||||
}
|
||||
/* third read head (second byte of every three) */
|
||||
for(j=bwidth-2;j>=0;j-=3){
|
||||
s->buffers[side][s->bytes_rx[side]++] = buf[i+j];
|
||||
}
|
||||
/* padding */
|
||||
for(j=0;j<tw;j++){
|
||||
s->buffers[side][s->bytes_rx[side]++] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DBG (10, "copy_buffer_2510: finish\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* split the data between two buffers
|
||||
* assumes that first byte of buffer is frontside data
|
||||
* and that the buffer starts/ends on a wide line boundary */
|
||||
static SANE_Status
|
||||
copy_buffer_duplex(struct scanner *s, unsigned char * buf, int len)
|
||||
{
|
||||
SANE_Status ret=SANE_STATUS_GOOD;
|
||||
int i,j;
|
||||
|
||||
DBG (10, "copy_buffer_duplex: start\n");
|
||||
|
||||
/*frontside, just copy*/
|
||||
for(i=0; i<len; i+=2*s->params.bytes_per_line){
|
||||
for(j=0; j<2*s->params.bytes_per_line; j+=2){
|
||||
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+j];
|
||||
}
|
||||
}
|
||||
|
||||
/*backside color: channels are in RGB order, but each is mirrored*/
|
||||
if(s->mode == MODE_COLOR){
|
||||
for(i=0; i<len; i+=2*s->params.bytes_per_line){
|
||||
for(j=s->params.pixels_per_line; j>0; j--){
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+j*2-1];
|
||||
}
|
||||
for(j=s->params.pixels_per_line; j>0; j--){
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++]
|
||||
= buf[i+2*s->params.pixels_per_line+j*2-1];
|
||||
}
|
||||
for(j=s->params.pixels_per_line; j>0; j--){
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++]
|
||||
= buf[i+4*s->params.pixels_per_line+j*2-1];
|
||||
}
|
||||
}
|
||||
}
|
||||
/*backside gray: single mirrored channel*/
|
||||
else{
|
||||
for(i=0; i<len; i+=2*s->params.bytes_per_line){
|
||||
for(j=2*s->params.bytes_per_line; j>0; j-=2){
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+j-1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DBG (10, "copy_buffer_duplex: finish\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* NOTE: this code assumes buffer is scanline aligned */
|
||||
static SANE_Status
|
||||
copy_buffer_duplex_2510(struct scanner *s, unsigned char * buf, int len)
|
||||
{
|
||||
SANE_Status ret=SANE_STATUS_GOOD;
|
||||
int i, j;
|
||||
|
||||
int bwidth = s->params.bytes_per_line;
|
||||
int tq = bwidth*3/4;
|
||||
int t = bwidth/3;
|
||||
int f = bwidth/4;
|
||||
int tf = bwidth/24;
|
||||
|
||||
DBG (10, "copy_buffer_duplex_2510: start\n");
|
||||
|
||||
if(s->mode == MODE_COLOR){
|
||||
|
||||
for(i=0; i<len; i+=bwidth){
|
||||
|
||||
/* first read head */
|
||||
for(j=t-5;j>=0;j-=6){
|
||||
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+j];
|
||||
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+t+j];
|
||||
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+2*t+j];
|
||||
}
|
||||
/* second read head */
|
||||
for(j=f-3;j>=0;j-=6){
|
||||
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+j];
|
||||
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+t+j];
|
||||
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+2*t+j];
|
||||
}
|
||||
/* third read head */
|
||||
for(j=t-6;j>=0;j-=6){
|
||||
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+j];
|
||||
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+t+j];
|
||||
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+2*t+j];
|
||||
}
|
||||
/* padding */
|
||||
for(j=0;j<tf;j++){
|
||||
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = 0;
|
||||
}
|
||||
|
||||
/* first read head */
|
||||
for(j=t-1;j>=0;j-=6){
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+j];
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+t+j];
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+2*t+j];
|
||||
}
|
||||
/* second read head */
|
||||
for(j=f-4;j>=0;j-=6){
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+j];
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+t+j];
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+2*t+j];
|
||||
}
|
||||
/* third read head */
|
||||
for(j=t-2;j>=0;j-=6){
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+j];
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+t+j];
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+2*t+j];
|
||||
}
|
||||
/* padding */
|
||||
for(j=0;j<tf;j++){
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
for(i=0; i<len; i+=bwidth){
|
||||
|
||||
/* first read head */
|
||||
for(j=bwidth-5;j>=0;j-=6){
|
||||
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+j];
|
||||
}
|
||||
/* second read head */
|
||||
for(j=tq-3;j>=0;j-=6){
|
||||
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+j];
|
||||
}
|
||||
/* third read head */
|
||||
for(j=bwidth-6;j>=0;j-=6){
|
||||
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = buf[i+j];
|
||||
}
|
||||
/* padding */
|
||||
for(j=0;j<tf;j++){
|
||||
s->buffers[SIDE_FRONT][s->bytes_rx[SIDE_FRONT]++] = 0;
|
||||
}
|
||||
|
||||
/* first read head */
|
||||
for(j=bwidth-1;j>=0;j-=6){
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+j];
|
||||
}
|
||||
/* second read head */
|
||||
for(j=tq-4;j>=0;j-=6){
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+j];
|
||||
}
|
||||
/* third read head */
|
||||
for(j=bwidth-2;j>=0;j-=6){
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = buf[i+j];
|
||||
}
|
||||
/* padding */
|
||||
for(j=0;j<tf;j++){
|
||||
s->buffers[SIDE_BACK][s->bytes_rx[SIDE_BACK]++] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DBG (10, "copy_buffer_duplex_2510: finish\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static SANE_Status
|
||||
read_from_buffer(struct scanner *s, SANE_Byte * buf,
|
||||
SANE_Int max_len, SANE_Int * len, int side)
|
||||
|
@ -3820,8 +3985,7 @@ read_from_buffer(struct scanner *s, SANE_Byte * buf,
|
|||
}
|
||||
|
||||
/* jpeg data does not use typical interlacing or inverting, just copy */
|
||||
if(s->compress == COMP_JPEG &&
|
||||
(s->mode == MODE_COLOR || s->mode == MODE_GRAYSCALE)){
|
||||
if(s->params.format == SANE_FRAME_JPEG){
|
||||
memcpy(buf,s->buffers[side]+s->bytes_tx[side],bytes);
|
||||
}
|
||||
|
||||
|
|
|
@ -473,6 +473,9 @@ static SANE_Status read_from_scanner_duplex(struct scanner *s);
|
|||
static SANE_Status copy_buffer(struct scanner *s, unsigned char * buf, int len, int side);
|
||||
static SANE_Status copy_buffer_2510(struct scanner *s, unsigned char * buf, int len, int side);
|
||||
|
||||
static SANE_Status copy_buffer_duplex(struct scanner *s, unsigned char * buf, int len);
|
||||
static SANE_Status copy_buffer_duplex_2510(struct scanner *s, unsigned char * buf, int len);
|
||||
|
||||
static SANE_Status read_from_buffer(struct scanner *s, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len, int side);
|
||||
|
||||
static SANE_Status setup_buffers (struct scanner *s);
|
||||
|
|
Ładowanie…
Reference in New Issue