Blender  V3.3
jpeg.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 /* This little block needed for linking to Blender... */
9 #include <setjmp.h>
10 #include <stdio.h>
11 
12 #include "MEM_guardedalloc.h"
13 
14 #include "BLI_fileops.h"
15 #include "BLI_string.h"
16 #include "BLI_utildefines.h"
17 
18 #include "BKE_idprop.h"
19 
20 #include "DNA_ID.h" /* ID property definitions. */
21 
22 #include "IMB_filetype.h"
23 #include "IMB_imbuf.h"
24 #include "IMB_imbuf_types.h"
25 #include "IMB_metadata.h"
26 #include "imbuf.h"
27 
28 #include <jerror.h>
29 #include <jpeglib.h>
30 
31 #include "IMB_colormanagement.h"
33 
34 /* the types are from the jpeg lib */
35 static void jpeg_error(j_common_ptr cinfo) ATTR_NORETURN;
36 static void init_source(j_decompress_ptr cinfo);
37 static boolean fill_input_buffer(j_decompress_ptr cinfo);
38 static void skip_input_data(j_decompress_ptr cinfo, long num_bytes);
39 static void term_source(j_decompress_ptr cinfo);
40 static void memory_source(j_decompress_ptr cinfo, const unsigned char *buffer, size_t size);
41 static boolean handle_app1(j_decompress_ptr cinfo);
42 static ImBuf *ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo,
43  int flags,
44  int max_size,
45  size_t *r_width,
46  size_t *r_height);
47 
48 static const uchar jpeg_default_quality = 75;
50 
51 bool imb_is_a_jpeg(const unsigned char *mem, const size_t size)
52 {
53  const char magic[2] = {0xFF, 0xD8};
54  if (size < sizeof(magic)) {
55  return false;
56  }
57  return memcmp(mem, magic, sizeof(magic)) == 0;
58 }
59 
60 /*----------------------------------------------------------
61  * JPG ERROR HANDLING
62  *---------------------------------------------------------- */
63 
64 typedef struct my_error_mgr {
65  struct jpeg_error_mgr pub; /* "public" fields */
66 
67  jmp_buf setjmp_buffer; /* for return to caller */
69 
71 
72 static void jpeg_error(j_common_ptr cinfo)
73 {
74  my_error_ptr err = (my_error_ptr)cinfo->err;
75 
76  /* Always display the message */
77  (*cinfo->err->output_message)(cinfo);
78 
79  /* Let the memory manager delete any temp files before we die */
80  jpeg_destroy(cinfo);
81 
82  /* return control to the setjmp point */
83  longjmp(err->setjmp_buffer, 1);
84 }
85 
86 /*----------------------------------------------------------
87  * INPUT HANDLER FROM MEMORY
88  *---------------------------------------------------------- */
89 
90 #if 0
91 typedef struct {
92  unsigned char *buffer;
93  int filled;
94 } buffer_struct;
95 #endif
96 
97 typedef struct {
98  struct jpeg_source_mgr pub; /* public fields */
99 
100  const unsigned char *buffer;
101  int size;
102  JOCTET terminal[2];
103 } my_source_mgr;
104 
106 
107 static void init_source(j_decompress_ptr cinfo)
108 {
109  (void)cinfo; /* unused */
110 }
111 
112 static boolean fill_input_buffer(j_decompress_ptr cinfo)
113 {
114  my_src_ptr src = (my_src_ptr)cinfo->src;
115 
116  /* Since we have given all we have got already
117  * we simply fake an end of file
118  */
119 
120  src->pub.next_input_byte = src->terminal;
121  src->pub.bytes_in_buffer = 2;
122  src->terminal[0] = (JOCTET)0xFF;
123  src->terminal[1] = (JOCTET)JPEG_EOI;
124 
125  return true;
126 }
127 
128 static void skip_input_data(j_decompress_ptr cinfo, long num_bytes)
129 {
130  my_src_ptr src = (my_src_ptr)cinfo->src;
131 
132  if (num_bytes > 0) {
133  /* prevent skipping over file end */
134  size_t skip_size = (size_t)num_bytes <= src->pub.bytes_in_buffer ? num_bytes :
135  src->pub.bytes_in_buffer;
136 
137  src->pub.next_input_byte = src->pub.next_input_byte + skip_size;
138  src->pub.bytes_in_buffer = src->pub.bytes_in_buffer - skip_size;
139  }
140 }
141 
142 static void term_source(j_decompress_ptr cinfo)
143 {
144  (void)cinfo; /* unused */
145 }
146 
147 static void memory_source(j_decompress_ptr cinfo, const unsigned char *buffer, size_t size)
148 {
149  my_src_ptr src;
150 
151  if (cinfo->src == NULL) { /* first time for this JPEG object? */
152  cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)(
153  (j_common_ptr)cinfo, JPOOL_PERMANENT, sizeof(my_source_mgr));
154  }
155 
156  src = (my_src_ptr)cinfo->src;
157  src->pub.init_source = init_source;
158  src->pub.fill_input_buffer = fill_input_buffer;
159  src->pub.skip_input_data = skip_input_data;
160  src->pub.resync_to_restart = jpeg_resync_to_restart;
161  src->pub.term_source = term_source;
162 
163  src->pub.bytes_in_buffer = size;
164  src->pub.next_input_byte = buffer;
165 
166  src->buffer = buffer;
167  src->size = size;
168 }
169 
170 #define MAKESTMT(stuff) \
171  do { \
172  stuff \
173  } while (0)
174 
175 #define INPUT_VARS(cinfo) \
176  struct jpeg_source_mgr *datasrc = (cinfo)->src; \
177  const JOCTET *next_input_byte = datasrc->next_input_byte; \
178  size_t bytes_in_buffer = datasrc->bytes_in_buffer
179 
180 /* Unload the local copies --- do this only at a restart boundary */
181 #define INPUT_SYNC(cinfo) \
182  (datasrc->next_input_byte = next_input_byte, datasrc->bytes_in_buffer = bytes_in_buffer)
183 
184 /* Reload the local copies --- seldom used except in MAKE_BYTE_AVAIL */
185 #define INPUT_RELOAD(cinfo) \
186  (next_input_byte = datasrc->next_input_byte, bytes_in_buffer = datasrc->bytes_in_buffer)
187 
188 /* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available.
189  * Note we do *not* do INPUT_SYNC before calling fill_input_buffer,
190  * but we must reload the local copies after a successful fill.
191  */
192 #define MAKE_BYTE_AVAIL(cinfo, action) \
193  if (bytes_in_buffer == 0) { \
194  if (!(*datasrc->fill_input_buffer)(cinfo)) { \
195  action; \
196  } \
197  INPUT_RELOAD(cinfo); \
198  } \
199  (void)0
200 
201 /* Read a byte into variable V.
202  * If must suspend, take the specified action (typically "return false").
203  */
204 #define INPUT_BYTE(cinfo, V, action) \
205  MAKESTMT(MAKE_BYTE_AVAIL(cinfo, action); bytes_in_buffer--; V = GETJOCTET(*next_input_byte++);)
206 
207 /* As above, but read two bytes interpreted as an unsigned 16-bit integer.
208  * V should be declared unsigned int or perhaps INT32.
209  */
210 #define INPUT_2BYTES(cinfo, V, action) \
211  MAKESTMT(MAKE_BYTE_AVAIL(cinfo, action); bytes_in_buffer--; \
212  V = ((unsigned int)GETJOCTET(*next_input_byte++)) << 8; \
213  MAKE_BYTE_AVAIL(cinfo, action); \
214  bytes_in_buffer--; \
215  V += GETJOCTET(*next_input_byte++);)
216 
217 struct NeoGeo_Word {
222 };
223 BLI_STATIC_ASSERT(sizeof(struct NeoGeo_Word) == 4, "Must be 4 bytes");
224 
225 static boolean handle_app1(j_decompress_ptr cinfo)
226 {
227  INT32 length; /* initialized by the macro */
228  INT32 i;
229  char neogeo[128];
230 
231  INPUT_VARS(cinfo);
232 
233  INPUT_2BYTES(cinfo, length, return false);
234  length -= 2;
235 
236  if (length < 16) {
237  for (i = 0; i < length; i++) {
238  INPUT_BYTE(cinfo, neogeo[i], return false);
239  }
240  length = 0;
241  if (STRPREFIX(neogeo, "NeoGeo")) {
242  struct NeoGeo_Word *neogeo_word = (struct NeoGeo_Word *)(neogeo + 6);
243  ibuf_quality = neogeo_word->quality;
244  }
245  }
246  INPUT_SYNC(cinfo); /* do before skip_input_data */
247  if (length > 0) {
248  (*cinfo->src->skip_input_data)(cinfo, length);
249  }
250  return true;
251 }
252 
253 static ImBuf *ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo,
254  int flags,
255  int max_size,
256  size_t *r_width,
257  size_t *r_height)
258 {
259  JSAMPARRAY row_pointer;
260  JSAMPLE *buffer = NULL;
261  int row_stride;
262  int x, y, depth, r, g, b, k;
263  struct ImBuf *ibuf = NULL;
264  uchar *rect;
265  jpeg_saved_marker_ptr marker;
266  char *str, *key, *value;
267 
268  /* install own app1 handler */
270  jpeg_set_marker_processor(cinfo, 0xe1, handle_app1);
271  cinfo->dct_method = JDCT_FLOAT;
272  jpeg_save_markers(cinfo, JPEG_COM, 0xffff);
273 
274  if (jpeg_read_header(cinfo, false) == JPEG_HEADER_OK) {
275  depth = cinfo->num_components;
276 
277  if (cinfo->jpeg_color_space == JCS_YCCK) {
278  cinfo->out_color_space = JCS_CMYK;
279  }
280 
281  if (r_width) {
282  *r_width = cinfo->image_width;
283  }
284  if (r_height) {
285  *r_height = cinfo->image_height;
286  }
287 
288  if (max_size > 0) {
289  /* `libjpeg` can more quickly decompress while scaling down to 1/2, 1/4, 1/8,
290  * while `libjpeg-turbo` can also do 3/8, 5/8, etc. But max is 1/8. */
291  float scale = (float)max_size / MAX2(cinfo->image_width, cinfo->image_height);
292  cinfo->scale_denom = 8;
293  cinfo->scale_num = max_uu(1, min_uu(8, ceill(scale * (float)cinfo->scale_denom)));
294  cinfo->dct_method = JDCT_FASTEST;
295  cinfo->dither_mode = JDITHER_ORDERED;
296  }
297 
298  jpeg_start_decompress(cinfo);
299 
300  x = cinfo->output_width;
301  y = cinfo->output_height;
302 
303  if (flags & IB_test) {
304  jpeg_abort_decompress(cinfo);
305  ibuf = IMB_allocImBuf(x, y, 8 * depth, 0);
306  }
307  else if ((ibuf = IMB_allocImBuf(x, y, 8 * depth, IB_rect)) == NULL) {
308  jpeg_abort_decompress(cinfo);
309  }
310  else {
311  row_stride = cinfo->output_width * depth;
312 
313  row_pointer = (*cinfo->mem->alloc_sarray)((j_common_ptr)cinfo, JPOOL_IMAGE, row_stride, 1);
314 
315  for (y = ibuf->y - 1; y >= 0; y--) {
316  jpeg_read_scanlines(cinfo, row_pointer, 1);
317  rect = (uchar *)(ibuf->rect + y * ibuf->x);
318  buffer = row_pointer[0];
319 
320  switch (depth) {
321  case 1:
322  for (x = ibuf->x; x > 0; x--) {
323  rect[3] = 255;
324  rect[0] = rect[1] = rect[2] = *buffer++;
325  rect += 4;
326  }
327  break;
328  case 3:
329  for (x = ibuf->x; x > 0; x--) {
330  rect[3] = 255;
331  rect[0] = *buffer++;
332  rect[1] = *buffer++;
333  rect[2] = *buffer++;
334  rect += 4;
335  }
336  break;
337  case 4:
338  for (x = ibuf->x; x > 0; x--) {
339  r = *buffer++;
340  g = *buffer++;
341  b = *buffer++;
342  k = *buffer++;
343 
344  r = (r * k) / 255;
345  g = (g * k) / 255;
346  b = (b * k) / 255;
347 
348  rect[3] = 255;
349  rect[2] = b;
350  rect[1] = g;
351  rect[0] = r;
352  rect += 4;
353  }
354  break;
355  }
356  }
357 
358  marker = cinfo->marker_list;
359  while (marker) {
360  if (marker->marker != JPEG_COM) {
361  goto next_stamp_marker;
362  }
363 
364  /*
365  * JPEG marker strings are not null-terminated,
366  * create a null-terminated copy before going further
367  */
368  str = BLI_strdupn((char *)marker->data, marker->data_length);
369 
370  /*
371  * Because JPEG format don't support the
372  * pair "key/value" like PNG, we store the
373  * stamp-info in a single "encode" string:
374  * "Blender:key:value"
375  *
376  * That is why we need split it to the
377  * common key/value here.
378  */
379  if (!STRPREFIX(str, "Blender")) {
380  /*
381  * Maybe the file have text that
382  * we don't know "what it's", in that
383  * case we keep the text (with a
384  * key "None").
385  * This is only for don't "lose"
386  * the information when we write
387  * it back to disk.
388  */
390  IMB_metadata_set_field(ibuf->metadata, "None", str);
391  ibuf->flags |= IB_metadata;
392  MEM_freeN(str);
393  goto next_stamp_marker;
394  }
395 
396  key = strchr(str, ':');
397  /*
398  * A little paranoid, but the file maybe
399  * is broken... and a "extra" check is better
400  * then segfault ;)
401  */
402  if (!key) {
403  MEM_freeN(str);
404  goto next_stamp_marker;
405  }
406 
407  key++;
408  value = strchr(key, ':');
409  if (!value) {
410  MEM_freeN(str);
411  goto next_stamp_marker;
412  }
413 
414  *value = '\0'; /* need finish the key string */
415  value++;
417  IMB_metadata_set_field(ibuf->metadata, key, value);
418  ibuf->flags |= IB_metadata;
419  MEM_freeN(str);
420  next_stamp_marker:
421  marker = marker->next;
422  }
423 
424  jpeg_finish_decompress(cinfo);
425  }
426 
427  if (ibuf) {
428  /* Density_unit may be 0 for unknown, 1 for dots/inch, or 2 for dots/cm. */
429  if (cinfo->density_unit == 1) {
430  /* Convert inches to meters. */
431  ibuf->ppm[0] = cinfo->X_density / 0.0254f;
432  ibuf->ppm[1] = cinfo->Y_density / 0.0254f;
433  }
434  else if (cinfo->density_unit == 2) {
435  ibuf->ppm[0] = cinfo->X_density * 100.0f;
436  ibuf->ppm[1] = cinfo->Y_density * 100.0f;
437  }
438 
439  ibuf->ftype = IMB_FTYPE_JPG;
440  ibuf->foptions.quality = MIN2(ibuf_quality, 100);
441  }
442  jpeg_destroy((j_common_ptr)cinfo);
443  }
444 
445  return ibuf;
446 }
447 
448 ImBuf *imb_load_jpeg(const unsigned char *buffer,
449  size_t size,
450  int flags,
451  char colorspace[IM_MAX_SPACE])
452 {
453  struct jpeg_decompress_struct _cinfo, *cinfo = &_cinfo;
454  struct my_error_mgr jerr;
455  ImBuf *ibuf;
456 
457  if (!imb_is_a_jpeg(buffer, size)) {
458  return NULL;
459  }
460 
462 
463  cinfo->err = jpeg_std_error(&jerr.pub);
464  jerr.pub.error_exit = jpeg_error;
465 
466  /* Establish the setjmp return context for my_error_exit to use. */
467  if (setjmp(jerr.setjmp_buffer)) {
468  /* If we get here, the JPEG code has signaled an error.
469  * We need to clean up the JPEG object, close the input file, and return.
470  */
471  jpeg_destroy_decompress(cinfo);
472  return NULL;
473  }
474 
475  jpeg_create_decompress(cinfo);
476  memory_source(cinfo, buffer, size);
477 
478  ibuf = ibJpegImageFromCinfo(cinfo, flags, -1, NULL, NULL);
479 
480  return ibuf;
481 }
482 
483 /* Defines for JPEG Header markers and segment size. */
484 #define JPEG_MARKER_MSB (0xFF)
485 #define JPEG_MARKER_SOI (0xD8)
486 #define JPEG_MARKER_APP1 (0xE1)
487 #define JPEG_APP1_MAX (1 << 16)
488 
489 struct ImBuf *imb_thumbnail_jpeg(const char *filepath,
490  const int flags,
491  const size_t max_thumb_size,
492  char colorspace[IM_MAX_SPACE],
493  size_t *r_width,
494  size_t *r_height)
495 {
496  struct jpeg_decompress_struct _cinfo, *cinfo = &_cinfo;
497  struct my_error_mgr jerr;
498  FILE *infile = NULL;
499 
501 
502  cinfo->err = jpeg_std_error(&jerr.pub);
503  jerr.pub.error_exit = jpeg_error;
504 
505  /* Establish the setjmp return context for my_error_exit to use. */
506  if (setjmp(jerr.setjmp_buffer)) {
507  /* If we get here, the JPEG code has signaled an error.
508  * We need to clean up the JPEG object, close the input file, and return.
509  */
510  jpeg_destroy_decompress(cinfo);
511  return NULL;
512  }
513 
514  if ((infile = BLI_fopen(filepath, "rb")) == NULL) {
515  fprintf(stderr, "can't open %s\n", filepath);
516  return NULL;
517  }
518 
519  /* If file contains an embedded thumbnail, let's return that instead. */
520 
521  if ((fgetc(infile) == JPEG_MARKER_MSB) && (fgetc(infile) == JPEG_MARKER_SOI) &&
522  (fgetc(infile) == JPEG_MARKER_MSB) && (fgetc(infile) == JPEG_MARKER_APP1)) {
523  /* This is a JPEG in EXIF format (SOI + APP1), not JFIF (SOI + APP0). */
524  unsigned int i = JPEG_APP1_MAX;
525  /* All EXIF data is within this 64K header segment. Skip ahead until next SOI for thumbnail. */
526  while (!((fgetc(infile) == JPEG_MARKER_MSB) && (fgetc(infile) == JPEG_MARKER_SOI)) &&
527  !feof(infile) && i--) {
528  }
529  if (i > 0 && !feof(infile)) {
530  /* We found a JPEG thumbnail inside this image. */
531  ImBuf *ibuf = NULL;
532  uchar *buffer = MEM_callocN(JPEG_APP1_MAX, "thumbbuffer");
533  /* Just put SOI directly in buffer rather than seeking back 2 bytes. */
534  buffer[0] = JPEG_MARKER_MSB;
535  buffer[1] = JPEG_MARKER_SOI;
536  if (fread(buffer + 2, JPEG_APP1_MAX - 2, 1, infile) == 1) {
537  ibuf = imb_load_jpeg(buffer, JPEG_APP1_MAX, flags, colorspace);
538  }
540  if (ibuf) {
541  fclose(infile);
542  return ibuf;
543  }
544  }
545  }
546 
547  /* No embedded thumbnail found, so let's create a new one. */
548 
549  fseek(infile, 0, SEEK_SET);
550  jpeg_create_decompress(cinfo);
551 
552  jpeg_stdio_src(cinfo, infile);
553  ImBuf *ibuf = ibJpegImageFromCinfo(cinfo, flags, max_thumb_size, r_width, r_height);
554  fclose(infile);
555 
556  return ibuf;
557 }
558 
559 #undef JPEG_MARKER_MSB
560 #undef JPEG_MARKER_SOI
561 #undef JPEG_MARKER_APP1
562 #undef JPEG_APP1_MAX
563 
564 static void write_jpeg(struct jpeg_compress_struct *cinfo, struct ImBuf *ibuf)
565 {
566  JSAMPLE *buffer = NULL;
567  JSAMPROW row_pointer[1];
568  uchar *rect;
569  int x, y;
570  char neogeo[128];
571  struct NeoGeo_Word *neogeo_word;
572 
573  jpeg_start_compress(cinfo, true);
574 
575  strcpy(neogeo, "NeoGeo");
576  neogeo_word = (struct NeoGeo_Word *)(neogeo + 6);
577  memset(neogeo_word, 0, sizeof(*neogeo_word));
578  neogeo_word->quality = ibuf->foptions.quality;
579  jpeg_write_marker(cinfo, 0xe1, (JOCTET *)neogeo, 10);
580  if (ibuf->metadata) {
581  IDProperty *prop;
582  /* Static storage array for the short metadata. */
583  char static_text[1024];
584  const int static_text_size = ARRAY_SIZE(static_text);
585  for (prop = ibuf->metadata->data.group.first; prop; prop = prop->next) {
586  if (prop->type == IDP_STRING) {
587  int text_len;
588  if (STREQ(prop->name, "None")) {
589  jpeg_write_marker(cinfo, JPEG_COM, (JOCTET *)IDP_String(prop), prop->len + 1);
590  }
591 
592  char *text = static_text;
593  int text_size = static_text_size;
594  /* 7 is for Blender, 2 colon separators, length of property
595  * name and property value, followed by the NULL-terminator. */
596  const int text_length_required = 7 + 2 + strlen(prop->name) + strlen(IDP_String(prop)) + 1;
597  if (text_length_required <= static_text_size) {
598  text = MEM_mallocN(text_length_required, "jpeg metadata field");
599  text_size = text_length_required;
600  }
601 
602  /*
603  * The JPEG format don't support a pair "key/value"
604  * like PNG, so we "encode" the stamp in a
605  * single string:
606  * "Blender:key:value"
607  *
608  * The first "Blender" is a simple identify to help
609  * in the read process.
610  */
611  text_len = BLI_snprintf_rlen(
612  text, text_size, "Blender:%s:%s", prop->name, IDP_String(prop));
613  jpeg_write_marker(cinfo, JPEG_COM, (JOCTET *)text, text_len + 1);
614 
615  /* TODO(sergey): Ideally we will try to re-use allocation as
616  * much as possible. In practice, such long fields don't happen
617  * often. */
618  if (text != static_text) {
619  MEM_freeN(text);
620  }
621  }
622  }
623  }
624 
625  row_pointer[0] = MEM_mallocN(sizeof(JSAMPLE) * cinfo->input_components * cinfo->image_width,
626  "jpeg row_pointer");
627 
628  for (y = ibuf->y - 1; y >= 0; y--) {
629  rect = (uchar *)(ibuf->rect + y * ibuf->x);
630  buffer = row_pointer[0];
631 
632  switch (cinfo->in_color_space) {
633  case JCS_RGB:
634  for (x = 0; x < ibuf->x; x++) {
635  *buffer++ = rect[0];
636  *buffer++ = rect[1];
637  *buffer++ = rect[2];
638  rect += 4;
639  }
640  break;
641  case JCS_GRAYSCALE:
642  for (x = 0; x < ibuf->x; x++) {
643  *buffer++ = rect[0];
644  rect += 4;
645  }
646  break;
647  case JCS_UNKNOWN:
648  memcpy(buffer, rect, 4 * ibuf->x);
649  break;
650  /* default was missing... intentional ? */
651  default:
652  /* do nothing */
653  break;
654  }
655 
656  jpeg_write_scanlines(cinfo, row_pointer, 1);
657  }
658 
659  jpeg_finish_compress(cinfo);
660  MEM_freeN(row_pointer[0]);
661 }
662 
663 static int init_jpeg(FILE *outfile, struct jpeg_compress_struct *cinfo, struct ImBuf *ibuf)
664 {
665  int quality;
666 
667  quality = ibuf->foptions.quality;
668  if (quality <= 0) {
670  }
671  if (quality > 100) {
672  quality = 100;
673  }
674 
675  jpeg_create_compress(cinfo);
676  jpeg_stdio_dest(cinfo, outfile);
677 
678  cinfo->image_width = ibuf->x;
679  cinfo->image_height = ibuf->y;
680 
681  cinfo->in_color_space = JCS_RGB;
682  if (ibuf->planes == 8) {
683  cinfo->in_color_space = JCS_GRAYSCALE;
684  }
685 #if 0
686  /* just write RGBA as RGB,
687  * unsupported feature only confuses other s/w */
688 
689  if (ibuf->planes == 32) {
690  cinfo->in_color_space = JCS_UNKNOWN;
691  }
692 #endif
693  switch (cinfo->in_color_space) {
694  case JCS_RGB:
695  cinfo->input_components = 3;
696  break;
697  case JCS_GRAYSCALE:
698  cinfo->input_components = 1;
699  break;
700  case JCS_UNKNOWN:
701  cinfo->input_components = 4;
702  break;
703  /* default was missing... intentional ? */
704  default:
705  /* do nothing */
706  break;
707  }
708  jpeg_set_defaults(cinfo);
709 
710  /* own settings */
711 
712  cinfo->dct_method = JDCT_FLOAT;
713  jpeg_set_quality(cinfo, quality, true);
714 
715  return 0;
716 }
717 
718 static bool save_stdjpeg(const char *name, struct ImBuf *ibuf)
719 {
720  FILE *outfile;
721  struct jpeg_compress_struct _cinfo, *cinfo = &_cinfo;
722  struct my_error_mgr jerr;
723 
724  if ((outfile = BLI_fopen(name, "wb")) == NULL) {
725  return 0;
726  }
727 
728  cinfo->err = jpeg_std_error(&jerr.pub);
729  jerr.pub.error_exit = jpeg_error;
730 
731  /* Establish the setjmp return context for jpeg_error to use. */
732  if (setjmp(jerr.setjmp_buffer)) {
733  /* If we get here, the JPEG code has signaled an error.
734  * We need to clean up the JPEG object, close the input file, and return.
735  */
736  jpeg_destroy_compress(cinfo);
737  fclose(outfile);
738  remove(name);
739  return 0;
740  }
741 
742  init_jpeg(outfile, cinfo, ibuf);
743 
744  write_jpeg(cinfo, ibuf);
745 
746  fclose(outfile);
747  jpeg_destroy_compress(cinfo);
748 
749  return 1;
750 }
751 
752 bool imb_savejpeg(struct ImBuf *ibuf, const char *filepath, int flags)
753 {
754 
755  ibuf->flags = flags;
756  return save_stdjpeg(filepath, ibuf);
757 }
typedef float(TangentPoint)[2]
#define IDP_String(prop)
Definition: BKE_idprop.h:271
#define ATTR_NORETURN
File and directory operations.
FILE * BLI_fopen(const char *filepath, const char *mode) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: fileops.c:906
MINLINE uint min_uu(uint a, uint b)
MINLINE uint max_uu(uint a, uint b)
size_t BLI_snprintf_rlen(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char * BLI_strdupn(const char *str, size_t len) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: string.c:33
unsigned char uchar
Definition: BLI_sys_types.h:70
#define STRPREFIX(a, b)
#define ARRAY_SIZE(arr)
#define MAX2(a, b)
#define MIN2(a, b)
#define STREQ(a, b)
ID and Library types, which are fundamental for sdna.
@ IDP_STRING
Definition: DNA_ID.h:136
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
@ COLOR_ROLE_DEFAULT_BYTE
struct ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
Definition: allocimbuf.c:500
#define IM_MAX_SPACE
Definition: IMB_imbuf.h:49
Contains defines and structs used throughout the imbuf module.
@ IB_metadata
@ IB_test
@ IB_rect
void IMB_metadata_set_field(struct IDProperty *metadata, const char *key, const char *value)
Definition: metadata.c:73
void IMB_metadata_ensure(struct IDProperty **metadata)
Definition: metadata.c:25
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
void colorspace_set_default_role(char *colorspace, int size, int role)
SyclQueue void void * src
SyclQueue void void size_t num_bytes void
#define str(s)
@ IMB_FTYPE_JPG
#define JPEG_MARKER_APP1
Definition: jpeg.c:486
#define INPUT_BYTE(cinfo, V, action)
Definition: jpeg.c:204
static const uchar jpeg_default_quality
Definition: jpeg.c:48
static ImBuf * ibJpegImageFromCinfo(struct jpeg_decompress_struct *cinfo, int flags, int max_size, size_t *r_width, size_t *r_height)
Definition: jpeg.c:253
#define JPEG_MARKER_MSB
Definition: jpeg.c:484
static void write_jpeg(struct jpeg_compress_struct *cinfo, struct ImBuf *ibuf)
Definition: jpeg.c:564
bool imb_savejpeg(struct ImBuf *ibuf, const char *filepath, int flags)
Definition: jpeg.c:752
static bool save_stdjpeg(const char *name, struct ImBuf *ibuf)
Definition: jpeg.c:718
my_source_mgr * my_src_ptr
Definition: jpeg.c:105
#define JPEG_MARKER_SOI
Definition: jpeg.c:485
#define INPUT_2BYTES(cinfo, V, action)
Definition: jpeg.c:210
#define INPUT_VARS(cinfo)
Definition: jpeg.c:175
struct my_error_mgr my_error_mgr
my_error_mgr * my_error_ptr
Definition: jpeg.c:70
static int init_jpeg(FILE *outfile, struct jpeg_compress_struct *cinfo, struct ImBuf *ibuf)
Definition: jpeg.c:663
BLI_STATIC_ASSERT(sizeof(struct NeoGeo_Word)==4, "Must be 4 bytes")
static void term_source(j_decompress_ptr cinfo)
Definition: jpeg.c:142
static uchar ibuf_quality
Definition: jpeg.c:49
static boolean handle_app1(j_decompress_ptr cinfo)
Definition: jpeg.c:225
#define INPUT_SYNC(cinfo)
Definition: jpeg.c:181
static void skip_input_data(j_decompress_ptr cinfo, long num_bytes)
Definition: jpeg.c:128
static void init_source(j_decompress_ptr cinfo)
Definition: jpeg.c:107
static void jpeg_error(j_common_ptr cinfo) ATTR_NORETURN
Definition: jpeg.c:72
static boolean fill_input_buffer(j_decompress_ptr cinfo)
Definition: jpeg.c:112
struct ImBuf * imb_thumbnail_jpeg(const char *filepath, const int flags, const size_t max_thumb_size, char colorspace[IM_MAX_SPACE], size_t *r_width, size_t *r_height)
Definition: jpeg.c:489
#define JPEG_APP1_MAX
Definition: jpeg.c:487
bool imb_is_a_jpeg(const unsigned char *mem, const size_t size)
Definition: jpeg.c:51
static void memory_source(j_decompress_ptr cinfo, const unsigned char *buffer, size_t size)
Definition: jpeg.c:147
ImBuf * imb_load_jpeg(const unsigned char *buffer, size_t size, int flags, char colorspace[IM_MAX_SPACE])
Definition: jpeg.c:448
ccl_global float * buffer
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
bool remove(void *owner, const AttributeIDRef &attribute_id)
T length(const vec_base< T, Size > &a)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static const pxr::TfToken g("g", pxr::TfToken::Immortal)
ListBase group
Definition: DNA_ID.h:101
int len
Definition: DNA_ID.h:121
struct IDProperty * next
Definition: DNA_ID.h:107
char name[64]
Definition: DNA_ID.h:111
IDPropertyData data
Definition: DNA_ID.h:117
char type
Definition: DNA_ID.h:108
struct IDProperty * metadata
ImbFormatOptions foptions
unsigned char planes
enum eImbFileType ftype
unsigned int * rect
double ppm[2]
void * first
Definition: DNA_listBase.h:31
uchar pad2
Definition: jpeg.c:219
uchar pad1
Definition: jpeg.c:218
uchar pad3
Definition: jpeg.c:220
uchar quality
Definition: jpeg.c:221
jmp_buf setjmp_buffer
Definition: jpeg.c:67
struct jpeg_error_mgr pub
Definition: jpeg.c:65
int size
Definition: jpeg.c:101
const unsigned char * buffer
Definition: jpeg.c:100
static int magic(const Tex *tex, const float texvec[3], TexResult *texres)
static FT_Error err