jpeg-load.c 64.8 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.
 */

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

Sven Neumann's avatar
Sven Neumann committed
144
#include <glib.h>     /* We want glib.h first because of some
Sven Neumann's avatar
Sven Neumann committed
145
146
                       * pretty obscure Win32 compilation issues.
                       */
147
#include <errno.h>
Elliot Lee's avatar
Elliot Lee committed
148
#include <setjmp.h>
149
#include <signal.h>
Elliot Lee's avatar
Elliot Lee committed
150
151
152
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
153
#include <sys/types.h>
154
#include <sys/stat.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
155
#ifdef HAVE_UNISTD_H
156
#include <unistd.h>
Tor Lillqvist's avatar
Tor Lillqvist committed
157
#endif
Elliot Lee's avatar
Elliot Lee committed
158
#include <jpeglib.h>
159
#include <jerror.h>
160

161
162
163
164
#ifdef HAVE_EXIF
#include <libexif/exif-data.h>
#endif /* HAVE_EXIF */

Michael Natterer's avatar
Michael Natterer committed
165
166
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
167

168
169
#include "libgimp/stdplugins-intl.h"

Sven Neumann's avatar
Sven Neumann committed
170
#define SCALE_WIDTH         125
Elliot Lee's avatar
Elliot Lee committed
171

172
173
/* if you are not compiling this from inside the gimp tree, you have to  */
/* take care yourself if your JPEG library supports progressive mode     */
174
/* #undef HAVE_PROGRESSIVE_JPEG   if your library doesn't support it     */
175
176
/* #define HAVE_PROGRESSIVE_JPEG  if your library knows how to handle it */

177
/* See bugs #63610 and #61088 for a discussion about the quality settings */
178
#define DEFAULT_QUALITY     85
Sven Neumann's avatar
Sven Neumann committed
179
#define DEFAULT_SMOOTHING   0.0
180
181
182
#define DEFAULT_OPTIMIZE    TRUE
#define DEFAULT_PROGRESSIVE FALSE
#define DEFAULT_BASELINE    TRUE
Sven Neumann's avatar
Sven Neumann committed
183
184
185
#define DEFAULT_SUBSMP      0
#define DEFAULT_RESTART     0
#define DEFAULT_DCT         0
186
187
#define DEFAULT_PREVIEW     FALSE
#define DEFAULT_EXIF        TRUE
188
189

/* sg - these should not be global... */
190
191
192
193
194
195
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;
196
static gboolean         undo_touched          = FALSE;
197

Elliot Lee's avatar
Elliot Lee committed
198
199
typedef struct
{
200
201
202
203
204
205
206
207
208
209
  gdouble  quality;
  gdouble  smoothing;
  gboolean optimize;
  gboolean progressive;
  gboolean baseline;
  gint     subsmp;
  gint     restart;
  gint     dct;
  gboolean preview;
  gboolean save_exif;
Elliot Lee's avatar
Elliot Lee committed
210
211
} JpegSaveVals;

212
typedef struct
213
214
{
  struct jpeg_compress_struct cinfo;
215
216
  gint          tile_height;
  FILE         *outfile;
217
  gboolean      has_alpha;
218
219
220
221
  gint          rowstride;
  guchar       *temp;
  guchar       *data;
  guchar       *src;
Sven Neumann's avatar
Sven Neumann committed
222
223
  GimpDrawable *drawable;
  GimpPixelRgn  pixel_rgn;
224
  const gchar  *file_name;
Sven Neumann's avatar
Sven Neumann committed
225
226
227
228
  gboolean      abort_me;
} PreviewPersistent;

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

230

Elliot Lee's avatar
Elliot Lee committed
231
232
/* Declare local functions.
 */
Sven Neumann's avatar
Sven Neumann committed
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
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);
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);
255

Elliot Lee's avatar
Elliot Lee committed
256

Sven Neumann's avatar
Sven Neumann committed
257
GimpPlugInInfo PLUG_IN_INFO =
Elliot Lee's avatar
Elliot Lee committed
258
{
259
260
261
262
  NULL,  /* init_proc  */
  NULL,  /* quit_proc  */
  query, /* query_proc */
  run,   /* run_proc   */
Elliot Lee's avatar
Elliot Lee committed
263
264
265
266
};

static JpegSaveVals jsvals =
{
267
268
269
  DEFAULT_QUALITY,
  DEFAULT_SMOOTHING,
  DEFAULT_OPTIMIZE,
270
271
272
273
274
  DEFAULT_PROGRESSIVE,
  DEFAULT_BASELINE,
  DEFAULT_SUBSMP,
  DEFAULT_RESTART,
  DEFAULT_DCT,
275
276
  DEFAULT_PREVIEW,
  DEFAULT_EXIF
Elliot Lee's avatar
Elliot Lee committed
277
278
279
};


Sven Neumann's avatar
Sven Neumann committed
280
static gchar     *image_comment         = NULL;
281
282
283
static GtkWidget *restart_markers_scale = NULL;
static GtkWidget *restart_markers_label = NULL;

284
285
286
#ifdef HAVE_EXIF
static ExifData  *exif_data             = NULL;
#endif /* HAVE_EXIF */
Sven Neumann's avatar
Sven Neumann committed
287

Elliot Lee's avatar
Elliot Lee committed
288
289
290
MAIN ()

static void
291
query (void)
Elliot Lee's avatar
Elliot Lee committed
292
{
Sven Neumann's avatar
Sven Neumann committed
293
  static GimpParamDef load_args[] =
Elliot Lee's avatar
Elliot Lee committed
294
  {
Sven Neumann's avatar
Sven Neumann committed
295
296
297
    { 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
298
  };
Sven Neumann's avatar
Sven Neumann committed
299
  static GimpParamDef load_return_vals[] =
Elliot Lee's avatar
Elliot Lee committed
300
  {
Sven Neumann's avatar
Sven Neumann committed
301
    { GIMP_PDB_IMAGE,   "image",         "Output image" }
Elliot Lee's avatar
Elliot Lee committed
302
303
  };

Sven Neumann's avatar
Sven Neumann committed
304
  static GimpParamDef save_args[] =
Elliot Lee's avatar
Elliot Lee committed
305
  {
Sven Neumann's avatar
Sven Neumann committed
306
307
308
309
310
311
312
313
314
315
316
317
318
319
    { 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
320
321
322
  };

  gimp_install_procedure ("file_jpeg_load",
Marc Lehmann's avatar
Marc Lehmann committed
323
324
                          "loads files in the JPEG file format",
                          "loads files in the JPEG file format",
325
                          "Spencer Kimball, Peter Mattis & others",
Elliot Lee's avatar
Elliot Lee committed
326
                          "Spencer Kimball & Peter Mattis",
327
                          "1995-1999",
Sven Neumann's avatar
Sven Neumann committed
328
329
                          N_("JPEG image"),
                          NULL,
Sven Neumann's avatar
Sven Neumann committed
330
                          GIMP_PLUGIN,
331
332
                          G_N_ELEMENTS (load_args),
                          G_N_ELEMENTS (load_return_vals),
Elliot Lee's avatar
Elliot Lee committed
333
334
                          load_args, load_return_vals);

335
336
  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
337
338
339
                                    "jpg,jpeg,jpe",
                                    "",
                                    "6,string,JFIF,6,string,Exif");
340

Elliot Lee's avatar
Elliot Lee committed
341
  gimp_install_procedure ("file_jpeg_save",
Marc Lehmann's avatar
Marc Lehmann committed
342
343
                          "saves files in the JPEG file format",
                          "saves files in the lossy, widely supported JPEG format",
344
                          "Spencer Kimball, Peter Mattis & others",
Elliot Lee's avatar
Elliot Lee committed
345
                          "Spencer Kimball & Peter Mattis",
346
                          "1995-1999",
347
                          N_("JPEG image"),
Sven Neumann's avatar
Sven Neumann committed
348
                          "RGB*, GRAY*",
Sven Neumann's avatar
Sven Neumann committed
349
                          GIMP_PLUGIN,
350
                          G_N_ELEMENTS (save_args), 0,
Elliot Lee's avatar
Elliot Lee committed
351
352
                          save_args, NULL);

353
  gimp_register_file_handler_mime ("file_jpeg_save", "image/jpeg");
354
  gimp_register_save_handler ("file_jpeg_save", "jpg,jpeg,jpe", "");
Elliot Lee's avatar
Elliot Lee committed
355
356
357
}

static void
358
359
360
361
362
run (const gchar      *name,
     gint              nparams,
     const GimpParam  *param,
     gint             *nreturn_vals,
     GimpParam       **return_vals)
Elliot Lee's avatar
Elliot Lee committed
363
{
364
365
366
367
368
369
370
371
372
373
  static GimpParam   values[2];
  GimpRunMode        run_mode;
  GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
  gint32             image_ID;
  gint32             drawable_ID;
  gint32             orig_image_ID;
  gint32             display_ID = -1;
  GimpParasite      *parasite;
  gboolean           err;
  GimpExportReturn   export = GIMP_EXPORT_CANCEL;
Elliot Lee's avatar
Elliot Lee committed
374
375
376

  run_mode = param[0].data.d_int32;

377
378
  INIT_I18N ();

Elliot Lee's avatar
Elliot Lee committed
379
  *nreturn_vals = 1;
380
  *return_vals  = values;
Sven Neumann's avatar
Sven Neumann committed
381
382
  values[0].type          = GIMP_PDB_STATUS;
  values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
383

Elliot Lee's avatar
Elliot Lee committed
384
385
  if (strcmp (name, "file_jpeg_load") == 0)
    {
386
      image_ID = load_image (param[1].data.d_string, run_mode, FALSE);
Elliot Lee's avatar
Elliot Lee committed
387
388

      if (image_ID != -1)
Sven Neumann's avatar
Sven Neumann committed
389
390
391
392
393
        {
          *nreturn_vals = 2;
          values[1].type         = GIMP_PDB_IMAGE;
          values[1].data.d_image = image_ID;
        }
Elliot Lee's avatar
Elliot Lee committed
394
      else
Sven Neumann's avatar
Sven Neumann committed
395
396
397
        {
          status = GIMP_PDB_EXECUTION_ERROR;
        }
Elliot Lee's avatar
Elliot Lee committed
398
399
400
    }
  else if (strcmp (name, "file_jpeg_save") == 0)
    {
Sven Neumann's avatar
Sven Neumann committed
401
402
403
      image_ID = orig_image_ID = param[1].data.d_int32;
      drawable_ID = param[2].data.d_int32;

404
       /*  eventually export the image */
Sven Neumann's avatar
Sven Neumann committed
405
      switch (run_mode)
Sven Neumann's avatar
Sven Neumann committed
406
407
408
409
410
411
412
413
414
415
        {
        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:
416
417
418
419
420
421
422
423
424
425
426
427
              {
                gchar *tmp = g_filename_from_utf8 (_("Export Preview"), -1,
                                                   NULL, NULL, NULL);
                if (tmp)
                  {
                    gimp_image_set_filename (image_ID, tmp);
                    g_free (tmp);
                  }

                display_ID = gimp_display_new (image_ID);
                gimp_displays_flush ();
              }
Sven Neumann's avatar
Sven Neumann committed
428
429
430
431
432
433
434
435
436
437
438
439
              break;
            case GIMP_EXPORT_IGNORE:
              break;
            case GIMP_EXPORT_CANCEL:
              values[0].data.d_status = GIMP_PDB_CANCEL;
              return;
              break;
            }
          break;
        default:
          break;
        }
440

441
442
443
444
445
#ifdef HAVE_EXIF
      exif_data_unref (exif_data);
      exif_data = NULL;
#endif /* HAVE_EXIF */

Sven Neumann's avatar
Sven Neumann committed
446
447
      g_free (image_comment);
      image_comment = NULL;
448

Marc Lehmann's avatar
Marc Lehmann committed
449
      parasite = gimp_image_parasite_find (orig_image_ID, "gimp-comment");
450
      if (parasite)
Sven Neumann's avatar
Sven Neumann committed
451
452
453
454
        {
          image_comment = g_strdup (parasite->data);
          gimp_parasite_free (parasite);
        }
455

456
#ifdef HAVE_EXIF
457
      parasite = gimp_image_parasite_find (orig_image_ID, "exif-data");
458
459
460
461
462
463
464
      if (parasite)
        {
          exif_data = exif_data_new_from_data (parasite->data, parasite->size);
          gimp_parasite_free (parasite);
        }
#endif /* HAVE_EXIF */

465
466
467
      jsvals.quality     = DEFAULT_QUALITY;
      jsvals.smoothing   = DEFAULT_SMOOTHING;
      jsvals.optimize    = DEFAULT_OPTIMIZE;
468
      jsvals.progressive = DEFAULT_PROGRESSIVE;
469
470
471
472
473
      jsvals.baseline    = DEFAULT_BASELINE;
      jsvals.subsmp      = DEFAULT_SUBSMP;
      jsvals.restart     = DEFAULT_RESTART;
      jsvals.dct         = DEFAULT_DCT;
      jsvals.preview     = DEFAULT_PREVIEW;
474
      jsvals.save_exif   = DEFAULT_EXIF;
475

Elliot Lee's avatar
Elliot Lee committed
476
      switch (run_mode)
Sven Neumann's avatar
Sven Neumann committed
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
        {
        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)
            {
              jsvals.quality     = ((JpegSaveVals *)parasite->data)->quality;
              jsvals.smoothing   = ((JpegSaveVals *)parasite->data)->smoothing;
              jsvals.optimize    = ((JpegSaveVals *)parasite->data)->optimize;
              jsvals.progressive = ((JpegSaveVals *)parasite->data)->progressive;
              jsvals.baseline    = ((JpegSaveVals *)parasite->data)->baseline;
              jsvals.subsmp      = ((JpegSaveVals *)parasite->data)->subsmp;
              jsvals.restart     = ((JpegSaveVals *)parasite->data)->restart;
              jsvals.dct         = ((JpegSaveVals *)parasite->data)->dct;
              jsvals.preview     = ((JpegSaveVals *)parasite->data)->preview;
              jsvals.save_exif   = ((JpegSaveVals *)parasite->data)->save_exif;
              gimp_parasite_free (parasite);
            }
499

500
501
          if (jsvals.preview)
            {
502
503
              /* we freeze undo saving so that we can avoid sucking up
               * tile cache with our unneeded preview steps. */
504
505
506
507
              gimp_image_undo_freeze (image_ID);

              undo_touched = TRUE;
            }
508

Sven Neumann's avatar
Sven Neumann committed
509
510
511
512
          /* prepare for the preview */
          image_ID_global = image_ID;
          orig_image_ID_global = orig_image_ID;
          drawable_ID_global = drawable_ID;
513

Sven Neumann's avatar
Sven Neumann committed
514
515
          /*  First acquire information with a dialog  */
          err = save_dialog ();
516

517
518
          if (undo_touched)
            {
519
520
              /* thaw undo saving and flush the displays to have them
               * reflect the current shortcuts */
521
              gimp_image_undo_thaw (image_ID);
522
              gimp_displays_flush ();
523
            }
524
525

          if (!err)
Sven Neumann's avatar
Sven Neumann committed
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
            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;
545
#ifdef HAVE_PROGRESSIVE_JPEG
Sven Neumann's avatar
Sven Neumann committed
546
                  jsvals.progressive = param[8].data.d_int32;
547
#endif /* HAVE_PROGRESSIVE_JPEG */
Sven Neumann's avatar
Sven Neumann committed
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
                  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)
            {
              jsvals.quality     = ((JpegSaveVals *)parasite->data)->quality;
              jsvals.smoothing   = ((JpegSaveVals *)parasite->data)->smoothing;
              jsvals.optimize    = ((JpegSaveVals *)parasite->data)->optimize;
              jsvals.progressive = ((JpegSaveVals *)parasite->data)->progressive;
              jsvals.baseline    = ((JpegSaveVals *)parasite->data)->baseline;
              jsvals.subsmp      = ((JpegSaveVals *)parasite->data)->subsmp;
              jsvals.restart     = ((JpegSaveVals *)parasite->data)->restart;
              jsvals.dct         = ((JpegSaveVals *)parasite->data)->dct;
              jsvals.preview     = FALSE;
              gimp_parasite_free (parasite);
            }
          break;

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

Sven Neumann's avatar
Sven Neumann committed
596
      if (status == GIMP_PDB_SUCCESS)
Sven Neumann's avatar
Sven Neumann committed
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
        {
          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;
            }
        }
612

613
      if (export == GIMP_EXPORT_EXPORT)
Sven Neumann's avatar
Sven Neumann committed
614
615
616
        {
          /* If the image was exported, delete the new display. */
          /* This also deletes the image.                       */
617

Sven Neumann's avatar
Sven Neumann committed
618
619
620
621
622
          if (display_ID > -1)
            gimp_display_delete (display_ID);
          else
            gimp_image_delete (image_ID);
        }
Sven Neumann's avatar
Sven Neumann committed
623

624
625
626
      /* 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. */
627

Marc Lehmann's avatar
Marc Lehmann committed
628
      gimp_image_parasite_detach (orig_image_ID, "gimp-comment");
629
      if (image_comment && strlen (image_comment))
Sven Neumann's avatar
Sven Neumann committed
630
631
632
633
634
635
636
637
        {
          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
638
      gimp_image_parasite_detach (orig_image_ID, "jpeg-save-options");
639

640
      parasite = gimp_parasite_new ("jpeg-save-options",
Sven Neumann's avatar
Sven Neumann committed
641
                                    0, sizeof (jsvals), &jsvals);
Marc Lehmann's avatar
Marc Lehmann committed
642
      gimp_image_parasite_attach (orig_image_ID, parasite);
643
      gimp_parasite_free (parasite);
Elliot Lee's avatar
Elliot Lee committed
644
    }
645
646
  else
    {
Sven Neumann's avatar
Sven Neumann committed
647
      status = GIMP_PDB_CALLING_ERROR;
648
    }
Elliot Lee's avatar
Elliot Lee committed
649

650
651
  values[0].data.d_status = status;
}
Elliot Lee's avatar
Elliot Lee committed
652

653
/* Read next byte */
654
static guint
655
656
jpeg_getc (j_decompress_ptr cinfo)
{
657
  struct jpeg_source_mgr *datasrc = cinfo->src;
658

659
  if (datasrc->bytes_in_buffer == 0)
Sven Neumann's avatar
Sven Neumann committed
660
661
    {
      if (! (*datasrc->fill_input_buffer) (cinfo))
Sven Neumann's avatar
Sven Neumann committed
662
        ERREXIT (cinfo, JERR_CANT_SUSPEND);
Sven Neumann's avatar
Sven Neumann committed
663
    }
664
  datasrc->bytes_in_buffer--;
665

666
667
668
669
670
671
672
673
674
675
676
677
  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
678
static GString *local_image_comments = NULL;
679
680
681
682

static boolean
COM_handler (j_decompress_ptr cinfo)
{
683
684
  gint  length;
  guint ch;
685
686
687
688
689

  length = jpeg_getc (cinfo) << 8;
  length += jpeg_getc (cinfo);
  if (length < 2)
    return FALSE;
Sven Neumann's avatar
Sven Neumann committed
690
  length -= 2;                  /* discount the length word itself */
691
692
693
694
695
696
697

  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
698
699
700
701
    {
      ch = jpeg_getc (cinfo);
      g_string_append_c (local_image_comments, ch);
    }
702
703
704
705

  return TRUE;
}

706
707
typedef struct my_error_mgr
{
708
709
710
711
712
713
  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.
714
   */
715
716
  long double           dummy;
#endif
717

718
  jmp_buf               setjmp_buffer;  /* for return to caller */
Elliot Lee's avatar
Elliot Lee committed
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
} *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);
}

739
740
741
742
743
static void
my_emit_message (j_common_ptr cinfo,
                 int          msg_level)
{
  if (msg_level == -1)
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
    {
      /*  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);
    }
772
773
}

Elliot Lee's avatar
Elliot Lee committed
774
static gint32
775
load_image (const gchar *filename,
Sven Neumann's avatar
Sven Neumann committed
776
777
            GimpRunMode  runmode,
            gboolean     preview)
Elliot Lee's avatar
Elliot Lee committed
778
{
779
780
781
782
  GimpPixelRgn     pixel_rgn;
  GimpDrawable    *drawable;
  gint32 volatile  image_ID;
  gint32           layer_ID;
Elliot Lee's avatar
Elliot Lee committed
783
  struct jpeg_decompress_struct cinfo;
784
785
786
787
  struct my_error_mgr           jerr;
  FILE    *infile;
  guchar  *buf;
  guchar  * volatile padded_buf = NULL;
Elliot Lee's avatar
Elliot Lee committed
788
  guchar **rowbuf;
789
790
791
792
793
  gint     image_type;
  gint     layer_type;
  gint     tile_height;
  gint     scanlines;
  gint     i, start, end;
Elliot Lee's avatar
Elliot Lee committed
794

795
  GimpParasite * volatile comment_parasite = NULL;
796

797
798
#ifdef HAVE_EXIF
  GimpParasite *exif_parasite = NULL;
799
  ExifData     *exif_data     = NULL;
800
801
#endif

Elliot Lee's avatar
Elliot Lee committed
802
803
804
805
  /* We set up the normal JPEG error routines. */
  cinfo.err = jpeg_std_error (&jerr.pub);
  jerr.pub.error_exit = my_error_exit;

806
807
808
  /* flag warnings, so we try to ignore corrupt EXIF data */
  if (!preview)
    {
809
810
811
812
      cinfo.client_data = GINT_TO_POINTER (FALSE);

      jerr.pub.emit_message   = my_emit_message;
      jerr.pub.output_message = my_output_message;
813
814
    }

Elliot Lee's avatar
Elliot Lee committed
815
816
  if ((infile = fopen (filename, "rb")) == NULL)
    {
817
      g_message (_("Could not open '%s' for reading: %s"),
818
                 gimp_filename_to_utf8 (filename), g_strerror (errno));
Elliot Lee's avatar
Elliot Lee committed
819
820
821
      gimp_quit ();
    }

822
823
  if (!preview)
    {
824
825
      gchar *name = g_strdup_printf (_("Opening '%s'..."),
                                     gimp_filename_to_utf8 (filename));
826
827
828
829

      gimp_progress_init (name);
      g_free (name);
    }
Elliot Lee's avatar
Elliot Lee committed
830
831
832
833
834
835
836
837
838
839

  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
840
        fclose (infile);
841
      if (image_ID != -1 && !preview)
Sven Neumann's avatar
Sven Neumann committed
842
        gimp_image_delete (image_ID);
843
      if (preview)
Sven Neumann's avatar
Sven Neumann committed
844
        destroy_preview();
Elliot Lee's avatar
Elliot Lee committed
845
846
      gimp_quit ();
    }
847

Elliot Lee's avatar
Elliot Lee committed
848
849
850
851
852
853
854
  /* 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);

855
  /* pw - step 2.1 let the lib know we want the comments. */
856
857

  jpeg_set_marker_processor (&cinfo, JPEG_COM, COM_handler);
858

Elliot Lee's avatar
Elliot Lee committed
859
860
861
  /* Step 3: read file parameters with jpeg_read_header() */

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

Elliot Lee's avatar
Elliot Lee committed
863
864
865
866
867
868
  /* 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.
   */

869
  if (!preview)
870
871
    {
      /* if we had any comments then make a parasite for them */
872
      if (local_image_comments && local_image_comments->len)
Sven Neumann's avatar
Sven Neumann committed
873
874
        {
          gchar *comment = local_image_comments->str;
875

Sven Neumann's avatar
Sven Neumann committed
876
          g_string_free (local_image_comments, FALSE);
877

Sven Neumann's avatar
Sven Neumann committed
878
          local_image_comments = NULL;
879
880
881
882
883
884
885

          if (g_utf8_validate (comment, -1, NULL))
            comment_parasite = gimp_parasite_new ("gimp-comment",
                                                  GIMP_PARASITE_PERSISTENT,
                                                  strlen (comment) + 1,
                                                  comment);
          g_free (comment);
Sven Neumann's avatar
Sven Neumann committed
886
        }
887

888
889
890
      /* Do not attach the "jpeg-save-options" parasite to the image
       * because this conflics with the global defaults.  See bug #75398:
       * http://bugzilla.gnome.org/show_bug.cgi?id=75398 */
891
892
    }

Elliot Lee's avatar
Elliot Lee committed
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
  /* Step 4: set parameters for decompression */

  /* In this example, we don't need to change any of the defaults set by
   * jpeg_read_header(), so we do nothing here.
   */

  /* Step 5: Start decompressor */

  jpeg_start_decompress (&cinfo);

  /* We may need to do some setup of our own at this point before reading
   * the data.  After jpeg_start_decompress() we have the correct scaled
   * output image dimensions available, as well as the output colormap
   * if we asked for color quantization.
   * In this example, we need to make an output work buffer of the right size.
   */
  /* temporary buffer */
  tile_height = gimp_tile_height ();
911
  buf = g_new (guchar,
Sven Neumann's avatar
Sven Neumann committed
912
               tile_height * cinfo.output_width * cinfo.output_components);
913

Elliot Lee's avatar
Elliot Lee committed
914
915
916
917
918
919
  rowbuf = g_new (guchar*, tile_height);

  for (i = 0; i < tile_height; i++)
    rowbuf[i] = buf + cinfo.output_width * cinfo.output_components * i;

  /* Create a new image of the proper size and associate the filename with it.
920
921
922

     Preview layers, not being on the bottom of a layer stack, MUST HAVE
     AN ALPHA CHANNEL!
Elliot Lee's avatar
Elliot Lee committed
923
924
925
926
   */
  switch (cinfo.output_components)
    {
    case 1:
Sven Neumann's avatar
Sven Neumann committed
927
928
      image_type = GIMP_GRAY;
      layer_type = preview ? GIMP_GRAYA_IMAGE : GIMP_GRAY_IMAGE;
Elliot Lee's avatar
Elliot Lee committed
929
      break;
930

Elliot Lee's avatar
Elliot Lee committed
931
    case 3:
Sven Neumann's avatar
Sven Neumann committed
932
933
      image_type = GIMP_RGB;
      layer_type = preview ? GIMP_RGBA_IMAGE : GIMP_RGB_IMAGE;
Elliot Lee's avatar
Elliot Lee committed
934
      break;
935

936
937
    case 4:
      if (cinfo.out_color_space == JCS_CMYK)
Sven Neumann's avatar
Sven Neumann committed
938
939
940
941
942
        {
          image_type = GIMP_RGB;
          layer_type = GIMP_RGB_IMAGE;
          break;
        }
943
944
      /*fallthrough*/

Elliot Lee's avatar
Elliot Lee committed
945
    default:
946
947
948
      g_message ("Don't know how to load JPEGs\n"
                 "with %d color channels\n"
                 "using colorspace %d (%d)",
Sven Neumann's avatar
Sven Neumann committed
949
950
                 cinfo.output_components, cinfo.out_color_space,
                 cinfo.jpeg_color_space);
Elliot Lee's avatar
Elliot Lee committed
951
      gimp_quit ();
952
      break;
Elliot Lee's avatar
Elliot Lee committed
953
954
    }

955
956
  if (preview)
    padded_buf = g_new (guchar, tile_height * cinfo.output_width *
Sven Neumann's avatar
Sven Neumann committed
957
                        (cinfo.output_components + 1));
958
959
960
961
962
  else if (cinfo.out_color_space == JCS_CMYK)
    padded_buf = g_new (guchar, tile_height * cinfo.output_width * 3);
  else
    padded_buf = NULL;

963
  if (preview)
Sven Neumann's avatar
Sven Neumann committed
964
965
    {
      image_ID = image_ID_global;
966
967
    }
  else
Sven Neumann's avatar
Sven Neumann committed
968
    {
969
      image_ID = gimp_image_new (cinfo.output_width, cinfo.output_height,
Sven Neumann's avatar
Sven Neumann committed
970
                                 image_type);
Sven Neumann's avatar
Sven Neumann committed
971
972
      gimp_image_set_filename (image_ID, filename);
    }
973

974
  if (preview)
Sven Neumann's avatar
Sven Neumann committed
975
    {
976
      layer_ID_global = layer_ID =
Sven Neumann's avatar
Sven Neumann committed
977
978
979
980
        gimp_layer_new (image_ID, _("JPEG preview"),
                        cinfo.output_width,
                        cinfo.output_height,
                        layer_type, 100, GIMP_NORMAL_MODE);
981
    }
982
  else
Sven Neumann's avatar
Sven Neumann committed
983
984
    {
      layer_ID = gimp_layer_new (image_ID, _("Background"),
Sven Neumann's avatar
Sven Neumann committed
985
986
987
                                 cinfo.output_width,
                                 cinfo.output_height,
                                 layer_type, 100, GIMP_NORMAL_MODE);
Sven Neumann's avatar
Sven Neumann committed
988
    }
Elliot Lee's avatar
Elliot Lee committed
989

990
  drawable_global = drawable = gimp_drawable_get (layer_ID);
991
  gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0,
Sven Neumann's avatar
Sven Neumann committed
992
                       drawable->width, drawable->height, TRUE, FALSE);
Elliot Lee's avatar
Elliot Lee committed
993

994
  /* Step 5.1: if the file had resolution information, set it on the image */
995
  if (!preview && cinfo.saw_JFIF_marker)
996
997
998
999
    {
      gdouble xresolution;
      gdouble yresolution;
      gdouble asymmetry;
1000

1001
1002
      xresolution = cinfo.X_density;
      yresolution = cinfo.Y_density;
1003

1004
      switch (cinfo.density_unit)
Sven Neumann's avatar
Sven Neumann committed
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
        {
        case 0: /* unknown -> set the aspect ratio but use the default
                *  image resolution
                */
          if (cinfo.Y_density != 0)
            asymmetry = xresolution / yresolution;
          else
            asymmetry = 1.0;

          gimp_image_get_resolution (image_ID, &xresolution, &yresolution);
          xresolution *= asymmetry;
          break;

        case 1: /* dots per inch */
          break;

        case 2: /* dots per cm */
          xresolution *= 2.54;
          yresolution *= 2.54;
          gimp_image_set_unit (image_ID, GIMP_UNIT_MM);
          break;

        default:
          g_message ("Unknown density unit %d\nassuming dots per inch",
                     cinfo.density_unit);
          break;
        }
1032
1033
1034

      gimp_image_set_resolution (image_ID, xresolution, yresolution);
    }
1035

Elliot Lee's avatar
Elliot Lee committed
1036
1037
1038
1039
1040
1041
1042
1043
1044
  /* Step 6: while (scan lines remain to be read) */
  /*           jpeg_read_scanlines(...); */

  /* Here we use the library's state variable cinfo.output_scanline as the
   * loop counter, so that we don't have to keep track ourselves.
   */
  while (cinfo.output_scanline < cinfo.output_height)
    {
      start = cinfo.output_scanline;
1045
1046
      end   = cinfo.output_scanline + tile_height;
      end   = MIN (end, cinfo.output_height);
Elliot Lee's avatar
Elliot Lee committed
1047
1048
1049
      scanlines = end - start;

      for (i = 0; i < scanlines; i++)
Sven Neumann's avatar
Sven Neumann committed
1050
        jpeg_read_scanlines (&cinfo, (JSAMPARRAY) &rowbuf[i], 1);
Elliot Lee's avatar
Elliot Lee committed
1051

1052
      if (preview) /* Add a dummy alpha channel -- convert buf to padded_buf */
Sven Neumann's avatar
Sven Neumann committed
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
        {
          guchar *dest = padded_buf;
          guchar *src  = buf;
          gint    num  = drawable->width * scanlines;

          switch (cinfo.output_components)
            {
            case 1:
              for (i = 0; i < num; i++)
                {
                  *(dest++) = *(src++);
                  *(dest++) = 255;
                }
              break;

            case 3:
              for (i = 0; i < num; i++)
                {
                  *(dest++) = *(src++);
                  *(dest++) = *(src++);
                  *(dest++) = *(src++);
                  *(dest++) = 255;
                }
              break;

            default:
              g_warning ("JPEG - shouldn't have gotten here.\nReport to http://bugzilla.gnome.org/");
              break;
            }
        }
1083
      else if (cinfo.out_color_space == JCS_CMYK) /* buf-> RGB in padded_buf */
Sven Neumann's avatar
Sven Neumann committed
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
        {
          guchar *dest = padded_buf;
          guchar *src  = buf;
          gint    num  = drawable->width * scanlines;

          for (i = 0; i < num; i++)
            {
              guint r_c, g_m, b_y, a_k;

              r_c = *(src++);
              g_m = *(src++);
              b_y = *(src++);
              a_k = *(src++);
              *(dest++) = (r_c * a_k) / 255;
              *(dest++) = (g_m * a_k) / 255;
              *(dest++) = (b_y * a_k) / 255;
            }
        }
1102
1103

      gimp_pixel_rgn_set_rect (&pixel_rgn, padded_buf ? padded_buf : buf,
Sven Neumann's avatar
Sven Neumann committed
1104
                               0, start, drawable->width, scanlines);
Elliot Lee's avatar
Elliot Lee committed
1105

1106
1107
1108
      if (! preview)
        gimp_progress_update ((gdouble) cinfo.output_scanline /
                              (gdouble) cinfo.output_height);
Elliot Lee's avatar
Elliot Lee committed
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
    }

  /* Step 7: Finish decompression */

  jpeg_finish_decompress (&cinfo);
  /* We can ignore the return value since suspension is not possible
   * with the stdio data source.
   */

  /* Step 8: Release JPEG decompression object */

  /* This is an important step since it will release a good deal of memory. */
  jpeg_destroy_decompress (&cinfo);

  /* free up the temporary buffers */
  g_free (rowbuf);
  g_free (buf);
1126
  g_free (padded_buf);
Elliot Lee's avatar
Elliot Lee committed
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140

  /* After finish_decompress, we can close the input file.
   * Here we postpone it until after no more JPEG errors are possible,
   * so as to simplify the setjmp error logic above.  (Actually, I don't
   * think that jpeg_destroy can do an error exit, but why assume anything...)
   */
  fclose (infile);

  /* At this point you may want to check to see whether any corrupt-data
   * warnings occurred (test whether jerr.num_warnings is nonzero).
   */

  /* Tell the GIMP to display the image.
   */
BST 1999 Andy Thomas's avatar
BST 1999 Andy Thomas committed
1141
  gimp_image_add_layer (image_ID, layer_ID, 0);
Elliot Lee's avatar
Elliot Lee committed
1142
1143
  gimp_drawable_flush (drawable);

1144
1145
  /* pw - Last of all, attach the parasites (couldn't do it earlier -
     there was no image. */
Sven Neumann's avatar
Sven Neumann committed
1146

1147
  if (!preview)
Sven Neumann's avatar
Sven Neumann committed
1148
1149
    {
      if (comment_parasite)
Sven Neumann's avatar
Sven Neumann committed
1150
1151
1152
        {
          gimp_image_parasite_attach (image_ID, comment_parasite);
          gimp_parasite_free (comment_parasite);
1153
1154

          comment_parasite = NULL;
Sven Neumann's avatar
Sven Neumann committed
1155
        }
1156
1157

#ifdef HAVE_EXIF
1158
1159
#define EXIF_HEADER_SIZE 8

1160
      if (! GPOINTER_TO_INT (cinfo.client_data))
Sven Neumann's avatar
Sven Neumann committed
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
        {
          exif_data = exif_data_new_from_file (filename);
          if (exif_data)
            {
              guchar *exif_buf;
              guint   exif_buf_len;

              exif_data_save_data (exif_data, &exif_buf, &exif_buf_len);
              exif_data_unref (exif_data);

              if (exif_buf_len > EXIF_HEADER_SIZE)
                {
                  exif_parasite = gimp_parasite_new ("exif-data",
                                                     GIMP_PARASITE_PERSISTENT,
                                                     exif_buf_len, exif_buf);
                  gimp_image_parasite_attach (image_ID, exif_parasite);
                  gimp_parasite_free (exif_parasite);
                }

              free (exif_buf);
            }
        }
1183
#endif
1184
    }
1185

Elliot Lee's avatar
Elliot Lee committed
1186
1187
1188
  return image_ID;
}

1189
1190
1191
1192
/*
 * sg - This is the best I can do, I'm afraid... I think it will fail
 * if something bad really happens (but it might not). If you have a
 * better solution, send it ;-)
1193
 */
1194
1195
1196
static void
background_error_exit (j_common_ptr cinfo)
{
1197
  if (abort_me)
Sven Neumann's avatar
Sven Neumann committed
1198
    *abort_me = TRUE;
1199
1200
1201
  (*cinfo->err->output_message) (cinfo);
}

1202
static gboolean
Sven Neumann's avatar
Sven Neumann committed
1203
background_jpeg_save (PreviewPersistent *pp)
1204
1205
1206
{
  guchar *t;
  guchar *s;
1207
1208
  gint    i, j;
  gint    yend;
1209

1210
1211
1212
1213
  if (pp->abort_me || (pp->cinfo.next_scanline >= pp->cinfo.image_height))
    {
      /* clean up... */
      if (pp->abort_me)
Sven Neumann's avatar
Sven Neumann committed
1214
1215
1216
        {
          jpeg_abort_compress (&(pp->cinfo));
        }
1217
      else
Sven Neumann's avatar
Sven Neumann committed
1218
1219
1220
        {
          jpeg_finish_compress (&(pp->cinfo));
        }
1221

1222
1223
      fclose (pp->outfile);
      jpeg_destroy_compress (&(pp->cinfo));
1224

1225
1226
      g_free (pp->temp);
      g_free (pp->data);
1227

1228
      if (pp->drawable)
Sven Neumann's avatar
Sven Neumann committed
1229
        gimp_drawable_detach (pp->drawable);
1230

1231
      /* display the preview stuff */
1232
      if (!pp->abort_me)
Sven Neumann's avatar
Sven Neumann committed
1233
1234
1235
        {
          struct stat buf;
          gchar       temp[128];
1236

Sven Neumann's avatar
Sven Neumann committed
1237
1238
1239
1240
1241
          stat (pp->file_name, &buf);
          g_snprintf (temp, sizeof (temp),
                      _("File size: %02.01f kB"),
                      (gdouble) (buf.st_size) / 1024.0);
          gtk_label_set_text (GTK_LABEL (preview_size), temp);
1242

Sven Neumann's avatar
Sven Neumann committed
1243
1244
1245
          /* and load the preview */
          load_image (pp->file_name, GIMP_RUN_NONINTERACTIVE, TRUE);
        }