kopia lustrzana https://gitlab.com/sane-project/backends
implement brightness/constrast enhancement using gamma tables
rodzic
017d8aaf88
commit
e3e5e9b3a3
|
|
@ -1,3 +1,8 @@
|
|||
2013-08-11 Stéphane Voltz <stef.dev@free.fr>
|
||||
* backend/genesys_low.[ch] backend/genesys_conv.c backend/genesys.c
|
||||
backend/genesys_gl841.c backend/genesys_gl646.c: make use of hardware
|
||||
gamma tables to implement constrast and brightness correction.
|
||||
|
||||
2013-08-07 Stéphane Voltz <stef.dev@free.fr>
|
||||
* backend/genesys.[ch] backend/genesys_conv.c doc/sane-genesys.man
|
||||
po/fr.po: add digital brightness and contrast options.
|
||||
|
|
|
|||
|
|
@ -3755,88 +3755,6 @@ genesys_wait_not_moving (Genesys_Device * dev, int mseconds)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Function to build a lookup table (LUT), often
|
||||
used by scanners to implement brightness/contrast/gamma
|
||||
or by backends to speed binarization/thresholding
|
||||
|
||||
offset and slope inputs are -127 to +127
|
||||
|
||||
slope rotates line around central input/output val,
|
||||
0 makes horizontal line
|
||||
|
||||
pos zero neg
|
||||
. x . . x
|
||||
. x . . x
|
||||
out . x .xxxxxxxxxxx . x
|
||||
. x . . x
|
||||
....x....... ............ .......x....
|
||||
in in in
|
||||
|
||||
offset moves line vertically, and clamps to output range
|
||||
0 keeps the line crossing the center of the table
|
||||
|
||||
high low
|
||||
. xxxxxxxx .
|
||||
. x .
|
||||
out x . x
|
||||
. . x
|
||||
............ xxxxxxxx....
|
||||
in in
|
||||
|
||||
out_min/max provide bounds on output values,
|
||||
useful when building thresholding lut.
|
||||
0 and 255 are good defaults otherwise.
|
||||
*/
|
||||
static SANE_Status
|
||||
load_lut (unsigned char * lut,
|
||||
int in_bits, int out_bits,
|
||||
int out_min, int out_max,
|
||||
int slope, int offset)
|
||||
{
|
||||
SANE_Status ret = SANE_STATUS_GOOD;
|
||||
int i, j;
|
||||
double shift, rise;
|
||||
int max_in_val = (1 << in_bits) - 1;
|
||||
int max_out_val = (1 << out_bits) - 1;
|
||||
unsigned char * lut_p = lut;
|
||||
|
||||
DBGSTART;
|
||||
|
||||
/* slope is converted to rise per unit run:
|
||||
* first [-127,127] to [-.999,.999]
|
||||
* then to [-PI/4,PI/4] then [0,PI/2]
|
||||
* then take the tangent (T.O.A)
|
||||
* then multiply by the normal linear slope
|
||||
* because the table may not be square, i.e. 1024x256*/
|
||||
rise = tan((double)slope/128 * M_PI_4 + M_PI_4) * max_out_val / max_in_val;
|
||||
|
||||
/* line must stay vertically centered, so figure
|
||||
* out vertical offset at central input value */
|
||||
shift = (double)max_out_val/2 - (rise*max_in_val/2);
|
||||
|
||||
/* convert the user offset setting to scale of output
|
||||
* first [-127,127] to [-1,1]
|
||||
* then to [-max_out_val/2,max_out_val/2]*/
|
||||
shift += (double)offset / 127 * max_out_val / 2;
|
||||
|
||||
for(i=0;i<=max_in_val;i++){
|
||||
j = rise*i + shift;
|
||||
|
||||
if(j<out_min){
|
||||
j=out_min;
|
||||
}
|
||||
else if(j>out_max){
|
||||
j=out_max;
|
||||
}
|
||||
|
||||
*lut_p=j;
|
||||
lut_p++;
|
||||
}
|
||||
|
||||
DBGCOMPLETED;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* High level (exported) functions */
|
||||
|
|
@ -4109,7 +4027,7 @@ genesys_start_scan (Genesys_Device * dev, SANE_Bool lamp_off)
|
|||
}
|
||||
}
|
||||
|
||||
/* send gamma tbales. They have been set ot device or user value
|
||||
/* send gamma tables. They have been set to device or user value
|
||||
* when setting option value */
|
||||
status = dev->model->cmd_set->send_gamma_table (dev);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
|
|
@ -4124,7 +4042,7 @@ genesys_start_scan (Genesys_Device * dev, SANE_Bool lamp_off)
|
|||
status = genesys_restore_calibration (dev);
|
||||
if (status == SANE_STATUS_UNSUPPORTED)
|
||||
{
|
||||
/* calibration : sheetfed scanners can't calibrate before each scan */
|
||||
/* calibration : sheetfed scanners can't calibrate before each scan */
|
||||
/* and also those who have the NO_CALIBRATION flag */
|
||||
if (!(dev->model->flags & GENESYS_FLAG_NO_CALIBRATION)
|
||||
&&dev->model->is_sheetfed == SANE_FALSE)
|
||||
|
|
@ -4156,7 +4074,7 @@ genesys_start_scan (Genesys_Device * dev, SANE_Bool lamp_off)
|
|||
/* build look up table for dynamic lineart */
|
||||
if(dev->settings.dynamic_lineart==SANE_TRUE)
|
||||
{
|
||||
status = load_lut(dev->lineart_lut, 8, 8, 50, 205,
|
||||
status = sanei_genesys_load_lut(dev->lineart_lut, 8, 8, 50, 205,
|
||||
dev->settings.threshold_curve,
|
||||
dev->settings.threshold-127);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
|
|
@ -5330,7 +5248,6 @@ calc_parameters (Genesys_Scanner * s)
|
|||
s->dev->settings.dynamic_lineart = SANE_TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* threshold curve for dynamic rasterization */
|
||||
s->dev->settings.threshold_curve=s->val[OPT_THRESHOLD_CURVE].w;
|
||||
|
||||
|
|
@ -5341,8 +5258,6 @@ calc_parameters (Genesys_Scanner * s)
|
|||
|| s->val[OPT_SWCROP].b
|
||||
|| s->val[OPT_SWDESKEW].b
|
||||
|| s->val[OPT_SWDEROTATE].b
|
||||
|| s->val[OPT_BRIGHTNESS].w!=0
|
||||
|| s->val[OPT_CONTRAST].w!=0
|
||||
||(SANE_UNFIX(s->val[OPT_SWSKIP].w)>0))
|
||||
&& (!s->val[OPT_PREVIEW].b)
|
||||
&& (s->val[OPT_BIT_DEPTH].w <= 8))
|
||||
|
|
@ -5354,6 +5269,18 @@ calc_parameters (Genesys_Scanner * s)
|
|||
s->dev->buffer_image=SANE_FALSE;
|
||||
}
|
||||
|
||||
/* brigthness and contrast only for for 8 bit scans */
|
||||
if(s->val[OPT_BIT_DEPTH].w <= 8)
|
||||
{
|
||||
s->dev->settings.contrast=(s->val[OPT_CONTRAST].w*127)/100;
|
||||
s->dev->settings.brightness=(s->val[OPT_BRIGHTNESS].w*127)/100;
|
||||
}
|
||||
else
|
||||
{
|
||||
s->dev->settings.contrast=0;
|
||||
s->dev->settings.brightness=0;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
@ -5373,9 +5300,13 @@ create_bpp_list (Genesys_Scanner * s, SANE_Int * bpp)
|
|||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/* this function initialize a gamma vector based on the ASIC:
|
||||
/** @brief this function initialize a gamma vector based on the ASIC:
|
||||
* Set up a default gamma table vector based on device description
|
||||
* gl646: 12 or 14 bits gamma table depending on GENESYS_FLAG_14BIT_GAMMA
|
||||
* gl84x: 16 bits
|
||||
* gl12x: 16 bits
|
||||
* @param scanner pointer to scanner session to get options
|
||||
* @param option option number of the gamma table to set
|
||||
*/
|
||||
static void
|
||||
init_gamma_vector_option (Genesys_Scanner * scanner, int option)
|
||||
|
|
@ -5400,7 +5331,7 @@ init_gamma_vector_option (Genesys_Scanner * scanner, int option)
|
|||
}
|
||||
}
|
||||
else
|
||||
{ /* GL841 case 16 bits gamma table */
|
||||
{ /* other asics have 16 bits words gamma table */
|
||||
scanner->opt[option].size = 256 * sizeof (SANE_Word);
|
||||
scanner->opt[option].constraint.range = &u16_range;
|
||||
}
|
||||
|
|
@ -5411,7 +5342,7 @@ init_gamma_vector_option (Genesys_Scanner * scanner, int option)
|
|||
/**
|
||||
* allocate a geometry range
|
||||
* @param size maximum size of the range
|
||||
* @return a poiter to a valid range or NULL
|
||||
* @return a pointer to a valid range or NULL
|
||||
*/
|
||||
static SANE_Range *create_range(SANE_Fixed size)
|
||||
{
|
||||
|
|
@ -7710,12 +7641,6 @@ sane_start (SANE_Handle handle)
|
|||
{
|
||||
RIE(genesys_derotate(s));
|
||||
}
|
||||
|
||||
/* adjust contrast/brightness if required */
|
||||
if(s->val[OPT_BRIGHTNESS].w!=0 || s->val[OPT_CONTRAST].w!=0)
|
||||
{
|
||||
RIE(genesys_enhance(s));
|
||||
}
|
||||
}
|
||||
|
||||
DBGCOMPLETED;
|
||||
|
|
|
|||
|
|
@ -475,31 +475,4 @@ genesys_derotate (Genesys_Scanner * s)
|
|||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
/** Apply brightness and constrast enhancement
|
||||
*
|
||||
*/
|
||||
static SANE_Status
|
||||
genesys_enhance (Genesys_Scanner * s)
|
||||
{
|
||||
SANE_Status status;
|
||||
unsigned char lut[256];
|
||||
int x;
|
||||
|
||||
DBGSTART;
|
||||
|
||||
/* build lookup table */
|
||||
status = load_lut (lut, 8, 8, 0, 255, (s->val[OPT_CONTRAST].w*127)/100, (s->val[OPT_BRIGHTNESS].w*127)/100);
|
||||
if (status != SANE_STATUS_GOOD) {
|
||||
DBG (5, "%s: ERROR: cannot load lut\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
/* parse binary data changing it through lut */
|
||||
for(x=0;x<s->params.bytes_per_line * s->params.lines;x++)
|
||||
{
|
||||
s->dev->img_buffer[x]=lut[s->dev->img_buffer[x]];
|
||||
}
|
||||
|
||||
DBGCOMPLETED;
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */
|
||||
|
|
|
|||
|
|
@ -3614,34 +3614,33 @@ gl646_send_gamma_table (Genesys_Device * dev)
|
|||
{
|
||||
int size;
|
||||
int address;
|
||||
int status;
|
||||
SANE_Status status;
|
||||
uint8_t *gamma;
|
||||
int i;
|
||||
int bits;
|
||||
|
||||
DBGSTART;
|
||||
|
||||
/* gamma table size */
|
||||
if (dev->reg[reg_0x05].value & REG05_GMMTYPE)
|
||||
size = 16384;
|
||||
{
|
||||
size = 16384;
|
||||
bits = 14;
|
||||
}
|
||||
else
|
||||
size = 4096;
|
||||
{
|
||||
size = 4096;
|
||||
bits = 12;
|
||||
}
|
||||
|
||||
/* allocate temporary gamma tables: 16 bits words, 3 channels */
|
||||
gamma = (uint8_t *) malloc (size * 2 * 3);
|
||||
if (!gamma)
|
||||
return SANE_STATUS_NO_MEM;
|
||||
|
||||
/* copy sensor specific's gamma tables */
|
||||
for (i = 0; i < size; i++)
|
||||
if (gamma==NULL)
|
||||
{
|
||||
gamma[i * 2] = dev->sensor.gamma_table[GENESYS_RED][i] & 0xff;
|
||||
gamma[i * 2 + 1] = dev->sensor.gamma_table[GENESYS_RED][i] >> 8;
|
||||
gamma[i * 2 + size * 2] = dev->sensor.gamma_table[GENESYS_GREEN][i] & 0xff;
|
||||
gamma[i * 2 + 1 + size * 2] = dev->sensor.gamma_table[GENESYS_GREEN][i] >> 8;
|
||||
gamma[i * 2 + size * 4] = dev->sensor.gamma_table[GENESYS_BLUE][i] & 0xff;
|
||||
gamma[i * 2 + 1 + size * 4] = dev->sensor.gamma_table[GENESYS_BLUE][i] >> 8;
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
RIE(sanei_genesys_generate_gamma_buffer(dev, bits, size-1, size, gamma));
|
||||
|
||||
/* table address */
|
||||
switch (dev->reg[reg_0x05].value >> 6)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4143,9 +4143,8 @@ static SANE_Status
|
|||
gl841_send_gamma_table (Genesys_Device * dev)
|
||||
{
|
||||
int size;
|
||||
int status;
|
||||
SANE_Status status;
|
||||
uint8_t *gamma;
|
||||
int i;
|
||||
|
||||
DBGSTART;
|
||||
|
||||
|
|
@ -4153,19 +4152,13 @@ gl841_send_gamma_table (Genesys_Device * dev)
|
|||
|
||||
/* allocate temporary gamma tables: 16 bits words, 3 channels */
|
||||
gamma = (uint8_t *) malloc (size * 2 * 3);
|
||||
if (!gamma)
|
||||
return SANE_STATUS_NO_MEM;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
if (gamma==NULL)
|
||||
{
|
||||
gamma[i*2 + size * 0 + 0] = dev->sensor.gamma_table[GENESYS_RED][i] & 0xff;
|
||||
gamma[i*2 + size * 0 + 1] = (dev->sensor.gamma_table[GENESYS_RED][i] >> 8) & 0xff;
|
||||
gamma[i*2 + size * 2 + 0] = dev->sensor.gamma_table[GENESYS_GREEN][i] & 0xff;
|
||||
gamma[i*2 + size * 2 + 1] = (dev->sensor.gamma_table[GENESYS_GREEN][i] >> 8) & 0xff;
|
||||
gamma[i*2 + size * 4 + 0] = dev->sensor.gamma_table[GENESYS_BLUE][i] & 0xff;
|
||||
gamma[i*2 + size * 4 + 1] = (dev->sensor.gamma_table[GENESYS_BLUE][i] >> 8) & 0xff;
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
RIE(sanei_genesys_generate_gamma_buffer(dev, 16, 65535, size, gamma));
|
||||
|
||||
/* send address */
|
||||
status = gl841_set_buffer_address_gamma (dev, 0x00000);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
|
|
|
|||
|
|
@ -1176,6 +1176,85 @@ sanei_genesys_write_ahb (SANE_Int dn, int usb_mode, uint32_t addr, uint32_t size
|
|||
return status;
|
||||
}
|
||||
|
||||
/** @brief generates gamma buffer to transfer
|
||||
* Generates gamma table buffer to send to ASIC. Applies
|
||||
* contrast and brightness if set.
|
||||
* @param dev device to set up
|
||||
* @param bits number of bits used by gamma
|
||||
* @param max value for gamma
|
||||
* @param size of the gamma table
|
||||
* @param gamma allocated gamma buffer to fill
|
||||
* @returns SANE_STATUS_GOOD or SANE_STATUS_NO_MEM
|
||||
*/
|
||||
SANE_Status sanei_genesys_generate_gamma_buffer(Genesys_Device * dev,
|
||||
int bits,
|
||||
int max,
|
||||
int size,
|
||||
uint8_t *gamma)
|
||||
{
|
||||
int i;
|
||||
uint16_t value, *lut=NULL;
|
||||
|
||||
if(dev->settings.contrast!=0 || dev->settings.brightness!=0)
|
||||
{
|
||||
lut=(uint16_t *)malloc(65536*2);
|
||||
if(lut==NULL)
|
||||
{
|
||||
free(gamma);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
sanei_genesys_load_lut((unsigned char *)lut,
|
||||
bits,
|
||||
bits,
|
||||
0,
|
||||
max,
|
||||
dev->settings.contrast,
|
||||
dev->settings.brightness);
|
||||
for (i = 0; i < size-1; i++)
|
||||
{
|
||||
value=dev->sensor.gamma_table[GENESYS_RED][i];
|
||||
value=lut[value];
|
||||
gamma[i * 2 + size * 0 + 0] = value & 0xff;
|
||||
gamma[i * 2 + size * 0 + 1] = (value >> 8) & 0xff;
|
||||
|
||||
value=dev->sensor.gamma_table[GENESYS_GREEN][i];
|
||||
value=lut[value];
|
||||
gamma[i * 2 + size * 2 + 0] = value & 0xff;
|
||||
gamma[i * 2 + size * 2 + 1] = (value >> 8) & 0xff;
|
||||
|
||||
value=dev->sensor.gamma_table[GENESYS_BLUE][i];
|
||||
value=lut[value];
|
||||
gamma[i * 2 + size * 4 + 0] = value & 0xff;
|
||||
gamma[i * 2 + size * 4 + 1] = (value >> 8) & 0xff;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < size-1; i++)
|
||||
{
|
||||
value=dev->sensor.gamma_table[GENESYS_RED][i];
|
||||
gamma[i * 2 + size * 0 + 0] = value & 0xff;
|
||||
gamma[i * 2 + size * 0 + 1] = (value >> 8) & 0xff;
|
||||
|
||||
value=dev->sensor.gamma_table[GENESYS_GREEN][i];
|
||||
gamma[i * 2 + size * 2 + 0] = value & 0xff;
|
||||
gamma[i * 2 + size * 2 + 1] = (value >> 8) & 0xff;
|
||||
|
||||
value=dev->sensor.gamma_table[GENESYS_BLUE][i];
|
||||
gamma[i * 2 + size * 4 + 0] = value & 0xff;
|
||||
gamma[i * 2 + size * 4 + 1] = (value >> 8) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(lut!=NULL)
|
||||
{
|
||||
free(lut);
|
||||
}
|
||||
|
||||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
|
||||
/** @brief send gamma table to scanner
|
||||
* This function sends generic gamma table (ie ones built with
|
||||
|
|
@ -1187,12 +1266,11 @@ SANE_Status
|
|||
sanei_genesys_send_gamma_table (Genesys_Device * dev)
|
||||
{
|
||||
int size;
|
||||
int status;
|
||||
uint8_t *gamma, val;
|
||||
int i;
|
||||
uint8_t *gamma, val;
|
||||
SANE_Status status;
|
||||
|
||||
DBG (DBG_proc, "gl124_send_gamma_table\n");
|
||||
|
||||
DBGSTART;
|
||||
|
||||
size = 256 + 1;
|
||||
|
||||
|
|
@ -1204,16 +1282,7 @@ sanei_genesys_send_gamma_table (Genesys_Device * dev)
|
|||
}
|
||||
memset(gamma, 255, size*3*2);
|
||||
|
||||
/* copy sensor defined gamma tables */
|
||||
for (i = 0; i < size-1; i++)
|
||||
{
|
||||
gamma[i * 2 + size * 0 + 0] = dev->sensor.gamma_table[GENESYS_RED][i] & 0xff;
|
||||
gamma[i * 2 + size * 0 + 1] = (dev->sensor.gamma_table[GENESYS_RED][i] >> 8) & 0xff;
|
||||
gamma[i * 2 + size * 2 + 0] = dev->sensor.gamma_table[GENESYS_GREEN][i] & 0xff;
|
||||
gamma[i * 2 + size * 2 + 1] = (dev->sensor.gamma_table[GENESYS_GREEN][i] >> 8) & 0xff;
|
||||
gamma[i * 2 + size * 4 + 0] = dev->sensor.gamma_table[GENESYS_BLUE][i] & 0xff;
|
||||
gamma[i * 2 + size * 4 + 1] = (dev->sensor.gamma_table[GENESYS_BLUE][i] >> 8) & 0xff;
|
||||
}
|
||||
RIE(sanei_genesys_generate_gamma_buffer(dev, 16, 65535, size, gamma));
|
||||
|
||||
/* loop sending gamma tables NOTE: 0x01000000 not 0x10000000 */
|
||||
for (i = 0; i < 3; i++)
|
||||
|
|
@ -1235,8 +1304,9 @@ sanei_genesys_send_gamma_table (Genesys_Device * dev)
|
|||
status = sanei_genesys_write_ahb (dev->dn, dev->usb_mode, 0x01000000 + 0x200 * i, (size-1) * 2, gamma + i * size * 2+2);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
free (gamma);
|
||||
DBG (DBG_error,
|
||||
"gl124_send_gamma_table: write to AHB failed writing table %d (%s)\n",
|
||||
"%s: write to AHB failed writing table %d (%s)\n", __FUNCTION__,
|
||||
i, sane_strstatus (status));
|
||||
}
|
||||
}
|
||||
|
|
@ -1801,6 +1871,111 @@ int sanei_genesys_compute_max_shift(Genesys_Device *dev,
|
|||
return max_shift;
|
||||
}
|
||||
|
||||
/** @brief build lookup table for digital enhancements
|
||||
* Function to build a lookup table (LUT), often
|
||||
used by scanners to implement brightness/contrast/gamma
|
||||
or by backends to speed binarization/thresholding
|
||||
|
||||
offset and slope inputs are -127 to +127
|
||||
|
||||
slope rotates line around central input/output val,
|
||||
0 makes horizontal line
|
||||
|
||||
pos zero neg
|
||||
. x . . x
|
||||
. x . . x
|
||||
out . x .xxxxxxxxxxx . x
|
||||
. x . . x
|
||||
....x....... ............ .......x....
|
||||
in in in
|
||||
|
||||
offset moves line vertically, and clamps to output range
|
||||
0 keeps the line crossing the center of the table
|
||||
|
||||
high low
|
||||
. xxxxxxxx .
|
||||
. x .
|
||||
out x . x
|
||||
. . x
|
||||
............ xxxxxxxx....
|
||||
in in
|
||||
|
||||
out_min/max provide bounds on output values,
|
||||
useful when building thresholding lut.
|
||||
0 and 255 are good defaults otherwise.
|
||||
* @param lut pointer where to store the generated lut
|
||||
* @param in_bits number of bits for in values
|
||||
* @param out_bits number of bits of out values
|
||||
* @param out_min minimal out value
|
||||
* @param out_max maximal out value
|
||||
* @param slope slope of the generated data
|
||||
* @param offset offset of the generated data
|
||||
*/
|
||||
SANE_Status
|
||||
sanei_genesys_load_lut (unsigned char * lut,
|
||||
int in_bits,
|
||||
int out_bits,
|
||||
int out_min,
|
||||
int out_max,
|
||||
int slope,
|
||||
int offset)
|
||||
{
|
||||
SANE_Status ret = SANE_STATUS_GOOD;
|
||||
int i, j;
|
||||
double shift, rise;
|
||||
int max_in_val = (1 << in_bits) - 1;
|
||||
int max_out_val = (1 << out_bits) - 1;
|
||||
uint8_t *lut_p8 = lut;
|
||||
uint16_t *lut_p16 = (uint16_t *) lut;
|
||||
|
||||
DBGSTART;
|
||||
|
||||
/* slope is converted to rise per unit run:
|
||||
* first [-127,127] to [-.999,.999]
|
||||
* then to [-PI/4,PI/4] then [0,PI/2]
|
||||
* then take the tangent (T.O.A)
|
||||
* then multiply by the normal linear slope
|
||||
* because the table may not be square, i.e. 1024x256*/
|
||||
rise = tan ((double) slope / 128 * M_PI_4 + M_PI_4) * max_out_val / max_in_val;
|
||||
|
||||
/* line must stay vertically centered, so figure
|
||||
* out vertical offset at central input value */
|
||||
shift = (double) max_out_val / 2 - (rise * max_in_val / 2);
|
||||
|
||||
/* convert the user offset setting to scale of output
|
||||
* first [-127,127] to [-1,1]
|
||||
* then to [-max_out_val/2,max_out_val/2]*/
|
||||
shift += (double) offset / 127 * max_out_val / 2;
|
||||
|
||||
for (i = 0; i <= max_in_val; i++)
|
||||
{
|
||||
j = rise * i + shift;
|
||||
|
||||
/* cap data to required range */
|
||||
if (j < out_min)
|
||||
{
|
||||
j = out_min;
|
||||
}
|
||||
else if (j > out_max)
|
||||
{
|
||||
j = out_max;
|
||||
}
|
||||
|
||||
/* copy result according to bit depth */
|
||||
if (out_bits <= 8)
|
||||
{
|
||||
*lut_p8 = j;
|
||||
lut_p8++;
|
||||
}
|
||||
else
|
||||
{
|
||||
*lut_p16 = j;
|
||||
lut_p16++;
|
||||
}
|
||||
}
|
||||
|
||||
DBGCOMPLETED;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ typedef struct
|
|||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t sensor_id; /**< id of the sensor description */
|
||||
uint8_t sensor_id; /**< id of the sensor description */
|
||||
int optical_res;
|
||||
int black_pixels;
|
||||
int dummy_pixel; /* value of dummy register. */
|
||||
|
|
@ -672,6 +672,12 @@ typedef struct
|
|||
/**< true is lineart is generated from gray data by
|
||||
* the dynamic rasterization algo */
|
||||
int dynamic_lineart;
|
||||
|
||||
/**< value for contrast enhancement in the [-100..100] range */
|
||||
int contrast;
|
||||
|
||||
/**< value for brightness enhancement in the [-100..100] range */
|
||||
int brightness;
|
||||
} Genesys_Settings;
|
||||
|
||||
typedef struct Genesys_Current_Setup
|
||||
|
|
@ -1107,6 +1113,23 @@ int sanei_genesys_compute_max_shift(Genesys_Device *dev,
|
|||
int channels,
|
||||
int yres,
|
||||
int flags);
|
||||
|
||||
extern SANE_Status
|
||||
sanei_genesys_load_lut (unsigned char * lut,
|
||||
int in_bits,
|
||||
int out_bits,
|
||||
int out_min,
|
||||
int out_max,
|
||||
int slope,
|
||||
int offset);
|
||||
|
||||
extern SANE_Status
|
||||
sanei_genesys_generate_gamma_buffer(Genesys_Device * dev,
|
||||
int bits,
|
||||
int max,
|
||||
int size,
|
||||
uint8_t *gamma);
|
||||
|
||||
#ifdef UNIT_TESTING
|
||||
SANE_Status
|
||||
genesys_send_offset_and_shading (Genesys_Device * dev,
|
||||
|
|
|
|||
Ładowanie…
Reference in New Issue