~ubuntu-branches/ubuntu/saucy/darktable/saucy

« back to all changes in this revision

Viewing changes to src/common/imageio_jpeg.c

  • Committer: Bazaar Package Importer
  • Author(s): David Bremner
  • Date: 2011-04-14 23:42:12 UTC
  • Revision ID: james.westby@ubuntu.com-20110414234212-kuffcz5wiu18v6ra
Tags: upstream-0.8
ImportĀ upstreamĀ versionĀ 0.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    This file is part of darktable,
 
3
    copyright (c) 2009--2010 johannes hanika.
 
4
 
 
5
    darktable is free software: you can redistribute it and/or modify
 
6
    it under the terms of the GNU General Public License as published by
 
7
    the Free Software Foundation, either version 3 of the License, or
 
8
    (at your option) any later version.
 
9
 
 
10
    darktable is distributed in the hope that it will be useful,
 
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
    GNU General Public License for more details.
 
14
 
 
15
    You should have received a copy of the GNU General Public License
 
16
    along with darktable.  If not, see <http://www.gnu.org/licenses/>.
 
17
*/
 
18
 
 
19
 
 
20
 
 
21
#ifdef HAVE_CONFIG_H
 
22
#include "config.h"
 
23
#endif
 
24
#include "common/colorspaces.h"
 
25
#include "common/imageio_jpeg.h"
 
26
#include <setjmp.h>
 
27
 
 
28
// error functions
 
29
 
 
30
struct dt_imageio_jpeg_error_mgr
 
31
{
 
32
  struct jpeg_error_mgr pub;
 
33
  jmp_buf setjmp_buffer;
 
34
}
 
35
dt_imageio_jpeg_error_mgr;
 
36
 
 
37
typedef struct dt_imageio_jpeg_error_mgr *dt_imageio_jpeg_error_ptr;
 
38
 
 
39
void dt_imageio_jpeg_error_exit (j_common_ptr cinfo)
 
40
{
 
41
  dt_imageio_jpeg_error_ptr myerr = (dt_imageio_jpeg_error_ptr) cinfo->err;
 
42
  (*cinfo->err->output_message) (cinfo);
 
43
  longjmp(myerr->setjmp_buffer, 1);
 
44
}
 
45
 
 
46
// destination functions
 
47
void dt_imageio_jpeg_init_destination(j_compress_ptr cinfo) {}
 
48
boolean dt_imageio_jpeg_empty_output_buffer(j_compress_ptr cinfo)
 
49
{
 
50
  fprintf(stderr, "[imageio_jpeg] output buffer full!\n");
 
51
  return FALSE;
 
52
}
 
53
void dt_imageio_jpeg_term_destination(j_compress_ptr cinfo) {}
 
54
 
 
55
// source functions
 
56
void dt_imageio_jpeg_init_source(j_decompress_ptr cinfo) {}
 
57
boolean dt_imageio_jpeg_fill_input_buffer(j_decompress_ptr cinfo)
 
58
{
 
59
  return 1;
 
60
}
 
61
void dt_imageio_jpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
 
62
{
 
63
  int i = cinfo->src->bytes_in_buffer - num_bytes;
 
64
  if (i < 0) i = 0;
 
65
  cinfo->src->bytes_in_buffer = i;
 
66
  cinfo->src->next_input_byte += num_bytes;
 
67
}
 
68
void dt_imageio_jpeg_term_source(j_decompress_ptr cinfo) {}
 
69
 
 
70
 
 
71
int dt_imageio_jpeg_decompress_header(const void *in, size_t length, dt_imageio_jpeg_t *jpg)
 
72
{
 
73
  jpeg_create_decompress(&(jpg->dinfo));
 
74
  jpg->src.init_source = dt_imageio_jpeg_init_source;
 
75
  jpg->src.fill_input_buffer = dt_imageio_jpeg_fill_input_buffer;
 
76
  jpg->src.skip_input_data = dt_imageio_jpeg_skip_input_data;
 
77
  jpg->src.resync_to_restart = jpeg_resync_to_restart;
 
78
  jpg->src.term_source = dt_imageio_jpeg_term_source;
 
79
  jpg->src.next_input_byte = (JOCTET*)in;
 
80
  jpg->src.bytes_in_buffer = length;
 
81
 
 
82
  struct dt_imageio_jpeg_error_mgr jerr;
 
83
  jpg->dinfo.err = jpeg_std_error(&jerr.pub);
 
84
  jerr.pub.error_exit = dt_imageio_jpeg_error_exit;
 
85
  if (setjmp(jerr.setjmp_buffer))
 
86
  {
 
87
    jpeg_destroy_decompress(&(jpg->dinfo));
 
88
    return 1;
 
89
  }
 
90
 
 
91
  jpg->dinfo.src = &(jpg->src);
 
92
  // jpg->dinfo.buffered_image = TRUE;
 
93
  jpeg_read_header(&(jpg->dinfo), TRUE);
 
94
  jpg->width  = jpg->dinfo.image_width;
 
95
  jpg->height = jpg->dinfo.image_height;
 
96
  return 0;
 
97
}
 
98
 
 
99
int dt_imageio_jpeg_decompress(dt_imageio_jpeg_t *jpg, uint8_t *out)
 
100
{
 
101
  struct dt_imageio_jpeg_error_mgr jerr;
 
102
  jpg->dinfo.err = jpeg_std_error(&jerr.pub);
 
103
  if (setjmp(jerr.setjmp_buffer))
 
104
  {
 
105
    jpeg_destroy_decompress(&(jpg->dinfo));
 
106
    return 1;
 
107
  }
 
108
  (void)jpeg_start_decompress(&(jpg->dinfo));
 
109
  JSAMPROW row_pointer[1];
 
110
  row_pointer[0] = (uint8_t *)malloc(jpg->dinfo.output_width*jpg->dinfo.num_components);
 
111
  uint8_t *tmp = out;
 
112
  while(jpg->dinfo.output_scanline < jpg->dinfo.image_height)
 
113
  {
 
114
    if(jpeg_read_scanlines(&(jpg->dinfo), row_pointer, 1) != 1)
 
115
    {
 
116
      free(row_pointer[0]);
 
117
      return 1;
 
118
    }
 
119
    for(int i=0; i<jpg->dinfo.image_width; i++) for(int k=0; k<3; k++)
 
120
        tmp[4*i+k] = row_pointer[0][3*i+k];
 
121
    tmp += 4*jpg->width;
 
122
  }
 
123
  // jpg->dinfo.src = NULL;
 
124
  // (void)jpeg_finish_decompress(&(jpg->dinfo)); // ???
 
125
  jpeg_destroy_decompress(&(jpg->dinfo));
 
126
  free(row_pointer[0]);
 
127
  return 0;
 
128
}
 
129
 
 
130
int dt_imageio_jpeg_compress(const uint8_t *in, uint8_t *out, const int width, const int height, const int quality)
 
131
{
 
132
  struct dt_imageio_jpeg_error_mgr jerr;
 
133
  dt_imageio_jpeg_t jpg;
 
134
  jpg.dest.init_destination = dt_imageio_jpeg_init_destination;
 
135
  jpg.dest.empty_output_buffer= dt_imageio_jpeg_empty_output_buffer;
 
136
  jpg.dest.term_destination = dt_imageio_jpeg_term_destination;
 
137
  jpg.dest.next_output_byte = (JOCTET *)out;
 
138
  jpg.dest.free_in_buffer = 4*width*height*sizeof(uint8_t);
 
139
 
 
140
  jpg.cinfo.err = jpeg_std_error(&jerr.pub);
 
141
  jerr.pub.error_exit = dt_imageio_jpeg_error_exit;
 
142
  if (setjmp(jerr.setjmp_buffer))
 
143
  {
 
144
    jpeg_destroy_compress(&(jpg.cinfo));
 
145
    return 1;
 
146
  }
 
147
  jpeg_create_compress(&(jpg.cinfo));
 
148
  jpg.cinfo.dest = &(jpg.dest);
 
149
 
 
150
  jpg.cinfo.image_width = width;
 
151
  jpg.cinfo.image_height = height;
 
152
  jpg.cinfo.input_components = 3;
 
153
  jpg.cinfo.in_color_space = JCS_RGB;
 
154
  jpeg_set_defaults(&(jpg.cinfo));
 
155
  jpeg_set_quality(&(jpg.cinfo), quality, TRUE);
 
156
  if(quality > 90) jpg.cinfo.comp_info[0].v_samp_factor = 1;
 
157
  if(quality > 92) jpg.cinfo.comp_info[0].h_samp_factor = 1;
 
158
  jpeg_start_compress(&(jpg.cinfo), TRUE);
 
159
  uint8_t row[3*width];
 
160
  const uint8_t *buf;
 
161
  while(jpg.cinfo.next_scanline < jpg.cinfo.image_height)
 
162
  {
 
163
    JSAMPROW tmp[1];
 
164
    buf = in + jpg.cinfo.next_scanline * jpg.cinfo.image_width * 4;
 
165
    for(int i=0; i<width; i++) for(int k=0; k<3; k++) row[3*i+k] = buf[4*i+k];
 
166
    tmp[0] = row;
 
167
    jpeg_write_scanlines(&(jpg.cinfo), tmp, 1);
 
168
  }
 
169
  jpeg_finish_compress (&(jpg.cinfo));
 
170
  jpeg_destroy_compress(&(jpg.cinfo));
 
171
  return 4*width*height*sizeof(uint8_t) - jpg.dest.free_in_buffer;
 
172
}
 
173
 
 
174
/*
 
175
 * Since an ICC profile can be larger than the maximum size of a JPEG marker
 
176
 * (64K), we need provisions to split it into multiple markers.  The format
 
177
 * defined by the ICC specifies one or more APP2 markers containing the
 
178
 * following data:
 
179
 *      Identifying string      ASCII "ICC_PROFILE\0"  (12 bytes)
 
180
 *      Marker sequence number  1 for first APP2, 2 for next, etc (1 byte)
 
181
 *      Number of markers       Total number of APP2's used (1 byte)
 
182
 *      Profile data            (remainder of APP2 data)
 
183
 * Decoders should use the marker sequence numbers to reassemble the profile,
 
184
 * rather than assuming that the APP2 markers appear in the correct sequence.
 
185
 */
 
186
 
 
187
#define ICC_MARKER  (JPEG_APP0 + 2)     /* JPEG marker code for ICC */
 
188
#define ICC_OVERHEAD_LEN  14            /* size of non-profile data in APP2 */
 
189
#define MAX_BYTES_IN_MARKER  65533      /* maximum data len of a JPEG marker */
 
190
#define MAX_DATA_BYTES_IN_MARKER  (MAX_BYTES_IN_MARKER - ICC_OVERHEAD_LEN)
 
191
 
 
192
 
 
193
/*
 
194
 * This routine writes the given ICC profile data into a JPEG file.
 
195
 * It *must* be called AFTER calling jpeg_start_compress() and BEFORE
 
196
 * the first call to jpeg_write_scanlines().
 
197
 * (This ordering ensures that the APP2 marker(s) will appear after the
 
198
 * SOI and JFIF or Adobe markers, but before all else.)
 
199
 */
 
200
 
 
201
void
 
202
write_icc_profile (j_compress_ptr cinfo,
 
203
                   const JOCTET *icc_data_ptr,
 
204
                   unsigned int icc_data_len)
 
205
{
 
206
  unsigned int num_markers;     /* total number of markers we'll write */
 
207
  int cur_marker = 1;           /* per spec, counting starts at 1 */
 
208
  unsigned int length;          /* number of bytes to write in this marker */
 
209
 
 
210
  /* Calculate the number of markers we'll need, rounding up of course */
 
211
  num_markers = icc_data_len / MAX_DATA_BYTES_IN_MARKER;
 
212
  if (num_markers * MAX_DATA_BYTES_IN_MARKER != icc_data_len)
 
213
    num_markers++;
 
214
 
 
215
  while (icc_data_len > 0)
 
216
  {
 
217
    /* length of profile to put in this marker */
 
218
    length = icc_data_len;
 
219
    if (length > MAX_DATA_BYTES_IN_MARKER)
 
220
      length = MAX_DATA_BYTES_IN_MARKER;
 
221
    icc_data_len -= length;
 
222
 
 
223
    /* Write the JPEG marker header (APP2 code and marker length) */
 
224
    jpeg_write_m_header(cinfo, ICC_MARKER,
 
225
                        (unsigned int) (length + ICC_OVERHEAD_LEN));
 
226
 
 
227
    /* Write the marker identifying string "ICC_PROFILE" (null-terminated).
 
228
     * We code it in this less-than-transparent way so that the code works
 
229
     * even if the local character set is not ASCII.
 
230
     */
 
231
    jpeg_write_m_byte(cinfo, 0x49);
 
232
    jpeg_write_m_byte(cinfo, 0x43);
 
233
    jpeg_write_m_byte(cinfo, 0x43);
 
234
    jpeg_write_m_byte(cinfo, 0x5F);
 
235
    jpeg_write_m_byte(cinfo, 0x50);
 
236
    jpeg_write_m_byte(cinfo, 0x52);
 
237
    jpeg_write_m_byte(cinfo, 0x4F);
 
238
    jpeg_write_m_byte(cinfo, 0x46);
 
239
    jpeg_write_m_byte(cinfo, 0x49);
 
240
    jpeg_write_m_byte(cinfo, 0x4C);
 
241
    jpeg_write_m_byte(cinfo, 0x45);
 
242
    jpeg_write_m_byte(cinfo, 0x0);
 
243
 
 
244
    /* Add the sequencing info */
 
245
    jpeg_write_m_byte(cinfo, cur_marker);
 
246
    jpeg_write_m_byte(cinfo, (int) num_markers);
 
247
 
 
248
    /* Add the profile data */
 
249
    while (length--)
 
250
    {
 
251
      jpeg_write_m_byte(cinfo, *icc_data_ptr);
 
252
      icc_data_ptr++;
 
253
    }
 
254
    cur_marker++;
 
255
  }
 
256
}
 
257
 
 
258
 
 
259
#if 0
 
260
/*
 
261
 * Prepare for reading an ICC profile
 
262
 */
 
263
 
 
264
void
 
265
setup_read_icc_profile (j_decompress_ptr cinfo)
 
266
{
 
267
  /* Tell the library to keep any APP2 data it may find */
 
268
  jpeg_save_markers(cinfo, ICC_MARKER, 0xFFFF);
 
269
}
 
270
 
 
271
 
 
272
/*
 
273
 * Handy subroutine to test whether a saved marker is an ICC profile marker.
 
274
 */
 
275
 
 
276
static boolean
 
277
marker_is_icc (jpeg_saved_marker_ptr marker)
 
278
{
 
279
  return
 
280
    marker->marker == ICC_MARKER &&
 
281
    marker->data_length >= ICC_OVERHEAD_LEN &&
 
282
    /* verify the identifying string */
 
283
    GETJOCTET(marker->data[0]) == 0x49 &&
 
284
    GETJOCTET(marker->data[1]) == 0x43 &&
 
285
    GETJOCTET(marker->data[2]) == 0x43 &&
 
286
    GETJOCTET(marker->data[3]) == 0x5F &&
 
287
    GETJOCTET(marker->data[4]) == 0x50 &&
 
288
    GETJOCTET(marker->data[5]) == 0x52 &&
 
289
    GETJOCTET(marker->data[6]) == 0x4F &&
 
290
    GETJOCTET(marker->data[7]) == 0x46 &&
 
291
    GETJOCTET(marker->data[8]) == 0x49 &&
 
292
    GETJOCTET(marker->data[9]) == 0x4C &&
 
293
    GETJOCTET(marker->data[10]) == 0x45 &&
 
294
    GETJOCTET(marker->data[11]) == 0x0;
 
295
}
 
296
 
 
297
 
 
298
/*
 
299
 * See if there was an ICC profile in the JPEG file being read;
 
300
 * if so, reassemble and return the profile data.
 
301
 *
 
302
 * TRUE is returned if an ICC profile was found, FALSE if not.
 
303
 * If TRUE is returned, *icc_data_ptr is set to point to the
 
304
 * returned data, and *icc_data_len is set to its length.
 
305
 *
 
306
 * IMPORTANT: the data at **icc_data_ptr has been allocated with malloc()
 
307
 * and must be freed by the caller with free() when the caller no longer
 
308
 * needs it.  (Alternatively, we could write this routine to use the
 
309
 * IJG library's memory allocator, so that the data would be freed implicitly
 
310
 * at jpeg_finish_decompress() time.  But it seems likely that many apps
 
311
 * will prefer to have the data stick around after decompression finishes.)
 
312
 *
 
313
 * NOTE: if the file contains invalid ICC APP2 markers, we just silently
 
314
 * return FALSE.  You might want to issue an error message instead.
 
315
 */
 
316
 
 
317
boolean
 
318
read_icc_profile (j_decompress_ptr cinfo,
 
319
                  JOCTET **icc_data_ptr,
 
320
                  unsigned int *icc_data_len)
 
321
{
 
322
  jpeg_saved_marker_ptr marker;
 
323
  int num_markers = 0;
 
324
  int seq_no;
 
325
  JOCTET *icc_data;
 
326
  unsigned int total_length;
 
327
#define MAX_SEQ_NO  255         /* sufficient since marker numbers are bytes */
 
328
  char marker_present[MAX_SEQ_NO+1];      /* 1 if marker found */
 
329
  unsigned int data_length[MAX_SEQ_NO+1]; /* size of profile data in marker */
 
330
  unsigned int data_offset[MAX_SEQ_NO+1]; /* offset for data in marker */
 
331
 
 
332
  *icc_data_ptr = NULL;         /* avoid confusion if FALSE return */
 
333
  *icc_data_len = 0;
 
334
 
 
335
  /* This first pass over the saved markers discovers whether there are
 
336
   * any ICC markers and verifies the consistency of the marker numbering.
 
337
   */
 
338
 
 
339
  for (seq_no = 1; seq_no <= MAX_SEQ_NO; seq_no++)
 
340
    marker_present[seq_no] = 0;
 
341
 
 
342
  for (marker = cinfo->marker_list; marker != NULL; marker = marker->next)
 
343
  {
 
344
    if (marker_is_icc(marker))
 
345
    {
 
346
      if (num_markers == 0)
 
347
        num_markers = GETJOCTET(marker->data[13]);
 
348
      else if (num_markers != GETJOCTET(marker->data[13]))
 
349
        return FALSE;           /* inconsistent num_markers fields */
 
350
      seq_no = GETJOCTET(marker->data[12]);
 
351
      if (seq_no <= 0 || seq_no > num_markers)
 
352
        return FALSE;           /* bogus sequence number */
 
353
      if (marker_present[seq_no])
 
354
        return FALSE;           /* duplicate sequence numbers */
 
355
      marker_present[seq_no] = 1;
 
356
      data_length[seq_no] = marker->data_length - ICC_OVERHEAD_LEN;
 
357
    }
 
358
  }
 
359
 
 
360
  if (num_markers == 0)
 
361
    return FALSE;
 
362
 
 
363
  /* Check for missing markers, count total space needed,
 
364
   * compute offset of each marker's part of the data.
 
365
   */
 
366
 
 
367
  total_length = 0;
 
368
  for (seq_no = 1; seq_no <= num_markers; seq_no++)
 
369
  {
 
370
    if (marker_present[seq_no] == 0)
 
371
      return FALSE;             /* missing sequence number */
 
372
    data_offset[seq_no] = total_length;
 
373
    total_length += data_length[seq_no];
 
374
  }
 
375
 
 
376
  if (total_length <= 0)
 
377
    return FALSE;               /* found only empty markers? */
 
378
 
 
379
  /* Allocate space for assembled data */
 
380
  icc_data = (JOCTET *) malloc(total_length * sizeof(JOCTET));
 
381
  if (icc_data == NULL)
 
382
    return FALSE;               /* oops, out of memory */
 
383
 
 
384
  /* and fill it in */
 
385
  for (marker = cinfo->marker_list; marker != NULL; marker = marker->next)
 
386
  {
 
387
    if (marker_is_icc(marker))
 
388
    {
 
389
      JOCTET FAR *src_ptr;
 
390
      JOCTET *dst_ptr;
 
391
      unsigned int length;
 
392
      seq_no = GETJOCTET(marker->data[12]);
 
393
      dst_ptr = icc_data + data_offset[seq_no];
 
394
      src_ptr = marker->data + ICC_OVERHEAD_LEN;
 
395
      length = data_length[seq_no];
 
396
      while (length--)
 
397
      {
 
398
        *dst_ptr++ = *src_ptr++;
 
399
      }
 
400
    }
 
401
  }
 
402
 
 
403
  *icc_data_ptr = icc_data;
 
404
  *icc_data_len = total_length;
 
405
 
 
406
  return TRUE;
 
407
}
 
408
#endif
 
409
#undef ICC_MARKER
 
410
#undef ICC_OVERHEAD_LEN
 
411
#undef MAX_BYTES_IN_MARKER
 
412
#undef MAX_DATA_BYTES_IN_MARKER
 
413
#undef MAX_SEQ_NO
 
414
 
 
415
 
 
416
int dt_imageio_jpeg_write_with_icc_profile(const char *filename, const uint8_t *in, const int width, const int height, const int quality, void *exif, int exif_len, int imgid)
 
417
{
 
418
  struct dt_imageio_jpeg_error_mgr jerr;
 
419
  dt_imageio_jpeg_t jpg;
 
420
 
 
421
  jpg.cinfo.err = jpeg_std_error(&jerr.pub);
 
422
  jerr.pub.error_exit = dt_imageio_jpeg_error_exit;
 
423
  if (setjmp(jerr.setjmp_buffer))
 
424
  {
 
425
    jpeg_destroy_compress(&(jpg.cinfo));
 
426
    return 1;
 
427
  }
 
428
  jpeg_create_compress(&(jpg.cinfo));
 
429
  FILE *f = fopen(filename, "wb");
 
430
  if(!f) return 1;
 
431
  jpeg_stdio_dest(&(jpg.cinfo), f);
 
432
 
 
433
  jpg.cinfo.image_width = width;
 
434
  jpg.cinfo.image_height = height;
 
435
  jpg.cinfo.input_components = 3;
 
436
  jpg.cinfo.in_color_space = JCS_RGB;
 
437
  jpeg_set_defaults(&(jpg.cinfo));
 
438
  jpeg_set_quality(&(jpg.cinfo), quality, TRUE);
 
439
  if(quality > 90) jpg.cinfo.comp_info[0].v_samp_factor = 1;
 
440
  if(quality > 92) jpg.cinfo.comp_info[0].h_samp_factor = 1;
 
441
  jpeg_start_compress(&(jpg.cinfo), TRUE);
 
442
 
 
443
  if(imgid > 0)
 
444
  {
 
445
    cmsHPROFILE out_profile = dt_colorspaces_create_output_profile(imgid);
 
446
    uint32_t len = 0;
 
447
    cmsSaveProfileToMem(out_profile, 0, &len);
 
448
    if (len > 0)
 
449
    {
 
450
      unsigned char buf[len];
 
451
      cmsSaveProfileToMem(out_profile, buf, &len);
 
452
      write_icc_profile(&(jpg.cinfo), buf, len);
 
453
    }
 
454
    dt_colorspaces_cleanup_profile(out_profile);
 
455
  }
 
456
 
 
457
  if(exif && exif_len > 0 && exif_len < 65534)
 
458
    jpeg_write_marker(&(jpg.cinfo), JPEG_APP0+1, exif, exif_len);
 
459
 
 
460
  uint8_t row[3*width];
 
461
  const uint8_t *buf;
 
462
  while(jpg.cinfo.next_scanline < jpg.cinfo.image_height)
 
463
  {
 
464
    JSAMPROW tmp[1];
 
465
    buf = in + jpg.cinfo.next_scanline * jpg.cinfo.image_width * 4;
 
466
    for(int i=0; i<width; i++) for(int k=0; k<3; k++) row[3*i+k] = buf[4*i+k];
 
467
    tmp[0] = row;
 
468
    jpeg_write_scanlines(&(jpg.cinfo), tmp, 1);
 
469
  }
 
470
  jpeg_finish_compress (&(jpg.cinfo));
 
471
  jpeg_destroy_compress(&(jpg.cinfo));
 
472
  fclose(f);
 
473
  return 0;
 
474
}
 
475
 
 
476
int dt_imageio_jpeg_write(const char *filename, const uint8_t *in, const int width, const int height, const int quality, void *exif, int exif_len)
 
477
{
 
478
  return dt_imageio_jpeg_write_with_icc_profile(filename, in, width, height, quality, exif, exif_len, -1);
 
479
}
 
480
 
 
481
int dt_imageio_jpeg_read_header(const char *filename, dt_imageio_jpeg_t *jpg)
 
482
{
 
483
  jpg->f = fopen(filename, "rb");
 
484
  if(!jpg->f) return 1;
 
485
 
 
486
  struct dt_imageio_jpeg_error_mgr jerr;
 
487
  jpg->dinfo.err = jpeg_std_error(&jerr.pub);
 
488
  jerr.pub.error_exit = dt_imageio_jpeg_error_exit;
 
489
  if (setjmp(jerr.setjmp_buffer))
 
490
  {
 
491
    jpeg_destroy_decompress(&(jpg->dinfo));
 
492
    fclose(jpg->f);
 
493
    return 1;
 
494
  }
 
495
  jpeg_create_decompress(&(jpg->dinfo));
 
496
  jpeg_stdio_src(&(jpg->dinfo), jpg->f);
 
497
  // jpg->dinfo.buffered_image = TRUE;
 
498
  jpeg_read_header(&(jpg->dinfo), TRUE);
 
499
  jpg->width  = jpg->dinfo.image_width;
 
500
  jpg->height = jpg->dinfo.image_height;
 
501
  return 0;
 
502
}
 
503
 
 
504
int dt_imageio_jpeg_read(dt_imageio_jpeg_t *jpg, uint8_t *out)
 
505
{
 
506
  struct dt_imageio_jpeg_error_mgr jerr;
 
507
  jpg->dinfo.err = jpeg_std_error(&jerr.pub);
 
508
  if (setjmp(jerr.setjmp_buffer))
 
509
  {
 
510
    jpeg_destroy_decompress(&(jpg->dinfo));
 
511
    fclose(jpg->f);
 
512
    return 1;
 
513
  }
 
514
  (void)jpeg_start_decompress(&(jpg->dinfo));
 
515
  JSAMPROW row_pointer[1];
 
516
  row_pointer[0] = (uint8_t *)malloc(jpg->dinfo.output_width*jpg->dinfo.num_components);
 
517
  uint8_t *tmp = out;
 
518
  while(jpg->dinfo.output_scanline < jpg->dinfo.image_height)
 
519
  {
 
520
    if(jpeg_read_scanlines(&(jpg->dinfo), row_pointer, 1) != 1)
 
521
    {
 
522
      jpeg_destroy_decompress(&(jpg->dinfo));
 
523
      free(row_pointer[0]);
 
524
      fclose(jpg->f);
 
525
      return 1;
 
526
    }
 
527
    if(jpg->dinfo.num_components < 3)
 
528
      for(int i=0; i<jpg->dinfo.image_width; i++) for(int k=0; k<3; k++)
 
529
          tmp[4*i+k] = row_pointer[0][jpg->dinfo.num_components*i+0];
 
530
    else
 
531
      for(int i=0; i<jpg->dinfo.image_width; i++) for(int k=0; k<3; k++)
 
532
          tmp[4*i+k] = row_pointer[0][3*i+k];
 
533
    tmp += 4*jpg->width;
 
534
  }
 
535
  // (void)jpeg_finish_decompress(&(jpg->dinfo));
 
536
  jpeg_destroy_decompress(&(jpg->dinfo));
 
537
  free(row_pointer[0]);
 
538
  fclose(jpg->f);
 
539
  return 0;
 
540
}
 
541
 
 
542
 
 
543