Skip to content

Commit

Permalink
Merge pull request #16711 from victoryforce/webp-loader-improvements
Browse files Browse the repository at this point in the history
[imageio] WebP loader improvements
  • Loading branch information
TurboGit authored May 1, 2024
2 parents 3a099fc + e6f32b6 commit 4d8df8a
Showing 1 changed file with 31 additions and 27 deletions.
58 changes: 31 additions & 27 deletions src/imageio/imageio_webp.c
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -16,8 +16,6 @@
along with darktable. If not, see <http://www.gnu.org/licenses/>.
*/

#include <inttypes.h>

#include <webp/decode.h>
#include <webp/mux.h>

Expand All @@ -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");
Expand All @@ -55,53 +51,61 @@ 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).
// We just have to return without complaining.
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;

float *mipbuf = (float *)dt_mipmap_cache_alloc(mbuf, img);
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)
{
Expand Down

0 comments on commit 4d8df8a

Please sign in to comment.