diff options
Diffstat (limited to 'gpr/source/lib/vc5_decoder/raw.c')
-rwxr-xr-x | gpr/source/lib/vc5_decoder/raw.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/gpr/source/lib/vc5_decoder/raw.c b/gpr/source/lib/vc5_decoder/raw.c new file mode 100755 index 0000000..7cbac6f --- /dev/null +++ b/gpr/source/lib/vc5_decoder/raw.c @@ -0,0 +1,135 @@ +/*! @file raw.c + * + * @brief Definition of routines for packing a row of pixels into a RAW image. + * + * (C) Copyright 2018 GoPro Inc (http://gopro.com/). + * + * Licensed under either: + * - Apache License, Version 2.0, http://www.apache.org/licenses/LICENSE-2.0 + * - MIT license, http://opensource.org/licenses/MIT + * at your option. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "headers.h" + +/*! + @brief Pack the component arrays into an output image + + The inverse component transform for Bayer images (VC-5 Part 3) + is applied to the component arrays before combining the values + into a packed image. + */ +CODEC_ERROR PackComponentsToRAW(const UNPACKED_IMAGE *image, + PIXEL *output_buffer, size_t output_pitch, + DIMENSION width, DIMENSION height, + ENABLED_PARTS enabled_parts, uint16_t output_bit_depth, PIXEL_FORMAT output_format ) +{ + // Define pointers to the rows for each input component + COMPONENT_VALUE *GS_input_buffer; + COMPONENT_VALUE *RG_input_buffer; + COMPONENT_VALUE *BG_input_buffer; + COMPONENT_VALUE *GD_input_buffer; + + // Define pointers to the rows for each output component + uint16_t *output_row1_ptr; + uint16_t *output_row2_ptr; + + //size_t input_quarter_pitch; + size_t output_half_pitch; + + int row; + + GS_input_buffer = image->component_array_list[0].data; + RG_input_buffer = image->component_array_list[1].data; + BG_input_buffer = image->component_array_list[2].data; + GD_input_buffer = image->component_array_list[3].data; + + // Compute the distance between the half rows in the Bayer grid + output_half_pitch = output_pitch / 2; + + for (row = 0; row < height; row++) + { + COMPONENT_VALUE *GS_input_row_ptr = (COMPONENT_VALUE *)((uintptr_t)GS_input_buffer + row * image->component_array_list[0].pitch); + COMPONENT_VALUE *RG_input_row_ptr = (COMPONENT_VALUE *)((uintptr_t)RG_input_buffer + row * image->component_array_list[1].pitch); + COMPONENT_VALUE *BG_input_row_ptr = (COMPONENT_VALUE *)((uintptr_t)BG_input_buffer + row * image->component_array_list[2].pitch); + COMPONENT_VALUE *GD_input_row_ptr = (COMPONENT_VALUE *)((uintptr_t)GD_input_buffer + row * image->component_array_list[3].pitch); + + uint8_t *output_row_ptr = (uint8_t *)output_buffer + row * output_pitch; + + const int32_t midpoint = 2048; + + int column; + + output_row1_ptr = (uint16_t *)output_row_ptr; + output_row2_ptr = (uint16_t *)(output_row_ptr + output_half_pitch); + + // Pack the rows of Bayer components into the BYR4 pattern + for (column = 0; column < width; column++) + { + int32_t GS, RG, BG, GD; + int32_t R, G1, G2, B; + + GS = GS_input_row_ptr[column]; + RG = RG_input_row_ptr[column]; + BG = BG_input_row_ptr[column]; + GD = GD_input_row_ptr[column]; + + // Convert unsigned values to signed values + GD -= midpoint; + RG -= midpoint; + BG -= midpoint; + + R = (RG << 1) + GS; + B = (BG << 1) + GS; + G1 = GS + GD; + G2 = GS - GD; + + R = clamp_uint(R, 12); + G1 = clamp_uint(G1, 12); + G2 = clamp_uint(G2, 12); + B = clamp_uint(B, 12); + + // Apply inverse protune log curve + R = DecoderLogCurve[R]; + B = DecoderLogCurve[B]; + G1 = DecoderLogCurve[G1]; + G2 = DecoderLogCurve[G2]; + + R >>= (16 - output_bit_depth); + B >>= (16 - output_bit_depth); + G1 >>= (16 - output_bit_depth); + G2 >>= (16 - output_bit_depth); + + switch (output_format) + { + case PIXEL_FORMAT_RAW_RGGB_12: + case PIXEL_FORMAT_RAW_RGGB_14: + output_row1_ptr[2 * column + 0] = (uint16_t)R; + output_row1_ptr[2 * column + 1] = (uint16_t)G1; + output_row2_ptr[2 * column + 0] = (uint16_t)G2; + output_row2_ptr[2 * column + 1] = (uint16_t)B; + break; + + case PIXEL_FORMAT_RAW_GBRG_12: + case PIXEL_FORMAT_RAW_GBRG_14: + output_row1_ptr[2 * column + 0] = (uint16_t)G1; + output_row1_ptr[2 * column + 1] = (uint16_t)B; + output_row2_ptr[2 * column + 0] = (uint16_t)R; + output_row2_ptr[2 * column + 1] = (uint16_t)G2; + break; + + default: + assert(0); + break; + } + } + } + + return CODEC_ERROR_OKAY; +} |