RISP4ML: further optimize memory allocation and usage This change further optimizes memory allocation/usage for RISP4ML. It enables in-place operations in RISP4ML stages whenever possible and minimizes use of "malloc". Unit tests are also updated accordingly. The change has been verified by comparing output@plain-C risp4ml against output@google3. All unit tests are passed. Change-Id: I93ec0c97f75c36be764bc65e4a886f725e0b2a9a
diff --git a/samples/risp4ml/isp_stages/blc.c b/samples/risp4ml/isp_stages/blc.c index 26e36b5..61d8c47 100644 --- a/samples/risp4ml/isp_stages/blc.c +++ b/samples/risp4ml/isp_stages/blc.c
@@ -6,23 +6,14 @@ void set_blc_params(BlcParams* params) { blc_params = *params; } -void blc_process(Image* input, Image* output) { - if (!blc_params.enable) { - *output = *input; - return; - } +void blc_process(Image* img) { + if (!blc_params.enable) return; - uint16_t height = input->height; - uint16_t width = input->width; - - for (uint16_t y = 0; y < height; ++y) { - const pixel_type_t* in_line = image_row(input, 0, y); - pixel_type_t* out_line = image_row(output, 0, y); - - for (uint16_t x = 0; x < width; ++x) { + for (uint16_t y = 0; y < img->height; ++y) { + pixel_type_t* line = image_row(img, 0, y); + for (uint16_t x = 0; x < img->width; ++x) { BayerIndex bayer_index = GetBayerIndex(kBayerType, x, y); - out_line[x] = - SubUnsignedZeroClamp(in_line[x], blc_params.offsets[bayer_index]); + line[x] = SubUnsignedZeroClamp(line[x], blc_params.offsets[bayer_index]); } } }
diff --git a/samples/risp4ml/isp_stages/blc.h b/samples/risp4ml/isp_stages/blc.h index 4ad1466..e4c9555 100644 --- a/samples/risp4ml/isp_stages/blc.h +++ b/samples/risp4ml/isp_stages/blc.h
@@ -14,7 +14,7 @@ void set_blc_params(BlcParams* params); -void blc_process(Image* input, Image* output); +void blc_process(Image* img); #ifdef __cplusplus } // extern "C"
diff --git a/samples/risp4ml/isp_stages/blc_test.cc b/samples/risp4ml/isp_stages/blc_test.cc index 1935048..ddd782b 100644 --- a/samples/risp4ml/isp_stages/blc_test.cc +++ b/samples/risp4ml/isp_stages/blc_test.cc
@@ -10,11 +10,14 @@ protected: void SetUp() override { in_ = image_new(1, kFrameSize, kFrameSize); - out_ = image_new(1, kFrameSize, kFrameSize); InitImageRandom(in_, 0, kRawPipelineMaxVal); // Force max/min values to be included. *image_pixel(in_, 0, 0, 0) = 0; *image_pixel(in_, 0, 0, 1) = kRawPipelineMaxVal; + out_ = image_new(1, kFrameSize, kFrameSize); + const uint32_t num_bytes = + in_->num_channels * in_->height * in_->width * sizeof(pixel_type_t); + memcpy(out_->data, in_->data, num_bytes); } void TearDown() override { image_delete(in_); @@ -29,7 +32,7 @@ BlcParams params = {.enable = false, .offsets = {20, 20, 20, 20}}; set_blc_params(¶ms); - blc_process(in_, out_); + blc_process(out_); // Expect no change for (uint16_t c = 0; c < in_->num_channels; ++c) { @@ -47,7 +50,7 @@ BlcParams params = {.enable = true, .offsets = {0, 0, 0, 0}}; set_blc_params(¶ms); - blc_process(in_, out_); + blc_process(out_); // Expect no change for (uint16_t c = 0; c < in_->num_channels; ++c) { @@ -67,7 +70,7 @@ kRawPipelineMaxVal, kRawPipelineMaxVal}}; set_blc_params(¶ms); - blc_process(in_, out_); + blc_process(out_); // Expect correct subtraction for (uint16_t c = 0; c < in_->num_channels; ++c) {
diff --git a/samples/risp4ml/isp_stages/dg.c b/samples/risp4ml/isp_stages/dg.c index 73f7f46..fbb66b8 100644 --- a/samples/risp4ml/isp_stages/dg.c +++ b/samples/risp4ml/isp_stages/dg.c
@@ -9,28 +9,20 @@ void set_dg_params(DgParams* params) { dg_params = *params; } -void dg_process(Image* input, Image* output) { - if (!dg_params.enable) { - *output = *input; - return; - } +void dg_process(Image* img) { + if (!dg_params.enable) return; - uint16_t height = input->height; - uint16_t width = input->width; + for (uint16_t y = 0; y < img->height; ++y) { + pixel_type_t* line = image_row(img, 0, y); - for (uint16_t y = 0; y < height; ++y) { - const pixel_type_t* in_line = image_row(input, 0, y); - pixel_type_t* out_line = image_row(output, 0, y); - - for (uint16_t x = 0; x < width; ++x) { + for (uint16_t x = 0; x < img->width; ++x) { BayerIndex bayer_index = GetBayerIndex(kBayerType, x, y); - uint16_t input_val = in_line[x]; // + (1 << (kDgFractional -1)) adds 0.5 for more accurate rounding - uint32_t scaled_pixel = - input_val * dg_params.gains[bayer_index] + (1 << (kDgFractional - 1)); + uint32_t scaled_pixel = (uint32_t)line[x] * dg_params.gains[bayer_index] + + (1 << (kDgFractional - 1)); - out_line[x] = (pixel_type_t)Clamp(scaled_pixel >> kDgFractional, 0, - kRawPipelineMaxVal); + line[x] = (pixel_type_t)Clamp(scaled_pixel >> kDgFractional, 0, + kRawPipelineMaxVal); } } }
diff --git a/samples/risp4ml/isp_stages/dg.h b/samples/risp4ml/isp_stages/dg.h index 1a0bc1b..5979019 100644 --- a/samples/risp4ml/isp_stages/dg.h +++ b/samples/risp4ml/isp_stages/dg.h
@@ -14,7 +14,7 @@ void set_dg_params(DgParams* params); -void dg_process(Image* input, Image* output); +void dg_process(Image* img); #ifdef __cplusplus } // extern "C"
diff --git a/samples/risp4ml/isp_stages/dg_test.cc b/samples/risp4ml/isp_stages/dg_test.cc index cf3b7dc..41bf18e 100644 --- a/samples/risp4ml/isp_stages/dg_test.cc +++ b/samples/risp4ml/isp_stages/dg_test.cc
@@ -12,6 +12,8 @@ void SetUp() override { in_ = image_new(1, kFrameSize, kFrameSize); out_ = image_new(1, kFrameSize, kFrameSize); + num_bytes_ = + in_->num_channels * in_->height * in_->width * sizeof(pixel_type_t); } void TearDown() override { image_delete(in_); @@ -20,17 +22,19 @@ Image* in_; Image* out_; + uint32_t num_bytes_; }; TEST_F(DgTest, Bypass) { InitImage(in_, 1); + memcpy(out_->data, in_->data, num_bytes_); // Set gain to 2x, gain is in 8.16 format. uint16_t gain = 2 << kDgFractional; DgParams params = {.enable = false, .gains = {gain, gain, gain, gain}}; set_dg_params(¶ms); - dg_process(in_, out_); + dg_process(out_); // Expect no change. for (uint16_t c = 0; c < in_->num_channels; ++c) { @@ -49,13 +53,14 @@ // Force max/min values to be included. *image_pixel(in_, 0, 0, 0) = 0; *image_pixel(in_, 0, 0, 1) = kRawPipelineMaxVal; + memcpy(out_->data, in_->data, num_bytes_); // Set gain to 1x, gain is in_ 8.8 format. uint16_t gain = 1 << kDgFractional; DgParams params = {.enable = true, .gains = {gain, gain, gain, gain}}; set_dg_params(¶ms); - dg_process(in_, out_); + dg_process(out_); // Expect no change. for (uint16_t c = 0; c < in_->num_channels; ++c) { @@ -75,13 +80,14 @@ // Force max/min values to be included. *image_pixel(in_, 0, 0, 0) = kRawPipelineMinVal / 2; *image_pixel(in_, 0, 0, 1) = kRawPipelineMaxVal / 2; + memcpy(out_->data, in_->data, num_bytes_); // Set gain to 2x, gain is in_ 8.16 format. uint16_t gain = 2 << kDgFractional; DgParams params = {.enable = true, .gains = {gain, gain, gain, gain}}; set_dg_params(¶ms); - dg_process(in_, out_); + dg_process(out_); // Expect all pixel values to be doubled, as no clipping. for (uint16_t c = 0; c < in_->num_channels; ++c) { @@ -97,13 +103,14 @@ TEST_F(DgTest, ClampHighRandomPixel) { // Init image with range of values that will clamp to max with 2x gain. InitImageRandom(in_, kRawPipelineMaxVal / 2, kRawPipelineMaxVal); + memcpy(out_->data, in_->data, num_bytes_); // Set gain to 2x, gain is in_ 8.16 format. uint16_t gain = 2 << kDgFractional; DgParams params = {.enable = true, .gains = {gain, gain, gain, gain}}; set_dg_params(¶ms); - dg_process(in_, out_); + dg_process(out_); // Expect all pixel values to be clamped high. for (uint16_t c = 0; c < in_->num_channels; ++c) { @@ -118,13 +125,14 @@ TEST_F(DgTest, ClampLowRandomPixel) { // Init image with range of values that will clamp to min with 2x gain. InitImageRandom(in_, kRawPipelineMinVal / 2, kRawPipelineMinVal); + memcpy(out_->data, in_->data, num_bytes_); // Set gain to 2x, gain is in_ 8.8 format. uint16_t gain = 2 << kDgFractional; DgParams params = {.enable = true, .gains = {gain, gain, gain, gain}}; set_dg_params(¶ms); - dg_process(in_, out_); + dg_process(out_); // Expect all pixel values to be clamped low. for (uint16_t c = 0; c < in_->num_channels; ++c) { @@ -147,6 +155,7 @@ } } } + memcpy(out_->data, in_->data, num_bytes_); // Set gain to max gain, 0xFFFF in_ 8.8 format, approximately 256. constexpr uint32_t kMaxGain = @@ -155,7 +164,7 @@ .gains = {kMaxGain, kMaxGain, kMaxGain, kMaxGain}}; set_dg_params(¶ms); - dg_process(in_, out_); + dg_process(out_); // Expect values 1, 2, ... 64 to be gained by 256, 128 and above to clip. for (uint16_t c = 0; c < in_->num_channels; ++c) { @@ -179,12 +188,13 @@ } } } + memcpy(out_->data, in_->data, num_bytes_); // Set gain to min non-zero gain, 0x000001 in_ 8.8 format, 1/256. DgParams params = {.enable = true, .gains = {1, 1, 1, 1}}; set_dg_params(¶ms); - dg_process(in_, out_); + dg_process(out_); constexpr uint32_t kExpectedOutput[] = {0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 4, 8, 16, 32, 64, 128}; @@ -210,12 +220,13 @@ } } } + memcpy(out_->data, in_->data, num_bytes_); // Set gain to min useful gain, 0x000002 in_ 8.8 format, 1/256. DgParams params = {.enable = true, .gains = {2, 2, 2, 2}}; set_dg_params(¶ms); - dg_process(in_, out_); + dg_process(out_); // Expect all output values < 128 to be zero, 128->1, 256->2. constexpr uint32_t kExpectedOutput[] = {0, 0, 0, 0, 0, 0, 1, 1, @@ -232,12 +243,13 @@ TEST_F(DgTest, ZeroGainRandomInput) { // Init image with range of values. InitImageRandom(in_, kRawPipelineMinVal, kRawPipelineMinVal); + memcpy(out_->data, in_->data, num_bytes_); // Set gain to 0x, gain is in_ 8.16 format. DgParams params = {.enable = true, .gains = {0, 0, 0, 0}}; set_dg_params(¶ms); - dg_process(in_, out_); + dg_process(out_); // Expect all output values to be zero. for (uint16_t c = 0; c < in_->num_channels; ++c) {
diff --git a/samples/risp4ml/isp_stages/gamma.c b/samples/risp4ml/isp_stages/gamma.c index f0e9f51..81cde21 100644 --- a/samples/risp4ml/isp_stages/gamma.c +++ b/samples/risp4ml/isp_stages/gamma.c
@@ -27,60 +27,53 @@ void set_gamma_params(GammaParams* params) { gamma_params = *params; } -void gamma_process(Image* input, Image* output) { - uint16_t height = input->height; - uint16_t width = input->width; +void gamma_process(Image* img) { + if (!gamma_params.enable) return; - const pixel_type_t* in_line[kRgbColorChannels]; - pixel_type_t* out_line[kRgbColorChannels]; + pixel_type_t* line[kRgbColorChannels]; - for (uint16_t y = 0; y < height; ++y) { + for (uint16_t y = 0; y < img->height; ++y) { for (uint16_t c = 0; c < kRgbColorChannels; ++c) { - in_line[c] = image_row(input, c, y); - out_line[c] = image_row(output, c, y); + line[c] = image_row(img, c, y); } - for (uint16_t x = 0; x < width; ++x) { + for (uint16_t x = 0; x < img->width; ++x) { for (uint16_t c = 0; c < kRgbColorChannels; ++c) { - if (!gamma_params.enable) { - out_line[c][x] = in_line[c][x]; - } else { - pixel_type_t pixel_val = - (pixel_type_t)Clamp(in_line[c][x], 0, kRgbPipelineMaxVal); + pixel_type_t pixel_val = + (pixel_type_t)Clamp(line[c][x], 0, kRgbPipelineMaxVal); - // Determine segment - int segment_index = - (kGammaNumberSegments - 1) - - ClzMsb(pixel_val, kRgbPipelineBpp, kGammaNumberSegments - 1); - uint16_t segment_left = - segment_index ? 1 << (kRgbPipelineBpp - - kGammaLogSegmentOffsets[segment_index]) - : 0; + // Determine segment + int segment_index = + (kGammaNumberSegments - 1) - + ClzMsb(pixel_val, kRgbPipelineBpp, kGammaNumberSegments - 1); + uint16_t segment_left = + segment_index ? 1 << (kRgbPipelineBpp - + kGammaLogSegmentOffsets[segment_index]) + : 0; - // Bin index - int bin_index = ((pixel_val - segment_left) >> - kGammaLogSegmentSpacing[segment_index]) + - kGammaSegmentLutOffset[segment_index]; + // Bin index + int bin_index = ((pixel_val - segment_left) >> + kGammaLogSegmentSpacing[segment_index]) + + kGammaSegmentLutOffset[segment_index]; - int offset_within_bin = - (pixel_val - segment_left) & - ((1 << kGammaLogSegmentSpacing[segment_index]) - 1); + int offset_within_bin = + (pixel_val - segment_left) & + ((1 << kGammaLogSegmentSpacing[segment_index]) - 1); - uint16_t l_val = gamma_params.lut[bin_index]; - uint16_t r_val = gamma_params.lut[bin_index + 1]; + uint16_t l_val = gamma_params.lut[bin_index]; + uint16_t r_val = gamma_params.lut[bin_index + 1]; - uint16_t bin_size = 1 << kGammaLogSegmentSpacing[segment_index]; + uint16_t bin_size = 1 << kGammaLogSegmentSpacing[segment_index]; - uint32_t lerp_val = (l_val * (bin_size - offset_within_bin) + - r_val * offset_within_bin + (bin_size >> 1)) >> - kGammaLogSegmentSpacing[segment_index]; + uint32_t lerp_val = (l_val * (bin_size - offset_within_bin) + + r_val * offset_within_bin + (bin_size >> 1)) >> + kGammaLogSegmentSpacing[segment_index]; - // Clamping is not requied - // TODO(alexkaplan): The comment above is from gChips source. - // this calc needs to be checked carefully: - // - out_line[c][x] = (pixel_type_t)lerp_val; - } + // Clamping is not requied + // TODO(alexkaplan): The comment above is from gChips source. + // this calc needs to be checked carefully: + // + line[c][x] = (pixel_type_t)lerp_val; } } }
diff --git a/samples/risp4ml/isp_stages/gamma.h b/samples/risp4ml/isp_stages/gamma.h index ad6d61e..4ef3777 100644 --- a/samples/risp4ml/isp_stages/gamma.h +++ b/samples/risp4ml/isp_stages/gamma.h
@@ -16,7 +16,7 @@ void set_gamma_params(GammaParams* params); -void gamma_process(Image* input, Image* output); +void gamma_process(Image* img); #ifdef __cplusplus } // extern "C"
diff --git a/samples/risp4ml/isp_stages/gamma_test.cc b/samples/risp4ml/isp_stages/gamma_test.cc index 9adc32c..cbf4a94 100644 --- a/samples/risp4ml/isp_stages/gamma_test.cc +++ b/samples/risp4ml/isp_stages/gamma_test.cc
@@ -33,7 +33,6 @@ protected: void setup(uint16_t width) { in_ = image_new(3, 2, width); - out_ = image_new(3, 2, width); for (uint16_t c = 0; c < in_->num_channels; ++c) { for (uint16_t y = 0; y < in_->height; ++y) { for (uint16_t x = 0; x < in_->width; ++x) { @@ -41,6 +40,10 @@ } } } + out_ = image_new(3, 2, width); + const uint32_t num_bytes = + in_->num_channels * in_->height * in_->width * sizeof(pixel_type_t); + memcpy(out_->data, in_->data, num_bytes); } void TearDown() override { image_delete(in_); @@ -63,7 +66,7 @@ set_gamma_params(¶ms); - gamma_process(in_, out_); + gamma_process(out_); for (uint16_t c = 0; c < in_->num_channels; ++c) { for (uint16_t y = 0; y < in_->height; ++y) { @@ -81,7 +84,7 @@ set_gamma_params(&linear_params); - gamma_process(in_, out_); + gamma_process(out_); for (uint16_t c = 0; c < in_->num_channels; ++c) { for (uint16_t y = 0; y < in_->height; ++y) { @@ -100,7 +103,7 @@ set_gamma_params(&rgb_params); - gamma_process(in_, out_); + gamma_process(out_); for (uint16_t c = 0; c < in_->num_channels; ++c) { for (uint16_t y = 0; y < in_->height; ++y) {
diff --git a/samples/risp4ml/isp_stages/wbg.c b/samples/risp4ml/isp_stages/wbg.c index 3e84fb2..f38135a 100644 --- a/samples/risp4ml/isp_stages/wbg.c +++ b/samples/risp4ml/isp_stages/wbg.c
@@ -15,13 +15,8 @@ void set_wbg_params(WbgParams* params) { wbg_params = *params; } -static void compute_wbg_gain(Image* input) { +static void compute_wbg_gain(Image* img) { // Calculate the white-balance gain values using the "gray world" algorithm - uint16_t height = input->height; - uint16_t width = input->width; - - pixel_type_t* in_line; - int64_t sum_of_reds = 0; uint32_t num_of_reds = 0; // will use only one of the greens for scaling, since the difference between @@ -31,25 +26,25 @@ int64_t sum_of_blues = 0; uint32_t num_of_blues = 0; - for (uint16_t y = 0; y < height; ++y) { - in_line = image_row(input, 0, y); - for (uint16_t x = 0; x < width; ++x) { + for (uint16_t y = 0; y < img->height; ++y) { + pixel_type_t* line = image_row(img, 0, y); + for (uint16_t x = 0; x < img->width; ++x) { BayerIndex bayer_index = GetBayerIndex(kBayerType, x, y); switch (bayer_index) { case (kR): { - sum_of_reds += in_line[x]; + sum_of_reds += line[x]; num_of_reds++; }; break; case (kGr): { - sum_of_greens += in_line[x]; + sum_of_greens += line[x]; num_of_greens++; }; break; case (kGb): { - sum_of_greens += in_line[x]; + sum_of_greens += line[x]; num_of_greens++; }; break; case (kB): { - sum_of_blues += in_line[x]; + sum_of_blues += line[x]; num_of_blues++; }; break; default: { @@ -83,34 +78,23 @@ wbg_params.gains[3] = blue_wb; } -void wbg_process(Image* input, Image* output) { - if (!wbg_params.enable) { - *output = *input; - return; - } - - uint16_t height = input->height; - uint16_t width = input->width; - - const pixel_type_t* in_line; - pixel_type_t* out_line; - +void wbg_process(Image* img) { + if (!wbg_params.enable) return; if (!wbg_params.fixed) { - compute_wbg_gain(input); + compute_wbg_gain(img); } - for (uint16_t y = 0; y < height; ++y) { - in_line = image_row(input, 0, y); - out_line = image_row(output, 0, y); + for (uint16_t y = 0; y < img->height; ++y) { + pixel_type_t* line = image_row(img, 0, y); - for (uint16_t x = 0; x < width; ++x) { + for (uint16_t x = 0; x < img->width; ++x) { BayerIndex bayer_index = GetBayerIndex(kBayerType, x, y); - uint32_t input_val = in_line[x]; + uint32_t input_val = (uint32_t)line[x]; uint32_t scaled_pixel = (input_val * wbg_params.gains[bayer_index] + (1 << (kWbgFractional - 1))) >> kWbgFractional; - out_line[x] = (pixel_type_t)Clamp(scaled_pixel, kRawPipelineMinVal, - kRawPipelineMaxVal); + line[x] = (pixel_type_t)Clamp(scaled_pixel, kRawPipelineMinVal, + kRawPipelineMaxVal); } } }
diff --git a/samples/risp4ml/isp_stages/wbg.h b/samples/risp4ml/isp_stages/wbg.h index 2af1b84..8c8d9b4 100644 --- a/samples/risp4ml/isp_stages/wbg.h +++ b/samples/risp4ml/isp_stages/wbg.h
@@ -15,7 +15,7 @@ void set_wbg_params(WbgParams* params); -void wbg_process(Image* input, Image* output); +void wbg_process(Image* img); #ifdef __cplusplus } // extern "C"
diff --git a/samples/risp4ml/isp_stages/wbg_test.cc b/samples/risp4ml/isp_stages/wbg_test.cc index 012a5c7..52695a0 100644 --- a/samples/risp4ml/isp_stages/wbg_test.cc +++ b/samples/risp4ml/isp_stages/wbg_test.cc
@@ -13,6 +13,8 @@ void SetUp() override { in_ = image_new(1, kFrameHeight, kFrameWidth); out_ = image_new(1, kFrameHeight, kFrameWidth); + num_bytes_ = + in_->num_channels * in_->height * in_->width * sizeof(pixel_type_t); } void TearDown() override { image_delete(in_); @@ -21,11 +23,13 @@ Image* in_; Image* out_; + uint32_t num_bytes_; }; TEST_F(WbgTest, IdentityTest) { // Use a grey input image. InitImageRandom(in_, kRawPipelineMinVal, kRawPipelineMaxVal); + memcpy(out_->data, in_->data, num_bytes_); // set the params to something boring. uint32_t gain = 1 << kWbgFractional; @@ -33,7 +37,7 @@ .enable = true, .fixed = true, .gains = {gain, gain, gain, gain}}; set_wbg_params(¶ms); - wbg_process(in_, out_); + wbg_process(out_); for (uint16_t y = 0; y < kFrameHeight; y++) { for (uint16_t x = 0; x < kFrameWidth; x++) { ASSERT_EQ(image_pixel_val(in_, 0, y, x), image_pixel_val(out_, 0, y, x)); @@ -45,6 +49,7 @@ // Use a grey input image. constexpr pixel_type_t kPixelVal = 1 << kWbgFractional; InitImage(in_, kPixelVal); + memcpy(out_->data, in_->data, num_bytes_); // set the params to something boring. WbgParams params = {.enable = true, @@ -52,7 +57,7 @@ .gains = {kPixelVal, kPixelVal, kPixelVal, kPixelVal}}; set_wbg_params(¶ms); - wbg_process(in_, out_); + wbg_process(out_); for (uint16_t c1 = 0; c1 < 2; ++c1) { for (uint16_t c2 = 0; c2 < 2; ++c2) { @@ -70,13 +75,14 @@ // Use a grey input image. constexpr pixel_type_t kPixelValHi = kRawPipelineMaxVal - 10; InitImage(in_, kPixelValHi); + memcpy(out_->data, in_->data, num_bytes_); uint32_t gain = 2 * (1 << kWbgFractional); WbgParams params = { .enable = true, .fixed = true, .gains = {gain, gain, gain, gain}}; set_wbg_params(¶ms); - wbg_process(in_, out_); + wbg_process(out_); for (uint16_t y = 0; y < kFrameHeight; y++) { for (uint16_t x = 0; x < kFrameWidth; x++) {
diff --git a/samples/risp4ml/pipeline/pipeline.c b/samples/risp4ml/pipeline/pipeline.c index ec561b2..bca482d 100644 --- a/samples/risp4ml/pipeline/pipeline.c +++ b/samples/risp4ml/pipeline/pipeline.c
@@ -8,36 +8,35 @@ #include "samples/risp4ml/pipeline/pipeline.h" void isp_pipeline(ImageU8 *input, ImageU8 *output) { - Image *input_image = + Image *img_bayer = image_new(input->num_channels, input->height, input->width); // shift the 8bits wide input to 16bits (the processing pipeline bitwidth) - uint32_t input_dimensions = + const uint32_t input_dimensions = input->num_channels * input->height * input->width; for (uint32_t i = 0; i < input_dimensions; ++i) { - input_image->data[i] = input->data[i] << kRawPipelineFraction; // 8 + img_bayer->data[i] = input->data[i] << kRawPipelineFraction; // 8 } - Image *image1 = image_new(input->num_channels, input->height, input->width); - blc_process(input_image, image1); - image_delete(input_image); + // black level offset (in-place) + blc_process(img_bayer); - Image *image2 = image_new(input->num_channels, input->height, input->width); - dg_process(image1, image2); - image_delete(image1); + // digital gain (in-place) + dg_process(img_bayer); - Image *image3 = image_new(input->num_channels, input->height, input->width); - wbg_process(image2, image3); - image_delete(image2); + // white balance gain (in-place) + wbg_process(img_bayer); - Image *image4 = image_new(output->num_channels, input->height, input->width); - demosaic_process(image3, image4); - image_delete(image3); + // demosaic + Image *img_color = + image_new(output->num_channels, input->height, input->width); + demosaic_process(img_bayer, img_color); + image_delete(img_bayer); - Image *image5 = image_new(output->num_channels, input->height, input->width); - gamma_process(image4, image5); - image_delete(image4); + // gamma correction (in-place) + gamma_process(img_color); - set_downscale_factor(image5, output); - downscale_process(image5, output); - image_delete(image5); + // downscaler + set_downscale_factor(img_color, output); + downscale_process(img_color, output); + image_delete(img_color); }