Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
png.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2009-2012 johannes hanika.
4 Copyright (C) 2010 Christian Himpel.
5 Copyright (C) 2011 Henrik Andersson.
6 Copyright (C) 2011 Tim Harder.
7 Copyright (C) 2011-2017, 2019-2020 Tobias Ellinghaus.
8 Copyright (C) 2012-2014, 2020-2021 Pascal Obry.
9 Copyright (C) 2012 Richard Wonka.
10 Copyright (C) 2013 Jérémy Rosen.
11 Copyright (C) 2013 Pascal de Bruijn.
12 Copyright (C) 2013 Simon Spannagel.
13 Copyright (C) 2013 Thomas Pryds.
14 Copyright (C) 2013-2014 Ulrich Pegelow.
15 Copyright (C) 2014-2016 Roman Lebedev.
16 Copyright (C) 2017 Matthieu Moy.
17 Copyright (C) 2017 Simon Raffeiner.
18 Copyright (C) 2019, 2022, 2025-2026 Aurélien PIERRE.
19 Copyright (C) 2019 Philippe Weyland.
20 Copyright (C) 2020 Diederik Ter Rahe.
21 Copyright (C) 2020-2021 Hubert Kowalski.
22 Copyright (C) 2021 Ralf Brown.
23 Copyright (C) 2022 Martin Bařinka.
24 Copyright (C) 2022 Miloš Komarčević.
25 Copyright (C) 2024 Alynx Zhou.
26
27 darktable is free software: you can redistribute it and/or modify
28 it under the terms of the GNU General Public License as published by
29 the Free Software Foundation, either version 3 of the License, or
30 (at your option) any later version.
31
32 darktable is distributed in the hope that it will be useful,
33 but WITHOUT ANY WARRANTY; without even the implied warranty of
34 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 GNU General Public License for more details.
36
37 You should have received a copy of the GNU General Public License
38 along with darktable. If not, see <http://www.gnu.org/licenses/>.
39*/
40
41#ifdef HAVE_CONFIG_H
42#include "config.h"
43#endif
44
45#include <inttypes.h>
46#include <png.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <zlib.h>
50
51#include "widgets/bauhaus.h"
53#include "system/macros.h"
54#include "system/mem_alloc.h"
56#include <glib/gstdio.h>
60#include "common/conf.h"
63
64DT_MODULE(3)
65
75
81
82/* Write EXIF data to PNG file.
83 * Code copied from DigiKam's libs/dimg/loaders/pngloader.cpp.
84 * The EXIF embedding is defined by ImageMagicK.
85 * It is documented in the ExifTool page:
86 * http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PNG.html
87 *
88 * ..and in turn copied from ufraw. thanks to udi and colleagues
89 * for making useful code much more readable and discoverable ;)
90 */
91
92static void PNGwriteRawProfile(png_struct *ping, png_info *ping_info, char *profile_type, guint8 *profile_data,
93 png_uint_32 length)
94{
95 png_textp text;
96 long i;
97 guint8 *sp;
98 png_charp dp;
99 png_uint_32 allocated_length, description_length;
100
101 const guint8 hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
102 text = png_malloc(ping, sizeof(png_text));
103 description_length = strlen(profile_type);
104 allocated_length = length * 2 + (length >> 5) + 20 + description_length;
105
106 text[0].text = png_malloc(ping, allocated_length);
107 text[0].key = png_malloc(ping, 80);
108 text[0].key[0] = '\0';
109
110 g_strlcat(text[0].key, "Raw profile type ", 80);
111 g_strlcat(text[0].key, profile_type, 80);
112
113 sp = profile_data;
114 dp = text[0].text;
115 *dp++ = '\n';
116
117 g_strlcpy(dp, profile_type, allocated_length);
118
119 dp += description_length;
120 *dp++ = '\n';
121 *dp = '\0';
122
123 g_snprintf(dp, allocated_length - strlen(text[0].text), "%8lu ", (unsigned long int)length);
124
125 dp += 8;
126
127 for(i = 0; i < (long)length; i++)
128 {
129 if(i % 36 == 0) *dp++ = '\n';
130
131 *(dp++) = hex[((*sp >> 4) & 0x0f)];
132 *(dp++) = hex[((*sp++) & 0x0f)];
133 }
134
135 *dp++ = '\n';
136 *dp = '\0';
137 text[0].text_length = (dp - text[0].text);
138 text[0].compression = -1;
139
140 if(text[0].text_length <= allocated_length) png_set_text(ping, ping_info, text, 1);
141
142 png_free(ping, text[0].text);
143 png_free(ping, text[0].key);
144 png_free(ping, text);
145}
146
147int write_image(dt_imageio_module_data_t *p_tmp, const char *filename, const void *ivoid,
148 dt_colorspaces_color_profile_type_t over_type, const char *over_filename,
149 void *exif, int exif_len, int32_t imgid, int num, int total, struct dt_dev_pixelpipe_t *pipe,
150 const gboolean export_masks)
151{
153 const int width = p->global.width, height = p->global.height;
154 FILE *f = g_fopen(filename, "wb");
155 if(IS_NULL_PTR(f)) return 1;
156
157 png_structp png_ptr;
158 png_infop info_ptr;
159
160 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
161 if(IS_NULL_PTR(png_ptr))
162 {
163 fclose(f);
164 return 1;
165 }
166
167 info_ptr = png_create_info_struct(png_ptr);
168 if(IS_NULL_PTR(info_ptr))
169 {
170 fclose(f);
171 png_destroy_write_struct(&png_ptr, NULL);
172 return 1;
173 }
174
175 if(setjmp(png_jmpbuf(png_ptr)))
176 {
177 fclose(f);
178 png_destroy_write_struct(&png_ptr, &info_ptr);
179 return 1;
180 }
181
182 png_init_io(png_ptr, f);
183
184 png_set_compression_level(png_ptr, p->compression);
185 png_set_compression_mem_level(png_ptr, 8);
186 png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
187 png_set_compression_window_bits(png_ptr, 15);
188 png_set_compression_method(png_ptr, 8);
189 png_set_compression_buffer_size(png_ptr, 8192);
190
191 png_set_IHDR(png_ptr, info_ptr, width, height, p->bpp, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
192 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
193
194 // metadata has to be written before the pixels
195
196 // embed icc profile
197 cmsHPROFILE out_profile = dt_colorspaces_get_output_profile(imgid, &over_type, over_filename)->profile;
198 uint32_t len = 0;
199 cmsSaveProfileToMem(out_profile, NULL, &len);
200 if(len > 0)
201 {
202 char *buf = malloc(sizeof(char) * len);
203 if(buf)
204 {
205 cmsSaveProfileToMem(out_profile, buf, &len);
206 char name[512] = { 0 };
207 dt_colorspaces_get_profile_name(out_profile, "en", "US", name, sizeof(name));
208
209 png_set_iCCP(png_ptr, info_ptr, *name ? name : "icc", 0,
210#if(PNG_LIBPNG_VER < 10500)
211 (png_charp)buf,
212#else
213 (png_const_bytep)buf,
214#endif
215 len);
216 dt_free(buf);
217 }
218 }
219
220 // write exif data
221 if(exif && exif_len > 0)
222 {
223 /* The legacy tEXt chunk storage scheme implies the "Exif\0\0" APP1 prefix */
224 uint8_t *buf = malloc(exif_len + 6);
225 if(buf)
226 {
227 memcpy(buf, "Exif\0\0", 6);
228 memcpy(buf + 6, exif, exif_len);
229 PNGwriteRawProfile(png_ptr, info_ptr, "exif", buf, exif_len + 6);
230 dt_free(buf);
231 }
232 }
233
234 png_write_info(png_ptr, info_ptr);
235
236 /*
237 * Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into
238 * RGB (4 channels -> 3 channels). The second parameter is not used.
239 */
240 png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
241
242 png_bytep *row_pointers = dt_pixelpipe_cache_alloc_align_cache(sizeof(png_bytep) * height, 0);
243
244 if(p->bpp > 8)
245 {
246 /* swap bytes of 16 bit files to most significant bit first */
247 png_set_swap(png_ptr);
248
249 for(unsigned i = 0; i < height; i++) row_pointers[i] = (png_bytep)((uint16_t *)ivoid + (size_t)4 * i * width);
250 }
251 else
252 {
253 for(unsigned i = 0; i < height; i++) row_pointers[i] = (uint8_t *)ivoid + (size_t)4 * i * width;
254 }
255
256 png_write_image(png_ptr, row_pointers);
257
258 dt_pixelpipe_cache_free_align(row_pointers);
259
260 png_write_end(png_ptr, info_ptr);
261 png_destroy_write_struct(&png_ptr, &info_ptr);
262 fclose(f);
263 return 0;
264}
265
266static int __attribute__((__unused__)) read_header(const char *filename, dt_imageio_module_data_t *p_tmp)
267{
268 dt_imageio_png_t *png = (dt_imageio_png_t *)p_tmp;
269 png->f = g_fopen(filename, "rb");
270
271 if(IS_NULL_PTR(png->f)) return 1;
272
273#define NUM_BYTES_CHECK (8)
274
275 png_byte dat[NUM_BYTES_CHECK];
276
277 size_t cnt = fread(dat, 1, NUM_BYTES_CHECK, png->f);
278
279 if(cnt != NUM_BYTES_CHECK || png_sig_cmp(dat, (png_size_t)0, NUM_BYTES_CHECK))
280 {
281 fclose(png->f);
282 return 1;
283 }
284
285 png->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
286
287 if(IS_NULL_PTR(png->png_ptr))
288 {
289 fclose(png->f);
290 return 1;
291 }
292
293 png->info_ptr = png_create_info_struct(png->png_ptr);
294 if(IS_NULL_PTR(png->info_ptr))
295 {
296 fclose(png->f);
297 png_destroy_read_struct(&png->png_ptr, NULL, NULL);
298 return 1;
299 }
300
301 if(setjmp(png_jmpbuf(png->png_ptr)))
302 {
303 fclose(png->f);
304 png_destroy_read_struct(&png->png_ptr, &png->info_ptr, NULL);
305 return 1;
306 }
307
308 png_init_io(png->png_ptr, png->f);
309
310 // we checked some bytes
311 png_set_sig_bytes(png->png_ptr, NUM_BYTES_CHECK);
312
313 // image info
314 png_read_info(png->png_ptr, png->info_ptr);
315
316 uint32_t bit_depth = png_get_bit_depth(png->png_ptr, png->info_ptr);
317 uint32_t color_type = png_get_color_type(png->png_ptr, png->info_ptr);
318
319 // image input transformations
320
321 // palette => rgb
322 if(color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png->png_ptr);
323
324 // 1, 2, 4 bit => 8 bit
325 if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png->png_ptr);
326
327 // strip alpha channel
328 if(color_type & PNG_COLOR_MASK_ALPHA) png_set_strip_alpha(png->png_ptr);
329
330 // grayscale => rgb
331 if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
332 png_set_gray_to_rgb(png->png_ptr);
333
334 // png->bytespp = 3*bit_depth/8;
335 png->global.width = png_get_image_width(png->png_ptr, png->info_ptr);
336 png->global.height = png_get_image_height(png->png_ptr, png->info_ptr);
337
338 return 0;
339
340#undef NUM_BYTES_CHECK
341}
342
343#if 0
344int dt_imageio_png_read_assure_8(dt_imageio_png_t *png)
345{
346 if (setjmp(png_jmpbuf(png->png_ptr)))
347 {
348 fclose(png->f);
349 png_destroy_read_struct(&png->png_ptr, NULL, NULL);
350 return 1;
351 }
352 uint32_t bit_depth = png_get_bit_depth(png->png_ptr, png->info_ptr);
353 // strip down to 8 bit channels
354 if (bit_depth == 16)
355 png_set_strip_16(png->png_ptr);
356
357 return 0;
358}
359#endif
360
362{
363 dt_imageio_png_t *png = (dt_imageio_png_t *)p_tmp;
364 if(setjmp(png_jmpbuf(png->png_ptr)))
365 {
366 fclose(png->f);
367 png_destroy_read_struct(&png->png_ptr, &png->info_ptr, NULL);
368 return 1;
369 }
370
371 png_bytep row_pointer = (png_bytep)out;
372 unsigned long rowbytes = png_get_rowbytes(png->png_ptr, png->info_ptr);
373
374 for(int y = 0; y < png->global.height; y++)
375 {
376 png_read_row(png->png_ptr, row_pointer, NULL);
377 row_pointer += rowbytes;
378 }
379
380 png_read_end(png->png_ptr, png->info_ptr);
381 png_destroy_read_struct(&png->png_ptr, &png->info_ptr, NULL);
382
383 fclose(png->f);
384 return 0;
385}
386
388{
389 return sizeof(dt_imageio_module_data_t) + 2 * sizeof(int);
390}
391
392void *legacy_params(dt_imageio_module_format_t *self, const void *const old_params, const size_t old_params_size,
393 const int old_version, const int new_version, size_t *new_size)
394{
395 if(old_version == 1 && new_version == 3)
396 {
397 typedef struct dt_imageio_png_v1_t
398 {
399 int max_width, max_height;
400 int width, height;
401 char style[128];
402 int bpp;
403 FILE *f;
404 png_structp png_ptr;
405 png_infop info_ptr;
406 } dt_imageio_png_v1_t;
407
408 dt_imageio_png_v1_t *o = (dt_imageio_png_v1_t *)old_params;
410
411 n->global.max_width = o->max_width;
412 n->global.max_height = o->max_height;
413 n->global.width = o->width;
414 n->global.height = o->height;
415 g_strlcpy(n->global.style, o->style, sizeof(o->style));
416 n->bpp = o->bpp;
417 n->compression = Z_BEST_COMPRESSION;
418 n->f = o->f;
419 n->png_ptr = o->png_ptr;
420 n->info_ptr = o->info_ptr;
421 *new_size = self->params_size(self);
422 return n;
423 }
424 else if(old_version == 2 && new_version == 3)
425 {
426 typedef struct dt_imageio_png_v2_t
427 {
428 int max_width, max_height;
429 int width, height;
430 char style[128];
431 gboolean style_append;
432 int bpp;
433 FILE *f;
434 png_structp png_ptr;
435 png_infop info_ptr;
436 } dt_imageio_png_v2_t;
437
438 dt_imageio_png_v2_t *o = (dt_imageio_png_v2_t *)old_params;
440
441 n->global.max_width = o->max_width;
442 n->global.max_height = o->max_height;
443 n->global.width = o->width;
444 n->global.height = o->height;
445 g_strlcpy(n->global.style, o->style, sizeof(o->style));
446 n->bpp = o->bpp;
447 n->compression = Z_BEST_COMPRESSION;
448 n->f = o->f;
449 n->png_ptr = o->png_ptr;
450 n->info_ptr = o->info_ptr;
451 *new_size = self->params_size(self);
452 return n;
453 }
454 return NULL;
455}
456
458{
459 dt_imageio_png_t *d = (dt_imageio_png_t *)calloc(1, sizeof(dt_imageio_png_t));
460 const char *bpp = dt_conf_get_string_const("plugins/imageio/format/png/bpp");
461 d->bpp = atoi(bpp);
462 if(d->bpp != 8 && d->bpp != 16)
463 d->bpp = 8;
464
465 // PNG compression level might actually be zero!
466 if(!dt_conf_key_exists("plugins/imageio/format/png/compression"))
467 d->compression = 5;
468 else
469 {
470 d->compression = dt_conf_get_int("plugins/imageio/format/png/compression");
471 if(d->compression < 0 || d->compression > 9) d->compression = 5;
472 }
473
474 return d;
475}
476
478{
479 dt_free(params);
480}
481
482int set_params(dt_imageio_module_format_t *self, const void *params, const int size)
483{
484 if(size != self->params_size(self)) return 1;
485 const dt_imageio_png_t *d = (dt_imageio_png_t *)params;
487 if(d->bpp < 12)
488 dt_bauhaus_combobox_set(g->bit_depth, 0);
489 else
490 dt_bauhaus_combobox_set(g->bit_depth, 1);
491 dt_conf_set_int("plugins/imageio/format/png/bpp", d->bpp);
492 dt_bauhaus_slider_set(g->compression, d->compression);
493 dt_conf_set_int("plugins/imageio/format/png/compression", d->compression);
494 return 0;
495}
496
498{
499 return ((dt_imageio_png_t *)p)->bpp;
500}
501
503{
504 return IMAGEIO_RGB | (((dt_imageio_png_t *)p)->bpp == 8 ? IMAGEIO_INT8 : IMAGEIO_INT16);
505}
506
508{
509 return "image/png";
510}
511
513{
514 return "png";
515}
516
517const char *name()
518{
519 return _("PNG (8/16-bit)");
520}
521
522static void bit_depth_changed(GtkWidget *widget, gpointer user_data)
523{
524 const int bpp = (dt_bauhaus_combobox_get(widget) == 0 ? 8 : 16);
525 dt_conf_set_int("plugins/imageio/format/png/bpp", bpp);
526}
527
528static void compression_level_changed(GtkWidget *slider, gpointer user_data)
529{
530 const int compression = (int)dt_bauhaus_slider_get(slider);
531 dt_conf_set_int("plugins/imageio/format/png/compression", compression);
532}
533
535{
536}
537
541
543{
545 self->gui_data = (void *)gui;
546 const char *conf_bpp = dt_conf_get_string_const("plugins/imageio/format/png/bpp");
547 int bpp = atoi(conf_bpp);
548
549 // PNG compression level might actually be zero!
550 int compression = 5;
551 if(dt_conf_key_exists("plugins/imageio/format/png/compression"))
552 compression = dt_conf_get_int("plugins/imageio/format/png/compression");
553
554 self->widget = gtk_box_new(GTK_ORIENTATION_VERTICAL, DT_GUI_BOX_SPACING);
555
556 // Bit depth combo box
558 dt_bauhaus_widget_set_label(gui->bit_depth, N_("bit depth"));
559 dt_bauhaus_combobox_add(gui->bit_depth, _("8 bit"));
560 dt_bauhaus_combobox_add(gui->bit_depth, _("16 bit"));
561 if(bpp == 16)
563 else {
564 bpp = 8; // We know only about 8 or 16 bits, at least for now
566 }
567 gtk_box_pack_start(GTK_BOX(self->widget), gui->bit_depth, TRUE, TRUE, 0);
568 g_signal_connect(G_OBJECT(gui->bit_depth), "value-changed", G_CALLBACK(bit_depth_changed), NULL);
569
570 // Compression level slider
572 dt_confgen_get_int("plugins/imageio/format/png/compression", DT_MIN),
573 dt_confgen_get_int("plugins/imageio/format/png/compression", DT_MAX),
574 1,
575 dt_confgen_get_int("plugins/imageio/format/png/compression", DT_DEFAULT),
576 0);
577 dt_bauhaus_widget_set_label(gui->compression, N_("compression"));
578 dt_bauhaus_slider_set(gui->compression, compression);
579 gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(gui->compression), TRUE, TRUE, 0);
580 g_signal_connect(G_OBJECT(gui->compression), "value-changed", G_CALLBACK(compression_level_changed), NULL);
581}
582
584{
585 dt_free(self->gui_data);
586}
587
589{
591 dt_bauhaus_combobox_set(gui->bit_depth, 0); // 8bpp
592 dt_bauhaus_slider_set(gui->compression, dt_confgen_get_int("plugins/imageio/format/png/compression", DT_DEFAULT));
593}
594
599
600// clang-format off
601// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
602// vim: shiftwidth=2 expandtab tabstop=2 cindent
603// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
604// clang-format on
#define TRUE
Definition ashift_lsd.c:162
uint32_t bit_depth
Definition avif.c:103
float dt_bauhaus_slider_get(GtkWidget *widget)
Definition bauhaus.c:3280
int dt_bauhaus_combobox_get(GtkWidget *widget)
Definition bauhaus.c:2136
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
Definition bauhaus.c:3331
void dt_bauhaus_combobox_set(GtkWidget *widget, const int pos)
Definition bauhaus.c:2090
void dt_bauhaus_widget_set_label(GtkWidget *widget, const char *label)
Definition bauhaus.c:1504
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)
Definition bauhaus.c:1632
GtkWidget * dt_bauhaus_combobox_new(dt_bauhaus_t *bh, dt_gui_module_t *self)
Definition bauhaus.c:1698
void dt_bauhaus_combobox_add(GtkWidget *widget, const char *text)
Definition bauhaus.c:1824
const float f
void dt_colorspaces_get_profile_name(cmsHPROFILE p, const char *language, const char *country, char *name, size_t len)
Read a profile's description tag into name, handling character encodings.
The colour-profile module's API: which profiles exist, and how to apply one.
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
Definition colorspaces.h:98
const dt_colormatrix_t dt_aligned_pixel_t out
int dt_conf_key_exists(const char *key)
Does key have a value?
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)
const char * dt_conf_get_string_const(const char *name)
Borrow the stored string for name without copying it.
@ DT_DEFAULT
Definition conf.h:135
@ DT_MAX
Definition conf.h:137
@ DT_MIN
Definition conf.h:136
struct dt_bauhaus_t * dt_bauhaus_get_global(void)
Definition darktable.c:646
#define DT_GUI_MODULE(x)
int bpp
@ IMAGEIO_INT16
@ IMAGEIO_RGB
@ IMAGEIO_INT8
@ FORMAT_FLAGS_SUPPORT_XMP
int read_header(const char *filename, dt_imageio_png_t *png)
Definition imageio_png.c:44
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...
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
char * key
uint32_t width
Definition mipmap_cache.c:0
uint32_t height
Definition mipmap_cache.c:1
size_t size
Definition mipmap_cache.c:3
dt_mipmap_buffer_dsc_flags flags
Definition mipmap_cache.c:4
#define DT_MODULE(MODVER)
Instantiate the version handshake every module must export. Use once, at file scope,...
#define dt_pixelpipe_cache_alloc_align_cache(size, id)
#define dt_pixelpipe_cache_free_align(mem)
const char * mime(dt_imageio_module_data_t *data)
Definition png.c:507
size_t params_size(dt_imageio_module_format_t *self)
Definition png.c:387
static void bit_depth_changed(GtkWidget *widget, gpointer user_data)
Definition png.c:522
void gui_reset(dt_imageio_module_format_t *self)
Definition png.c:588
#define NUM_BYTES_CHECK
void gui_init(dt_imageio_module_format_t *self)
Definition png.c:542
static void compression_level_changed(GtkWidget *slider, gpointer user_data)
Definition png.c:528
const char * extension(dt_imageio_module_data_t *data)
Definition png.c:512
int set_params(dt_imageio_module_format_t *self, const void *params, const int size)
Definition png.c:482
const char * name()
Definition png.c:517
void cleanup(dt_imageio_module_format_t *self)
Definition png.c:538
int read_image(dt_imageio_module_data_t *p_tmp, uint8_t *out)
Definition png.c:361
int levels(dt_imageio_module_data_t *p)
Definition png.c:502
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)
Definition png.c:392
void free_params(dt_imageio_module_format_t *self, dt_imageio_module_data_t *params)
Definition png.c:477
struct dt_imageio_png_t dt_imageio_png_t
int write_image(dt_imageio_module_data_t *p_tmp, const char *filename, const void *ivoid, 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)
Definition png.c:147
static void PNGwriteRawProfile(png_struct *ping, png_info *ping_info, char *profile_type, guint8 *profile_data, png_uint_32 length)
Definition png.c:92
void init(dt_imageio_module_format_t *self)
Definition png.c:534
void * get_params(dt_imageio_module_format_t *self)
Definition png.c:457
void gui_cleanup(dt_imageio_module_format_t *self)
Definition png.c:583
dt_colorspaces_color_profile_type_t
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Apply one channel's tone curve to each of the three colour channels, or pass the channel through unto...
Definition simd.h:55
cmsHPROFILE profile
the actual profile; NULL for the three category entries
GModule *GtkWidget * widget
GtkWidget * compression
Definition png.c:79
GtkWidget * bit_depth
Definition png.c:78
int compression
Definition png.c:70
png_infop info_ptr
Definition png.c:73
png_structp png_ptr
Definition png.c:72
FILE * f
Definition png.c:71
dt_imageio_module_data_t global
Definition png.c:68
#define DT_GUI_BOX_SPACING