* backend/canon_dr.[ch]: backend v22

- add deinterlacing code for DR-2510C in duplex and color
merge-requests/1/head
m. allan noah 2009-03-26 03:05:18 +00:00
rodzic ce2fdfbfbe
commit 009c5cd33d
3 zmienionych plików z 437 dodań i 266 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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);