56#include <glib/gstdio.h>
92static void PNGwriteRawProfile(png_struct *ping, png_info *ping_info,
char *profile_type, guint8 *profile_data,
99 png_uint_32 allocated_length, description_length;
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;
106 text[0].text = png_malloc(ping, allocated_length);
107 text[0].key = png_malloc(ping, 80);
108 text[0].key[0] =
'\0';
110 g_strlcat(text[0].
key,
"Raw profile type ", 80);
111 g_strlcat(text[0].
key, profile_type, 80);
117 g_strlcpy(dp, profile_type, allocated_length);
119 dp += description_length;
123 g_snprintf(dp, allocated_length - strlen(text[0].text),
"%8lu ", (
unsigned long int)length);
127 for(
i = 0;
i < (long)length;
i++)
129 if(
i % 36 == 0) *dp++ =
'\n';
131 *(dp++) = hex[((*sp >> 4) & 0x0f)];
132 *(dp++) = hex[((*sp++) & 0x0f)];
137 text[0].text_length = (dp - text[0].text);
138 text[0].compression = -1;
140 if(text[0].text_length <= allocated_length) png_set_text(ping, ping_info, text, 1);
142 png_free(ping, text[0].text);
143 png_free(ping, text[0].
key);
144 png_free(ping, text);
149 void *exif,
int exif_len, int32_t imgid,
int num,
int total,
struct dt_dev_pixelpipe_t *pipe,
150 const gboolean export_masks)
154 FILE *
f = g_fopen(filename,
"wb");
160 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
167 info_ptr = png_create_info_struct(png_ptr);
171 png_destroy_write_struct(&png_ptr, NULL);
175 if(setjmp(png_jmpbuf(png_ptr)))
178 png_destroy_write_struct(&png_ptr, &info_ptr);
182 png_init_io(png_ptr,
f);
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);
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);
199 cmsSaveProfileToMem(out_profile, NULL, &len);
202 char *buf = malloc(
sizeof(
char) * len);
205 cmsSaveProfileToMem(out_profile, buf, &len);
206 char name[512] = { 0 };
209 png_set_iCCP(png_ptr, info_ptr, *
name ?
name :
"icc", 0,
210#if(PNG_LIBPNG_VER < 10500)
213 (png_const_bytep)buf,
221 if(exif && exif_len > 0)
224 uint8_t *buf = malloc(exif_len + 6);
227 memcpy(buf,
"Exif\0\0", 6);
228 memcpy(buf + 6, exif, exif_len);
234 png_write_info(png_ptr, info_ptr);
240 png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
247 png_set_swap(png_ptr);
249 for(
unsigned i = 0;
i <
height;
i++) row_pointers[
i] = (png_bytep)((uint16_t *)ivoid + (
size_t)4 *
i *
width);
253 for(
unsigned i = 0;
i <
height;
i++) row_pointers[
i] = (uint8_t *)ivoid + (size_t)4 *
i *
width;
256 png_write_image(png_ptr, row_pointers);
260 png_write_end(png_ptr, info_ptr);
261 png_destroy_write_struct(&png_ptr, &info_ptr);
269 png->
f = g_fopen(filename,
"rb");
273#define NUM_BYTES_CHECK (8)
285 png->
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
297 png_destroy_read_struct(&png->
png_ptr, NULL, NULL);
301 if(setjmp(png_jmpbuf(png->
png_ptr)))
322 if(color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png->
png_ptr);
325 if(color_type == PNG_COLOR_TYPE_GRAY &&
bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png->
png_ptr);
328 if(color_type & PNG_COLOR_MASK_ALPHA) png_set_strip_alpha(png->
png_ptr);
331 if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
332 png_set_gray_to_rgb(png->
png_ptr);
340#undef NUM_BYTES_CHECK
346 if (setjmp(png_jmpbuf(png->
png_ptr)))
349 png_destroy_read_struct(&png->
png_ptr, NULL, NULL);
355 png_set_strip_16(png->
png_ptr);
364 if(setjmp(png_jmpbuf(png->
png_ptr)))
371 png_bytep row_pointer = (png_bytep)
out;
372 unsigned long rowbytes = png_get_rowbytes(png->
png_ptr, png->
info_ptr);
376 png_read_row(png->
png_ptr, row_pointer, NULL);
377 row_pointer += rowbytes;
393 const int old_version,
const int new_version,
size_t *new_size)
395 if(old_version == 1 && new_version == 3)
397 typedef struct dt_imageio_png_v1_t
399 int max_width, max_height;
406 } dt_imageio_png_v1_t;
408 dt_imageio_png_v1_t *o = (dt_imageio_png_v1_t *)old_params;
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));
417 n->compression = Z_BEST_COMPRESSION;
419 n->png_ptr = o->png_ptr;
420 n->info_ptr = o->info_ptr;
421 *new_size = self->params_size(self);
424 else if(old_version == 2 && new_version == 3)
426 typedef struct dt_imageio_png_v2_t
428 int max_width, max_height;
431 gboolean style_append;
436 } dt_imageio_png_v2_t;
438 dt_imageio_png_v2_t *o = (dt_imageio_png_v2_t *)old_params;
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));
447 n->compression = Z_BEST_COMPRESSION;
449 n->png_ptr = o->png_ptr;
450 n->info_ptr = o->info_ptr;
451 *new_size = self->params_size(self);
462 if(
d->bpp != 8 &&
d->bpp != 16)
471 if(
d->compression < 0 ||
d->compression > 9)
d->compression = 5;
484 if(
size != self->params_size(self))
return 1;
519 return _(
"PNG (8/16-bit)");
531 dt_conf_set_int(
"plugins/imageio/format/png/compression", compression);
547 int bpp = atoi(conf_bpp);
552 compression =
dt_conf_get_int(
"plugins/imageio/format/png/compression");
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_combobox_add(GtkWidget *widget, const char *text)
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.
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.
struct dt_bauhaus_t * dt_bauhaus_get_global(void)
@ FORMAT_FLAGS_SUPPORT_XMP
int read_header(const char *filename, dt_imageio_png_t *png)
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,...
#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)
size_t params_size(dt_imageio_module_format_t *self)
static void bit_depth_changed(GtkWidget *widget, gpointer user_data)
void gui_reset(dt_imageio_module_format_t *self)
void gui_init(dt_imageio_module_format_t *self)
static void compression_level_changed(GtkWidget *slider, gpointer user_data)
const char * extension(dt_imageio_module_data_t *data)
int set_params(dt_imageio_module_format_t *self, const void *params, const int size)
void cleanup(dt_imageio_module_format_t *self)
int read_image(dt_imageio_module_data_t *p_tmp, uint8_t *out)
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)
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)
static void PNGwriteRawProfile(png_struct *ping, png_info *ping_info, char *profile_type, guint8 *profile_data, png_uint_32 length)
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)
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...
cmsHPROFILE profile
the actual profile; NULL for the three category entries
dt_imageio_module_data_t global