Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
imageio_webp.c
Go to the documentation of this file.
1/*
2 This file is part of the Ansel project.
3 Copyright (C) 2023 Alynx Zhou.
4
5 Ansel is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 Ansel is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Ansel. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#include "system/macros.h"
20#include "system/mem_alloc.h"
21#include "common/logging.h"
22#include "system/openmp.h"
23#include <glib/gstdio.h>
24#include <inttypes.h>
25
26#include <webp/decode.h>
27#include <webp/mux.h>
28
29#include "common/image.h"
30#include "develop/imageop.h" // for IOP_CS_RGB
31
33{
34 int w, h;
35 WebPMux *mux;
36 WebPData wp_data;
37 WebPData icc_profile;
38
39 FILE *f = g_fopen(filename, "rb");
40 if(IS_NULL_PTR(f))
41 {
42 dt_print(DT_DEBUG_IMAGEIO, "[webp_open] cannot open file for read: %s\n", filename);
44 }
45
46 fseek(f, 0, SEEK_END);
47 size_t filesize = ftell(f);
48 fseek(f, 0, SEEK_SET);
49
50 void *read_buffer = g_malloc(filesize);
51
52 if(fread(read_buffer, 1, filesize, f) != filesize)
53 {
54 fclose(f);
55 dt_free(read_buffer);
56 dt_print(DT_DEBUG_IMAGEIO, "[webp_open] failed to read %" G_GSIZE_FORMAT " bytes from %s\n", filesize, filename);
58 }
59 fclose(f);
60
61 // WebPGetInfo should tell us the image dimensions needed for darktable image buffer allocation
62 if(!WebPGetInfo(read_buffer, filesize, &w, &h))
63 {
64 // If we couldn't get the webp metadata, then the file we're trying to read is most likely in
65 // a different format (darktable just trying different loaders until it finds the right one).
66 // We just have to return without complaining.
67 dt_free(read_buffer);
69 }
70 img->width = w;
71 img->height = h;
72 img->dsc.channels = 4;
73 img->dsc.datatype = TYPE_FLOAT;
74 img->dsc.bpp = 4 * sizeof(float);
75 img->dsc.cst = IOP_CS_RGB;
76 img->dsc.filters = 0u;
77 img->flags &= ~DT_IMAGE_RAW;
78 img->flags &= ~DT_IMAGE_S_RAW;
79 img->flags &= ~DT_IMAGE_HDR;
80 img->flags |= DT_IMAGE_LDR;
81 img->loader = LOADER_WEBP;
82
83 if(IS_NULL_PTR(mbuf))
84 {
85 dt_free(read_buffer);
86 return DT_IMAGEIO_OK;
87 }
88
89 float *mipbuf = (float *)dt_mipmap_cache_alloc(mbuf, img);
90 if(IS_NULL_PTR(mipbuf))
91 {
92 dt_free(read_buffer);
93 dt_print(DT_DEBUG_IMAGEIO, "[webp_open] could not alloc full buffer for image: %s\n", img->filename);
95 }
96
97 uint8_t *int_RGBA_buf = WebPDecodeRGBA(read_buffer, filesize, &w, &h);
98 if(IS_NULL_PTR(int_RGBA_buf))
99 {
100 dt_free(read_buffer);
101 dt_print(DT_DEBUG_IMAGEIO,"[webp_open] failed to decode file: %s\n", filename);
103 }
104
105 uint8_t intval;
106 float floatval;
107 __OMP_PARALLEL_FOR__(private(intval, floatval))
108 for(int i=0; i < w*h*4; i++)
109 {
110 intval = *(int_RGBA_buf+i);
111 floatval = intval / 255.f;
112 *(mipbuf+i) = floatval;
113 }
114
115 WebPFree(int_RGBA_buf);
116
117 wp_data.bytes = (uint8_t *)read_buffer;
118 wp_data.size = filesize;
119 mux = WebPMuxCreate(&wp_data, 0); // 0 = data will NOT be copied to the mux object
120
121 if(mux)
122 {
123 WebPMuxGetChunk(mux, "ICCP", &icc_profile);
124 if(icc_profile.size)
125 {
126 img->profile_size = icc_profile.size;
127 img->profile = (uint8_t *)g_malloc0(icc_profile.size);
128 memcpy(img->profile, icc_profile.bytes, icc_profile.size);
129 }
130 WebPMuxDelete(mux);
131 }
132
133 dt_free(read_buffer);
134 return DT_IMAGEIO_OK;
135}
136
137// clang-format off
138// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
139// vim: shiftwidth=2 expandtab tabstop=2 cindent
140// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
141// clang-format on
@ IOP_CS_RGB
const float f
@ TYPE_FLOAT
Definition format.h:56
dt_imageio_retval_t
Definition image.h:91
@ DT_IMAGEIO_OK
Definition image.h:92
@ DT_IMAGEIO_CACHE_FULL
Definition image.h:95
@ DT_IMAGEIO_FILE_CORRUPTED
Definition image.h:94
@ DT_IMAGE_LDR
Definition image.h:122
@ LOADER_WEBP
Definition image.h:296
dt_imageio_retval_t dt_imageio_open_webp(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
@ DT_DEBUG_IMAGEIO
Definition logging.h:68
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition macros.h:96
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
Definition mem_alloc.h:171
void * dt_mipmap_cache_alloc(dt_mipmap_buffer_t *buf, const dt_image_t *img)
#define __OMP_PARALLEL_FOR__(...)
Definition openmp.h:95
int32_t height
Definition image.h:397
dt_image_loader_t loader
Definition image.h:417
int32_t flags
Definition image.h:401
int32_t width
Definition image.h:397
uint32_t profile_size
Definition image.h:423
dt_iop_buffer_dsc_t dsc
Definition image.h:419
uint8_t * profile
Definition image.h:422
char filename[DT_MAX_FILENAME_LEN]
Definition image.h:386
uint32_t filters
Definition format.h:89
unsigned int channels
Definition format.h:83
dt_iop_buffer_type_t datatype
Definition format.h:85