diff --git a/src/imageio/imageio_webp.c b/src/imageio/imageio_webp.c
index 0f245bd33eb2..7ab6655c300b 100644
--- a/src/imageio/imageio_webp.c
+++ b/src/imageio/imageio_webp.c
@@ -1,6 +1,6 @@
/*
This file is part of darktable,
- Copyright (C) 2022-2023 darktable developers.
+ Copyright (C) 2022-2024 darktable developers.
darktable is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -16,8 +16,6 @@
along with darktable. If not, see .
*/
-#include
-
#include
#include
@@ -27,9 +25,7 @@
dt_imageio_retval_t dt_imageio_open_webp(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
{
- int w, h;
- WebPMux *mux;
- WebPData wp_data;
+ int width, height;
WebPData icc_profile;
FILE *f = g_fopen(filename, "rb");
@@ -55,7 +51,7 @@ dt_imageio_retval_t dt_imageio_open_webp(dt_image_t *img, const char *filename,
fclose(f);
// WebPGetInfo should tell us the image dimensions needed for darktable image buffer allocation
- if(!WebPGetInfo(read_buffer, filesize, &w, &h))
+ if(!WebPGetInfo(read_buffer, filesize, &width, &height))
{
// If we couldn't get the webp metadata, then the file we're trying to read is most likely in
// a different format (darktable just trying different loaders until it finds the right one).
@@ -63,8 +59,22 @@ dt_imageio_retval_t dt_imageio_open_webp(dt_image_t *img, const char *filename,
g_free(read_buffer);
return DT_IMAGEIO_LOAD_FAILED;
}
- img->width = w;
- img->height = h;
+
+ // The maximum pixel dimensions of a WebP image is 16383 x 16383,
+ // so the number of pixels will never overflow int
+ const int npixels = width * height;
+
+ uint8_t *int_RGBA_buf = dt_alloc_align_uint8(npixels * 4);
+ int_RGBA_buf = WebPDecodeRGBAInto(read_buffer, filesize, int_RGBA_buf, npixels * 4, width * 4);
+ if(!int_RGBA_buf)
+ {
+ g_free(read_buffer);
+ dt_print(DT_DEBUG_ALWAYS,"[webp_open] failed to decode file: %s\n", filename);
+ return DT_IMAGEIO_LOAD_FAILED;
+ }
+
+ img->width = width;
+ img->height = height;
img->buf_dsc.channels = 4;
img->buf_dsc.datatype = TYPE_FLOAT;
@@ -72,36 +82,30 @@ dt_imageio_retval_t dt_imageio_open_webp(dt_image_t *img, const char *filename,
if(!mipbuf)
{
g_free(read_buffer);
+ dt_free_align(int_RGBA_buf);
dt_print(DT_DEBUG_ALWAYS, "[webp_open] could not alloc full buffer for image: %s\n", img->filename);
return DT_IMAGEIO_CACHE_FULL;
}
- uint8_t *int_RGBA_buf = WebPDecodeRGBA(read_buffer, filesize, &w, &h);
- if(!int_RGBA_buf)
- {
- g_free(read_buffer);
- dt_print(DT_DEBUG_ALWAYS,"[webp_open] failed to decode file: %s\n", filename);
- return DT_IMAGEIO_LOAD_FAILED;
- }
-
- uint8_t intval;
- float floatval;
-
#ifdef _OPENMP
-#pragma omp parallel for private(intval, floatval)
+#pragma omp parallel for default(none) \
+ schedule(static) \
+ dt_omp_firstprivate(npixels, int_RGBA_buf, mipbuf)
#endif
- for(int i=0; i < w*h*4; i++)
+ for(int i = 0; i < npixels; i++)
{
- intval = *(int_RGBA_buf+i);
- floatval = intval / 255.f;
- *(mipbuf+i) = floatval;
+ dt_aligned_pixel_t pix = {0.0f, 0.0f, 0.0f, 0.0f};
+ for_three_channels(c)
+ pix[c] = *(int_RGBA_buf + i * 4 + c) / 255.f;
+ copy_pixel_nontemporal(&mipbuf[i * 4], pix);
}
- WebPFree(int_RGBA_buf);
+ dt_free_align(int_RGBA_buf);
+ WebPData wp_data;
wp_data.bytes = (uint8_t *)read_buffer;
wp_data.size = filesize;
- mux = WebPMuxCreate(&wp_data, 0); // 0 = data will NOT be copied to the mux object
+ WebPMux *mux = WebPMuxCreate(&wp_data, 0); // 0 = data will NOT be copied to the mux object
if(mux)
{