diff options
| author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2020-09-10 19:11:27 +0200 | 
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2020-09-10 19:11:27 +0200 | 
| commit | 7e9455b3b15671ff99ed168638c405e2acedb6df (patch) | |
| tree | 444e59ece236e09dc153f665e42160aeb0208c24 /backend/genesys/image_pipeline.cpp | |
| parent | bc8a517abd2e11e1435f4ef042cfcc8648b62ef7 (diff) | |
| parent | bce41b3c37c2a68e7dab234ce0247755a61ceb40 (diff) | |
Merge branch 'release/debian/1.0.31-1_experimental1' into masterdebian/1.0.31-1_experimental1
Diffstat (limited to 'backend/genesys/image_pipeline.cpp')
| -rw-r--r-- | backend/genesys/image_pipeline.cpp | 211 | 
1 files changed, 130 insertions, 81 deletions
| diff --git a/backend/genesys/image_pipeline.cpp b/backend/genesys/image_pipeline.cpp index c01b7f4..8d67be9 100644 --- a/backend/genesys/image_pipeline.cpp +++ b/backend/genesys/image_pipeline.cpp @@ -53,15 +53,6 @@ namespace genesys {  ImagePipelineNode::~ImagePipelineNode() {} -std::size_t ImagePipelineNodeBytesSource::consume_remaining_bytes(std::size_t bytes) -{ -    if (bytes > remaining_bytes_) { -        bytes = remaining_bytes_; -    } -    remaining_bytes_ -= bytes; -    return bytes; -} -  bool ImagePipelineNodeCallableSource::get_next_row_data(std::uint8_t* out_data)  {      bool got_data = producer_(get_row_bytes(), out_data); @@ -78,7 +69,7 @@ ImagePipelineNodeBufferedCallableSource::ImagePipelineNodeBufferedCallableSource      format_{format},      buffer_{input_batch_size, producer}  { -    set_remaining_bytes(height_ * get_row_bytes()); +    buffer_.set_remaining_size(height_ * get_row_bytes());  }  bool ImagePipelineNodeBufferedCallableSource::get_next_row_data(std::uint8_t* out_data) @@ -92,13 +83,7 @@ bool ImagePipelineNodeBufferedCallableSource::get_next_row_data(std::uint8_t* ou      bool got_data = true; -    auto row_bytes = get_row_bytes(); -    auto bytes_to_ask = consume_remaining_bytes(row_bytes); -    if (bytes_to_ask < row_bytes) { -        got_data = false; -    } - -    got_data &= buffer_.get_data(bytes_to_ask, out_data); +    got_data &= buffer_.get_data(get_row_bytes(), out_data);      curr_row_++;      if (!got_data) {          eof_ = true; @@ -106,37 +91,6 @@ bool ImagePipelineNodeBufferedCallableSource::get_next_row_data(std::uint8_t* ou      return got_data;  } - -ImagePipelineNodeBufferedGenesysUsb::ImagePipelineNodeBufferedGenesysUsb( -        std::size_t width, std::size_t height, PixelFormat format, std::size_t total_size, -        const FakeBufferModel& buffer_model, ProducerCallback producer) : -    width_{width}, -    height_{height}, -    format_{format}, -    buffer_{total_size, buffer_model, producer} -{ -    set_remaining_bytes(total_size); -} - -bool ImagePipelineNodeBufferedGenesysUsb::get_next_row_data(std::uint8_t* out_data) -{ -    if (remaining_bytes() != buffer_.remaining_size() + buffer_.available()) { -        buffer_.set_remaining_size(remaining_bytes() - buffer_.available()); -    } -    bool got_data = true; - -    std::size_t row_bytes = get_row_bytes(); -    std::size_t ask_bytes = consume_remaining_bytes(row_bytes); -    if (ask_bytes < row_bytes) { -        got_data = false; -    } -    got_data &= buffer_.get_data(ask_bytes, out_data); -    if (!got_data) { -        eof_ = true; -    } -    return got_data; -} -  ImagePipelineNodeArraySource::ImagePipelineNodeArraySource(std::size_t width, std::size_t height,                                                             PixelFormat format,                                                             std::vector<std::uint8_t> data) : @@ -151,7 +105,6 @@ ImagePipelineNodeArraySource::ImagePipelineNodeArraySource(std::size_t width, st          throw SaneException("The given array is too small (%zu bytes). Need at least %zu",                              data_.size(), size);      } -    set_remaining_bytes(size);  }  bool ImagePipelineNodeArraySource::get_next_row_data(std::uint8_t* out_data) @@ -161,21 +114,11 @@ bool ImagePipelineNodeArraySource::get_next_row_data(std::uint8_t* out_data)          return false;      } -    bool got_data = true; -      auto row_bytes = get_row_bytes(); -    auto bytes_to_ask = consume_remaining_bytes(row_bytes); -    if (bytes_to_ask < row_bytes) { -        got_data = false; -    } - -    std::memcpy(out_data, data_.data() + get_row_bytes() * next_row_, bytes_to_ask); +    std::memcpy(out_data, data_.data() + row_bytes * next_row_, row_bytes);      next_row_++; -    if (!got_data) { -        eof_ = true; -    } -    return got_data; +    return true;  } @@ -319,6 +262,50 @@ bool ImagePipelineNodeSwap16BitEndian::get_next_row_data(std::uint8_t* out_data)      return got_data;  } +ImagePipelineNodeInvert::ImagePipelineNodeInvert(ImagePipelineNode& source) : +    source_(source) +{ +} + +bool ImagePipelineNodeInvert::get_next_row_data(std::uint8_t* out_data) +{ +    bool got_data = source_.get_next_row_data(out_data); +    auto num_values = get_width() * get_pixel_channels(source_.get_format()); +    auto depth = get_pixel_format_depth(source_.get_format()); + +    switch (depth) { +        case 16: { +            auto* data = reinterpret_cast<std::uint16_t*>(out_data); +            for (std::size_t i = 0; i < num_values; ++i) { +                *data = 0xffff - *data; +                data++; +            } +            break; +        } +        case 8: { +            auto* data = out_data; +            for (std::size_t i = 0; i < num_values; ++i) { +                *data = 0xff - *data; +                data++; +            } +            break; +        } +        case 1: { +            auto* data = out_data; +            auto num_bytes = (num_values + 7) / 8; +            for (std::size_t i = 0; i < num_bytes; ++i) { +                *data = ~*data; +                data++; +            } +            break; +        } +        default: +            throw SaneException("Unsupported pixel depth"); +    } + +    return got_data; +} +  ImagePipelineNodeMergeMonoLines::ImagePipelineNodeMergeMonoLines(ImagePipelineNode& source,                                                                   ColorOrder color_order) :      source_(source), @@ -456,6 +443,12 @@ ImagePipelineNodeComponentShiftLines::ImagePipelineNodeComponentShiftLines(                                  static_cast<unsigned>(source.get_format()));      }      extra_height_ = *std::max_element(channel_shifts_.begin(), channel_shifts_.end()); +    height_ = source_.get_height(); +    if (extra_height_ > height_) { +        height_ = 0; +    } else { +        height_ -= extra_height_; +    }  }  bool ImagePipelineNodeComponentShiftLines::get_next_row_data(std::uint8_t* out_data) @@ -492,18 +485,13 @@ ImagePipelineNodePixelShiftLines::ImagePipelineNodePixelShiftLines(      pixel_shifts_{shifts},      buffer_{get_row_bytes()}  { -    DBG_HELPER(dbg); -    DBG(DBG_proc, "%s: shifts={", __func__); -    for (auto el : pixel_shifts_) { -        DBG(DBG_proc, " %zu", el); -    } -    DBG(DBG_proc, " }\n"); - -    if (pixel_shifts_.size() > MAX_SHIFTS) { -        throw SaneException("Unsupported number of shift configurations %zu", pixel_shifts_.size()); -    } -      extra_height_ = *std::max_element(pixel_shifts_.begin(), pixel_shifts_.end()); +    height_ = source_.get_height(); +    if (extra_height_ > height_) { +        height_ = 0; +    } else { +        height_ -= extra_height_; +    }  }  bool ImagePipelineNodePixelShiftLines::get_next_row_data(std::uint8_t* out_data) @@ -521,7 +509,8 @@ bool ImagePipelineNodePixelShiftLines::get_next_row_data(std::uint8_t* out_data)      auto format = get_format();      auto shift_count = pixel_shifts_.size(); -    std::array<std::uint8_t*, MAX_SHIFTS> rows; +    std::vector<std::uint8_t*> rows; +    rows.resize(shift_count, nullptr);      for (std::size_t irow = 0; irow < shift_count; ++irow) {          rows[irow] = buffer_.get_row_ptr(pixel_shifts_[irow]); @@ -536,6 +525,63 @@ bool ImagePipelineNodePixelShiftLines::get_next_row_data(std::uint8_t* out_data)      return got_data;  } +ImagePipelineNodePixelShiftColumns::ImagePipelineNodePixelShiftColumns( +        ImagePipelineNode& source, const std::vector<std::size_t>& shifts) : +    source_(source), +    pixel_shifts_{shifts} +{ +    width_ = source_.get_width(); +    extra_width_ = compute_pixel_shift_extra_width(width_, pixel_shifts_); +    if (extra_width_ > width_) { +        width_ = 0; +    } else { +        width_ -= extra_width_; +    } +    temp_buffer_.resize(source_.get_row_bytes()); +} + +bool ImagePipelineNodePixelShiftColumns::get_next_row_data(std::uint8_t* out_data) +{ +    if (width_ == 0) { +        throw SaneException("Attempt to read zero-width line"); +    } +    bool got_data = source_.get_next_row_data(temp_buffer_.data()); + +    auto format = get_format(); +    auto shift_count = pixel_shifts_.size(); + +    for (std::size_t x = 0, width = get_width(); x < width; x += shift_count) { +        for (std::size_t ishift = 0; ishift < shift_count && x + ishift < width; ishift++) { +            RawPixel pixel = get_raw_pixel_from_row(temp_buffer_.data(), x + pixel_shifts_[ishift], +                                                    format); +            set_raw_pixel_to_row(out_data, x + ishift, pixel, format); +        } +    } +    return got_data; +} + + +std::size_t compute_pixel_shift_extra_width(std::size_t source_width, +                                            const std::vector<std::size_t>& shifts) +{ +    // we iterate across pixel shifts and find the pixel that needs the maximum shift according to +    // source_width. +    int group_size = shifts.size(); +    int non_filled_group = source_width % shifts.size(); +    int extra_width = 0; + +    for (int i = 0; i < group_size; ++i) { +        int shift_groups = shifts[i] / group_size; +        int shift_rem = shifts[i] % group_size; + +        if (shift_rem < non_filled_group) { +            shift_groups--; +        } +        extra_width = std::max(extra_width, shift_groups * group_size + non_filled_group - i); +    } +    return extra_width; +} +  ImagePipelineNodeExtract::ImagePipelineNodeExtract(ImagePipelineNode& source,                                                     std::size_t offset_x, std::size_t offset_y,                                                     std::size_t width, std::size_t height) : @@ -666,16 +712,21 @@ bool ImagePipelineNodeExtract::get_next_row_data(std::uint8_t* out_data)  ImagePipelineNodeCalibrate::ImagePipelineNodeCalibrate(ImagePipelineNode& source,                                                         const std::vector<std::uint16_t>& bottom, -                                                       const std::vector<std::uint16_t>& top) : +                                                       const std::vector<std::uint16_t>& top, +                                                       std::size_t x_start) :      source_{source}  { -    auto size = std::min(bottom.size(), top.size()); +    std::size_t size = 0; +    if (bottom.size() >= x_start && top.size() >= x_start) { +        size = std::min(bottom.size() - x_start, top.size() - x_start); +    } +      offset_.reserve(size);      multiplier_.reserve(size);      for (std::size_t i = 0; i < size; ++i) { -        offset_.push_back(bottom[i] / 65535.0f); -        multiplier_.push_back(65535.0f / (top[i] - bottom[i])); +        offset_.push_back(bottom[i + x_start] / 65535.0f); +        multiplier_.push_back(65535.0f / (top[i + x_start] - bottom[i + x_start]));      }  } @@ -729,10 +780,8 @@ ImagePipelineNodeDebug::~ImagePipelineNodeDebug()          auto format = get_format();          buffer_.linearize(); -        sanei_genesys_write_pnm_file(path_.c_str(), buffer_.get_front_row_ptr(), -                                     get_pixel_format_depth(format), -                                     get_pixel_channels(format), -                                     get_width(), buffer_.height()); +        write_tiff_file(path_, buffer_.get_front_row_ptr(), get_pixel_format_depth(format), +                        get_pixel_channels(format), get_width(), buffer_.height());      });  } | 
