From f615a08edc4d662de969dad4e7f7cead4087df61 Mon Sep 17 00:00:00 2001 From: Naushir Patuck Date: Wed, 1 May 2024 10:46:27 +0100 Subject: [PATCH] backend: Allow users to set separate crops for each output For backward compatibility, we keep the existing BackEnd::SetCrop behaving the same and setting the same crop params for all outputs. Signed-off-by: Naushir Patuck --- src/libpisp/backend/backend.cpp | 11 +++++- src/libpisp/backend/backend.hpp | 1 + src/libpisp/backend/backend_prepare.cpp | 45 +++++++++++----------- src/libpisp/backend/pisp_be_config.h | 4 +- src/libpisp/backend/tiling/pisp_tiling.cpp | 11 ++++-- src/libpisp/backend/tiling/pisp_tiling.hpp | 6 +-- 6 files changed, 46 insertions(+), 32 deletions(-) diff --git a/src/libpisp/backend/backend.cpp b/src/libpisp/backend/backend.cpp index 6e704be..f1d7b3c 100644 --- a/src/libpisp/backend/backend.cpp +++ b/src/libpisp/backend/backend.cpp @@ -338,7 +338,16 @@ void BackEnd::GetGamma(pisp_be_gamma_config &gamma) void BackEnd::SetCrop(pisp_be_crop_config const &crop) { - be_config_.crop = crop; + for (unsigned int i = 0; i < variant_.BackEndNumBranches(0); i++) + be_config_.crop[i] = crop; + be_config_.dirty_flags_extra |= PISP_BE_DIRTY_CROP; + retile_ = true; +} + +void BackEnd::SetCrop(unsigned int i, pisp_be_crop_config const &crop) +{ + PISP_ASSERT(i < variant_.BackEndNumBranches(0)); + be_config_.crop[i] = crop; be_config_.dirty_flags_extra |= PISP_BE_DIRTY_CROP; retile_ = true; } diff --git a/src/libpisp/backend/backend.hpp b/src/libpisp/backend/backend.hpp index dd1d04d..5a42a9b 100644 --- a/src/libpisp/backend/backend.hpp +++ b/src/libpisp/backend/backend.hpp @@ -102,6 +102,7 @@ class BackEnd void SetGamma(pisp_be_gamma_config const &gamma); void GetGamma(pisp_be_gamma_config &gamma); void SetCrop(pisp_be_crop_config const &crop); + void SetCrop(unsigned int i, pisp_be_crop_config const &crop); void SetCsc(unsigned int i, pisp_be_ccm_config const &csc); void GetCsc(unsigned int i, pisp_be_ccm_config &csc); void SetOutputFormat(unsigned int i, pisp_be_output_format_config const &output_format); diff --git a/src/libpisp/backend/backend_prepare.cpp b/src/libpisp/backend/backend_prepare.cpp index 6db201d..08fc5cf 100644 --- a/src/libpisp/backend/backend_prepare.cpp +++ b/src/libpisp/backend/backend_prepare.cpp @@ -488,8 +488,8 @@ void BackEnd::finaliseConfig() if (enabled) { // crop is enabled when it contains non-zero width/height - uint16_t w = be_config_.crop.width ? be_config_.crop.width : be_config_.input_format.width; - uint16_t h = be_config_.crop.width ? be_config_.crop.height : be_config_.input_format.height; + uint16_t w = be_config_.crop[j].width ? be_config_.crop[j].width : be_config_.input_format.width; + uint16_t h = be_config_.crop[j].width ? be_config_.crop[j].height : be_config_.input_format.height; if (dirty_flags_rgb & PISP_BE_RGB_ENABLE_DOWNSCALE(j)) { @@ -535,18 +535,18 @@ void BackEnd::updateSmartResize() { std::string filter; - // First get the size of the input to the rescalers. The crops are zero when not in use. - uint16_t input_width = be_config_.crop.width; - if (!input_width) - input_width = be_config_.input_format.width; - uint16_t input_height = be_config_.crop.height; - if (!input_height) - input_height = be_config_.input_format.height; - // Look through the output branches adjusting the scaling blocks where "smart resizing" // has been requested. for (unsigned int i = 0; i < variant_.BackEndNumBranches(0); i++) { + // First get the size of the input to the rescalers. The crops are zero when not in use. + uint16_t input_width = be_config_.crop[i].width; + if (!input_width) + input_width = be_config_.input_format.width; + uint16_t input_height = be_config_.crop[i].height; + if (!input_height) + input_height = be_config_.input_format.height; + if ((smart_resize_dirty_ & (1 << i)) || (be_config_.dirty_flags_extra & PISP_BE_DIRTY_CROP)) { if (smart_resize_[i].width && smart_resize_[i].height) @@ -688,15 +688,16 @@ void BackEnd::updateTiles() PISP_LOG(debug, "Input alignments are " << tiling_config.input_alignment << " pixels"); tiling_config.input_image_size = tiling::Length2(c.input_format.width, c.input_format.height); - tiling_config.crop = tiling::Interval2(tiling::Interval(c.crop.offset_x, c.crop.width), - tiling::Interval(c.crop.offset_y, c.crop.height)); - - if (tiling_config.crop.x.length == 0 || tiling_config.crop.y.length == 0) - tiling_config.crop = tiling::Interval2(tiling::Interval(0, c.input_format.width), - tiling::Interval(0, c.input_format.height)); for (unsigned int i = 0; i < variant_.BackEndNumBranches(0); i++) { + tiling_config.crop[i] = tiling::Interval2(tiling::Interval(c.crop[i].offset_x, c.crop[i].width), + tiling::Interval(c.crop[i].offset_y, c.crop[i].height)); + + if (tiling_config.crop[i].x.length == 0 || tiling_config.crop[i].y.length == 0) + tiling_config.crop[i] = tiling::Interval2(tiling::Interval(0, c.input_format.width), + tiling::Interval(0, c.input_format.height)); + tiling_config.output_h_mirror[i] = be_config_.output_format[i].transform & PISP_BE_TRANSFORM_HFLIP; tiling_config.downscale_factor[i] = tiling::Length2(c.downscale[i].scale_factor_h, c.downscale[i].scale_factor_v); @@ -791,7 +792,7 @@ std::vector BackEnd::retilePipeline(TilingConfig const &tiling_config } tiling::Crop2 downscale_crop; - tiling::Interval2 resample_size = tiles[i].crop.output; + tiling::Interval2 resample_size = tiles[i].crop[j].output; resample_size.x = resample_size.x - tiles[i].resample[j].crop.x; resample_size.y = resample_size.y - tiles[i].resample[j].crop.y; @@ -799,17 +800,17 @@ std::vector BackEnd::retilePipeline(TilingConfig const &tiling_config // next block. Also there will be no extra crop necessary for the resize operation. if (be_config_.global.rgb_enables & PISP_BE_RGB_ENABLE_DOWNSCALE(j)) { - downscale_crop = tiles[i].downscale[j].crop + tiles[i].crop.crop; + downscale_crop = tiles[i].downscale[j].crop + tiles[i].crop[j].crop; // Size of the tile going into the resample block needs to be set here. resample_size = tiles[i].downscale[j].output; } else if (be_config_.global.rgb_enables & PISP_BE_RGB_ENABLE_RESAMPLE(j)) { - downscale_crop = tiles[i].resample[j].crop + tiles[i].crop.crop; + downscale_crop = tiles[i].resample[j].crop + tiles[i].crop[j].crop; } else { - downscale_crop = tiles[i].output[j].crop + tiles[i].crop.crop; + downscale_crop = tiles[i].output[j].crop + tiles[i].crop[j].crop; } t.crop_x_start[j] = downscale_crop.x.start; @@ -949,8 +950,8 @@ void BackEnd::getOutputSize(int i, uint16_t *width, uint16_t *height, pisp_image *width = be_config_.resample_extra[i].scaled_width, *height = be_config_.resample_extra[i].scaled_height; else if (be_config_.global.rgb_enables & PISP_BE_RGB_ENABLE_DOWNSCALE(i)) *width = be_config_.downscale_extra[i].scaled_width, *height = be_config_.downscale_extra[i].scaled_height; - else if (be_config_.crop.width) // crop width and height will be zero when crop disabled - *width = be_config_.crop.width, *height = be_config_.crop.height; + else if (be_config_.crop[i].width) // crop width and height will be zero when crop disabled + *width = be_config_.crop[i].width, *height = be_config_.crop[i].height; else *width = ifmt.width, *height = ifmt.height; } diff --git a/src/libpisp/backend/pisp_be_config.h b/src/libpisp/backend/pisp_be_config.h index 1fb39ca..b2ab007 100644 --- a/src/libpisp/backend/pisp_be_config.h +++ b/src/libpisp/backend/pisp_be_config.h @@ -451,7 +451,7 @@ typedef struct { pisp_be_downscale_extra downscale_extra[PISP_BACK_END_NUM_OUTPUTS]; pisp_be_resample_extra resample_extra[PISP_BACK_END_NUM_OUTPUTS]; - pisp_be_crop_config crop; + pisp_be_crop_config crop[PISP_BACK_END_NUM_OUTPUTS]; pisp_image_format_config hog_format; uint32_t dirty_flags_bayer; /* these use pisp_be_bayer_enable */ uint32_t dirty_flags_rgb; /* use pisp_be_rgb_enable */ @@ -523,9 +523,9 @@ typedef struct { static_assert(sizeof(pisp_tile) == 160, "pisp_tile not packed as expected"); typedef struct { - pisp_be_config config; pisp_tile tiles[PISP_BACK_END_NUM_TILES]; int num_tiles; + pisp_be_config config; } pisp_be_tiles_config; #endif /* _PISP_BE_CONFIG_H_ */ diff --git a/src/libpisp/backend/tiling/pisp_tiling.cpp b/src/libpisp/backend/tiling/pisp_tiling.cpp index c66c878..cd88d2a 100644 --- a/src/libpisp/backend/tiling/pisp_tiling.cpp +++ b/src/libpisp/backend/tiling/pisp_tiling.cpp @@ -56,11 +56,9 @@ void tile_pipeline(TilingConfig const &config, Tile *tiles, int num_tiles, Lengt Length2(PipelineAlignX, PipelineAlignY)); ContextStage context_stage("context", &input_stage, context_config, offsetof(Tile, context)); - CropStage::Config crop_config(config.crop); - CropStage crop_stage("crop", &context_stage, crop_config, offsetof(Tile, crop)); - - SplitStage split_stage("split", &crop_stage); + SplitStage split_stage("split", &context_stage); + std::unique_ptr crop_stages[NumOutputBranches]; std::unique_ptr downscale_stages[NumOutputBranches]; std::unique_ptr resample_stages[NumOutputBranches]; std::unique_ptr output_stages[NumOutputBranches]; @@ -74,6 +72,11 @@ void tile_pipeline(TilingConfig const &config, Tile *tiles, int num_tiles, Lengt char name[32]; Stage *prev_stage = &split_stage; + sprintf(name, "crop%d", i); + crop_stages[i] = std::unique_ptr( + new CropStage(name, prev_stage, config.crop[i], offsetof(Tile, crop) + i * sizeof(Region))); + prev_stage = crop_stages[i].get(); + // There's a little awkwardness if the resize blocks (downscale and resample) are not enabled. Resize *does* change the output tile // size, even if it's doing a 1-to-1 scaling (it loses context), so we must leave it out of the tiling // calculation. diff --git a/src/libpisp/backend/tiling/pisp_tiling.hpp b/src/libpisp/backend/tiling/pisp_tiling.hpp index 9e0b71c..ad3217e 100644 --- a/src/libpisp/backend/tiling/pisp_tiling.hpp +++ b/src/libpisp/backend/tiling/pisp_tiling.hpp @@ -22,7 +22,7 @@ struct Tile tiling::Region input; tiling::Region decompress; tiling::Region context; - tiling::Region crop; + tiling::Region crop[NumOutputBranches]; tiling::Region downscale[NumOutputBranches]; tiling::Region resample[NumOutputBranches]; tiling::Region output[NumOutputBranches]; @@ -31,7 +31,7 @@ struct Tile struct TilingConfig { tiling::Length2 input_image_size; - tiling::Interval2 crop; + tiling::Interval2 crop[NumOutputBranches]; tiling::Length2 downscale_image_size[NumOutputBranches]; tiling::Length2 output_image_size[NumOutputBranches]; tiling::Length2 max_tile_size; @@ -51,9 +51,9 @@ inline std::ostream &operator<<(std::ostream &os, TilingConfig const &tc) { os << "TilingConfig:" << std::endl; os << "\tinput_image_size " << tc.input_image_size << " align " << tc.input_alignment << std::endl; - os << "\tcrop " << tc.crop << std::endl; for (int i = 0; i < NumOutputBranches; i++) { + os << "\tcrop[" << i << "] " << tc.crop[i] << std::endl; os << "\toutput_image_size[" << i << "] " << tc.output_image_size[i] << " align max " << tc.output_max_alignment[i] << " min " << tc.output_min_alignment[i] << std::endl; os << "\tdownscale_image_size " << tc.downscale_image_size[i] << " downscale_factor " << tc.downscale_factor[i]