68 struct jpeg_source_mgr src;
69 struct jpeg_destination_mgr dest;
70 struct jpeg_decompress_struct dinfo;
71 struct jpeg_compress_struct cinfo;
84 struct jpeg_error_mgr
pub;
93 (*cinfo->err->output_message)(cinfo);
110#define ICC_MARKER (JPEG_APP0 + 2)
111#define ICC_OVERHEAD_LEN 14
112#define MAX_BYTES_IN_MARKER 65533
113#define MAX_DATA_BYTES_IN_MARKER (MAX_BYTES_IN_MARKER - ICC_OVERHEAD_LEN)
124static void write_icc_profile(j_compress_ptr cinfo,
const JOCTET *icc_data_ptr,
unsigned int icc_data_len)
132 while(icc_data_len > 0)
135 unsigned int length = icc_data_len;
138 icc_data_len -= length;
147 jpeg_write_m_byte(cinfo, 0x49);
148 jpeg_write_m_byte(cinfo, 0x43);
149 jpeg_write_m_byte(cinfo, 0x43);
150 jpeg_write_m_byte(cinfo, 0x5F);
151 jpeg_write_m_byte(cinfo, 0x50);
152 jpeg_write_m_byte(cinfo, 0x52);
153 jpeg_write_m_byte(cinfo, 0x4F);
154 jpeg_write_m_byte(cinfo, 0x46);
155 jpeg_write_m_byte(cinfo, 0x49);
156 jpeg_write_m_byte(cinfo, 0x4C);
157 jpeg_write_m_byte(cinfo, 0x45);
158 jpeg_write_m_byte(cinfo, 0x0);
161 jpeg_write_m_byte(cinfo, cur_marker);
162 jpeg_write_m_byte(cinfo, (
int)num_markers);
167 jpeg_write_m_byte(cinfo, *icc_data_ptr);
199 GETJOCTET(marker->data[0]) == 0x49 &&
200 GETJOCTET(marker->data[1]) == 0x43 &&
201 GETJOCTET(marker->data[2]) == 0x43 &&
202 GETJOCTET(marker->data[3]) == 0x5F &&
203 GETJOCTET(marker->data[4]) == 0x50 &&
204 GETJOCTET(marker->data[5]) == 0x52 &&
205 GETJOCTET(marker->data[6]) == 0x4F &&
206 GETJOCTET(marker->data[7]) == 0x46 &&
207 GETJOCTET(marker->data[8]) == 0x49 &&
208 GETJOCTET(marker->data[9]) == 0x4C &&
209 GETJOCTET(marker->data[10]) == 0x45 &&
210 GETJOCTET(marker->data[11]) == 0x0;
235 JOCTET **icc_data_ptr,
236 unsigned int *icc_data_len)
239#define MAX_SEQ_NO 255
244 *icc_data_ptr = NULL;
251 for(
int seq_no = 1; seq_no <=
MAX_SEQ_NO; seq_no++)
252 marker_present[seq_no] = 0;
254 for(jpeg_saved_marker_ptr marker = cinfo->marker_list; !
IS_NULL_PTR(marker); marker = marker->next)
259 num_markers = GETJOCTET(marker->data[13]);
260 else if(num_markers != GETJOCTET(marker->data[13]))
262 const int seq_no = GETJOCTET(marker->data[12]);
263 if(seq_no <= 0 || seq_no > num_markers)
265 if(marker_present[seq_no])
267 marker_present[seq_no] = 1;
279 unsigned int total_length = 0;
280 for(
int seq_no = 1; seq_no <= num_markers; seq_no++)
282 if(marker_present[seq_no] == 0)
284 data_offset[seq_no] = total_length;
285 total_length += data_length[seq_no];
288 if(total_length <= 0)
292 JOCTET *icc_data = (JOCTET *)calloc(total_length,
sizeof(JOCTET));
297 for(jpeg_saved_marker_ptr marker = cinfo->marker_list; !
IS_NULL_PTR(marker); marker = marker->next)
301 const int seq_no = GETJOCTET(marker->data[12]);
302 JOCTET *dst_ptr = icc_data + data_offset[seq_no];
304 unsigned int length = data_length[seq_no];
307 *dst_ptr++ = *src_ptr++;
312 *icc_data_ptr = icc_data;
313 *icc_data_len = total_length;
319#undef ICC_OVERHEAD_LEN
320#undef MAX_BYTES_IN_MARKER
321#undef MAX_DATA_BYTES_IN_MARKER
327 void *exif,
int exif_len, int32_t imgid,
int num,
int total,
struct dt_dev_pixelpipe_t *pipe,
328 const gboolean export_masks)
331 const uint8_t *in = (
const uint8_t *)in_tmp;
334 jpg->
cinfo.err = jpeg_std_error(&jerr.
pub);
338 jpeg_destroy_compress(&(jpg->
cinfo));
341 jpeg_create_compress(&(jpg->
cinfo));
342 FILE *
f = g_fopen(filename,
"wb");
344 jpeg_stdio_dest(&(jpg->
cinfo),
f);
348 jpg->
cinfo.input_components = 3;
349 jpg->
cinfo.in_color_space = JCS_RGB;
350 jpeg_set_defaults(&(jpg->
cinfo));
352 if(jpg->
quality > 90) jpg->
cinfo.comp_info[0].v_samp_factor = 1;
353 if(jpg->
quality > 92) jpg->
cinfo.comp_info[0].h_samp_factor = 1;
354 if(jpg->
quality > 95) jpg->
cinfo.dct_method = JDCT_FLOAT;
355 if(jpg->
quality < 50) jpg->
cinfo.dct_method = JDCT_IFAST;
359 jpg->
cinfo.optimize_coding = 1;
362 jpg->
cinfo.density_unit = 1;
363 jpg->
cinfo.X_density = resolution;
364 jpg->
cinfo.Y_density = resolution;
366 jpeg_start_compress(&(jpg->
cinfo),
TRUE);
370 cmsSaveProfileToMem(out_profile, NULL, &len);
373 unsigned char *buf = malloc(
sizeof(
unsigned char) * len);
376 cmsSaveProfileToMem(out_profile, buf, &len);
384 while(
row && jpg->
cinfo.next_scanline < jpg->
cinfo.image_height)
387 buf = in + (size_t)jpg->
cinfo.next_scanline * jpg->
cinfo.image_width * 4;
389 for(
int k = 0;
k < 3;
k++)
row[3 *
i +
k] = buf[4 *
i +
k];
391 jpeg_write_scanlines(&(jpg->
cinfo), tmp, 1);
393 jpeg_finish_compress(&(jpg->
cinfo));
395 jpeg_destroy_compress(&(jpg->
cinfo));
405 jpg->
f = g_fopen(filename,
"rb");
409 jpg->
dinfo.err = jpeg_std_error(&jerr.
pub);
413 jpeg_destroy_decompress(&(jpg->
dinfo));
417 jpeg_create_decompress(&(jpg->
dinfo));
418 jpeg_stdio_src(&(jpg->
dinfo), jpg->
f);
430 jpg->
dinfo.err = jpeg_std_error(&jerr.
pub);
434 jpeg_destroy_decompress(&(jpg->
dinfo));
438 (
void)jpeg_start_decompress(&(jpg->
dinfo));
439 JSAMPROW row_pointer[1];
441 (
size_t)jpg->
dinfo.output_width * jpg->
dinfo.num_components, 0);
443 while(row_pointer[0] && jpg->
dinfo.output_scanline < jpg->
dinfo.image_height)
445 if(jpeg_read_scanlines(&(jpg->
dinfo), row_pointer, 1) != 1)
return 1;
446 if(jpg->
dinfo.num_components < 3)
447 for(JDIMENSION
i = 0;
i < jpg->
dinfo.image_width;
i++)
448 for(
int k = 0;
k < 3;
k++) tmp[4 *
i +
k] = row_pointer[0][jpg->
dinfo.num_components *
i + 0];
450 for(JDIMENSION
i = 0;
i < jpg->
dinfo.image_width;
i++)
451 for(
int k = 0;
k < 3;
k++) tmp[4 *
i +
k] = row_pointer[0][3 *
i +
k];
456 jpeg_destroy_decompress(&(jpg->
dinfo));
461 (
void)jpeg_finish_decompress(&(jpg->
dinfo));
462 jpeg_destroy_decompress(&(jpg->
dinfo));
474 const size_t old_params_size,
const int old_version,
const int new_version,
477 if(old_version == 1 && new_version == 2)
479 typedef struct dt_imageio_jpeg_v1_t
481 int max_width, max_height;
485 struct jpeg_source_mgr src;
486 struct jpeg_destination_mgr dest;
487 struct jpeg_decompress_struct dinfo;
488 struct jpeg_compress_struct cinfo;
490 } dt_imageio_jpeg_v1_t;
492 const dt_imageio_jpeg_v1_t *o = (dt_imageio_jpeg_v1_t *)old_params;
496 n->global.max_height = o->max_height;
497 n->global.width = o->width;
498 n->global.height = o->height;
499 g_strlcpy(
n->global.style, o->style,
sizeof(o->style));
500 n->quality = o->quality;
506 *new_size = self->params_size(self);
517 if(
d->quality <= 0 ||
d->quality > 100)
d->quality = 100;
528 if(
size != self->params_size(self))
return 1;
574 return _(
"JPEG (8-bit)");
600 gtk_box_pack_start(GTK_BOX(box), GTK_WIDGET(
g->quality),
TRUE,
TRUE, 0);
601 g_signal_connect(G_OBJECT(
g->quality),
"value-changed", G_CALLBACK(
quality_changed), NULL);
void dt_bauhaus_slider_set_default(GtkWidget *widget, float def)
float dt_bauhaus_slider_get(GtkWidget *widget)
void dt_bauhaus_slider_set(GtkWidget *widget, float 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)
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
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)
dt_colorspaces_color_profile_type_t
const dt_aligned_pixel_t f
const dt_colormatrix_t dt_aligned_pixel_t out
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
int dt_confgen_get_int(const char *name, dt_confgen_value_kind_t kind)
#define dt_pixelpipe_cache_alloc_align_cache(size, id)
#define DT_MODULE(MODVER)
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Enable aggressive floating-point arithmetic optimizations, in denormals handling. Set through user pr...
#define dt_pixelpipe_cache_free_align(mem)
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
int dt_exif_write_blob(uint8_t *blob, uint32_t size, const char *path, const int compressed)
#define DT_GUI_BOX_SPACING
static void setup_read_icc_profile(j_decompress_ptr cinfo)
static boolean marker_is_icc(jpeg_saved_marker_ptr marker)
static boolean read_icc_profile(j_decompress_ptr dinfo, JOCTET **icc_data_ptr, unsigned int *icc_data_len)
@ FORMAT_FLAGS_SUPPORT_XMP
int read_header(const char *filename, dt_imageio_png_t *png)
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)
static void dt_imageio_jpeg_error_exit(j_common_ptr cinfo)
void gui_init(dt_imageio_module_format_t *self)
const char * extension(dt_imageio_module_data_t *data)
int read_image(dt_imageio_module_data_t *jpg_tmp, uint8_t *out)
int set_params(dt_imageio_module_format_t *self, const void *params, const int size)
int write_image(dt_imageio_module_data_t *jpg_tmp, 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)
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)
struct dt_imageio_jpeg_error_mgr * dt_imageio_jpeg_error_ptr
void init(dt_imageio_module_format_t *self)
void * get_params(dt_imageio_module_format_t *self)
static void write_icc_profile(j_compress_ptr cinfo, const JOCTET *icc_data_ptr, unsigned int icc_data_len)
void gui_cleanup(dt_imageio_module_format_t *self)
#define MAX_DATA_BYTES_IN_MARKER
static void quality_changed(GtkWidget *slider, gpointer user_data)
float *const restrict const size_t k
dt_mipmap_buffer_dsc_flags flags
struct _GtkWidget GtkWidget
struct dt_bauhaus_t * bauhaus
struct jpeg_error_mgr pub
struct jpeg_decompress_struct dinfo
dt_imageio_module_data_t global
struct jpeg_compress_struct cinfo