1
/* The GIMP -- an image manipulation program
2
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
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.
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.
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.
19
/* JPEG loading and saving file filter for the GIMP
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.
27
/* 11-JAN-99 - Added support for JPEG comments and Progressive saves.
28
* -pete whiting <pwhiting@sprint.net>
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.
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>
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...).
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.)
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.
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.
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.)
90
* ...and thus ends my additions to the JPEG plug-in. I hope. *sigh* :-)
94
* 21-AUG-99 - Bunch O' Fixes.
95
* - Adam D. Moss <adam@gimp.org>
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.
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
107
* 22-DEC-99 - volatiles added
108
* - Austin Donnelly <austin@gimp.org>
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.
123
* 4-SEP-01 - remove the use of GtkText
124
* - DindinX <David@dindinx.org>
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;
132
* 22-JUN-03 - add support for keeping EXIF information
133
* - Dave Neary <bolsh@gimp.org>
135
* This is little more than a modified version fo a patch from the
136
* libexif owner (Lutz Muller) which attaches exif information to
137
* 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.
143
* 15-NOV-04 - add support for EXIF JPEG thumbnail reading and writing
144
* - S. Mukund <muks@mukund.org>
146
* Digital cameras store a TIFF APP1 marker that contains various
147
* parameters of the shot along with a thumbnail image.
151
* 14-JAN-05 - avoid to write more than 65533 bytes of EXIF marker length
152
* - Nils Philippsen <nphilipp@redhat.com>
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.
159
#include "config.h" /* configure cares about HAVE_PROGRESSIVE_JPEG */
161
#include <glib.h> /* We want glib.h first because of some
162
* pretty obscure Win32 compilation issues.
170
#include <sys/types.h>
171
#include <sys/stat.h>
179
#include <libexif/exif-data.h>
181
#define MARKER_CODE_EXIF 0xE1
182
#endif /* HAVE_EXIF */
184
#include <libgimp/gimp.h>
185
#include <libgimp/gimpui.h>
187
#include "libgimp/stdplugins-intl.h"
189
#define SCALE_WIDTH 125
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 */
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
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;
225
gboolean progressive;
232
gboolean save_thumbnail;
237
struct jpeg_compress_struct cinfo;
238
struct jpeg_error_mgr jerr;
246
GimpDrawable *drawable;
247
GimpPixelRgn pixel_rgn;
248
const gchar *file_name;
252
static gboolean *abort_me = NULL;
255
/* Declare local functions.
257
static void query (void);
258
static void run (const gchar *name,
260
const GimpParam *param,
262
GimpParam **return_vals);
263
static gint32 load_image (const gchar *filename,
268
static gint32 load_thumbnail_image(const gchar *filename,
272
static gint create_thumbnail (gint32 image_ID,
275
gchar **thumbnail_buffer);
277
#endif /* HAVE_EXIF */
279
static gboolean save_image (const gchar *filename,
282
gint32 orig_image_ID,
285
static gboolean save_dialog (void);
287
static void make_preview (void);
288
static void destroy_preview (void);
290
static void save_restart_update (GtkAdjustment *adjustment,
294
GimpPlugInInfo PLUG_IN_INFO =
296
NULL, /* init_proc */
297
NULL, /* quit_proc */
298
query, /* query_proc */
302
static JpegSaveVals jsvals =
318
static gchar *image_comment = NULL;
319
static GtkWidget *restart_markers_scale = NULL;
320
static GtkWidget *restart_markers_label = NULL;
323
static ExifData *exif_data = NULL;
324
#endif /* HAVE_EXIF */
333
static GimpParamDef load_args[] =
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" }
339
static GimpParamDef load_return_vals[] =
341
{ GIMP_PDB_IMAGE, "image", "Output image" }
346
static GimpParamDef thumb_args[] =
348
{ GIMP_PDB_STRING, "filename", "The name of the file to load" },
349
{ GIMP_PDB_INT32, "thumb_size", "Preferred thumbnail size" }
351
static GimpParamDef thumb_return_vals[] =
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" }
358
#endif /* HAVE_EXIF */
360
static GimpParamDef save_args[] =
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)" }
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",
387
G_N_ELEMENTS (load_args),
388
G_N_ELEMENTS (load_return_vals),
389
load_args, load_return_vals);
391
gimp_register_file_handler_mime ("file_jpeg_load", "image/jpeg");
392
gimp_register_magic_load_handler ("file_jpeg_load",
395
"6,string,JFIF,6,string,Exif");
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>",
408
G_N_ELEMENTS (thumb_args),
409
G_N_ELEMENTS (thumb_return_vals),
410
thumb_args, thumb_return_vals);
412
gimp_register_thumbnail_loader ("file_jpeg_load", "file_jpeg_load_thumb");
414
#endif /* HAVE_EXIF */
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",
425
G_N_ELEMENTS (save_args), 0,
428
gimp_register_file_handler_mime ("file_jpeg_save", "image/jpeg");
429
gimp_register_save_handler ("file_jpeg_save", "jpg,jpeg,jpe", "");
433
run (const gchar *name,
435
const GimpParam *param,
437
GimpParam **return_vals)
439
static GimpParam values[4];
440
GimpRunMode run_mode;
441
GimpPDBStatusType status = GIMP_PDB_SUCCESS;
444
gint32 orig_image_ID;
445
GimpParasite *parasite;
447
GimpExportReturn export = GIMP_EXPORT_CANCEL;
449
run_mode = param[0].data.d_int32;
454
*return_vals = values;
455
values[0].type = GIMP_PDB_STATUS;
456
values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
458
if (strcmp (name, "file_jpeg_load") == 0)
460
image_ID = load_image (param[1].data.d_string, run_mode, FALSE);
465
values[1].type = GIMP_PDB_IMAGE;
466
values[1].data.d_image = image_ID;
470
status = GIMP_PDB_EXECUTION_ERROR;
476
else if (strcmp (name, "file_jpeg_load_thumb") == 0)
480
status = GIMP_PDB_CALLING_ERROR;
484
const gchar *filename = param[0].data.d_string;
489
image_ID = load_thumbnail_image (filename, &width, &height);
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;
503
status = GIMP_PDB_EXECUTION_ERROR;
508
#endif /* HAVE_EXIF */
510
else if (strcmp (name, "file_jpeg_save") == 0)
512
image_ID = orig_image_ID = param[1].data.d_int32;
513
drawable_ID = param[2].data.d_int32;
515
/* eventually export the image */
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));
526
case GIMP_EXPORT_EXPORT:
528
gchar *tmp = g_filename_from_utf8 (_("Export Preview"), -1,
532
gimp_image_set_filename (image_ID, tmp);
539
case GIMP_EXPORT_IGNORE:
541
case GIMP_EXPORT_CANCEL:
542
values[0].data.d_status = GIMP_PDB_CANCEL;
552
exif_data_unref (exif_data);
554
#endif /* HAVE_EXIF */
556
g_free (image_comment);
557
image_comment = NULL;
559
parasite = gimp_image_parasite_find (orig_image_ID, "gimp-comment");
562
image_comment = g_strndup (gimp_parasite_data (parasite),
563
gimp_parasite_data_size (parasite));
564
gimp_parasite_free (parasite);
569
parasite = gimp_image_parasite_find (orig_image_ID, "exif-data");
572
exif_data = exif_data_new_from_data (gimp_parasite_data (parasite),
573
gimp_parasite_data_size (parasite));
574
gimp_parasite_free (parasite);
577
#endif /* HAVE_EXIF */
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;
593
if (exif_data && (exif_data->data))
594
jsvals.save_thumbnail = TRUE;
596
#endif /* HAVE_EXIF */
600
case GIMP_RUN_INTERACTIVE:
601
/* Possibly retrieve data */
602
gimp_get_data ("file_jpeg_save", &jsvals);
604
/* load up the previously used values */
605
parasite = gimp_image_parasite_find (orig_image_ID,
606
"jpeg-save-options");
609
const JpegSaveVals *save_vals = gimp_parasite_data (parasite);
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;
623
gimp_parasite_free (parasite);
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);
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;
640
/* First acquire information with a dialog */
641
err = save_dialog ();
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 ();
652
status = GIMP_PDB_CANCEL;
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 */
661
status = GIMP_PDB_CALLING_ERROR;
665
/* Once the PDB gets default parameters, remove this hack */
666
if (param[5].data.d_float > 0.05)
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;
679
/* free up the default -- wasted some effort earlier */
680
g_free (image_comment);
681
image_comment = g_strdup (param[9].data.d_string);
684
jsvals.preview = FALSE;
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;
697
case GIMP_RUN_WITH_LAST_VALS:
698
/* Possibly retrieve data */
699
gimp_get_data ("file_jpeg_save", &jsvals);
701
parasite = gimp_image_parasite_find (orig_image_ID,
702
"jpeg-save-options");
705
const JpegSaveVals *save_vals = gimp_parasite_data (parasite);
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;
717
gimp_parasite_free (parasite);
725
if (status == GIMP_PDB_SUCCESS)
727
if (save_image (param[3].data.d_string,
733
/* Store mvals data */
734
gimp_set_data ("file_jpeg_save", &jsvals, sizeof (JpegSaveVals));
738
status = GIMP_PDB_EXECUTION_ERROR;
742
if (export == GIMP_EXPORT_EXPORT)
744
/* If the image was exported, delete the new display. */
745
/* This also deletes the image. */
747
if (display_ID != -1)
748
gimp_display_delete (display_ID);
750
gimp_image_delete (image_ID);
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. */
757
gimp_image_parasite_detach (orig_image_ID, "gimp-comment");
758
if (image_comment && strlen (image_comment))
760
parasite = gimp_parasite_new ("gimp-comment",
761
GIMP_PARASITE_PERSISTENT,
762
strlen (image_comment) + 1,
764
gimp_image_parasite_attach (orig_image_ID, parasite);
765
gimp_parasite_free (parasite);
767
gimp_image_parasite_detach (orig_image_ID, "jpeg-save-options");
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);
776
status = GIMP_PDB_CALLING_ERROR;
779
values[0].data.d_status = status;
784
jpeg_getc (j_decompress_ptr cinfo)
786
struct jpeg_source_mgr *datasrc = cinfo->src;
788
if (datasrc->bytes_in_buffer == 0)
790
if (! (*datasrc->fill_input_buffer) (cinfo))
791
ERREXIT (cinfo, JERR_CANT_SUSPEND);
793
datasrc->bytes_in_buffer--;
795
return *datasrc->next_input_byte++;
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
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.
807
static GString *local_image_comments = NULL;
810
COM_handler (j_decompress_ptr cinfo)
815
length = jpeg_getc (cinfo) << 8;
816
length += jpeg_getc (cinfo);
819
length -= 2; /* discount the length word itself */
821
if (!local_image_comments)
822
local_image_comments = g_string_new (NULL);
824
g_string_append_c (local_image_comments, '\n');
828
ch = jpeg_getc (cinfo);
829
g_string_append_c (local_image_comments, ch);
835
typedef struct my_error_mgr
837
struct jpeg_error_mgr pub; /* "public" fields */
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
847
jmp_buf setjmp_buffer; /* for return to caller */
851
* Here's the routine that will replace the standard error_exit method:
855
my_error_exit (j_common_ptr cinfo)
857
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
858
my_error_ptr myerr = (my_error_ptr) cinfo->err;
860
/* Always display the message. */
861
/* We could postpone this until after returning, if we chose. */
862
(*cinfo->err->output_message) (cinfo);
864
/* Return control to the setjmp point */
865
longjmp (myerr->setjmp_buffer, 1);
869
my_emit_message (j_common_ptr cinfo,
874
/* disable loading of EXIF data */
875
cinfo->client_data = GINT_TO_POINTER (TRUE);
877
(*cinfo->err->output_message) (cinfo);
882
my_output_message (j_common_ptr cinfo)
884
gchar buffer[JMSG_LENGTH_MAX + 1];
886
(*cinfo->err->format_message)(cinfo, buffer);
888
if (GPOINTER_TO_INT (cinfo->client_data))
890
gchar *msg = g_strconcat (buffer,
892
_("EXIF data will be ignored."),
904
load_image (const gchar *filename,
908
GimpPixelRgn pixel_rgn;
909
GimpDrawable *drawable;
910
gint32 volatile image_ID;
912
struct jpeg_decompress_struct cinfo;
913
struct my_error_mgr jerr;
916
guchar * volatile padded_buf = NULL;
924
GimpParasite * volatile comment_parasite = NULL;
927
GimpParasite *exif_parasite = NULL;
928
ExifData *exif_data = NULL;
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;
935
/* flag warnings, so we try to ignore corrupt EXIF data */
938
cinfo.client_data = GINT_TO_POINTER (FALSE);
940
jerr.pub.emit_message = my_emit_message;
941
jerr.pub.output_message = my_output_message;
944
if ((infile = fopen (filename, "rb")) == NULL)
946
g_message (_("Could not open '%s' for reading: %s"),
947
gimp_filename_to_utf8 (filename), g_strerror (errno));
953
gchar *name = g_strdup_printf (_("Opening '%s'..."),
954
gimp_filename_to_utf8 (filename));
956
gimp_progress_init (name);
961
/* Establish the setjmp return context for my_error_exit to use. */
962
if (setjmp (jerr.setjmp_buffer))
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.
967
jpeg_destroy_decompress (&cinfo);
970
if (image_ID != -1 && !preview)
971
gimp_image_delete (image_ID);
977
/* Now we can initialize the JPEG decompression object. */
978
jpeg_create_decompress (&cinfo);
980
/* Step 2: specify data source (eg, a file) */
982
jpeg_stdio_src (&cinfo, infile);
984
/* pw - step 2.1 let the lib know we want the comments. */
986
jpeg_set_marker_processor (&cinfo, JPEG_COM, COM_handler);
988
/* Step 3: read file parameters with jpeg_read_header() */
990
(void) jpeg_read_header (&cinfo, TRUE);
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.
1000
/* if we had any comments then make a parasite for them */
1001
if (local_image_comments && local_image_comments->len)
1003
gchar *comment = local_image_comments->str;
1005
g_string_free (local_image_comments, FALSE);
1007
local_image_comments = NULL;
1009
if (g_utf8_validate (comment, -1, NULL))
1010
comment_parasite = gimp_parasite_new ("gimp-comment",
1011
GIMP_PARASITE_PERSISTENT,
1012
strlen (comment) + 1,
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 */
1022
/* Step 4: set parameters for decompression */
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.
1028
/* Step 5: Start decompressor */
1030
jpeg_start_decompress (&cinfo);
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.
1038
/* temporary buffer */
1039
tile_height = gimp_tile_height ();
1040
buf = g_new (guchar,
1041
tile_height * cinfo.output_width * cinfo.output_components);
1043
rowbuf = g_new (guchar*, tile_height);
1045
for (i = 0; i < tile_height; i++)
1046
rowbuf[i] = buf + cinfo.output_width * cinfo.output_components * i;
1048
/* Create a new image of the proper size and associate the filename with it.
1050
Preview layers, not being on the bottom of a layer stack, MUST HAVE
1053
switch (cinfo.output_components)
1056
image_type = GIMP_GRAY;
1057
layer_type = preview ? GIMP_GRAYA_IMAGE : GIMP_GRAY_IMAGE;
1061
image_type = GIMP_RGB;
1062
layer_type = preview ? GIMP_RGBA_IMAGE : GIMP_RGB_IMAGE;
1066
if (cinfo.out_color_space == JCS_CMYK)
1068
image_type = GIMP_RGB;
1069
layer_type = GIMP_RGB_IMAGE;
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);
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);
1094
image_ID = image_ID_global;
1098
image_ID = gimp_image_new (cinfo.output_width, cinfo.output_height,
1100
gimp_image_set_filename (image_ID, filename);
1105
layer_ID_global = layer_ID =
1106
gimp_layer_new (image_ID, _("JPEG preview"),
1108
cinfo.output_height,
1109
layer_type, 100, GIMP_NORMAL_MODE);
1113
layer_ID = gimp_layer_new (image_ID, _("Background"),
1115
cinfo.output_height,
1116
layer_type, 100, GIMP_NORMAL_MODE);
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);
1123
/* Step 5.1: if the file had resolution information, set it on the image */
1124
if (!preview && cinfo.saw_JFIF_marker)
1126
gdouble xresolution;
1127
gdouble yresolution;
1130
xresolution = cinfo.X_density;
1131
yresolution = cinfo.Y_density;
1133
switch (cinfo.density_unit)
1135
case 0: /* unknown -> set the aspect ratio but use the default
1138
if (cinfo.Y_density != 0)
1139
asymmetry = xresolution / yresolution;
1143
gimp_image_get_resolution (image_ID, &xresolution, &yresolution);
1144
xresolution *= asymmetry;
1147
case 1: /* dots per inch */
1150
case 2: /* dots per cm */
1151
xresolution *= 2.54;
1152
yresolution *= 2.54;
1153
gimp_image_set_unit (image_ID, GIMP_UNIT_MM);
1157
g_message ("Unknown density unit %d\nassuming dots per inch",
1158
cinfo.density_unit);
1162
gimp_image_set_resolution (image_ID, xresolution, yresolution);
1165
/* Step 6: while (scan lines remain to be read) */
1166
/* jpeg_read_scanlines(...); */
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.
1171
while (cinfo.output_scanline < cinfo.output_height)
1173
start = cinfo.output_scanline;
1174
end = cinfo.output_scanline + tile_height;
1175
end = MIN (end, cinfo.output_height);
1176
scanlines = end - start;
1178
for (i = 0; i < scanlines; i++)
1179
jpeg_read_scanlines (&cinfo, (JSAMPARRAY) &rowbuf[i], 1);
1181
if (preview) /* Add a dummy alpha channel -- convert buf to padded_buf */
1183
guchar *dest = padded_buf;
1185
gint num = drawable->width * scanlines;
1187
switch (cinfo.output_components)
1190
for (i = 0; i < num; i++)
1192
*(dest++) = *(src++);
1198
for (i = 0; i < num; i++)
1200
*(dest++) = *(src++);
1201
*(dest++) = *(src++);
1202
*(dest++) = *(src++);
1208
g_warning ("JPEG - shouldn't have gotten here.\nReport to http://bugzilla.gnome.org/");
1212
else if (cinfo.out_color_space == JCS_CMYK) /* buf-> RGB in padded_buf */
1214
guchar *dest = padded_buf;
1216
gint num = drawable->width * scanlines;
1218
for (i = 0; i < num; i++)
1220
guint r_c, g_m, b_y, a_k;
1226
*(dest++) = (r_c * a_k) / 255;
1227
*(dest++) = (g_m * a_k) / 255;
1228
*(dest++) = (b_y * a_k) / 255;
1232
gimp_pixel_rgn_set_rect (&pixel_rgn, padded_buf ? padded_buf : buf,
1233
0, start, drawable->width, scanlines);
1236
gimp_progress_update ((gdouble) cinfo.output_scanline /
1237
(gdouble) cinfo.output_height);
1240
/* Step 7: Finish decompression */
1242
jpeg_finish_decompress (&cinfo);
1243
/* We can ignore the return value since suspension is not possible
1244
* with the stdio data source.
1247
/* Step 8: Release JPEG decompression object */
1249
/* This is an important step since it will release a good deal of memory. */
1250
jpeg_destroy_decompress (&cinfo);
1252
/* free up the temporary buffers */
1255
g_free (padded_buf);
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...)
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).
1268
/* Tell the GIMP to display the image.
1270
gimp_image_add_layer (image_ID, layer_ID, 0);
1271
gimp_drawable_flush (drawable);
1273
/* pw - Last of all, attach the parasites (couldn't do it earlier -
1274
there was no image. */
1278
if (comment_parasite)
1280
gimp_image_parasite_attach (image_ID, comment_parasite);
1281
gimp_parasite_free (comment_parasite);
1283
comment_parasite = NULL;
1287
#define EXIF_HEADER_SIZE 8
1289
if (! GPOINTER_TO_INT (cinfo.client_data))
1291
exif_data = exif_data_new_from_file (filename);
1297
exif_data_save_data (exif_data, &exif_buf, &exif_buf_len);
1298
exif_data_unref (exif_data);
1300
if (exif_buf_len > EXIF_HEADER_SIZE)
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);
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 ;-)
1324
background_error_exit (j_common_ptr cinfo)
1328
(*cinfo->err->output_message) (cinfo);
1332
background_jpeg_save (PreviewPersistent *pp)
1339
if (pp->abort_me || (pp->cinfo.next_scanline >= pp->cinfo.image_height))
1344
jpeg_abort_compress (&(pp->cinfo));
1348
jpeg_finish_compress (&(pp->cinfo));
1351
fclose (pp->outfile);
1352
jpeg_destroy_compress (&(pp->cinfo));
1358
gimp_drawable_detach (pp->drawable);
1360
/* display the preview stuff */
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);
1372
/* and load the preview */
1373
load_image (pp->file_name, GIMP_RUN_NONINTERACTIVE, TRUE);
1376
/* we cleanup here (load_image doesn't run in the background) */
1377
unlink (pp->file_name);
1379
if (abort_me == &(pp->abort_me))
1384
gimp_displays_flush ();
1391
if ((pp->cinfo.next_scanline % pp->tile_height) == 0)
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));
1404
i = pp->cinfo.image_width;
1408
for (j = 0; j < pp->cinfo.input_components; j++)
1410
if (pp->has_alpha) /* ignore alpha channel */
1414
pp->src += pp->rowstride;
1415
jpeg_write_scanlines (&(pp->cinfo), (JSAMPARRAY) &(pp->temp), 1);
1422
save_image (const gchar *filename,
1425
gint32 orig_image_ID,
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;
1439
gint rowstride, yend;
1442
gchar *thumbnail_buffer = NULL;
1443
gint thumbnail_buffer_length = 0;
1444
ExifData *exif_data_tmp = NULL;
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);
1454
name = g_strdup_printf (_("Saving '%s'..."),
1455
gimp_filename_to_utf8 (filename));
1456
gimp_progress_init (name);
1460
/* Step 1: allocate and initialize JPEG compression object */
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.
1467
cinfo.err = jpeg_std_error (&jerr.pub);
1468
jerr.pub.error_exit = my_error_exit;
1471
/* Establish the setjmp return context for my_error_exit to use. */
1472
if (setjmp (jerr.setjmp_buffer))
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.
1477
jpeg_destroy_compress (&cinfo);
1481
gimp_drawable_detach (drawable);
1486
/* Now we can initialize the JPEG compression object. */
1487
jpeg_create_compress (&cinfo);
1489
/* Step 2: specify data destination (eg, a file) */
1490
/* Note: steps 2 and 3 can be done in either order. */
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.
1497
if ((outfile = fopen (filename, "wb")) == NULL)
1499
g_message (_("Could not open '%s' for writing: %s"),
1500
gimp_filename_to_utf8 (filename), g_strerror (errno));
1503
jpeg_stdio_dest (&cinfo, outfile);
1505
/* Get the input image and a pointer to its data.
1507
switch (drawable_type)
1509
case GIMP_RGB_IMAGE:
1510
case GIMP_GRAY_IMAGE:
1511
/* # of color components per pixel */
1512
cinfo.input_components = drawable->bpp;
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;
1524
case GIMP_INDEXED_IMAGE:
1525
/*gimp_message ("jpeg: cannot operate on indexed color images");*/
1530
/*gimp_message ("jpeg: cannot operate on unknown image types");*/
1535
/* Step 3: set parameters for compression */
1537
/* First we supply a description of the input image.
1538
* Four fields of the cinfo struct must be filled in:
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.)
1551
jpeg_set_defaults (&cinfo);
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;
1557
#ifdef HAVE_PROGRESSIVE_JPEG
1558
if (jsvals.progressive)
1560
jpeg_simple_progression (&cinfo);
1562
#endif /* HAVE_PROGRESSIVE_JPEG */
1564
switch (jsvals.subsmp)
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;
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;
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;
1595
cinfo.restart_interval = 0;
1596
cinfo.restart_in_rows = jsvals.restart;
1602
cinfo.dct_method = JDCT_ISLOW;
1606
cinfo.dct_method = JDCT_IFAST;
1610
cinfo.dct_method = JDCT_FLOAT;
1615
gdouble xresolution;
1616
gdouble yresolution;
1618
gimp_image_get_resolution (orig_image_ID, &xresolution, &yresolution);
1620
if (xresolution > 1e-5 && yresolution > 1e-5)
1624
factor = gimp_unit_get_factor (gimp_image_get_unit (orig_image_ID));
1626
if (factor == 2.54 /* cm */ ||
1627
factor == 25.4 /* mm */)
1629
cinfo.density_unit = 2; /* dots per cm */
1631
xresolution /= 2.54;
1632
yresolution /= 2.54;
1636
cinfo.density_unit = 1; /* dots per inch */
1639
cinfo.X_density = xresolution;
1640
cinfo.Y_density = yresolution;
1644
/* Step 4: Start compressor */
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.
1649
jpeg_start_compress (&cinfo, TRUE);
1653
/* Create the thumbnail JPEG in a buffer */
1655
if (jsvals.save_exif || jsvals.save_thumbnail)
1657
guchar *exif_buf = NULL;
1659
gdouble quality = MIN (75.0, jsvals.quality);
1661
if ( (! jsvals.save_exif) || (! exif_data))
1662
exif_data_tmp = exif_data_new ();
1664
exif_data_tmp = exif_data;
1666
/* avoid saving markers longer than 65533, gradually decrease
1667
* quality in steps of 5 until exif_buf_len is lower than that.
1669
for (exif_buf_len = 65535;
1670
exif_buf_len > 65533 && quality > 0.0;
1673
if (jsvals.save_thumbnail)
1674
thumbnail_buffer_length = create_thumbnail (image_ID, drawable_ID,
1678
exif_data_tmp->data = thumbnail_buffer;
1679
exif_data_tmp->size = thumbnail_buffer_length;
1684
exif_data_save_data (exif_data_tmp, &exif_buf, &exif_buf_len);
1687
if (exif_buf_len > 65533)
1689
/* last attempt with quality 0.0 */
1690
if (jsvals.save_thumbnail)
1691
thumbnail_buffer_length = create_thumbnail (image_ID, drawable_ID,
1694
exif_data_tmp->data = thumbnail_buffer;
1695
exif_data_tmp->size = thumbnail_buffer_length;
1700
exif_data_save_data (exif_data_tmp, &exif_buf, &exif_buf_len);
1703
if (exif_buf_len > 65533)
1705
/* still no go? save without thumbnail */
1706
exif_data_tmp->data = NULL;
1707
exif_data_tmp->size = 0;
1712
exif_data_save_data (exif_data_tmp, &exif_buf, &exif_buf_len);
1715
jpeg_write_marker (&cinfo, MARKER_CODE_EXIF, exif_buf, exif_buf_len);
1720
#endif /* HAVE_EXIF */
1722
/* Step 4.1: Write the comment out - pw */
1723
if (image_comment && *image_comment)
1725
jpeg_write_marker (&cinfo, JPEG_COM,
1726
(guchar *) image_comment, strlen (image_comment));
1729
/* Step 5: while (scan lines remain to be written) */
1730
/* jpeg_write_scanlines(...); */
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.
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 ());
1742
/* fault if cinfo.next_scanline isn't initially a multiple of
1743
* gimp_tile_height */
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
1753
PreviewPersistent *pp = g_new (PreviewPersistent, 1);
1755
/* pass all the information we need */
1757
pp->tile_height = gimp_tile_height();
1759
pp->outfile = outfile;
1760
pp->has_alpha = has_alpha;
1761
pp->rowstride = rowstride;
1764
pp->drawable = drawable;
1765
pp->pixel_rgn = pixel_rgn;
1767
pp->file_name = filename;
1769
pp->abort_me = FALSE;
1770
abort_me = &(pp->abort_me);
1772
pp->cinfo.err = jpeg_std_error(&(pp->jerr));
1773
pp->jerr.error_exit = background_error_exit;
1775
g_idle_add ((GSourceFunc) background_jpeg_save, pp);
1777
/* background_jpeg_save() will cleanup as needed */
1781
while (cinfo.next_scanline < cinfo.image_height)
1783
if ((cinfo.next_scanline % gimp_tile_height ()) == 0)
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,
1790
(yend - cinfo.next_scanline));
1796
i = cinfo.image_width;
1800
for (j = 0; j < cinfo.input_components; j++)
1802
if (has_alpha) /* ignore alpha channel */
1807
jpeg_write_scanlines (&cinfo, (JSAMPARRAY) &temp, 1);
1809
if ((cinfo.next_scanline % 5) == 0)
1810
gimp_progress_update ((gdouble) cinfo.next_scanline /
1811
(gdouble) cinfo.image_height);
1814
/* Step 6: Finish compression */
1815
jpeg_finish_compress (&cinfo);
1816
/* After finish_compress, we can close the output file. */
1819
/* Step 7: release JPEG compression object */
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 */
1827
/* And we're done! */
1828
/*gimp_do_progress (1, 1);*/
1830
gimp_drawable_detach (drawable);
1842
gchar *tn = gimp_temp_name ("jpeg");
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);
1850
undo_touched = TRUE;
1856
orig_image_ID_global,
1859
if (display_ID == -1)
1860
display_ID = gimp_display_new (image_ID_global);
1864
gtk_label_set_text (GTK_LABEL (preview_size), _("File size: unknown"));
1865
gimp_displays_flush ();
1868
gtk_widget_set_sensitive (preview_size, jsvals.preview);
1872
destroy_preview (void)
1875
*abort_me = TRUE; /* signal the background save to stop */
1877
if (drawable_global)
1879
gimp_drawable_detach (drawable_global);
1880
drawable_global = NULL;
1883
if (layer_ID_global != -1 && image_ID_global != -1)
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);
1890
layer_ID_global = -1;
1902
GtkWidget *expander;
1905
GtkWidget *spinbutton;
1906
GtkObject *scale_data;
1909
GtkWidget *progressive;
1910
GtkWidget *baseline;
1914
GtkWidget *exif_toggle;
1915
GtkWidget *thumbnail_toggle;
1916
#endif /* HAVE_EXIF */
1921
GtkWidget *text_view;
1922
GtkTextBuffer *text_buffer;
1923
GtkWidget *scrolled_window;
1925
GimpImageType dtype;
1929
dialog = gimp_dialog_new (_("Save as JPEG"), "jpeg",
1931
gimp_standard_help_func, "file-jpeg-save",
1933
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1934
GTK_STOCK_OK, GTK_RESPONSE_OK,
1938
gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
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);
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);
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,
1954
_("JPEG quality parameter"),
1955
"file-jpeg-save-quality");
1957
g_signal_connect (entry, "value_changed",
1958
G_CALLBACK (gimp_double_adjustment_update),
1960
g_signal_connect (entry, "value_changed",
1961
G_CALLBACK (make_preview),
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,
1969
gtk_box_pack_start (GTK_BOX (vbox), preview_size, FALSE, FALSE, 0);
1970
gtk_widget_show (preview_size);
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);
1978
g_signal_connect (preview, "toggled",
1979
G_CALLBACK (gimp_toggle_button_update),
1981
g_signal_connect (preview, "toggled",
1982
G_CALLBACK (make_preview),
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);
1991
gtk_box_pack_start (GTK_BOX (vbox), expander, TRUE, TRUE, 0);
1992
gtk_widget_show (expander);
1994
vbox = gtk_vbox_new (FALSE, 12);
1995
gtk_container_add (GTK_CONTAINER (expander), vbox);
1996
gtk_widget_show (vbox);
1998
frame = gimp_frame_new ("<expander>");
1999
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
2000
gtk_widget_show (frame);
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);
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);
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,
2019
"file-jpeg-save-smoothing");
2020
g_signal_connect (entry, "value_changed",
2021
G_CALLBACK (gimp_double_adjustment_update),
2023
g_signal_connect (entry, "value_changed",
2024
G_CALLBACK (make_preview),
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);
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);
2041
restart = gtk_check_button_new_with_label (_("Use restart markers"));
2042
gtk_table_attach (GTK_TABLE (table), restart, 2, 4, 1, 2,
2044
gtk_widget_show (restart);
2046
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (restart), jsvals.restart);
2048
gtk_widget_set_sensitive (restart_markers_label, jsvals.restart);
2049
gtk_widget_set_sensitive (restart_markers_scale, jsvals.restart);
2051
g_signal_connect (scale_data, "value_changed",
2052
G_CALLBACK (save_restart_update),
2054
g_signal_connect_swapped (restart, "toggled",
2055
G_CALLBACK (save_restart_update),
2058
toggle = gtk_check_button_new_with_label (_("Optimize"));
2059
gtk_table_attach (GTK_TABLE (table), toggle, 0, 1, 0, 1,
2061
gtk_widget_show (toggle);
2063
g_signal_connect (toggle, "toggled",
2064
G_CALLBACK (gimp_toggle_button_update),
2066
g_signal_connect (toggle, "toggled",
2067
G_CALLBACK (make_preview),
2070
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), jsvals.optimize);
2072
progressive = gtk_check_button_new_with_label (_("Progressive"));
2073
gtk_table_attach (GTK_TABLE (table), progressive, 0, 1, 1, 2,
2075
gtk_widget_show (progressive);
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),
2084
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (progressive),
2085
jsvals.progressive);
2087
#ifndef HAVE_PROGRESSIVE_JPEG
2088
gtk_widget_set_sensitive (progressive, FALSE);
2091
baseline = gtk_check_button_new_with_label (_("Force baseline JPEG"));
2092
gtk_table_attach (GTK_TABLE (table), baseline, 0, 1, 2, 3,
2094
gtk_widget_show (baseline);
2096
g_signal_connect (baseline, "toggled",
2097
G_CALLBACK (gimp_toggle_button_update),
2099
g_signal_connect (baseline, "toggled",
2100
G_CALLBACK (make_preview),
2103
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (baseline),
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,
2110
gtk_widget_show (exif_toggle);
2112
g_signal_connect (exif_toggle, "toggled",
2113
G_CALLBACK (gimp_toggle_button_update),
2115
g_signal_connect (exif_toggle, "toggled",
2116
G_CALLBACK (make_preview),
2119
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (exif_toggle),
2120
jsvals.save_exif && exif_data);
2122
gtk_widget_set_sensitive (exif_toggle, exif_data != NULL);
2124
thumbnail_toggle = gtk_check_button_new_with_label (_("Save thumbnail"));
2125
gtk_table_attach (GTK_TABLE (table), thumbnail_toggle, 0, 1, 4, 5,
2127
gtk_widget_show (thumbnail_toggle);
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),
2136
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (thumbnail_toggle),
2137
jsvals.save_thumbnail);
2138
#endif /* HAVE_EXIF */
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);
2147
combo = gimp_int_combo_box_new ("2x2,1x1,1x1", 0,
2148
"2x1,1x1,1x1 (4:2:2)", 1,
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);
2156
g_signal_connect (combo, "changed",
2157
G_CALLBACK (gimp_int_combo_box_get_active),
2159
g_signal_connect (combo, "changed",
2160
G_CALLBACK (make_preview),
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);
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);
2174
combo = gimp_int_combo_box_new (_("Fast Integer"), 1,
2176
_("Floating-Point"), 2,
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);
2183
g_signal_connect (combo, "changed",
2184
G_CALLBACK (gimp_int_combo_box_get_active),
2186
g_signal_connect (combo, "changed",
2187
G_CALLBACK (make_preview),
2190
frame = gimp_frame_new (_("Comment"));
2191
gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0);
2192
gtk_widget_show (frame);
2194
scrolled_window = gtk_scrolled_window_new (NULL, NULL);
2195
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
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);
2204
text_buffer = gtk_text_buffer_new (NULL);
2206
gtk_text_buffer_set_text (text_buffer, image_comment, -1);
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);
2211
gtk_container_add (GTK_CONTAINER (scrolled_window), text_view);
2212
gtk_widget_show (text_view);
2214
g_object_unref (text_buffer);
2216
gtk_widget_show (frame);
2218
gtk_widget_show (table);
2219
gtk_widget_show (dialog);
2223
run = (gimp_dialog_run (GIMP_DIALOG (dialog)) == GTK_RESPONSE_OK);
2227
GtkTextIter start_iter;
2228
GtkTextIter end_iter;
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);
2235
gtk_widget_destroy (dialog);
2238
gimp_displays_flush ();
2244
save_restart_update (GtkAdjustment *adjustment,
2247
jsvals.restart = GTK_TOGGLE_BUTTON (toggle)->active ? adjustment->value : 0;
2249
gtk_widget_set_sensitive (restart_markers_label, jsvals.restart);
2250
gtk_widget_set_sensitive (restart_markers_scale, jsvals.restart);
2259
struct jpeg_source_mgr pub; /* public fields */
2266
typedef my_source_mgr * my_src_ptr;
2269
init_source (j_decompress_ptr cinfo)
2275
fill_input_buffer (j_decompress_ptr cinfo)
2277
my_src_ptr src = (my_src_ptr) cinfo->src;
2279
/* Since we have given all we have got already
2280
* we simply fake an end of file
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;
2292
skip_input_data (j_decompress_ptr cinfo,
2295
my_src_ptr src = (my_src_ptr) cinfo->src;
2297
src->pub.next_input_byte = src->pub.next_input_byte + num_bytes;
2301
term_source (j_decompress_ptr cinfo)
2306
load_thumbnail_image (const gchar *filename,
2310
gint32 volatile image_ID;
2311
ExifData *exif_data;
2312
GimpPixelRgn pixel_rgn;
2313
GimpDrawable *drawable;
2315
struct jpeg_decompress_struct cinfo;
2316
struct my_error_mgr jerr;
2318
guchar * volatile padded_buf = NULL;
2329
exif_data = exif_data_new_from_file (filename);
2331
if (! ((exif_data) && (exif_data->data) && (exif_data->size > 0)))
2334
cinfo.err = jpeg_std_error (&jerr.pub);
2335
jerr.pub.error_exit = my_error_exit;
2337
cinfo.client_data = GINT_TO_POINTER (FALSE);
2339
jerr.pub.emit_message = my_emit_message;
2340
jerr.pub.output_message = my_output_message;
2343
gchar *name = g_strdup_printf (_("Opening thumbnail for '%s'..."),
2344
gimp_filename_to_utf8 (filename));
2345
gimp_progress_init (name);
2349
/* Establish the setjmp return context for my_error_exit to use. */
2350
if (setjmp (jerr.setjmp_buffer))
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,
2356
jpeg_destroy_decompress (&cinfo);
2359
gimp_image_delete (image_ID);
2363
exif_data_unref (exif_data);
2370
/* Now we can initialize the JPEG decompression object. */
2371
jpeg_create_decompress (&cinfo);
2373
/* Step 2: specify data source (eg, a file) */
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));
2380
src = (my_src_ptr) cinfo.src;
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;
2388
src->pub.bytes_in_buffer = exif_data->size;
2389
src->pub.next_input_byte = exif_data->data;
2391
src->buffer = exif_data->data;
2392
src->size = exif_data->size;
2394
/* Step 3: read file parameters with jpeg_read_header() */
2396
jpeg_read_header (&cinfo, TRUE);
2398
/* Step 4: set parameters for decompression */
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.
2404
/* Step 5: Start decompressor */
2406
jpeg_start_decompress (&cinfo);
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
2416
/* temporary buffer */
2417
tile_height = gimp_tile_height ();
2418
buf = g_new (guchar,
2419
tile_height * cinfo.output_width * cinfo.output_components);
2421
rowbuf = g_new (guchar *, tile_height);
2423
for (i = 0; i < tile_height; i++)
2424
rowbuf[i] = buf + cinfo.output_width * cinfo.output_components * i;
2426
/* Create a new image of the proper size and associate the
2429
* Preview layers, not being on the bottom of a layer stack,
2430
* MUST HAVE AN ALPHA CHANNEL!
2432
switch (cinfo.output_components)
2435
image_type = GIMP_GRAY;
2436
layer_type = GIMP_GRAY_IMAGE;
2440
image_type = GIMP_RGB;
2441
layer_type = GIMP_RGB_IMAGE;
2445
if (cinfo.out_color_space == JCS_CMYK)
2447
image_type = GIMP_RGB;
2448
layer_type = GIMP_RGB_IMAGE;
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);
2462
exif_data_unref (exif_data);
2470
if (cinfo.out_color_space == JCS_CMYK)
2471
padded_buf = g_new (guchar, tile_height * cinfo.output_width * 3);
2475
image_ID = gimp_image_new (cinfo.output_width, cinfo.output_height,
2477
gimp_image_set_filename (image_ID, filename);
2479
layer_ID = gimp_layer_new (image_ID, _("Background"),
2481
cinfo.output_height,
2482
layer_type, 100, GIMP_NORMAL_MODE);
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);
2488
/* Step 5.1: if the file had resolution information, set it on the image */
2489
if (cinfo.saw_JFIF_marker)
2491
gdouble xresolution;
2492
gdouble yresolution;
2495
xresolution = cinfo.X_density;
2496
yresolution = cinfo.Y_density;
2498
switch (cinfo.density_unit)
2500
case 0: /* unknown -> set the aspect ratio but use the default
2503
if (cinfo.Y_density != 0)
2504
asymmetry = xresolution / yresolution;
2508
gimp_image_get_resolution (image_ID, &xresolution, &yresolution);
2509
xresolution *= asymmetry;
2512
case 1: /* dots per inch */
2515
case 2: /* dots per cm */
2516
xresolution *= 2.54;
2517
yresolution *= 2.54;
2518
gimp_image_set_unit (image_ID, GIMP_UNIT_MM);
2522
g_message ("Unknown density unit %d\nassuming dots per inch",
2523
cinfo.density_unit);
2527
gimp_image_set_resolution (image_ID, xresolution, yresolution);
2530
/* Step 6: while (scan lines remain to be read) */
2531
/* jpeg_read_scanlines(...); */
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.
2536
while (cinfo.output_scanline < cinfo.output_height)
2538
start = cinfo.output_scanline;
2539
end = cinfo.output_scanline + tile_height;
2540
end = MIN (end, cinfo.output_height);
2541
scanlines = end - start;
2543
for (i = 0; i < scanlines; i++)
2544
jpeg_read_scanlines (&cinfo, (JSAMPARRAY) &rowbuf[i], 1);
2546
if (cinfo.out_color_space == JCS_CMYK) /* buf-> RGB in padded_buf */
2548
guchar *dest = padded_buf;
2550
gint num = drawable->width * scanlines;
2552
for (i = 0; i < num; i++)
2554
guint r_c, g_m, b_y, a_k;
2560
*(dest++) = (r_c * a_k) / 255;
2561
*(dest++) = (g_m * a_k) / 255;
2562
*(dest++) = (b_y * a_k) / 255;
2566
gimp_pixel_rgn_set_rect (&pixel_rgn, padded_buf ? padded_buf : buf,
2567
0, start, drawable->width, scanlines);
2569
gimp_progress_update ((gdouble) cinfo.output_scanline /
2570
(gdouble) cinfo.output_height);
2573
/* Step 7: Finish decompression */
2575
jpeg_finish_decompress (&cinfo);
2576
/* We can ignore the return value since suspension is not possible
2577
* with the stdio data source.
2580
/* Step 8: Release JPEG decompression object */
2582
/* This is an important step since it will release a good deal
2585
jpeg_destroy_decompress (&cinfo);
2587
/* free up the temporary buffers */
2590
g_free (padded_buf);
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).
2596
gimp_image_add_layer (image_ID, layer_ID, 0);
2599
/* NOW to get the dimensions of the actual image to return the
2602
cinfo.err = jpeg_std_error (&jerr.pub);
2603
jerr.pub.error_exit = my_error_exit;
2605
cinfo.client_data = GINT_TO_POINTER (FALSE);
2607
jerr.pub.emit_message = my_emit_message;
2608
jerr.pub.output_message = my_output_message;
2610
if ((infile = fopen (filename, "rb")) == NULL)
2612
g_message (_("Could not open '%s' for reading: %s"),
2613
gimp_filename_to_utf8 (filename), g_strerror (errno));
2617
exif_data_unref (exif_data);
2624
/* Establish the setjmp return context for my_error_exit to use. */
2625
if (setjmp (jerr.setjmp_buffer))
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,
2631
jpeg_destroy_decompress (&cinfo);
2634
gimp_image_delete (image_ID);
2638
exif_data_unref (exif_data);
2645
/* Now we can initialize the JPEG decompression object. */
2646
jpeg_create_decompress (&cinfo);
2648
/* Step 2: specify data source (eg, a file) */
2650
jpeg_stdio_src (&cinfo, infile);
2652
/* Step 3: read file parameters with jpeg_read_header() */
2654
jpeg_read_header (&cinfo, TRUE);
2656
jpeg_start_decompress (&cinfo);
2658
*width = cinfo.output_width;
2659
*height = cinfo.output_height;
2661
/* Step 4: Release JPEG decompression object */
2663
/* This is an important step since it will release a good deal
2666
jpeg_destroy_decompress (&cinfo);
2670
exif_data_unref (exif_data);
2677
static gchar *tbuffer = NULL;
2678
static gchar *tbuffer2 = NULL;
2680
static gint tbuffer_count = 0;
2684
struct jpeg_destination_mgr pub; /* public fields */
2687
} my_destination_mgr;
2689
typedef my_destination_mgr *my_dest_ptr;
2692
init_destination (j_compress_ptr cinfo)
2697
empty_output_buffer (j_compress_ptr cinfo)
2699
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
2701
tbuffer_count = tbuffer_count + 16384;
2702
tbuffer = (gchar *) g_realloc(tbuffer, tbuffer_count);
2703
g_memmove (tbuffer + tbuffer_count - 16384, tbuffer2, 16384);
2705
dest->pub.next_output_byte = tbuffer2;
2706
dest->pub.free_in_buffer = 16384;
2712
term_destination (j_compress_ptr cinfo)
2714
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
2716
tbuffer_count = (tbuffer_count + 16384) - (dest->pub.free_in_buffer);
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);
2723
create_thumbnail (gint32 image_ID,
2726
gchar **thumbnail_buffer)
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;
2734
gboolean alpha = FALSE;
2735
JSAMPROW scanline[1];
2739
drawable = gimp_drawable_get (drawable_ID);
2744
if (MIN (drawable->width, drawable->height) < 196)
2745
req_width = req_height = MIN(drawable->width, drawable->height);
2747
thumbnail_data = gimp_drawable_get_thumbnail_data (drawable_ID,
2748
&req_width, &req_height,
2751
if (! thumbnail_data)
2756
if ((bpp == 2) || (bpp == 4))
2762
buf = g_new (guchar, req_width * bpp);
2763
tbuffer2 = g_new (gchar, 16384);
2767
cinfo.err = jpeg_std_error (&jerr.pub);
2768
jerr.pub.error_exit = my_error_exit;
2770
/* Establish the setjmp return context for my_error_exit to use. */
2771
if (setjmp (jerr.setjmp_buffer))
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.
2776
jpeg_destroy_compress (&cinfo);
2780
g_free (thumbnail_data);
2781
thumbnail_data = NULL;
2797
gimp_drawable_detach (drawable);
2802
/* Now we can initialize the JPEG compression object. */
2803
jpeg_create_compress (&cinfo);
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));
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;
2815
dest->pub.next_output_byte = tbuffer2;
2816
dest->pub.free_in_buffer = 16384;
2818
dest->buffer = tbuffer2;
2821
cinfo.input_components = rbpp;
2822
cinfo.image_width = req_width;
2823
cinfo.image_height = req_height;
2825
/* colorspace of input image */
2826
cinfo.in_color_space = (rbpp == 3) ? JCS_RGB : JCS_GRAYSCALE;
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.)
2832
jpeg_set_defaults (&cinfo);
2834
jpeg_set_quality (&cinfo, (gint) (quality + 0.5), jsvals.baseline);
2836
/* Step 4: Start compressor */
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.
2841
jpeg_start_compress (&cinfo, TRUE);
2843
while (cinfo.next_scanline < (unsigned int) req_height)
2845
for (i = 0; i < req_width; i++)
2847
buf[(i * rbpp) + 0] = thumbnail_data[(cinfo.next_scanline * req_width * bpp) + (i * bpp) + 0];
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];
2857
jpeg_write_scanlines (&cinfo, scanline, 1);
2860
/* Step 6: Finish compression */
2861
jpeg_finish_compress (&cinfo);
2863
/* Step 7: release JPEG compression object */
2865
/* This is an important step since it will release a good deal of memory. */
2866
jpeg_destroy_compress (&cinfo);
2868
/* And we're done! */
2872
g_free (thumbnail_data);
2873
thumbnail_data = NULL;
2884
gimp_drawable_detach (drawable);
2888
*thumbnail_buffer = tbuffer;
2890
return tbuffer_count;
2893
#endif /* HAVE_EXIF */