diff --git a/libheif/api/libheif/heif.cc b/libheif/api/libheif/heif.cc index ca98e7c4b7..ad62025ddd 100644 --- a/libheif/api/libheif/heif.cc +++ b/libheif/api/libheif/heif.cc @@ -1806,11 +1806,8 @@ int heif_image_has_channel(const struct heif_image* img, enum heif_channel chann struct heif_error heif_image_add_plane(struct heif_image* image, heif_channel channel, int width, int height, int bit_depth) { - if (!image->image->add_plane(channel, width, height, bit_depth)) { - struct heif_error err = {heif_error_Memory_allocation_error, - heif_suberror_Unspecified, - "Cannot allocate memory for image plane"}; - return err; + if (auto err = image->image->add_plane2(channel, width, height, bit_depth)) { + return err.error_struct(image->image.get()); } else { return heif_error_success; @@ -1997,11 +1994,9 @@ int heif_image_is_premultiplied_alpha(struct heif_image* image) struct heif_error heif_image_extend_padding_to_size(struct heif_image* image, int min_physical_width, int min_physical_height) { - bool mem_alloc_success = image->image->extend_padding_to_size(min_physical_width, min_physical_height); - if (!mem_alloc_success) { - return heif_error{heif_error_Memory_allocation_error, - heif_suberror_Unspecified, - "Cannot allocate image memory."}; + Error err = image->image->extend_padding_to_size2(min_physical_width, min_physical_height); + if (err) { + return err.error_struct(image->image.get()); } else { return heif_error_success; @@ -2031,11 +2026,9 @@ struct heif_error heif_image_scale_image(const struct heif_image* input, struct heif_error heif_image_extend_to_size_fill_with_zero(struct heif_image* image, uint32_t width, uint32_t height) { - bool success = image->image->extend_to_size_with_zero(width, height); - if (!success) { - return heif_error{heif_error_Memory_allocation_error, - heif_suberror_Unspecified, - "Not enough memory to extend image size."}; + Error err = image->image->extend_to_size_with_zero2(width, height); + if (err) { + return err.error_struct(image->image.get()); } return heif_error_ok; diff --git a/libheif/codecs/uncompressed/unc_codec.cc b/libheif/codecs/uncompressed/unc_codec.cc index cfca1c2d73..b46a49029f 100644 --- a/libheif/codecs/uncompressed/unc_codec.cc +++ b/libheif/codecs/uncompressed/unc_codec.cc @@ -465,10 +465,14 @@ Result> UncompressedImageCodec::create_image(con } if ((channel == heif_channel_Cb) || (channel == heif_channel_Cr)) { - img->add_plane(channel, (width / chroma_h_subsampling(chroma)), (height / chroma_v_subsampling(chroma)), component.component_bit_depth); + if (auto err = img->add_plane2(channel, (width / chroma_h_subsampling(chroma)), (height / chroma_v_subsampling(chroma)), component.component_bit_depth)) { + return err; + } } else { - img->add_plane(channel, width, height, component.component_bit_depth); + if (auto err = img->add_plane2(channel, width, height, component.component_bit_depth)) { + return err; + } } } } diff --git a/libheif/color-conversion/alpha.cc b/libheif/color-conversion/alpha.cc index c2d913d375..93d2cccd65 100644 --- a/libheif/color-conversion/alpha.cc +++ b/libheif/color-conversion/alpha.cc @@ -52,7 +52,7 @@ Op_drop_alpha_plane::state_after_conversion(const ColorState& input_state, } -std::shared_ptr +Result> Op_drop_alpha_plane::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, diff --git a/libheif/color-conversion/alpha.h b/libheif/color-conversion/alpha.h index 850c3c271d..e398f1d03b 100644 --- a/libheif/color-conversion/alpha.h +++ b/libheif/color-conversion/alpha.h @@ -34,7 +34,7 @@ class Op_drop_alpha_plane : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, diff --git a/libheif/color-conversion/chroma_sampling.cc b/libheif/color-conversion/chroma_sampling.cc index 16492a16ad..106a97495d 100644 --- a/libheif/color-conversion/chroma_sampling.cc +++ b/libheif/color-conversion/chroma_sampling.cc @@ -75,7 +75,7 @@ Op_YCbCr444_to_YCbCr420_average::state_after_conversion(const ColorState& template -std::shared_ptr +Result> Op_YCbCr444_to_YCbCr420_average::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -98,14 +98,14 @@ Op_YCbCr444_to_YCbCr420_average::convert_colorspace(const std::shared_ptr if (bpp_y > 8 || bpp_cb > 8 || bpp_cr > 8) { - return nullptr; + return Error::InternalError; } } else { if (bpp_y <= 8 || bpp_cb <= 8 || bpp_cr <= 8) { - return nullptr; + return Error::InternalError; } } @@ -113,7 +113,7 @@ Op_YCbCr444_to_YCbCr420_average::convert_colorspace(const std::shared_ptr if (bpp_y != bpp_cb || bpp_y != bpp_cr) { // TODO: test with varying bit depths when we have a test image - return nullptr; + return Error::InternalError; } @@ -129,15 +129,15 @@ Op_YCbCr444_to_YCbCr420_average::convert_colorspace(const std::shared_ptr uint32_t cwidth = (width + 1) / 2; uint32_t cheight = (height + 1) / 2; - if (!outimg->add_plane(heif_channel_Y, width, height, bpp_y) || - !outimg->add_plane(heif_channel_Cb, cwidth, cheight, bpp_cb) || - !outimg->add_plane(heif_channel_Cr, cwidth, cheight, bpp_cr)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Y, width, height, bpp_y) || + outimg->add_plane2(heif_channel_Cb, cwidth, cheight, bpp_cb) || + outimg->add_plane2(heif_channel_Cr, cwidth, cheight, bpp_cr)) { + return err; } if (has_alpha) { - if (!outimg->add_plane(heif_channel_Alpha, width, height, bpp_a)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Alpha, width, height, bpp_a)) { + return err; } } @@ -293,7 +293,7 @@ Op_YCbCr444_to_YCbCr422_average::state_after_conversion(const ColorState& template -std::shared_ptr +Result> Op_YCbCr444_to_YCbCr422_average::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -316,14 +316,14 @@ Op_YCbCr444_to_YCbCr422_average::convert_colorspace(const std::shared_ptr if (bpp_y > 8 || bpp_cb > 8 || bpp_cr > 8) { - return nullptr; + return Error::InternalError; } } else { if (bpp_y <= 8 || bpp_cb <= 8 || bpp_cr <= 8) { - return nullptr; + return Error::InternalError; } } @@ -331,7 +331,7 @@ Op_YCbCr444_to_YCbCr422_average::convert_colorspace(const std::shared_ptr if (bpp_y != bpp_cb || bpp_y != bpp_cr) { // TODO: test with varying bit depths when we have a test image - return nullptr; + return Error::InternalError; } @@ -347,15 +347,15 @@ Op_YCbCr444_to_YCbCr422_average::convert_colorspace(const std::shared_ptr uint32_t cwidth = (width + 1) / 2; uint32_t cheight = height; - if (!outimg->add_plane(heif_channel_Y, width, height, bpp_y) || - !outimg->add_plane(heif_channel_Cb, cwidth, cheight, bpp_cb) || - !outimg->add_plane(heif_channel_Cr, cwidth, cheight, bpp_cr)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Y, width, height, bpp_y) || + outimg->add_plane2(heif_channel_Cb, cwidth, cheight, bpp_cb) || + outimg->add_plane2(heif_channel_Cr, cwidth, cheight, bpp_cr)) { + return err; } if (has_alpha) { - if (!outimg->add_plane(heif_channel_Alpha, width, height, bpp_a)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Alpha, width, height, bpp_a)) { + return err; } } @@ -487,7 +487,7 @@ Op_YCbCr420_bilinear_to_YCbCr444::state_after_conversion(const ColorState template -std::shared_ptr +Result> Op_YCbCr420_bilinear_to_YCbCr444::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -510,14 +510,14 @@ Op_YCbCr420_bilinear_to_YCbCr444::convert_colorspace(const std::shared_pt if (bpp_y > 8 || bpp_cb > 8 || bpp_cr > 8) { - return nullptr; + return Error::InternalError; } } else { if (bpp_y <= 8 || bpp_cb <= 8 || bpp_cr <= 8) { - return nullptr; + return Error::InternalError; } } @@ -525,7 +525,7 @@ Op_YCbCr420_bilinear_to_YCbCr444::convert_colorspace(const std::shared_pt if (bpp_y != bpp_cb || bpp_y != bpp_cr) { // TODO: test with varying bit depths when we have a test image - return nullptr; + return Error::InternalError; } @@ -538,15 +538,15 @@ Op_YCbCr420_bilinear_to_YCbCr444::convert_colorspace(const std::shared_pt outimg->create(width, height, heif_colorspace_YCbCr, heif_chroma_444); - if (!outimg->add_plane(heif_channel_Y, width, height, bpp_y) || - !outimg->add_plane(heif_channel_Cb, width, height, bpp_cb) || - !outimg->add_plane(heif_channel_Cr, width, height, bpp_cr)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Y, width, height, bpp_y) || + outimg->add_plane2(heif_channel_Cb, width, height, bpp_cb) || + outimg->add_plane2(heif_channel_Cr, width, height, bpp_cr)) { + return err; } if (has_alpha) { - if (!outimg->add_plane(heif_channel_Alpha, width, height, bpp_a)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Alpha, width, height, bpp_a)) { + return err; } } @@ -764,7 +764,7 @@ Op_YCbCr422_bilinear_to_YCbCr444::state_after_conversion(const ColorState template -std::shared_ptr +Result> Op_YCbCr422_bilinear_to_YCbCr444::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -787,14 +787,14 @@ Op_YCbCr422_bilinear_to_YCbCr444::convert_colorspace(const std::shared_pt if (bpp_y > 8 || bpp_cb > 8 || bpp_cr > 8) { - return nullptr; + return Error::InternalError; } } else { if (bpp_y <= 8 || bpp_cb <= 8 || bpp_cr <= 8) { - return nullptr; + return Error::InternalError; } } @@ -802,7 +802,7 @@ Op_YCbCr422_bilinear_to_YCbCr444::convert_colorspace(const std::shared_pt if (bpp_y != bpp_cb || bpp_y != bpp_cr) { // TODO: test with varying bit depths when we have a test image - return nullptr; + return Error::InternalError; } @@ -815,15 +815,15 @@ Op_YCbCr422_bilinear_to_YCbCr444::convert_colorspace(const std::shared_pt outimg->create(width, height, heif_colorspace_YCbCr, heif_chroma_444); - if (!outimg->add_plane(heif_channel_Y, width, height, bpp_y) || - !outimg->add_plane(heif_channel_Cb, width, height, bpp_cb) || - !outimg->add_plane(heif_channel_Cr, width, height, bpp_cr)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Y, width, height, bpp_y) || + outimg->add_plane2(heif_channel_Cb, width, height, bpp_cb) || + outimg->add_plane2(heif_channel_Cr, width, height, bpp_cr)) { + return err; } if (has_alpha) { - if (!outimg->add_plane(heif_channel_Alpha, width, height, bpp_a)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Alpha, width, height, bpp_a)) { + return err; } } diff --git a/libheif/color-conversion/chroma_sampling.h b/libheif/color-conversion/chroma_sampling.h index 446bd952f8..b0f8e831b8 100644 --- a/libheif/color-conversion/chroma_sampling.h +++ b/libheif/color-conversion/chroma_sampling.h @@ -37,7 +37,7 @@ class Op_YCbCr444_to_YCbCr420_average : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -54,7 +54,7 @@ class Op_YCbCr444_to_YCbCr422_average : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -73,7 +73,7 @@ class Op_YCbCr420_bilinear_to_YCbCr444 : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -89,7 +89,7 @@ class Op_YCbCr422_bilinear_to_YCbCr444 : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, diff --git a/libheif/color-conversion/colorconversion.cc b/libheif/color-conversion/colorconversion.cc index a550bd5d79..1673534dd0 100644 --- a/libheif/color-conversion/colorconversion.cc +++ b/libheif/color-conversion/colorconversion.cc @@ -427,7 +427,7 @@ std::string ColorConversionPipeline::debug_dump_pipeline() const } -std::shared_ptr ColorConversionPipeline::convert_image(const std::shared_ptr& input) +Result> ColorConversionPipeline::convert_image(const std::shared_ptr& input) { std::shared_ptr in = input; std::shared_ptr out = in; @@ -439,9 +439,12 @@ std::shared_ptr ColorConversionPipeline::convert_image(const std print_spec(std::cerr, in); #endif - out = step.operation->convert_colorspace(in, step.input_state, step.output_state, m_options); - if (!out) { - return nullptr; // TODO: we should return a proper error + auto outResult = step.operation->convert_colorspace(in, step.input_state, step.output_state, m_options); + if (outResult.error) { + return outResult.error; + } + else { + out = *outResult; } // --- pass the color profiles to the new image @@ -479,12 +482,12 @@ std::shared_ptr ColorConversionPipeline::convert_image(const std } -std::shared_ptr convert_colorspace(const std::shared_ptr& input, - heif_colorspace target_colorspace, - heif_chroma target_chroma, - const std::shared_ptr& target_profile, - int output_bpp, - const heif_color_conversion_options& options) +Result> convert_colorspace(const std::shared_ptr& input, + heif_colorspace target_colorspace, + heif_chroma target_chroma, + const std::shared_ptr& target_profile, + int output_bpp, + const heif_color_conversion_options& options) { // --- check that input image is valid @@ -496,7 +499,7 @@ std::shared_ptr convert_colorspace(const std::shared_ptrhas_channel(heif_channel_Alpha)) { if (input->get_width(heif_channel_Alpha) != width || input->get_height(heif_channel_Alpha) != height) { - return nullptr; + return Error::InternalError; } } @@ -506,7 +509,7 @@ std::shared_ptr convert_colorspace(const std::shared_ptr convert_colorspace(const std::shared_ptr convert_colorspace(const std::shared_ptr convert_colorspace(const std::shared_ptr& input, - heif_colorspace colorspace, - heif_chroma chroma, - const std::shared_ptr& target_profile, - int output_bpp, - const heif_color_conversion_options& options) +Result> convert_colorspace(const std::shared_ptr& input, + heif_colorspace colorspace, + heif_chroma chroma, + const std::shared_ptr& target_profile, + int output_bpp, + const heif_color_conversion_options& options) { std::shared_ptr non_const_input = std::const_pointer_cast(input); - return convert_colorspace(non_const_input, colorspace, chroma, target_profile, output_bpp, options); + auto result = convert_colorspace(non_const_input, colorspace, chroma, target_profile, output_bpp, options); + if (result.error) { + return result.error; + } + else { + // TODO: can we simplify this? It's a bit awkward to do these assignments just to get a "const HeifPixelImage". + std::shared_ptr constImage = *result; + return constImage; + } } diff --git a/libheif/color-conversion/colorconversion.h b/libheif/color-conversion/colorconversion.h index d35e3ff09c..d25a2f3636 100644 --- a/libheif/color-conversion/colorconversion.h +++ b/libheif/color-conversion/colorconversion.h @@ -85,7 +85,7 @@ class ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const = 0; - virtual std::shared_ptr + virtual Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -105,7 +105,7 @@ class ColorConversionPipeline const ColorState& target_state, const heif_color_conversion_options& options); - std::shared_ptr convert_image(const std::shared_ptr& input); + Result> convert_image(const std::shared_ptr& input); std::string debug_dump_pipeline() const; @@ -126,18 +126,18 @@ class ColorConversionPipeline // If no conversion is required, the input is simply passed through without copy. // The input image is never modified by this function, but the input is still non-const because we may pass it through. -std::shared_ptr convert_colorspace(const std::shared_ptr& input, - heif_colorspace colorspace, - heif_chroma chroma, - const std::shared_ptr& target_profile, - int output_bpp, - const heif_color_conversion_options& options); - -std::shared_ptr convert_colorspace(const std::shared_ptr& input, - heif_colorspace colorspace, - heif_chroma chroma, - const std::shared_ptr& target_profile, - int output_bpp, - const heif_color_conversion_options& options); +Result> convert_colorspace(const std::shared_ptr& input, + heif_colorspace colorspace, + heif_chroma chroma, + const std::shared_ptr& target_profile, + int output_bpp, + const heif_color_conversion_options& options); + +Result> convert_colorspace(const std::shared_ptr& input, + heif_colorspace colorspace, + heif_chroma chroma, + const std::shared_ptr& target_profile, + int output_bpp, + const heif_color_conversion_options& options); #endif diff --git a/libheif/color-conversion/hdr_sdr.cc b/libheif/color-conversion/hdr_sdr.cc index 6bf07f4d91..83db410ff5 100644 --- a/libheif/color-conversion/hdr_sdr.cc +++ b/libheif/color-conversion/hdr_sdr.cc @@ -50,7 +50,7 @@ Op_to_hdr_planes::state_after_conversion(const ColorState& input_state, } -std::shared_ptr +Result> Op_to_hdr_planes::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -73,8 +73,8 @@ Op_to_hdr_planes::convert_colorspace(const std::shared_ptr if (input->has_channel(channel)) { uint32_t width = input->get_width(channel); uint32_t height = input->get_height(channel); - if (!outimg->add_plane(channel, width, height, target_state.bits_per_pixel)) { - return nullptr; + if (auto err = outimg->add_plane2(channel, width, height, target_state.bits_per_pixel)) { + return err; } int input_bits = input->get_bits_per_pixel(channel); @@ -137,7 +137,7 @@ Op_to_sdr_planes::state_after_conversion(const ColorState& input_state, } -std::shared_ptr +Result> Op_to_sdr_planes::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -164,8 +164,8 @@ Op_to_sdr_planes::convert_colorspace(const std::shared_ptr if (input_bits > 8) { uint32_t width = input->get_width(channel); uint32_t height = input->get_height(channel); - if (!outimg->add_plane(channel, width, height, 8)) { - return nullptr; + if (auto err = outimg->add_plane2(channel, width, height, 8)) { + return err; } int shift = input_bits - 8; @@ -187,8 +187,8 @@ Op_to_sdr_planes::convert_colorspace(const std::shared_ptr } else if (input_bits < 8) { uint32_t width = input->get_width(channel); uint32_t height = input->get_height(channel); - if (!outimg->add_plane(channel, width, height, 8)) { - return nullptr; + if (auto err = outimg->add_plane2(channel, width, height, 8)) { + return err; } // We also want to support converting inputs with < 4 bits per pixel covering the whole output range. diff --git a/libheif/color-conversion/hdr_sdr.h b/libheif/color-conversion/hdr_sdr.h index 4fd79d4fe1..e0f892769f 100644 --- a/libheif/color-conversion/hdr_sdr.h +++ b/libheif/color-conversion/hdr_sdr.h @@ -34,7 +34,7 @@ class Op_to_hdr_planes : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -50,7 +50,7 @@ class Op_to_sdr_planes : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, diff --git a/libheif/color-conversion/monochrome.cc b/libheif/color-conversion/monochrome.cc index 1c0b9c5c9b..ad33dd32f8 100644 --- a/libheif/color-conversion/monochrome.cc +++ b/libheif/color-conversion/monochrome.cc @@ -49,7 +49,7 @@ Op_mono_to_YCbCr420::state_after_conversion(const ColorState& input_state, } -std::shared_ptr +Result> Op_mono_to_YCbCr420::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -67,18 +67,18 @@ Op_mono_to_YCbCr420::convert_colorspace(const std::shared_ptradd_plane(heif_channel_Y, width, height, input_bpp) || - !outimg->add_plane(heif_channel_Cb, chroma_width, chroma_height, input_bpp) || - !outimg->add_plane(heif_channel_Cr, chroma_width, chroma_height, input_bpp)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Y, width, height, input_bpp) || + outimg->add_plane2(heif_channel_Cb, chroma_width, chroma_height, input_bpp) || + outimg->add_plane2(heif_channel_Cr, chroma_width, chroma_height, input_bpp)) { + return err; } int alpha_bpp = 0; bool has_alpha = input->has_channel(heif_channel_Alpha); if (has_alpha) { alpha_bpp = input->get_bits_per_pixel(heif_channel_Alpha); - if (!outimg->add_plane(heif_channel_Alpha, width, height, alpha_bpp)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Alpha, width, height, alpha_bpp)) { + return err; } } @@ -200,7 +200,7 @@ Op_mono_to_RGB24_32::state_after_conversion(const ColorState& input_state, } -std::shared_ptr +Result> Op_mono_to_RGB24_32::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -210,7 +210,7 @@ Op_mono_to_RGB24_32::convert_colorspace(const std::shared_ptrget_height(); if (input->get_bits_per_pixel(heif_channel_Y) != 8) { - return nullptr; + return Error::InternalError; } auto outimg = std::make_shared(); @@ -224,8 +224,8 @@ Op_mono_to_RGB24_32::convert_colorspace(const std::shared_ptrcreate(width, height, heif_colorspace_RGB, heif_chroma_interleaved_24bit); } - if (!outimg->add_plane(heif_channel_interleaved, width, height, 8)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_interleaved, width, height, 8)) { + return err; } const uint8_t* in_y, * in_a = nullptr; diff --git a/libheif/color-conversion/monochrome.h b/libheif/color-conversion/monochrome.h index 9b93f7eda2..1de56a1e16 100644 --- a/libheif/color-conversion/monochrome.h +++ b/libheif/color-conversion/monochrome.h @@ -34,7 +34,7 @@ class Op_mono_to_YCbCr420 : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -50,7 +50,7 @@ class Op_mono_to_RGB24_32 : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, diff --git a/libheif/color-conversion/rgb2rgb.cc b/libheif/color-conversion/rgb2rgb.cc index 89b5e12499..dc5bb6aa52 100644 --- a/libheif/color-conversion/rgb2rgb.cc +++ b/libheif/color-conversion/rgb2rgb.cc @@ -63,7 +63,7 @@ Op_RGB_to_RGB24_32::state_after_conversion(const ColorState& input_state, } -std::shared_ptr +Result> Op_RGB_to_RGB24_32::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -75,11 +75,11 @@ Op_RGB_to_RGB24_32::convert_colorspace(const std::shared_ptrget_bits_per_pixel(heif_channel_R) != 8 || input->get_bits_per_pixel(heif_channel_G) != 8 || input->get_bits_per_pixel(heif_channel_B) != 8) { - return nullptr; + return Error::InternalError; } if (has_alpha && input->get_bits_per_pixel(heif_channel_Alpha) != 8) { - return nullptr; + return Error::InternalError; } auto outimg = std::make_shared(); @@ -90,8 +90,8 @@ Op_RGB_to_RGB24_32::convert_colorspace(const std::shared_ptrcreate(width, height, heif_colorspace_RGB, want_alpha ? heif_chroma_interleaved_32bit : heif_chroma_interleaved_24bit); - if (!outimg->add_plane(heif_channel_interleaved, width, height, 8)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_interleaved, width, height, 8)) { + return err; } const uint8_t* in_r, * in_g, * in_b, * in_a = nullptr; @@ -186,7 +186,7 @@ Op_RGB_HDR_to_RRGGBBaa_BE::state_after_conversion(const ColorState& input_state, } -std::shared_ptr +Result> Op_RGB_HDR_to_RRGGBBaa_BE::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -195,7 +195,7 @@ Op_RGB_HDR_to_RRGGBBaa_BE::convert_colorspace(const std::shared_ptrget_bits_per_pixel(heif_channel_R) <= 8 || input->get_bits_per_pixel(heif_channel_G) <= 8 || input->get_bits_per_pixel(heif_channel_B) <= 8) { - return nullptr; + return Error::InternalError; } bool input_has_alpha = input->has_channel(heif_channel_Alpha); @@ -203,16 +203,16 @@ Op_RGB_HDR_to_RRGGBBaa_BE::convert_colorspace(const std::shared_ptrget_bits_per_pixel(heif_channel_Alpha) <= 8) { - return nullptr; + return Error::InternalError; } if (input->get_width(heif_channel_Alpha) != input->get_width(heif_channel_G) || input->get_height(heif_channel_Alpha) != input->get_height(heif_channel_G)) { - return nullptr; + return Error::InternalError; } } int bpp = input->get_bits_per_pixel(heif_channel_R); - if (bpp <= 0) return nullptr; + if (bpp <= 0) return Error::InternalError; auto outimg = std::make_shared(); @@ -221,8 +221,8 @@ Op_RGB_HDR_to_RRGGBBaa_BE::convert_colorspace(const std::shared_ptrcreate(width, height, heif_colorspace_RGB, output_has_alpha ? heif_chroma_interleaved_RRGGBBAA_BE : heif_chroma_interleaved_RRGGBB_BE); - if (!outimg->add_plane(heif_channel_interleaved, width, height, bpp)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_interleaved, width, height, bpp)) { + return err; } const uint16_t* in_r, * in_g, * in_b, * in_a = nullptr; @@ -242,7 +242,7 @@ Op_RGB_HDR_to_RRGGBBaa_BE::convert_colorspace(const std::shared_ptr +Result> Op_RGB_to_RRGGBBaa_BE::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -329,7 +329,7 @@ Op_RGB_to_RRGGBBaa_BE::convert_colorspace(const std::shared_ptrget_bits_per_pixel(heif_channel_R) != 8 || input->get_bits_per_pixel(heif_channel_G) != 8 || input->get_bits_per_pixel(heif_channel_B) != 8) { - return nullptr; + return Error::InternalError; } //int bpp = input->get_bits_per_pixel(heif_channel_R); @@ -338,7 +338,7 @@ Op_RGB_to_RRGGBBaa_BE::convert_colorspace(const std::shared_ptrget_bits_per_pixel(heif_channel_Alpha) != 8) { - return nullptr; + return Error::InternalError; } auto outimg = std::make_shared(); @@ -349,8 +349,8 @@ Op_RGB_to_RRGGBBaa_BE::convert_colorspace(const std::shared_ptrcreate(width, height, heif_colorspace_RGB, output_has_alpha ? heif_chroma_interleaved_RRGGBBAA_BE : heif_chroma_interleaved_RRGGBB_BE); - if (!outimg->add_plane(heif_channel_interleaved, width, height, input->get_bits_per_pixel(heif_channel_R))) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_interleaved, width, height, input->get_bits_per_pixel(heif_channel_R))) { + return err; } const uint8_t* in_r, * in_g, * in_b, * in_a = nullptr; @@ -437,7 +437,7 @@ Op_RRGGBBaa_BE_to_RGB_HDR::state_after_conversion(const ColorState& input_state, } -std::shared_ptr +Result> Op_RRGGBBaa_BE_to_RGB_HDR::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -455,15 +455,15 @@ Op_RRGGBBaa_BE_to_RGB_HDR::convert_colorspace(const std::shared_ptrcreate(width, height, heif_colorspace_RGB, heif_chroma_444); - if (!outimg->add_plane(heif_channel_R, width, height, bpp) || - !outimg->add_plane(heif_channel_G, width, height, bpp) || - !outimg->add_plane(heif_channel_B, width, height, bpp)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_R, width, height, bpp) || + outimg->add_plane2(heif_channel_G, width, height, bpp) || + outimg->add_plane2(heif_channel_B, width, height, bpp)) { + return err; } if (want_alpha) { - if (!outimg->add_plane(heif_channel_Alpha, width, height, bpp)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Alpha, width, height, bpp)) { + return err; } } @@ -550,7 +550,7 @@ Op_RGB24_32_to_RGB::state_after_conversion(const ColorState& input_state, } -std::shared_ptr +Result> Op_RGB24_32_to_RGB::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -566,15 +566,15 @@ Op_RGB24_32_to_RGB::convert_colorspace(const std::shared_ptrcreate(width, height, heif_colorspace_RGB, heif_chroma_444); - if (!outimg->add_plane(heif_channel_R, width, height, 8) || - !outimg->add_plane(heif_channel_G, width, height, 8) || - !outimg->add_plane(heif_channel_B, width, height, 8)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_R, width, height, 8) || + outimg->add_plane2(heif_channel_G, width, height, 8) || + outimg->add_plane2(heif_channel_B, width, height, 8)) { + return err; } if (want_alpha) { - if (!outimg->add_plane(heif_channel_Alpha, width, height, 8)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Alpha, width, height, 8)) { + return err; } } @@ -676,7 +676,7 @@ Op_RRGGBBaa_swap_endianness::state_after_conversion(const ColorState& input_stat } -std::shared_ptr +Result> Op_RRGGBBaa_swap_endianness::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -701,12 +701,12 @@ Op_RRGGBBaa_swap_endianness::convert_colorspace(const std::shared_ptrcreate(width, height, heif_colorspace_RGB, heif_chroma_interleaved_RRGGBBAA_LE); break; default: - return nullptr; + return Error::InternalError; } - if (!outimg->add_plane(heif_channel_interleaved, width, height, - input->get_bits_per_pixel(heif_channel_interleaved))) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_interleaved, width, height, + input->get_bits_per_pixel(heif_channel_interleaved))) { + return err; } const uint8_t* in_p = nullptr; diff --git a/libheif/color-conversion/rgb2rgb.h b/libheif/color-conversion/rgb2rgb.h index dee344bade..c6f46fe552 100644 --- a/libheif/color-conversion/rgb2rgb.h +++ b/libheif/color-conversion/rgb2rgb.h @@ -34,7 +34,7 @@ class Op_RGB_to_RGB24_32 : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -50,7 +50,7 @@ class Op_RGB_HDR_to_RRGGBBaa_BE : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -66,7 +66,7 @@ class Op_RGB_to_RRGGBBaa_BE : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -82,7 +82,7 @@ class Op_RRGGBBaa_BE_to_RGB_HDR : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -98,7 +98,7 @@ class Op_RGB24_32_to_RGB : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -114,7 +114,7 @@ class Op_RRGGBBaa_swap_endianness : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, diff --git a/libheif/color-conversion/rgb2yuv.cc b/libheif/color-conversion/rgb2yuv.cc index b7436c10ad..3dc34f8964 100644 --- a/libheif/color-conversion/rgb2yuv.cc +++ b/libheif/color-conversion/rgb2yuv.cc @@ -89,9 +89,8 @@ Op_RGB_to_YCbCr::state_after_conversion(const ColorState& input_state, return states; } - template -std::shared_ptr +Result> Op_RGB_to_YCbCr::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -108,13 +107,13 @@ Op_RGB_to_YCbCr::convert_colorspace(const std::shared_ptrget_bits_per_pixel(heif_channel_R); if (bpp < 8 || (bpp > 8) != hdr) { - return nullptr; + return Error::InternalError; } bool has_alpha = input->has_channel(heif_channel_Alpha); if (has_alpha && input->get_bits_per_pixel(heif_channel_Alpha) != bpp) { - return nullptr; + return Error::InternalError; } auto outimg = std::make_shared(); @@ -124,15 +123,15 @@ Op_RGB_to_YCbCr::convert_colorspace(const std::shared_ptradd_plane(heif_channel_Y, width, height, bpp) || - !outimg->add_plane(heif_channel_Cb, cwidth, cheight, bpp) || - !outimg->add_plane(heif_channel_Cr, cwidth, cheight, bpp)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Y, width, height, bpp) || + outimg->add_plane2(heif_channel_Cb, cwidth, cheight, bpp) || + outimg->add_plane2(heif_channel_Cr, cwidth, cheight, bpp)) { + return err; } if (has_alpha) { - if (!outimg->add_plane(heif_channel_Alpha, width, height, bpp)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Alpha, width, height, bpp)) { + return err; } } @@ -336,7 +335,7 @@ Op_RRGGBBxx_HDR_to_YCbCr420::state_after_conversion(const ColorState& input_stat } -std::shared_ptr +Result> Op_RRGGBBxx_HDR_to_YCbCr420::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -359,15 +358,15 @@ Op_RRGGBBxx_HDR_to_YCbCr420::convert_colorspace(const std::shared_ptradd_plane(heif_channel_Y, width, height, bpp) || - !outimg->add_plane(heif_channel_Cb, cwidth, cheight, bpp) || - !outimg->add_plane(heif_channel_Cr, cwidth, cheight, bpp)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Y, width, height, bpp) || + outimg->add_plane2(heif_channel_Cb, cwidth, cheight, bpp) || + outimg->add_plane2(heif_channel_Cr, cwidth, cheight, bpp)) { + return err; } if (has_alpha) { - if (!outimg->add_plane(heif_channel_Alpha, width, height, bpp)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Alpha, width, height, bpp)) { + return err; } } @@ -542,7 +541,7 @@ inline void set_chroma_pixels(uint8_t* out_cb, uint8_t* out_cr, } -std::shared_ptr +Result> Op_RGB24_32_to_YCbCr::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -565,15 +564,15 @@ Op_RGB24_32_to_YCbCr::convert_colorspace(const std::shared_ptrget_chroma_format() == heif_chroma_interleaved_32bit); const bool want_alpha = target_state.has_alpha; - if (!outimg->add_plane(heif_channel_Y, width, height, 8) || - !outimg->add_plane(heif_channel_Cb, chroma_width, chroma_height, 8) || - !outimg->add_plane(heif_channel_Cr, chroma_width, chroma_height, 8)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Y, width, height, 8) || + outimg->add_plane2(heif_channel_Cb, chroma_width, chroma_height, 8) || + outimg->add_plane2(heif_channel_Cr, chroma_width, chroma_height, 8)) { + return err; } if (want_alpha) { - if (!outimg->add_plane(heif_channel_Alpha, width, height, 8)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Alpha, width, height, 8)) { + return err; } } @@ -814,7 +813,7 @@ Op_RGB24_32_to_YCbCr444_GBR::state_after_conversion(const ColorState& input_stat } -std::shared_ptr +Result> Op_RGB24_32_to_YCbCr444_GBR::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -830,15 +829,15 @@ Op_RGB24_32_to_YCbCr444_GBR::convert_colorspace(const std::shared_ptrget_chroma_format() == heif_chroma_interleaved_32bit); const bool want_alpha = target_state.has_alpha; - if (!outimg->add_plane(heif_channel_Y, width, height, 8) || - !outimg->add_plane(heif_channel_Cb, width, height, 8) || - !outimg->add_plane(heif_channel_Cr, width, height, 8)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Y, width, height, 8) || + outimg->add_plane2(heif_channel_Cb, width, height, 8) || + outimg->add_plane2(heif_channel_Cr, width, height, 8)) { + return err; } if (want_alpha) { - if (!outimg->add_plane(heif_channel_Alpha, width, height, 8)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Alpha, width, height, 8)) { + return err; } } diff --git a/libheif/color-conversion/rgb2yuv.h b/libheif/color-conversion/rgb2yuv.h index 74b929b0a0..7ab2a91fc8 100644 --- a/libheif/color-conversion/rgb2yuv.h +++ b/libheif/color-conversion/rgb2yuv.h @@ -35,7 +35,7 @@ class Op_RGB_to_YCbCr : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -52,7 +52,7 @@ class Op_RRGGBBxx_HDR_to_YCbCr420 : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -68,7 +68,7 @@ class Op_RGB24_32_to_YCbCr : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -84,7 +84,7 @@ class Op_RGB24_32_to_YCbCr444_GBR : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, diff --git a/libheif/color-conversion/rgb2yuv_sharp.cc b/libheif/color-conversion/rgb2yuv_sharp.cc index da63393d84..ca19cd8569 100644 --- a/libheif/color-conversion/rgb2yuv_sharp.cc +++ b/libheif/color-conversion/rgb2yuv_sharp.cc @@ -121,7 +121,7 @@ Op_Any_RGB_to_YCbCr_420_Sharp::state_after_conversion( #endif } -std::shared_ptr +Result> Op_Any_RGB_to_YCbCr_420_Sharp::convert_colorspace( const std::shared_ptr& input, const ColorState& input_state, @@ -154,15 +154,15 @@ Op_Any_RGB_to_YCbCr_420_Sharp::convert_colorspace( bool want_alpha = target_state.has_alpha; int output_bits = target_state.bits_per_pixel; - if (!outimg->add_plane(heif_channel_Y, width, height, output_bits) || - !outimg->add_plane(heif_channel_Cb, chroma_width, chroma_height, output_bits) || - !outimg->add_plane(heif_channel_Cr, chroma_width, chroma_height, output_bits)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Y, width, height, output_bits) || + outimg->add_plane2(heif_channel_Cb, chroma_width, chroma_height, output_bits) || + outimg->add_plane2(heif_channel_Cr, chroma_width, chroma_height, output_bits)) { + return err; } if (want_alpha) { - if (!outimg->add_plane(heif_channel_Alpha, width, height, output_bits)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Alpha, width, height, output_bits)) { + return err; } } @@ -186,14 +186,14 @@ Op_Any_RGB_to_YCbCr_420_Sharp::convert_colorspace( in_b = input->get_plane(heif_channel_B, &in_b_stride); // The stride must be the same for all channels. if (in_r_stride != in_g_stride || in_r_stride != in_b_stride) { - return nullptr; + return Error::InternalError; } in_stride = in_r_stride; // Bpp must also be the same. input_bits = input->get_bits_per_pixel(heif_channel_R); if (input_bits != input->get_bits_per_pixel(heif_channel_G) || input_bits != input->get_bits_per_pixel(heif_channel_B)) { - return nullptr; + return Error::InternalError; } if (has_alpha) { in_a = input->get_plane(heif_channel_Alpha, &in_a_stride); @@ -237,7 +237,9 @@ Op_Any_RGB_to_YCbCr_420_Sharp::convert_colorspace( out_cr, out_cr_stride, output_bits, input->get_width(), input->get_height(), &yuv_matrix); if (!sharpyuv_ok) { - return nullptr; + return Error{heif_error_Unsupported_feature, + heif_suberror_Unsupported_color_conversion, + "SharpYuv color convertion failed"}; } if (want_alpha) { diff --git a/libheif/color-conversion/rgb2yuv_sharp.h b/libheif/color-conversion/rgb2yuv_sharp.h index 057529cdbc..ba49939257 100644 --- a/libheif/color-conversion/rgb2yuv_sharp.h +++ b/libheif/color-conversion/rgb2yuv_sharp.h @@ -34,7 +34,7 @@ class Op_Any_RGB_to_YCbCr_420_Sharp : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, diff --git a/libheif/color-conversion/yuv2rgb.cc b/libheif/color-conversion/yuv2rgb.cc index bc8c1b7b8b..dc33cd109f 100644 --- a/libheif/color-conversion/yuv2rgb.cc +++ b/libheif/color-conversion/yuv2rgb.cc @@ -82,7 +82,7 @@ Op_YCbCr_to_RGB::state_after_conversion(const ColorState& input_state, template -std::shared_ptr +Result> Op_YCbCr_to_RGB::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -107,14 +107,14 @@ Op_YCbCr_to_RGB::convert_colorspace(const std::shared_ptr::convert_colorspace(const std::shared_ptr::convert_colorspace(const std::shared_ptrcreate(width, height, heif_colorspace_RGB, heif_chroma_444); - if (!outimg->add_plane(heif_channel_R, width, height, bpp_y) || - !outimg->add_plane(heif_channel_G, width, height, bpp_y) || - !outimg->add_plane(heif_channel_B, width, height, bpp_y)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_R, width, height, bpp_y) || + outimg->add_plane2(heif_channel_G, width, height, bpp_y) || + outimg->add_plane2(heif_channel_B, width, height, bpp_y)) { + return err; } if (has_alpha) { - if (!outimg->add_plane(heif_channel_Alpha, width, height, bpp_a)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Alpha, width, height, bpp_a)) { + return err; } } @@ -308,7 +308,7 @@ Op_YCbCr420_to_RGB24::state_after_conversion(const ColorState& input_state, } -std::shared_ptr +Result> Op_YCbCr420_to_RGB24::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -317,7 +317,7 @@ Op_YCbCr420_to_RGB24::convert_colorspace(const std::shared_ptrget_bits_per_pixel(heif_channel_Y) != 8 || input->get_bits_per_pixel(heif_channel_Cb) != 8 || input->get_bits_per_pixel(heif_channel_Cr) != 8) { - return nullptr; + return Error::InternalError; } auto outimg = std::make_shared(); @@ -327,8 +327,8 @@ Op_YCbCr420_to_RGB24::convert_colorspace(const std::shared_ptrcreate(width, height, heif_colorspace_RGB, heif_chroma_interleaved_24bit); - if (!outimg->add_plane(heif_channel_interleaved, width, height, 8)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_interleaved, width, height, 8)) { + return err; } auto colorProfile = input->get_color_profile_nclx(); @@ -418,7 +418,7 @@ Op_YCbCr420_to_RGB32::state_after_conversion(const ColorState& input_state, } -std::shared_ptr +Result> Op_YCbCr420_to_RGB32::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -427,7 +427,7 @@ Op_YCbCr420_to_RGB32::convert_colorspace(const std::shared_ptrget_bits_per_pixel(heif_channel_Y) != 8 || input->get_bits_per_pixel(heif_channel_Cb) != 8 || input->get_bits_per_pixel(heif_channel_Cr) != 8) { - return nullptr; + return Error::InternalError; } auto outimg = std::make_shared(); @@ -437,8 +437,8 @@ Op_YCbCr420_to_RGB32::convert_colorspace(const std::shared_ptrcreate(width, height, heif_colorspace_RGB, heif_chroma_interleaved_32bit); - if (!outimg->add_plane(heif_channel_interleaved, width, height, 8)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_interleaved, width, height, 8)) { + return err; } @@ -552,7 +552,7 @@ Op_YCbCr420_to_RRGGBBaa::state_after_conversion(const ColorState& input_state, } -std::shared_ptr +Result> Op_YCbCr420_to_RRGGBBaa::convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -572,13 +572,13 @@ Op_YCbCr420_to_RRGGBBaa::convert_colorspace(const std::shared_ptradd_plane(heif_channel_interleaved, width, height, bpp)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_interleaved, width, height, bpp)) { + return err; } if (has_alpha) { - if (!outimg->add_plane(heif_channel_Alpha, width, height, bpp)) { - return nullptr; + if (auto err = outimg->add_plane2(heif_channel_Alpha, width, height, bpp)) { + return err; } } diff --git a/libheif/color-conversion/yuv2rgb.h b/libheif/color-conversion/yuv2rgb.h index 40228ebdc5..c61331635c 100644 --- a/libheif/color-conversion/yuv2rgb.h +++ b/libheif/color-conversion/yuv2rgb.h @@ -36,7 +36,7 @@ class Op_YCbCr_to_RGB : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -52,7 +52,7 @@ class Op_YCbCr420_to_RGB24 : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -68,7 +68,7 @@ class Op_YCbCr420_to_RGB32 : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, @@ -84,7 +84,7 @@ class Op_YCbCr420_to_RRGGBBaa : public ColorConversionOperation const ColorState& target_state, const heif_color_conversion_options& options) const override; - std::shared_ptr + Result> convert_colorspace(const std::shared_ptr& input, const ColorState& input_state, const ColorState& target_state, diff --git a/libheif/context.cc b/libheif/context.cc index 7567b2fcce..e096b9a60f 100644 --- a/libheif/context.cc +++ b/libheif/context.cc @@ -1087,9 +1087,12 @@ Result> HeifContext::decode_image(heif_item_id I // TODO: check BPP changed if (different_chroma || different_colorspace) { - img = convert_colorspace(img, target_colorspace, target_chroma, nullptr, bpp, options.color_conversion_options); - if (!img) { - return Error(heif_error_Unsupported_feature, heif_suberror_Unsupported_color_conversion); + auto img_result = convert_colorspace(img, target_colorspace, target_chroma, nullptr, bpp, options.color_conversion_options); + if (img_result.error) { + return img_result.error; + } + else { + img = *img_result; } } @@ -1099,7 +1102,7 @@ Result> HeifContext::decode_image(heif_item_id I } -static std::shared_ptr +static Result> create_alpha_image_from_image_alpha_channel(const std::shared_ptr& image) { // --- generate alpha image @@ -1112,7 +1115,9 @@ create_alpha_image_from_image_alpha_channel(const std::shared_ptrcopy_new_plane_from(image, heif_channel_Alpha, heif_channel_Y); } else if (image->get_chroma_format() == heif_chroma_interleaved_RGBA) { - alpha_image->extract_alpha_from_RGBA(image); + if (auto err = alpha_image->extract_alpha_from_RGBA2(image)) { + return err; + } } // TODO: 16 bit @@ -1195,7 +1200,12 @@ Result> HeifContext::encode_image(const std::shared_p // TODO: can we directly code a monochrome image instead of the dummy color channels? std::shared_ptr alpha_image; - alpha_image = create_alpha_image_from_image_alpha_channel(colorConvertedImage); + auto alpha_image_result = create_alpha_image_from_image_alpha_channel(colorConvertedImage); + if (!alpha_image_result) { + return alpha_image_result.error; + } + + alpha_image = *alpha_image_result; // --- encode the alpha image diff --git a/libheif/image-items/grid.cc b/libheif/image-items/grid.cc index b9fd87d106..cbc127540b 100644 --- a/libheif/image-items/grid.cc +++ b/libheif/image-items/grid.cc @@ -453,7 +453,10 @@ Error ImageItem_Grid::decode_and_paste_tile_image(heif_item_id tileID, uint32_t if (!inout_image) { auto grid_image = std::make_shared(); - grid_image->create_clone_image_at_new_size(tile_img, w, h); + auto err = grid_image->create_clone_image_at_new_size2(tile_img, w, h); + if (err) { + return err; + } // Fill alpha plane with opaque in case not all tiles have alpha planes diff --git a/libheif/image-items/image_item.cc b/libheif/image-items/image_item.cc index baf71af659..887a1be3bf 100644 --- a/libheif/image-items/image_item.cc +++ b/libheif/image-items/image_item.cc @@ -604,26 +604,26 @@ Result> ImageItem::convert_colorspace_for_encodi std::shared_ptr output_image; - if (colorspace != image->get_colorspace() || - chroma != image->get_chroma_format() || - !nclx_profile_matches_spec(colorspace, image->get_color_profile_nclx(), output_nclx_profile)) { - // @TODO: use color profile when converting - int output_bpp = 0; // same as input - - //auto target_nclx = std::make_shared(); - //target_nclx->set_from_heif_color_profile_nclx(target_heif_nclx); - - output_image = convert_colorspace(image, colorspace, chroma, target_nclx_profile, - output_bpp, options.color_conversion_options); - if (!output_image) { - return Error(heif_error_Unsupported_feature, heif_suberror_Unsupported_color_conversion); - } + if (colorspace == image->get_colorspace() && + chroma == image->get_chroma_format() && + nclx_profile_matches_spec(colorspace, image->get_color_profile_nclx(), output_nclx_profile)) { + return image; } - else { - output_image = image; + + + // @TODO: use color profile when converting + int output_bpp = 0; // same as input + + //auto target_nclx = std::make_shared(); + //target_nclx->set_from_heif_color_profile_nclx(target_heif_nclx); + + auto output_image_result = convert_colorspace(image, colorspace, chroma, target_nclx_profile, + output_bpp, options.color_conversion_options); + if (output_image_result.error) { + return output_image_result.error; } - return output_image; + return *output_image_result; } diff --git a/libheif/image-items/mask_image.cc b/libheif/image-items/mask_image.cc index c9adc67c3a..cf7cc3c735 100644 --- a/libheif/image-items/mask_image.cc +++ b/libheif/image-items/mask_image.cc @@ -105,7 +105,11 @@ Error MaskImageCodec::decode_mask_image(const HeifContext* context, img = std::make_shared(); img->create(width, height, heif_colorspace_monochrome, heif_chroma_monochrome); - img->add_plane(heif_channel_Y, width, height, mskC->get_bits_per_pixel()); + auto err = img->add_plane2(heif_channel_Y, width, height, mskC->get_bits_per_pixel()); + if (err) { + return err; + } + uint32_t stride; uint8_t* dst = img->get_plane(heif_channel_Y, &stride); if (((uint32_t)stride) == width) { diff --git a/libheif/image-items/overlay.cc b/libheif/image-items/overlay.cc index fb84689133..8f2078e3b2 100644 --- a/libheif/image-items/overlay.cc +++ b/libheif/image-items/overlay.cc @@ -297,9 +297,15 @@ Result> ImageItem_Overlay::decode_overlay_image( img->create(w, h, heif_colorspace_RGB, heif_chroma_444); - img->add_plane(heif_channel_R, w, h, 8); // TODO: other bit depths - img->add_plane(heif_channel_G, w, h, 8); // TODO: other bit depths - img->add_plane(heif_channel_B, w, h, 8); // TODO: other bit depths + if (auto error = img->add_plane2(heif_channel_R, w, h, 8)) { // TODO: other bit depths + return error; + } + if (auto error = img->add_plane2(heif_channel_G, w, h, 8)) { // TODO: other bit depths + return error; + } + if (auto error = img->add_plane2(heif_channel_B, w, h, 8)) { // TODO: other bit depths + return error; + } uint16_t bkg_color[4]; m_overlay_spec.get_background_color(bkg_color); @@ -339,9 +345,12 @@ Result> ImageItem_Overlay::decode_overlay_image( if (overlay_img->get_colorspace() != heif_colorspace_RGB || overlay_img->get_chroma_format() != heif_chroma_444) { - overlay_img = convert_colorspace(overlay_img, heif_colorspace_RGB, heif_chroma_444, nullptr, 0, options.color_conversion_options); - if (!overlay_img) { - return Error(heif_error_Unsupported_feature, heif_suberror_Unsupported_color_conversion); + auto overlay_img_result = convert_colorspace(overlay_img, heif_colorspace_RGB, heif_chroma_444, nullptr, 0, options.color_conversion_options); + if (overlay_img_result.error) { + return overlay_img_result.error; + } + else { + overlay_img = *overlay_img_result; } } diff --git a/libheif/pixelimage.cc b/libheif/pixelimage.cc index ee14ff0191..14f72e65bd 100644 --- a/libheif/pixelimage.cc +++ b/libheif/pixelimage.cc @@ -189,7 +189,7 @@ static uint32_t rounded_size(uint32_t s) return s; } -bool HeifPixelImage::add_plane(heif_channel channel, uint32_t width, uint32_t height, int bit_depth) +Error HeifPixelImage::add_plane2(heif_channel channel, uint32_t width, uint32_t height, int bit_depth) { assert(!has_channel(channel)); @@ -206,12 +206,12 @@ bool HeifPixelImage::add_plane(heif_channel channel, uint32_t width, uint32_t he bit_depth = 8; } - if (plane.alloc(width, height, heif_channel_datatype_unsigned_integer, bit_depth, num_interleaved_pixels)) { - m_planes.insert(std::make_pair(channel, plane)); - return true; + if (auto err = plane.alloc2(width, height, heif_channel_datatype_unsigned_integer, bit_depth, num_interleaved_pixels)) { + return err; } else { - return false; + m_planes.insert(std::make_pair(channel, plane)); + return Error::Ok; } } @@ -219,18 +219,18 @@ bool HeifPixelImage::add_plane(heif_channel channel, uint32_t width, uint32_t he bool HeifPixelImage::add_channel(heif_channel channel, uint32_t width, uint32_t height, heif_channel_datatype datatype, int bit_depth) { ImagePlane plane; - if (plane.alloc(width, height, datatype, bit_depth, 1)) { - m_planes.insert(std::make_pair(channel, plane)); - return true; + if (Error err = plane.alloc2(width, height, datatype, bit_depth, 1)) { + return err; } else { - return false; + m_planes.insert(std::make_pair(channel, plane)); + return Error::Ok; } } -bool HeifPixelImage::ImagePlane::alloc(uint32_t width, uint32_t height, heif_channel_datatype datatype, int bit_depth, - int num_interleaved_components) // heif_chroma chroma) +Error HeifPixelImage::ImagePlane::alloc2(uint32_t width, uint32_t height, heif_channel_datatype datatype, int bit_depth, + int num_interleaved_components) // heif_chroma chroma) { assert(bit_depth >= 1); assert(bit_depth <= 128); @@ -257,8 +257,14 @@ bool HeifPixelImage::ImagePlane::alloc(uint32_t width, uint32_t height, heif_cha stride = m_mem_width * bytes_per_pixel; stride = (stride + alignment - 1U) & ~(alignment - 1U); - if ((heif_get_global_security_limits()->max_memory_block_size - (alignment + 1)) / stride < m_mem_height) { - return false; + if ((heif_get_global_security_limits()->max_memory_block_size - (alignment - 1)) / stride < m_mem_height) { + std::stringstream sstr; + sstr << "Allocating " << static_cast(m_mem_height) * stride + alignment - 1 << " exceeds the security limit of " + << heif_get_global_security_limits()->max_memory_block_size << " bytes"; + + return {heif_error_Memory_allocation_error, + heif_suberror_Security_limit_exceeded, + sstr.str()}; } try { @@ -275,15 +281,20 @@ bool HeifPixelImage::ImagePlane::alloc(uint32_t width, uint32_t height, heif_cha mem = mem_8; - return true; + return Error::Ok; } catch (const std::bad_alloc& excpt) { - return false; + std::stringstream sstr; + sstr << "Allocating " << static_cast(m_mem_height) * stride + alignment - 1 << " bytes failed"; + + return {heif_error_Memory_allocation_error, + heif_suberror_Unspecified, + sstr.str()}; } } -bool HeifPixelImage::extend_padding_to_size(uint32_t width, uint32_t height, bool adjust_size) +Error HeifPixelImage::extend_padding_to_size2(uint32_t width, uint32_t height, bool adjust_size) { for (auto& planeIter : m_planes) { auto* plane = &planeIter.second; @@ -301,8 +312,8 @@ bool HeifPixelImage::extend_padding_to_size(uint32_t width, uint32_t height, boo plane->m_mem_height < subsampled_height) { ImagePlane newPlane; - if (!newPlane.alloc(subsampled_width, subsampled_height, plane->m_datatype, plane->m_bit_depth, num_interleaved_pixels_per_plane(m_chroma))) { - return false; + if (auto err = newPlane.alloc2(subsampled_width, subsampled_height, plane->m_datatype, plane->m_bit_depth, num_interleaved_pixels_per_plane(m_chroma))) { + return err; } // copy the visible part of the old plane into the new plane @@ -349,11 +360,11 @@ bool HeifPixelImage::extend_padding_to_size(uint32_t width, uint32_t height, boo m_height = height; } - return true; + return Error::Ok; } -bool HeifPixelImage::extend_to_size_with_zero(uint32_t width, uint32_t height) +Error HeifPixelImage::extend_to_size_with_zero2(uint32_t width, uint32_t height) { for (auto& planeIter : m_planes) { auto* plane = &planeIter.second; @@ -371,8 +382,8 @@ bool HeifPixelImage::extend_to_size_with_zero(uint32_t width, uint32_t height) plane->m_mem_height < subsampled_height) { ImagePlane newPlane; - if (!newPlane.alloc(subsampled_width, subsampled_height, plane->m_datatype, plane->m_bit_depth, num_interleaved_pixels_per_plane(m_chroma))) { - return false; + if (auto err = newPlane.alloc2(subsampled_width, subsampled_height, plane->m_datatype, plane->m_bit_depth, num_interleaved_pixels_per_plane(m_chroma))) { + return err; } // copy the visible part of the old plane into the new plane @@ -413,7 +424,7 @@ bool HeifPixelImage::extend_to_size_with_zero(uint32_t width, uint32_t height) m_width = width; m_height = height; - return true; + return Error::Ok; } bool HeifPixelImage::has_channel(heif_channel channel) const @@ -560,12 +571,14 @@ void HeifPixelImage::copy_new_plane_from(const std::shared_ptr& src_image) +Error HeifPixelImage::extract_alpha_from_RGBA2(const std::shared_ptr& src_image) { uint32_t width = src_image->get_width(); uint32_t height = src_image->get_height(); - add_plane(heif_channel_Y, width, height, src_image->get_bits_per_pixel(heif_channel_interleaved)); + if (Error err = add_plane2(heif_channel_Y, width, height, src_image->get_bits_per_pixel(heif_channel_interleaved))) { + return err; + } uint8_t* dst; uint32_t dst_stride = 0; @@ -583,13 +596,20 @@ void HeifPixelImage::extract_alpha_from_RGBA(const std::shared_ptr> HeifPixelImage::rotate_ccw(int angle_deg heif_color_conversion_options options{}; heif_color_conversion_options_set_defaults(&options); - auto converted_image = convert_colorspace(shared_from_this(), heif_colorspace_YCbCr, heif_chroma_444, nullptr, get_bits_per_pixel(heif_channel_Y), options); - return converted_image->rotate_ccw(angle_degrees); + auto converted_image_result = convert_colorspace(shared_from_this(), heif_colorspace_YCbCr, heif_chroma_444, nullptr, get_bits_per_pixel(heif_channel_Y), options); + if (converted_image_result.error) { + return converted_image_result.error; + } + + return (*converted_image_result)->rotate_ccw(angle_degrees); } @@ -892,8 +916,12 @@ Result> HeifPixelImage::mirror_inplace(heif_tran heif_color_conversion_options options{}; heif_color_conversion_options_set_defaults(&options); - auto converted_image = convert_colorspace(shared_from_this(), heif_colorspace_YCbCr, heif_chroma_444, nullptr, get_bits_per_pixel(heif_channel_Y), options); - return converted_image->mirror_inplace(direction); + auto converted_image_result = convert_colorspace(shared_from_this(), heif_colorspace_YCbCr, heif_chroma_444, nullptr, get_bits_per_pixel(heif_channel_Y), options); + if (converted_image_result.error) { + return converted_image_result.error; + } + + return (*converted_image_result)->mirror_inplace(direction); } @@ -967,8 +995,12 @@ Result> HeifPixelImage::crop(uint32_t left, uint heif_color_conversion_options options{}; heif_color_conversion_options_set_defaults(&options); - auto converted_image = convert_colorspace(shared_from_this(), heif_colorspace_YCbCr, heif_chroma_444, nullptr, get_bits_per_pixel(heif_channel_Y), options); - return converted_image->crop(left, right, top, bottom); + auto converted_image_result = convert_colorspace(shared_from_this(), heif_colorspace_YCbCr, heif_chroma_444, nullptr, get_bits_per_pixel(heif_channel_Y), options); + if (converted_image_result.error) { + return converted_image_result.error; + } + + return (*converted_image_result)->crop(left, right, top, bottom); } @@ -1250,7 +1282,9 @@ Error HeifPixelImage::scale_nearest_neighbor(std::shared_ptr& ou // --- create output image with scaled planes if (has_channel(heif_channel_interleaved)) { - out_img->add_plane(heif_channel_interleaved, width, height, get_bits_per_pixel(heif_channel_interleaved)); + if (auto err = out_img->add_plane2(heif_channel_interleaved, width, height, get_bits_per_pixel(heif_channel_interleaved))) { + return err; + } } else { if (get_colorspace() == heif_colorspace_RGB) { @@ -1260,16 +1294,24 @@ Error HeifPixelImage::scale_nearest_neighbor(std::shared_ptr& ou return {heif_error_Invalid_input, heif_suberror_Unspecified, "RGB input without R,G,B, planes"}; } - out_img->add_plane(heif_channel_R, width, height, get_bits_per_pixel(heif_channel_R)); - out_img->add_plane(heif_channel_G, width, height, get_bits_per_pixel(heif_channel_G)); - out_img->add_plane(heif_channel_B, width, height, get_bits_per_pixel(heif_channel_B)); + if (auto err = out_img->add_plane2(heif_channel_R, width, height, get_bits_per_pixel(heif_channel_R))) { + return err; + } + if (auto err = out_img->add_plane2(heif_channel_G, width, height, get_bits_per_pixel(heif_channel_G))) { + return err; + } + if (auto err = out_img->add_plane2(heif_channel_B, width, height, get_bits_per_pixel(heif_channel_B))) { + return err; + } } else if (get_colorspace() == heif_colorspace_monochrome) { if (!has_channel(heif_channel_Y)) { return {heif_error_Invalid_input, heif_suberror_Unspecified, "monochrome input with no Y plane"}; } - out_img->add_plane(heif_channel_Y, width, height, get_bits_per_pixel(heif_channel_Y)); + if (auto err = out_img->add_plane2(heif_channel_Y, width, height, get_bits_per_pixel(heif_channel_Y))) { + return err; + } } else if (get_colorspace() == heif_colorspace_YCbCr) { if (!has_channel(heif_channel_Y) || @@ -1280,16 +1322,24 @@ Error HeifPixelImage::scale_nearest_neighbor(std::shared_ptr& ou uint32_t cw, ch; get_subsampled_size(width, height, heif_channel_Cb, get_chroma_format(), &cw, &ch); - out_img->add_plane(heif_channel_Y, width, height, get_bits_per_pixel(heif_channel_Y)); - out_img->add_plane(heif_channel_Cb, cw, ch, get_bits_per_pixel(heif_channel_Cb)); - out_img->add_plane(heif_channel_Cr, cw, ch, get_bits_per_pixel(heif_channel_Cr)); + if (auto err = out_img->add_plane2(heif_channel_Y, width, height, get_bits_per_pixel(heif_channel_Y))) { + return err; + } + if (auto err = out_img->add_plane2(heif_channel_Cb, cw, ch, get_bits_per_pixel(heif_channel_Cb))) { + return err; + } + if (auto err = out_img->add_plane2(heif_channel_Cr, cw, ch, get_bits_per_pixel(heif_channel_Cr))) { + return err; + } } else { return {heif_error_Invalid_input, heif_suberror_Unspecified, "unknown color configuration"}; } if (has_channel(heif_channel_Alpha)) { - out_img->add_plane(heif_channel_Alpha, width, height, get_bits_per_pixel(heif_channel_Alpha)); + if (auto err = out_img->add_plane2(heif_channel_Alpha, width, height, get_bits_per_pixel(heif_channel_Alpha))) { + return err; + } } } @@ -1365,7 +1415,7 @@ void HeifPixelImage::debug_dump() const } } -void HeifPixelImage::create_clone_image_at_new_size(const std::shared_ptr& source, uint32_t w, uint32_t h) +Error HeifPixelImage::create_clone_image_at_new_size2(const std::shared_ptr& source, uint32_t w, uint32_t h) { heif_colorspace colorspace = source->get_colorspace(); heif_chroma chroma = source->get_chroma_format(); @@ -1374,17 +1424,31 @@ void HeifPixelImage::create_clone_image_at_new_size(const std::shared_ptrget_bits_per_pixel(heif_channel_Y)); + if (auto err = add_plane2(heif_channel_Y, w, h, source->get_bits_per_pixel(heif_channel_Y))) { + return err; + } break; case heif_colorspace_YCbCr: - add_plane(heif_channel_Y, w, h, source->get_bits_per_pixel(heif_channel_Y)); - add_plane(heif_channel_Cb, chroma_width(w, chroma), chroma_height(h, chroma), source->get_bits_per_pixel(heif_channel_Cb)); - add_plane(heif_channel_Cr, chroma_width(w, chroma), chroma_height(h, chroma), source->get_bits_per_pixel(heif_channel_Cr)); + if (auto err = add_plane2(heif_channel_Y, w, h, source->get_bits_per_pixel(heif_channel_Y))) { + return err; + } + if (auto err = add_plane2(heif_channel_Cb, chroma_width(w, chroma), chroma_height(h, chroma), source->get_bits_per_pixel(heif_channel_Cb))) { + return err; + } + if (auto err = add_plane2(heif_channel_Cr, chroma_width(w, chroma), chroma_height(h, chroma), source->get_bits_per_pixel(heif_channel_Cr))) { + return err; + } break; case heif_colorspace_RGB: - add_plane(heif_channel_R, w, h, source->get_bits_per_pixel(heif_channel_R)); - add_plane(heif_channel_G, w, h, source->get_bits_per_pixel(heif_channel_G)); - add_plane(heif_channel_B, w, h, source->get_bits_per_pixel(heif_channel_B)); + if (auto err = add_plane2(heif_channel_R, w, h, source->get_bits_per_pixel(heif_channel_R))) { + return err; + } + if (auto err = add_plane2(heif_channel_G, w, h, source->get_bits_per_pixel(heif_channel_G))) { + return err; + } + if (auto err = add_plane2(heif_channel_B, w, h, source->get_bits_per_pixel(heif_channel_B))) { + return err; + } break; default: assert(false); @@ -1392,6 +1456,10 @@ void HeifPixelImage::create_clone_image_at_new_size(const std::shared_ptrhas_alpha()) { - add_plane(heif_channel_Alpha, w, h, source->get_bits_per_pixel(heif_channel_Alpha)); + if (auto err = add_plane2(heif_channel_Alpha, w, h, source->get_bits_per_pixel(heif_channel_Alpha))) { + return err; + } } + + return Error::Ok; } diff --git a/libheif/pixelimage.h b/libheif/pixelimage.h index 0b24b852f9..fcbc3aba2a 100644 --- a/libheif/pixelimage.h +++ b/libheif/pixelimage.h @@ -81,9 +81,9 @@ class HeifPixelImage : public std::enable_shared_from_this, void create(uint32_t width, uint32_t height, heif_colorspace colorspace, heif_chroma chroma); - void create_clone_image_at_new_size(const std::shared_ptr& source, uint32_t w, uint32_t h); + Error create_clone_image_at_new_size2(const std::shared_ptr& source, uint32_t w, uint32_t h); - bool add_plane(heif_channel channel, uint32_t width, uint32_t height, int bit_depth); + Error add_plane2(heif_channel channel, uint32_t width, uint32_t height, int bit_depth); bool add_channel(heif_channel channel, uint32_t width, uint32_t height, heif_channel_datatype datatype, int bit_depth); @@ -156,11 +156,11 @@ class HeifPixelImage : public std::enable_shared_from_this, heif_channel src_channel, heif_channel dst_channel); - void extract_alpha_from_RGBA(const std::shared_ptr& srcimage); + Error extract_alpha_from_RGBA2(const std::shared_ptr& srcimage); void fill_plane(heif_channel dst_channel, uint16_t value); - void fill_new_plane(heif_channel dst_channel, uint16_t value, int width, int height, int bpp); + Error fill_new_plane2(heif_channel dst_channel, uint16_t value, int width, int height, int bpp); void transfer_plane_from_image_as(const std::shared_ptr& source, heif_channel src_channel, @@ -190,9 +190,9 @@ class HeifPixelImage : public std::enable_shared_from_this, void debug_dump() const; - bool extend_padding_to_size(uint32_t width, uint32_t height, bool adjust_size = false); + Error extend_padding_to_size2(uint32_t width, uint32_t height, bool adjust_size = false); - bool extend_to_size_with_zero(uint32_t width, uint32_t height); + Error extend_to_size_with_zero2(uint32_t width, uint32_t height); // --- pixel aspect ratio @@ -243,7 +243,7 @@ class HeifPixelImage : public std::enable_shared_from_this, private: struct ImagePlane { - bool alloc(uint32_t width, uint32_t height, heif_channel_datatype datatype, int bit_depth, int num_interleaved_components); + Error alloc2(uint32_t width, uint32_t height, heif_channel_datatype datatype, int bit_depth, int num_interleaved_components); heif_channel_datatype m_datatype = heif_channel_datatype_unsigned_integer; uint8_t m_bit_depth = 0; diff --git a/tests/conversion.cc b/tests/conversion.cc index 1ea9f444ef..ea10f3e52b 100644 --- a/tests/conversion.cc +++ b/tests/conversion.cc @@ -237,8 +237,11 @@ bool MakeTestImage(const ColorState& state, int width, int height, int half_max = (1 << (plane.bit_depth -1)); uint16_t value = SwapBytesIfNeeded( static_cast(half_max + i * 10 + i), state.chroma); - image->fill_new_plane(plane.channel, value, plane.width, plane.height, - plane.bit_depth); + auto err = image->fill_new_plane2(plane.channel, value, plane.width, plane.height, + plane.bit_depth); + if (err) { + return false; + } } return true; } @@ -288,8 +291,9 @@ void TestConversion(const std::string& test_name, const ColorState& input_state, int height = 8; REQUIRE(MakeTestImage(input_state, width, height, in_image.get())); - std::shared_ptr out_image; - out_image = pipeline.convert_image(in_image); + auto out_image_result = pipeline.convert_image(in_image); + REQUIRE(out_image_result); + std::shared_ptr out_image = *out_image_result; REQUIRE(out_image != nullptr); CHECK(out_image->get_colorspace() == target_state.colorspace); @@ -315,9 +319,9 @@ void TestConversion(const std::string& test_name, const ColorState& input_state, ColorConversionPipeline reverse_pipeline; if (reverse_pipeline.construct_pipeline(target_state, input_state, options)) { INFO("reverse pipeline: " << reverse_pipeline.debug_dump_pipeline()); - std::shared_ptr recovered_image = - reverse_pipeline.convert_image(out_image); - REQUIRE(recovered_image != nullptr); + auto recovered_image_result =reverse_pipeline.convert_image(out_image); + REQUIRE(recovered_image_result); + std::shared_ptr recovered_image = *recovered_image_result; // If the alpha plane was lost in the target state, it should come back // as the max value for the given bpp, i.e. (1<& img, heif_channel channel, int w, int h, const std::vector& pixels) { - img->add_plane(channel, w, h, 8); + auto error = img->add_plane2(channel, w, h, 8); + REQUIRE(!error); uint32_t stride; uint8_t* p = img->get_plane(channel, &stride); @@ -646,7 +651,9 @@ TEST_CASE("Bilinear upsampling", "[heif_image]") std::shared_ptr img = std::make_shared(); img->create(4, 4, heif_colorspace_YCbCr, heif_chroma_420); - img->fill_new_plane(heif_channel_Y, 128, 4,4, 8); + auto error = img->fill_new_plane2(heif_channel_Y, 128, 4,4, 8); + REQUIRE(!error); + fill_plane(img, heif_channel_Cb, 2,2, {10, 40, 100, 240}); @@ -654,7 +661,9 @@ TEST_CASE("Bilinear upsampling", "[heif_image]") {255, 200, 50, 0}); - std::shared_ptr out = convert_colorspace(img, heif_colorspace_YCbCr, heif_chroma_444, nullptr, 8, options); + auto conversionResult = convert_colorspace(img, heif_colorspace_YCbCr, heif_chroma_444, nullptr, 8, options); + REQUIRE(conversionResult); + std::shared_ptr out = *conversionResult; assert_plane(out, heif_channel_Cb, { @@ -682,11 +691,15 @@ TEST_CASE("RGB 5-6-5 to RGB") const uint32_t width = 3; const uint32_t height = 2; img->create(width, height, heif_colorspace_RGB, heif_chroma_444); - img->add_plane(heif_channel_R, width, height, 5); + Error err; + err = img->add_plane2(heif_channel_R, width, height, 5); + REQUIRE(!err); REQUIRE(img->get_bits_per_pixel(heif_channel_R) == 5); - img->add_plane(heif_channel_G, width, height, 6); + err = img->add_plane2(heif_channel_G, width, height, 6); + REQUIRE(!err); REQUIRE(img->get_bits_per_pixel(heif_channel_G) == 6); - img->add_plane(heif_channel_B, width, height, 5); + err = img->add_plane2(heif_channel_B, width, height, 5); + REQUIRE(!err); REQUIRE(img->get_bits_per_pixel(heif_channel_B) == 5); uint8_t v = 1; @@ -701,7 +714,9 @@ TEST_CASE("RGB 5-6-5 to RGB") } } - std::shared_ptr out = convert_colorspace(img, heif_colorspace_RGB, heif_chroma_444, nullptr, 8, options); + auto conversionResult = convert_colorspace(img, heif_colorspace_RGB, heif_chroma_444, nullptr, 8, options); + REQUIRE(conversionResult); + std::shared_ptr out = *conversionResult; assert_plane(out, heif_channel_R, {8, 16, 24, 33, 41, 49}); assert_plane(out, heif_channel_G, {28, 32, 36, 40, 44, 48});