jpeg.c 87.5 KB
Newer Older
Elliot Lee's avatar
Elliot Lee committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* The GIMP -- an image manipulation program
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
17
18
19
20
21
22
23
24
25
26
 */

/* JPEG loading and saving file filter for the GIMP
 *  -Peter Mattis
 *
 * This filter is heavily based upon the "example.c" file in libjpeg.
 * In fact most of the loading and saving code was simply cut-and-pasted
 *  from that file. The filter, therefore, also uses libjpeg.
 */

27
28
29
30
31
32
33
34
35
36
37
/* 11-JAN-99 - Added support for JPEG comments and Progressive saves.
 *  -pete whiting <pwhiting@sprint.net>
 *
 * Comments of size up to 32k can be stored in the header of jpeg
 * files.  (They are not compressed.)  The JPEG specs and libraries
 * support the storing of multiple comments.  The behavior of this
 * code is to merge all comments in a loading image into a single
 * comment (putting \n between each) and attach that string as a
 * parasite - gimp-comment - to the image.  When saving, the image is
 * checked to see if it has the gimp-comment parasite - if so, that is
 * used as the default comment in the save dialog.  Further, the other
38
 * jpeg parameters (quality, smoothing, compression and progressive)
39
40
 * are attached to the image as a parasite.  This allows the
 * parameters to remain consistent between saves.  I was not able to
41
 * figure out how to determine the quality, smoothing or compression
42
43
44
45
46
47
 * values of an image as it is being loaded, but the code is there to
 * support it if anyone knows how.  Progressive mode is a method of
 * saving the image such that as a browser (or other app supporting
 * progressive loads - gimp doesn't) loads the image it first gets a
 * low res version displayed and then the image is progressively
 * enhanced until you get the final version.  It doesn't add any size
48
49
50
 * to the image (actually it often results in smaller file size) - the
 * only draw backs are that progressive jpegs are not supported by some
 * older viewers/browsers, and some might find it annoying.
51
52
 */

53
/*
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
 * 21-AUG-99 - Added support for JPEG previews, subsampling,
 *             non-baseline JPEGs, restart markers and DCT method choice
 * - Steinar H. Gunderson <sgunderson@bigfoot.com>
 *
 * A small preview appears and changes according to the changes to the
 * compression options. The image itself works as a much bigger preview.
 * For slower machines, the save operation (not the load operation) is
 * done in the background, with a standard GTK+ idle loop, which turned
 * out to be the most portable way. Win32 porters shouldn't have much
 * difficulty porting my changes (at least I hope so...).
 *
 * Subsampling is a pretty obscure feature, but I thought it might be nice
 * to have it in anyway, for people to play with :-) Does anybody have
 * any better suggestions than the ones I've put in the menu? (See wizard.doc
 * from the libjpeg distribution for a tiny bit of information on subsampling.)
 *
 * A baseline JPEG is often larger and/or of worse quality than a non-baseline
 * one (especially at low quality settings), but all decoders are guaranteed
 * to read baseline JPEGs (I think). Not all will read a non-baseline one.
 *
 * Restart markers are useful if you are transmitting the image over an
 * unreliable network. If a file gets corrupted, it will only be corrupted
 * up to the next restart marker. Of course, if there are no restart markers,
 * the rest of the image will be corrupted. Restart markers take up extra
 * space. The libjpeg developers recommend a restart every 1 row for
 * transmitting images over unreliable networks, such as Usenet.
 *
 * The DCT method is said by the libjpeg docs to _only_ influence quality vs.
 * speed, and nothing else. However, I've found that there _are_ size
 * differences. Fast integer, on the other hand, is faster than integer,
 * which in turn is faster than FP. According to the libjpeg docs (and I
 * believe it's true), FP has only a theoretical advantage in quality, and
 * will be slower than the two other methods, unless you're blessed with
 * very a fast FPU. (In addition, images might not be identical on
 * different types of FP hardware.)
 *
 * ...and thus ends my additions to the JPEG plug-in. I hope. *sigh* :-)
 */

93
/*
94
95
96
97
98
99
100
101
102
103
104
105
 * 21-AUG-99 - Bunch O' Fixes.
 * - Adam D. Moss <adam@gimp.org>
 *
 * We now correctly create an alpha-padded layer for our preview --
 * having a non-background non-alpha layer is a no-no in GIMP.
 *
 * I've also tweaked the GIMP undo API a little and changed the JPEG
 * plugin to use gimp_image_{freeze,thaw}_undo so that it doesn't store
 * up a whole load of superfluous tile data every time the preview is
 * changed.
 */

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/*
 * 22-DEC-99 - volatiles added
 * - Austin Donnelly <austin@gimp.org>
 *
 * When gcc complains a variable may be clobbered by a longjmp or
 * vfork, it means the following: setjmp() was called by the JPEG
 * library for error recovery purposes, but gcc is keeping some
 * variables in registers without updating the memory locations on the
 * stack consistently.  If JPEG error recovery is every invoked, the
 * values of these variable will be inconsistent.  This is almost
 * always a bug, but not one that's commonly seen unless JPEG recovery
 * code is exercised frequently.  The correct solution is to tell gcc
 * to keep the stack version of the affected variables up to date, by
 * using the "volatile" keyword.   Here endeth the lesson.
 */

122
123
124
125
126
127
128
129
/*
 * 4-SEP-01 - remove the use of GtkText
 * - DindinX <David@dindinx.org>
 *
 * The new version of GTK+ does not support GtkText anymore.
 * I've just replaced the one used for the image comment by
 * a GtkTextView/GtkTextBuffer couple;
 */
130

131
132
133
134
/*
 * 22-JUN-03 - add support for keeping EXIF information
 * - Dave Neary <bolsh@gimp.org>
 *
135
 * This is little more than a modified version fo a patch from the
136
 * libexif owner (Lutz Muller) which attaches exif information to
137
138
 * a GimpImage, and if there is infoprmation available at save
 * time, writes it out. No modification of the exif data is
139
140
141
 * currently possible.
 */

142
143
144
145
146
147
148
149
/*
 * 15-NOV-04 - add support for EXIF JPEG thumbnail reading and writing
 * - S. Mukund <muks@mukund.org>
 *
 * Digital cameras store a TIFF APP1 marker that contains various
 * parameters of the shot along with a thumbnail image.
 */

150
151
152
153
154
155
/*
 * 14-JAN-05 - avoid to write more than 65533 bytes of EXIF marker length
 * - Nils Philippsen <nphilipp@redhat.com>
 *
 * When writing thumbnails with high quality settings, EXIF marker length could
 * get more than 65533 (sanity checking in libjpeg). Gradually decrease
156
 * thumbnail quality (in steps of 5) until it fits.
157
158
 */

Sven Neumann's avatar
Sven Neumann committed
159
#include "config.h"   /* configure cares about HAVE_PROGRESSIVE_JPEG */
Tor Lillqvist's avatar
Tor Lillqvist committed
160

Sven Neumann's avatar
Sven Neumann committed
161
#include <glib.h>     /* We want glib.h first because of some
Sven Neumann's avatar
Sven Neumann committed
162
163
                       * pretty obscure Win32 compilation issues.
                       */
164
#include <errno.h>
Elliot Lee's avatar
Elliot Lee committed
165
#include <setjmp.h>
166
#include <signal.h>
Elliot Lee's avatar
Elliot Lee committed
167
168
169
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
170
#include <sys/types.h>
171
#include <sys/stat.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
172
#ifdef HAVE_UNISTD_H
173
#include <unistd.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
174
#endif
Elliot Lee's avatar
Elliot Lee committed
175
#include <jpeglib.h>
176
#include <jerror.h>
177

178
179
#ifdef HAVE_EXIF
#include <libexif/exif-data.h>
180
181

#define MARKER_CODE_EXIF 0xE1
182
183
#endif /* HAVE_EXIF */

Michael Natterer's avatar
Michael Natterer committed
184
185
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
186

187
188
#include "libgimp/stdplugins-intl.h"

Sven Neumann's avatar
Sven Neumann committed
189
#define SCALE_WIDTH         125
Elliot Lee's avatar
Elliot Lee committed
190

191
192
/* if you are not compiling this from inside the gimp tree, you have to  */
/* take care yourself if your JPEG library supports progressive mode     */
193
/* #undef HAVE_PROGRESSIVE_JPEG   if your library doesn't support it     */
194
195
/* #define HAVE_PROGRESSIVE_JPEG  if your library knows how to handle it */

196
/* See bugs #63610 and #61088 for a discussion about the quality settings */
197
#define DEFAULT_QUALITY     85.0
Sven Neumann's avatar
Sven Neumann committed
198
#define DEFAULT_SMOOTHING   0.0
199
200
201
#define DEFAULT_OPTIMIZE    TRUE
#define DEFAULT_PROGRESSIVE FALSE
#define DEFAULT_BASELINE    TRUE
Sven Neumann's avatar
Sven Neumann committed
202
203
204
#define DEFAULT_SUBSMP      0
#define DEFAULT_RESTART     0
#define DEFAULT_DCT         0
205
206
#define DEFAULT_PREVIEW     FALSE
#define DEFAULT_EXIF        TRUE
207
#define DEFAULT_THUMBNAIL   FALSE
208
209

/* sg - these should not be global... */
210
211
212
213
214
215
216
217
218
static  gint32 volatile  image_ID_global       = -1;
static  gint32           orig_image_ID_global  = -1;
static  gint32           drawable_ID_global    = -1;
static  gint32           layer_ID_global       = -1;
static  GtkWidget       *preview_size          = NULL;
static  GimpDrawable    *drawable_global       = NULL;
static  gboolean         undo_touched          = FALSE;
static  gint32           display_ID            = 0;

219

Elliot Lee's avatar
Elliot Lee committed
220
221
typedef struct
{
222
223
224
225
226
227
228
229
230
231
  gdouble  quality;
  gdouble  smoothing;
  gboolean optimize;
  gboolean progressive;
  gboolean baseline;
  gint     subsmp;
  gint     restart;
  gint     dct;
  gboolean preview;
  gboolean save_exif;
232
  gboolean save_thumbnail;
Elliot Lee's avatar
Elliot Lee committed
233
234
} JpegSaveVals;

235
typedef struct
236
237
{
  struct jpeg_compress_struct cinfo;
238
  struct jpeg_error_mgr jerr;
239
240
  gint          tile_height;
  FILE         *outfile;
241
  gboolean      has_alpha;
242
243
244
245
  gint          rowstride;
  guchar       *temp;
  guchar       *data;
  guchar       *src;
Sven Neumann's avatar
Sven Neumann committed
246
247
  GimpDrawable *drawable;
  GimpPixelRgn  pixel_rgn;
248
  const gchar  *file_name;
Sven Neumann's avatar
Sven Neumann committed
249
250
251
252
  gboolean      abort_me;
} PreviewPersistent;

static gboolean *abort_me = NULL;
Sven Neumann's avatar
Sven Neumann committed
253

254

Elliot Lee's avatar
Elliot Lee committed
255
256
/* Declare local functions.
 */
Sven Neumann's avatar
Sven Neumann committed
257
258
259
260
261
262
263
264
265
static void      query               (void);
static void      run                 (const gchar      *name,
                                      gint              nparams,
                                      const GimpParam  *param,
                                      gint             *nreturn_vals,
                                      GimpParam       **return_vals);
static gint32    load_image          (const gchar      *filename,
                                      GimpRunMode       runmode,
                                      gboolean          preview);
266
267
268
269
270
271
272
273
#ifdef HAVE_EXIF

static gint32    load_thumbnail_image(const gchar      *filename,
                                      gint             *width,
                                      gint             *height);

static gint      create_thumbnail    (gint32            image_ID,
                                      gint32            drawable_ID,
274
                                      gdouble           quality,
275
276
277
278
                                      gchar           **thumbnail_buffer);

#endif /* HAVE_EXIF */

Sven Neumann's avatar
Sven Neumann committed
279
280
281
282
283
284
285
286
287
288
289
290
291
static gboolean  save_image          (const gchar      *filename,
                                      gint32            image_ID,
                                      gint32            drawable_ID,
                                      gint32            orig_image_ID,
                                      gboolean          preview);

static gboolean  save_dialog         (void);

static void      make_preview        (void);
static void      destroy_preview     (void);

static void      save_restart_update (GtkAdjustment    *adjustment,
                                      GtkWidget        *toggle);
292

Elliot Lee's avatar
Elliot Lee committed
293

Sven Neumann's avatar
Sven Neumann committed
294
GimpPlugInInfo PLUG_IN_INFO =
Elliot Lee's avatar
Elliot Lee committed
295
{
296
297
298
299
  NULL,  /* init_proc  */
  NULL,  /* quit_proc  */
  query, /* query_proc */
  run,   /* run_proc   */
Elliot Lee's avatar
Elliot Lee committed
300
301
302
303
};

static JpegSaveVals jsvals =
{
304
305
306
  DEFAULT_QUALITY,
  DEFAULT_SMOOTHING,
  DEFAULT_OPTIMIZE,
307
308
309
310
311
  DEFAULT_PROGRESSIVE,
  DEFAULT_BASELINE,
  DEFAULT_SUBSMP,
  DEFAULT_RESTART,
  DEFAULT_DCT,
312
  DEFAULT_PREVIEW,
313
314
  DEFAULT_EXIF,
  DEFAULT_THUMBNAIL
Elliot Lee's avatar
Elliot Lee committed
315
316
317
};


Sven Neumann's avatar
Sven Neumann committed
318
static gchar     *image_comment         = NULL;
319
320
321
static GtkWidget *restart_markers_scale = NULL;
static GtkWidget *restart_markers_label = NULL;

322
323
324
#ifdef HAVE_EXIF
static ExifData  *exif_data             = NULL;
#endif /* HAVE_EXIF */
Sven Neumann's avatar
Sven Neumann committed
325

326

Elliot Lee's avatar
Elliot Lee committed
327
328
MAIN ()

329

Elliot Lee's avatar
Elliot Lee committed
330
static void
331
query (void)
Elliot Lee's avatar
Elliot Lee committed
332
{
Sven Neumann's avatar
Sven Neumann committed
333
  static GimpParamDef load_args[] =
Elliot Lee's avatar
Elliot Lee committed
334
  {
Sven Neumann's avatar
Sven Neumann committed
335
336
337
    { GIMP_PDB_INT32,    "run_mode",     "Interactive, non-interactive" },
    { GIMP_PDB_STRING,   "filename",     "The name of the file to load" },
    { GIMP_PDB_STRING,   "raw_filename", "The name of the file to load" }
Elliot Lee's avatar
Elliot Lee committed
338
  };
Sven Neumann's avatar
Sven Neumann committed
339
  static GimpParamDef load_return_vals[] =
Elliot Lee's avatar
Elliot Lee committed
340
  {
Sven Neumann's avatar
Sven Neumann committed
341
    { GIMP_PDB_IMAGE,   "image",         "Output image" }
Elliot Lee's avatar
Elliot Lee committed
342
343
  };

344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
#ifdef HAVE_EXIF

  static GimpParamDef thumb_args[] =
  {
    { GIMP_PDB_STRING, "filename",     "The name of the file to load"  },
    { GIMP_PDB_INT32,  "thumb_size",   "Preferred thumbnail size"      }
  };
  static GimpParamDef thumb_return_vals[] =
  {
    { GIMP_PDB_IMAGE,  "image",        "Thumbnail image"               },
    { GIMP_PDB_INT32,  "image_width",  "Width of full-sized image"     },
    { GIMP_PDB_INT32,  "image_height", "Height of full-sized image"    }
  };

#endif /* HAVE_EXIF */

Sven Neumann's avatar
Sven Neumann committed
360
  static GimpParamDef save_args[] =
Elliot Lee's avatar
Elliot Lee committed
361
  {
Sven Neumann's avatar
Sven Neumann committed
362
363
364
365
366
367
368
369
370
371
372
373
374
375
    { GIMP_PDB_INT32,    "run_mode",     "Interactive, non-interactive" },
    { GIMP_PDB_IMAGE,    "image",        "Input image" },
    { GIMP_PDB_DRAWABLE, "drawable",     "Drawable to save" },
    { GIMP_PDB_STRING,   "filename",     "The name of the file to save the image in" },
    { GIMP_PDB_STRING,   "raw_filename", "The name of the file to save the image in" },
    { GIMP_PDB_FLOAT,    "quality",      "Quality of saved image (0 <= quality <= 1)" },
    { GIMP_PDB_FLOAT,    "smoothing",    "Smoothing factor for saved image (0 <= smoothing <= 1)" },
    { GIMP_PDB_INT32,    "optimize",     "Optimization of entropy encoding parameters (0/1)" },
    { GIMP_PDB_INT32,    "progressive",  "Enable progressive jpeg image loading - ignored if not compiled with HAVE_PROGRESSIVE_JPEG (0/1)" },
    { GIMP_PDB_STRING,   "comment",      "Image comment" },
    { GIMP_PDB_INT32,    "subsmp",       "The subsampling option number" },
    { GIMP_PDB_INT32,    "baseline",     "Force creation of a baseline JPEG (non-baseline JPEGs can't be read by all decoders) (0/1)" },
    { GIMP_PDB_INT32,    "restart",      "Frequency of restart markers (in rows, 0 = no restart markers)" },
    { GIMP_PDB_INT32,    "dct",          "DCT algorithm to use (speed/quality tradeoff)" }
Elliot Lee's avatar
Elliot Lee committed
376
377
378
  };

  gimp_install_procedure ("file_jpeg_load",
Marc Lehmann's avatar
Marc Lehmann committed
379
380
                          "loads files in the JPEG file format",
                          "loads files in the JPEG file format",
381
                          "Spencer Kimball, Peter Mattis & others",
Elliot Lee's avatar
Elliot Lee committed
382
                          "Spencer Kimball & Peter Mattis",
383
                          "1995-1999",
Sven Neumann's avatar
Sven Neumann committed
384
385
                          N_("JPEG image"),
                          NULL,
Sven Neumann's avatar
Sven Neumann committed
386
                          GIMP_PLUGIN,
387
388
                          G_N_ELEMENTS (load_args),
                          G_N_ELEMENTS (load_return_vals),
Elliot Lee's avatar
Elliot Lee committed
389
390
                          load_args, load_return_vals);

391
392
  gimp_register_file_handler_mime ("file_jpeg_load", "image/jpeg");
  gimp_register_magic_load_handler ("file_jpeg_load",
Sven Neumann's avatar
Sven Neumann committed
393
394
395
                                    "jpg,jpeg,jpe",
                                    "",
                                    "6,string,JFIF,6,string,Exif");
396

397
398
399
400
401
402
403
404
#ifdef HAVE_EXIF

  gimp_install_procedure ("file_jpeg_load_thumb",
                          "Loads a thumbnail from a JPEG image",
                          "Loads a thumbnail from a JPEG image (only if it exists)",
                          "S. Mukund <muks@mukund.org>, Sven Neumann <sven@gimp.org>",
                          "S. Mukund <muks@mukund.org>, Sven Neumann <sven@gimp.org>",
                          "November 15, 2004",
405
                          NULL,
406
407
408
409
410
411
412
413
414
415
                          NULL,
                          GIMP_PLUGIN,
                          G_N_ELEMENTS (thumb_args),
                          G_N_ELEMENTS (thumb_return_vals),
                          thumb_args, thumb_return_vals);

  gimp_register_thumbnail_loader ("file_jpeg_load", "file_jpeg_load_thumb");

#endif /* HAVE_EXIF */

Elliot Lee's avatar
Elliot Lee committed
416
  gimp_install_procedure ("file_jpeg_save",
Marc Lehmann's avatar
Marc Lehmann committed
417
418
                          "saves files in the JPEG file format",
                          "saves files in the lossy, widely supported JPEG format",
419
                          "Spencer Kimball, Peter Mattis & others",
Elliot Lee's avatar
Elliot Lee committed
420
                          "Spencer Kimball & Peter Mattis",
421
                          "1995-1999",
422
                          N_("JPEG image"),
Sven Neumann's avatar
Sven Neumann committed
423
                          "RGB*, GRAY*",
Sven Neumann's avatar
Sven Neumann committed
424
                          GIMP_PLUGIN,
425
                          G_N_ELEMENTS (save_args), 0,
Elliot Lee's avatar
Elliot Lee committed
426
427
                          save_args, NULL);

428
  gimp_register_file_handler_mime ("file_jpeg_save", "image/jpeg");
429
  gimp_register_save_handler ("file_jpeg_save", "jpg,jpeg,jpe", "");
Elliot Lee's avatar
Elliot Lee committed
430
431
432
}

static void
433
434
435
436
437
run (const gchar      *name,
     gint              nparams,
     const GimpParam  *param,
     gint             *nreturn_vals,
     GimpParam       **return_vals)
Elliot Lee's avatar
Elliot Lee committed
438
{
439
  static GimpParam   values[4];
440
441
442
443
444
445
446
447
  GimpRunMode        run_mode;
  GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
  gint32             image_ID;
  gint32             drawable_ID;
  gint32             orig_image_ID;
  GimpParasite      *parasite;
  gboolean           err;
  GimpExportReturn   export = GIMP_EXPORT_CANCEL;
Elliot Lee's avatar
Elliot Lee committed
448
449
450

  run_mode = param[0].data.d_int32;

451
452
  INIT_I18N ();

Elliot Lee's avatar
Elliot Lee committed
453
  *nreturn_vals = 1;
454
  *return_vals  = values;
Sven Neumann's avatar
Sven Neumann committed
455
456
  values[0].type          = GIMP_PDB_STATUS;
  values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
457

Elliot Lee's avatar
Elliot Lee committed
458
459
  if (strcmp (name, "file_jpeg_load") == 0)
    {
460
      image_ID = load_image (param[1].data.d_string, run_mode, FALSE);
Elliot Lee's avatar
Elliot Lee committed
461
462

      if (image_ID != -1)
Sven Neumann's avatar
Sven Neumann committed
463
464
465
466
467
        {
          *nreturn_vals = 2;
          values[1].type         = GIMP_PDB_IMAGE;
          values[1].data.d_image = image_ID;
        }
Elliot Lee's avatar
Elliot Lee committed
468
      else
Sven Neumann's avatar
Sven Neumann committed
469
470
471
        {
          status = GIMP_PDB_EXECUTION_ERROR;
        }
Elliot Lee's avatar
Elliot Lee committed
472
    }
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509

#ifdef HAVE_EXIF

  else if (strcmp (name, "file_jpeg_load_thumb") == 0)
    {
      if (nparams < 2)
        {
          status = GIMP_PDB_CALLING_ERROR;
        }
      else
        {
          const gchar *filename = param[0].data.d_string;
          gint         width    = 0;
          gint         height   = 0;
          gint32       image_ID;

          image_ID = load_thumbnail_image (filename, &width, &height);

          if (image_ID != -1)
            {
              *nreturn_vals = 4;
              values[1].type         = GIMP_PDB_IMAGE;
              values[1].data.d_image = image_ID;
              values[2].type         = GIMP_PDB_INT32;
              values[2].data.d_int32 = width;
              values[3].type         = GIMP_PDB_INT32;
              values[3].data.d_int32 = height;
            }
          else
            {
              status = GIMP_PDB_EXECUTION_ERROR;
            }
        }
    }

#endif /* HAVE_EXIF */

Elliot Lee's avatar
Elliot Lee committed
510
511
  else if (strcmp (name, "file_jpeg_save") == 0)
    {
Sven Neumann's avatar
Sven Neumann committed
512
513
514
      image_ID = orig_image_ID = param[1].data.d_int32;
      drawable_ID = param[2].data.d_int32;

515
       /*  eventually export the image */
Sven Neumann's avatar
Sven Neumann committed
516
      switch (run_mode)
Sven Neumann's avatar
Sven Neumann committed
517
518
519
520
521
522
523
524
525
526
        {
        case GIMP_RUN_INTERACTIVE:
        case GIMP_RUN_WITH_LAST_VALS:
          gimp_ui_init ("jpeg", FALSE);
          export = gimp_export_image (&image_ID, &drawable_ID, "JPEG",
                                      (GIMP_EXPORT_CAN_HANDLE_RGB |
                                       GIMP_EXPORT_CAN_HANDLE_GRAY));
          switch (export)
            {
            case GIMP_EXPORT_EXPORT:
527
528
529
530
531
532
533
534
535
              {
                gchar *tmp = g_filename_from_utf8 (_("Export Preview"), -1,
                                                   NULL, NULL, NULL);
                if (tmp)
                  {
                    gimp_image_set_filename (image_ID, tmp);
                    g_free (tmp);
                  }

536
                display_ID = -1;
537
              }
Sven Neumann's avatar
Sven Neumann committed
538
539
540
541
542
543
544
545
546
547
548
549
              break;
            case GIMP_EXPORT_IGNORE:
              break;
            case GIMP_EXPORT_CANCEL:
              values[0].data.d_status = GIMP_PDB_CANCEL;
              return;
              break;
            }
          break;
        default:
          break;
        }
550

551
552
553
554
555
#ifdef HAVE_EXIF
      exif_data_unref (exif_data);
      exif_data = NULL;
#endif /* HAVE_EXIF */

Sven Neumann's avatar
Sven Neumann committed
556
557
      g_free (image_comment);
      image_comment = NULL;
558

Marc Lehmann's avatar
Marc Lehmann committed
559
      parasite = gimp_image_parasite_find (orig_image_ID, "gimp-comment");
560
      if (parasite)
Sven Neumann's avatar
Sven Neumann committed
561
        {
Michael Natterer's avatar
Michael Natterer committed
562
563
          image_comment = g_strndup (gimp_parasite_data (parasite),
                                     gimp_parasite_data_size (parasite));
Sven Neumann's avatar
Sven Neumann committed
564
565
          gimp_parasite_free (parasite);
        }
566

567
#ifdef HAVE_EXIF
568

569
      parasite = gimp_image_parasite_find (orig_image_ID, "exif-data");
570
571
      if (parasite)
        {
Michael Natterer's avatar
Michael Natterer committed
572
573
          exif_data = exif_data_new_from_data (gimp_parasite_data (parasite),
                                               gimp_parasite_data_size (parasite));
574
575
          gimp_parasite_free (parasite);
        }
576

577
578
#endif /* HAVE_EXIF */

579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
      jsvals.quality        = DEFAULT_QUALITY;
      jsvals.smoothing      = DEFAULT_SMOOTHING;
      jsvals.optimize       = DEFAULT_OPTIMIZE;
      jsvals.progressive    = DEFAULT_PROGRESSIVE;
      jsvals.baseline       = DEFAULT_BASELINE;
      jsvals.subsmp         = DEFAULT_SUBSMP;
      jsvals.restart        = DEFAULT_RESTART;
      jsvals.dct            = DEFAULT_DCT;
      jsvals.preview        = DEFAULT_PREVIEW;
      jsvals.save_exif      = DEFAULT_EXIF;
      jsvals.save_thumbnail = DEFAULT_THUMBNAIL;

#ifdef HAVE_EXIF

      if (exif_data && (exif_data->data))
        jsvals.save_thumbnail = TRUE;

#endif /* HAVE_EXIF */
597

Elliot Lee's avatar
Elliot Lee committed
598
      switch (run_mode)
Sven Neumann's avatar
Sven Neumann committed
599
600
601
602
603
604
605
606
607
608
        {
        case GIMP_RUN_INTERACTIVE:
          /*  Possibly retrieve data  */
          gimp_get_data ("file_jpeg_save", &jsvals);

          /* load up the previously used values */
          parasite = gimp_image_parasite_find (orig_image_ID,
                                               "jpeg-save-options");
          if (parasite)
            {
609
610
611
612
613
614
615
616
617
618
619
620
621
622
              const JpegSaveVals *save_vals = gimp_parasite_data (parasite);

              jsvals.quality        = save_vals->quality;
              jsvals.smoothing      = save_vals->smoothing;
              jsvals.optimize       = save_vals->optimize;
              jsvals.progressive    = save_vals->progressive;
              jsvals.baseline       = save_vals->baseline;
              jsvals.subsmp         = save_vals->subsmp;
              jsvals.restart        = save_vals->restart;
              jsvals.dct            = save_vals->dct;
              jsvals.preview        = save_vals->preview;
              jsvals.save_exif      = save_vals->save_exif;
              jsvals.save_thumbnail = save_vals->save_thumbnail;

Sven Neumann's avatar
Sven Neumann committed
623
624
              gimp_parasite_free (parasite);
            }
625

626
627
          if (jsvals.preview)
            {
628
629
              /* we freeze undo saving so that we can avoid sucking up
               * tile cache with our unneeded preview steps. */
630
631
632
633
              gimp_image_undo_freeze (image_ID);

              undo_touched = TRUE;
            }
634

Sven Neumann's avatar
Sven Neumann committed
635
636
637
638
          /* prepare for the preview */
          image_ID_global = image_ID;
          orig_image_ID_global = orig_image_ID;
          drawable_ID_global = drawable_ID;
639

Sven Neumann's avatar
Sven Neumann committed
640
641
          /*  First acquire information with a dialog  */
          err = save_dialog ();
642

643
644
          if (undo_touched)
            {
645
646
              /* thaw undo saving and flush the displays to have them
               * reflect the current shortcuts */
647
              gimp_image_undo_thaw (image_ID);
648
              gimp_displays_flush ();
649
            }
650
651

          if (!err)
Sven Neumann's avatar
Sven Neumann committed
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
            status = GIMP_PDB_CANCEL;
          break;

        case GIMP_RUN_NONINTERACTIVE:
          /*  Make sure all the arguments are there!  */
          /*  pw - added two more progressive and comment */
          /*  sg - added subsampling, preview, baseline, restarts and DCT */
          if (nparams != 14)
            {
              status = GIMP_PDB_CALLING_ERROR;
            }
          else
            {
              /* Once the PDB gets default parameters, remove this hack */
              if (param[5].data.d_float > 0.05)
                {
                  jsvals.quality     = 100.0 * param[5].data.d_float;
                  jsvals.smoothing   = param[6].data.d_float;
                  jsvals.optimize    = param[7].data.d_int32;
671
#ifdef HAVE_PROGRESSIVE_JPEG
Sven Neumann's avatar
Sven Neumann committed
672
                  jsvals.progressive = param[8].data.d_int32;
673
#endif /* HAVE_PROGRESSIVE_JPEG */
Sven Neumann's avatar
Sven Neumann committed
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
                  jsvals.baseline    = param[11].data.d_int32;
                  jsvals.subsmp      = param[10].data.d_int32;
                  jsvals.restart     = param[12].data.d_int32;
                  jsvals.dct         = param[13].data.d_int32;

                  /* free up the default -- wasted some effort earlier */
                  g_free (image_comment);
                  image_comment = g_strdup (param[9].data.d_string);
                }

              jsvals.preview = FALSE;

              if (jsvals.quality < 0.0 || jsvals.quality > 100.0)
                status = GIMP_PDB_CALLING_ERROR;
              else if (jsvals.smoothing < 0.0 || jsvals.smoothing > 1.0)
                status = GIMP_PDB_CALLING_ERROR;
              else if (jsvals.subsmp < 0 || jsvals.subsmp > 2)
                status = GIMP_PDB_CALLING_ERROR;
              else if (jsvals.dct < 0 || jsvals.dct > 2)
                status = GIMP_PDB_CALLING_ERROR;
            }
          break;

        case GIMP_RUN_WITH_LAST_VALS:
          /*  Possibly retrieve data  */
          gimp_get_data ("file_jpeg_save", &jsvals);

          parasite = gimp_image_parasite_find (orig_image_ID,
                                               "jpeg-save-options");
          if (parasite)
            {
705
706
707
708
709
710
711
712
713
714
              const JpegSaveVals *save_vals = gimp_parasite_data (parasite);

              jsvals.quality     = save_vals->quality;
              jsvals.smoothing   = save_vals->smoothing;
              jsvals.optimize    = save_vals->optimize;
              jsvals.progressive = save_vals->progressive;
              jsvals.baseline    = save_vals->baseline;
              jsvals.subsmp      = save_vals->subsmp;
              jsvals.restart     = save_vals->restart;
              jsvals.dct         = save_vals->dct;
Sven Neumann's avatar
Sven Neumann committed
715
              jsvals.preview     = FALSE;
716

Sven Neumann's avatar
Sven Neumann committed
717
718
719
720
721
722
723
              gimp_parasite_free (parasite);
            }
          break;

        default:
          break;
        }
Elliot Lee's avatar
Elliot Lee committed
724

Sven Neumann's avatar
Sven Neumann committed
725
      if (status == GIMP_PDB_SUCCESS)
Sven Neumann's avatar
Sven Neumann committed
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
        {
          if (save_image (param[3].data.d_string,
                          image_ID,
                          drawable_ID,
                          orig_image_ID,
                          FALSE))
            {
              /*  Store mvals data  */
              gimp_set_data ("file_jpeg_save", &jsvals, sizeof (JpegSaveVals));
            }
          else
            {
              status = GIMP_PDB_EXECUTION_ERROR;
            }
        }
741

742
      if (export == GIMP_EXPORT_EXPORT)
Sven Neumann's avatar
Sven Neumann committed
743
744
745
        {
          /* If the image was exported, delete the new display. */
          /* This also deletes the image.                       */
746

747
          if (display_ID != -1)
Sven Neumann's avatar
Sven Neumann committed
748
749
750
751
            gimp_display_delete (display_ID);
          else
            gimp_image_delete (image_ID);
        }
Sven Neumann's avatar
Sven Neumann committed
752

753
754
755
      /* pw - now we need to change the defaults to be whatever
       * was used to save this image.  Dump the old parasites
       * and add new ones. */
756

Marc Lehmann's avatar
Marc Lehmann committed
757
      gimp_image_parasite_detach (orig_image_ID, "gimp-comment");
758
      if (image_comment && strlen (image_comment))
Sven Neumann's avatar
Sven Neumann committed
759
760
761
762
763
764
765
766
        {
          parasite = gimp_parasite_new ("gimp-comment",
                                        GIMP_PARASITE_PERSISTENT,
                                        strlen (image_comment) + 1,
                                        image_comment);
          gimp_image_parasite_attach (orig_image_ID, parasite);
          gimp_parasite_free (parasite);
        }
Marc Lehmann's avatar
Marc Lehmann committed
767
      gimp_image_parasite_detach (orig_image_ID, "jpeg-save-options");
768

769
      parasite = gimp_parasite_new ("jpeg-save-options",
Sven Neumann's avatar
Sven Neumann committed
770
                                    0, sizeof (jsvals), &jsvals);
Marc Lehmann's avatar
Marc Lehmann committed
771
      gimp_image_parasite_attach (orig_image_ID, parasite);
772
      gimp_parasite_free (parasite);
Elliot Lee's avatar
Elliot Lee committed
773
    }
774
775
  else
    {
Sven Neumann's avatar
Sven Neumann committed
776
      status = GIMP_PDB_CALLING_ERROR;
777
    }
Elliot Lee's avatar
Elliot Lee committed
778

779
780
  values[0].data.d_status = status;
}
Elliot Lee's avatar
Elliot Lee committed
781

782
/* Read next byte */
783
static guint
784
785
jpeg_getc (j_decompress_ptr cinfo)
{
786
  struct jpeg_source_mgr *datasrc = cinfo->src;
787

788
  if (datasrc->bytes_in_buffer == 0)
Sven Neumann's avatar
Sven Neumann committed
789
790
    {
      if (! (*datasrc->fill_input_buffer) (cinfo))
Sven Neumann's avatar
Sven Neumann committed
791
        ERREXIT (cinfo, JERR_CANT_SUSPEND);
Sven Neumann's avatar
Sven Neumann committed
792
    }
793
  datasrc->bytes_in_buffer--;
794

795
796
797
798
799
800
801
802
803
804
805
806
  return *datasrc->next_input_byte++;
}

/* We need our own marker parser, since early versions of libjpeg
 * don't keep a conventient list of the marker's that have been
 * seen. */

/*
 * Marker processor for COM markers.
 * This replaces the library's built-in processor, which just skips the marker.
 * Note this code relies on a non-suspending data source.
 */
Sven Neumann's avatar
Sven Neumann committed
807
static GString *local_image_comments = NULL;
808
809
810
811

static boolean
COM_handler (j_decompress_ptr cinfo)
{
812
813
  gint  length;
  guint ch;
814
815
816
817
818

  length = jpeg_getc (cinfo) << 8;
  length += jpeg_getc (cinfo);
  if (length < 2)
    return FALSE;
Sven Neumann's avatar
Sven Neumann committed
819
  length -= 2;                  /* discount the length word itself */
820
821
822
823
824
825
826

  if (!local_image_comments)
    local_image_comments = g_string_new (NULL);
  else
    g_string_append_c (local_image_comments, '\n');

  while (length-- > 0)
Sven Neumann's avatar
Sven Neumann committed
827
828
829
830
    {
      ch = jpeg_getc (cinfo);
      g_string_append_c (local_image_comments, ch);
    }
831
832
833
834

  return TRUE;
}

835
836
typedef struct my_error_mgr
{
837
838
839
840
841
842
  struct jpeg_error_mgr pub;            /* "public" fields */

#ifdef __ia64__
  /* Ugh, the jmp_buf field needs to be 16-byte aligned on ia64 and some
   * glibc/icc combinations don't guarantee this. So we pad. See bug #138357
   * for details.
843
   */
844
845
  long double           dummy;
#endif
846

847
  jmp_buf               setjmp_buffer;  /* for return to caller */
Elliot Lee's avatar
Elliot Lee committed
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
} *my_error_ptr;

/*
 * Here's the routine that will replace the standard error_exit method:
 */

static void
my_error_exit (j_common_ptr cinfo)
{
  /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
  my_error_ptr myerr = (my_error_ptr) cinfo->err;

  /* Always display the message. */
  /* We could postpone this until after returning, if we chose. */
  (*cinfo->err->output_message) (cinfo);

  /* Return control to the setjmp point */
  longjmp (myerr->setjmp_buffer, 1);
}

868
869
870
871
872
static void
my_emit_message (j_common_ptr cinfo,
                 int          msg_level)
{
  if (msg_level == -1)
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
    {
      /*  disable loading of EXIF data  */
      cinfo->client_data = GINT_TO_POINTER (TRUE);

      (*cinfo->err->output_message) (cinfo);
    }
}

static void
my_output_message (j_common_ptr cinfo)
{
  gchar  buffer[JMSG_LENGTH_MAX + 1];

  (*cinfo->err->format_message)(cinfo, buffer);

  if (GPOINTER_TO_INT (cinfo->client_data))
    {
      gchar *msg = g_strconcat (buffer,
                                "\n\n",
                                _("EXIF data will be ignored."),
                                NULL);
      g_message (msg);
      g_free (msg);
    }
  else
    {
      g_message (buffer);
    }
901
902
}

Elliot Lee's avatar
Elliot Lee committed
903
static gint32
904
load_image (const gchar *filename,
Sven Neumann's avatar
Sven Neumann committed
905
906
            GimpRunMode  runmode,
            gboolean     preview)
Elliot Lee's avatar
Elliot Lee committed
907
{
908
909
910
911
  GimpPixelRgn     pixel_rgn;
  GimpDrawable    *drawable;
  gint32 volatile  image_ID;
  gint32           layer_ID;
Elliot Lee's avatar
Elliot Lee committed
912
  struct jpeg_decompress_struct cinfo;
913
914
915
916
  struct my_error_mgr           jerr;
  FILE    *infile;
  guchar  *buf;
  guchar  * volatile padded_buf = NULL;
Elliot Lee's avatar
Elliot Lee committed
917
  guchar **rowbuf;
918
919
920
921
922
  gint     image_type;
  gint     layer_type;
  gint     tile_height;
  gint     scanlines;
  gint     i, start, end;
Elliot Lee's avatar
Elliot Lee committed
923

924
  GimpParasite * volatile comment_parasite = NULL;
925

926
927
#ifdef HAVE_EXIF
  GimpParasite *exif_parasite = NULL;
928
  ExifData     *exif_data     = NULL;
929
930
#endif

Elliot Lee's avatar
Elliot Lee committed
931
932
933
934
  /* We set up the normal JPEG error routines. */
  cinfo.err = jpeg_std_error (&jerr.pub);
  jerr.pub.error_exit = my_error_exit;

935
936
937
  /* flag warnings, so we try to ignore corrupt EXIF data */
  if (!preview)
    {
938
939
940
941
      cinfo.client_data = GINT_TO_POINTER (FALSE);

      jerr.pub.emit_message   = my_emit_message;
      jerr.pub.output_message = my_output_message;
942
943
    }

Elliot Lee's avatar
Elliot Lee committed
944
945
  if ((infile = fopen (filename, "rb")) == NULL)
    {
946
      g_message (_("Could not open '%s' for reading: %s"),
947
                 gimp_filename_to_utf8 (filename), g_strerror (errno));
Elliot Lee's avatar
Elliot Lee committed
948
949
950
      gimp_quit ();
    }

951
952
  if (!preview)
    {
953
954
      gchar *name = g_strdup_printf (_("Opening '%s'..."),
                                     gimp_filename_to_utf8 (filename));
955
956
957
958

      gimp_progress_init (name);
      g_free (name);
    }
Elliot Lee's avatar
Elliot Lee committed
959
960
961
962
963
964
965
966
967
968

  image_ID = -1;
  /* Establish the setjmp return context for my_error_exit to use. */
  if (setjmp (jerr.setjmp_buffer))
    {
      /* If we get here, the JPEG code has signaled an error.
       * We need to clean up the JPEG object, close the input file, and return.
       */
      jpeg_destroy_decompress (&cinfo);
      if (infile)
Sven Neumann's avatar
Sven Neumann committed
969
        fclose (infile);
970
      if (image_ID != -1 && !preview)
Sven Neumann's avatar
Sven Neumann committed
971
        gimp_image_delete (image_ID);
972
      if (preview)
Sven Neumann's avatar
Sven Neumann committed
973
        destroy_preview();
Elliot Lee's avatar
Elliot Lee committed
974
975
      gimp_quit ();
    }
976

Elliot Lee's avatar
Elliot Lee committed
977
978
979
980
981
982
983
  /* Now we can initialize the JPEG decompression object. */
  jpeg_create_decompress (&cinfo);

  /* Step 2: specify data source (eg, a file) */

  jpeg_stdio_src (&cinfo, infile);

984
  /* pw - step 2.1 let the lib know we want the comments. */
985
986

  jpeg_set_marker_processor (&cinfo, JPEG_COM, COM_handler);
987

Elliot Lee's avatar
Elliot Lee committed
988
989
990
  /* Step 3: read file parameters with jpeg_read_header() */

  (void) jpeg_read_header (&cinfo, TRUE);
991

Elliot Lee's avatar
Elliot Lee committed
992
993
994
995
996
997
  /* We can ignore the return value from jpeg_read_header since
   *   (a) suspension is not possible with the stdio data source, and
   *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
   * See libjpeg.doc for more info.
   */

998
  if (!preview)
999
1000
    {
      /* if we had any comments then make a parasite for them */