kopia lustrzana https://gitlab.com/sane-project/backends
genesys: Use new image pipeline for CCD line shifts and unstagger
rodzic
0b1bfa3f12
commit
bf7e890fa4
|
@ -3439,9 +3439,8 @@ static void genesys_fill_read_buffer(Genesys_Device* dev)
|
|||
static void genesys_read_ordered_data(Genesys_Device* dev, SANE_Byte* destination, size_t* len)
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
size_t bytes, extra;
|
||||
size_t bytes;
|
||||
unsigned int channels, depth, src_pixels;
|
||||
unsigned int ccd_shift[12], shift_count;
|
||||
uint8_t *work_buffer_src;
|
||||
uint8_t *work_buffer_dst;
|
||||
unsigned int dst_lines;
|
||||
|
@ -3489,31 +3488,6 @@ static void genesys_read_ordered_data(Genesys_Device* dev, SANE_Byte* destinatio
|
|||
((dev->read_bytes_left_after_deseg + dev->read_buffer.avail()) * 8UL) /
|
||||
(src_pixels * channels * depth));
|
||||
|
||||
if (channels == 1)
|
||||
{
|
||||
ccd_shift[0] = 0;
|
||||
ccd_shift[1] = dev->current_setup.stagger;
|
||||
shift_count = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ccd_shift[0] =
|
||||
((dev->ld_shift_r * dev->settings.yres) /
|
||||
dev->motor.base_ydpi);
|
||||
ccd_shift[1] =
|
||||
((dev->ld_shift_g * dev->settings.yres) /
|
||||
dev->motor.base_ydpi);
|
||||
ccd_shift[2] =
|
||||
((dev->ld_shift_b * dev->settings.yres) /
|
||||
dev->motor.base_ydpi);
|
||||
|
||||
ccd_shift[3] = ccd_shift[0] + dev->current_setup.stagger;
|
||||
ccd_shift[4] = ccd_shift[1] + dev->current_setup.stagger;
|
||||
ccd_shift[5] = ccd_shift[2] + dev->current_setup.stagger;
|
||||
|
||||
shift_count = 6;
|
||||
}
|
||||
|
||||
|
||||
/* convert data */
|
||||
/*
|
||||
|
@ -3546,56 +3520,6 @@ Problems with the first approach:
|
|||
|
||||
src_buffer = &(dev->read_buffer);
|
||||
|
||||
// maybe reverse effects of ccd layout
|
||||
if (dev->session.pipeline_needs_ccd)
|
||||
{
|
||||
// should not happen with depth == 1.
|
||||
if (depth == 1) {
|
||||
throw SaneException("Can't reverse ccd single bit data\n");
|
||||
}
|
||||
|
||||
dst_buffer = &(dev->shrink_buffer);
|
||||
|
||||
work_buffer_src = src_buffer->get_read_pos();
|
||||
bytes = src_buffer->avail();
|
||||
|
||||
extra =
|
||||
(dev->current_setup.max_shift * src_pixels * channels * depth) / 8;
|
||||
|
||||
/*extra bytes are reserved, and should not be consumed*/
|
||||
if (bytes < extra)
|
||||
bytes = 0;
|
||||
else
|
||||
bytes -= extra;
|
||||
|
||||
/*how many bytes can be processed here?*/
|
||||
/*we are greedy. we work as much as possible*/
|
||||
if (bytes > dst_buffer->size() - dst_buffer->avail())
|
||||
bytes = dst_buffer->size() - dst_buffer->avail();
|
||||
|
||||
dst_lines = (bytes * 8) / (src_pixels * channels * depth);
|
||||
bytes = (dst_lines * src_pixels * channels * depth) / 8;
|
||||
|
||||
work_buffer_dst = dst_buffer->get_write_pos(bytes);
|
||||
|
||||
DBG(DBG_info, "%s: un-ccd-ing %d lines\n", __func__, dst_lines);
|
||||
|
||||
if (dst_lines != 0)
|
||||
{
|
||||
|
||||
if (depth == 8) {
|
||||
genesys_reverse_ccd_8(work_buffer_src, work_buffer_dst, dst_lines,
|
||||
src_pixels * channels, ccd_shift, shift_count);
|
||||
} else {
|
||||
genesys_reverse_ccd_16(work_buffer_src, work_buffer_dst, dst_lines,
|
||||
src_pixels * channels, ccd_shift, shift_count);
|
||||
}
|
||||
dst_buffer->produce(bytes);
|
||||
src_buffer->consume(bytes);
|
||||
}
|
||||
src_buffer = dst_buffer;
|
||||
}
|
||||
|
||||
// maybe shrink(or enlarge) lines
|
||||
if (dev->session.pipeline_needs_shrink) {
|
||||
|
||||
|
|
|
@ -45,70 +45,6 @@
|
|||
* Conversion filters for genesys backend
|
||||
*/
|
||||
|
||||
static void FUNC_NAME(genesys_reverse_ccd) (uint8_t* src_data, uint8_t* dst_data,
|
||||
unsigned int lines, unsigned int components_per_line,
|
||||
unsigned int *ccd_shift, unsigned int component_count)
|
||||
{
|
||||
DBG_HELPER(dbg);
|
||||
unsigned int x, y, c;
|
||||
COMPONENT_TYPE *src = (COMPONENT_TYPE *)src_data;
|
||||
COMPONENT_TYPE *dst = (COMPONENT_TYPE *)dst_data;
|
||||
COMPONENT_TYPE *srcp;
|
||||
COMPONENT_TYPE *dstp;
|
||||
unsigned int pitch = components_per_line;
|
||||
unsigned int ccd_shift_pitch[12];
|
||||
unsigned int *csp;
|
||||
|
||||
for (c = 0; c < component_count; c++)
|
||||
ccd_shift_pitch[c] = ccd_shift[c] * pitch;
|
||||
|
||||
/*
|
||||
* cache efficiency:
|
||||
we are processing a single line component_count times, so it should fit
|
||||
into the cpu cache for maximum efficiency. our lines take
|
||||
maximum 252kb(3 channels, 16bit, 2400dpi, full gl841 shading range)
|
||||
* instruction efficiency:
|
||||
the innermost loop runs long and consists of 3 adds, one compare,
|
||||
2 derefences.
|
||||
*/
|
||||
/*
|
||||
for (y = 0; y < lines; y++) {
|
||||
csp = ccd_shift_pitch;
|
||||
for (c = 0; c < component_count; c++) {
|
||||
srcp = src + c + *csp++;
|
||||
dstp = dst + c;
|
||||
for (x = 0; x < pitch; x += component_count) {
|
||||
*dstp = *srcp;
|
||||
srcp += component_count;
|
||||
dstp += component_count;
|
||||
}
|
||||
}
|
||||
dst += pitch;
|
||||
src += pitch;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
* cache efficency:
|
||||
here only line_dist_pitch needs to stay in cache. 12*4 = 48 bytes
|
||||
* instruction efficiency:
|
||||
we have a short running inner loop, consisting of 4 incs, 2 compare, 1 add,
|
||||
2 dereference and 1 indexed dereference.
|
||||
the enclosing loop is long running, consisting of 1 add, 1 compare.
|
||||
*/
|
||||
srcp = src;
|
||||
dstp = dst;
|
||||
for (y = 0; y < lines; y++) {
|
||||
for (x = 0; x < pitch; x += component_count) {
|
||||
csp = ccd_shift_pitch;
|
||||
for (c = 0; c < component_count && c + x < pitch; c++) {
|
||||
*dstp = srcp[*csp++];
|
||||
dstp++;
|
||||
srcp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void FUNC_NAME(genesys_shrink_lines) (uint8_t* src_data, uint8_t* dst_data,
|
||||
unsigned int lines,
|
||||
unsigned int src_pixels, unsigned int dst_pixels,
|
||||
|
|
|
@ -55,7 +55,6 @@ Genesys_Device::~Genesys_Device()
|
|||
void Genesys_Device::clear()
|
||||
{
|
||||
read_buffer.clear();
|
||||
shrink_buffer.clear();
|
||||
out_buffer.clear();
|
||||
binarize_buffer.clear();
|
||||
local_buffer.clear();
|
||||
|
|
|
@ -282,7 +282,6 @@ struct Genesys_Device
|
|||
SANE_Bool needs_home_ta = 0;
|
||||
|
||||
Genesys_Buffer read_buffer;
|
||||
Genesys_Buffer shrink_buffer;
|
||||
Genesys_Buffer out_buffer;
|
||||
|
||||
// buffer for digital lineart from gray data
|
||||
|
|
|
@ -1053,9 +1053,6 @@ static void gl124_init_scan_regs(Genesys_Device* dev, const Genesys_Sensor& sens
|
|||
dev->read_buffer.clear();
|
||||
dev->read_buffer.alloc(session.buffer_size_read);
|
||||
|
||||
dev->shrink_buffer.clear();
|
||||
dev->shrink_buffer.alloc(session.buffer_size_shrink);
|
||||
|
||||
dev->out_buffer.clear();
|
||||
dev->out_buffer.alloc(session.buffer_size_out);
|
||||
|
||||
|
|
|
@ -718,9 +718,6 @@ static void gl646_setup_registers(Genesys_Device* dev,
|
|||
dev->read_buffer.clear();
|
||||
dev->read_buffer.alloc(session.buffer_size_read);
|
||||
|
||||
dev->shrink_buffer.clear();
|
||||
dev->shrink_buffer.alloc(session.buffer_size_shrink);
|
||||
|
||||
dev->out_buffer.clear();
|
||||
dev->out_buffer.alloc(session.buffer_size_out);
|
||||
|
||||
|
|
|
@ -1875,9 +1875,6 @@ dummy \ scanned lines
|
|||
dev->read_buffer.clear();
|
||||
dev->read_buffer.alloc(session.buffer_size_read);
|
||||
|
||||
dev->shrink_buffer.clear();
|
||||
dev->shrink_buffer.alloc(session.buffer_size_shrink);
|
||||
|
||||
dev->out_buffer.clear();
|
||||
dev->out_buffer.alloc(session.buffer_size_out);
|
||||
|
||||
|
|
|
@ -1292,9 +1292,6 @@ static void gl843_init_scan_regs(Genesys_Device* dev, const Genesys_Sensor& sens
|
|||
dev->read_buffer.clear();
|
||||
dev->read_buffer.alloc(session.buffer_size_read);
|
||||
|
||||
dev->shrink_buffer.clear();
|
||||
dev->shrink_buffer.alloc(session.buffer_size_shrink);
|
||||
|
||||
dev->out_buffer.clear();
|
||||
dev->out_buffer.alloc(session.buffer_size_out);
|
||||
|
||||
|
|
|
@ -918,9 +918,6 @@ static void gl846_init_scan_regs(Genesys_Device* dev, const Genesys_Sensor& sens
|
|||
dev->read_buffer.clear();
|
||||
dev->read_buffer.alloc(session.buffer_size_read);
|
||||
|
||||
dev->shrink_buffer.clear();
|
||||
dev->shrink_buffer.alloc(session.buffer_size_shrink);
|
||||
|
||||
dev->out_buffer.clear();
|
||||
dev->out_buffer.alloc(session.buffer_size_out);
|
||||
|
||||
|
|
|
@ -928,9 +928,6 @@ static void gl847_init_scan_regs(Genesys_Device* dev, const Genesys_Sensor& sens
|
|||
dev->read_buffer.clear();
|
||||
dev->read_buffer.alloc(session.buffer_size_read);
|
||||
|
||||
dev->shrink_buffer.clear();
|
||||
dev->shrink_buffer.alloc(session.buffer_size_shrink);
|
||||
|
||||
dev->out_buffer.clear();
|
||||
dev->out_buffer.alloc(session.buffer_size_out);
|
||||
|
||||
|
|
|
@ -1519,6 +1519,17 @@ void build_image_pipeline(Genesys_Device* dev, const ScanSession& session)
|
|||
dev->pipeline.push_node<ImagePipelineNodeFormatConvert>(PixelFormat::RGB161616);
|
||||
}
|
||||
|
||||
if (session.max_color_shift_lines > 0 && session.params.channels == 3) {
|
||||
std::size_t shift_r = (dev->ld_shift_r * session.params.yres) / dev->motor.base_ydpi;
|
||||
std::size_t shift_g = (dev->ld_shift_g * session.params.yres) / dev->motor.base_ydpi;
|
||||
std::size_t shift_b = (dev->ld_shift_b * session.params.yres) / dev->motor.base_ydpi;
|
||||
dev->pipeline.push_node<ImagePipelineNodeComponentShiftLines>(shift_r, shift_g, shift_b);
|
||||
}
|
||||
|
||||
if (session.num_staggered_lines > 0) {
|
||||
std::vector<std::size_t> shifts{0, session.num_staggered_lines};
|
||||
dev->pipeline.push_node<ImagePipelineNodePixelShiftLines>(shifts);
|
||||
}
|
||||
|
||||
auto read_from_pipeline = [dev](std::size_t size, std::uint8_t* out_data)
|
||||
{
|
||||
|
|
Ładowanie…
Reference in New Issue