kopia lustrzana https://gitlab.com/sane-project/backends
1 bit B/W lineart for pixma_mp150 and pixma_810 subdrivers
rodzic
bd379a59aa
commit
974ee17cf4
|
@ -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.
|
||||
|
||||
|
|
123
backend/pixma.c
123
backend/pixma.c
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 \
|
||||
}
|
||||
|
||||
|
|
|
@ -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 \
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ typedef enum
|
|||
opt_button_update,
|
||||
opt_button_1,
|
||||
opt_button_2,
|
||||
opt__group_5,
|
||||
opt_threshold,
|
||||
opt_last
|
||||
} option_t;
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue