genesys: Fix a bug in segmented sensors when scanning 16-bit data

merge-requests/178/head
Povilas Kanapickas 2019-09-13 15:37:33 +03:00
rodzic af17797d3c
commit d4e4bf35c1
4 zmienionych plików z 23 dodań i 27 usunięć

Wyświetl plik

@ -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)
{}

Wyświetl plik

@ -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;

Wyświetl plik

@ -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);

Wyświetl plik

@ -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