kopia lustrzana https://gitlab.com/sane-project/backends
genesys: Fix a bug in segmented sensors when scanning 16-bit data
rodzic
af17797d3c
commit
d4e4bf35c1
|
@ -129,17 +129,21 @@ void ImagePipelineNodeFormatConvert::get_next_row_data(std::uint8_t* out_data)
|
|||
ImagePipelineNodeDesegment::ImagePipelineNodeDesegment(ImagePipelineNode& source,
|
||||
std::size_t output_width,
|
||||
const std::vector<unsigned>& segment_order,
|
||||
std::size_t segment_size,
|
||||
std::size_t segment_pixels,
|
||||
std::size_t interleaved_lines,
|
||||
std::size_t pixels_per_chunk) :
|
||||
source_(source),
|
||||
output_width_{output_width},
|
||||
segment_order_{segment_order},
|
||||
segment_size_{segment_size},
|
||||
segment_pixels_{segment_pixels},
|
||||
interleaved_lines_{interleaved_lines},
|
||||
pixels_per_chunk_{pixels_per_chunk},
|
||||
buffer_{get_row_bytes()}
|
||||
{
|
||||
DBG_HELPER_ARGS(dbg, "segment_count=%zu, segment_size=%zu, interleaved_lines=%zu, "
|
||||
"pixels_per_shunk=%zu", segment_order.size(), segment_pixels,
|
||||
interleaved_lines, pixels_per_chunk);
|
||||
|
||||
if (source_.get_height() % interleaved_lines_ > 0) {
|
||||
throw SaneException("Height is not a multiple of the number of lines to interelave %zu/%zu",
|
||||
source_.get_height(), interleaved_lines_);
|
||||
|
@ -149,18 +153,18 @@ ImagePipelineNodeDesegment::ImagePipelineNodeDesegment(ImagePipelineNode& source
|
|||
ImagePipelineNodeDesegment::ImagePipelineNodeDesegment(ImagePipelineNode& source,
|
||||
std::size_t output_width,
|
||||
std::size_t segment_count,
|
||||
std::size_t segment_size,
|
||||
std::size_t segment_pixels,
|
||||
std::size_t interleaved_lines,
|
||||
std::size_t pixels_per_chunk) :
|
||||
source_(source),
|
||||
output_width_{output_width},
|
||||
segment_size_{segment_size},
|
||||
segment_pixels_{segment_pixels},
|
||||
interleaved_lines_{interleaved_lines},
|
||||
pixels_per_chunk_{pixels_per_chunk},
|
||||
buffer_{source_.get_row_bytes()}
|
||||
{
|
||||
DBG_HELPER_ARGS(dbg, "segment_count=%zu, segment_size=%zu, interleaved_lines=%zu, "
|
||||
"pixels_per_shunk=%zu", segment_count, segment_size, interleaved_lines,
|
||||
"pixels_per_shunk=%zu", segment_count, segment_pixels, interleaved_lines,
|
||||
pixels_per_chunk);
|
||||
|
||||
segment_order_.resize(segment_count);
|
||||
|
@ -183,16 +187,12 @@ void ImagePipelineNodeDesegment::get_next_row_data(uint8_t* out_data)
|
|||
|
||||
const std::uint8_t* in_data = buffer_.get_row_ptr(0);
|
||||
|
||||
// verify that dev->session.output_segment_pixel_group_count == groups_count
|
||||
// output_width = session.output_segment_pixel_group_count * session.segment_count
|
||||
// segment_size_ = dev->session.conseq_pixel_dist_bytes
|
||||
std::size_t groups_count = output_width_ / (segment_order_.size() * pixels_per_chunk_);
|
||||
|
||||
for (std::size_t igroup = 0; igroup < groups_count; ++igroup) {
|
||||
for (std::size_t isegment = 0; isegment < segment_count; ++isegment) {
|
||||
auto input_offset = igroup * pixels_per_chunk_;
|
||||
// BUG: segment_size_ is specified in bytes, but here we're expected it in pixels
|
||||
input_offset += segment_size_ * segment_order_[isegment];
|
||||
input_offset += segment_pixels_ * segment_order_[isegment];
|
||||
auto output_offset = (igroup * segment_count + isegment) * pixels_per_chunk_;
|
||||
|
||||
for (std::size_t ipixel = 0; ipixel < pixels_per_chunk_; ++ipixel) {
|
||||
|
@ -206,7 +206,7 @@ void ImagePipelineNodeDesegment::get_next_row_data(uint8_t* out_data)
|
|||
ImagePipelineNodeDeinterleaveLines::ImagePipelineNodeDeinterleaveLines(
|
||||
ImagePipelineNode& source, std::size_t interleaved_lines, std::size_t pixels_per_chunk) :
|
||||
ImagePipelineNodeDesegment(source, source.get_width() * interleaved_lines,
|
||||
interleaved_lines, source.get_row_bytes(),
|
||||
interleaved_lines, source.get_width(),
|
||||
interleaved_lines, pixels_per_chunk)
|
||||
{}
|
||||
|
||||
|
|
|
@ -206,19 +206,17 @@ private:
|
|||
class ImagePipelineNodeDesegment : public ImagePipelineNode
|
||||
{
|
||||
public:
|
||||
// segment size is specified in bytes. TODO: switch to pixels
|
||||
ImagePipelineNodeDesegment(ImagePipelineNode& source,
|
||||
std::size_t output_width,
|
||||
const std::vector<unsigned>& segment_order,
|
||||
std::size_t segment_size,
|
||||
std::size_t segment_pixels,
|
||||
std::size_t interleaved_lines,
|
||||
std::size_t pixels_per_chunk);
|
||||
|
||||
// segment size is specified in bytes. TODO: switch to pixels
|
||||
ImagePipelineNodeDesegment(ImagePipelineNode& source,
|
||||
std::size_t output_width,
|
||||
std::size_t segment_count,
|
||||
std::size_t segment_size,
|
||||
std::size_t segment_pixels,
|
||||
std::size_t interleaved_lines,
|
||||
std::size_t pixels_per_chunk);
|
||||
|
||||
|
@ -234,7 +232,7 @@ private:
|
|||
ImagePipelineNode& source_;
|
||||
std::size_t output_width_;
|
||||
std::vector<unsigned> segment_order_;
|
||||
std::size_t segment_size_ = 0;
|
||||
std::size_t segment_pixels_ = 0;
|
||||
std::size_t interleaved_lines_ = 0;
|
||||
std::size_t pixels_per_chunk_ = 0;
|
||||
|
||||
|
|
|
@ -1357,7 +1357,7 @@ void compute_session(Genesys_Device* dev, ScanSession& s, const Genesys_Sensor&
|
|||
|
||||
s.optical_pixels_raw = s.optical_pixels;
|
||||
s.output_line_bytes_raw = s.output_line_bytes;
|
||||
s.conseq_pixel_dist_bytes = 0;
|
||||
s.conseq_pixel_dist = 0;
|
||||
|
||||
if (dev->model->asic_type == AsicType::GL646) {
|
||||
// BUG: most likely segmented sensors were never used, so incorrect value was supplied
|
||||
|
@ -1369,18 +1369,16 @@ void compute_session(Genesys_Device* dev, ScanSession& s, const Genesys_Sensor&
|
|||
dev->model->asic_type == AsicType::GL847)
|
||||
{
|
||||
if (s.segment_count > 1) {
|
||||
s.conseq_pixel_dist_bytes = sensor_profile->segment_size;
|
||||
s.conseq_pixel_dist = sensor_profile->segment_size;
|
||||
|
||||
// in case of multi-segments sensor, we have to add the width of the sensor crossed by
|
||||
// the scan area
|
||||
unsigned extra_segment_scan_area = align_multiple_ceil(s.conseq_pixel_dist_bytes, 2);
|
||||
unsigned extra_segment_scan_area = align_multiple_ceil(s.conseq_pixel_dist, 2);
|
||||
extra_segment_scan_area *= s.segment_count - 1;
|
||||
extra_segment_scan_area *= s.hwdpi_divisor * s.segment_count;
|
||||
extra_segment_scan_area *= ccd_pixels_per_system_pixel;
|
||||
|
||||
s.optical_pixels_raw += extra_segment_scan_area;
|
||||
s.conseq_pixel_dist_bytes = multiply_by_depth_ceil(s.conseq_pixel_dist_bytes,
|
||||
s.params.depth);
|
||||
}
|
||||
|
||||
s.output_line_bytes_raw = multiply_by_depth_ceil(
|
||||
|
@ -1391,11 +1389,11 @@ void compute_session(Genesys_Device* dev, ScanSession& s, const Genesys_Sensor&
|
|||
if (dev->model->asic_type == AsicType::GL124) {
|
||||
s.output_line_bytes_raw = multiply_by_depth_ceil(s.output_pixels / s.ccd_size_divisor,
|
||||
s.params.depth);
|
||||
s.conseq_pixel_dist_bytes = s.output_line_bytes_raw / s.segment_count;
|
||||
s.conseq_pixel_dist = s.output_pixels / s.ccd_size_divisor / s.segment_count;
|
||||
}
|
||||
|
||||
if (dev->model->asic_type == AsicType::GL843) {
|
||||
s.conseq_pixel_dist_bytes = s.output_line_bytes_raw / s.segment_count;
|
||||
s.conseq_pixel_dist = s.output_pixels / s.segment_count;
|
||||
}
|
||||
|
||||
s.output_segment_pixel_group_count = 0;
|
||||
|
@ -1484,7 +1482,7 @@ void build_image_pipeline(Genesys_Device* dev, const ScanSession& session)
|
|||
|
||||
auto output_width = session.output_segment_pixel_group_count * session.segment_count;
|
||||
dev->pipeline.push_node<ImagePipelineNodeDesegment>(output_width, dev->segment_order,
|
||||
session.conseq_pixel_dist_bytes,
|
||||
session.conseq_pixel_dist,
|
||||
1, 1);
|
||||
} else {
|
||||
auto read_bytes_left_after_deseg = session.output_line_bytes * session.output_line_count;
|
||||
|
@ -2250,7 +2248,7 @@ void debug_dump(unsigned level, const ScanSession& session)
|
|||
DBG(level, " segment_count : %d\n", session.segment_count);
|
||||
DBG(level, " pixel_startx : %d\n", session.pixel_startx);
|
||||
DBG(level, " pixel_endx : %d\n", session.pixel_endx);
|
||||
DBG(level, " conseq_pixel_dist_bytes : %d\n", session.conseq_pixel_dist_bytes);
|
||||
DBG(level, " conseq_pixel_dist : %d\n", session.conseq_pixel_dist);
|
||||
DBG(level, " output_segment_pixel_group_count : %d\n",
|
||||
session.output_segment_pixel_group_count);
|
||||
DBG(level, " buffer_size_read : %zu\n", session.buffer_size_read);
|
||||
|
|
|
@ -271,10 +271,10 @@ struct ScanSession {
|
|||
unsigned pixel_startx = 0;
|
||||
unsigned pixel_endx = 0;
|
||||
|
||||
// Distance in bytes between consecutive pixels, e.g. between odd and even pixels. Note that
|
||||
// Distance in pixels between consecutive pixels, e.g. between odd and even pixels. Note that
|
||||
// the number of segments can be large.
|
||||
// only on gl124, gl846, gl847
|
||||
unsigned conseq_pixel_dist_bytes = 0;
|
||||
unsigned conseq_pixel_dist = 0;
|
||||
|
||||
// The number of "even" pixels to scan. This corresponds to the number of pixels that will be
|
||||
// scanned from a single segment
|
||||
|
|
Ładowanie…
Reference in New Issue