~ubuntu-branches/ubuntu/jaunty/gimp/jaunty-security

« back to all changes in this revision

Viewing changes to plug-ins/common/jpeg.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2007-05-02 16:33:03 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070502163303-bvzhjzbpw8qglc4y
Tags: 2.3.16-1ubuntu1
* Resynchronized with Debian, remaining Ubuntu changes:
  - debian/rules: i18n magic.
* debian/control.in:
  - Maintainer: Ubuntu Core Developers <ubuntu-devel@lists.ubuntu.com>
* debian/patches/02_help-message.patch,
  debian/patches/03_gimp.desktop.in.in.patch,
  debian/patches/10_dont_show_wizard.patch: updated.
* debian/patches/04_composite-signedness.patch,
  debian/patches/05_add-letter-spacing.patch: dropped, used upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* The GIMP -- an image manipulation program
2
 
 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3
 
 *
4
 
 * This program is free software; you can redistribute it and/or modify
5
 
 * it under the terms of the GNU General Public License as published by
6
 
 * the Free Software Foundation; either version 2 of the License, or
7
 
 * (at your option) any later version.
8
 
 *
9
 
 * This program is distributed in the hope that it will be useful,
10
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
 * GNU General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU General Public License
15
 
 * along with this program; if not, write to the Free Software
16
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
 
 */
18
 
 
19
 
/* JPEG loading and saving file filter for the GIMP
20
 
 *  -Peter Mattis
21
 
 *
22
 
 * This filter is heavily based upon the "example.c" file in libjpeg.
23
 
 * In fact most of the loading and saving code was simply cut-and-pasted
24
 
 *  from that file. The filter, therefore, also uses libjpeg.
25
 
 */
26
 
 
27
 
/* 11-JAN-99 - Added support for JPEG comments and Progressive saves.
28
 
 *  -pete whiting <pwhiting@sprint.net>
29
 
 *
30
 
 * Comments of size up to 32k can be stored in the header of jpeg
31
 
 * files.  (They are not compressed.)  The JPEG specs and libraries
32
 
 * support the storing of multiple comments.  The behavior of this
33
 
 * code is to merge all comments in a loading image into a single
34
 
 * comment (putting \n between each) and attach that string as a
35
 
 * parasite - gimp-comment - to the image.  When saving, the image is
36
 
 * checked to see if it has the gimp-comment parasite - if so, that is
37
 
 * used as the default comment in the save dialog.  Further, the other
38
 
 * jpeg parameters (quality, smoothing, compression and progressive)
39
 
 * are attached to the image as a parasite.  This allows the
40
 
 * parameters to remain consistent between saves.  I was not able to
41
 
 * figure out how to determine the quality, smoothing or compression
42
 
 * values of an image as it is being loaded, but the code is there to
43
 
 * support it if anyone knows how.  Progressive mode is a method of
44
 
 * saving the image such that as a browser (or other app supporting
45
 
 * progressive loads - gimp doesn't) loads the image it first gets a
46
 
 * low res version displayed and then the image is progressively
47
 
 * enhanced until you get the final version.  It doesn't add any size
48
 
 * to the image (actually it often results in smaller file size) - the
49
 
 * only draw backs are that progressive jpegs are not supported by some
50
 
 * older viewers/browsers, and some might find it annoying.
51
 
 */
52
 
 
53
 
/*
54
 
 * 21-AUG-99 - Added support for JPEG previews, subsampling,
55
 
 *             non-baseline JPEGs, restart markers and DCT method choice
56
 
 * - Steinar H. Gunderson <sgunderson@bigfoot.com>
57
 
 *
58
 
 * A small preview appears and changes according to the changes to the
59
 
 * compression options. The image itself works as a much bigger preview.
60
 
 * For slower machines, the save operation (not the load operation) is
61
 
 * done in the background, with a standard GTK+ idle loop, which turned
62
 
 * out to be the most portable way. Win32 porters shouldn't have much
63
 
 * difficulty porting my changes (at least I hope so...).
64
 
 *
65
 
 * Subsampling is a pretty obscure feature, but I thought it might be nice
66
 
 * to have it in anyway, for people to play with :-) Does anybody have
67
 
 * any better suggestions than the ones I've put in the menu? (See wizard.doc
68
 
 * from the libjpeg distribution for a tiny bit of information on subsampling.)
69
 
 *
70
 
 * A baseline JPEG is often larger and/or of worse quality than a non-baseline
71
 
 * one (especially at low quality settings), but all decoders are guaranteed
72
 
 * to read baseline JPEGs (I think). Not all will read a non-baseline one.
73
 
 *
74
 
 * Restart markers are useful if you are transmitting the image over an
75
 
 * unreliable network. If a file gets corrupted, it will only be corrupted
76
 
 * up to the next restart marker. Of course, if there are no restart markers,
77
 
 * the rest of the image will be corrupted. Restart markers take up extra
78
 
 * space. The libjpeg developers recommend a restart every 1 row for
79
 
 * transmitting images over unreliable networks, such as Usenet.
80
 
 *
81
 
 * The DCT method is said by the libjpeg docs to _only_ influence quality vs.
82
 
 * speed, and nothing else. However, I've found that there _are_ size
83
 
 * differences. Fast integer, on the other hand, is faster than integer,
84
 
 * which in turn is faster than FP. According to the libjpeg docs (and I
85
 
 * believe it's true), FP has only a theoretical advantage in quality, and
86
 
 * will be slower than the two other methods, unless you're blessed with
87
 
 * very a fast FPU. (In addition, images might not be identical on
88
 
 * different types of FP hardware.)
89
 
 *
90
 
 * ...and thus ends my additions to the JPEG plug-in. I hope. *sigh* :-)
91
 
 */
92
 
 
93
 
/*
94
 
 * 21-AUG-99 - Bunch O' Fixes.
95
 
 * - Adam D. Moss <adam@gimp.org>
96
 
 *
97
 
 * We now correctly create an alpha-padded layer for our preview --
98
 
 * having a non-background non-alpha layer is a no-no in GIMP.
99
 
 *
100
 
 * I've also tweaked the GIMP undo API a little and changed the JPEG
101
 
 * plugin to use gimp_image_{freeze,thaw}_undo so that it doesn't store
102
 
 * up a whole load of superfluous tile data every time the preview is
103
 
 * changed.
104
 
 */
105
 
 
106
 
/*
107
 
 * 22-DEC-99 - volatiles added
108
 
 * - Austin Donnelly <austin@gimp.org>
109
 
 *
110
 
 * When gcc complains a variable may be clobbered by a longjmp or
111
 
 * vfork, it means the following: setjmp() was called by the JPEG
112
 
 * library for error recovery purposes, but gcc is keeping some
113
 
 * variables in registers without updating the memory locations on the
114
 
 * stack consistently.  If JPEG error recovery is every invoked, the
115
 
 * values of these variable will be inconsistent.  This is almost
116
 
 * always a bug, but not one that's commonly seen unless JPEG recovery
117
 
 * code is exercised frequently.  The correct solution is to tell gcc
118
 
 * to keep the stack version of the affected variables up to date, by
119
 
 * using the "volatile" keyword.   Here endeth the lesson.
120
 
 */
121
 
 
122
 
/*
123
 
 * 4-SEP-01 - remove the use of GtkText
124
 
 * - DindinX <David@dindinx.org>
125
 
 *
126
 
 * The new version of GTK+ does not support GtkText anymore.
127
 
 * I've just replaced the one used for the image comment by
128
 
 * a GtkTextView/GtkTextBuffer couple;
129
 
 */
130
 
 
131
 
/*
132
 
 * 22-JUN-03 - add support for keeping EXIF information
133
 
 * - Dave Neary <bolsh@gimp.org>
134
 
 *
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
 
 * a GimpImage, and if there is infoprmation available at save
138
 
 * time, writes it out. No modification of the exif data is
139
 
 * currently possible.
140
 
 */
141
 
 
142
 
/*
143
 
 * 15-NOV-04 - add support for EXIF JPEG thumbnail reading and writing
144
 
 * - S. Mukund <muks@mukund.org>
145
 
 *
146
 
 * Digital cameras store a TIFF APP1 marker that contains various
147
 
 * parameters of the shot along with a thumbnail image.
148
 
 */
149
 
 
150
 
/*
151
 
 * 14-JAN-05 - avoid to write more than 65533 bytes of EXIF marker length
152
 
 * - Nils Philippsen <nphilipp@redhat.com>
153
 
 *
154
 
 * When writing thumbnails with high quality settings, EXIF marker length could
155
 
 * get more than 65533 (sanity checking in libjpeg). Gradually decrease
156
 
 * thumbnail quality (in steps of 5) until it fits.
157
 
 */
158
 
 
159
 
#include "config.h"   /* configure cares about HAVE_PROGRESSIVE_JPEG */
160
 
 
161
 
#include <glib.h>     /* We want glib.h first because of some
162
 
                       * pretty obscure Win32 compilation issues.
163
 
                       */
164
 
#include <errno.h>
165
 
#include <setjmp.h>
166
 
#include <signal.h>
167
 
#include <stdio.h>
168
 
#include <stdlib.h>
169
 
#include <string.h>
170
 
#include <sys/types.h>
171
 
#include <sys/stat.h>
172
 
#ifdef HAVE_UNISTD_H
173
 
#include <unistd.h>
174
 
#endif
175
 
#include <jpeglib.h>
176
 
#include <jerror.h>
177
 
 
178
 
#ifdef HAVE_EXIF
179
 
#include <libexif/exif-data.h>
180
 
 
181
 
#define MARKER_CODE_EXIF 0xE1
182
 
#endif /* HAVE_EXIF */
183
 
 
184
 
#include <libgimp/gimp.h>
185
 
#include <libgimp/gimpui.h>
186
 
 
187
 
#include "libgimp/stdplugins-intl.h"
188
 
 
189
 
#define SCALE_WIDTH         125
190
 
 
191
 
/* if you are not compiling this from inside the gimp tree, you have to  */
192
 
/* take care yourself if your JPEG library supports progressive mode     */
193
 
/* #undef HAVE_PROGRESSIVE_JPEG   if your library doesn't support it     */
194
 
/* #define HAVE_PROGRESSIVE_JPEG  if your library knows how to handle it */
195
 
 
196
 
/* See bugs #63610 and #61088 for a discussion about the quality settings */
197
 
#define DEFAULT_QUALITY     85.0
198
 
#define DEFAULT_SMOOTHING   0.0
199
 
#define DEFAULT_OPTIMIZE    TRUE
200
 
#define DEFAULT_PROGRESSIVE FALSE
201
 
#define DEFAULT_BASELINE    TRUE
202
 
#define DEFAULT_SUBSMP      0
203
 
#define DEFAULT_RESTART     0
204
 
#define DEFAULT_DCT         0
205
 
#define DEFAULT_PREVIEW     FALSE
206
 
#define DEFAULT_EXIF        TRUE
207
 
#define DEFAULT_THUMBNAIL   FALSE
208
 
 
209
 
/* sg - these should not be global... */
210
 
static  gint32 volatile  image_ID_global       = -1;
211
 
static  gint32           orig_image_ID_global  = -1;
212
 
static  gint32           drawable_ID_global    = -1;
213
 
static  gint32           layer_ID_global       = -1;
214
 
static  GtkWidget       *preview_size          = NULL;
215
 
static  GimpDrawable    *drawable_global       = NULL;
216
 
static  gboolean         undo_touched          = FALSE;
217
 
static  gint32           display_ID            = 0;
218
 
 
219
 
 
220
 
typedef struct
221
 
{
222
 
  gdouble  quality;
223
 
  gdouble  smoothing;
224
 
  gboolean optimize;
225
 
  gboolean progressive;
226
 
  gboolean baseline;
227
 
  gint     subsmp;
228
 
  gint     restart;
229
 
  gint     dct;
230
 
  gboolean preview;
231
 
  gboolean save_exif;
232
 
  gboolean save_thumbnail;
233
 
} JpegSaveVals;
234
 
 
235
 
typedef struct
236
 
{
237
 
  struct jpeg_compress_struct cinfo;
238
 
  struct jpeg_error_mgr jerr;
239
 
  gint          tile_height;
240
 
  FILE         *outfile;
241
 
  gboolean      has_alpha;
242
 
  gint          rowstride;
243
 
  guchar       *temp;
244
 
  guchar       *data;
245
 
  guchar       *src;
246
 
  GimpDrawable *drawable;
247
 
  GimpPixelRgn  pixel_rgn;
248
 
  const gchar  *file_name;
249
 
  gboolean      abort_me;
250
 
} PreviewPersistent;
251
 
 
252
 
static gboolean *abort_me = NULL;
253
 
 
254
 
 
255
 
/* Declare local functions.
256
 
 */
257
 
static void      query               (void);
258
 
static void      run                 (const gchar      *name,
259
 
                                      gint              nparams,
260
 
                                      const GimpParam  *param,
261
 
                                      gint             *nreturn_vals,
262
 
                                      GimpParam       **return_vals);
263
 
static gint32    load_image          (const gchar      *filename,
264
 
                                      GimpRunMode       runmode,
265
 
                                      gboolean          preview);
266
 
#ifdef HAVE_EXIF
267
 
 
268
 
static gint32    load_thumbnail_image(const gchar      *filename,
269
 
                                      gint             *width,
270
 
                                      gint             *height);
271
 
 
272
 
static gint      create_thumbnail    (gint32            image_ID,
273
 
                                      gint32            drawable_ID,
274
 
                                      gdouble           quality,
275
 
                                      gchar           **thumbnail_buffer);
276
 
 
277
 
#endif /* HAVE_EXIF */
278
 
 
279
 
static gboolean  save_image          (const gchar      *filename,
280
 
                                      gint32            image_ID,
281
 
                                      gint32            drawable_ID,
282
 
                                      gint32            orig_image_ID,
283
 
                                      gboolean          preview);
284
 
 
285
 
static gboolean  save_dialog         (void);
286
 
 
287
 
static void      make_preview        (void);
288
 
static void      destroy_preview     (void);
289
 
 
290
 
static void      save_restart_update (GtkAdjustment    *adjustment,
291
 
                                      GtkWidget        *toggle);
292
 
 
293
 
 
294
 
GimpPlugInInfo PLUG_IN_INFO =
295
 
{
296
 
  NULL,  /* init_proc  */
297
 
  NULL,  /* quit_proc  */
298
 
  query, /* query_proc */
299
 
  run,   /* run_proc   */
300
 
};
301
 
 
302
 
static JpegSaveVals jsvals =
303
 
{
304
 
  DEFAULT_QUALITY,
305
 
  DEFAULT_SMOOTHING,
306
 
  DEFAULT_OPTIMIZE,
307
 
  DEFAULT_PROGRESSIVE,
308
 
  DEFAULT_BASELINE,
309
 
  DEFAULT_SUBSMP,
310
 
  DEFAULT_RESTART,
311
 
  DEFAULT_DCT,
312
 
  DEFAULT_PREVIEW,
313
 
  DEFAULT_EXIF,
314
 
  DEFAULT_THUMBNAIL
315
 
};
316
 
 
317
 
 
318
 
static gchar     *image_comment         = NULL;
319
 
static GtkWidget *restart_markers_scale = NULL;
320
 
static GtkWidget *restart_markers_label = NULL;
321
 
 
322
 
#ifdef HAVE_EXIF
323
 
static ExifData  *exif_data             = NULL;
324
 
#endif /* HAVE_EXIF */
325
 
 
326
 
 
327
 
MAIN ()
328
 
 
329
 
 
330
 
static void
331
 
query (void)
332
 
{
333
 
  static GimpParamDef load_args[] =
334
 
  {
335
 
    { GIMP_PDB_INT32,    "run_mode",     "Interactive, non-interactive" },
336
 
    { GIMP_PDB_STRING,   "filename",     "The name of the file to load" },
337
 
    { GIMP_PDB_STRING,   "raw_filename", "The name of the file to load" }
338
 
  };
339
 
  static GimpParamDef load_return_vals[] =
340
 
  {
341
 
    { GIMP_PDB_IMAGE,   "image",         "Output image" }
342
 
  };
343
 
 
344
 
#ifdef HAVE_EXIF
345
 
 
346
 
  static GimpParamDef thumb_args[] =
347
 
  {
348
 
    { GIMP_PDB_STRING, "filename",     "The name of the file to load"  },
349
 
    { GIMP_PDB_INT32,  "thumb_size",   "Preferred thumbnail size"      }
350
 
  };
351
 
  static GimpParamDef thumb_return_vals[] =
352
 
  {
353
 
    { GIMP_PDB_IMAGE,  "image",        "Thumbnail image"               },
354
 
    { GIMP_PDB_INT32,  "image_width",  "Width of full-sized image"     },
355
 
    { GIMP_PDB_INT32,  "image_height", "Height of full-sized image"    }
356
 
  };
357
 
 
358
 
#endif /* HAVE_EXIF */
359
 
 
360
 
  static GimpParamDef save_args[] =
361
 
  {
362
 
    { GIMP_PDB_INT32,    "run_mode",     "Interactive, non-interactive" },
363
 
    { GIMP_PDB_IMAGE,    "image",        "Input image" },
364
 
    { GIMP_PDB_DRAWABLE, "drawable",     "Drawable to save" },
365
 
    { GIMP_PDB_STRING,   "filename",     "The name of the file to save the image in" },
366
 
    { GIMP_PDB_STRING,   "raw_filename", "The name of the file to save the image in" },
367
 
    { GIMP_PDB_FLOAT,    "quality",      "Quality of saved image (0 <= quality <= 1)" },
368
 
    { GIMP_PDB_FLOAT,    "smoothing",    "Smoothing factor for saved image (0 <= smoothing <= 1)" },
369
 
    { GIMP_PDB_INT32,    "optimize",     "Optimization of entropy encoding parameters (0/1)" },
370
 
    { GIMP_PDB_INT32,    "progressive",  "Enable progressive jpeg image loading - ignored if not compiled with HAVE_PROGRESSIVE_JPEG (0/1)" },
371
 
    { GIMP_PDB_STRING,   "comment",      "Image comment" },
372
 
    { GIMP_PDB_INT32,    "subsmp",       "The subsampling option number" },
373
 
    { GIMP_PDB_INT32,    "baseline",     "Force creation of a baseline JPEG (non-baseline JPEGs can't be read by all decoders) (0/1)" },
374
 
    { GIMP_PDB_INT32,    "restart",      "Frequency of restart markers (in rows, 0 = no restart markers)" },
375
 
    { GIMP_PDB_INT32,    "dct",          "DCT algorithm to use (speed/quality tradeoff)" }
376
 
  };
377
 
 
378
 
  gimp_install_procedure ("file_jpeg_load",
379
 
                          "loads files in the JPEG file format",
380
 
                          "loads files in the JPEG file format",
381
 
                          "Spencer Kimball, Peter Mattis & others",
382
 
                          "Spencer Kimball & Peter Mattis",
383
 
                          "1995-1999",
384
 
                          N_("JPEG image"),
385
 
                          NULL,
386
 
                          GIMP_PLUGIN,
387
 
                          G_N_ELEMENTS (load_args),
388
 
                          G_N_ELEMENTS (load_return_vals),
389
 
                          load_args, load_return_vals);
390
 
 
391
 
  gimp_register_file_handler_mime ("file_jpeg_load", "image/jpeg");
392
 
  gimp_register_magic_load_handler ("file_jpeg_load",
393
 
                                    "jpg,jpeg,jpe",
394
 
                                    "",
395
 
                                    "6,string,JFIF,6,string,Exif");
396
 
 
397
 
#ifdef HAVE_EXIF
398
 
 
399
 
  gimp_install_procedure ("file_jpeg_load_thumb",
400
 
                          "Loads a thumbnail from a JPEG image",
401
 
                          "Loads a thumbnail from a JPEG image (only if it exists)",
402
 
                          "S. Mukund <muks@mukund.org>, Sven Neumann <sven@gimp.org>",
403
 
                          "S. Mukund <muks@mukund.org>, Sven Neumann <sven@gimp.org>",
404
 
                          "November 15, 2004",
405
 
                          NULL,
406
 
                          NULL,
407
 
                          GIMP_PLUGIN,
408
 
                          G_N_ELEMENTS (thumb_args),
409
 
                          G_N_ELEMENTS (thumb_return_vals),
410
 
                          thumb_args, thumb_return_vals);
411
 
 
412
 
  gimp_register_thumbnail_loader ("file_jpeg_load", "file_jpeg_load_thumb");
413
 
 
414
 
#endif /* HAVE_EXIF */
415
 
 
416
 
  gimp_install_procedure ("file_jpeg_save",
417
 
                          "saves files in the JPEG file format",
418
 
                          "saves files in the lossy, widely supported JPEG format",
419
 
                          "Spencer Kimball, Peter Mattis & others",
420
 
                          "Spencer Kimball & Peter Mattis",
421
 
                          "1995-1999",
422
 
                          N_("JPEG image"),
423
 
                          "RGB*, GRAY*",
424
 
                          GIMP_PLUGIN,
425
 
                          G_N_ELEMENTS (save_args), 0,
426
 
                          save_args, NULL);
427
 
 
428
 
  gimp_register_file_handler_mime ("file_jpeg_save", "image/jpeg");
429
 
  gimp_register_save_handler ("file_jpeg_save", "jpg,jpeg,jpe", "");
430
 
}
431
 
 
432
 
static void
433
 
run (const gchar      *name,
434
 
     gint              nparams,
435
 
     const GimpParam  *param,
436
 
     gint             *nreturn_vals,
437
 
     GimpParam       **return_vals)
438
 
{
439
 
  static GimpParam   values[4];
440
 
  GimpRunMode        run_mode;
441
 
  GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
442
 
  gint32             image_ID;
443
 
  gint32             drawable_ID;
444
 
  gint32             orig_image_ID;
445
 
  GimpParasite      *parasite;
446
 
  gboolean           err;
447
 
  GimpExportReturn   export = GIMP_EXPORT_CANCEL;
448
 
 
449
 
  run_mode = param[0].data.d_int32;
450
 
 
451
 
  INIT_I18N ();
452
 
 
453
 
  *nreturn_vals = 1;
454
 
  *return_vals  = values;
455
 
  values[0].type          = GIMP_PDB_STATUS;
456
 
  values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
457
 
 
458
 
  if (strcmp (name, "file_jpeg_load") == 0)
459
 
    {
460
 
      image_ID = load_image (param[1].data.d_string, run_mode, FALSE);
461
 
 
462
 
      if (image_ID != -1)
463
 
        {
464
 
          *nreturn_vals = 2;
465
 
          values[1].type         = GIMP_PDB_IMAGE;
466
 
          values[1].data.d_image = image_ID;
467
 
        }
468
 
      else
469
 
        {
470
 
          status = GIMP_PDB_EXECUTION_ERROR;
471
 
        }
472
 
    }
473
 
 
474
 
#ifdef HAVE_EXIF
475
 
 
476
 
  else if (strcmp (name, "file_jpeg_load_thumb") == 0)
477
 
    {
478
 
      if (nparams < 2)
479
 
        {
480
 
          status = GIMP_PDB_CALLING_ERROR;
481
 
        }
482
 
      else
483
 
        {
484
 
          const gchar *filename = param[0].data.d_string;
485
 
          gint         width    = 0;
486
 
          gint         height   = 0;
487
 
          gint32       image_ID;
488
 
 
489
 
          image_ID = load_thumbnail_image (filename, &width, &height);
490
 
 
491
 
          if (image_ID != -1)
492
 
            {
493
 
              *nreturn_vals = 4;
494
 
              values[1].type         = GIMP_PDB_IMAGE;
495
 
              values[1].data.d_image = image_ID;
496
 
              values[2].type         = GIMP_PDB_INT32;
497
 
              values[2].data.d_int32 = width;
498
 
              values[3].type         = GIMP_PDB_INT32;
499
 
              values[3].data.d_int32 = height;
500
 
            }
501
 
          else
502
 
            {
503
 
              status = GIMP_PDB_EXECUTION_ERROR;
504
 
            }
505
 
        }
506
 
    }
507
 
 
508
 
#endif /* HAVE_EXIF */
509
 
 
510
 
  else if (strcmp (name, "file_jpeg_save") == 0)
511
 
    {
512
 
      image_ID = orig_image_ID = param[1].data.d_int32;
513
 
      drawable_ID = param[2].data.d_int32;
514
 
 
515
 
       /*  eventually export the image */
516
 
      switch (run_mode)
517
 
        {
518
 
        case GIMP_RUN_INTERACTIVE:
519
 
        case GIMP_RUN_WITH_LAST_VALS:
520
 
          gimp_ui_init ("jpeg", FALSE);
521
 
          export = gimp_export_image (&image_ID, &drawable_ID, "JPEG",
522
 
                                      (GIMP_EXPORT_CAN_HANDLE_RGB |
523
 
                                       GIMP_EXPORT_CAN_HANDLE_GRAY));
524
 
          switch (export)
525
 
            {
526
 
            case GIMP_EXPORT_EXPORT:
527
 
              {
528
 
                gchar *tmp = g_filename_from_utf8 (_("Export Preview"), -1,
529
 
                                                   NULL, NULL, NULL);
530
 
                if (tmp)
531
 
                  {
532
 
                    gimp_image_set_filename (image_ID, tmp);
533
 
                    g_free (tmp);
534
 
                  }
535
 
 
536
 
                display_ID = -1;
537
 
              }
538
 
              break;
539
 
            case GIMP_EXPORT_IGNORE:
540
 
              break;
541
 
            case GIMP_EXPORT_CANCEL:
542
 
              values[0].data.d_status = GIMP_PDB_CANCEL;
543
 
              return;
544
 
              break;
545
 
            }
546
 
          break;
547
 
        default:
548
 
          break;
549
 
        }
550
 
 
551
 
#ifdef HAVE_EXIF
552
 
      exif_data_unref (exif_data);
553
 
      exif_data = NULL;
554
 
#endif /* HAVE_EXIF */
555
 
 
556
 
      g_free (image_comment);
557
 
      image_comment = NULL;
558
 
 
559
 
      parasite = gimp_image_parasite_find (orig_image_ID, "gimp-comment");
560
 
      if (parasite)
561
 
        {
562
 
          image_comment = g_strndup (gimp_parasite_data (parasite),
563
 
                                     gimp_parasite_data_size (parasite));
564
 
          gimp_parasite_free (parasite);
565
 
        }
566
 
 
567
 
#ifdef HAVE_EXIF
568
 
 
569
 
      parasite = gimp_image_parasite_find (orig_image_ID, "exif-data");
570
 
      if (parasite)
571
 
        {
572
 
          exif_data = exif_data_new_from_data (gimp_parasite_data (parasite),
573
 
                                               gimp_parasite_data_size (parasite));
574
 
          gimp_parasite_free (parasite);
575
 
        }
576
 
 
577
 
#endif /* HAVE_EXIF */
578
 
 
579
 
      jsvals.quality        = DEFAULT_QUALITY;
580
 
      jsvals.smoothing      = DEFAULT_SMOOTHING;
581
 
      jsvals.optimize       = DEFAULT_OPTIMIZE;
582
 
      jsvals.progressive    = DEFAULT_PROGRESSIVE;
583
 
      jsvals.baseline       = DEFAULT_BASELINE;
584
 
      jsvals.subsmp         = DEFAULT_SUBSMP;
585
 
      jsvals.restart        = DEFAULT_RESTART;
586
 
      jsvals.dct            = DEFAULT_DCT;
587
 
      jsvals.preview        = DEFAULT_PREVIEW;
588
 
      jsvals.save_exif      = DEFAULT_EXIF;
589
 
      jsvals.save_thumbnail = DEFAULT_THUMBNAIL;
590
 
 
591
 
#ifdef HAVE_EXIF
592
 
 
593
 
      if (exif_data && (exif_data->data))
594
 
        jsvals.save_thumbnail = TRUE;
595
 
 
596
 
#endif /* HAVE_EXIF */
597
 
 
598
 
      switch (run_mode)
599
 
        {
600
 
        case GIMP_RUN_INTERACTIVE:
601
 
          /*  Possibly retrieve data  */
602
 
          gimp_get_data ("file_jpeg_save", &jsvals);
603
 
 
604
 
          /* load up the previously used values */
605
 
          parasite = gimp_image_parasite_find (orig_image_ID,
606
 
                                               "jpeg-save-options");
607
 
          if (parasite)
608
 
            {
609
 
              const JpegSaveVals *save_vals = gimp_parasite_data (parasite);
610
 
 
611
 
              jsvals.quality        = save_vals->quality;
612
 
              jsvals.smoothing      = save_vals->smoothing;
613
 
              jsvals.optimize       = save_vals->optimize;
614
 
              jsvals.progressive    = save_vals->progressive;
615
 
              jsvals.baseline       = save_vals->baseline;
616
 
              jsvals.subsmp         = save_vals->subsmp;
617
 
              jsvals.restart        = save_vals->restart;
618
 
              jsvals.dct            = save_vals->dct;
619
 
              jsvals.preview        = save_vals->preview;
620
 
              jsvals.save_exif      = save_vals->save_exif;
621
 
              jsvals.save_thumbnail = save_vals->save_thumbnail;
622
 
 
623
 
              gimp_parasite_free (parasite);
624
 
            }
625
 
 
626
 
          if (jsvals.preview)
627
 
            {
628
 
              /* we freeze undo saving so that we can avoid sucking up
629
 
               * tile cache with our unneeded preview steps. */
630
 
              gimp_image_undo_freeze (image_ID);
631
 
 
632
 
              undo_touched = TRUE;
633
 
            }
634
 
 
635
 
          /* prepare for the preview */
636
 
          image_ID_global = image_ID;
637
 
          orig_image_ID_global = orig_image_ID;
638
 
          drawable_ID_global = drawable_ID;
639
 
 
640
 
          /*  First acquire information with a dialog  */
641
 
          err = save_dialog ();
642
 
 
643
 
          if (undo_touched)
644
 
            {
645
 
              /* thaw undo saving and flush the displays to have them
646
 
               * reflect the current shortcuts */
647
 
              gimp_image_undo_thaw (image_ID);
648
 
              gimp_displays_flush ();
649
 
            }
650
 
 
651
 
          if (!err)
652
 
            status = GIMP_PDB_CANCEL;
653
 
          break;
654
 
 
655
 
        case GIMP_RUN_NONINTERACTIVE:
656
 
          /*  Make sure all the arguments are there!  */
657
 
          /*  pw - added two more progressive and comment */
658
 
          /*  sg - added subsampling, preview, baseline, restarts and DCT */
659
 
          if (nparams != 14)
660
 
            {
661
 
              status = GIMP_PDB_CALLING_ERROR;
662
 
            }
663
 
          else
664
 
            {
665
 
              /* Once the PDB gets default parameters, remove this hack */
666
 
              if (param[5].data.d_float > 0.05)
667
 
                {
668
 
                  jsvals.quality     = 100.0 * param[5].data.d_float;
669
 
                  jsvals.smoothing   = param[6].data.d_float;
670
 
                  jsvals.optimize    = param[7].data.d_int32;
671
 
#ifdef HAVE_PROGRESSIVE_JPEG
672
 
                  jsvals.progressive = param[8].data.d_int32;
673
 
#endif /* HAVE_PROGRESSIVE_JPEG */
674
 
                  jsvals.baseline    = param[11].data.d_int32;
675
 
                  jsvals.subsmp      = param[10].data.d_int32;
676
 
                  jsvals.restart     = param[12].data.d_int32;
677
 
                  jsvals.dct         = param[13].data.d_int32;
678
 
 
679
 
                  /* free up the default -- wasted some effort earlier */
680
 
                  g_free (image_comment);
681
 
                  image_comment = g_strdup (param[9].data.d_string);
682
 
                }
683
 
 
684
 
              jsvals.preview = FALSE;
685
 
 
686
 
              if (jsvals.quality < 0.0 || jsvals.quality > 100.0)
687
 
                status = GIMP_PDB_CALLING_ERROR;
688
 
              else if (jsvals.smoothing < 0.0 || jsvals.smoothing > 1.0)
689
 
                status = GIMP_PDB_CALLING_ERROR;
690
 
              else if (jsvals.subsmp < 0 || jsvals.subsmp > 2)
691
 
                status = GIMP_PDB_CALLING_ERROR;
692
 
              else if (jsvals.dct < 0 || jsvals.dct > 2)
693
 
                status = GIMP_PDB_CALLING_ERROR;
694
 
            }
695
 
          break;
696
 
 
697
 
        case GIMP_RUN_WITH_LAST_VALS:
698
 
          /*  Possibly retrieve data  */
699
 
          gimp_get_data ("file_jpeg_save", &jsvals);
700
 
 
701
 
          parasite = gimp_image_parasite_find (orig_image_ID,
702
 
                                               "jpeg-save-options");
703
 
          if (parasite)
704
 
            {
705
 
              const JpegSaveVals *save_vals = gimp_parasite_data (parasite);
706
 
 
707
 
              jsvals.quality     = save_vals->quality;
708
 
              jsvals.smoothing   = save_vals->smoothing;
709
 
              jsvals.optimize    = save_vals->optimize;
710
 
              jsvals.progressive = save_vals->progressive;
711
 
              jsvals.baseline    = save_vals->baseline;
712
 
              jsvals.subsmp      = save_vals->subsmp;
713
 
              jsvals.restart     = save_vals->restart;
714
 
              jsvals.dct         = save_vals->dct;
715
 
              jsvals.preview     = FALSE;
716
 
 
717
 
              gimp_parasite_free (parasite);
718
 
            }
719
 
          break;
720
 
 
721
 
        default:
722
 
          break;
723
 
        }
724
 
 
725
 
      if (status == GIMP_PDB_SUCCESS)
726
 
        {
727
 
          if (save_image (param[3].data.d_string,
728
 
                          image_ID,
729
 
                          drawable_ID,
730
 
                          orig_image_ID,
731
 
                          FALSE))
732
 
            {
733
 
              /*  Store mvals data  */
734
 
              gimp_set_data ("file_jpeg_save", &jsvals, sizeof (JpegSaveVals));
735
 
            }
736
 
          else
737
 
            {
738
 
              status = GIMP_PDB_EXECUTION_ERROR;
739
 
            }
740
 
        }
741
 
 
742
 
      if (export == GIMP_EXPORT_EXPORT)
743
 
        {
744
 
          /* If the image was exported, delete the new display. */
745
 
          /* This also deletes the image.                       */
746
 
 
747
 
          if (display_ID != -1)
748
 
            gimp_display_delete (display_ID);
749
 
          else
750
 
            gimp_image_delete (image_ID);
751
 
        }
752
 
 
753
 
      /* pw - now we need to change the defaults to be whatever
754
 
       * was used to save this image.  Dump the old parasites
755
 
       * and add new ones. */
756
 
 
757
 
      gimp_image_parasite_detach (orig_image_ID, "gimp-comment");
758
 
      if (image_comment && strlen (image_comment))
759
 
        {
760
 
          parasite = gimp_parasite_new ("gimp-comment",
761
 
                                        GIMP_PARASITE_PERSISTENT,
762
 
                                        strlen (image_comment) + 1,
763
 
                                        image_comment);
764
 
          gimp_image_parasite_attach (orig_image_ID, parasite);
765
 
          gimp_parasite_free (parasite);
766
 
        }
767
 
      gimp_image_parasite_detach (orig_image_ID, "jpeg-save-options");
768
 
 
769
 
      parasite = gimp_parasite_new ("jpeg-save-options",
770
 
                                    0, sizeof (jsvals), &jsvals);
771
 
      gimp_image_parasite_attach (orig_image_ID, parasite);
772
 
      gimp_parasite_free (parasite);
773
 
    }
774
 
  else
775
 
    {
776
 
      status = GIMP_PDB_CALLING_ERROR;
777
 
    }
778
 
 
779
 
  values[0].data.d_status = status;
780
 
}
781
 
 
782
 
/* Read next byte */
783
 
static guint
784
 
jpeg_getc (j_decompress_ptr cinfo)
785
 
{
786
 
  struct jpeg_source_mgr *datasrc = cinfo->src;
787
 
 
788
 
  if (datasrc->bytes_in_buffer == 0)
789
 
    {
790
 
      if (! (*datasrc->fill_input_buffer) (cinfo))
791
 
        ERREXIT (cinfo, JERR_CANT_SUSPEND);
792
 
    }
793
 
  datasrc->bytes_in_buffer--;
794
 
 
795
 
  return *datasrc->next_input_byte++;
796
 
}
797
 
 
798
 
/* We need our own marker parser, since early versions of libjpeg
799
 
 * don't keep a conventient list of the marker's that have been
800
 
 * seen. */
801
 
 
802
 
/*
803
 
 * Marker processor for COM markers.
804
 
 * This replaces the library's built-in processor, which just skips the marker.
805
 
 * Note this code relies on a non-suspending data source.
806
 
 */
807
 
static GString *local_image_comments = NULL;
808
 
 
809
 
static boolean
810
 
COM_handler (j_decompress_ptr cinfo)
811
 
{
812
 
  gint  length;
813
 
  guint ch;
814
 
 
815
 
  length = jpeg_getc (cinfo) << 8;
816
 
  length += jpeg_getc (cinfo);
817
 
  if (length < 2)
818
 
    return FALSE;
819
 
  length -= 2;                  /* discount the length word itself */
820
 
 
821
 
  if (!local_image_comments)
822
 
    local_image_comments = g_string_new (NULL);
823
 
  else
824
 
    g_string_append_c (local_image_comments, '\n');
825
 
 
826
 
  while (length-- > 0)
827
 
    {
828
 
      ch = jpeg_getc (cinfo);
829
 
      g_string_append_c (local_image_comments, ch);
830
 
    }
831
 
 
832
 
  return TRUE;
833
 
}
834
 
 
835
 
typedef struct my_error_mgr
836
 
{
837
 
  struct jpeg_error_mgr pub;            /* "public" fields */
838
 
 
839
 
#ifdef __ia64__
840
 
  /* Ugh, the jmp_buf field needs to be 16-byte aligned on ia64 and some
841
 
   * glibc/icc combinations don't guarantee this. So we pad. See bug #138357
842
 
   * for details.
843
 
   */
844
 
  long double           dummy;
845
 
#endif
846
 
 
847
 
  jmp_buf               setjmp_buffer;  /* for return to caller */
848
 
} *my_error_ptr;
849
 
 
850
 
/*
851
 
 * Here's the routine that will replace the standard error_exit method:
852
 
 */
853
 
 
854
 
static void
855
 
my_error_exit (j_common_ptr cinfo)
856
 
{
857
 
  /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
858
 
  my_error_ptr myerr = (my_error_ptr) cinfo->err;
859
 
 
860
 
  /* Always display the message. */
861
 
  /* We could postpone this until after returning, if we chose. */
862
 
  (*cinfo->err->output_message) (cinfo);
863
 
 
864
 
  /* Return control to the setjmp point */
865
 
  longjmp (myerr->setjmp_buffer, 1);
866
 
}
867
 
 
868
 
static void
869
 
my_emit_message (j_common_ptr cinfo,
870
 
                 int          msg_level)
871
 
{
872
 
  if (msg_level == -1)
873
 
    {
874
 
      /*  disable loading of EXIF data  */
875
 
      cinfo->client_data = GINT_TO_POINTER (TRUE);
876
 
 
877
 
      (*cinfo->err->output_message) (cinfo);
878
 
    }
879
 
}
880
 
 
881
 
static void
882
 
my_output_message (j_common_ptr cinfo)
883
 
{
884
 
  gchar  buffer[JMSG_LENGTH_MAX + 1];
885
 
 
886
 
  (*cinfo->err->format_message)(cinfo, buffer);
887
 
 
888
 
  if (GPOINTER_TO_INT (cinfo->client_data))
889
 
    {
890
 
      gchar *msg = g_strconcat (buffer,
891
 
                                "\n\n",
892
 
                                _("EXIF data will be ignored."),
893
 
                                NULL);
894
 
      g_message (msg);
895
 
      g_free (msg);
896
 
    }
897
 
  else
898
 
    {
899
 
      g_message (buffer);
900
 
    }
901
 
}
902
 
 
903
 
static gint32
904
 
load_image (const gchar *filename,
905
 
            GimpRunMode  runmode,
906
 
            gboolean     preview)
907
 
{
908
 
  GimpPixelRgn     pixel_rgn;
909
 
  GimpDrawable    *drawable;
910
 
  gint32 volatile  image_ID;
911
 
  gint32           layer_ID;
912
 
  struct jpeg_decompress_struct cinfo;
913
 
  struct my_error_mgr           jerr;
914
 
  FILE    *infile;
915
 
  guchar  *buf;
916
 
  guchar  * volatile padded_buf = NULL;
917
 
  guchar **rowbuf;
918
 
  gint     image_type;
919
 
  gint     layer_type;
920
 
  gint     tile_height;
921
 
  gint     scanlines;
922
 
  gint     i, start, end;
923
 
 
924
 
  GimpParasite * volatile comment_parasite = NULL;
925
 
 
926
 
#ifdef HAVE_EXIF
927
 
  GimpParasite *exif_parasite = NULL;
928
 
  ExifData     *exif_data     = NULL;
929
 
#endif
930
 
 
931
 
  /* We set up the normal JPEG error routines. */
932
 
  cinfo.err = jpeg_std_error (&jerr.pub);
933
 
  jerr.pub.error_exit = my_error_exit;
934
 
 
935
 
  /* flag warnings, so we try to ignore corrupt EXIF data */
936
 
  if (!preview)
937
 
    {
938
 
      cinfo.client_data = GINT_TO_POINTER (FALSE);
939
 
 
940
 
      jerr.pub.emit_message   = my_emit_message;
941
 
      jerr.pub.output_message = my_output_message;
942
 
    }
943
 
 
944
 
  if ((infile = fopen (filename, "rb")) == NULL)
945
 
    {
946
 
      g_message (_("Could not open '%s' for reading: %s"),
947
 
                 gimp_filename_to_utf8 (filename), g_strerror (errno));
948
 
      gimp_quit ();
949
 
    }
950
 
 
951
 
  if (!preview)
952
 
    {
953
 
      gchar *name = g_strdup_printf (_("Opening '%s'..."),
954
 
                                     gimp_filename_to_utf8 (filename));
955
 
 
956
 
      gimp_progress_init (name);
957
 
      g_free (name);
958
 
    }
959
 
 
960
 
  image_ID = -1;
961
 
  /* Establish the setjmp return context for my_error_exit to use. */
962
 
  if (setjmp (jerr.setjmp_buffer))
963
 
    {
964
 
      /* If we get here, the JPEG code has signaled an error.
965
 
       * We need to clean up the JPEG object, close the input file, and return.
966
 
       */
967
 
      jpeg_destroy_decompress (&cinfo);
968
 
      if (infile)
969
 
        fclose (infile);
970
 
      if (image_ID != -1 && !preview)
971
 
        gimp_image_delete (image_ID);
972
 
      if (preview)
973
 
        destroy_preview();
974
 
      gimp_quit ();
975
 
    }
976
 
 
977
 
  /* Now we can initialize the JPEG decompression object. */
978
 
  jpeg_create_decompress (&cinfo);
979
 
 
980
 
  /* Step 2: specify data source (eg, a file) */
981
 
 
982
 
  jpeg_stdio_src (&cinfo, infile);
983
 
 
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
 
 
988
 
  /* Step 3: read file parameters with jpeg_read_header() */
989
 
 
990
 
  (void) jpeg_read_header (&cinfo, TRUE);
991
 
 
992
 
  /* We can ignore the return value from jpeg_read_header since
993
 
   *   (a) suspension is not possible with the stdio data source, and
994
 
   *   (b) we passed TRUE to reject a tables-only JPEG file as an error.
995
 
   * See libjpeg.doc for more info.
996
 
   */
997
 
 
998
 
  if (!preview)
999
 
    {
1000
 
      /* if we had any comments then make a parasite for them */
1001
 
      if (local_image_comments && local_image_comments->len)
1002
 
        {
1003
 
          gchar *comment = local_image_comments->str;
1004
 
 
1005
 
          g_string_free (local_image_comments, FALSE);
1006
 
 
1007
 
          local_image_comments = NULL;
1008
 
 
1009
 
          if (g_utf8_validate (comment, -1, NULL))
1010
 
            comment_parasite = gimp_parasite_new ("gimp-comment",
1011
 
                                                  GIMP_PARASITE_PERSISTENT,
1012
 
                                                  strlen (comment) + 1,
1013
 
                                                  comment);
1014
 
          g_free (comment);
1015
 
        }
1016
 
 
1017
 
      /* Do not attach the "jpeg-save-options" parasite to the image
1018
 
       * because this conflics with the global defaults.  See bug #75398:
1019
 
       * http://bugzilla.gnome.org/show_bug.cgi?id=75398 */
1020
 
    }
1021
 
 
1022
 
  /* Step 4: set parameters for decompression */
1023
 
 
1024
 
  /* In this example, we don't need to change any of the defaults set by
1025
 
   * jpeg_read_header(), so we do nothing here.
1026
 
   */
1027
 
 
1028
 
  /* Step 5: Start decompressor */
1029
 
 
1030
 
  jpeg_start_decompress (&cinfo);
1031
 
 
1032
 
  /* We may need to do some setup of our own at this point before reading
1033
 
   * the data.  After jpeg_start_decompress() we have the correct scaled
1034
 
   * output image dimensions available, as well as the output colormap
1035
 
   * if we asked for color quantization.
1036
 
   * In this example, we need to make an output work buffer of the right size.
1037
 
   */
1038
 
  /* temporary buffer */
1039
 
  tile_height = gimp_tile_height ();
1040
 
  buf = g_new (guchar,
1041
 
               tile_height * cinfo.output_width * cinfo.output_components);
1042
 
 
1043
 
  rowbuf = g_new (guchar*, tile_height);
1044
 
 
1045
 
  for (i = 0; i < tile_height; i++)
1046
 
    rowbuf[i] = buf + cinfo.output_width * cinfo.output_components * i;
1047
 
 
1048
 
  /* Create a new image of the proper size and associate the filename with it.
1049
 
 
1050
 
     Preview layers, not being on the bottom of a layer stack, MUST HAVE
1051
 
     AN ALPHA CHANNEL!
1052
 
   */
1053
 
  switch (cinfo.output_components)
1054
 
    {
1055
 
    case 1:
1056
 
      image_type = GIMP_GRAY;
1057
 
      layer_type = preview ? GIMP_GRAYA_IMAGE : GIMP_GRAY_IMAGE;
1058
 
      break;
1059
 
 
1060
 
    case 3:
1061
 
      image_type = GIMP_RGB;
1062
 
      layer_type = preview ? GIMP_RGBA_IMAGE : GIMP_RGB_IMAGE;
1063
 
      break;
1064
 
 
1065
 
    case 4:
1066
 
      if (cinfo.out_color_space == JCS_CMYK)
1067
 
        {
1068
 
          image_type = GIMP_RGB;
1069
 
          layer_type = GIMP_RGB_IMAGE;
1070
 
          break;
1071
 
        }
1072
 
      /*fallthrough*/
1073
 
 
1074
 
    default:
1075
 
      g_message ("Don't know how to load JPEGs\n"
1076
 
                 "with %d color channels\n"
1077
 
                 "using colorspace %d (%d)",
1078
 
                 cinfo.output_components, cinfo.out_color_space,
1079
 
                 cinfo.jpeg_color_space);
1080
 
      gimp_quit ();
1081
 
      break;
1082
 
    }
1083
 
 
1084
 
  if (preview)
1085
 
    padded_buf = g_new (guchar, tile_height * cinfo.output_width *
1086
 
                        (cinfo.output_components + 1));
1087
 
  else if (cinfo.out_color_space == JCS_CMYK)
1088
 
    padded_buf = g_new (guchar, tile_height * cinfo.output_width * 3);
1089
 
  else
1090
 
    padded_buf = NULL;
1091
 
 
1092
 
  if (preview)
1093
 
    {
1094
 
      image_ID = image_ID_global;
1095
 
    }
1096
 
  else
1097
 
    {
1098
 
      image_ID = gimp_image_new (cinfo.output_width, cinfo.output_height,
1099
 
                                 image_type);
1100
 
      gimp_image_set_filename (image_ID, filename);
1101
 
    }
1102
 
 
1103
 
  if (preview)
1104
 
    {
1105
 
      layer_ID_global = layer_ID =
1106
 
        gimp_layer_new (image_ID, _("JPEG preview"),
1107
 
                        cinfo.output_width,
1108
 
                        cinfo.output_height,
1109
 
                        layer_type, 100, GIMP_NORMAL_MODE);
1110
 
    }
1111
 
  else
1112
 
    {
1113
 
      layer_ID = gimp_layer_new (image_ID, _("Background"),
1114
 
                                 cinfo.output_width,
1115
 
                                 cinfo.output_height,
1116
 
                                 layer_type, 100, GIMP_NORMAL_MODE);
1117
 
    }
1118
 
 
1119
 
  drawable_global = drawable = gimp_drawable_get (layer_ID);
1120
 
  gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0,
1121
 
                       drawable->width, drawable->height, TRUE, FALSE);
1122
 
 
1123
 
  /* Step 5.1: if the file had resolution information, set it on the image */
1124
 
  if (!preview && cinfo.saw_JFIF_marker)
1125
 
    {
1126
 
      gdouble xresolution;
1127
 
      gdouble yresolution;
1128
 
      gdouble asymmetry;
1129
 
 
1130
 
      xresolution = cinfo.X_density;
1131
 
      yresolution = cinfo.Y_density;
1132
 
 
1133
 
      switch (cinfo.density_unit)
1134
 
        {
1135
 
        case 0: /* unknown -> set the aspect ratio but use the default
1136
 
                *  image resolution
1137
 
                */
1138
 
          if (cinfo.Y_density != 0)
1139
 
            asymmetry = xresolution / yresolution;
1140
 
          else
1141
 
            asymmetry = 1.0;
1142
 
 
1143
 
          gimp_image_get_resolution (image_ID, &xresolution, &yresolution);
1144
 
          xresolution *= asymmetry;
1145
 
          break;
1146
 
 
1147
 
        case 1: /* dots per inch */
1148
 
          break;
1149
 
 
1150
 
        case 2: /* dots per cm */
1151
 
          xresolution *= 2.54;
1152
 
          yresolution *= 2.54;
1153
 
          gimp_image_set_unit (image_ID, GIMP_UNIT_MM);
1154
 
          break;
1155
 
 
1156
 
        default:
1157
 
          g_message ("Unknown density unit %d\nassuming dots per inch",
1158
 
                     cinfo.density_unit);
1159
 
          break;
1160
 
        }
1161
 
 
1162
 
      gimp_image_set_resolution (image_ID, xresolution, yresolution);
1163
 
    }
1164
 
 
1165
 
  /* Step 6: while (scan lines remain to be read) */
1166
 
  /*           jpeg_read_scanlines(...); */
1167
 
 
1168
 
  /* Here we use the library's state variable cinfo.output_scanline as the
1169
 
   * loop counter, so that we don't have to keep track ourselves.
1170
 
   */
1171
 
  while (cinfo.output_scanline < cinfo.output_height)
1172
 
    {
1173
 
      start = cinfo.output_scanline;
1174
 
      end   = cinfo.output_scanline + tile_height;
1175
 
      end   = MIN (end, cinfo.output_height);
1176
 
      scanlines = end - start;
1177
 
 
1178
 
      for (i = 0; i < scanlines; i++)
1179
 
        jpeg_read_scanlines (&cinfo, (JSAMPARRAY) &rowbuf[i], 1);
1180
 
 
1181
 
      if (preview) /* Add a dummy alpha channel -- convert buf to padded_buf */
1182
 
        {
1183
 
          guchar *dest = padded_buf;
1184
 
          guchar *src  = buf;
1185
 
          gint    num  = drawable->width * scanlines;
1186
 
 
1187
 
          switch (cinfo.output_components)
1188
 
            {
1189
 
            case 1:
1190
 
              for (i = 0; i < num; i++)
1191
 
                {
1192
 
                  *(dest++) = *(src++);
1193
 
                  *(dest++) = 255;
1194
 
                }
1195
 
              break;
1196
 
 
1197
 
            case 3:
1198
 
              for (i = 0; i < num; i++)
1199
 
                {
1200
 
                  *(dest++) = *(src++);
1201
 
                  *(dest++) = *(src++);
1202
 
                  *(dest++) = *(src++);
1203
 
                  *(dest++) = 255;
1204
 
                }
1205
 
              break;
1206
 
 
1207
 
            default:
1208
 
              g_warning ("JPEG - shouldn't have gotten here.\nReport to http://bugzilla.gnome.org/");
1209
 
              break;
1210
 
            }
1211
 
        }
1212
 
      else if (cinfo.out_color_space == JCS_CMYK) /* buf-> RGB in padded_buf */
1213
 
        {
1214
 
          guchar *dest = padded_buf;
1215
 
          guchar *src  = buf;
1216
 
          gint    num  = drawable->width * scanlines;
1217
 
 
1218
 
          for (i = 0; i < num; i++)
1219
 
            {
1220
 
              guint r_c, g_m, b_y, a_k;
1221
 
 
1222
 
              r_c = *(src++);
1223
 
              g_m = *(src++);
1224
 
              b_y = *(src++);
1225
 
              a_k = *(src++);
1226
 
              *(dest++) = (r_c * a_k) / 255;
1227
 
              *(dest++) = (g_m * a_k) / 255;
1228
 
              *(dest++) = (b_y * a_k) / 255;
1229
 
            }
1230
 
        }
1231
 
 
1232
 
      gimp_pixel_rgn_set_rect (&pixel_rgn, padded_buf ? padded_buf : buf,
1233
 
                               0, start, drawable->width, scanlines);
1234
 
 
1235
 
      if (! preview)
1236
 
        gimp_progress_update ((gdouble) cinfo.output_scanline /
1237
 
                              (gdouble) cinfo.output_height);
1238
 
    }
1239
 
 
1240
 
  /* Step 7: Finish decompression */
1241
 
 
1242
 
  jpeg_finish_decompress (&cinfo);
1243
 
  /* We can ignore the return value since suspension is not possible
1244
 
   * with the stdio data source.
1245
 
   */
1246
 
 
1247
 
  /* Step 8: Release JPEG decompression object */
1248
 
 
1249
 
  /* This is an important step since it will release a good deal of memory. */
1250
 
  jpeg_destroy_decompress (&cinfo);
1251
 
 
1252
 
  /* free up the temporary buffers */
1253
 
  g_free (rowbuf);
1254
 
  g_free (buf);
1255
 
  g_free (padded_buf);
1256
 
 
1257
 
  /* After finish_decompress, we can close the input file.
1258
 
   * Here we postpone it until after no more JPEG errors are possible,
1259
 
   * so as to simplify the setjmp error logic above.  (Actually, I don't
1260
 
   * think that jpeg_destroy can do an error exit, but why assume anything...)
1261
 
   */
1262
 
  fclose (infile);
1263
 
 
1264
 
  /* At this point you may want to check to see whether any corrupt-data
1265
 
   * warnings occurred (test whether jerr.num_warnings is nonzero).
1266
 
   */
1267
 
 
1268
 
  /* Tell the GIMP to display the image.
1269
 
   */
1270
 
  gimp_image_add_layer (image_ID, layer_ID, 0);
1271
 
  gimp_drawable_flush (drawable);
1272
 
 
1273
 
  /* pw - Last of all, attach the parasites (couldn't do it earlier -
1274
 
     there was no image. */
1275
 
 
1276
 
  if (!preview)
1277
 
    {
1278
 
      if (comment_parasite)
1279
 
        {
1280
 
          gimp_image_parasite_attach (image_ID, comment_parasite);
1281
 
          gimp_parasite_free (comment_parasite);
1282
 
 
1283
 
          comment_parasite = NULL;
1284
 
        }
1285
 
 
1286
 
#ifdef HAVE_EXIF
1287
 
#define EXIF_HEADER_SIZE 8
1288
 
 
1289
 
      if (! GPOINTER_TO_INT (cinfo.client_data))
1290
 
        {
1291
 
          exif_data = exif_data_new_from_file (filename);
1292
 
          if (exif_data)
1293
 
            {
1294
 
              guchar *exif_buf;
1295
 
              guint   exif_buf_len;
1296
 
 
1297
 
              exif_data_save_data (exif_data, &exif_buf, &exif_buf_len);
1298
 
              exif_data_unref (exif_data);
1299
 
 
1300
 
              if (exif_buf_len > EXIF_HEADER_SIZE)
1301
 
                {
1302
 
                  exif_parasite = gimp_parasite_new ("exif-data",
1303
 
                                                     GIMP_PARASITE_PERSISTENT,
1304
 
                                                     exif_buf_len, exif_buf);
1305
 
                  gimp_image_parasite_attach (image_ID, exif_parasite);
1306
 
                  gimp_parasite_free (exif_parasite);
1307
 
                }
1308
 
 
1309
 
              free (exif_buf);
1310
 
            }
1311
 
        }
1312
 
#endif
1313
 
    }
1314
 
 
1315
 
  return image_ID;
1316
 
}
1317
 
 
1318
 
/*
1319
 
 * sg - This is the best I can do, I'm afraid... I think it will fail
1320
 
 * if something bad really happens (but it might not). If you have a
1321
 
 * better solution, send it ;-)
1322
 
 */
1323
 
static void
1324
 
background_error_exit (j_common_ptr cinfo)
1325
 
{
1326
 
  if (abort_me)
1327
 
    *abort_me = TRUE;
1328
 
  (*cinfo->err->output_message) (cinfo);
1329
 
}
1330
 
 
1331
 
static gboolean
1332
 
background_jpeg_save (PreviewPersistent *pp)
1333
 
{
1334
 
  guchar *t;
1335
 
  guchar *s;
1336
 
  gint    i, j;
1337
 
  gint    yend;
1338
 
 
1339
 
  if (pp->abort_me || (pp->cinfo.next_scanline >= pp->cinfo.image_height))
1340
 
    {
1341
 
      /* clean up... */
1342
 
      if (pp->abort_me)
1343
 
        {
1344
 
          jpeg_abort_compress (&(pp->cinfo));
1345
 
        }
1346
 
      else
1347
 
        {
1348
 
          jpeg_finish_compress (&(pp->cinfo));
1349
 
        }
1350
 
 
1351
 
      fclose (pp->outfile);
1352
 
      jpeg_destroy_compress (&(pp->cinfo));
1353
 
 
1354
 
      g_free (pp->temp);
1355
 
      g_free (pp->data);
1356
 
 
1357
 
      if (pp->drawable)
1358
 
        gimp_drawable_detach (pp->drawable);
1359
 
 
1360
 
      /* display the preview stuff */
1361
 
      if (!pp->abort_me)
1362
 
        {
1363
 
          struct stat buf;
1364
 
          gchar       temp[128];
1365
 
 
1366
 
          stat (pp->file_name, &buf);
1367
 
          g_snprintf (temp, sizeof (temp),
1368
 
                      _("File size: %02.01f kB"),
1369
 
                      (gdouble) (buf.st_size) / 1024.0);
1370
 
          gtk_label_set_text (GTK_LABEL (preview_size), temp);
1371
 
 
1372
 
          /* and load the preview */
1373
 
          load_image (pp->file_name, GIMP_RUN_NONINTERACTIVE, TRUE);
1374
 
        }
1375
 
 
1376
 
      /* we cleanup here (load_image doesn't run in the background) */
1377
 
      unlink (pp->file_name);
1378
 
 
1379
 
      if (abort_me == &(pp->abort_me))
1380
 
        abort_me = NULL;
1381
 
 
1382
 
      g_free (pp);
1383
 
 
1384
 
      gimp_displays_flush ();
1385
 
      gdk_flush ();
1386
 
 
1387
 
      return FALSE;
1388
 
    }
1389
 
  else
1390
 
    {
1391
 
      if ((pp->cinfo.next_scanline % pp->tile_height) == 0)
1392
 
        {
1393
 
          yend = pp->cinfo.next_scanline + pp->tile_height;
1394
 
          yend = MIN (yend, pp->cinfo.image_height);
1395
 
          gimp_pixel_rgn_get_rect (&pp->pixel_rgn, pp->data, 0,
1396
 
                                   pp->cinfo.next_scanline,
1397
 
                                   pp->cinfo.image_width,
1398
 
                                   (yend - pp->cinfo.next_scanline));
1399
 
          pp->src = pp->data;
1400
 
        }
1401
 
 
1402
 
      t = pp->temp;
1403
 
      s = pp->src;
1404
 
      i = pp->cinfo.image_width;
1405
 
 
1406
 
      while (i--)
1407
 
        {
1408
 
          for (j = 0; j < pp->cinfo.input_components; j++)
1409
 
            *t++ = *s++;
1410
 
          if (pp->has_alpha)  /* ignore alpha channel */
1411
 
            s++;
1412
 
        }
1413
 
 
1414
 
      pp->src += pp->rowstride;
1415
 
      jpeg_write_scanlines (&(pp->cinfo), (JSAMPARRAY) &(pp->temp), 1);
1416
 
 
1417
 
      return TRUE;
1418
 
    }
1419
 
}
1420
 
 
1421
 
static gboolean
1422
 
save_image (const gchar *filename,
1423
 
            gint32       image_ID,
1424
 
            gint32       drawable_ID,
1425
 
            gint32       orig_image_ID,
1426
 
            gboolean     preview)
1427
 
{
1428
 
  GimpPixelRgn   pixel_rgn;
1429
 
  GimpDrawable  *drawable;
1430
 
  GimpImageType  drawable_type;
1431
 
  struct jpeg_compress_struct cinfo;
1432
 
  struct my_error_mgr         jerr;
1433
 
  FILE     * volatile outfile;
1434
 
  guchar   *temp, *t;
1435
 
  guchar   *data;
1436
 
  guchar   *src, *s;
1437
 
  gchar    *name;
1438
 
  gboolean  has_alpha;
1439
 
  gint      rowstride, yend;
1440
 
  gint      i, j;
1441
 
#ifdef HAVE_EXIF
1442
 
  gchar    *thumbnail_buffer        = NULL;
1443
 
  gint      thumbnail_buffer_length = 0;
1444
 
  ExifData  *exif_data_tmp          = NULL;
1445
 
#endif
1446
 
 
1447
 
  drawable = gimp_drawable_get (drawable_ID);
1448
 
  drawable_type = gimp_drawable_type (drawable_ID);
1449
 
  gimp_pixel_rgn_init (&pixel_rgn, drawable,
1450
 
                       0, 0, drawable->width, drawable->height, FALSE, FALSE);
1451
 
 
1452
 
  if (!preview)
1453
 
    {
1454
 
      name = g_strdup_printf (_("Saving '%s'..."),
1455
 
                              gimp_filename_to_utf8 (filename));
1456
 
      gimp_progress_init (name);
1457
 
      g_free (name);
1458
 
    }
1459
 
 
1460
 
  /* Step 1: allocate and initialize JPEG compression object */
1461
 
 
1462
 
  /* We have to set up the error handler first, in case the initialization
1463
 
   * step fails.  (Unlikely, but it could happen if you are out of memory.)
1464
 
   * This routine fills in the contents of struct jerr, and returns jerr's
1465
 
   * address which we place into the link field in cinfo.
1466
 
   */
1467
 
  cinfo.err = jpeg_std_error (&jerr.pub);
1468
 
  jerr.pub.error_exit = my_error_exit;
1469
 
 
1470
 
  outfile = NULL;
1471
 
  /* Establish the setjmp return context for my_error_exit to use. */
1472
 
  if (setjmp (jerr.setjmp_buffer))
1473
 
    {
1474
 
      /* If we get here, the JPEG code has signaled an error.
1475
 
       * We need to clean up the JPEG object, close the input file, and return.
1476
 
       */
1477
 
      jpeg_destroy_compress (&cinfo);
1478
 
      if (outfile)
1479
 
        fclose (outfile);
1480
 
      if (drawable)
1481
 
        gimp_drawable_detach (drawable);
1482
 
 
1483
 
      return FALSE;
1484
 
    }
1485
 
 
1486
 
  /* Now we can initialize the JPEG compression object. */
1487
 
  jpeg_create_compress (&cinfo);
1488
 
 
1489
 
  /* Step 2: specify data destination (eg, a file) */
1490
 
  /* Note: steps 2 and 3 can be done in either order. */
1491
 
 
1492
 
  /* Here we use the library-supplied code to send compressed data to a
1493
 
   * stdio stream.  You can also write your own code to do something else.
1494
 
   * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
1495
 
   * requires it in order to write binary files.
1496
 
   */
1497
 
  if ((outfile = fopen (filename, "wb")) == NULL)
1498
 
    {
1499
 
      g_message (_("Could not open '%s' for writing: %s"),
1500
 
                 gimp_filename_to_utf8 (filename), g_strerror (errno));
1501
 
      return FALSE;
1502
 
    }
1503
 
  jpeg_stdio_dest (&cinfo, outfile);
1504
 
 
1505
 
  /* Get the input image and a pointer to its data.
1506
 
   */
1507
 
  switch (drawable_type)
1508
 
    {
1509
 
    case GIMP_RGB_IMAGE:
1510
 
    case GIMP_GRAY_IMAGE:
1511
 
      /* # of color components per pixel */
1512
 
      cinfo.input_components = drawable->bpp;
1513
 
      has_alpha = FALSE;
1514
 
      break;
1515
 
 
1516
 
    case GIMP_RGBA_IMAGE:
1517
 
    case GIMP_GRAYA_IMAGE:
1518
 
      /*gimp_message ("jpeg: image contains a-channel info which will be lost");*/
1519
 
      /* # of color components per pixel (minus the GIMP alpha channel) */
1520
 
      cinfo.input_components = drawable->bpp - 1;
1521
 
      has_alpha = TRUE;
1522
 
      break;
1523
 
 
1524
 
    case GIMP_INDEXED_IMAGE:
1525
 
      /*gimp_message ("jpeg: cannot operate on indexed color images");*/
1526
 
      return FALSE;
1527
 
      break;
1528
 
 
1529
 
    default:
1530
 
      /*gimp_message ("jpeg: cannot operate on unknown image types");*/
1531
 
      return FALSE;
1532
 
      break;
1533
 
    }
1534
 
 
1535
 
  /* Step 3: set parameters for compression */
1536
 
 
1537
 
  /* First we supply a description of the input image.
1538
 
   * Four fields of the cinfo struct must be filled in:
1539
 
   */
1540
 
  /* image width and height, in pixels */
1541
 
  cinfo.image_width  = drawable->width;
1542
 
  cinfo.image_height = drawable->height;
1543
 
  /* colorspace of input image */
1544
 
  cinfo.in_color_space = (drawable_type == GIMP_RGB_IMAGE ||
1545
 
                          drawable_type == GIMP_RGBA_IMAGE)
1546
 
    ? JCS_RGB : JCS_GRAYSCALE;
1547
 
  /* Now use the library's routine to set default compression parameters.
1548
 
   * (You must set at least cinfo.in_color_space before calling this,
1549
 
   * since the defaults depend on the source color space.)
1550
 
   */
1551
 
  jpeg_set_defaults (&cinfo);
1552
 
 
1553
 
  jpeg_set_quality (&cinfo, (gint) (jsvals.quality + 0.5), jsvals.baseline);
1554
 
  cinfo.smoothing_factor = (gint) (jsvals.smoothing * 100);
1555
 
  cinfo.optimize_coding = jsvals.optimize;
1556
 
 
1557
 
#ifdef HAVE_PROGRESSIVE_JPEG
1558
 
  if (jsvals.progressive)
1559
 
    {
1560
 
      jpeg_simple_progression (&cinfo);
1561
 
    }
1562
 
#endif /* HAVE_PROGRESSIVE_JPEG */
1563
 
 
1564
 
  switch (jsvals.subsmp)
1565
 
    {
1566
 
    case 0:
1567
 
    default:
1568
 
      cinfo.comp_info[0].h_samp_factor = 2;
1569
 
      cinfo.comp_info[0].v_samp_factor = 2;
1570
 
      cinfo.comp_info[1].h_samp_factor = 1;
1571
 
      cinfo.comp_info[1].v_samp_factor = 1;
1572
 
      cinfo.comp_info[2].h_samp_factor = 1;
1573
 
      cinfo.comp_info[2].v_samp_factor = 1;
1574
 
      break;
1575
 
 
1576
 
    case 1:
1577
 
      cinfo.comp_info[0].h_samp_factor = 2;
1578
 
      cinfo.comp_info[0].v_samp_factor = 1;
1579
 
      cinfo.comp_info[1].h_samp_factor = 1;
1580
 
      cinfo.comp_info[1].v_samp_factor = 1;
1581
 
      cinfo.comp_info[2].h_samp_factor = 1;
1582
 
      cinfo.comp_info[2].v_samp_factor = 1;
1583
 
      break;
1584
 
 
1585
 
    case 2:
1586
 
      cinfo.comp_info[0].h_samp_factor = 1;
1587
 
      cinfo.comp_info[0].v_samp_factor = 1;
1588
 
      cinfo.comp_info[1].h_samp_factor = 1;
1589
 
      cinfo.comp_info[1].v_samp_factor = 1;
1590
 
      cinfo.comp_info[2].h_samp_factor = 1;
1591
 
      cinfo.comp_info[2].v_samp_factor = 1;
1592
 
      break;
1593
 
    }
1594
 
 
1595
 
  cinfo.restart_interval = 0;
1596
 
  cinfo.restart_in_rows = jsvals.restart;
1597
 
 
1598
 
  switch (jsvals.dct)
1599
 
    {
1600
 
    case 0:
1601
 
    default:
1602
 
      cinfo.dct_method = JDCT_ISLOW;
1603
 
      break;
1604
 
 
1605
 
    case 1:
1606
 
      cinfo.dct_method = JDCT_IFAST;
1607
 
      break;
1608
 
 
1609
 
    case 2:
1610
 
      cinfo.dct_method = JDCT_FLOAT;
1611
 
      break;
1612
 
    }
1613
 
 
1614
 
  {
1615
 
    gdouble xresolution;
1616
 
    gdouble yresolution;
1617
 
 
1618
 
    gimp_image_get_resolution (orig_image_ID, &xresolution, &yresolution);
1619
 
 
1620
 
    if (xresolution > 1e-5 && yresolution > 1e-5)
1621
 
      {
1622
 
        gdouble factor;
1623
 
 
1624
 
        factor = gimp_unit_get_factor (gimp_image_get_unit (orig_image_ID));
1625
 
 
1626
 
        if (factor == 2.54 /* cm */ ||
1627
 
            factor == 25.4 /* mm */)
1628
 
          {
1629
 
            cinfo.density_unit = 2;  /* dots per cm */
1630
 
 
1631
 
            xresolution /= 2.54;
1632
 
            yresolution /= 2.54;
1633
 
          }
1634
 
        else
1635
 
          {
1636
 
            cinfo.density_unit = 1;  /* dots per inch */
1637
 
          }
1638
 
 
1639
 
        cinfo.X_density = xresolution;
1640
 
        cinfo.Y_density = yresolution;
1641
 
      }
1642
 
  }
1643
 
 
1644
 
  /* Step 4: Start compressor */
1645
 
 
1646
 
  /* TRUE ensures that we will write a complete interchange-JPEG file.
1647
 
   * Pass TRUE unless you are very sure of what you're doing.
1648
 
   */
1649
 
  jpeg_start_compress (&cinfo, TRUE);
1650
 
 
1651
 
#ifdef HAVE_EXIF
1652
 
 
1653
 
  /* Create the thumbnail JPEG in a buffer */
1654
 
 
1655
 
  if (jsvals.save_exif || jsvals.save_thumbnail)
1656
 
    {
1657
 
      guchar  *exif_buf = NULL;
1658
 
      guint    exif_buf_len;
1659
 
      gdouble  quality  = MIN (75.0, jsvals.quality);
1660
 
 
1661
 
      if ( (! jsvals.save_exif) || (! exif_data))
1662
 
        exif_data_tmp = exif_data_new ();
1663
 
      else
1664
 
        exif_data_tmp = exif_data;
1665
 
 
1666
 
      /* avoid saving markers longer than 65533, gradually decrease
1667
 
       * quality in steps of 5 until exif_buf_len is lower than that.
1668
 
       */
1669
 
      for (exif_buf_len = 65535;
1670
 
           exif_buf_len > 65533 && quality > 0.0;
1671
 
           quality -= 5.0)
1672
 
        {
1673
 
          if (jsvals.save_thumbnail)
1674
 
            thumbnail_buffer_length = create_thumbnail (image_ID, drawable_ID,
1675
 
                                                        quality,
1676
 
                                                        &thumbnail_buffer);
1677
 
 
1678
 
          exif_data_tmp->data = thumbnail_buffer;
1679
 
          exif_data_tmp->size = thumbnail_buffer_length;
1680
 
 
1681
 
          if (exif_buf)
1682
 
            free (exif_buf);
1683
 
 
1684
 
          exif_data_save_data (exif_data_tmp, &exif_buf, &exif_buf_len);
1685
 
        }
1686
 
 
1687
 
      if (exif_buf_len > 65533)
1688
 
        {
1689
 
          /* last attempt with quality 0.0 */
1690
 
          if (jsvals.save_thumbnail)
1691
 
            thumbnail_buffer_length = create_thumbnail (image_ID, drawable_ID,
1692
 
                                                        0.0,
1693
 
                                                        &thumbnail_buffer);
1694
 
          exif_data_tmp->data = thumbnail_buffer;
1695
 
          exif_data_tmp->size = thumbnail_buffer_length;
1696
 
 
1697
 
          if (exif_buf)
1698
 
            free (exif_buf);
1699
 
 
1700
 
          exif_data_save_data (exif_data_tmp, &exif_buf, &exif_buf_len);
1701
 
        }
1702
 
 
1703
 
      if (exif_buf_len > 65533)
1704
 
        {
1705
 
          /* still no go? save without thumbnail */
1706
 
          exif_data_tmp->data = NULL;
1707
 
          exif_data_tmp->size = 0;
1708
 
 
1709
 
          if (exif_buf)
1710
 
            free (exif_buf);
1711
 
 
1712
 
          exif_data_save_data (exif_data_tmp, &exif_buf, &exif_buf_len);
1713
 
        }
1714
 
 
1715
 
      jpeg_write_marker (&cinfo, MARKER_CODE_EXIF, exif_buf, exif_buf_len);
1716
 
 
1717
 
      if (exif_buf)
1718
 
        free (exif_buf);
1719
 
    }
1720
 
#endif /* HAVE_EXIF */
1721
 
 
1722
 
  /* Step 4.1: Write the comment out - pw */
1723
 
  if (image_comment && *image_comment)
1724
 
    {
1725
 
      jpeg_write_marker (&cinfo, JPEG_COM,
1726
 
                         (guchar *) image_comment, strlen (image_comment));
1727
 
    }
1728
 
 
1729
 
  /* Step 5: while (scan lines remain to be written) */
1730
 
  /*           jpeg_write_scanlines(...); */
1731
 
 
1732
 
  /* Here we use the library's state variable cinfo.next_scanline as the
1733
 
   * loop counter, so that we don't have to keep track ourselves.
1734
 
   * To keep things simple, we pass one scanline per call; you can pass
1735
 
   * more if you wish, though.
1736
 
   */
1737
 
  /* JSAMPLEs per row in image_buffer */
1738
 
  rowstride = drawable->bpp * drawable->width;
1739
 
  temp = g_new (guchar, cinfo.image_width * cinfo.input_components);
1740
 
  data = g_new (guchar, rowstride * gimp_tile_height ());
1741
 
 
1742
 
  /* fault if cinfo.next_scanline isn't initially a multiple of
1743
 
   * gimp_tile_height */
1744
 
  src = NULL;
1745
 
 
1746
 
  /*
1747
 
   * sg - if we preview, we want this to happen in the background -- do
1748
 
   * not duplicate code in the future; for now, it's OK
1749
 
   */
1750
 
 
1751
 
  if (preview)
1752
 
    {
1753
 
      PreviewPersistent *pp = g_new (PreviewPersistent, 1);
1754
 
 
1755
 
      /* pass all the information we need */
1756
 
      pp->cinfo       = cinfo;
1757
 
      pp->tile_height = gimp_tile_height();
1758
 
      pp->data        = data;
1759
 
      pp->outfile     = outfile;
1760
 
      pp->has_alpha   = has_alpha;
1761
 
      pp->rowstride   = rowstride;
1762
 
      pp->temp        = temp;
1763
 
      pp->data        = data;
1764
 
      pp->drawable    = drawable;
1765
 
      pp->pixel_rgn   = pixel_rgn;
1766
 
      pp->src         = NULL;
1767
 
      pp->file_name   = filename;
1768
 
 
1769
 
      pp->abort_me    = FALSE;
1770
 
      abort_me = &(pp->abort_me);
1771
 
 
1772
 
      pp->cinfo.err = jpeg_std_error(&(pp->jerr));
1773
 
      pp->jerr.error_exit = background_error_exit;
1774
 
 
1775
 
      g_idle_add ((GSourceFunc) background_jpeg_save, pp);
1776
 
 
1777
 
      /* background_jpeg_save() will cleanup as needed */
1778
 
      return TRUE;
1779
 
    }
1780
 
 
1781
 
  while (cinfo.next_scanline < cinfo.image_height)
1782
 
    {
1783
 
      if ((cinfo.next_scanline % gimp_tile_height ()) == 0)
1784
 
        {
1785
 
          yend = cinfo.next_scanline + gimp_tile_height ();
1786
 
          yend = MIN (yend, cinfo.image_height);
1787
 
          gimp_pixel_rgn_get_rect (&pixel_rgn, data,
1788
 
                                   0, cinfo.next_scanline,
1789
 
                                   cinfo.image_width,
1790
 
                                   (yend - cinfo.next_scanline));
1791
 
          src = data;
1792
 
        }
1793
 
 
1794
 
      t = temp;
1795
 
      s = src;
1796
 
      i = cinfo.image_width;
1797
 
 
1798
 
      while (i--)
1799
 
        {
1800
 
          for (j = 0; j < cinfo.input_components; j++)
1801
 
            *t++ = *s++;
1802
 
          if (has_alpha)  /* ignore alpha channel */
1803
 
            s++;
1804
 
        }
1805
 
 
1806
 
      src += rowstride;
1807
 
      jpeg_write_scanlines (&cinfo, (JSAMPARRAY) &temp, 1);
1808
 
 
1809
 
      if ((cinfo.next_scanline % 5) == 0)
1810
 
        gimp_progress_update ((gdouble) cinfo.next_scanline /
1811
 
                              (gdouble) cinfo.image_height);
1812
 
    }
1813
 
 
1814
 
  /* Step 6: Finish compression */
1815
 
  jpeg_finish_compress (&cinfo);
1816
 
  /* After finish_compress, we can close the output file. */
1817
 
  fclose (outfile);
1818
 
 
1819
 
  /* Step 7: release JPEG compression object */
1820
 
 
1821
 
  /* This is an important step since it will release a good deal of memory. */
1822
 
  jpeg_destroy_compress (&cinfo);
1823
 
  /* free the temporary buffer */
1824
 
  g_free (temp);
1825
 
  g_free (data);
1826
 
 
1827
 
  /* And we're done! */
1828
 
  /*gimp_do_progress (1, 1);*/
1829
 
 
1830
 
  gimp_drawable_detach (drawable);
1831
 
 
1832
 
  return TRUE;
1833
 
}
1834
 
 
1835
 
static void
1836
 
make_preview (void)
1837
 
{
1838
 
  destroy_preview ();
1839
 
 
1840
 
  if (jsvals.preview)
1841
 
    {
1842
 
      gchar *tn = gimp_temp_name ("jpeg");
1843
 
 
1844
 
      if (! undo_touched)
1845
 
        {
1846
 
          /* we freeze undo saving so that we can avoid sucking up
1847
 
           * tile cache with our unneeded preview steps. */
1848
 
          gimp_image_undo_freeze (image_ID_global);
1849
 
 
1850
 
          undo_touched = TRUE;
1851
 
        }
1852
 
 
1853
 
      save_image (tn,
1854
 
                  image_ID_global,
1855
 
                  drawable_ID_global,
1856
 
                  orig_image_ID_global,
1857
 
                  TRUE);
1858
 
 
1859
 
      if (display_ID == -1)
1860
 
        display_ID = gimp_display_new (image_ID_global);
1861
 
    }
1862
 
  else
1863
 
    {
1864
 
      gtk_label_set_text (GTK_LABEL (preview_size), _("File size: unknown"));
1865
 
      gimp_displays_flush ();
1866
 
    }
1867
 
 
1868
 
  gtk_widget_set_sensitive (preview_size, jsvals.preview);
1869
 
}
1870
 
 
1871
 
static void
1872
 
destroy_preview (void)
1873
 
{
1874
 
  if (abort_me)
1875
 
    *abort_me = TRUE;   /* signal the background save to stop */
1876
 
 
1877
 
  if (drawable_global)
1878
 
    {
1879
 
      gimp_drawable_detach (drawable_global);
1880
 
      drawable_global = NULL;
1881
 
    }
1882
 
 
1883
 
  if (layer_ID_global != -1 && image_ID_global != -1)
1884
 
    {
1885
 
      /*  assuming that reference counting is working correctly,
1886
 
          we do not need to delete the layer, removing it from
1887
 
          the image should be sufficient  */
1888
 
      gimp_image_remove_layer (image_ID_global, layer_ID_global);
1889
 
 
1890
 
      layer_ID_global = -1;
1891
 
    }
1892
 
}
1893
 
 
1894
 
static gboolean
1895
 
save_dialog (void)
1896
 
{
1897
 
  GtkWidget     *dialog;
1898
 
  GtkWidget     *vbox;
1899
 
  GtkObject     *entry;
1900
 
  GtkWidget     *table;
1901
 
  GtkWidget     *table2;
1902
 
  GtkWidget     *expander;
1903
 
  GtkWidget     *frame;
1904
 
  GtkWidget     *toggle;
1905
 
  GtkWidget     *spinbutton;
1906
 
  GtkObject     *scale_data;
1907
 
  GtkWidget     *label;
1908
 
 
1909
 
  GtkWidget     *progressive;
1910
 
  GtkWidget     *baseline;
1911
 
  GtkWidget     *restart;
1912
 
 
1913
 
#ifdef HAVE_EXIF
1914
 
  GtkWidget     *exif_toggle;
1915
 
  GtkWidget     *thumbnail_toggle;
1916
 
#endif /* HAVE_EXIF */
1917
 
 
1918
 
  GtkWidget     *preview;
1919
 
  GtkWidget     *combo;
1920
 
 
1921
 
  GtkWidget     *text_view;
1922
 
  GtkTextBuffer *text_buffer;
1923
 
  GtkWidget     *scrolled_window;
1924
 
 
1925
 
  GimpImageType  dtype;
1926
 
  gchar         *text;
1927
 
  gboolean       run;
1928
 
 
1929
 
  dialog = gimp_dialog_new (_("Save as JPEG"), "jpeg",
1930
 
                            NULL, 0,
1931
 
                            gimp_standard_help_func, "file-jpeg-save",
1932
 
 
1933
 
                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1934
 
                            GTK_STOCK_OK,     GTK_RESPONSE_OK,
1935
 
 
1936
 
                            NULL);
1937
 
 
1938
 
  gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
1939
 
 
1940
 
  vbox = gtk_vbox_new (FALSE, 12);
1941
 
  gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
1942
 
  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), vbox, TRUE, TRUE, 0);
1943
 
  gtk_widget_show (vbox);
1944
 
 
1945
 
  table = gtk_table_new (1, 3, FALSE);
1946
 
  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
1947
 
  gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
1948
 
  gtk_widget_show (table);
1949
 
 
1950
 
  entry = gimp_scale_entry_new (GTK_TABLE (table), 0, 0, _("_Quality:"),
1951
 
                                SCALE_WIDTH, 0, jsvals.quality,
1952
 
                                0.0, 100.0, 1.0, 10.0, 0,
1953
 
                                TRUE, 0.0, 0.0,
1954
 
                                _("JPEG quality parameter"),
1955
 
                                "file-jpeg-save-quality");
1956
 
 
1957
 
  g_signal_connect (entry, "value_changed",
1958
 
                    G_CALLBACK (gimp_double_adjustment_update),
1959
 
                    &jsvals.quality);
1960
 
  g_signal_connect (entry, "value_changed",
1961
 
                    G_CALLBACK (make_preview),
1962
 
                    NULL);
1963
 
 
1964
 
  preview_size = gtk_label_new (_("File size: unknown"));
1965
 
  gtk_misc_set_alignment (GTK_MISC (preview_size), 0.0, 0.5);
1966
 
  gimp_label_set_attributes (GTK_LABEL (preview_size),
1967
 
                             PANGO_ATTR_STYLE, PANGO_STYLE_ITALIC,
1968
 
                             -1);
1969
 
  gtk_box_pack_start (GTK_BOX (vbox), preview_size, FALSE, FALSE, 0);
1970
 
  gtk_widget_show (preview_size);
1971
 
 
1972
 
  preview =
1973
 
    gtk_check_button_new_with_mnemonic (_("Show _Preview in image window"));
1974
 
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (preview), jsvals.preview);
1975
 
  gtk_box_pack_start (GTK_BOX (vbox), preview, FALSE, FALSE, 0);
1976
 
  gtk_widget_show (preview);
1977
 
 
1978
 
  g_signal_connect (preview, "toggled",
1979
 
                    G_CALLBACK (gimp_toggle_button_update),
1980
 
                    &jsvals.preview);
1981
 
  g_signal_connect (preview, "toggled",
1982
 
                    G_CALLBACK (make_preview),
1983
 
                    NULL);
1984
 
 
1985
 
 
1986
 
  text = g_strdup_printf ("<b>%s</b>", _("_Advanced Options"));
1987
 
  expander = gtk_expander_new_with_mnemonic (text);
1988
 
  gtk_expander_set_use_markup (GTK_EXPANDER (expander), TRUE);
1989
 
  g_free (text);
1990
 
 
1991
 
  gtk_box_pack_start (GTK_BOX (vbox), expander, TRUE, TRUE, 0);
1992
 
  gtk_widget_show (expander);
1993
 
 
1994
 
  vbox = gtk_vbox_new (FALSE, 12);
1995
 
  gtk_container_add (GTK_CONTAINER (expander), vbox);
1996
 
  gtk_widget_show (vbox);
1997
 
 
1998
 
  frame = gimp_frame_new ("<expander>");
1999
 
  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
2000
 
  gtk_widget_show (frame);
2001
 
 
2002
 
  table = gtk_table_new (4, 6, FALSE);
2003
 
  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
2004
 
  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
2005
 
  gtk_table_set_col_spacing (GTK_TABLE (table), 1, 12);
2006
 
  gtk_container_add (GTK_CONTAINER (frame), table);
2007
 
 
2008
 
  table2 = gtk_table_new (1, 3, FALSE);
2009
 
  gtk_table_set_col_spacings (GTK_TABLE (table2), 6);
2010
 
  gtk_table_attach (GTK_TABLE (table), table2,
2011
 
                    2, 6, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
2012
 
  gtk_widget_show (table2);
2013
 
 
2014
 
  entry = gimp_scale_entry_new (GTK_TABLE (table2), 0, 0, _("_Smoothing:"),
2015
 
                                100, 0, jsvals.smoothing,
2016
 
                                0.0, 1.0, 0.01, 0.1, 2,
2017
 
                                TRUE, 0.0, 0.0,
2018
 
                                NULL,
2019
 
                                "file-jpeg-save-smoothing");
2020
 
  g_signal_connect (entry, "value_changed",
2021
 
                    G_CALLBACK (gimp_double_adjustment_update),
2022
 
                    &jsvals.smoothing);
2023
 
  g_signal_connect (entry, "value_changed",
2024
 
                    G_CALLBACK (make_preview),
2025
 
                    NULL);
2026
 
 
2027
 
  restart_markers_label = gtk_label_new (_("Frequency (rows):"));
2028
 
  gtk_misc_set_alignment (GTK_MISC (restart_markers_label), 1.0, 0.5);
2029
 
  gtk_table_attach (GTK_TABLE (table), restart_markers_label, 4, 5, 1, 2,
2030
 
                    GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
2031
 
  gtk_widget_show (restart_markers_label);
2032
 
 
2033
 
  restart_markers_scale = spinbutton =
2034
 
    gimp_spin_button_new (&scale_data,
2035
 
                          (jsvals.restart == 0) ? 1 : jsvals.restart,
2036
 
                          1.0, 64.0, 1.0, 1.0, 64.0, 1.0, 0);
2037
 
  gtk_table_attach (GTK_TABLE (table), spinbutton, 5, 6, 1, 2,
2038
 
                    GTK_FILL, GTK_FILL, 0, 0);
2039
 
  gtk_widget_show (spinbutton);
2040
 
 
2041
 
  restart = gtk_check_button_new_with_label (_("Use restart markers"));
2042
 
  gtk_table_attach (GTK_TABLE (table), restart, 2, 4, 1, 2,
2043
 
                    GTK_FILL, 0, 0, 0);
2044
 
  gtk_widget_show (restart);
2045
 
 
2046
 
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (restart), jsvals.restart);
2047
 
 
2048
 
  gtk_widget_set_sensitive (restart_markers_label, jsvals.restart);
2049
 
  gtk_widget_set_sensitive (restart_markers_scale, jsvals.restart);
2050
 
 
2051
 
  g_signal_connect (scale_data, "value_changed",
2052
 
                    G_CALLBACK (save_restart_update),
2053
 
                    restart);
2054
 
  g_signal_connect_swapped (restart, "toggled",
2055
 
                            G_CALLBACK (save_restart_update),
2056
 
                            scale_data);
2057
 
 
2058
 
  toggle = gtk_check_button_new_with_label (_("Optimize"));
2059
 
  gtk_table_attach (GTK_TABLE (table), toggle, 0, 1, 0, 1,
2060
 
                    GTK_FILL, 0, 0, 0);
2061
 
  gtk_widget_show (toggle);
2062
 
 
2063
 
  g_signal_connect (toggle, "toggled",
2064
 
                    G_CALLBACK (gimp_toggle_button_update),
2065
 
                    &jsvals.optimize);
2066
 
  g_signal_connect (toggle, "toggled",
2067
 
                    G_CALLBACK (make_preview),
2068
 
                    NULL);
2069
 
 
2070
 
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), jsvals.optimize);
2071
 
 
2072
 
  progressive = gtk_check_button_new_with_label (_("Progressive"));
2073
 
  gtk_table_attach (GTK_TABLE (table), progressive, 0, 1, 1, 2,
2074
 
                    GTK_FILL, 0, 0, 0);
2075
 
  gtk_widget_show (progressive);
2076
 
 
2077
 
  g_signal_connect (progressive, "toggled",
2078
 
                    G_CALLBACK (gimp_toggle_button_update),
2079
 
                    &jsvals.progressive);
2080
 
  g_signal_connect (progressive, "toggled",
2081
 
                    G_CALLBACK (make_preview),
2082
 
                    NULL);
2083
 
 
2084
 
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (progressive),
2085
 
                                jsvals.progressive);
2086
 
 
2087
 
#ifndef HAVE_PROGRESSIVE_JPEG
2088
 
  gtk_widget_set_sensitive (progressive, FALSE);
2089
 
#endif
2090
 
 
2091
 
  baseline = gtk_check_button_new_with_label (_("Force baseline JPEG"));
2092
 
  gtk_table_attach (GTK_TABLE (table), baseline, 0, 1, 2, 3,
2093
 
                    GTK_FILL, 0, 0, 0);
2094
 
  gtk_widget_show (baseline);
2095
 
 
2096
 
  g_signal_connect (baseline, "toggled",
2097
 
                    G_CALLBACK (gimp_toggle_button_update),
2098
 
                    &jsvals.baseline);
2099
 
  g_signal_connect (baseline, "toggled",
2100
 
                    G_CALLBACK (make_preview),
2101
 
                    NULL);
2102
 
 
2103
 
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (baseline),
2104
 
                                jsvals.baseline);
2105
 
 
2106
 
#ifdef HAVE_EXIF
2107
 
  exif_toggle = gtk_check_button_new_with_label (_("Save EXIF data"));
2108
 
  gtk_table_attach (GTK_TABLE (table), exif_toggle, 0, 1, 3, 4,
2109
 
                    GTK_FILL, 0, 0, 0);
2110
 
  gtk_widget_show (exif_toggle);
2111
 
 
2112
 
  g_signal_connect (exif_toggle, "toggled",
2113
 
                    G_CALLBACK (gimp_toggle_button_update),
2114
 
                    &jsvals.save_exif);
2115
 
  g_signal_connect (exif_toggle, "toggled",
2116
 
                    G_CALLBACK (make_preview),
2117
 
                    NULL);
2118
 
 
2119
 
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (exif_toggle),
2120
 
                                jsvals.save_exif && exif_data);
2121
 
 
2122
 
  gtk_widget_set_sensitive (exif_toggle, exif_data != NULL);
2123
 
 
2124
 
  thumbnail_toggle = gtk_check_button_new_with_label (_("Save thumbnail"));
2125
 
  gtk_table_attach (GTK_TABLE (table), thumbnail_toggle, 0, 1, 4, 5,
2126
 
                    GTK_FILL, 0, 0, 0);
2127
 
  gtk_widget_show (thumbnail_toggle);
2128
 
 
2129
 
  g_signal_connect (thumbnail_toggle, "toggled",
2130
 
                    G_CALLBACK (gimp_toggle_button_update),
2131
 
                    &jsvals.save_thumbnail);
2132
 
  g_signal_connect (thumbnail_toggle, "toggled",
2133
 
                    G_CALLBACK (make_preview),
2134
 
                    NULL);
2135
 
 
2136
 
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (thumbnail_toggle),
2137
 
                                jsvals.save_thumbnail);
2138
 
#endif /* HAVE_EXIF */
2139
 
 
2140
 
  /* Subsampling */
2141
 
  label = gtk_label_new (_("Subsampling:"));
2142
 
  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
2143
 
  gtk_table_attach (GTK_TABLE (table), label, 2, 3, 2, 3,
2144
 
                    GTK_FILL, GTK_FILL, 0, 0);
2145
 
  gtk_widget_show (label);
2146
 
 
2147
 
  combo = gimp_int_combo_box_new ("2x2,1x1,1x1",         0,
2148
 
                                  "2x1,1x1,1x1 (4:2:2)", 1,
2149
 
                                  "1x1,1x1,1x1",         2,
2150
 
                                  NULL);
2151
 
  gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo), jsvals.subsmp);
2152
 
  gtk_table_attach (GTK_TABLE (table), combo, 3, 6, 2, 3,
2153
 
                    GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
2154
 
  gtk_widget_show (combo);
2155
 
 
2156
 
  g_signal_connect (combo, "changed",
2157
 
                    G_CALLBACK (gimp_int_combo_box_get_active),
2158
 
                    &jsvals.subsmp);
2159
 
  g_signal_connect (combo, "changed",
2160
 
                    G_CALLBACK (make_preview),
2161
 
                    NULL);
2162
 
 
2163
 
  dtype = gimp_drawable_type (drawable_ID_global);
2164
 
  if (dtype != GIMP_RGB_IMAGE && dtype != GIMP_RGBA_IMAGE)
2165
 
    gtk_widget_set_sensitive (combo, FALSE);
2166
 
 
2167
 
  /* DCT method */
2168
 
  label = gtk_label_new (_("DCT method:"));
2169
 
  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
2170
 
  gtk_table_attach (GTK_TABLE (table), label, 2, 3, 3, 4,
2171
 
                    GTK_FILL, GTK_FILL, 0, 0);
2172
 
  gtk_widget_show (label);
2173
 
 
2174
 
  combo = gimp_int_combo_box_new (_("Fast Integer"),   1,
2175
 
                                  _("Integer"),        0,
2176
 
                                  _("Floating-Point"), 2,
2177
 
                                  NULL);
2178
 
  gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo), jsvals.dct);
2179
 
  gtk_table_attach (GTK_TABLE (table), combo, 3, 6, 3, 4,
2180
 
                    GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
2181
 
  gtk_widget_show (combo);
2182
 
 
2183
 
  g_signal_connect (combo, "changed",
2184
 
                    G_CALLBACK (gimp_int_combo_box_get_active),
2185
 
                    &jsvals.dct);
2186
 
  g_signal_connect (combo, "changed",
2187
 
                    G_CALLBACK (make_preview),
2188
 
                    NULL);
2189
 
 
2190
 
  frame = gimp_frame_new (_("Comment"));
2191
 
  gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
2192
 
  gtk_widget_show (frame);
2193
 
 
2194
 
  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
2195
 
  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
2196
 
                                       GTK_SHADOW_IN);
2197
 
  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
2198
 
                                  GTK_POLICY_AUTOMATIC,
2199
 
                                  GTK_POLICY_AUTOMATIC);
2200
 
  gtk_widget_set_size_request (scrolled_window, 250, 50);
2201
 
  gtk_container_add (GTK_CONTAINER (frame), scrolled_window);
2202
 
  gtk_widget_show (scrolled_window);
2203
 
 
2204
 
  text_buffer = gtk_text_buffer_new (NULL);
2205
 
  if (image_comment)
2206
 
    gtk_text_buffer_set_text (text_buffer, image_comment, -1);
2207
 
 
2208
 
  text_view = gtk_text_view_new_with_buffer (text_buffer);
2209
 
  gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (text_view), GTK_WRAP_WORD);
2210
 
 
2211
 
  gtk_container_add (GTK_CONTAINER (scrolled_window), text_view);
2212
 
  gtk_widget_show (text_view);
2213
 
 
2214
 
  g_object_unref (text_buffer);
2215
 
 
2216
 
  gtk_widget_show (frame);
2217
 
 
2218
 
  gtk_widget_show (table);
2219
 
  gtk_widget_show (dialog);
2220
 
 
2221
 
  make_preview ();
2222
 
 
2223
 
  run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
2224
 
 
2225
 
  if (run)
2226
 
    {
2227
 
      GtkTextIter start_iter;
2228
 
      GtkTextIter end_iter;
2229
 
 
2230
 
      gtk_text_buffer_get_bounds (text_buffer, &start_iter, &end_iter);
2231
 
      image_comment = gtk_text_buffer_get_text (text_buffer,
2232
 
                                                &start_iter, &end_iter, FALSE);
2233
 
    }
2234
 
 
2235
 
  gtk_widget_destroy (dialog);
2236
 
 
2237
 
  destroy_preview ();
2238
 
  gimp_displays_flush ();
2239
 
 
2240
 
  return run;
2241
 
}
2242
 
 
2243
 
static void
2244
 
save_restart_update (GtkAdjustment *adjustment,
2245
 
                     GtkWidget     *toggle)
2246
 
{
2247
 
  jsvals.restart = GTK_TOGGLE_BUTTON (toggle)->active ? adjustment->value : 0;
2248
 
 
2249
 
  gtk_widget_set_sensitive (restart_markers_label, jsvals.restart);
2250
 
  gtk_widget_set_sensitive (restart_markers_scale, jsvals.restart);
2251
 
 
2252
 
  make_preview ();
2253
 
}
2254
 
 
2255
 
#ifdef HAVE_EXIF
2256
 
 
2257
 
typedef struct
2258
 
{
2259
 
  struct jpeg_source_mgr pub;   /* public fields */
2260
 
 
2261
 
  gchar   *buffer;
2262
 
  gint     size;
2263
 
  JOCTET   terminal[2];
2264
 
} my_source_mgr;
2265
 
 
2266
 
typedef my_source_mgr * my_src_ptr;
2267
 
 
2268
 
static void
2269
 
init_source (j_decompress_ptr cinfo)
2270
 
{
2271
 
}
2272
 
 
2273
 
 
2274
 
static boolean
2275
 
fill_input_buffer (j_decompress_ptr cinfo)
2276
 
{
2277
 
  my_src_ptr src = (my_src_ptr) cinfo->src;
2278
 
 
2279
 
  /* Since we have given all we have got already
2280
 
   * we simply fake an end of file
2281
 
   */
2282
 
 
2283
 
  src->pub.next_input_byte = src->terminal;
2284
 
  src->pub.bytes_in_buffer = 2;
2285
 
  src->terminal[0]         = (JOCTET) 0xFF;
2286
 
  src->terminal[1]         = (JOCTET) JPEG_EOI;
2287
 
 
2288
 
  return TRUE;
2289
 
}
2290
 
 
2291
 
static void
2292
 
skip_input_data (j_decompress_ptr cinfo,
2293
 
                 long             num_bytes)
2294
 
{
2295
 
  my_src_ptr src = (my_src_ptr) cinfo->src;
2296
 
 
2297
 
  src->pub.next_input_byte = src->pub.next_input_byte + num_bytes;
2298
 
}
2299
 
 
2300
 
static void
2301
 
term_source (j_decompress_ptr cinfo)
2302
 
{
2303
 
}
2304
 
 
2305
 
static gint32
2306
 
load_thumbnail_image (const gchar *filename,
2307
 
                      gint        *width,
2308
 
                      gint        *height)
2309
 
{
2310
 
  gint32 volatile  image_ID;
2311
 
  ExifData        *exif_data;
2312
 
  GimpPixelRgn     pixel_rgn;
2313
 
  GimpDrawable    *drawable;
2314
 
  gint32           layer_ID;
2315
 
  struct jpeg_decompress_struct cinfo;
2316
 
  struct my_error_mgr           jerr;
2317
 
  guchar     *buf;
2318
 
  guchar  * volatile padded_buf = NULL;
2319
 
  guchar    **rowbuf;
2320
 
  gint        image_type;
2321
 
  gint        layer_type;
2322
 
  gint        tile_height;
2323
 
  gint        scanlines;
2324
 
  gint        i, start, end;
2325
 
  my_src_ptr  src;
2326
 
  FILE       *infile;
2327
 
 
2328
 
  image_ID = -1;
2329
 
  exif_data = exif_data_new_from_file (filename);
2330
 
 
2331
 
  if (! ((exif_data) && (exif_data->data) && (exif_data->size > 0)))
2332
 
    return -1;
2333
 
 
2334
 
  cinfo.err = jpeg_std_error (&jerr.pub);
2335
 
  jerr.pub.error_exit = my_error_exit;
2336
 
 
2337
 
  cinfo.client_data = GINT_TO_POINTER (FALSE);
2338
 
 
2339
 
  jerr.pub.emit_message   = my_emit_message;
2340
 
  jerr.pub.output_message = my_output_message;
2341
 
 
2342
 
  {
2343
 
    gchar *name = g_strdup_printf (_("Opening thumbnail for '%s'..."),
2344
 
                                   gimp_filename_to_utf8 (filename));
2345
 
    gimp_progress_init (name);
2346
 
    g_free (name);
2347
 
  }
2348
 
 
2349
 
  /* Establish the setjmp return context for my_error_exit to use. */
2350
 
  if (setjmp (jerr.setjmp_buffer))
2351
 
    {
2352
 
      /* If we get here, the JPEG code has signaled an error.  We
2353
 
       * need to clean up the JPEG object, close the input file,
2354
 
       * and return.
2355
 
       */
2356
 
      jpeg_destroy_decompress (&cinfo);
2357
 
 
2358
 
      if (image_ID != -1)
2359
 
        gimp_image_delete (image_ID);
2360
 
 
2361
 
      if (exif_data)
2362
 
        {
2363
 
          exif_data_unref (exif_data);
2364
 
          exif_data = NULL;
2365
 
        }
2366
 
 
2367
 
      return -1;
2368
 
    }
2369
 
 
2370
 
  /* Now we can initialize the JPEG decompression object. */
2371
 
  jpeg_create_decompress (&cinfo);
2372
 
 
2373
 
  /* Step 2: specify data source (eg, a file) */
2374
 
 
2375
 
  if (cinfo.src == NULL)
2376
 
    cinfo.src = (struct jpeg_source_mgr *)(*cinfo.mem->alloc_small)
2377
 
      ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
2378
 
       sizeof (my_source_mgr));
2379
 
 
2380
 
  src = (my_src_ptr) cinfo.src;
2381
 
 
2382
 
  src->pub.init_source       = init_source;
2383
 
  src->pub.fill_input_buffer = fill_input_buffer;
2384
 
  src->pub.skip_input_data   = skip_input_data;
2385
 
  src->pub.resync_to_restart = jpeg_resync_to_restart;
2386
 
  src->pub.term_source       = term_source;
2387
 
 
2388
 
  src->pub.bytes_in_buffer   = exif_data->size;
2389
 
  src->pub.next_input_byte   = exif_data->data;
2390
 
 
2391
 
  src->buffer = exif_data->data;
2392
 
  src->size = exif_data->size;
2393
 
 
2394
 
  /* Step 3: read file parameters with jpeg_read_header() */
2395
 
 
2396
 
  jpeg_read_header (&cinfo, TRUE);
2397
 
 
2398
 
  /* Step 4: set parameters for decompression */
2399
 
 
2400
 
  /* In this example, we don't need to change any of the defaults set by
2401
 
   * jpeg_read_header(), so we do nothing here.
2402
 
   */
2403
 
 
2404
 
  /* Step 5: Start decompressor */
2405
 
 
2406
 
  jpeg_start_decompress (&cinfo);
2407
 
 
2408
 
  /* We may need to do some setup of our own at this point before
2409
 
   * reading the data.  After jpeg_start_decompress() we have the
2410
 
   * correct scaled output image dimensions available, as well as
2411
 
   * the output colormap if we asked for color quantization.  In
2412
 
   * this example, we need to make an output work buffer of the
2413
 
   * right size.
2414
 
   */
2415
 
 
2416
 
  /* temporary buffer */
2417
 
  tile_height = gimp_tile_height ();
2418
 
  buf = g_new (guchar,
2419
 
               tile_height * cinfo.output_width * cinfo.output_components);
2420
 
 
2421
 
  rowbuf = g_new (guchar *, tile_height);
2422
 
 
2423
 
  for (i = 0; i < tile_height; i++)
2424
 
    rowbuf[i] = buf + cinfo.output_width * cinfo.output_components * i;
2425
 
 
2426
 
  /* Create a new image of the proper size and associate the
2427
 
   * filename with it.
2428
 
   *
2429
 
   * Preview layers, not being on the bottom of a layer stack,
2430
 
   * MUST HAVE AN ALPHA CHANNEL!
2431
 
   */
2432
 
  switch (cinfo.output_components)
2433
 
    {
2434
 
    case 1:
2435
 
      image_type = GIMP_GRAY;
2436
 
      layer_type = GIMP_GRAY_IMAGE;
2437
 
      break;
2438
 
 
2439
 
    case 3:
2440
 
      image_type = GIMP_RGB;
2441
 
      layer_type = GIMP_RGB_IMAGE;
2442
 
      break;
2443
 
 
2444
 
    case 4:
2445
 
      if (cinfo.out_color_space == JCS_CMYK)
2446
 
        {
2447
 
          image_type = GIMP_RGB;
2448
 
          layer_type = GIMP_RGB_IMAGE;
2449
 
          break;
2450
 
        }
2451
 
      /*fallthrough*/
2452
 
 
2453
 
    default:
2454
 
      g_message ("Don't know how to load JPEGs\n"
2455
 
                 "with %d color channels\n"
2456
 
                 "using colorspace %d (%d)",
2457
 
                 cinfo.output_components, cinfo.out_color_space,
2458
 
                 cinfo.jpeg_color_space);
2459
 
 
2460
 
      if (exif_data)
2461
 
        {
2462
 
          exif_data_unref (exif_data);
2463
 
          exif_data = NULL;
2464
 
        }
2465
 
 
2466
 
      return -1;
2467
 
      break;
2468
 
    }
2469
 
 
2470
 
  if (cinfo.out_color_space == JCS_CMYK)
2471
 
    padded_buf = g_new (guchar, tile_height * cinfo.output_width * 3);
2472
 
  else
2473
 
    padded_buf = NULL;
2474
 
 
2475
 
  image_ID = gimp_image_new (cinfo.output_width, cinfo.output_height,
2476
 
                             image_type);
2477
 
  gimp_image_set_filename (image_ID, filename);
2478
 
 
2479
 
  layer_ID = gimp_layer_new (image_ID, _("Background"),
2480
 
                             cinfo.output_width,
2481
 
                             cinfo.output_height,
2482
 
                             layer_type, 100, GIMP_NORMAL_MODE);
2483
 
 
2484
 
  drawable_global = drawable = gimp_drawable_get (layer_ID);
2485
 
  gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0,
2486
 
                       drawable->width, drawable->height, TRUE, FALSE);
2487
 
 
2488
 
  /* Step 5.1: if the file had resolution information, set it on the image */
2489
 
  if (cinfo.saw_JFIF_marker)
2490
 
    {
2491
 
      gdouble xresolution;
2492
 
      gdouble yresolution;
2493
 
      gdouble asymmetry;
2494
 
 
2495
 
      xresolution = cinfo.X_density;
2496
 
      yresolution = cinfo.Y_density;
2497
 
 
2498
 
      switch (cinfo.density_unit)
2499
 
        {
2500
 
        case 0: /* unknown -> set the aspect ratio but use the default
2501
 
                 *  image resolution
2502
 
                 */
2503
 
          if (cinfo.Y_density != 0)
2504
 
            asymmetry = xresolution / yresolution;
2505
 
          else
2506
 
            asymmetry = 1.0;
2507
 
 
2508
 
          gimp_image_get_resolution (image_ID, &xresolution, &yresolution);
2509
 
          xresolution *= asymmetry;
2510
 
          break;
2511
 
 
2512
 
        case 1: /* dots per inch */
2513
 
          break;
2514
 
 
2515
 
        case 2: /* dots per cm */
2516
 
          xresolution *= 2.54;
2517
 
          yresolution *= 2.54;
2518
 
          gimp_image_set_unit (image_ID, GIMP_UNIT_MM);
2519
 
          break;
2520
 
 
2521
 
        default:
2522
 
          g_message ("Unknown density unit %d\nassuming dots per inch",
2523
 
                     cinfo.density_unit);
2524
 
          break;
2525
 
        }
2526
 
 
2527
 
      gimp_image_set_resolution (image_ID, xresolution, yresolution);
2528
 
    }
2529
 
 
2530
 
  /* Step 6: while (scan lines remain to be read) */
2531
 
  /*           jpeg_read_scanlines(...); */
2532
 
 
2533
 
  /* Here we use the library's state variable cinfo.output_scanline as the
2534
 
   * loop counter, so that we don't have to keep track ourselves.
2535
 
   */
2536
 
  while (cinfo.output_scanline < cinfo.output_height)
2537
 
    {
2538
 
      start = cinfo.output_scanline;
2539
 
      end   = cinfo.output_scanline + tile_height;
2540
 
      end   = MIN (end, cinfo.output_height);
2541
 
      scanlines = end - start;
2542
 
 
2543
 
      for (i = 0; i < scanlines; i++)
2544
 
        jpeg_read_scanlines (&cinfo, (JSAMPARRAY) &rowbuf[i], 1);
2545
 
 
2546
 
      if (cinfo.out_color_space == JCS_CMYK) /* buf-> RGB in padded_buf */
2547
 
        {
2548
 
          guchar *dest = padded_buf;
2549
 
          guchar *src  = buf;
2550
 
          gint    num  = drawable->width * scanlines;
2551
 
 
2552
 
          for (i = 0; i < num; i++)
2553
 
            {
2554
 
              guint r_c, g_m, b_y, a_k;
2555
 
 
2556
 
              r_c = *(src++);
2557
 
              g_m = *(src++);
2558
 
              b_y = *(src++);
2559
 
              a_k = *(src++);
2560
 
              *(dest++) = (r_c * a_k) / 255;
2561
 
              *(dest++) = (g_m * a_k) / 255;
2562
 
              *(dest++) = (b_y * a_k) / 255;
2563
 
            }
2564
 
        }
2565
 
 
2566
 
      gimp_pixel_rgn_set_rect (&pixel_rgn, padded_buf ? padded_buf : buf,
2567
 
                               0, start, drawable->width, scanlines);
2568
 
 
2569
 
      gimp_progress_update ((gdouble) cinfo.output_scanline /
2570
 
                            (gdouble) cinfo.output_height);
2571
 
    }
2572
 
 
2573
 
  /* Step 7: Finish decompression */
2574
 
 
2575
 
  jpeg_finish_decompress (&cinfo);
2576
 
  /* We can ignore the return value since suspension is not possible
2577
 
   * with the stdio data source.
2578
 
   */
2579
 
 
2580
 
  /* Step 8: Release JPEG decompression object */
2581
 
 
2582
 
  /* This is an important step since it will release a good deal
2583
 
   * of memory.
2584
 
   */
2585
 
  jpeg_destroy_decompress (&cinfo);
2586
 
 
2587
 
  /* free up the temporary buffers */
2588
 
  g_free (rowbuf);
2589
 
  g_free (buf);
2590
 
  g_free (padded_buf);
2591
 
 
2592
 
  /* At this point you may want to check to see whether any
2593
 
   * corrupt-data warnings occurred (test whether
2594
 
   * jerr.num_warnings is nonzero).
2595
 
   */
2596
 
  gimp_image_add_layer (image_ID, layer_ID, 0);
2597
 
 
2598
 
 
2599
 
  /* NOW to get the dimensions of the actual image to return the
2600
 
   * calling app
2601
 
   */
2602
 
  cinfo.err = jpeg_std_error (&jerr.pub);
2603
 
  jerr.pub.error_exit = my_error_exit;
2604
 
 
2605
 
  cinfo.client_data = GINT_TO_POINTER (FALSE);
2606
 
 
2607
 
  jerr.pub.emit_message   = my_emit_message;
2608
 
  jerr.pub.output_message = my_output_message;
2609
 
 
2610
 
  if ((infile = fopen (filename, "rb")) == NULL)
2611
 
    {
2612
 
      g_message (_("Could not open '%s' for reading: %s"),
2613
 
                 gimp_filename_to_utf8 (filename), g_strerror (errno));
2614
 
 
2615
 
      if (exif_data)
2616
 
        {
2617
 
          exif_data_unref (exif_data);
2618
 
          exif_data = NULL;
2619
 
        }
2620
 
 
2621
 
      return -1;
2622
 
    }
2623
 
 
2624
 
  /* Establish the setjmp return context for my_error_exit to use. */
2625
 
  if (setjmp (jerr.setjmp_buffer))
2626
 
    {
2627
 
      /* If we get here, the JPEG code has signaled an error.  We
2628
 
       * need to clean up the JPEG object, close the input file,
2629
 
       * and return.
2630
 
       */
2631
 
      jpeg_destroy_decompress (&cinfo);
2632
 
 
2633
 
      if (image_ID != -1)
2634
 
        gimp_image_delete (image_ID);
2635
 
 
2636
 
      if (exif_data)
2637
 
        {
2638
 
          exif_data_unref (exif_data);
2639
 
          exif_data = NULL;
2640
 
        }
2641
 
 
2642
 
      return -1;
2643
 
    }
2644
 
 
2645
 
  /* Now we can initialize the JPEG decompression object. */
2646
 
  jpeg_create_decompress (&cinfo);
2647
 
 
2648
 
  /* Step 2: specify data source (eg, a file) */
2649
 
 
2650
 
  jpeg_stdio_src (&cinfo, infile);
2651
 
 
2652
 
  /* Step 3: read file parameters with jpeg_read_header() */
2653
 
 
2654
 
  jpeg_read_header (&cinfo, TRUE);
2655
 
 
2656
 
  jpeg_start_decompress (&cinfo);
2657
 
 
2658
 
  *width  = cinfo.output_width;
2659
 
  *height = cinfo.output_height;
2660
 
 
2661
 
  /* Step 4: Release JPEG decompression object */
2662
 
 
2663
 
  /* This is an important step since it will release a good deal
2664
 
   * of memory.
2665
 
   */
2666
 
  jpeg_destroy_decompress (&cinfo);
2667
 
 
2668
 
  if (exif_data)
2669
 
    {
2670
 
      exif_data_unref (exif_data);
2671
 
      exif_data = NULL;
2672
 
    }
2673
 
 
2674
 
  return image_ID;
2675
 
}
2676
 
 
2677
 
static gchar *tbuffer = NULL;
2678
 
static gchar *tbuffer2 = NULL;
2679
 
 
2680
 
static gint tbuffer_count = 0;
2681
 
 
2682
 
typedef struct
2683
 
{
2684
 
  struct jpeg_destination_mgr  pub;   /* public fields */
2685
 
  gchar                       *buffer;
2686
 
  gint                         size;
2687
 
} my_destination_mgr;
2688
 
 
2689
 
typedef my_destination_mgr *my_dest_ptr;
2690
 
 
2691
 
void
2692
 
init_destination (j_compress_ptr cinfo)
2693
 
{
2694
 
}
2695
 
 
2696
 
gboolean
2697
 
empty_output_buffer (j_compress_ptr cinfo)
2698
 
{
2699
 
  my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
2700
 
 
2701
 
  tbuffer_count = tbuffer_count + 16384;
2702
 
  tbuffer = (gchar *) g_realloc(tbuffer, tbuffer_count);
2703
 
  g_memmove (tbuffer + tbuffer_count - 16384, tbuffer2, 16384);
2704
 
 
2705
 
  dest->pub.next_output_byte = tbuffer2;
2706
 
  dest->pub.free_in_buffer   = 16384;
2707
 
 
2708
 
  return TRUE;
2709
 
}
2710
 
 
2711
 
void
2712
 
term_destination (j_compress_ptr cinfo)
2713
 
{
2714
 
  my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
2715
 
 
2716
 
  tbuffer_count = (tbuffer_count + 16384) - (dest->pub.free_in_buffer);
2717
 
 
2718
 
  tbuffer = (gchar *) g_realloc (tbuffer, tbuffer_count);
2719
 
  g_memmove(tbuffer + tbuffer_count - (16384 - dest->pub.free_in_buffer), tbuffer2, 16384 - dest->pub.free_in_buffer);
2720
 
}
2721
 
 
2722
 
static gint
2723
 
create_thumbnail (gint32   image_ID,
2724
 
                  gint32   drawable_ID,
2725
 
                  gdouble  quality,
2726
 
                  gchar  **thumbnail_buffer)
2727
 
{
2728
 
  GimpDrawable  *drawable;
2729
 
  gint           req_width, req_height, bpp, rbpp;
2730
 
  guchar        *thumbnail_data = NULL;
2731
 
  struct jpeg_compress_struct cinfo;
2732
 
  struct my_error_mgr         jerr;
2733
 
  my_dest_ptr dest;
2734
 
  gboolean  alpha = FALSE;
2735
 
  JSAMPROW  scanline[1];
2736
 
  guchar   *buf = NULL;
2737
 
  gint      i;
2738
 
 
2739
 
  drawable = gimp_drawable_get (drawable_ID);
2740
 
 
2741
 
  req_width  = 196;
2742
 
  req_height = 196;
2743
 
 
2744
 
  if (MIN (drawable->width, drawable->height) < 196)
2745
 
    req_width = req_height = MIN(drawable->width, drawable->height);
2746
 
 
2747
 
  thumbnail_data = gimp_drawable_get_thumbnail_data (drawable_ID,
2748
 
                                                     &req_width, &req_height,
2749
 
                                                     &bpp);
2750
 
 
2751
 
  if (! thumbnail_data)
2752
 
    return 0;
2753
 
 
2754
 
  rbpp = bpp;
2755
 
 
2756
 
  if ((bpp == 2) || (bpp == 4))
2757
 
    {
2758
 
      alpha = TRUE;
2759
 
      rbpp = bpp - 1;
2760
 
    }
2761
 
 
2762
 
  buf = g_new (guchar, req_width * bpp);
2763
 
  tbuffer2 = g_new (gchar, 16384);
2764
 
 
2765
 
  tbuffer_count = 0;
2766
 
 
2767
 
  cinfo.err = jpeg_std_error (&jerr.pub);
2768
 
  jerr.pub.error_exit = my_error_exit;
2769
 
 
2770
 
  /* Establish the setjmp return context for my_error_exit to use. */
2771
 
  if (setjmp (jerr.setjmp_buffer))
2772
 
    {
2773
 
      /* If we get here, the JPEG code has signaled an error.
2774
 
       * We need to clean up the JPEG object, free memory, and return.
2775
 
       */
2776
 
      jpeg_destroy_compress (&cinfo);
2777
 
 
2778
 
      if (thumbnail_data)
2779
 
        {
2780
 
          g_free (thumbnail_data);
2781
 
          thumbnail_data = NULL;
2782
 
        }
2783
 
 
2784
 
      if (buf)
2785
 
        {
2786
 
          g_free (buf);
2787
 
          buf = NULL;
2788
 
        }
2789
 
 
2790
 
      if (tbuffer2)
2791
 
        {
2792
 
          g_free (tbuffer2);
2793
 
          tbuffer2 = NULL;
2794
 
        }
2795
 
 
2796
 
      if (drawable)
2797
 
        gimp_drawable_detach (drawable);
2798
 
 
2799
 
      return 0;
2800
 
    }
2801
 
 
2802
 
  /* Now we can initialize the JPEG compression object. */
2803
 
  jpeg_create_compress (&cinfo);
2804
 
 
2805
 
  if (cinfo.dest == NULL)
2806
 
    cinfo.dest = (struct jpeg_destination_mgr *)
2807
 
      (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo, JPOOL_PERMANENT,
2808
 
                                 sizeof(my_destination_mgr));
2809
 
 
2810
 
  dest = (my_dest_ptr) cinfo.dest;
2811
 
  dest->pub.init_destination    = init_destination;
2812
 
  dest->pub.empty_output_buffer = empty_output_buffer;
2813
 
  dest->pub.term_destination    = term_destination;
2814
 
 
2815
 
  dest->pub.next_output_byte = tbuffer2;
2816
 
  dest->pub.free_in_buffer   = 16384;
2817
 
 
2818
 
  dest->buffer = tbuffer2;
2819
 
  dest->size   = 16384;
2820
 
 
2821
 
  cinfo.input_components = rbpp;
2822
 
  cinfo.image_width      = req_width;
2823
 
  cinfo.image_height     = req_height;
2824
 
 
2825
 
  /* colorspace of input image */
2826
 
  cinfo.in_color_space = (rbpp == 3) ? JCS_RGB : JCS_GRAYSCALE;
2827
 
 
2828
 
  /* Now use the library's routine to set default compression parameters.
2829
 
   * (You must set at least cinfo.in_color_space before calling this,
2830
 
   * since the defaults depend on the source color space.)
2831
 
   */
2832
 
  jpeg_set_defaults (&cinfo);
2833
 
 
2834
 
  jpeg_set_quality (&cinfo, (gint) (quality + 0.5), jsvals.baseline);
2835
 
 
2836
 
  /* Step 4: Start compressor */
2837
 
 
2838
 
  /* TRUE ensures that we will write a complete interchange-JPEG file.
2839
 
   * Pass TRUE unless you are very sure of what you're doing.
2840
 
   */
2841
 
  jpeg_start_compress (&cinfo, TRUE);
2842
 
 
2843
 
  while (cinfo.next_scanline < (unsigned int) req_height)
2844
 
    {
2845
 
      for (i = 0; i < req_width; i++)
2846
 
        {
2847
 
          buf[(i * rbpp) + 0] = thumbnail_data[(cinfo.next_scanline * req_width * bpp) + (i * bpp) + 0];
2848
 
 
2849
 
          if (rbpp == 3)
2850
 
            {
2851
 
              buf[(i * rbpp) + 1] = thumbnail_data[(cinfo.next_scanline * req_width * bpp) + (i * bpp) + 1];
2852
 
              buf[(i * rbpp) + 2] = thumbnail_data[(cinfo.next_scanline * req_width * bpp) + (i * bpp) + 2];
2853
 
            }
2854
 
        }
2855
 
 
2856
 
      scanline[0] = buf;
2857
 
      jpeg_write_scanlines (&cinfo, scanline, 1);
2858
 
  }
2859
 
 
2860
 
  /* Step 6: Finish compression */
2861
 
  jpeg_finish_compress (&cinfo);
2862
 
 
2863
 
  /* Step 7: release JPEG compression object */
2864
 
 
2865
 
  /* This is an important step since it will release a good deal of memory. */
2866
 
  jpeg_destroy_compress (&cinfo);
2867
 
 
2868
 
  /* And we're done! */
2869
 
 
2870
 
  if (thumbnail_data)
2871
 
    {
2872
 
      g_free (thumbnail_data);
2873
 
      thumbnail_data = NULL;
2874
 
    }
2875
 
 
2876
 
  if (buf)
2877
 
    {
2878
 
      g_free (buf);
2879
 
      buf = NULL;
2880
 
    }
2881
 
 
2882
 
  if (drawable)
2883
 
    {
2884
 
      gimp_drawable_detach (drawable);
2885
 
      drawable = NULL;
2886
 
    }
2887
 
 
2888
 
  *thumbnail_buffer = tbuffer;
2889
 
 
2890
 
  return tbuffer_count;
2891
 
}
2892
 
 
2893
 
#endif /* HAVE_EXIF */