Centralise image loading errors

This commit is contained in:
p
2026-10-02 23:45:01 +02:00
parent 8dca81061c
commit 79ef749f22
27 changed files with 443 additions and 521 deletions
+2 -1
View File
@@ -163,7 +163,8 @@ decode_webp(const QByteArray &bytes, dawn::Cmm &cmm, dawn::Profile *source,
WebPFree(bgra);
return {};
}
dawn::ImagePtr image = dawn::image_new(uint32_t(width), uint32_t(height));
dawn::ImagePtr image =
dawn::image_new(uint32_t(width), uint32_t(height), nullptr);
if (image &&
!cmm.transform_bgra8_to_bgra16(bgra, image->data.data(), image->width,
image->height, source, target, true))
+10 -7
View File
@@ -115,18 +115,20 @@ render_dimensions(double width, double height, uint32_t *out_width,
}
ImagePtr
image_new(uint32_t width, uint32_t height)
image_new(uint32_t width, uint32_t height, Error *error)
{
if (width == 0 || height == 0)
if (width == 0 || height == 0) {
set_error(error, _("invalid image dimensions"));
return nullptr;
if (width > kMaxDimension || height > kMaxDimension)
return nullptr;
if (width > UINT32_MAX / kBytesPerPixel)
}
if (width > kMaxDimension || height > kMaxDimension ||
width > UINT32_MAX / kBytesPerPixel ||
height > SIZE_MAX / (width * kBytesPerPixel)) {
set_error(error, _("image dimensions too large"));
return nullptr;
}
uint32_t stride = width * kBytesPerPixel;
if (height > SIZE_MAX / stride)
return nullptr;
ImagePtr image;
try {
@@ -134,6 +136,7 @@ image_new(uint32_t width, uint32_t height)
StageClock clk(&OpenTiming::alloc_ms);
image->data.assign(size_t(stride) * height, 0);
} catch (const bad_alloc &) {
set_error(error, _("image allocation failure"));
return nullptr;
}
image->width = width;
+3 -2
View File
@@ -385,8 +385,9 @@ row_u16(const Image &img, uint32_t y)
return assume_aligned<const uint16_t>(row_bytes(img, y));
}
/// Allocate a zeroed working-format image. Returns null on OOM / overflow.
ImagePtr image_new(uint32_t width, uint32_t height);
/// Allocate a zeroed working-format image. Returns null, saying why, when the
/// dimensions are unusable or memory runs out.
ImagePtr image_new(uint32_t width, uint32_t height, Error *error);
// --- Opening -----------------------------------------------------------------
+1 -2
View File
@@ -119,11 +119,10 @@ CGPDFRenderClosure::render(const OpenContext &ctx, double scale, Error *error)
CGContextDrawPDFPage(context, page);
CGContextRelease(context);
ImagePtr image = image_new(uw, uh);
ImagePtr image = image_new(uw, uh, error);
if (!image) {
if (icc)
CFRelease(icc);
set_error(error, _("image allocation failure"));
return nullptr;
}
+4 -8
View File
@@ -110,11 +110,9 @@ load_float_frame(const dnrs_frame &frame, const OpenContext &ctx, Error *error)
set_error(error, _("invalid or truncated frame"));
return nullptr;
}
ImagePtr image = image_new(frame.width, frame.height);
if (!image) {
set_error(error, _("image allocation failure"));
ImagePtr image = image_new(frame.width, frame.height, error);
if (!image)
return nullptr;
}
vector<float> rgba(size_t(frame.width) * frame.height * 4, 1);
for (uint32_t y = 0; y < frame.height; y++) {
@@ -168,11 +166,9 @@ load_frame(const dnrs_frame &frame, Error *error)
return nullptr;
}
ImagePtr image = image_new(frame.width, frame.height);
if (!image) {
set_error(error, _("image allocation failure"));
ImagePtr image = image_new(frame.width, frame.height, error);
if (!image)
return nullptr;
}
switch (frame.format) {
case DNRS_PIXEL_GRAY8:
pack_gray(*image, frame, false, false);
+4 -4
View File
@@ -172,9 +172,8 @@ decode_heif_pixels(
return nullptr;
}
ImagePtr result = image_new(uint32_t(w), uint32_t(h));
ImagePtr result = image_new(uint32_t(w), uint32_t(h), error);
if (!result) {
set_error(error, _("image allocation failure"));
heif_image_release(image);
return nullptr;
}
@@ -691,9 +690,10 @@ load_heif_sample(const heif_image *img, bool has_alpha, uint64_t *retained,
return nullptr;
}
ImagePtr frame = image_new(uint32_t(w), uint32_t(h));
Error error;
ImagePtr frame = image_new(uint32_t(w), uint32_t(h), &error);
if (!frame) {
add_warning(ctx, _("image allocation failure"));
add_warning(ctx, error.message);
return nullptr;
}
+8 -16
View File
@@ -280,11 +280,9 @@ decode_low_depth(const Entry &entry, const IconInfo &info,
mask = mask_data(entries, info, &one_bit_mask);
}
ImagePtr image = image_new(info.width, info.height);
if (!image) {
set_error(error, _("failed to allocate indexed icon image"));
ImagePtr image = image_new(info.width, info.height, error);
if (!image)
return nullptr;
}
for (uint32_t y = 0; y < info.height; y++) {
for (uint32_t x = 0; x < info.width; x++) {
size_t pixel = size_t(y) * info.width + x;
@@ -360,11 +358,9 @@ decode_argb_rle(span<const uint8_t> data, const IconInfo &info, Error *error)
error))
return nullptr;
ImagePtr image = image_new(info.width, info.height);
if (!image) {
set_error(error, _("failed to allocate ARGB icon image"));
ImagePtr image = image_new(info.width, info.height, error);
if (!image)
return nullptr;
}
for (uint32_t y = 0; y < info.height; y++)
for (uint32_t x = 0; x < info.width; x++) {
size_t p = size_t(y) * info.width + x;
@@ -402,11 +398,9 @@ decode_rgb24(const Entry &entry, const IconInfo &info,
bool one_bit_mask = false;
span<const uint8_t> mask = mask_data(entries, info, &one_bit_mask);
ImagePtr image = image_new(info.width, info.height);
if (!image) {
set_error(error, _("failed to allocate RGB icon image"));
ImagePtr image = image_new(info.width, info.height, error);
if (!image)
return nullptr;
}
for (uint32_t y = 0; y < info.height; y++)
for (uint32_t x = 0; x < info.width; x++) {
size_t p = size_t(y) * info.width + x;
@@ -431,11 +425,9 @@ decode_argb_raw(span<const uint8_t> data, const IconInfo &info, Error *error)
set_error(error, _("unsupported ARGB icon encoding"));
return nullptr;
}
ImagePtr image = image_new(info.width, info.height);
if (!image) {
set_error(error, _("failed to allocate ARGB icon image"));
ImagePtr image = image_new(info.width, info.height, error);
if (!image)
return nullptr;
}
for (uint32_t y = 0; y < info.height; y++)
for (uint32_t x = 0; x < info.width; x++) {
size_t p = size_t(y) * info.width + x;
+4 -7
View File
@@ -144,7 +144,7 @@ imageio_gain_map_pixels(CFDictionaryRef info, const GainMap &metadata)
double(CFDataGetLength(data)) < stride * (height - 1) + width)
return nullptr;
ImagePtr pixels = image_new(uint32_t(width), uint32_t(height));
ImagePtr pixels = image_new(uint32_t(width), uint32_t(height), nullptr);
if (!pixels)
return nullptr;
@@ -253,11 +253,9 @@ load_imageio_hdr(CGImageRef cg, const OpenContext &ctx, Error *error)
context, CGRectMake(0, 0, double(width), double(height)), cg);
CGContextRelease(context);
ImagePtr image = image_new(uint32_t(width), uint32_t(height));
if (!image) {
set_error(error, _("image allocation failure"));
ImagePtr image = image_new(uint32_t(width), uint32_t(height), error);
if (!image)
return nullptr;
}
if (!split_hdr(*image, ctx, rgba, true, kRec2020Primaries, error))
return nullptr;
return image;
@@ -306,11 +304,10 @@ load_imageio_image(CGImageRef cg, const OpenContext &ctx, Error *error)
return nullptr;
}
ImagePtr image = image_new(uint32_t(width), uint32_t(height));
ImagePtr image = image_new(uint32_t(width), uint32_t(height), error);
if (!image) {
if (icc)
CFRelease(icc);
set_error(error, _("image allocation failure"));
return nullptr;
}
+2 -4
View File
@@ -660,11 +660,9 @@ load_libjpeg_turbo(span<const uint8_t> data, const OpenContext &ctx,
size_t width = size_t(cinfo.output_width);
size_t height = size_t(cinfo.output_height);
ImagePtr image = image_new(uint32_t(width), uint32_t(height));
if (!image) {
set_error(error, _("image allocation failure"));
ImagePtr image = image_new(uint32_t(width), uint32_t(height), error);
if (!image)
return nullptr;
}
#if defined MAXJ12SAMPLE || defined MAXJ16SAMPLE
if (high) {
+4 -10
View File
@@ -281,17 +281,11 @@ split_signal_frame(
static bool
append_decoded_frame(JxlLoadContext &ctx, Error *error)
{
// This also catches a frame arriving before the header we subscribed to.
if (!ctx.info.xsize || !ctx.info.ysize) {
set_error(error, _("invalid image dimensions"));
// Zero dimensions also catch a frame arriving before the header we
// subscribed to.
ImagePtr image = image_new(ctx.info.xsize, ctx.info.ysize, error);
if (!image)
return false;
}
ImagePtr image = image_new(ctx.info.xsize, ctx.info.ysize);
if (!image) {
set_error(error, _("image allocation failure"));
return false;
}
// Coalescing stays on, so every frame covers the whole canvas.
if (ctx.transfer != 8)
+2 -4
View File
@@ -365,11 +365,9 @@ decode_image(JxrLoadContext &ctx, const OpenContext &octx, Error *error)
return nullptr;
}
ImagePtr image = image_new(uint32_t(width), uint32_t(height));
if (!image) {
set_error(error, _("image allocation failure"));
ImagePtr image = image_new(uint32_t(width), uint32_t(height), error);
if (!image)
return nullptr;
}
U32 icc = 0;
if (!ctx.decoder->GetColorContext(ctx.decoder, nullptr, &icc) && icc) {
+2 -4
View File
@@ -133,11 +133,9 @@ load_libraw_page(libraw_data_t *iprc, const OpenContext &ctx,
return nullptr;
}
ImagePtr result = image_new(iprc->sizes.width, iprc->sizes.height);
if (!result) {
set_error(error, _("image allocation failure"));
ImagePtr result = image_new(iprc->sizes.width, iprc->sizes.height, error);
if (!result)
return nullptr;
}
develop(iprc, *result);
result->orientation = orientation;
+1 -2
View File
@@ -99,9 +99,8 @@ LibrsvgRenderClosure::render(const OpenContext &ctx, double scale, Error *error)
}
cairo_surface_flush(surface);
ImagePtr image = image_new(uw, uh);
ImagePtr image = image_new(uw, uh, error);
if (!image) {
set_error(error, _("image allocation failure"));
cairo_surface_destroy(surface);
return nullptr;
}
+2 -4
View File
@@ -388,11 +388,9 @@ build_image(OpenJpegLoadContext &ctx, Error *error)
make_sampler(c, first.dx ? first.dx : 1, first.dy ? first.dy : 1);
}
ImagePtr out = image_new(first.w, first.h);
if (!out) {
set_error(error, _("image allocation failure"));
ImagePtr out = image_new(first.w, first.h, error);
if (!out)
return nullptr;
}
write_pixels(layout, samplers, *out);
if (image.icc_profile_buf && image.icc_profile_len) {
+2 -4
View File
@@ -112,11 +112,9 @@ PopplerRenderClosure::render(const OpenContext &ctx, double scale, Error *error)
return nullptr;
}
ImagePtr image = image_new(uint32_t(rw), uint32_t(rh));
if (!image) {
set_error(error, _("image allocation failure"));
ImagePtr image = image_new(uint32_t(rw), uint32_t(rh), error);
if (!image)
return nullptr;
}
pack_rgb8_to_bgra16(*image, (const uint8_t *) raster.const_data(),
size_t(raster.bytes_per_row()));
+2 -4
View File
@@ -444,11 +444,9 @@ load_psd(span<const uint8_t> data, const OpenContext &ctx, Error *error)
return nullptr;
}
ImagePtr image = image_new(h.width, h.height);
if (!image) {
set_error(error, _("unsupported PSD image dimensions"));
ImagePtr image = image_new(h.width, h.height, error);
if (!image)
return nullptr;
}
vector<uint8_t> planes;
if (!read_composite(r, h, &planes, error))
+2 -5
View File
@@ -5,7 +5,6 @@
// SPDX-License-Identifier: MPL-2.0
//
#include "gettext.hpp"
#include "libdn-loaders.hpp"
#include "libdn.hpp"
@@ -85,11 +84,9 @@ ResvgRenderClosure::render(const OpenContext &ctx, double scale, Error *error)
transform.d = float(scale);
resvg_render(tree_, transform, uw, uh, (char *) pixmap.data());
ImagePtr image = image_new(uw, uh);
if (!image) {
set_error(error, _("image allocation failure"));
ImagePtr image = image_new(uw, uh, error);
if (!image)
return nullptr;
}
// resvg_render() always produces premultiplied RGBA8888; pack it
// into working-format BGRA16, leaving the association untouched.
+3 -17
View File
@@ -328,22 +328,15 @@ load_tiff_directory_u16(TIFF *tiff, const OpenContext &ctx,
if (!grey && !rgb)
return nullptr;
if (width > kMaxDimension || height > kMaxDimension) {
set_error(error, _("image dimensions too large"));
return nullptr;
}
tmsize_t scan_bytes = TIFFScanlineSize(tiff);
if (scan_bytes <= 0) {
set_error(error, _("invalid TIFF scanline size"));
return nullptr;
}
ImagePtr image = image_new(width, height);
if (!image) {
set_error(error, _("image allocation failure"));
ImagePtr image = image_new(width, height, error);
if (!image)
return nullptr;
}
vector<uint8_t> scan;
scan.resize(size_t(scan_bytes));
@@ -447,15 +440,8 @@ load_tiff_directory(TIFF *tiff, const OpenContext &ctx, Error *error)
return nullptr;
}
if (img.width > kMaxDimension || img.height > kMaxDimension) {
set_error(error, _("image dimensions too large"));
TIFFRGBAImageEnd(&img);
return nullptr;
}
ImagePtr image = image_new(img.width, img.height);
ImagePtr image = image_new(img.width, img.height, error);
if (!image) {
set_error(error, _("image allocation failure"));
TIFFRGBAImageEnd(&img);
return nullptr;
}
+4 -8
View File
@@ -62,11 +62,9 @@ load_webp_still(WebPDecoderConfig *config, const WebPData &wd, bool premultiply,
{
auto width = uint32_t(config->input.width);
auto height = uint32_t(config->input.height);
ImagePtr image = image_new(width, height);
if (!image) {
set_error(error, _("image allocation failure"));
ImagePtr image = image_new(width, height, error);
if (!image)
return nullptr;
}
config->options.use_threads = 1;
config->output.width = config->input.width;
@@ -117,11 +115,9 @@ load_webp_frame(WebPAnimDecoder *dec, const WebPAnimInfo &info,
return nullptr;
}
ImagePtr image = image_new(info.canvas_width, info.canvas_height);
if (!image) {
set_error(error, _("image allocation failure"));
ImagePtr image = image_new(info.canvas_width, info.canvas_height, error);
if (!image)
return nullptr;
}
size_t stride = size_t(info.canvas_width) * 4;
widen_bgra8_to_bgra16(*image, buf, stride);
+6 -11
View File
@@ -198,7 +198,7 @@ crop(const Image &src, wuffs_base__rect_ie_u32 r)
{
uint32_t w = r.max_excl_x - r.min_incl_x;
uint32_t h = r.max_excl_y - r.min_incl_y;
ImagePtr out = image_new(w, h);
ImagePtr out = image_new(w, h, nullptr);
if (!out)
return nullptr;
for (uint32_t y = 0; y < h; y++) {
@@ -301,11 +301,9 @@ load_wuffs_frame_compose(WuffsLoadContext &ctx, ImagePtr &image,
{
// Copy the previous frame to a new image.
const ImagePtr &prev = ctx.result_tail;
ImagePtr canvas = image_new(prev->width, prev->height);
if (!canvas) {
set_error(error, _("image allocation failure"));
ImagePtr canvas = image_new(prev->width, prev->height, error);
if (!canvas)
return false;
}
const Image &base = ctx.restore_previous ? *ctx.restore_previous : *prev;
memcpy(canvas->data.data(), base.data.data(), base.data.size());
@@ -334,11 +332,9 @@ load_wuffs_frame_compose(WuffsLoadContext &ctx, ImagePtr &image,
if (wuffs_base__frame_config__disposal(&fc) ==
WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_PREVIOUS) {
ctx.restore_previous = image_new(canvas->width, canvas->height);
if (!ctx.restore_previous) {
set_error(error, _("image allocation failure"));
ctx.restore_previous = image_new(canvas->width, canvas->height, error);
if (!ctx.restore_previous)
return false;
}
memcpy(ctx.restore_previous->data.data(), canvas->data.data(),
canvas->data.size());
}
@@ -389,9 +385,8 @@ load_wuffs_frame(WuffsLoadContext &ctx, Error *error)
break;
}
ImagePtr image = image_new(ctx.width, ctx.height);
ImagePtr image = image_new(ctx.width, ctx.height, error);
if (!image) {
set_error(error, _("image allocation failure"));
ctx.result.reset();
ctx.result_tail.reset();
return false;
+1 -1
View File
@@ -108,7 +108,7 @@ load_xcursor_image(const XcursorImage *src)
if (!src->width || !src->height)
return nullptr;
ImagePtr image = image_new(src->width, src->height);
ImagePtr image = image_new(src->width, src->height, nullptr);
if (!image)
return nullptr;
+365 -388
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -93,7 +93,7 @@ load_fixture(const string &name)
static void
test_pack_helpers()
{
dawn::ImagePtr img = dawn::image_new(1, 1);
dawn::ImagePtr img = dawn::image_new(1, 1, nullptr);
CHECK(img != nullptr);
// RGBA8 red → B=0 G=0 R=65535 A=65535
@@ -186,7 +186,7 @@ test_unpremultiply_alpha_last8()
static dawn::ImagePtr
image_1x1(uint16_t b, uint16_t g, uint16_t r, uint16_t a)
{
dawn::ImagePtr img = dawn::image_new(1, 1);
dawn::ImagePtr img = dawn::image_new(1, 1, nullptr);
if (!img) {
test::fail("image_new failed");
exit(1);
@@ -448,7 +448,7 @@ test_cmyk_cms_opaque()
auto src = cmm->get_profile(bytes);
CHECK(src != nullptr);
dawn::ImagePtr img = dawn::image_new(1, 1);
dawn::ImagePtr img = dawn::image_new(1, 1, nullptr);
CHECK(img != nullptr);
const uint8_t cmyk[4] = {0, 255, 255, 0};
cmm->convert_cmyk8(
+1 -1
View File
@@ -386,7 +386,7 @@ test_apple()
CHECK(!dawn::gain_map_applies(dawn::apple_gain_map(none), {}));
// Texels become normalized log2 gain.
auto pixels = dawn::image_new(3, 1);
auto pixels = dawn::image_new(3, 1, nullptr);
uint16_t *p = dawn::row_u16(*pixels, 0);
const uint16_t texels[3] = {0, 32768, 65535};
for (int i = 0; i < 3; i++)
+1 -1
View File
@@ -21,7 +21,7 @@ using namespace std;
static dawn::ImagePtr
gradient(uint32_t w, uint32_t h)
{
auto image = dawn::image_new(w, h);
auto image = dawn::image_new(w, h, nullptr);
CHECK(image);
if (!image)
return image;
+1 -1
View File
@@ -1257,7 +1257,7 @@ test_thumb_tiles()
return;
}
auto image = dawn::image_new(512, 512);
auto image = dawn::image_new(512, 512, nullptr);
for (uint32_t y = 0; y < image->height; y++)
for (uint32_t x = 0; x < image->width; x++)
memcpy(dawn::row_u16(*image, y) + x * 4, &kRed, sizeof kRed);
+3 -2
View File
@@ -53,7 +53,8 @@ split(uint32_t width, const vector<float> &rgb, const vector<float> &alpha,
shared_ptr<dawn::Profile> screen = nullptr)
{
Split result;
result.image = dawn::image_new(width, uint32_t(rgb.size() / 3 / width));
result.image =
dawn::image_new(width, uint32_t(rgb.size() / 3 / width), nullptr);
dawn::OpenContext ctx;
ctx.gain_maps = gain_maps;
ctx.warnings = &result.warnings;
@@ -314,7 +315,7 @@ static dawn::ImagePtr
split_signal(
uint8_t transfer, const vector<double> &signal, double peak, double alpha)
{
auto image = dawn::image_new(uint32_t(signal.size()), 1);
auto image = dawn::image_new(uint32_t(signal.size()), 1, nullptr);
uint16_t *p = dawn::row_u16(*image, 0);
for (size_t i = 0; i < signal.size(); i++, p += 4) {
p[0] = p[1] = p[2] = uint16_t(lround(signal[i] * alpha * 65535));