40#include <glib/gstdio.h>
50#include <webp/encode.h>
87#define _stringify(a) #a
88#define stringify(a) _stringify(a)
92 "out_of_memory: out of memory allocating objects",
93 "bitstream_out_of_memory: out of memory re-allocating byte buffer",
94 "null_parameter: null parameter passed to function",
95 "invalid_configuration: configuration is invalid",
96 "bad_dimension: bad picture dimension. maximum width and height "
97 "allowed is " stringify(WEBP_MAX_DIMENSION)
" pixels.",
98 "partition0_overflow: partition #0 is too big to fit 512k.\n"
99 "to reduce the size of this partition, try using less segments "
100 "with the -segments option, and eventually reduce the number of "
101 "header bits using -partition_limit. more details are available "
102 "in the manual (`man cwebp`)",
103 "partition_overflow: partition is too big to fit 16M",
104 "bad_write: picture writer returned an i/o error",
105 "file_too_big: file would be too big to fit in 4G",
106 "user_abort: encoding abort requested by user"
113 return "Unknown error. Consider open an issue to ansel to update the webp error list.";
128 void *exif,
int exif_len, int32_t imgid,
int num,
int total,
struct dt_dev_pixelpipe_t *pipe,
129 const gboolean export_masks)
135 WebPMemoryWriter writer;
136 WebPMemoryWriterInit(&writer);
137 WebPData icc_profile;
138 WebPDataInit(&icc_profile);
140 WebPDataInit(&bitstream);
141 WebPData assembled_data;
142 WebPDataInit(&assembled_data);
143 WebPMux *mux = WebPMuxNew();
150 if(!WebPConfigPreset(&config, webp_data->
hint, (
float)webp_data->
quality))
goto out;
154 config.image_hint = webp_data->
hint;
160 config.partition_limit = 70;
161 if(!WebPValidateConfig(&config))
163 fprintf(stderr,
"[webp export] error validating encoder configuration\n");
170 cmsSaveProfileToMem(out_profile, NULL, &len);
173 buf = (uint8_t *)g_malloc(len);
176 cmsSaveProfileToMem(out_profile, buf, &len);
177 icc_profile.bytes = buf;
178 icc_profile.size = len;
179 err = WebPMuxSetChunk(mux,
"ICCP", &icc_profile, 0);
180 if(err != WEBP_MUX_OK)
182 fprintf(stderr,
"[webp export] error adding ICC profile to WebP stream\n");
188 fprintf(stderr,
"[webp export] error allocating ICC profile buffer\n");
194 if(!WebPPictureInit(&pic))
goto out;
197 pic.use_argb = !!(config.lossless);
198 pic.writer = WebPMemoryWrite;
199 pic.custom_ptr = &writer;
201 WebPPictureImportRGBX(&pic, (
const uint8_t *)in_tmp, webp_data->
global.
width * 4);
209 WebPPictureSharpARGBToYUVA(&pic);
212 if(!WebPEncode(&config, &pic))
214 fprintf(stderr,
"[webp export] error during encoding (error: %d - %s)\n",
219 bitstream.bytes = writer.mem;
220 bitstream.size = writer.size;
221 err = WebPMuxSetImage(mux, &bitstream, 0);
222 if(err != WEBP_MUX_OK)
224 fprintf(stderr,
"[webp export] error adding image to WebP stream\n");
229 err = WebPMuxAssemble(mux, &assembled_data);
230 if(err != WEBP_MUX_OK)
232 fprintf(stderr,
"[webp export] error assembling the WebP file\n");
236 out = g_fopen(filename,
"w+b");
239 fprintf(stderr,
"[webp export] error creating file %s\n", filename);
242 if(fwrite(assembled_data.bytes, assembled_data.size, 1,
out) != 1)
244 fprintf(stderr,
"[webp export] error writing %" G_GSIZE_FORMAT
" bytes to file %s\n", assembled_data.size, filename);
251 WebPPictureFree(&pic);
252 WebPMemoryWriterClear(&writer);
254 WebPDataClear(&assembled_data);
267 const size_t old_params_size,
const int old_version,
const int new_version,
270 if(old_version == 1 && new_version == 2)
272 typedef struct dt_imageio_webp_v1_t
274 int max_width, max_height;
280 } dt_imageio_webp_v1_t;
282 dt_imageio_webp_v1_t *o = (dt_imageio_webp_v1_t *)old_params;
286 n->global.max_height = o->max_height;
287 n->global.width = o->width;
288 n->global.height = o->height;
289 g_strlcpy(
n->global.style, o->style,
sizeof(o->style));
290 n->comp_type = o->comp_type;
291 n->quality = o->quality;
293 *new_size = self->params_size(self);
313 if(
size != self->params_size(self))
return 1;
350 return _(
"WebP (8-bit)");
359 gtk_widget_set_sensitive(GTK_WIDGET(user_data),
FALSE);
361 gtk_widget_set_sensitive(GTK_WIDGET(user_data),
TRUE);
380 const int comp_type =
dt_conf_get_int(
"plugins/imageio/format/webp/comp_type");
381 const int quality =
dt_conf_get_int(
"plugins/imageio/format/webp/quality");
402 gtk_widget_set_tooltip_text(gui->
quality, _(
"applies only to lossy setting"));
414 gtk_widget_set_tooltip_text(gui->
hint,
415 _(
"image characteristics hint for the underlying encoder.\n"
416 "picture : digital picture, like portrait, inner shot\n"
417 "photo : outdoor photograph, with natural lighting\n"
418 "graphic : discrete tone image (graph, map-tile etc)"));
void dt_bauhaus_slider_set_default(GtkWidget *widget, float def)
float dt_bauhaus_slider_get(GtkWidget *widget)
int dt_bauhaus_combobox_get(GtkWidget *widget)
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
void dt_bauhaus_combobox_set(GtkWidget *widget, const int pos)
void dt_bauhaus_widget_set_label(GtkWidget *widget, const char *label)
GtkWidget * dt_bauhaus_slider_new_with_range(dt_bauhaus_t *bh, dt_gui_module_t *self, float min, float max, float step, float defval, int digits)
GtkWidget * dt_bauhaus_combobox_new(dt_bauhaus_t *bh, dt_gui_module_t *self)
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
void dt_bauhaus_combobox_add(GtkWidget *widget, const char *text)
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
const dt_colormatrix_t dt_aligned_pixel_t out
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
Integer for name, clamped to the bounds declared in the XML.
int dt_confgen_get_int(const char *name, dt_confgen_value_kind_t kind)
struct dt_bauhaus_t * dt_bauhaus_get_global(void)
int dt_exif_write_blob(uint8_t *blob, uint32_t size, const char *path, const int compressed)
What a photograph says about itself: the EXIF, IPTC and XMP tags a camera and a cataloguer write,...
@ FORMAT_FLAGS_SUPPORT_XMP
const dt_colorspaces_color_profile_t * dt_colorspaces_get_output_profile(const int32_t imgid, dt_colorspaces_color_profile_type_t *over_type, const char *over_filename)
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
dt_mipmap_buffer_dsc_flags flags
#define DT_MODULE(MODVER)
Instantiate the version handshake every module must export. Use once, at file scope,...
dt_colorspaces_color_profile_type_t
cmsHPROFILE profile
the actual profile; NULL for the three category entries
dt_imageio_module_data_t global
const char * mime(dt_imageio_module_data_t *data)
size_t params_size(dt_imageio_module_format_t *self)
void gui_reset(dt_imageio_module_format_t *self)
void gui_init(dt_imageio_module_format_t *self)
const char * extension(dt_imageio_module_data_t *data)
static const char *const EncoderError[]
int set_params(dt_imageio_module_format_t *self, const void *params, const int size)
void cleanup(dt_imageio_module_format_t *self)
int levels(dt_imageio_module_data_t *p)
void * legacy_params(dt_imageio_module_format_t *self, const void *const old_params, const size_t old_params_size, const int old_version, const int new_version, size_t *new_size)
void free_params(dt_imageio_module_format_t *self, dt_imageio_module_data_t *params)
const char * get_error_str(int err)
static void compression_changed(GtkWidget *widget, gpointer user_data)
void init(dt_imageio_module_format_t *self)
void * get_params(dt_imageio_module_format_t *self)
void gui_cleanup(dt_imageio_module_format_t *self)
static void hint_combobox_changed(GtkWidget *widget, gpointer user_data)
int write_image(dt_imageio_module_data_t *webp, const char *filename, const void *in_tmp, dt_colorspaces_color_profile_type_t over_type, const char *over_filename, void *exif, int exif_len, int32_t imgid, int num, int total, struct dt_dev_pixelpipe_t *pipe, const gboolean export_masks)
static void quality_changed(GtkWidget *slider, gpointer user_data)