kopia lustrzana https://gitlab.com/sane-project/backends
First implementation of deinterlacer for Epson scanners at high resolutions (thanks to Brad Johnson)
rodzic
21840be6f1
commit
d1e4cbcf4c
|
@ -1,3 +1,8 @@
|
|||
2004-11-10 Oliver Schwartz <Oliver.Schwartz@gmx.de>
|
||||
|
||||
* snapscan-sources.c: First implementation of deinterlacer for epson
|
||||
scanners at high resolutions (thanks to Brad Johnson)
|
||||
|
||||
2004-11-07 Henning Meier-Geinitz <henning@meier-geinitz.de>
|
||||
|
||||
* configure configure.in: Updated version. Enabled compilation
|
||||
|
|
|
@ -664,6 +664,192 @@ static SANE_Status create_Expander (SnapScan_Scanner *pss,
|
|||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
This filter implements a fix for scanners that have some columns
|
||||
of pixels offset. Currently it only shifts every other column
|
||||
starting with the first one down 4 pixels.
|
||||
|
||||
The Deinterlacer detects if data is in SANE RGB frame format (3 bytes/pixel)
|
||||
or in Grayscale (1 byte/pixel).
|
||||
|
||||
The first 4 lines of data in the output are fudged so that even indexed
|
||||
add odd indexed pixels will have the same value. This is necessary because
|
||||
the real pixel values of the columns that are shifted down are not
|
||||
in the data for the first 4 lines. A better way to handle this would be to
|
||||
scan in 4 extra lines of data, but I haven't figured out how to do this
|
||||
yet.
|
||||
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
TX_SOURCE_GUTS;
|
||||
SANE_Byte *ch_buf; /* channel buffer */
|
||||
SANE_Int ch_size; /* channel buffer size */
|
||||
SANE_Int ch_ndata; /* actual #bytes in channel buffer */
|
||||
SANE_Int ch_pos; /* position in buffer */
|
||||
SANE_Int ch_past_init; /* flag indicating if we have enough data to shift pixels down */
|
||||
SANE_Int ch_bytes_per_pixel;
|
||||
} Deinterlacer;
|
||||
|
||||
static SANE_Int Deinterlacer_remaining (Source *pself)
|
||||
{
|
||||
Deinterlacer *ps = (Deinterlacer *) pself;
|
||||
SANE_Int result = TxSource_remaining(pself);
|
||||
result += ps->ch_ndata - ps->ch_pos;
|
||||
return result;
|
||||
}
|
||||
|
||||
static SANE_Status Deinterlacer_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen)
|
||||
{
|
||||
Deinterlacer *ps = (Deinterlacer *) pself;
|
||||
SANE_Status status = SANE_STATUS_GOOD;
|
||||
SANE_Int remaining = *plen;
|
||||
SANE_Int org_len = *plen;
|
||||
char *me = "Deinterlacer_get";
|
||||
|
||||
DBG(DL_DATA_TRACE, "%s: remaining=%d, pself->remaining=%d, ch_ndata=%d, ch_pos=%d\n",
|
||||
me, remaining, pself->remaining(pself), ps->ch_ndata, ps->ch_pos);
|
||||
|
||||
while (remaining > 0
|
||||
&&
|
||||
pself->remaining(pself) > 0 &&
|
||||
!cancelRead)
|
||||
{
|
||||
if (ps->ch_pos % (ps->ch_size/5) == ps->ch_ndata % (ps->ch_size/5) )
|
||||
{
|
||||
/* we need more data; try to get the remainder of the current
|
||||
line, or else the next line */
|
||||
SANE_Int ndata = (ps->ch_size/5) - ps->ch_ndata % (ps->ch_size/5);
|
||||
if (ps->ch_pos >= ps->ch_size)
|
||||
{
|
||||
/* wrap to the beginning of the buffer if we need to */
|
||||
ps->ch_ndata = 0;
|
||||
ps->ch_pos = 0;
|
||||
ndata = ps->ch_size /5;
|
||||
}
|
||||
status = TxSource_get(pself, ps->ch_buf + ps->ch_pos, &ndata);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
break;
|
||||
if (ndata == 0)
|
||||
break;
|
||||
ps->ch_ndata += ndata;
|
||||
}
|
||||
|
||||
if ((ps->ch_pos/ps->ch_bytes_per_pixel) % 2 == 0)
|
||||
{
|
||||
/* the even indexed pixels need to be shifted down */
|
||||
if (ps->ch_past_init){
|
||||
/* We need to use data 4 lines back */
|
||||
/* So we just go one forward and it will wrap around to 4 back. */
|
||||
*pbuf = ps->ch_buf[(ps->ch_pos + (ps->ch_size/5)) % ps->ch_size];
|
||||
}else{
|
||||
/* Use data from the next pixel for even indexed pixels
|
||||
if we are on the first few lines.
|
||||
TODO: also we will overread the buffer if the buffer read ended
|
||||
on the first pixel. */
|
||||
if (ps->ch_pos % (ps->ch_size/5) == 0 )
|
||||
*pbuf = ps->ch_buf[ps->ch_pos+ps->ch_bytes_per_pixel];
|
||||
else
|
||||
*pbuf = ps->ch_buf[ps->ch_pos-ps->ch_bytes_per_pixel];
|
||||
}
|
||||
}else{
|
||||
/* odd indexed pixels are okay */
|
||||
*pbuf = ps->ch_buf[ps->ch_pos];
|
||||
}
|
||||
/* set the flag so we know we have enough data to start shifting columns */
|
||||
if (ps->ch_pos >= ps->ch_size /5 *4)
|
||||
ps->ch_past_init = 1;
|
||||
|
||||
pbuf++;
|
||||
remaining--;
|
||||
ps->ch_pos++;
|
||||
}
|
||||
|
||||
*plen -= remaining;
|
||||
|
||||
DBG(DL_DATA_TRACE,
|
||||
"%s: Request=%d, remaining=%d, read=%d, TXSource_rem=%d, bytes_rem=%lu\n",
|
||||
me,
|
||||
org_len,
|
||||
pself->remaining(pself),
|
||||
*plen,
|
||||
TxSource_remaining(pself),
|
||||
(u_long) ps->pss->bytes_remaining);
|
||||
return status;
|
||||
}
|
||||
|
||||
static SANE_Status Deinterlacer_done (Source *pself)
|
||||
{
|
||||
Deinterlacer *ps = (Deinterlacer *) pself;
|
||||
SANE_Status status = TxSource_done(pself);
|
||||
free(ps->ch_buf);
|
||||
ps->ch_buf = NULL;
|
||||
ps->ch_size = 0;
|
||||
ps->ch_pos = 0;
|
||||
return status;
|
||||
}
|
||||
|
||||
static SANE_Status Deinterlacer_init (Deinterlacer *pself,
|
||||
SnapScan_Scanner *pss,
|
||||
Source *psub)
|
||||
{
|
||||
SANE_Status status = TxSource_init((TxSource *) pself,
|
||||
pss,
|
||||
Deinterlacer_remaining,
|
||||
TxSource_bytesPerLine,
|
||||
TxSource_pixelsPerLine,
|
||||
Deinterlacer_get,
|
||||
Deinterlacer_done,
|
||||
psub);
|
||||
if (status == SANE_STATUS_GOOD)
|
||||
{
|
||||
/* We need at least 5 lines of buffer in order to shift up 4 pixels. */
|
||||
pself->ch_size = TxSource_bytesPerLine((Source *) pself) *5;
|
||||
pself->ch_buf = (SANE_Byte *) malloc(pself->ch_size);
|
||||
if (pself->ch_buf == NULL)
|
||||
{
|
||||
DBG (DL_MAJOR_ERROR,
|
||||
"%s: couldn't allocate channel buffer.\n",
|
||||
__FUNCTION__);
|
||||
status = SANE_STATUS_NO_MEM;
|
||||
}
|
||||
else
|
||||
{
|
||||
pself->ch_ndata = 0;
|
||||
pself->ch_pos = 0;
|
||||
pself->ch_past_init = 0;
|
||||
if (actual_mode(pss) == MD_GREYSCALE)
|
||||
pself->ch_bytes_per_pixel = 1;
|
||||
else
|
||||
pself->ch_bytes_per_pixel = 3;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static SANE_Status create_Deinterlacer (SnapScan_Scanner *pss,
|
||||
Source *psub,
|
||||
Source **pps)
|
||||
{
|
||||
SANE_Status status = SANE_STATUS_GOOD;
|
||||
*pps = (Source *) malloc(sizeof(Deinterlacer));
|
||||
if (*pps == NULL)
|
||||
{
|
||||
DBG (DL_MAJOR_ERROR,
|
||||
"%s: failed to allocate Deinterlacer.\n",
|
||||
__FUNCTION__);
|
||||
status = SANE_STATUS_NO_MEM;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = Deinterlacer_init ((Deinterlacer *) *pps, pss, psub);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------- */
|
||||
|
||||
/* the RGB router assumes 8-bit RGB data arranged in contiguous
|
||||
channels, possibly with R-G and R-B offsets, and rearranges the
|
||||
data into SANE RGB frame format */
|
||||
|
@ -935,14 +1121,29 @@ static SANE_Status create_source_chain (SnapScan_Scanner *pss,
|
|||
{
|
||||
case MD_COLOUR:
|
||||
status = create_RGBRouter (pss, *pps, pps);
|
||||
/* We only have the interlace probelms on
|
||||
some scanners like the Epson Perfection 2480/2580
|
||||
at 2400 dpi. */
|
||||
if (status == SANE_STATUS_GOOD &&
|
||||
pss->pdev->model == PERFECTION2480 &&
|
||||
pss->res == 2400)
|
||||
status = create_Deinterlacer (pss, *pps, pps);
|
||||
break;
|
||||
case MD_BILEVELCOLOUR:
|
||||
status = create_Expander (pss, *pps, pps);
|
||||
if (status == SANE_STATUS_GOOD)
|
||||
status = create_RGBRouter (pss, *pps, pps);
|
||||
if (status == SANE_STATUS_GOOD &&
|
||||
pss->pdev->model == PERFECTION2480 &&
|
||||
pss->res == 2400)
|
||||
status = create_Deinterlacer (pss, *pps, pps);
|
||||
break;
|
||||
case MD_GREYSCALE:
|
||||
if (pss->pdev->model == PERFECTION2480 &&
|
||||
pss->res == 2400)
|
||||
status = create_Deinterlacer (pss, *pps, pps);
|
||||
break;
|
||||
|
||||
case MD_LINEART:
|
||||
/* The SnapScan creates a negative image by
|
||||
default... so for the user interface to make sense,
|
||||
|
@ -962,6 +1163,9 @@ static SANE_Status create_source_chain (SnapScan_Scanner *pss,
|
|||
|
||||
/*
|
||||
* $Log$
|
||||
* Revision 1.11 2004/11/09 23:17:38 oliver-guest
|
||||
* First implementation of deinterlacer for Epson scanners at high resolutions (thanks to Brad Johnson)
|
||||
*
|
||||
* Revision 1.10 2004/10/03 17:34:36 hmg-guest
|
||||
* 64 bit platform fixes (bug #300799).
|
||||
*
|
||||
|
|
Ładowanie…
Reference in New Issue