Cleanup main.h header
[geeqie.git] / src / image-load-jpeg.cc
1 /*
2  * Copyright (C) 1999 Michael Zucchi
3  * Copyright (C) 1999 The Free Software Foundation
4  * Copyright (C) 2004 John Ellis
5  * Copyright (C) 2008 - 2016 The Geeqie Team
6  *
7  * Authors: Michael Zucchi <zucchi@zedzone.mmc.com.au>
8  *          Federico Mena-Quintero <federico@gimp.org>
9  *          Michael Fulbright <drmike@redhat.com>
10  *          Vladimir Nadvornik
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License along
23  * with this program; if not, write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25  */
26
27 /** This is a Will Not Fix */
28 #pragma GCC diagnostic ignored "-Wclobbered"
29
30 #include <config.h>
31
32 #ifdef HAVE_JPEG
33
34 #include "image-load-jpeg.h"
35
36 #include <csetjmp>
37 #include <cstdio> // for FILE and size_t in jpeglib.h
38
39 #include <jerror.h>
40 #include <jpeglib.h>
41
42 #include "debug.h"
43 #include "image-load.h"
44 #include "intl.h"
45 #include "jpeg-parser.h"
46 #include "typedefs.h"
47
48 struct ImageLoaderJpeg {
49         ImageLoaderBackendCbAreaUpdated area_updated_cb;
50         ImageLoaderBackendCbSize size_cb;
51         ImageLoaderBackendCbAreaPrepared area_prepared_cb;
52
53         gpointer data;
54
55         GdkPixbuf *pixbuf;
56         guint requested_width;
57         guint requested_height;
58
59         gboolean abort;
60         gboolean stereo;
61
62 };
63
64 /* error handler data */
65 struct error_handler_data {
66         struct jpeg_error_mgr pub;
67         sigjmp_buf setjmp_buffer;
68         GError **error;
69 };
70
71 /* explode gray image data from jpeg library into rgb components in pixbuf */
72 static void
73 explode_gray_into_buf (struct jpeg_decompress_struct *cinfo,
74                        guchar **lines)
75 {
76         gint i;
77         gint j;
78         guint w;
79
80         g_return_if_fail (cinfo != nullptr);
81         g_return_if_fail (cinfo->output_components == 1);
82         g_return_if_fail (cinfo->out_color_space == JCS_GRAYSCALE);
83
84         /* Expand grey->colour.  Expand from the end of the
85          * memory down, so we can use the same buffer.
86          */
87         w = cinfo->output_width;
88         for (i = cinfo->rec_outbuf_height - 1; i >= 0; i--) {
89                 guchar *from;
90                 guchar *to;
91
92                 from = lines[i] + w - 1;
93                 to = lines[i] + (w - 1) * 3;
94                 for (j = w - 1; j >= 0; j--) {
95                         to[0] = from[0];
96                         to[1] = from[0];
97                         to[2] = from[0];
98                         to -= 3;
99                         from--;
100                 }
101         }
102 }
103
104
105 static void
106 convert_cmyk_to_rgb (struct jpeg_decompress_struct *cinfo,
107                      guchar **lines)
108 {
109         gint i;
110         guint j;
111
112         g_return_if_fail (cinfo != nullptr);
113         g_return_if_fail (cinfo->output_components == 4);
114         g_return_if_fail (cinfo->out_color_space == JCS_CMYK);
115
116         for (i = cinfo->rec_outbuf_height - 1; i >= 0; i--) {
117                 guchar *p;
118
119                 p = lines[i];
120                 for (j = 0; j < cinfo->output_width; j++) {
121                         int c;
122                         int m;
123                         int y;
124                         int k;
125                         c = p[0];
126                         m = p[1];
127                         y = p[2];
128                         k = p[3];
129                         if (cinfo->saw_Adobe_marker) {
130                                 p[0] = k*c / 255;
131                                 p[1] = k*m / 255;
132                                 p[2] = k*y / 255;
133                         }
134                         else {
135                                 p[0] = (255 - k)*(255 - c) / 255;
136                                 p[1] = (255 - k)*(255 - m) / 255;
137                                 p[2] = (255 - k)*(255 - y) / 255;
138                         }
139                         p[3] = 255;
140                         p += 4;
141                 }
142         }
143 }
144
145
146 static gpointer image_loader_jpeg_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data)
147 {
148         auto loader = g_new0(ImageLoaderJpeg, 1);
149
150         loader->area_updated_cb = area_updated_cb;
151         loader->size_cb = size_cb;
152         loader->area_prepared_cb = area_prepared_cb;
153         loader->data = data;
154         return loader;
155 }
156
157 static void
158 fatal_error_handler (j_common_ptr cinfo)
159 {
160         struct error_handler_data *errmgr;
161         char buffer[JMSG_LENGTH_MAX];
162
163         errmgr = reinterpret_cast<struct error_handler_data *>(cinfo->err);
164
165         /* Create the message */
166         (* cinfo->err->format_message) (cinfo, buffer);
167
168         /* broken check for *error == NULL for robustness against
169          * crappy JPEG library
170          */
171         if (errmgr->error && *errmgr->error == nullptr) {
172                 g_set_error (errmgr->error,
173                              GDK_PIXBUF_ERROR,
174                              cinfo->err->msg_code == JERR_OUT_OF_MEMORY
175                              ? GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY
176                              : GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
177                              _("Error interpreting JPEG image file (%s)"),
178                              buffer);
179         }
180
181         siglongjmp (errmgr->setjmp_buffer, 1);
182
183         g_assert_not_reached ();
184 }
185
186 static void
187 output_message_handler (j_common_ptr)
188 {
189   /* This method keeps libjpeg from dumping crap to stderr */
190
191   /* do nothing */
192 }
193
194
195 void image_loader_jpeg_read_scanline(struct jpeg_decompress_struct *cinfo, guchar **dptr, guint rowstride)
196 {
197         guchar *lines[4];
198         guchar **lptr;
199         gint i;
200
201         lptr = lines;
202         for (i = 0; i < cinfo->rec_outbuf_height; i++)
203                 {
204                 *lptr++ = *dptr;
205                 *dptr += rowstride;
206                 }
207
208         jpeg_read_scanlines (cinfo, lines, cinfo->rec_outbuf_height);
209
210         switch (cinfo->out_color_space)
211                 {
212                     case JCS_GRAYSCALE:
213                       explode_gray_into_buf (cinfo, lines);
214                       break;
215                     case JCS_RGB:
216                       /* do nothing */
217                       break;
218                     case JCS_CMYK:
219                       convert_cmyk_to_rgb (cinfo, lines);
220                       break;
221                     default:
222                       break;
223                 }
224 }
225
226
227 static void init_source (j_decompress_ptr) {}
228 static boolean fill_input_buffer (j_decompress_ptr cinfo)
229 {
230         ERREXIT(cinfo, JERR_INPUT_EMPTY);
231         return TRUE;
232 }
233 static void skip_input_data (j_decompress_ptr cinfo, long num_bytes)
234 {
235         auto src = static_cast<struct jpeg_source_mgr*>(cinfo->src);
236
237         if (static_cast<gulong>(num_bytes) > src->bytes_in_buffer)
238                 {
239                 ERREXIT(cinfo, JERR_INPUT_EOF);
240                 }
241         else if (num_bytes > 0)
242                 {
243                 src->next_input_byte += static_cast<size_t>(num_bytes);
244                 src->bytes_in_buffer -= static_cast<size_t>(num_bytes);
245                 }
246 }
247 static void term_source (j_decompress_ptr) {}
248 static void set_mem_src (j_decompress_ptr cinfo, void* buffer, long nbytes)
249 {
250         struct jpeg_source_mgr* src;
251
252         if (cinfo->src == nullptr)
253                 {   /* first time for this JPEG object? */
254                 cinfo->src = static_cast<struct jpeg_source_mgr *>((*cinfo->mem->alloc_small) (
255                                         reinterpret_cast<j_common_ptr>(cinfo), JPOOL_PERMANENT,
256                                         sizeof(struct jpeg_source_mgr)));
257                 }
258
259         src = static_cast<struct jpeg_source_mgr*>(cinfo->src);
260         src->init_source = init_source;
261         src->fill_input_buffer = fill_input_buffer;
262         src->skip_input_data = skip_input_data;
263         src->resync_to_restart = jpeg_resync_to_restart; /* use default method */
264         src->term_source = term_source;
265         src->bytes_in_buffer = nbytes;
266         src->next_input_byte = static_cast<JOCTET*>(buffer);
267 }
268
269
270 static gboolean image_loader_jpeg_load (gpointer loader, const guchar *buf, gsize count, GError **error)
271 {
272         auto lj = static_cast<ImageLoaderJpeg *>(loader);
273         struct jpeg_decompress_struct cinfo;
274         struct jpeg_decompress_struct cinfo2;
275         guchar *dptr;
276         guchar *dptr2;
277         guint rowstride;
278         guchar *stereo_buf2 = nullptr;
279         guint stereo_length = 0;
280
281         struct error_handler_data jerr;
282
283         lj->stereo = FALSE;
284
285         MPOData *mpo = jpeg_get_mpo_data(buf, count);
286         if (mpo && mpo->num_images > 1)
287                 {
288                 guint i;
289                 gint idx1 = -1;
290                 gint idx2 = -1;
291                 guint num2 = 1;
292
293                 for (i = 0; i < mpo->num_images; i++)
294                         {
295                         if (mpo->images[i].type_code == 0x20002)
296                                 {
297                                 if (mpo->images[i].MPIndividualNum == 1)
298                                         {
299                                         idx1 = i;
300                                         }
301                                 else if (mpo->images[i].MPIndividualNum > num2)
302                                         {
303                                         idx2 = i;
304                                         num2 = mpo->images[i].MPIndividualNum;
305                                         }
306                                 }
307                         }
308
309                 if (idx1 >= 0 && idx2 >= 0)
310                         {
311                         lj->stereo = TRUE;
312                         stereo_buf2 = const_cast<unsigned char *>(buf) + mpo->images[idx2].offset;
313                         stereo_length = mpo->images[idx2].length;
314                         buf = const_cast<unsigned char *>(buf) + mpo->images[idx1].offset;
315                         count = mpo->images[idx1].length;
316                         }
317                 }
318         jpeg_mpo_data_free(mpo);
319
320         /* setup error handler */
321         cinfo.err = jpeg_std_error (&jerr.pub);
322         if (lj->stereo) cinfo2.err = jpeg_std_error (&jerr.pub);
323         jerr.pub.error_exit = fatal_error_handler;
324         jerr.pub.output_message = output_message_handler;
325
326         jerr.error = error;
327
328
329         if (sigsetjmp(jerr.setjmp_buffer, 0))
330                 {
331                 /* If we get here, the JPEG code has signaled an error.
332                  * We need to clean up the JPEG object, close the input file, and return.
333                 */
334                 jpeg_destroy_decompress(&cinfo);
335                 if (lj->stereo) jpeg_destroy_decompress(&cinfo2);
336                 return FALSE;
337                 }
338
339         jpeg_create_decompress(&cinfo);
340
341         set_mem_src(&cinfo, const_cast<unsigned char *>(buf), count);
342
343
344         jpeg_read_header(&cinfo, TRUE);
345
346         if (lj->stereo)
347                 {
348                 jpeg_create_decompress(&cinfo2);
349                 set_mem_src(&cinfo2, stereo_buf2, stereo_length);
350                 jpeg_read_header(&cinfo2, TRUE);
351
352                 if (cinfo.image_width != cinfo2.image_width ||
353                     cinfo.image_height != cinfo2.image_height)
354                         {
355                         DEBUG_1("stereo data with different size");
356                         jpeg_destroy_decompress(&cinfo2);
357                         lj->stereo = FALSE;
358                         }
359                 }
360
361
362
363         lj->requested_width = lj->stereo ? cinfo.image_width * 2: cinfo.image_width;
364         lj->requested_height = cinfo.image_height;
365         lj->size_cb(loader, lj->requested_width, lj->requested_height, lj->data);
366
367         cinfo.scale_num = 1;
368         for (cinfo.scale_denom = 2; cinfo.scale_denom <= 8; cinfo.scale_denom *= 2) {
369                 jpeg_calc_output_dimensions(&cinfo);
370                 if (cinfo.output_width < (lj->stereo ? lj->requested_width / 2 : lj->requested_width) || cinfo.output_height < lj->requested_height) {
371                         cinfo.scale_denom /= 2;
372                         break;
373                 }
374         }
375         jpeg_calc_output_dimensions(&cinfo);
376         if (lj->stereo)
377                 {
378                 cinfo2.scale_num = cinfo.scale_num;
379                 cinfo2.scale_denom = cinfo.scale_denom;
380                 jpeg_calc_output_dimensions(&cinfo2);
381                 jpeg_start_decompress(&cinfo2);
382                 }
383
384
385         jpeg_start_decompress(&cinfo);
386
387
388         if (lj->stereo)
389                 {
390                 if (cinfo.output_width != cinfo2.output_width ||
391                     cinfo.output_height != cinfo2.output_height ||
392                     cinfo.out_color_components != cinfo2.out_color_components)
393                         {
394                         DEBUG_1("stereo data with different output size");
395                         jpeg_destroy_decompress(&cinfo2);
396                         lj->stereo = FALSE;
397                         }
398                 }
399
400
401         lj->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
402                                      cinfo.out_color_components == 4 ? TRUE : FALSE,
403                                      8, lj->stereo ? cinfo.output_width * 2: cinfo.output_width, cinfo.output_height);
404
405         if (!lj->pixbuf)
406                 {
407                 jpeg_destroy_decompress (&cinfo);
408                 if (lj->stereo) jpeg_destroy_decompress (&cinfo2);
409                 return 0;
410                 }
411         if (lj->stereo) g_object_set_data(G_OBJECT(lj->pixbuf), "stereo_data", GINT_TO_POINTER(STEREO_PIXBUF_CROSS));
412         lj->area_prepared_cb(loader, lj->data);
413
414         rowstride = gdk_pixbuf_get_rowstride(lj->pixbuf);
415         dptr = gdk_pixbuf_get_pixels(lj->pixbuf);
416         dptr2 = gdk_pixbuf_get_pixels(lj->pixbuf) + ((cinfo.out_color_components == 4) ? 4 * cinfo.output_width : 3 * cinfo.output_width);
417
418
419         while (cinfo.output_scanline < cinfo.output_height && !lj->abort)
420                 {
421                 guint scanline = cinfo.output_scanline;
422                 image_loader_jpeg_read_scanline(&cinfo, &dptr, rowstride);
423                 lj->area_updated_cb(loader, 0, scanline, cinfo.output_width, cinfo.rec_outbuf_height, lj->data);
424                 if (lj->stereo)
425                         {
426                         guint scanline = cinfo2.output_scanline;
427                         image_loader_jpeg_read_scanline(&cinfo2, &dptr2, rowstride);
428                         lj->area_updated_cb(loader, cinfo.output_width, scanline, cinfo2.output_width, cinfo2.rec_outbuf_height, lj->data);
429                         }
430                 }
431
432         jpeg_finish_decompress(&cinfo);
433         jpeg_destroy_decompress(&cinfo);
434         if (lj->stereo)
435                 {
436                 jpeg_finish_decompress(&cinfo);
437                 jpeg_destroy_decompress(&cinfo);
438                 }
439
440         return TRUE;
441 }
442
443 static void image_loader_jpeg_set_size(gpointer loader, int width, int height)
444 {
445         auto lj = static_cast<ImageLoaderJpeg *>(loader);
446         lj->requested_width = width;
447         lj->requested_height = height;
448 }
449
450 static GdkPixbuf* image_loader_jpeg_get_pixbuf(gpointer loader)
451 {
452         auto lj = static_cast<ImageLoaderJpeg *>(loader);
453         return lj->pixbuf;
454 }
455
456 static gchar* image_loader_jpeg_get_format_name(gpointer)
457 {
458         return g_strdup("jpeg");
459 }
460 static gchar** image_loader_jpeg_get_format_mime_types(gpointer)
461 {
462         static const gchar *mime[] = {"image/jpeg", nullptr};
463         return g_strdupv(const_cast<gchar **>(mime));
464 }
465
466 static gboolean image_loader_jpeg_close(gpointer, GError **)
467 {
468         return TRUE;
469 }
470
471 static void image_loader_jpeg_abort(gpointer loader)
472 {
473         auto lj = static_cast<ImageLoaderJpeg *>(loader);
474         lj->abort = TRUE;
475 }
476
477 static void image_loader_jpeg_free(gpointer loader)
478 {
479         auto lj = static_cast<ImageLoaderJpeg *>(loader);
480         if (lj->pixbuf) g_object_unref(lj->pixbuf);
481         g_free(lj);
482 }
483
484
485 void image_loader_backend_set_jpeg(ImageLoaderBackend *funcs)
486 {
487         funcs->loader_new = image_loader_jpeg_new;
488         funcs->set_size = image_loader_jpeg_set_size;
489         funcs->load = image_loader_jpeg_load;
490         funcs->write = nullptr;
491         funcs->get_pixbuf = image_loader_jpeg_get_pixbuf;
492         funcs->close = image_loader_jpeg_close;
493         funcs->abort = image_loader_jpeg_abort;
494         funcs->free = image_loader_jpeg_free;
495
496         funcs->get_format_name = image_loader_jpeg_get_format_name;
497         funcs->get_format_mime_types = image_loader_jpeg_get_format_mime_types;
498 }
499
500
501 #endif
502
503 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */