1 bit B/W lineart for pixma_mp150 and pixma_810 subdrivers

merge-requests/1/head
Rolf Bensch 2012-02-03 22:05:32 +01:00
rodzic bd379a59aa
commit 974ee17cf4
9 zmienionych plików z 403 dodań i 100 usunięć

Wyświetl plik

@ -1,3 +1,8 @@
2012-02-03 Rolf Bensch <rolf at bensch hyphen online dot de>
* backend/pixma.[ch], backend/pixma_common.[ch],
backend/pixma_sane_options.[ch], backend/pixma_mp{150,810}.c:
1 bit B/W lineart for pixma_mp150 and pixma_810 subdrivers.
2012-02-03 Rolf Bensch <rolf at bensch hyphen online dot de>
* backend/pixma.h: set PIXMA_VERSION_{MAJOR,MINOR,BUILD} to 0.16.3.

Wyświetl plik

@ -84,8 +84,10 @@
#define OVAL(opt) OPT_IN_CTX[opt].val
#define AUTO_GAMMA 2.2
#include "pixma_sane_options.h" /* generated by gen_options.py */
/* pixma_sane_options.h generated by
* scripts/pixma_gen_options.py h < pixma.c > pixma_sane_options.h
* *and* formatted */
#include "pixma_sane_options.h"
typedef struct pixma_sane_t
{
@ -103,6 +105,7 @@ typedef struct pixma_sane_t
SANE_Range xrange, yrange;
SANE_Word dpi_list[9]; /* up to 9600 dpi */
SANE_String_Const mode_list[4];
pixma_scan_mode_t mode_map[4];
uint8_t gamma_table[4096];
SANE_String_Const source_list[4];
pixma_paper_source_t source_map[4];
@ -324,6 +327,43 @@ clamp_value (pixma_sane_t * ss, SANE_Int n, void *v, SANE_Int * info)
}
}
/* create dynamic mode_list
* ss: scanner device
* tpu = 0: flatbed or ADF mode
* 1 bit lineart, 8 bit grayscale and 24 bit color scans
* tpu = 1: TPU mode
* 16 bit grayscale and 48 bit color scans */
static void
create_mode_list (pixma_sane_t * ss, SANE_Bool tpu)
{
const pixma_config_t *cfg;
int i;
cfg = pixma_get_config (ss->s);
/* setup available mode. */
i = 0;
ss->mode_list[i] = SANE_VALUE_SCAN_MODE_COLOR;
ss->mode_map[i] = PIXMA_SCAN_MODE_COLOR;
i++;
if (cfg->cap & PIXMA_CAP_GRAY)
{
ss->mode_list[i] = SANE_VALUE_SCAN_MODE_GRAY;
ss->mode_map[i] = PIXMA_SCAN_MODE_GRAY;
i++;
}
if (!tpu && cfg->cap & PIXMA_CAP_LINEART)
{
ss->mode_list[i] = SANE_VALUE_SCAN_MODE_LINEART;
ss->mode_map[i] = PIXMA_SCAN_MODE_LINEART;
i++;
}
/* terminate mode_list and mode_map */
ss->mode_list[i] = 0;
ss->mode_map[i] = 0;
}
/* create ss->dpi_list
* ss: scanner device
* ext = 0: min = 75 dpi; max = cfg->xdpi
@ -533,6 +573,8 @@ control_option (pixma_sane_t * ss, SANE_Int n,
cfg = pixma_get_config (ss->s);
/* PDBG (pixma_dbg (4, "*control_option***** n = %u, a = %u\n", n, a)); */
result = SANE_STATUS_UNSUPPORTED;
switch (n)
{
@ -598,22 +640,46 @@ control_option (pixma_sane_t * ss, SANE_Int n,
*info |= SANE_INFO_RELOAD_OPTIONS;
}
break;
case opt_mode:
if (a == SANE_ACTION_SET_VALUE || a == SANE_ACTION_SET_AUTO)
{
if (ss->mode_map[OVAL (opt_mode).w] == PIXMA_SCAN_MODE_LINEART)
{
enable_option (ss, opt_threshold, SANE_TRUE);
enable_option (ss, opt_custom_gamma, SANE_FALSE);
}
else
{
enable_option (ss, opt_custom_gamma, SANE_TRUE);
enable_option (ss, opt_threshold, SANE_FALSE);
}
*info |= SANE_INFO_RELOAD_OPTIONS;
}
break;
case opt_source:
if (cfg->cap & (PIXMA_CAP_ADF|PIXMA_CAP_ADFDUP|PIXMA_CAP_TPU)
&& (a == SANE_ACTION_SET_VALUE || a == SANE_ACTION_SET_AUTO))
{ /* new source selected: flatbed, ADF, TPU, ... */
/* to avoid fatal errors, select 600 dpi for dpi_list */
/* to avoid fatal errors, select 600 dpi
* and first entry of dynamic mode_list
* available identifiers are unknown here */
OVAL (opt_resolution).w = 600;
if (ss->source_map[OVAL (opt_source).w] == PIXMA_SOURCE_TPU
|| ss->source_map[OVAL (opt_source).w] == PIXMA_SOURCE_ADF
|| ss->source_map[OVAL (opt_source).w] == PIXMA_SOURCE_ADFDUP)
{
/* create dpi_list for ADF/TPU mode */
OVAL (opt_mode).w = 0;
/* recreate dynamic lists */
if (ss->source_map[OVAL (opt_source).w] == PIXMA_SOURCE_TPU)
{ /* TPU mode */
create_mode_list (ss, SANE_TRUE);
create_dpi_list (ss, SANE_TRUE);
}
else if (ss->source_map[OVAL (opt_source).w] == PIXMA_SOURCE_ADF
|| ss->source_map[OVAL (opt_source).w] == PIXMA_SOURCE_ADFDUP)
{ /* ADF mode */
create_mode_list (ss, SANE_FALSE);
create_dpi_list (ss, SANE_TRUE);
}
else
{
/* create dpi_list for flatbed mode */
{ /* flatbed mode */
create_mode_list (ss, SANE_FALSE);
create_dpi_list (ss, SANE_FALSE);
}
*info |= SANE_INFO_RELOAD_OPTIONS;
@ -680,7 +746,9 @@ calc_scan_param (pixma_sane_t * ss, pixma_scan_param_t * sp)
sp->gamma_table = (OVAL (opt_custom_gamma).b) ? ss->gamma_table : NULL;
sp->source = ss->source_map[OVAL (opt_source).w];
sp->mode = ss->mode_map[OVAL (opt_mode).w];
sp->adf_pageid = ss->page_count;
sp->threshold = OVAL (opt_threshold).w;
error = pixma_check_scan_param (ss->s, sp);
if (error < 0)
@ -715,16 +783,7 @@ init_option_descriptors (pixma_sane_t * ss)
* because the whole pixma_sane_t was cleared during allocation. */
/* setup available mode. */
ss->mode_list[0] = SANE_VALUE_SCAN_MODE_COLOR;
if (cfg->cap & PIXMA_CAP_GRAY)
{
ss->mode_list[1] = SANE_VALUE_SCAN_MODE_GRAY;
}
if (cfg->cap & PIXMA_CAP_LINEART)
{
ss->mode_list[2] = SANE_VALUE_SCAN_MODE_LINEART;
}
create_mode_list (ss, SANE_FALSE);
/* setup paper source */
i = 0;
@ -1393,7 +1452,9 @@ sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len)
return ss->last_read_status;
status = SANE_STATUS_GOOD;
if ((ss->sp.line_size - ss->output_line_size) == 0)
/* CCD scanners use software lineart
* the scanner must scan 24 bit color for one bit lineart */
if ((ss->sp.line_size - ((ss->sp.software_lineart == 1) ? (ss->output_line_size * 8) : ss->output_line_size)) == 0)
{
status = read_image (ss, buf, maxlen, &sum);
}
@ -1401,6 +1462,7 @@ sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len)
{
/* FIXME: Because there is no frontend that can cope with padding at
the end of line, we've to remove it here in the backend! */
PDBG (pixma_dbg (1, "*sane_read***** Warning: padding may cause incomplete scan results\n"));
sum = 0;
while (sum < maxlen)
{
@ -1513,8 +1575,8 @@ type int resolution
info reload_params
type string mode[10]
default Color
constraint @string_list = ss->mode_list
default @s = SANE_I18N(ss->mode_list[0])
title @SANE_TITLE_SCAN_MODE
desc @SANE_DESC_SCAN_MODE
cap soft_select soft_detect automatic
@ -1607,7 +1669,22 @@ type int button-2
title Button 2
cap soft_select soft_detect advanced
rem -------------------------------------------
type group
title Extras
type int threshold
unit PERCENT
default 50
title @SANE_TITLE_THRESHOLD
desc @SANE_DESC_THRESHOLD
cap soft_select soft_detect automatic inactive
rem -------------------------------------------
END SANE_Option_Descriptor
*/
#include "pixma_sane_options.c" /* generated by gen_options.py */
/* pixma_sane_options.c generated by
* scripts/pixma_gen_options.py < pixma.c > pixma_sane_options.c
* *and* formatted */
#include "pixma_sane_options.c"

Wyświetl plik

@ -198,6 +198,16 @@ typedef enum pixma_paper_source_t
PIXMA_SOURCE_ADFDUP /* duplex */
} pixma_paper_source_t;
/** Scan modes */
typedef enum pixma_scan_mode_t
{
/* standard scan modes */
PIXMA_SCAN_MODE_COLOR,
PIXMA_SCAN_MODE_GRAY,
/* 1 bit lineart scan mode */
PIXMA_SCAN_MODE_LINEART
} pixma_scan_mode_t;
typedef enum pixma_hardware_status_t
{
PIXMA_HARDWARE_OK,
@ -251,10 +261,15 @@ struct pixma_scan_param_t
* This field will be set by pixma_check_scan_param(). */
uint64_t image_size;
/** Channels per pixel. 1 = grayscale, 3 = color */
/** Channels per pixel. 1 = grayscale and lineart, 3 = color */
unsigned channels;
/** Bits per channels. 0 = default. Currently not used. */
/** Bits per channels.
* 1 = 1 bit B/W lineart (flatbed)
* 8 = 8 bit grayscale,
* 24 bit color (both flatbed)
* 16 = 16 bit grayscale (TPU, flatbed not implemeted),
* 48 bit color (TPU, flatbed not implemented) */
unsigned depth;
/*@{ */
@ -277,6 +292,15 @@ struct pixma_scan_param_t
* Currently only used in pixma_mp810.c sub-driver */
unsigned tpu_offset_added;
/** Flag indicating whether a software-lineart scan is in progress
* 0 = other scan
* 1 = software-lineart scan */
unsigned software_lineart;
/** Threshold for software-lineart scans
* Value in percent (0% ... 100%) */
unsigned threshold;
/** Gamma table. 4096 entries, 12 bit => 8 bit. If \c NULL, default gamma
* specified by subdriver will be used. */
const uint8_t *gamma_table;
@ -284,6 +308,9 @@ struct pixma_scan_param_t
/** \see #pixma_paper_source_t */
pixma_paper_source_t source;
/** \see #pixma_scan_mode_t */
pixma_scan_mode_t mode;
/** The current page # in the same ADF scan session, 0 in non ADF */
unsigned adf_pageid;
};

Wyświetl plik

@ -304,6 +304,115 @@ pixma_get_time (time_t * sec, uint32_t * usec)
*usec = tv.tv_usec;
}
/* convert 24/48 bit RGB to 8/16 bit grayscale
*
* Formular: g = (R + G + B) / 3
*
* sptr: source color scale buffer
* gptr: destination gray scale buffer
* c == 3: 24 bit RGB -> 8 bit gray
* c == 6: 48 bit RGB -> 16 bit gray
*/
uint8_t *
pixma_rgb_to_gray (uint8_t * gptr, uint8_t * sptr, unsigned w, unsigned c)
{
unsigned i, j, g;
/* PDBG (pixma_dbg (4, "*pixma_rgb_to_gray*****\n")); */
for (i = 0; i < w; i++)
{
for (j = 0, g = 0; j < 3; j++)
{
g += *sptr++;
if (c == 6) g += (*sptr++ << 8); /* 48 bit RGB: high byte */
}
g /= 3; /* 8 or 16 bit gray */
*gptr++ = g;
if (c == 6) *gptr++ = (g >> 8); /* 16 bit gray: high byte */
}
return gptr;
}
/**
* This code was taken from the genesys backend
* This sub-driver has no threshold_curve
* uses threshold to control software binarization
* @param sp device set up for the scan
* @param dst pointer where to store result
* @param src pointer to raw data
* @param width width of the processed line
* @param c 3 for 3-channel single-byte data, 6 for double-byte data
* */
uint8_t *
pixma_binarize_line(pixma_scan_param_t * sp, uint8_t * dst, uint8_t * src, unsigned width, unsigned c)
{
unsigned j, x, offset;
unsigned char mask;
uint8_t min, max;
unsigned threshold = 0xFF * sp->threshold / 100; /* sp->threshold is 0% ... 100% */
/* PDBG (pixma_dbg (4, "*pixma_binarize_line***** src = %u, dst = %u, width = %u, c = %u, threshold = %u *****\n",
src, dst, width, c, sp->threshold)); */
/* 16 bit grayscale not supported */
if (c == 6)
{
PDBG (pixma_dbg (1, "*pixma_binarize_line***** Error: 16 bit grayscale not supported\n"));
return dst;
}
/* first, color convert to grayscale */
pixma_rgb_to_gray(dst, src, width, c);
/* second, normalize line */
min = 255;
max = 0;
for (x = 0; x < width; x++)
{
if (src[x] > max)
{
max = src[x];
}
if (src[x] < min)
{
min = src[x];
}
}
/* safeguard against dark or white areas */
if(min>80)
min=0;
if(max<80)
max=255;
for (x = 0; x < width; x++)
{
src[x] = ((src[x] - min) * 255) / (max - min);
}
/* third, walk the input buffer, output bits */
for (j = 0; j < width; j++)
{
/* output image location */
offset = j % 8;
mask = 0x80 >> offset;
/* lookup threshold */
if (src[j] > threshold)
*dst &= ~mask; /* white */
else
*dst |= mask; /* black */
if (offset == 7)
dst++;
}
/* PDBG (pixma_dbg (4, " *pixma_binarize_line***** ready: src = %u, dst = %u *****\n", src, dst)); */
return dst;
}
int
pixma_map_status_errno (unsigned status)
{
@ -574,6 +683,7 @@ pixma_scan (pixma_t * s, pixma_scan_param_t * sp)
pixma_dbg (3, " dpi=%ux%u offset=(%u,%u) dimension=%ux%u\n",
sp->xdpi, sp->ydpi, sp->x, sp->y, sp->w, sp->h);
pixma_dbg (3, " gamma_table=%p source=%d\n", sp->gamma_table, sp->source);
pixma_dbg (3, " threshold=%d\n", sp->threshold);
#endif
s->param = sp;
@ -843,6 +953,10 @@ pixma_check_scan_param (pixma_t * s, pixma_scan_param_t * sp)
if (sp->line_size == 0)
sp->line_size = sp->depth / 8 * sp->channels * sp->w;
sp->image_size = sp->line_size * sp->h;
/* image_size for software lineart is counted in bits */
if (sp->software_lineart == 1)
sp->image_size /= 8;
return 0;
}

Wyświetl plik

@ -188,6 +188,8 @@ uint8_t pixma_sum_bytes (const void *data, unsigned len);
int pixma_check_dpi (unsigned dpi, unsigned max);
void pixma_sleep (unsigned long usec);
void pixma_get_time (time_t * sec, uint32_t * usec);
uint8_t * pixma_rgb_to_gray (uint8_t * gptr, uint8_t * sptr, unsigned w, unsigned c);
uint8_t * pixma_binarize_line(pixma_scan_param_t *, uint8_t * dst, uint8_t * src, unsigned width, unsigned c);
/**@}*/
/** \name Command related functions */

Wyświetl plik

@ -567,15 +567,22 @@ has_ccd_sensor (pixma_t * s)
static int
is_ccd_grayscale (pixma_t * s)
{
return (has_ccd_sensor (s) && (s->param->channels == 1));
return (has_ccd_sensor (s) && (s->param->channels == 1) && !s->param->software_lineart);
}
/* CCD sensors don't have a Grayscale mode, but use color mode instead */
static int
is_ccd_lineart (pixma_t * s)
{
return (has_ccd_sensor (s) && s->param->software_lineart);
}
/* CCD sensors don't have neither a Grayscale mode nor a Lineart mode,
* but use color mode instead */
static unsigned
get_cis_ccd_line_size (pixma_t * s)
{
return (s->param->wx ? s->param->line_size / s->param->w * s->param->wx
: s->param->line_size) * ((is_ccd_grayscale (s)) ? 3 : 1);
return ((s->param->wx ? s->param->line_size / s->param->w * s->param->wx
: s->param->line_size) * ((is_ccd_grayscale (s) || is_ccd_lineart (s)) ? 3 : 1));
}
static unsigned
@ -654,6 +661,12 @@ send_scan_param (pixma_t * s)
unsigned h = MIN (s->param->h + calc_shifting (s),
s->cfg->height * s->param->ydpi / 75);
/* TPU scan does not support lineart */
if (is_scanning_from_tpu (s) && is_ccd_lineart (s))
{
return PIXMA_ENOTSUP;
}
if (mp->generation <= 2)
{
data = pixma_newcmd (&mp->cb, cmd_scan_param, 0x30, 0);
@ -665,8 +678,8 @@ send_scan_param (pixma_t * s)
pixma_set_be32 (s->param->y, data + 0x0c);
pixma_set_be32 (raw_width, data + 0x10);
pixma_set_be32 (h, data + 0x14);
data[0x18] = ((s->param->channels != 1) || is_ccd_grayscale (s)) ? 0x08 : 0x04;
data[0x19] = s->param->depth * ((is_ccd_grayscale (s)) ? 3 : s->param->channels); /* bits per pixel */
data[0x18] = ((s->param->channels != 1) || is_ccd_grayscale (s) || is_ccd_lineart (s)) ? 0x08 : 0x04;
data[0x19] = s->param->depth * ((is_ccd_grayscale (s) || is_ccd_lineart (s)) ? 3 : s->param->channels); /* bits per pixel */
data[0x1a] = (is_scanning_from_tpu (s) ? 1 : 0);
data[0x20] = 0xff;
data[0x23] = 0x81;
@ -699,13 +712,14 @@ send_scan_param (pixma_t * s)
pixma_set_be32 (s->param->y, data + 0x10);
pixma_set_be32 (raw_width, data + 0x14);
pixma_set_be32 (h, data + 0x18);
data[0x1c] = ((s->param->channels != 1) || is_ccd_grayscale (s)) ? 0x08 : 0x04;
data[0x1c] = ((s->param->channels != 1) || is_ccd_grayscale (s) || is_ccd_lineart (s)) ? 0x08 : 0x04;
#ifdef DEBUG_TPU_48
data[0x1d] = 24;
#else
data[0x1d] = (is_scanning_from_tpu (s)) ? 48 :
s->param->depth * ((is_ccd_grayscale (s)) ? 3 : s->param->channels); /* bits per pixel */
data[0x1d] = (is_scanning_from_tpu (s)) ? 48
: (((s->param->depth == 1) ? 8 : s->param->depth)
* ((is_ccd_grayscale (s) || is_ccd_lineart (s)) ? 3 : s->param->channels)); /* bits per pixel */
#endif
data[0x1f] = 0x01;
@ -952,26 +966,6 @@ shift_colors (uint8_t * dptr, uint8_t * sptr,
return dptr;
}
static uint8_t *
rgb_to_gray (uint8_t * gptr, uint8_t * sptr, unsigned w, unsigned c)
{
unsigned i, j, g;
for (i = 0; i < w; i++)
{
for (j = 0, g = 0; j < 3; j++)
{
g += *sptr++;
if (c == 6) g += (*sptr++ << 8);
}
g /= 3;
*gptr++ = g;
if (c == 6) *gptr++ = (g >> 8);
}
return gptr;
}
static void
reorder_pixels (uint8_t * linebuf, uint8_t * sptr, unsigned c, unsigned n,
unsigned m, unsigned w, unsigned line_size)
@ -1018,7 +1012,8 @@ post_process_image_data (pixma_t * s, pixma_imagebuf_t * ib)
unsigned c, lines, i, line_size, n, m, cw, cx;
uint8_t *sptr, *dptr, *gptr, *cptr;
c = ((is_ccd_grayscale (s)) ? 3 : s->param->channels) * s->param->depth / 8;
c = ((is_ccd_grayscale (s) || is_ccd_lineart (s)) ? 3 : s->param->channels)
* ((s->param->depth == 1) ? 8 : s->param->depth) / 8;
cw = c * s->param->w;
cx = c * s->param->xs;
@ -1059,9 +1054,12 @@ post_process_image_data (pixma_t * s, pixma_imagebuf_t * ib)
/* Crop line to selected borders */
memmove(cptr, sptr + cx, cw);
/* Color to Lineart convert for CCD sensor */
if (is_ccd_lineart (s))
cptr = gptr = pixma_binarize_line (s->param, gptr, cptr, s->param->w, c);
/* Color to Grayscale convert for CCD sensor */
if (is_ccd_grayscale (s))
cptr = gptr = rgb_to_gray (gptr, cptr, s->param->w, c);
else if (is_ccd_grayscale (s))
cptr = gptr = pixma_rgb_to_gray (gptr, cptr, s->param->w, c);
else
cptr += cw;
}
@ -1140,14 +1138,39 @@ static int
mp150_check_param (pixma_t * s, pixma_scan_param_t * sp)
{
mp150_t *mp = (mp150_t *) s->subdriver;
unsigned w_max;
sp->depth = 8; /* MP150 only supports 8 bit per channel. */
/* MP150 only supports 8 bit per channel in color and grayscale mode */
if (sp->depth != 1)
{
sp->software_lineart = 0;
sp->depth = 8;
#ifdef TPU_48
#ifndef DEBUG_TPU_48
if (sp->source == PIXMA_SOURCE_TPU)
if (sp->source == PIXMA_SOURCE_TPU)
#endif
sp->depth = 16; /* TPU in 16 bits mode */
sp->depth = 16; /* TPU in 16 bits mode */
#endif
}
else
{
/* software lineart */
sp->software_lineart = 1;
sp->depth = 1;
sp->channels = 1;
}
/* for software lineart w must be a multiple of 8 */
if (sp->software_lineart == 1 && sp->w % 8)
{
sp->w += 8 - (sp->w % 8);
/* do not exceed the scanner capability */
w_max = s->cfg->width * s->cfg->xdpi / 75;
w_max -= w_max % 8;
if (sp->w > w_max)
sp->w = w_max;
}
if (mp->generation >= 2)
{
@ -1159,7 +1182,7 @@ mp150_check_param (pixma_t * s, pixma_scan_param_t * sp)
sp->xs = 0;
/*PDBG (pixma_dbg (4, "*mp150_check_param***** Selected origin, origin shift: %i, %i *****\n", sp->x, sp->xs));*/
sp->wx = calc_raw_width (mp, sp);
sp->line_size = sp->w * sp->channels * (sp->depth / 8); /* bytes per line per color after cropping */
sp->line_size = sp->w * sp->channels * (((sp->depth == 1) ? 8 : sp->depth) / 8); /* bytes per line per color after cropping */
/*PDBG (pixma_dbg (4, "*mp150_check_param***** Final scan width and line-size: %i, %i *****\n", sp->wx, sp->line_size));*/
/* Some exceptions here for particular devices */
@ -1504,6 +1527,7 @@ static const pixma_scan_ops_t pixma_mp150_ops = {
ext_min_dpi, ext_max_dpi, /* ext_min_dpi, ext_max_dpi */ \
w, h, /* width, height */ \
PIXMA_CAP_EASY_RGB|PIXMA_CAP_GRAY| \
PIXMA_CAP_LINEART| \
PIXMA_CAP_GAMMA_TABLE|PIXMA_CAP_EVENTS|cap \
}

Wyświetl plik

@ -489,7 +489,7 @@ static unsigned
calc_raw_width (const mp810_t * mp, const pixma_scan_param_t * param)
{
unsigned raw_width;
/* NOTE: Actually, we can send arbitary width to MP150. Lines returned
/* NOTE: Actually, we can send arbitary width to MP810. Lines returned
are always padded to multiple of 4 or 12 pixels. Is this valid for
other models, too? */
if (mp->generation >= 2)
@ -517,15 +517,22 @@ has_ccd_sensor (pixma_t * s)
static int
is_ccd_grayscale (pixma_t * s)
{
return (has_ccd_sensor (s) && (s->param->channels == 1));
return (has_ccd_sensor (s) && (s->param->channels == 1) && !s->param->software_lineart);
}
/* CCD sensors don't have a Grayscale mode, but use color mode instead */
static int
is_ccd_lineart (pixma_t * s)
{
return (has_ccd_sensor (s) && s->param->software_lineart);
}
/* CCD sensors don't have neither a Grayscale mode nor a Lineart mode,
* but use color mode instead */
static unsigned
get_cis_ccd_line_size (pixma_t * s)
{
return (s->param->wx ? s->param->line_size / s->param->w * s->param->wx
: s->param->line_size) * ((is_ccd_grayscale (s)) ? 3 : 1);
return ((s->param->wx ? s->param->line_size / s->param->w * s->param->wx
: s->param->line_size) * ((is_ccd_grayscale (s) || is_ccd_lineart (s)) ? 3 : 1));
}
static unsigned
@ -679,6 +686,12 @@ send_scan_param (pixma_t * s)
unsigned raw_width = calc_raw_width (mp, s->param);
unsigned h, h1, h2, shifting;
/* TPU scan does not support lineart */
if (is_scanning_from_tpu (s) && is_ccd_lineart (s))
{
return PIXMA_ENOTSUP;
}
shifting = calc_shifting (s);
h1 = s->param->h + shifting; /* add lines for color shifting */
/* PDBG (pixma_dbg (4, "* send_scan_param: height calc (choose lesser) 1 %u \n", h1 )); */
@ -710,8 +723,8 @@ send_scan_param (pixma_t * s)
pixma_set_be32 (s->param->y, data + 0x0c);
pixma_set_be32 (raw_width, data + 0x10);
pixma_set_be32 (h, data + 0x14);
data[0x18] = ((s->param->channels != 1) || is_ccd_grayscale (s)) ? 0x08 : 0x04;
data[0x19] = s->param->depth * ((is_ccd_grayscale (s)) ? 3 : s->param->channels); /* bits per pixel */
data[0x18] = ((s->param->channels != 1) || is_ccd_grayscale (s) || is_ccd_lineart (s)) ? 0x08 : 0x04;
data[0x19] = s->param->depth * ((is_ccd_grayscale (s) || is_ccd_lineart (s)) ? 3 : s->param->channels); /* bits per pixel */
data[0x1a] = (is_scanning_from_tpu (s) ? 1 : 0);
data[0x20] = 0xff;
data[0x23] = 0x81;
@ -752,13 +765,14 @@ send_scan_param (pixma_t * s)
pixma_set_be32 (s->param->y, data + 0x10);
pixma_set_be32 (raw_width, data + 0x14);
pixma_set_be32 (h, data + 0x18);
data[0x1c] = ((s->param->channels != 1) || is_ccd_grayscale (s)) ? 0x08 : 0x04;
data[0x1c] = ((s->param->channels != 1) || is_ccd_grayscale (s) || is_ccd_lineart (s)) ? 0x08 : 0x04;
#ifdef DEBUG_TPU_48
data[0x1d] = 24;
#else
data[0x1d] = (is_scanning_from_tpu (s)) ? 48 :
s->param->depth * ((is_ccd_grayscale (s)) ? 3 : s->param->channels); /* bits per pixel */
data[0x1d] = (is_scanning_from_tpu (s)) ? 48
: (((s->param->depth == 1) ? 8 : s->param->depth)
* ((is_ccd_grayscale (s) || is_ccd_lineart (s)) ? 3 : s->param->channels)); /* bits per pixel */
#endif
data[0x1f] = 0x01; /* for 9000F this appears to be 0x00, not sure if that is because of positives */
@ -1080,26 +1094,6 @@ shift_colorsCS9000 (uint8_t * dptr, uint8_t * sptr,
return dptr;
}
static uint8_t *
rgb_to_gray (uint8_t * gptr, uint8_t * sptr, unsigned w, unsigned c)
{
unsigned i, j, g;
for (i = 0; i < w; i++)
{
for (j = 0, g = 0; j < 3; j++)
{
g += *sptr++;
if (c == 6) g += (*sptr++ << 8);
}
g /= 3;
*gptr++ = g;
if (c == 6) *gptr++ = (g >> 8);
}
return gptr;
}
/* under some conditions some scanners have sub images in one line */
/* e.g. doubled image, line size = 8 */
/* line before reordering: px1 px3 px5 px7 px2 px4 px6 px8 */
@ -1292,7 +1286,8 @@ post_process_image_data (pixma_t * s, pixma_imagebuf_t * ib)
test=0;
jumplines=0;
c = ((is_ccd_grayscale (s)) ? 3 : s->param->channels) * s->param->depth / 8;
c = ((is_ccd_grayscale (s) || is_ccd_lineart (s)) ? 3 : s->param->channels)
* ((s->param->depth == 1) ? 8 : s->param->depth) / 8;
cw = c * s->param->w;
cx = c * s->param->xs;
@ -1440,9 +1435,12 @@ post_process_image_data (pixma_t * s, pixma_imagebuf_t * ib)
memmove(cptr, sptr + cx, cw);
/* PDBG (pixma_dbg (4, "*post_process_image_data***** crop line: cx=%u, cw=%u ***** \n", cx, cw)); */
/* Color to Lineart convert for CCD sensor */
if (is_ccd_lineart (s))
cptr = gptr = pixma_binarize_line (s->param, gptr, cptr, s->param->w, c);
/* Color to Grayscale convert for CCD sensor */
if (is_ccd_grayscale (s))
cptr = gptr = rgb_to_gray (gptr, cptr, s->param->w, c);
else if (is_ccd_grayscale (s))
cptr = gptr = pixma_rgb_to_gray (gptr, cptr, s->param->w, c);
else
cptr += cw;
}
@ -1533,14 +1531,42 @@ static int
mp810_check_param (pixma_t * s, pixma_scan_param_t * sp)
{
mp810_t *mp = (mp810_t *) s->subdriver;
unsigned w_max;
sp->depth = 8; /* MP150 only supports 8 bit per channel. */
/* PDBG (pixma_dbg (4, "*mp810_check_param***** Initially: channels=%u, depth=%u, x=%u, y=%u, w=%u, h=%u, xs=%u, wx=%u *****\n",
sp->channels, sp->depth, sp->x, sp->y, sp->w, sp->h, sp->xs, sp->wx)); */
/* MP810 only supports 8 bit per channel in color and grayscale mode */
if (sp->depth != 1)
{
sp->software_lineart = 0;
sp->depth = 8;
#ifdef TPU_48
#ifndef DEBUG_TPU_48
if (sp->source == PIXMA_SOURCE_TPU)
if (sp->source == PIXMA_SOURCE_TPU)
#endif
sp->depth = 16; /* TPU in 16 bits mode */
sp->depth = 16; /* TPU in 16 bits mode */
#endif
}
else
{
/* software lineart */
sp->software_lineart = 1;
sp->depth = 1;
sp->channels = 1;
}
/* for software lineart w must be a multiple of 8 */
if (sp->software_lineart == 1 && sp->w % 8)
{
sp->w += 8 - (sp->w % 8);
/* do not exceed the scanner capability */
w_max = s->cfg->width * s->cfg->xdpi / 75;
w_max -= w_max % 8;
if (sp->w > w_max)
sp->w = w_max;
}
if (sp->source == PIXMA_SOURCE_TPU && !sp->tpu_offset_added)
{
@ -1620,7 +1646,7 @@ mp810_check_param (pixma_t * s, pixma_scan_param_t * sp)
/* PDBG (pixma_dbg (4, "*mp810_check_param***** (else) xs=0 Selected origin, origin shift: %u, %u *****\n", sp->x, sp->xs)); */
}
sp->wx = calc_raw_width (mp, sp);
sp->line_size = sp->w * sp->channels * (sp->depth / 8); /* bytes per line per color after cropping */
sp->line_size = sp->w * sp->channels * (((sp->depth == 1) ? 8 : sp->depth) / 8); /* bytes per line per color after cropping */
/* PDBG (pixma_dbg (4, "*mp810_check_param***** (else) Final scan width and line-size: %u, %"PRIu64" *****\n", sp->wx, sp->line_size)); */
if (sp->source == PIXMA_SOURCE_FLATBED)
@ -1674,6 +1700,9 @@ mp810_check_param (pixma_t * s, pixma_scan_param_t * sp)
sp->ydpi = sp->xdpi;
}
/* PDBG (pixma_dbg (4, "*mp810_check_param***** Finally: channels=%u, depth=%u, x=%u, y=%u, w=%u, h=%u, xs=%u, wx=%u *****\n",
sp->channels, sp->depth, sp->x, sp->y, sp->w, sp->h, sp->xs, sp->wx)); */
return 0;
}
@ -1971,6 +2000,7 @@ static const pixma_scan_ops_t pixma_mp810_ops = {
ext_min_dpi, ext_max_dpi, /* ext_min_dpi, ext_max_dpi */ \
w, h, /* width, height */ \
PIXMA_CAP_EASY_RGB|PIXMA_CAP_GRAY| \
PIXMA_CAP_LINEART| \
PIXMA_CAP_GAMMA_TABLE|PIXMA_CAP_EVENTS|cap \
}

Wyświetl plik

@ -1,7 +1,6 @@
/* Automatically generated from pixma_sane.c */
static const SANE_Range constraint_gamma_table = { 0, 255, 0 };
static int
find_string_in_list (SANE_String_Const str, const SANE_String_Const * list)
{
@ -67,7 +66,7 @@ build_option_descriptors (struct pixma_sane_t *ss)
sod->constraint_type = SANE_CONSTRAINT_STRING_LIST;
sod->constraint.string_list = ss->mode_list;
OPT_IN_CTX[opt_mode].info = SANE_INFO_RELOAD_PARAMS;
opt->def.s = SANE_VALUE_SCAN_MODE_COLOR;
opt->def.s = SANE_I18N (ss->mode_list[0]);
opt->val.w = find_string_in_list (opt->def.s, sod->constraint.string_list);
opt = &(OPT_IN_CTX[opt_source]);
@ -250,6 +249,29 @@ build_option_descriptors (struct pixma_sane_t *ss)
opt->def.w = 0;
opt->val.w = 0;
opt = &(OPT_IN_CTX[opt__group_5]);
sod = &opt->sod;
sod->type = SANE_TYPE_GROUP;
sod->title = SANE_I18N ("Extras");
sod->desc = sod->title;
opt = &(OPT_IN_CTX[opt_threshold]);
sod = &opt->sod;
sod->type = SANE_TYPE_INT;
sod->title = SANE_TITLE_THRESHOLD;
sod->desc = SANE_DESC_THRESHOLD;
sod->name = "threshold";
sod->unit = SANE_UNIT_PERCENT;
sod->size = 1 * sizeof (SANE_Word);
sod->cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC |
SANE_CAP_INACTIVE;
sod->constraint_type = SANE_CONSTRAINT_NONE;
OPT_IN_CTX[opt_threshold].info = 0;
opt->def.w = 50;
opt->val.w = 50;
return 0;
}

Wyświetl plik

@ -30,6 +30,8 @@ typedef enum
opt_button_update,
opt_button_1,
opt_button_2,
opt__group_5,
opt_threshold,
opt_last
} option_t;