]> granicus.if.org Git - imagemagick/blob - coders/jpeg.c
07589a9428a09e3a87faea99c1ff553bbf37c6ff
[imagemagick] / coders / jpeg.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                        JJJJJ  PPPP   EEEEE   GGGG                           %
7 %                          J    P   P  E      G                               %
8 %                          J    PPPP   EEE    G  GG                           %
9 %                        J J    P      E      G   G                           %
10 %                        JJJ    P      EEEEE   GGG                            %
11 %                                                                             %
12 %                                                                             %
13 %                       Read/Write JPEG Image Format                          %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                John Cristy                                  %
17 %                                 July 1992                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    http://www.imagemagick.org/script/license.php                            %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 % This software is based in part on the work of the Independent JPEG Group.
37 % See ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz for copyright and
38 % licensing restrictions.  Blob support contributed by Glenn Randers-Pehrson.
39 %
40 %
41 */
42 \f
43 /*
44   Include declarations.
45 */
46 #include "magick/studio.h"
47 #include "magick/blob.h"
48 #include "magick/blob-private.h"
49 #include "magick/cache.h"
50 #include "magick/color.h"
51 #include "magick/colormap-private.h"
52 #include "magick/color-private.h"
53 #include "magick/colormap.h"
54 #include "magick/colorspace.h"
55 #include "magick/constitute.h"
56 #include "magick/exception.h"
57 #include "magick/exception-private.h"
58 #include "magick/geometry.h"
59 #include "magick/image.h"
60 #include "magick/image-private.h"
61 #include "magick/list.h"
62 #include "magick/log.h"
63 #include "magick/magick.h"
64 #include "magick/memory_.h"
65 #include "magick/module.h"
66 #include "magick/monitor.h"
67 #include "magick/monitor-private.h"
68 #include "magick/option.h"
69 #include "magick/profile.h"
70 #include "magick/property.h"
71 #include "magick/quantum-private.h"
72 #include "magick/resource_.h"
73 #include "magick/splay-tree.h"
74 #include "magick/static.h"
75 #include "magick/string_.h"
76 #include "magick/string-private.h"
77 #include "magick/utility.h"
78 #include <setjmp.h>
79 #if defined(MAGICKCORE_JPEG_DELEGATE)
80 #define JPEG_INTERNAL_OPTIONS
81 #if defined(__MINGW32__)
82 # define XMD_H 1  /* Avoid conflicting typedef for INT32 */
83 typedef unsigned char boolean;
84 #endif
85 #undef HAVE_STDLIB_H
86 #include "jpeglib.h"
87 #include "jerror.h"
88 #endif
89 \f
90 /*
91   Define declarations.
92 */
93 #define ICC_MARKER  (JPEG_APP0+2)
94 #define ICC_PROFILE  "ICC_PROFILE"
95 #define IPTC_MARKER  (JPEG_APP0+13)
96 #define XML_MARKER  (JPEG_APP0+1)
97 #define MaxBufferExtent  8192
98 \f
99 /*
100   Typedef declarations.
101 */
102 #if defined(MAGICKCORE_JPEG_DELEGATE)
103 typedef struct _DestinationManager
104 {
105   struct jpeg_destination_mgr
106     manager;
107
108   Image
109     *image;
110
111   JOCTET
112     *buffer;
113 } DestinationManager;
114
115 typedef struct _ErrorManager
116 {
117   Image
118     *image;
119
120   jmp_buf
121     error_recovery;
122 } ErrorManager;
123
124 typedef struct _SourceManager
125 {
126   struct jpeg_source_mgr
127     manager;
128
129   Image
130     *image;
131
132   JOCTET
133     *buffer;
134
135   boolean
136     start_of_blob;
137 } SourceManager;
138 #endif
139 \f
140 /*
141   Forward declarations.
142 */
143 #if defined(MAGICKCORE_JPEG_DELEGATE)
144 static MagickBooleanType
145   WriteJPEGImage(const ImageInfo *,Image *);
146 #endif
147 \f
148 /*
149 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
150 %                                                                             %
151 %                                                                             %
152 %                                                                             %
153 %   I s J P E G                                                               %
154 %                                                                             %
155 %                                                                             %
156 %                                                                             %
157 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
158 %
159 %  IsJPEG() returns MagickTrue if the image format type, identified by the
160 %  magick string, is JPEG.
161 %
162 %  The format of the IsJPEG  method is:
163 %
164 %      MagickBooleanType IsJPEG(const unsigned char *magick,const size_t length)
165 %
166 %  A description of each parameter follows:
167 %
168 %    o magick: compare image format pattern against these bytes.
169 %
170 %    o length: Specifies the length of the magick string.
171 %
172 */
173 static MagickBooleanType IsJPEG(const unsigned char *magick,const size_t length)
174 {
175   if (length < 3)
176     return(MagickFalse);
177   if (memcmp(magick,"\377\330\377",3) == 0)
178     return(MagickTrue);
179   return(MagickFalse);
180 }
181 \f
182 #if defined(MAGICKCORE_JPEG_DELEGATE)
183 /*
184 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
185 %                                                                             %
186 %                                                                             %
187 %                                                                             %
188 %   R e a d J P E G I m a g e                                                 %
189 %                                                                             %
190 %                                                                             %
191 %                                                                             %
192 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
193 %
194 %  ReadJPEGImage() reads a JPEG image file and returns it.  It allocates
195 %  the memory necessary for the new Image structure and returns a pointer to
196 %  the new image.
197 %
198 %  The format of the ReadJPEGImage method is:
199 %
200 %      Image *ReadJPEGImage(const ImageInfo *image_info,
201 %        ExceptionInfo *exception)
202 %
203 %  A description of each parameter follows:
204 %
205 %    o image_info: the image info.
206 %
207 %    o exception: return any errors or warnings in this structure.
208 %
209 */
210
211 static MagickBooleanType EmitMessage(j_common_ptr jpeg_info,int level)
212 {
213   char
214     message[JMSG_LENGTH_MAX];
215
216   ErrorManager
217     *error_manager;
218
219   Image
220     *image;
221
222   (jpeg_info->err->format_message)(jpeg_info,message);
223   error_manager=(ErrorManager *) jpeg_info->client_data;
224   image=error_manager->image;
225   if (level < 0)
226     {
227       if ((jpeg_info->err->num_warnings == 0) ||
228           (jpeg_info->err->trace_level >= 3))
229         ThrowBinaryException(CorruptImageWarning,(char *) message,
230           image->filename);
231       jpeg_info->err->num_warnings++;
232     }
233   else
234     if (jpeg_info->err->trace_level >= level)
235       ThrowBinaryException(CoderError,(char *) message,image->filename);
236   return(MagickTrue);
237 }
238
239 static boolean FillInputBuffer(j_decompress_ptr cinfo)
240 {
241   SourceManager
242     *source;
243
244   source=(SourceManager *) cinfo->src;
245   source->manager.bytes_in_buffer=(size_t) ReadBlob(source->image,
246     MaxBufferExtent,source->buffer);
247   if (source->manager.bytes_in_buffer == 0)
248     {
249       if (source->start_of_blob != 0)
250         ERREXIT(cinfo,JERR_INPUT_EMPTY);
251       WARNMS(cinfo,JWRN_JPEG_EOF);
252       source->buffer[0]=(JOCTET) 0xff;
253       source->buffer[1]=(JOCTET) JPEG_EOI;
254       source->manager.bytes_in_buffer=2;
255     }
256   source->manager.next_input_byte=source->buffer;
257   source->start_of_blob=FALSE;
258   return(TRUE);
259 }
260
261 static int GetCharacter(j_decompress_ptr jpeg_info)
262 {
263   if (jpeg_info->src->bytes_in_buffer == 0)
264     (void) (*jpeg_info->src->fill_input_buffer)(jpeg_info);
265   jpeg_info->src->bytes_in_buffer--;
266   return((int) GETJOCTET(*jpeg_info->src->next_input_byte++));
267 }
268
269 static void InitializeSource(j_decompress_ptr cinfo)
270 {
271   SourceManager
272     *source;
273
274   source=(SourceManager *) cinfo->src;
275   source->start_of_blob=TRUE;
276 }
277
278 static MagickBooleanType IsITUFaxImage(const Image *image)
279 {
280   const StringInfo
281     *profile;
282
283   const unsigned char
284     *datum;
285
286   profile=GetImageProfile(image,"8bim");
287   if (profile == (const StringInfo *) NULL)
288     return(MagickFalse);
289   if (GetStringInfoLength(profile) < 5)
290     return(MagickFalse);
291   datum=GetStringInfoDatum(profile);
292   if ((datum[0] == 0x47) && (datum[1] == 0x33) && (datum[2] == 0x46) &&
293       (datum[3] == 0x41) && (datum[4] == 0x58))
294     return(MagickTrue);
295   return(MagickFalse);
296 }
297
298 static void JPEGErrorHandler(j_common_ptr jpeg_info)
299 {
300   ErrorManager
301     *error_manager;
302
303   (void) EmitMessage(jpeg_info,0);
304   error_manager=(ErrorManager *) jpeg_info->client_data;
305   longjmp(error_manager->error_recovery,1);
306 }
307
308 static boolean ReadComment(j_decompress_ptr jpeg_info)
309 {
310   char
311     *comment;
312
313   ErrorManager
314     *error_manager;
315
316   Image
317     *image;
318
319   register char
320     *p;
321
322   register ssize_t
323     i;
324
325   size_t
326     length;
327
328   /*
329     Determine length of comment.
330   */
331   error_manager=(ErrorManager *) jpeg_info->client_data;
332   image=error_manager->image;
333   length=(size_t) ((size_t) GetCharacter(jpeg_info) << 8);
334   length+=GetCharacter(jpeg_info);
335   length-=2;
336   if (length <= 0)
337     return(MagickTrue);
338   comment=(char *) NULL;
339   if (~length >= MaxTextExtent)
340     comment=(char *) AcquireQuantumMemory(length+MaxTextExtent,
341       sizeof(*comment));
342   if (comment == (char *) NULL)
343     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
344       image->filename);
345   /*
346     Read comment.
347   */
348   i=(ssize_t) length-1;
349   for (p=comment; i-- >= 0; p++)
350     *p=(char) GetCharacter(jpeg_info);
351   *p='\0';
352   (void) SetImageProperty(image,"comment",comment);
353   comment=DestroyString(comment);
354   return(MagickTrue);
355 }
356
357 static boolean ReadICCProfile(j_decompress_ptr jpeg_info)
358 {
359   char
360     magick[12];
361
362   ErrorManager
363     *error_manager;
364
365   Image
366     *image;
367
368   MagickBooleanType
369     status;
370
371   register ssize_t
372     i;
373
374   register unsigned char
375     *p;
376
377   size_t
378     length;
379
380   StringInfo
381     *icc_profile,
382     *profile;
383
384   /*
385     Read color profile.
386   */
387   length=(size_t) ((size_t) GetCharacter(jpeg_info) << 8);
388   length+=(size_t) GetCharacter(jpeg_info);
389   length-=2;
390   if (length <= 14)
391     {
392       while (length-- > 0)
393         (void) GetCharacter(jpeg_info);
394       return(MagickTrue);
395     }
396   for (i=0; i < 12; i++)
397     magick[i]=(char) GetCharacter(jpeg_info);
398   if (LocaleCompare(magick,ICC_PROFILE) != 0)
399     {
400       /*
401         Not a ICC profile, return.
402       */
403       for (i=0; i < (ssize_t) (length-12); i++)
404         (void) GetCharacter(jpeg_info);
405       return(MagickTrue);
406     }
407   (void) GetCharacter(jpeg_info);  /* id */
408   (void) GetCharacter(jpeg_info);  /* markers */
409   length-=14;
410   error_manager=(ErrorManager *) jpeg_info->client_data;
411   image=error_manager->image;
412   profile=AcquireStringInfo(length);
413   if (profile == (StringInfo *) NULL)
414     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
415       image->filename);
416   p=GetStringInfoDatum(profile);
417   for (i=(ssize_t) GetStringInfoLength(profile)-1; i >= 0; i--)
418     *p++=(unsigned char) GetCharacter(jpeg_info);
419   icc_profile=(StringInfo *) GetImageProfile(image,"icc");
420   if (icc_profile != (StringInfo *) NULL)
421     {
422       ConcatenateStringInfo(icc_profile,profile);
423       profile=DestroyStringInfo(profile);
424     }
425   else
426     {
427       status=SetImageProfile(image,"icc",profile);
428       profile=DestroyStringInfo(profile);
429       if (status == MagickFalse)
430         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
431           image->filename);
432     }
433   if (image->debug != MagickFalse)
434     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
435       "Profile: ICC, %.20g bytes",(double) length);
436   return(MagickTrue);
437 }
438
439 static boolean ReadIPTCProfile(j_decompress_ptr jpeg_info)
440 {
441   char
442     magick[MaxTextExtent];
443
444   ErrorManager
445     *error_manager;
446
447   Image
448     *image;
449
450   MagickBooleanType
451     status;
452
453   register ssize_t
454     i;
455
456   register unsigned char
457     *p;
458
459   size_t
460     length;
461
462   StringInfo
463     *iptc_profile,
464     *profile;
465
466   /*
467     Determine length of binary data stored here.
468   */
469   length=(size_t) ((size_t) GetCharacter(jpeg_info) << 8);
470   length+=(size_t) GetCharacter(jpeg_info);
471   length-=2;
472   if (length <= 14)
473     {
474       while (length-- > 0)
475         (void) GetCharacter(jpeg_info);
476       return(MagickTrue);
477     }
478   /*
479     Validate that this was written as a Photoshop resource format slug.
480   */
481   for (i=0; i < 10; i++)
482     magick[i]=(char) GetCharacter(jpeg_info);
483   magick[10]='\0';
484   if (length <= 10)
485     return(MagickTrue);
486   length-=10;
487   if (LocaleCompare(magick,"Photoshop ") != 0)
488     {
489       /*
490         Not a IPTC profile, return.
491       */
492       for (i=0; i < (ssize_t) length; i++)
493         (void) GetCharacter(jpeg_info);
494       return(MagickTrue);
495     }
496   /*
497     Remove the version number.
498   */
499   for (i=0; i < 4; i++)
500     (void) GetCharacter(jpeg_info);
501   if (length <= 4)
502     return(MagickTrue);
503   length-=4;
504   if (length == 0)
505     return(MagickTrue);
506   error_manager=(ErrorManager *) jpeg_info->client_data;
507   image=error_manager->image;
508   profile=AcquireStringInfo(length);
509   if (profile == (StringInfo *) NULL)
510     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
511       image->filename);
512   p=GetStringInfoDatum(profile);
513   for (i=0;  i < (ssize_t) GetStringInfoLength(profile); i++)
514     *p++=(unsigned char) GetCharacter(jpeg_info);
515   iptc_profile=(StringInfo *) GetImageProfile(image,"8bim");
516   if (iptc_profile != (StringInfo *) NULL)
517     {
518       ConcatenateStringInfo(iptc_profile,profile);
519       profile=DestroyStringInfo(profile);
520     }
521   else
522     {
523       status=SetImageProfile(image,"8bim",profile);
524       profile=DestroyStringInfo(profile);
525       if (status == MagickFalse)
526         ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
527           image->filename);
528     }
529   if (image->debug != MagickFalse)
530     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
531       "Profile: iptc, %.20g bytes",(double) length);
532   return(MagickTrue);
533 }
534
535 static boolean ReadProfile(j_decompress_ptr jpeg_info)
536 {
537   char
538     name[MaxTextExtent];
539
540   ErrorManager
541     *error_manager;
542
543   Image
544     *image;
545
546   int
547     marker;
548
549   MagickBooleanType
550     status;
551
552   register ssize_t
553     i;
554
555   register unsigned char
556     *p;
557
558   size_t
559     length;
560
561   StringInfo
562     *profile;
563
564   /*
565     Read generic profile.
566   */
567   length=(size_t) ((size_t) GetCharacter(jpeg_info) << 8);
568   length+=(size_t) GetCharacter(jpeg_info);
569   if (length <= 2)
570     return(MagickTrue);
571   length-=2;
572   marker=jpeg_info->unread_marker-JPEG_APP0;
573   (void) FormatMagickString(name,MaxTextExtent,"APP%d",marker);
574   error_manager=(ErrorManager *) jpeg_info->client_data;
575   image=error_manager->image;
576   profile=AcquireStringInfo(length);
577   if (profile == (StringInfo *) NULL)
578     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
579       image->filename);
580   p=GetStringInfoDatum(profile);
581   for (i=(ssize_t) GetStringInfoLength(profile)-1; i >= 0; i--)
582     *p++=(unsigned char) GetCharacter(jpeg_info);
583   if (marker == 1)
584     {
585       p=GetStringInfoDatum(profile);
586       if ((length > 4) && (LocaleNCompare((char *) p,"exif",4) == 0))
587         (void) CopyMagickString(name,"exif",MaxTextExtent);
588       if ((length > 5) && (LocaleNCompare((char *) p,"http:",5) == 0))
589         {
590           ssize_t
591             j;
592
593           /*
594             Extract namespace from XMP profile.
595           */
596           p=GetStringInfoDatum(profile);
597           for (j=0; j < (ssize_t) GetStringInfoLength(profile); j++)
598           {
599             if (*p == '\0')
600               break;
601             p++;
602           }
603           if (j < (ssize_t) GetStringInfoLength(profile))
604             (void) DestroyStringInfo(SplitStringInfo(profile,(size_t) (j+1)));
605           (void) CopyMagickString(name,"xmp",MaxTextExtent);
606         }
607     }
608   status=SetImageProfile(image,name,profile);
609   profile=DestroyStringInfo(profile);
610   if (status == MagickFalse)
611     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
612       image->filename);
613   if (image->debug != MagickFalse)
614     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
615       "Profile: %s, %.20g bytes",name,(double) length);
616   return(MagickTrue);
617 }
618
619 static void SkipInputData(j_decompress_ptr cinfo,long number_bytes)
620 {
621   SourceManager
622     *source;
623
624   if (number_bytes <= 0)
625     return;
626   source=(SourceManager *) cinfo->src;
627   while (number_bytes > (long) source->manager.bytes_in_buffer)
628   {
629     number_bytes-=(long) source->manager.bytes_in_buffer;
630     (void) FillInputBuffer(cinfo);
631   }
632   source->manager.next_input_byte+=number_bytes;
633   source->manager.bytes_in_buffer-=number_bytes;
634 }
635
636 static void TerminateSource(j_decompress_ptr cinfo)
637 {
638   cinfo=cinfo;
639 }
640
641 static void JPEGSourceManager(j_decompress_ptr cinfo,Image *image)
642 {
643   SourceManager
644     *source;
645
646   cinfo->src=(struct jpeg_source_mgr *) (*cinfo->mem->alloc_small)
647     ((j_common_ptr) cinfo,JPOOL_IMAGE,sizeof(SourceManager));
648   source=(SourceManager *) cinfo->src;
649   source->buffer=(JOCTET *) (*cinfo->mem->alloc_small)
650     ((j_common_ptr) cinfo,JPOOL_IMAGE,MaxBufferExtent*sizeof(JOCTET));
651   source=(SourceManager *) cinfo->src;
652   source->manager.init_source=InitializeSource;
653   source->manager.fill_input_buffer=FillInputBuffer;
654   source->manager.skip_input_data=SkipInputData;
655   source->manager.resync_to_restart=jpeg_resync_to_restart;
656   source->manager.term_source=TerminateSource;
657   source->manager.bytes_in_buffer=0;
658   source->manager.next_input_byte=NULL;
659   source->image=image;
660 }
661
662 static void JPEGSetImageQuality(struct jpeg_decompress_struct *jpeg_info,
663   Image *image)
664 {
665   image->quality=UndefinedCompressionQuality;
666 #if defined(D_PROGRESSIVE_SUPPORTED)
667   if (image->compression == LosslessJPEGCompression)
668     {
669       image->quality=100;
670       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
671         "Quality: 100 (lossless)");
672     }
673   else
674 #endif
675   {
676     ssize_t
677       j,
678       qvalue,
679       sum;
680
681     register ssize_t
682       i;
683
684     /*
685       Determine the JPEG compression quality from the quantization tables.
686     */
687     sum=0;
688     for (i=0; i < NUM_QUANT_TBLS; i++)
689     {
690       if (jpeg_info->quant_tbl_ptrs[i] != NULL)
691         for (j=0; j < DCTSIZE2; j++)
692           sum+=jpeg_info->quant_tbl_ptrs[i]->quantval[j];
693      }
694      if ((jpeg_info->quant_tbl_ptrs[0] != NULL) &&
695          (jpeg_info->quant_tbl_ptrs[1] != NULL))
696        {
697          ssize_t
698            hash[101] =
699            {
700              1020, 1015,  932,  848,  780,  735,  702,  679,  660,  645,
701               632,  623,  613,  607,  600,  594,  589,  585,  581,  571,
702               555,  542,  529,  514,  494,  474,  457,  439,  424,  410,
703               397,  386,  373,  364,  351,  341,  334,  324,  317,  309,
704               299,  294,  287,  279,  274,  267,  262,  257,  251,  247,
705               243,  237,  232,  227,  222,  217,  213,  207,  202,  198,
706               192,  188,  183,  177,  173,  168,  163,  157,  153,  148,
707               143,  139,  132,  128,  125,  119,  115,  108,  104,   99,
708                94,   90,   84,   79,   74,   70,   64,   59,   55,   49,
709                45,   40,   34,   30,   25,   20,   15,   11,    6,    4,
710                 0
711            },
712            sums[101] =
713            {
714              32640, 32635, 32266, 31495, 30665, 29804, 29146, 28599, 28104,
715              27670, 27225, 26725, 26210, 25716, 25240, 24789, 24373, 23946,
716              23572, 22846, 21801, 20842, 19949, 19121, 18386, 17651, 16998,
717              16349, 15800, 15247, 14783, 14321, 13859, 13535, 13081, 12702,
718              12423, 12056, 11779, 11513, 11135, 10955, 10676, 10392, 10208,
719               9928,  9747,  9564,  9369,  9193,  9017,  8822,  8639,  8458,
720               8270,  8084,  7896,  7710,  7527,  7347,  7156,  6977,  6788,
721               6607,  6422,  6236,  6054,  5867,  5684,  5495,  5305,  5128,
722               4945,  4751,  4638,  4442,  4248,  4065,  3888,  3698,  3509,
723               3326,  3139,  2957,  2775,  2586,  2405,  2216,  2037,  1846,
724               1666,  1483,  1297,  1109,   927,   735,   554,   375,   201,
725                128,     0
726            };
727
728          qvalue=(ssize_t) (jpeg_info->quant_tbl_ptrs[0]->quantval[2]+
729            jpeg_info->quant_tbl_ptrs[0]->quantval[53]+
730            jpeg_info->quant_tbl_ptrs[1]->quantval[0]+
731            jpeg_info->quant_tbl_ptrs[1]->quantval[DCTSIZE2-1]);
732          for (i=0; i < 100; i++)
733          {
734            if ((qvalue < hash[i]) && (sum < sums[i]))
735              continue;
736            if (((qvalue <= hash[i]) && (sum <= sums[i])) || (i >= 50))
737              image->quality=(size_t) i+1;
738            if (image->debug != MagickFalse)
739              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
740                "Quality: %.20g (%s)",(double) i+1,(qvalue <= hash[i]) &&
741                (sum <= sums[i]) ? "exact" : "approximate");
742            break;
743          }
744        }
745      else
746        if (jpeg_info->quant_tbl_ptrs[0] != NULL)
747          {
748            ssize_t
749              hash[101] =
750              {
751                510,  505,  422,  380,  355,  338,  326,  318,  311,  305,
752                300,  297,  293,  291,  288,  286,  284,  283,  281,  280,
753                279,  278,  277,  273,  262,  251,  243,  233,  225,  218,
754                211,  205,  198,  193,  186,  181,  177,  172,  168,  164,
755                158,  156,  152,  148,  145,  142,  139,  136,  133,  131,
756                129,  126,  123,  120,  118,  115,  113,  110,  107,  105,
757                102,  100,   97,   94,   92,   89,   87,   83,   81,   79,
758                 76,   74,   70,   68,   66,   63,   61,   57,   55,   52,
759                 50,   48,   44,   42,   39,   37,   34,   31,   29,   26,
760                 24,   21,   18,   16,   13,   11,    8,    6,    3,    2,
761                  0
762              },
763              sums[101] =
764              {
765                16320, 16315, 15946, 15277, 14655, 14073, 13623, 13230, 12859,
766                12560, 12240, 11861, 11456, 11081, 10714, 10360, 10027,  9679,
767                 9368,  9056,  8680,  8331,  7995,  7668,  7376,  7084,  6823,
768                 6562,  6345,  6125,  5939,  5756,  5571,  5421,  5240,  5086,
769                 4976,  4829,  4719,  4616,  4463,  4393,  4280,  4166,  4092,
770                 3980,  3909,  3835,  3755,  3688,  3621,  3541,  3467,  3396,
771                 3323,  3247,  3170,  3096,  3021,  2952,  2874,  2804,  2727,
772                 2657,  2583,  2509,  2437,  2362,  2290,  2211,  2136,  2068,
773                 1996,  1915,  1858,  1773,  1692,  1620,  1552,  1477,  1398,
774                 1326,  1251,  1179,  1109,  1031,   961,   884,   814,   736,
775                  667,   592,   518,   441,   369,   292,   221,   151,    86,
776                   64,     0
777              };
778
779            qvalue=(ssize_t) (jpeg_info->quant_tbl_ptrs[0]->quantval[2]+
780              jpeg_info->quant_tbl_ptrs[0]->quantval[53]);
781            for (i=0; i < 100; i++)
782            {
783              if ((qvalue < hash[i]) && (sum < sums[i]))
784                continue;
785              if (((qvalue <= hash[i]) && (sum <= sums[i])) || (i >= 50))
786                image->quality=(size_t) i+1;
787              if (image->debug != MagickFalse)
788                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
789                  "Quality: %.20g (%s)",(double) i+1,(qvalue <= hash[i]) &&
790                  (sum <= sums[i]) ? "exact" : "approximate");
791              break;
792            }
793          }
794   }
795 }
796
797 static void JPEGSetImageSamplingFactor(struct jpeg_decompress_struct *jpeg_info,  Image *image)
798 {
799   char
800     sampling_factor[MaxTextExtent];
801
802   switch (jpeg_info->out_color_space)
803   {
804     case JCS_CMYK:
805     {
806       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Colorspace: CMYK");
807       (void) FormatMagickString(sampling_factor,MaxTextExtent,
808         "%dx%d,%dx%d,%dx%d,%dx%d",jpeg_info->comp_info[0].h_samp_factor,
809         jpeg_info->comp_info[0].v_samp_factor,
810         jpeg_info->comp_info[1].h_samp_factor,
811         jpeg_info->comp_info[1].v_samp_factor,
812         jpeg_info->comp_info[2].h_samp_factor,
813         jpeg_info->comp_info[2].v_samp_factor,
814         jpeg_info->comp_info[3].h_samp_factor,
815         jpeg_info->comp_info[3].v_samp_factor);
816       break;
817     }
818     case JCS_GRAYSCALE:
819     {
820       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
821         "Colorspace: GRAYSCALE");
822       (void) FormatMagickString(sampling_factor,MaxTextExtent,"%dx%d",
823         jpeg_info->comp_info[0].h_samp_factor,
824         jpeg_info->comp_info[0].v_samp_factor);
825       break;
826     }
827     case JCS_RGB:
828     {
829       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Colorspace: RGB");
830       (void) FormatMagickString(sampling_factor,MaxTextExtent,
831         "%dx%d,%dx%d,%dx%d",jpeg_info->comp_info[0].h_samp_factor,
832         jpeg_info->comp_info[0].v_samp_factor,
833         jpeg_info->comp_info[1].h_samp_factor,
834         jpeg_info->comp_info[1].v_samp_factor,
835         jpeg_info->comp_info[2].h_samp_factor,
836         jpeg_info->comp_info[2].v_samp_factor);
837       break;
838     }
839     default:
840     {
841       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Colorspace: %d",
842         jpeg_info->out_color_space);
843       (void) FormatMagickString(sampling_factor,MaxTextExtent,
844         "%dx%d,%dx%d,%dx%d,%dx%d",jpeg_info->comp_info[0].h_samp_factor,
845         jpeg_info->comp_info[0].v_samp_factor,
846         jpeg_info->comp_info[1].h_samp_factor,
847         jpeg_info->comp_info[1].v_samp_factor,
848         jpeg_info->comp_info[2].h_samp_factor,
849         jpeg_info->comp_info[2].v_samp_factor,
850         jpeg_info->comp_info[3].h_samp_factor,
851         jpeg_info->comp_info[3].v_samp_factor);
852       break;
853     }
854   }
855   (void) SetImageProperty(image,"jpeg:sampling-factor",sampling_factor);
856   (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Sampling Factors: %s",
857     sampling_factor);
858 }
859
860 static Image *ReadJPEGImage(const ImageInfo *image_info,
861   ExceptionInfo *exception)
862 {
863   char
864     value[MaxTextExtent];
865
866   const char
867     *option;
868
869   ErrorManager
870     error_manager;
871
872   Image
873     *image;
874
875   IndexPacket
876     index;
877
878   JSAMPLE
879     *jpeg_pixels;
880
881   JSAMPROW
882     scanline[1];
883
884   MagickBooleanType
885     debug,
886     status;
887
888   MagickSizeType
889     number_pixels;
890
891   register ssize_t
892     i;
893
894   struct jpeg_decompress_struct
895     jpeg_info;
896
897   struct jpeg_error_mgr
898     jpeg_error;
899
900   register JSAMPLE
901     *p;
902
903   size_t
904     precision,
905     units;
906
907   ssize_t
908     y;
909
910   /*
911     Open image file.
912   */
913   assert(image_info != (const ImageInfo *) NULL);
914   assert(image_info->signature == MagickSignature);
915   if (image_info->debug != MagickFalse)
916     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
917       image_info->filename);
918   assert(exception != (ExceptionInfo *) NULL);
919   assert(exception->signature == MagickSignature);
920   debug=IsEventLogging();
921   (void) debug;
922   image=AcquireImage(image_info);
923   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
924   if (status == MagickFalse)
925     {
926       image=DestroyImageList(image);
927       return((Image *) NULL);
928     }
929   /*
930     Initialize JPEG parameters.
931   */
932   (void) ResetMagickMemory(&error_manager,0,sizeof(error_manager));
933   (void) ResetMagickMemory(&jpeg_info,0,sizeof(jpeg_info));
934   (void) ResetMagickMemory(&jpeg_error,0,sizeof(jpeg_error));
935   jpeg_info.err=jpeg_std_error(&jpeg_error);
936   jpeg_info.err->emit_message=(void (*)(j_common_ptr,int)) EmitMessage;
937   jpeg_info.err->error_exit=(void (*)(j_common_ptr)) JPEGErrorHandler;
938   jpeg_pixels=(JSAMPLE *) NULL;
939   error_manager.image=image;
940   if (setjmp(error_manager.error_recovery) != 0)
941     {
942       jpeg_destroy_decompress(&jpeg_info);
943       (void) CloseBlob(image);
944       number_pixels=(MagickSizeType) image->columns*image->rows;
945       if (number_pixels != 0)
946         return(GetFirstImageInList(image));
947       InheritException(exception,&image->exception);
948       return(DestroyImage(image));
949     }
950   jpeg_info.client_data=(void *) &error_manager;
951   jpeg_create_decompress(&jpeg_info);
952   JPEGSourceManager(&jpeg_info,image);
953   jpeg_set_marker_processor(&jpeg_info,JPEG_COM,ReadComment);
954   jpeg_set_marker_processor(&jpeg_info,ICC_MARKER,ReadICCProfile);
955   jpeg_set_marker_processor(&jpeg_info,IPTC_MARKER,ReadIPTCProfile);
956   for (i=1; i < 16; i++)
957     if ((i != 2) && (i != 13) && (i != 14))
958       jpeg_set_marker_processor(&jpeg_info,(int) (JPEG_APP0+i),ReadProfile);
959   i=(ssize_t) jpeg_read_header(&jpeg_info,MagickTrue);
960   if ((image_info->colorspace == YCbCrColorspace) ||
961       (image_info->colorspace == Rec601YCbCrColorspace) ||
962       (image_info->colorspace == Rec709YCbCrColorspace))
963     jpeg_info.out_color_space=JCS_YCbCr;
964   if (IsITUFaxImage(image) != MagickFalse)
965     {
966       image->colorspace=LabColorspace;
967       jpeg_info.out_color_space=JCS_YCbCr;
968     }
969   else
970     if (jpeg_info.out_color_space == JCS_CMYK)
971       image->colorspace=CMYKColorspace;
972   /*
973     Set image resolution.
974   */
975   units=0;
976   if ((jpeg_info.saw_JFIF_marker != 0) && (jpeg_info.X_density != 1) &&
977       (jpeg_info.Y_density != 1))
978     {
979       image->x_resolution=(double) jpeg_info.X_density;
980       image->y_resolution=(double) jpeg_info.Y_density;
981       units=(size_t) jpeg_info.density_unit;
982     }
983   if (units == 1)
984     image->units=PixelsPerInchResolution;
985   if (units == 2)
986     image->units=PixelsPerCentimeterResolution;
987   number_pixels=(MagickSizeType) image->columns*image->rows;
988   option=GetImageOption(image_info,"jpeg:size");
989   if (option != (const char *) NULL)
990     {
991       double
992         scale_factor;
993
994       GeometryInfo
995         geometry_info;
996
997       MagickStatusType
998         flags;
999
1000       /*
1001         Scale the image.
1002       */
1003       flags=ParseGeometry(option,&geometry_info);
1004       if ((flags & SigmaValue) == 0)
1005         geometry_info.sigma=geometry_info.rho;
1006       jpeg_calc_output_dimensions(&jpeg_info);
1007       image->magick_columns=jpeg_info.output_width;
1008       image->magick_rows=jpeg_info.output_height;
1009       scale_factor=1.0;
1010       if (geometry_info.rho != 0.0)
1011         scale_factor=jpeg_info.output_width/geometry_info.rho;
1012       if ((geometry_info.sigma != 0.0) &&
1013           (scale_factor > (jpeg_info.output_height/geometry_info.sigma)))
1014         scale_factor=jpeg_info.output_height/geometry_info.sigma;
1015       jpeg_info.scale_num=1U;
1016       jpeg_info.scale_denom=(unsigned int) scale_factor;
1017       jpeg_calc_output_dimensions(&jpeg_info);
1018       if (image->debug != MagickFalse)
1019         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1020           "Scale factor: %.20g",(double) scale_factor);
1021     }
1022   precision=(size_t) jpeg_info.data_precision;
1023 #if (JPEG_LIB_VERSION >= 61) && defined(D_PROGRESSIVE_SUPPORTED)
1024 #if defined(D_LOSSLESS_SUPPORTED)
1025   image->interlace=jpeg_info.process == JPROC_PROGRESSIVE ?
1026     JPEGInterlace : NoInterlace;
1027   image->compression=jpeg_info.process == JPROC_LOSSLESS ?
1028     LosslessJPEGCompression : JPEGCompression;
1029   if (jpeg_info.data_precision > 8)
1030     (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
1031       "12-bit JPEG not supported. Reducing pixel data to 8 bits","`%s'",
1032       image->filename);
1033   if (jpeg_info.data_precision == 16)
1034     jpeg_info.data_precision=12;
1035 #else
1036   image->interlace=jpeg_info.progressive_mode != 0 ? JPEGInterlace :
1037     NoInterlace;
1038   image->compression=JPEGCompression;
1039 #endif
1040 #else
1041   image->compression=JPEGCompression;
1042   image->interlace=JPEGInterlace;
1043 #endif
1044   if ((image_info->colors > 8) && (image_info->colors <= 256))
1045     {
1046       /*
1047         Let the JPEG library quantize for us.
1048       */
1049       jpeg_info.quantize_colors=MagickTrue;
1050       jpeg_info.desired_number_of_colors=(int) image_info->colors;
1051     }
1052   option=GetImageOption(image_info,"jpeg:block-smoothing");
1053   if (option != (const char *) NULL)
1054     {
1055       jpeg_info.do_block_smoothing=MagickFalse;
1056       if (IsMagickTrue(option) != MagickFalse)
1057         jpeg_info.do_block_smoothing=MagickTrue;
1058     }
1059   option=GetImageOption(image_info,"jpeg:dct-method");
1060   if (option != (const char *) NULL)
1061     switch (*option)
1062     {
1063       case 'D':
1064       case 'd':
1065       {
1066         if (LocaleCompare(option,"default") == 0)
1067           jpeg_info.dct_method=JDCT_DEFAULT;
1068         break;
1069       }
1070       case 'F':
1071       case 'f':
1072       {
1073         if (LocaleCompare(option,"fastest") == 0)
1074           jpeg_info.dct_method=JDCT_FASTEST;
1075         if (LocaleCompare(option,"float") == 0)
1076           jpeg_info.dct_method=JDCT_FLOAT;
1077         break;
1078       }
1079       case 'I':
1080       case 'i':
1081       {
1082         if (LocaleCompare(option,"ifast") == 0)
1083           jpeg_info.dct_method=JDCT_IFAST;
1084         if (LocaleCompare(option,"islow") == 0)
1085           jpeg_info.dct_method=JDCT_ISLOW;
1086         break;
1087       }
1088     }
1089   option=GetImageOption(image_info,"jpeg:fancy-upsampling");
1090   if (option != (const char *) NULL)
1091     {
1092       jpeg_info.do_fancy_upsampling=MagickFalse;
1093       if (IsMagickTrue(option) != MagickFalse)
1094         jpeg_info.do_fancy_upsampling=MagickTrue;
1095     }
1096   (void) jpeg_start_decompress(&jpeg_info);
1097   image->columns=jpeg_info.output_width;
1098   image->rows=jpeg_info.output_height;
1099   image->depth=(size_t) jpeg_info.data_precision;
1100   if (jpeg_info.out_color_space == JCS_YCbCr)
1101     image->colorspace=YCbCrColorspace;
1102   if (jpeg_info.out_color_space == JCS_CMYK)
1103     image->colorspace=CMYKColorspace;
1104   if ((image_info->colors != 0) && (image_info->colors <= 256))
1105     if (AcquireImageColormap(image,image_info->colors) == MagickFalse)
1106       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1107   if ((jpeg_info.output_components == 1) &&
1108       (jpeg_info.quantize_colors == MagickFalse))
1109     {
1110       size_t
1111         colors;
1112
1113       colors=(size_t) GetQuantumRange(image->depth)+1;
1114       if (AcquireImageColormap(image,colors) == MagickFalse)
1115         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1116     }
1117   if (image->debug != MagickFalse)
1118     {
1119       if (image->interlace != NoInterlace)
1120         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1121           "Interlace: progressive");
1122       else
1123         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1124           "Interlace: nonprogressive");
1125       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Data precision: %d",
1126         (int) jpeg_info.data_precision);
1127       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Geometry: %dx%d",
1128         (int) jpeg_info.output_width,(int) jpeg_info.output_height);
1129     }
1130   JPEGSetImageQuality(&jpeg_info,image);
1131   JPEGSetImageSamplingFactor(&jpeg_info,image);
1132   (void) FormatMagickString(value,MaxTextExtent,"%.20g",(double)
1133     jpeg_info.out_color_space);
1134   (void) SetImageProperty(image,"jpeg:colorspace",value);
1135   if (image_info->ping != MagickFalse)
1136     {
1137       jpeg_destroy_decompress(&jpeg_info);
1138       (void) CloseBlob(image);
1139       return(GetFirstImageInList(image));
1140     }
1141   jpeg_pixels=(JSAMPLE *) AcquireQuantumMemory((size_t) image->columns,
1142     jpeg_info.output_components*sizeof(JSAMPLE));
1143   if (jpeg_pixels == (JSAMPLE *) NULL)
1144     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1145   /*
1146     Convert JPEG pixels to pixel packets.
1147   */
1148   if (setjmp(error_manager.error_recovery) != 0)
1149     {
1150       if (jpeg_pixels != (unsigned char *) NULL)
1151         jpeg_pixels=(unsigned char *) RelinquishMagickMemory(jpeg_pixels);
1152       jpeg_destroy_decompress(&jpeg_info);
1153       (void) CloseBlob(image);
1154       number_pixels=(MagickSizeType) image->columns*image->rows;
1155       if (number_pixels != 0)
1156         return(GetFirstImageInList(image));
1157       return(DestroyImage(image));
1158     }
1159   if (jpeg_info.quantize_colors != MagickFalse)
1160     {
1161       image->colors=(size_t) jpeg_info.actual_number_of_colors;
1162       if (jpeg_info.out_color_space == JCS_GRAYSCALE)
1163         for (i=0; i < (ssize_t) image->colors; i++)
1164         {
1165           image->colormap[i].red=ScaleCharToQuantum(jpeg_info.colormap[0][i]);
1166           image->colormap[i].green=image->colormap[i].red;
1167           image->colormap[i].blue=image->colormap[i].red;
1168           image->colormap[i].opacity=OpaqueOpacity;
1169         }
1170       else
1171         for (i=0; i < (ssize_t) image->colors; i++)
1172         {
1173           image->colormap[i].red=ScaleCharToQuantum(jpeg_info.colormap[0][i]);
1174           image->colormap[i].green=ScaleCharToQuantum(jpeg_info.colormap[1][i]);
1175           image->colormap[i].blue=ScaleCharToQuantum(jpeg_info.colormap[2][i]);
1176           image->colormap[i].opacity=OpaqueOpacity;
1177         }
1178     }
1179   scanline[0]=(JSAMPROW) jpeg_pixels;
1180   for (y=0; y < (ssize_t) image->rows; y++)
1181   {
1182     register IndexPacket
1183       *restrict indexes;
1184
1185     register ssize_t
1186       x;
1187
1188     register PixelPacket
1189       *restrict q;
1190
1191     if (jpeg_read_scanlines(&jpeg_info,scanline,1) != 1)
1192       {
1193         (void) ThrowMagickException(exception,GetMagickModule(),
1194           CorruptImageWarning,"SkipToSyncByte","`%s'",image->filename);
1195         continue;
1196       }
1197     p=jpeg_pixels;
1198     q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1199     if (q == (PixelPacket *) NULL)
1200       break;
1201     indexes=GetAuthenticIndexQueue(image);
1202     if (jpeg_info.data_precision > 8)
1203       {
1204         if (jpeg_info.output_components == 1)
1205           for (x=0; x < (ssize_t) image->columns; x++)
1206           {
1207             size_t
1208               pixel;
1209
1210             if (precision != 16)
1211               pixel=(size_t) GETJSAMPLE(*p);
1212             else
1213               pixel=(size_t) ((GETJSAMPLE(*p) ^ 0x80) << 4);
1214             index=ConstrainColormapIndex(image,pixel);
1215             SetIndexPixelComponent(indexes+x,index);
1216             SetRedPixelComponent(q,image->colormap[(int) index].red);
1217             SetGreenPixelComponent(q,image->colormap[(int) index].green);
1218             SetBluePixelComponent(q,image->colormap[(int) index].blue);
1219             p++;
1220             q++;
1221           }
1222         else
1223           if (image->colorspace != CMYKColorspace)
1224             for (x=0; x < (ssize_t) image->columns; x++)
1225             {
1226               SetRedPixelComponent(q,ScaleShortToQuantum((unsigned char)
1227                 (GETJSAMPLE(*p++) << 4)));
1228               SetGreenPixelComponent(q,ScaleShortToQuantum((unsigned char)
1229                 (GETJSAMPLE(*p++) << 4)));
1230               SetBluePixelComponent(q,ScaleShortToQuantum((unsigned char)
1231                 (GETJSAMPLE(*p++) << 4)));
1232               SetOpacityPixelComponent(q,OpaqueOpacity);
1233               q++;
1234             }
1235           else
1236             for (x=0; x < (ssize_t) image->columns; x++)
1237             {
1238               SetCyanPixelComponent(q,QuantumRange-ScaleShortToQuantum(
1239                 (unsigned char) (GETJSAMPLE(*p++) << 4)));
1240               SetMagentaPixelComponent(q,QuantumRange-ScaleShortToQuantum(
1241                 (unsigned char) (GETJSAMPLE(*p++) << 4)));
1242               SetYellowPixelComponent(q,QuantumRange-ScaleShortToQuantum(
1243                 (unsigned char) (GETJSAMPLE(*p++) << 4)));
1244               SetBlackPixelComponent(indexes+x,QuantumRange-ScaleShortToQuantum(
1245                 (unsigned char) (GETJSAMPLE(*p++) << 4)));
1246               SetOpacityPixelComponent(q,OpaqueOpacity);
1247               q++;
1248             }
1249       }
1250     else
1251       if (jpeg_info.output_components == 1)
1252         for (x=0; x < (ssize_t) image->columns; x++)
1253         {
1254           index=ConstrainColormapIndex(image,(size_t) GETJSAMPLE(*p));
1255           SetIndexPixelComponent(indexes+x,index);
1256           SetRedPixelComponent(q,image->colormap[(int) index].red);
1257           SetGreenPixelComponent(q,image->colormap[(int) index].green);
1258           SetBluePixelComponent(q,image->colormap[(int) index].blue);
1259           p++;
1260           q++;
1261         }
1262       else
1263         if (image->colorspace != CMYKColorspace)
1264           for (x=0; x < (ssize_t) image->columns; x++)
1265           {
1266             SetRedPixelComponent(q,ScaleCharToQuantum((unsigned char)
1267               GETJSAMPLE(*p++)));
1268             SetGreenPixelComponent(q,ScaleCharToQuantum((unsigned char)
1269               GETJSAMPLE(*p++)));
1270             SetBluePixelComponent(q,ScaleCharToQuantum((unsigned char)
1271               GETJSAMPLE(*p++)));
1272             SetOpacityPixelComponent(q,OpaqueOpacity);
1273             q++;
1274           }
1275         else
1276           for (x=0; x < (ssize_t) image->columns; x++)
1277           {
1278             SetCyanPixelComponent(q,QuantumRange-ScaleCharToQuantum(
1279               (unsigned char) GETJSAMPLE(*p++)));
1280             SetMagentaPixelComponent(q,QuantumRange-ScaleCharToQuantum(
1281               (unsigned char) GETJSAMPLE(*p++)));
1282             SetYellowPixelComponent(q,QuantumRange-ScaleCharToQuantum(
1283               (unsigned char) GETJSAMPLE(*p++)));
1284             SetBlackPixelComponent(indexes+x,QuantumRange-ScaleCharToQuantum(
1285               (unsigned char) GETJSAMPLE(*p++)));
1286             SetOpacityPixelComponent(q,OpaqueOpacity);
1287             q++;
1288           }
1289     if (SyncAuthenticPixels(image,exception) == MagickFalse)
1290       break;
1291     status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
1292       image->rows);
1293     if (status == MagickFalse)
1294       break;
1295   }
1296   /*
1297     Free jpeg resources.
1298   */
1299   (void) jpeg_finish_decompress(&jpeg_info);
1300   jpeg_destroy_decompress(&jpeg_info);
1301   jpeg_pixels=(unsigned char *) RelinquishMagickMemory(jpeg_pixels);
1302   (void) CloseBlob(image);
1303   return(GetFirstImageInList(image));
1304 }
1305 #endif
1306 \f
1307 /*
1308 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1309 %                                                                             %
1310 %                                                                             %
1311 %                                                                             %
1312 %   R e g i s t e r J P E G I m a g e                                         %
1313 %                                                                             %
1314 %                                                                             %
1315 %                                                                             %
1316 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1317 %
1318 %  RegisterJPEGImage() adds properties for the JPEG image format to
1319 %  the list of supported formats.  The properties include the image format
1320 %  tag, a method to read and/or write the format, whether the format
1321 %  supports the saving of more than one frame to the same file or blob,
1322 %  whether the format supports native in-memory I/O, and a brief
1323 %  description of the format.
1324 %
1325 %  The format of the RegisterJPEGImage method is:
1326 %
1327 %      size_t RegisterJPEGImage(void)
1328 %
1329 */
1330 ModuleExport size_t RegisterJPEGImage(void)
1331 {
1332   char
1333     version[MaxTextExtent];
1334
1335   MagickInfo
1336     *entry;
1337
1338   static const char
1339     description[] = "Joint Photographic Experts Group JFIF format";
1340
1341   *version='\0';
1342 #if defined(JPEG_LIB_VERSION)
1343   (void) FormatMagickString(version,MaxTextExtent,"%d",JPEG_LIB_VERSION);
1344 #endif
1345   entry=SetMagickInfo("JPEG");
1346   entry->thread_support=NoThreadSupport;
1347 #if defined(MAGICKCORE_JPEG_DELEGATE)
1348   entry->decoder=(DecodeImageHandler *) ReadJPEGImage;
1349   entry->encoder=(EncodeImageHandler *) WriteJPEGImage;
1350 #endif
1351   entry->magick=(IsImageFormatHandler *) IsJPEG;
1352   entry->adjoin=MagickFalse;
1353   entry->description=ConstantString(description);
1354   if (*version != '\0')
1355     entry->version=ConstantString(version);
1356   entry->module=ConstantString("JPEG");
1357   (void) RegisterMagickInfo(entry);
1358   entry=SetMagickInfo("JPG");
1359   entry->thread_support=NoThreadSupport;
1360 #if defined(MAGICKCORE_JPEG_DELEGATE)
1361   entry->decoder=(DecodeImageHandler *) ReadJPEGImage;
1362   entry->encoder=(EncodeImageHandler *) WriteJPEGImage;
1363 #endif
1364   entry->adjoin=MagickFalse;
1365   entry->description=ConstantString(description);
1366   if (*version != '\0')
1367     entry->version=ConstantString(version);
1368   entry->module=ConstantString("JPEG");
1369   (void) RegisterMagickInfo(entry);
1370   entry=SetMagickInfo("PJPEG");
1371   entry->thread_support=NoThreadSupport;
1372 #if defined(MAGICKCORE_JPEG_DELEGATE)
1373   entry->decoder=(DecodeImageHandler *) ReadJPEGImage;
1374   entry->encoder=(EncodeImageHandler *) WriteJPEGImage;
1375 #endif
1376   entry->adjoin=MagickFalse;
1377   entry->description=ConstantString(description);
1378   if (*version != '\0')
1379     entry->version=ConstantString(version);
1380   entry->module=ConstantString("JPEG");
1381   (void) RegisterMagickInfo(entry);
1382   return(MagickImageCoderSignature);
1383 }
1384 \f
1385 /*
1386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1387 %                                                                             %
1388 %                                                                             %
1389 %                                                                             %
1390 %   U n r e g i s t e r J P E G I m a g e                                     %
1391 %                                                                             %
1392 %                                                                             %
1393 %                                                                             %
1394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1395 %
1396 %  UnregisterJPEGImage() removes format registrations made by the
1397 %  JPEG module from the list of supported formats.
1398 %
1399 %  The format of the UnregisterJPEGImage method is:
1400 %
1401 %      UnregisterJPEGImage(void)
1402 %
1403 */
1404 ModuleExport void UnregisterJPEGImage(void)
1405 {
1406   (void) UnregisterMagickInfo("PJPG");
1407   (void) UnregisterMagickInfo("JPEG");
1408   (void) UnregisterMagickInfo("JPG");
1409 }
1410 \f
1411 #if defined(MAGICKCORE_JPEG_DELEGATE)
1412 /*
1413 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1414 %                                                                             %
1415 %                                                                             %
1416 %                                                                             %
1417 %  W r i t e J P E G I m a g e                                                %
1418 %                                                                             %
1419 %                                                                             %
1420 %                                                                             %
1421 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1422 %
1423 %  WriteJPEGImage() writes a JPEG image file and returns it.  It
1424 %  allocates the memory necessary for the new Image structure and returns a
1425 %  pointer to the new image.
1426 %
1427 %  The format of the WriteJPEGImage method is:
1428 %
1429 %      MagickBooleanType WriteJPEGImage(const ImageInfo *image_info,
1430 %        Image *image)
1431 %
1432 %  A description of each parameter follows:
1433 %
1434 %    o image_info: the image info.
1435 %
1436 %    o jpeg_image:  The image.
1437 %
1438 %
1439 */
1440
1441 static boolean EmptyOutputBuffer(j_compress_ptr cinfo)
1442 {
1443   DestinationManager
1444     *destination;
1445
1446   destination=(DestinationManager *) cinfo->dest;
1447   destination->manager.free_in_buffer=(size_t) WriteBlob(destination->image,
1448     MaxBufferExtent,destination->buffer);
1449   if (destination->manager.free_in_buffer != MaxBufferExtent)
1450     ERREXIT(cinfo,JERR_FILE_WRITE);
1451   destination->manager.next_output_byte=destination->buffer;
1452   return(TRUE);
1453 }
1454
1455 static void InitializeDestination(j_compress_ptr cinfo)
1456 {
1457   DestinationManager
1458     *destination;
1459
1460   destination=(DestinationManager *) cinfo->dest;
1461   destination->buffer=(JOCTET *) (*cinfo->mem->alloc_small)
1462     ((j_common_ptr) cinfo,JPOOL_IMAGE,MaxBufferExtent*sizeof(JOCTET));
1463   destination->manager.next_output_byte=destination->buffer;
1464   destination->manager.free_in_buffer=MaxBufferExtent;
1465 }
1466
1467 static inline size_t MagickMin(const size_t x,const size_t y)
1468 {
1469   if (x < y)
1470     return(x);
1471   return(y);
1472 }
1473
1474 static void TerminateDestination(j_compress_ptr cinfo)
1475 {
1476   DestinationManager
1477     *destination;
1478
1479   destination=(DestinationManager *) cinfo->dest;
1480   if ((MaxBufferExtent-(int) destination->manager.free_in_buffer) > 0)
1481     {
1482       ssize_t
1483         count;
1484
1485       count=WriteBlob(destination->image,MaxBufferExtent-
1486         destination->manager.free_in_buffer,destination->buffer);
1487       if (count != (ssize_t)
1488           (MaxBufferExtent-destination->manager.free_in_buffer))
1489         ERREXIT(cinfo,JERR_FILE_WRITE);
1490     }
1491 }
1492
1493 static void WriteProfile(j_compress_ptr jpeg_info,Image *image)
1494 {
1495   const char
1496     *name;
1497
1498   const StringInfo
1499     *profile;
1500
1501   MagickBooleanType
1502     iptc;
1503
1504   register ssize_t
1505     i;
1506
1507   size_t
1508     length,
1509     tag_length;
1510
1511   StringInfo
1512     *custom_profile;
1513
1514   /*
1515     Save image profile as a APP marker.
1516   */
1517   iptc=MagickFalse;
1518   custom_profile=AcquireStringInfo(65535L);
1519   ResetImageProfileIterator(image);
1520   for (name=GetNextImageProfile(image); name != (const char *) NULL; )
1521   {
1522     register unsigned char
1523       *p;
1524
1525     profile=GetImageProfile(image,name);
1526     p=GetStringInfoDatum(custom_profile);
1527     if (LocaleCompare(name,"EXIF") == 0)
1528       for (i=0; i < (ssize_t) GetStringInfoLength(profile); i+=65533L)
1529       {
1530         length=MagickMin(GetStringInfoLength(profile)-i,65533L);
1531         jpeg_write_marker(jpeg_info,XML_MARKER,GetStringInfoDatum(profile)+i,
1532           (unsigned int) length);
1533       }
1534     if (LocaleCompare(name,"ICC") == 0)
1535       {
1536         register unsigned char
1537           *p;
1538
1539         tag_length=14;
1540         p=GetStringInfoDatum(custom_profile);
1541         (void) CopyMagickMemory(p,ICC_PROFILE,tag_length);
1542         for (i=0; i < (ssize_t) GetStringInfoLength(profile); i+=65519L)
1543         {
1544           length=MagickMin(GetStringInfoLength(profile)-i,65519L);
1545           p[12]=(unsigned char) ((i/65519L)+1);
1546           p[13]=(unsigned char) (GetStringInfoLength(profile)/65519L+1);
1547           (void) CopyMagickMemory(p+tag_length,GetStringInfoDatum(profile)+i,
1548             length);
1549           jpeg_write_marker(jpeg_info,ICC_MARKER,GetStringInfoDatum(
1550             custom_profile),(unsigned int) (length+tag_length));
1551         }
1552       }
1553     if (((LocaleCompare(name,"IPTC") == 0) ||
1554         (LocaleCompare(name,"8BIM") == 0)) && (iptc == MagickFalse))
1555       {
1556         size_t
1557           roundup;
1558
1559         iptc=MagickTrue;
1560         for (i=0; i < (ssize_t) GetStringInfoLength(profile); i+=65500L)
1561         {
1562           length=MagickMin(GetStringInfoLength(profile)-i,65500L);
1563           roundup=(size_t) (length & 0x01);
1564           if (LocaleNCompare((char *) GetStringInfoDatum(profile),"8BIM",4) == 0)
1565             {
1566               (void) memcpy(p,"Photoshop 3.0 ",14);
1567               tag_length=14;
1568             }
1569           else
1570             {
1571               (void) CopyMagickMemory(p,"Photoshop 3.0 8BIM\04\04\0\0\0\0",24);
1572               tag_length=26;
1573               p[24]=(unsigned char) (length >> 8);
1574               p[25]=(unsigned char) (length & 0xff);
1575             }
1576           p[13]=0x00;
1577           (void) memcpy(p+tag_length,GetStringInfoDatum(profile)+i,length);
1578           if (roundup != 0)
1579             p[length+tag_length]='\0';
1580           jpeg_write_marker(jpeg_info,IPTC_MARKER,GetStringInfoDatum(
1581             custom_profile),(unsigned int) (length+tag_length+roundup));
1582         }
1583       }
1584     if (LocaleCompare(name,"XMP") == 0)
1585       {
1586         StringInfo
1587           *xmp_profile;
1588
1589         /*
1590           Add namespace to XMP profile.
1591         */
1592         xmp_profile=StringToStringInfo("http://ns.adobe.com/xap/1.0/");
1593         ConcatenateStringInfo(xmp_profile,profile);
1594         GetStringInfoDatum(xmp_profile)[28]='\0';
1595         for (i=0; i < (ssize_t) GetStringInfoLength(xmp_profile); i+=65533L)
1596         {
1597           length=MagickMin(GetStringInfoLength(xmp_profile)-i,65533L);
1598           jpeg_write_marker(jpeg_info,XML_MARKER,
1599             GetStringInfoDatum(xmp_profile)+i,(unsigned int) length);
1600         }
1601         xmp_profile=DestroyStringInfo(xmp_profile);
1602       }
1603     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1604       "%s profile: %.20g bytes",name,(double) GetStringInfoLength(profile));
1605     name=GetNextImageProfile(image);
1606   }
1607   custom_profile=DestroyStringInfo(custom_profile);
1608 }
1609
1610 static void JPEGDestinationManager(j_compress_ptr cinfo,Image * image)
1611 {
1612   DestinationManager
1613     *destination;
1614
1615   cinfo->dest=(struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small)
1616     ((j_common_ptr) cinfo,JPOOL_IMAGE,sizeof(DestinationManager));
1617   destination=(DestinationManager *) cinfo->dest;
1618   destination->manager.init_destination=InitializeDestination;
1619   destination->manager.empty_output_buffer=EmptyOutputBuffer;
1620   destination->manager.term_destination=TerminateDestination;
1621   destination->image=image;
1622 }
1623
1624 static char **SamplingFactorToList(const char *text)
1625 {
1626   char
1627     **textlist;
1628
1629   register char
1630     *q;
1631
1632   register const char
1633     *p;
1634
1635   register ssize_t
1636     i;
1637
1638   size_t
1639     lines;
1640
1641   if (text == (char *) NULL)
1642     return((char **) NULL);
1643   /*
1644     Convert string to an ASCII list.
1645   */
1646   lines=1;
1647   for (p=text; *p != '\0'; p++)
1648     if (*p == ',')
1649       lines++;
1650   textlist=(char **) AcquireQuantumMemory((size_t) lines+MaxTextExtent,
1651     sizeof(*textlist));
1652   if (textlist == (char **) NULL)
1653     ThrowFatalException(ResourceLimitFatalError,"UnableToConvertText");
1654   p=text;
1655   for (i=0; i < (ssize_t) lines; i++)
1656   {
1657     for (q=(char *) p; *q != '\0'; q++)
1658       if (*q == ',')
1659         break;
1660     textlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent,
1661       sizeof(*textlist[i]));
1662     if (textlist[i] == (char *) NULL)
1663       ThrowFatalException(ResourceLimitFatalError,"UnableToConvertText");
1664     (void) CopyMagickString(textlist[i],p,(size_t) (q-p+1));
1665     if (*q == '\r')
1666       q++;
1667     p=q+1;
1668   }
1669   textlist[i]=(char *) NULL;
1670   return(textlist);
1671 }
1672
1673 static MagickBooleanType WriteJPEGImage(const ImageInfo *image_info,
1674   Image *image)
1675 {
1676   const char
1677     *option,
1678     *sampling_factor,
1679     *value;
1680
1681   ErrorManager
1682     error_manager;
1683
1684   JSAMPLE
1685     *jpeg_pixels;
1686
1687   JSAMPROW
1688     scanline[1];
1689
1690   MagickBooleanType
1691     status;
1692
1693   register JSAMPLE
1694     *q;
1695
1696   register ssize_t
1697     i;
1698
1699   ssize_t
1700     y;
1701
1702   struct jpeg_compress_struct
1703     jpeg_info;
1704
1705   struct jpeg_error_mgr
1706     jpeg_error;
1707
1708   /*
1709     Open image file.
1710   */
1711   assert(image_info != (const ImageInfo *) NULL);
1712   assert(image_info->signature == MagickSignature);
1713   assert(image != (Image *) NULL);
1714   assert(image->signature == MagickSignature);
1715   if (image->debug != MagickFalse)
1716     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1717   status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1718   if (status == MagickFalse)
1719     return(status);
1720   /*
1721     Initialize JPEG parameters.
1722   */
1723   (void) ResetMagickMemory(&error_manager,0,sizeof(error_manager));
1724   (void) ResetMagickMemory(&jpeg_info,0,sizeof(jpeg_info));
1725   (void) ResetMagickMemory(&jpeg_error,0,sizeof(jpeg_error));
1726   jpeg_info.client_data=(void *) image;
1727   jpeg_info.err=jpeg_std_error(&jpeg_error);
1728   jpeg_info.err->emit_message=(void (*)(j_common_ptr,int)) EmitMessage;
1729   jpeg_info.err->error_exit=(void (*)(j_common_ptr)) JPEGErrorHandler;
1730   error_manager.image=image;
1731   jpeg_pixels=(JSAMPLE *) NULL;
1732   if (setjmp(error_manager.error_recovery) != 0)
1733     {
1734       jpeg_destroy_compress(&jpeg_info);
1735       (void) CloseBlob(image);
1736       return(MagickFalse);
1737     }
1738   jpeg_info.client_data=(void *) &error_manager;
1739   jpeg_create_compress(&jpeg_info);
1740   JPEGDestinationManager(&jpeg_info,image);
1741   if ((image->columns != (unsigned int) image->columns) ||
1742       (image->rows != (unsigned int) image->rows))
1743     ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
1744   jpeg_info.image_width=(unsigned int) image->columns;
1745   jpeg_info.image_height=(unsigned int) image->rows;
1746   jpeg_info.input_components=3;
1747   jpeg_info.data_precision=8;
1748   jpeg_info.in_color_space=JCS_RGB;
1749   switch (image->colorspace)
1750   {
1751     case CMYKColorspace:
1752     {
1753       jpeg_info.input_components=4;
1754       jpeg_info.in_color_space=JCS_CMYK;
1755       break;
1756     }
1757     case YCbCrColorspace:
1758     case Rec601YCbCrColorspace:
1759     case Rec709YCbCrColorspace:
1760     {
1761       jpeg_info.in_color_space=JCS_YCbCr;
1762       break;
1763     }
1764     case GRAYColorspace:
1765     case Rec601LumaColorspace:
1766     case Rec709LumaColorspace:
1767     {
1768       jpeg_info.input_components=1;
1769       jpeg_info.in_color_space=JCS_GRAYSCALE;
1770       break;
1771     }
1772     default:
1773     {
1774       if (image->colorspace != RGBColorspace)
1775         (void) TransformImageColorspace(image,RGBColorspace);
1776       break;
1777     }
1778   }
1779   if ((image_info->type != TrueColorType) &&
1780       (IsGrayImage(image,&image->exception) != MagickFalse))
1781     {
1782       jpeg_info.input_components=1;
1783       jpeg_info.in_color_space=JCS_GRAYSCALE;
1784     }
1785   jpeg_set_defaults(&jpeg_info);
1786   if ((jpeg_info.data_precision != 12) && (image->depth <= 8))
1787     jpeg_info.data_precision=8;
1788   else
1789     if (sizeof(JSAMPLE) > 1)
1790       jpeg_info.data_precision=12;
1791   jpeg_info.density_unit=(UINT8) 1;
1792   if (image->debug != MagickFalse)
1793     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1794       "Image resolution: %.20g,%.20g",floor(image->x_resolution+0.5),
1795       floor(image->y_resolution+0.5));
1796   if ((image->x_resolution != 0.0) && (image->y_resolution != 0.0))
1797     {
1798       /*
1799         Set image resolution.
1800       */
1801       jpeg_info.write_JFIF_header=MagickTrue;
1802       jpeg_info.X_density=(UINT16) floor(image->x_resolution+0.5);
1803       jpeg_info.Y_density=(UINT16) floor(image->y_resolution+0.5);
1804       if (image->units == PixelsPerInchResolution)
1805         jpeg_info.density_unit=(UINT8) 1;
1806       if (image->units == PixelsPerCentimeterResolution)
1807         jpeg_info.density_unit=(UINT8) 2;
1808     }
1809   option=GetImageOption(image_info,"jpeg:dct-method");
1810   if (option != (const char *) NULL)
1811     switch (*option)
1812     {
1813       case 'D':
1814       case 'd':
1815       {
1816         if (LocaleCompare(option,"default") == 0)
1817           jpeg_info.dct_method=JDCT_DEFAULT;
1818         break;
1819       }
1820       case 'F':
1821       case 'f':
1822       {
1823         if (LocaleCompare(option,"fastest") == 0)
1824           jpeg_info.dct_method=JDCT_FASTEST;
1825         if (LocaleCompare(option,"float") == 0)
1826           jpeg_info.dct_method=JDCT_FLOAT;
1827         break;
1828       }
1829       case 'I':
1830       case 'i':
1831       {
1832         if (LocaleCompare(option,"ifast") == 0)
1833           jpeg_info.dct_method=JDCT_IFAST;
1834         if (LocaleCompare(option,"islow") == 0)
1835           jpeg_info.dct_method=JDCT_ISLOW;
1836         break;
1837       }
1838     }
1839   option=GetImageOption(image_info,"jpeg:optimize-coding");
1840   if (option != (const char *) NULL)
1841     {
1842       jpeg_info.optimize_coding=MagickFalse;
1843       if (IsMagickTrue(option) != MagickFalse)
1844         jpeg_info.optimize_coding=MagickTrue;
1845     }
1846   else
1847     {
1848       MagickSizeType
1849         length;
1850
1851       length=(MagickSizeType) jpeg_info.input_components*image->columns*
1852         image->rows*sizeof(JSAMPLE);
1853       if (length == (MagickSizeType) ((size_t) length))
1854         {
1855           /*
1856             Perform optimization only if available memory resources permit it.
1857           */
1858           status=AcquireMagickResource(MemoryResource,length);
1859           if (status != MagickFalse)
1860             jpeg_info.optimize_coding=MagickTrue;
1861           RelinquishMagickResource(MemoryResource,length);
1862         }
1863     }
1864 #if (JPEG_LIB_VERSION >= 61) && defined(C_PROGRESSIVE_SUPPORTED)
1865   if ((LocaleCompare(image_info->magick,"PJPEG") == 0) ||
1866       (image_info->interlace != NoInterlace))
1867     {
1868       if (image->debug != MagickFalse)
1869         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1870           "Interlace: progressive");
1871       jpeg_simple_progression(&jpeg_info);
1872     }
1873   else
1874     if (image->debug != MagickFalse)
1875       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1876         "Interlace: non-progressive");
1877 #else
1878   if (image->debug != MagickFalse)
1879     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1880       "Interlace: nonprogressive");
1881 #endif
1882   option=GetImageOption(image_info,"jpeg:extent");
1883   if (option != (const char *) NULL)
1884     {
1885       Image
1886         *jpeg_image;
1887
1888       ImageInfo
1889         *jpeg_info;
1890
1891       jpeg_info=CloneImageInfo(image_info);
1892       jpeg_image=CloneImage(image,0,0,MagickTrue,&image->exception);
1893       if (jpeg_image != (Image *) NULL)
1894         {
1895           MagickSizeType
1896             extent;
1897
1898           size_t
1899             maximum,
1900             minimum;
1901
1902           /*
1903             Search for compression quality that does not exceed image extent.
1904           */
1905           jpeg_info->quality=0;
1906           extent=(MagickSizeType) SiPrefixToDouble(option,100.0);
1907           (void) DeleteImageOption(jpeg_info,"jpeg:extent");
1908           (void) AcquireUniqueFilename(jpeg_image->filename);
1909           maximum=101;
1910           for (minimum=0; minimum != maximum; )
1911           {
1912             jpeg_image->quality=minimum+(maximum-minimum)/2;
1913             status=WriteJPEGImage(jpeg_info,jpeg_image);
1914             if (GetBlobSize(jpeg_image) <= extent)
1915               minimum=jpeg_image->quality+1;
1916             else
1917               maximum=jpeg_image->quality-1;
1918           }
1919           (void) RelinquishUniqueFileResource(jpeg_image->filename);
1920           image->quality=minimum-1;
1921           jpeg_image=DestroyImage(jpeg_image);
1922         }
1923       jpeg_info=DestroyImageInfo(jpeg_info);
1924     }
1925   if ((image_info->compression != LosslessJPEGCompression) &&
1926       (image->quality <= 100))
1927     {
1928       if (image->quality == UndefinedCompressionQuality)
1929         jpeg_set_quality(&jpeg_info,92,MagickTrue);
1930       else
1931         jpeg_set_quality(&jpeg_info,(int) image->quality,MagickTrue);
1932       if (image->debug != MagickFalse)
1933         (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Quality: %.20g",
1934           (double) image->quality);
1935     }
1936   else
1937     {
1938 #if !defined(C_LOSSLESS_SUPPORTED)
1939       jpeg_set_quality(&jpeg_info,100,MagickTrue);
1940       if (image->debug != MagickFalse)
1941         (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Quality: 100");
1942 #else
1943       if (image->quality < 100)
1944         (void) ThrowMagickException(&image->exception,GetMagickModule(),
1945           CoderWarning,"LosslessToLossyJPEGConversion",image->filename);
1946       else
1947         {
1948           int
1949             point_transform,
1950             predictor;
1951
1952           predictor=image->quality/100;  /* range 1-7 */
1953           point_transform=image->quality % 20;  /* range 0-15 */
1954           jpeg_simple_lossless(&jpeg_info,predictor,point_transform);
1955           if (image->debug != MagickFalse)
1956             {
1957               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1958                 "Compression: lossless");
1959               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1960                 "Predictor: %d",predictor);
1961               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1962                 "Point Transform: %d",point_transform);
1963             }
1964         }
1965 #endif
1966     }
1967   sampling_factor=(const char *) NULL;
1968   value=GetImageProperty(image,"jpeg:sampling-factor");
1969   if (value != (char *) NULL)
1970     {
1971       sampling_factor=value;
1972       if (image->debug != MagickFalse)
1973         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1974           "  Input sampling-factors=%s",sampling_factor);
1975     }
1976   if (image_info->sampling_factor != (char *) NULL)
1977     sampling_factor=image_info->sampling_factor;
1978   if (sampling_factor == (const char *) NULL)
1979     {
1980       if (image->quality >= 90)
1981         for (i=0; i < MAX_COMPONENTS; i++)
1982         {
1983           jpeg_info.comp_info[i].h_samp_factor=1;
1984           jpeg_info.comp_info[i].v_samp_factor=1;
1985         }
1986     }
1987   else
1988     {
1989       char
1990         **factors;
1991
1992       GeometryInfo
1993         geometry_info;
1994
1995       MagickStatusType
1996         flags;
1997
1998       /*
1999         Set sampling factor.
2000       */
2001       i=0;
2002       factors=SamplingFactorToList(sampling_factor);
2003       if (factors != (char **) NULL)
2004         {
2005           for (i=0; i < MAX_COMPONENTS; i++)
2006           {
2007             if (factors[i] == (char *) NULL)
2008               break;
2009             flags=ParseGeometry(factors[i],&geometry_info);
2010             if ((flags & SigmaValue) == 0)
2011               geometry_info.sigma=geometry_info.rho;
2012             jpeg_info.comp_info[i].h_samp_factor=(int) geometry_info.rho;
2013             jpeg_info.comp_info[i].v_samp_factor=(int) geometry_info.sigma;
2014             factors[i]=(char *) RelinquishMagickMemory(factors[i]);
2015           }
2016           factors=(char **) RelinquishMagickMemory(factors);
2017         }
2018       for ( ; i < MAX_COMPONENTS; i++)
2019       {
2020         jpeg_info.comp_info[i].h_samp_factor=1;
2021         jpeg_info.comp_info[i].v_samp_factor=1;
2022       }
2023     }
2024   if (jpeg_info.input_components == 1)
2025     for (i=0; i < MAX_COMPONENTS; i++)
2026     {
2027       jpeg_info.comp_info[i].h_samp_factor=1;
2028       jpeg_info.comp_info[i].v_samp_factor=1;
2029     }
2030   jpeg_start_compress(&jpeg_info,MagickTrue);
2031   if (image->debug != MagickFalse)
2032     {
2033       if (image->storage_class == PseudoClass)
2034         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2035           "Storage class: PseudoClass");
2036       else
2037         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2038           "Storage class: DirectClass");
2039       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Depth: %.20g",
2040         (double) image->depth);
2041       if (image->colors != 0)
2042         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2043           "Number of colors: %.20g",(double) image->colors);
2044       else
2045         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2046           "Number of colors: unspecified");
2047       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2048         "JPEG data precision: %d",(int) jpeg_info.data_precision);
2049       switch (image->colorspace)
2050       {
2051         case CMYKColorspace:
2052         {
2053           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2054             "Storage class: DirectClass");
2055           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2056             "Colorspace: CMYK");
2057           break;
2058         }
2059         case YCbCrColorspace:
2060         case Rec601YCbCrColorspace:
2061         case Rec709YCbCrColorspace:
2062         {
2063           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2064             "Colorspace: YCbCr");
2065           break;
2066         }
2067         default:
2068           break;
2069       }
2070       switch (image->colorspace)
2071       {
2072         case CMYKColorspace:
2073         {
2074           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2075             "Colorspace: CMYK");
2076           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2077             "Sampling factors: %dx%d,%dx%d,%dx%d,%dx%d",
2078             jpeg_info.comp_info[0].h_samp_factor,
2079             jpeg_info.comp_info[0].v_samp_factor,
2080             jpeg_info.comp_info[1].h_samp_factor,
2081             jpeg_info.comp_info[1].v_samp_factor,
2082             jpeg_info.comp_info[2].h_samp_factor,
2083             jpeg_info.comp_info[2].v_samp_factor,
2084             jpeg_info.comp_info[3].h_samp_factor,
2085             jpeg_info.comp_info[3].v_samp_factor);
2086           break;
2087         }
2088         case GRAYColorspace:
2089         case Rec601LumaColorspace:
2090         case Rec709LumaColorspace:
2091         {
2092           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2093             "Colorspace: GRAY");
2094           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2095             "Sampling factors: %dx%d",jpeg_info.comp_info[0].h_samp_factor,
2096             jpeg_info.comp_info[0].v_samp_factor);
2097           break;
2098         }
2099         case RGBColorspace:
2100         {
2101           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2102             "Image colorspace is RGB");
2103           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2104             "Sampling factors: %dx%d,%dx%d,%dx%d",
2105             jpeg_info.comp_info[0].h_samp_factor,
2106             jpeg_info.comp_info[0].v_samp_factor,
2107             jpeg_info.comp_info[1].h_samp_factor,
2108             jpeg_info.comp_info[1].v_samp_factor,
2109             jpeg_info.comp_info[2].h_samp_factor,
2110             jpeg_info.comp_info[2].v_samp_factor);
2111           break;
2112         }
2113         case YCbCrColorspace:
2114         case Rec601YCbCrColorspace:
2115         case Rec709YCbCrColorspace:
2116         {
2117           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2118             "Colorspace: YCbCr");
2119           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2120             "Sampling factors: %dx%d,%dx%d,%dx%d",
2121             jpeg_info.comp_info[0].h_samp_factor,
2122             jpeg_info.comp_info[0].v_samp_factor,
2123             jpeg_info.comp_info[1].h_samp_factor,
2124             jpeg_info.comp_info[1].v_samp_factor,
2125             jpeg_info.comp_info[2].h_samp_factor,
2126             jpeg_info.comp_info[2].v_samp_factor);
2127           break;
2128         }
2129         default:
2130         {
2131           (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Colorspace: %d",
2132             image->colorspace);
2133           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2134             "Sampling factors: %dx%d,%dx%d,%dx%d,%dx%d",
2135             jpeg_info.comp_info[0].h_samp_factor,
2136             jpeg_info.comp_info[0].v_samp_factor,
2137             jpeg_info.comp_info[1].h_samp_factor,
2138             jpeg_info.comp_info[1].v_samp_factor,
2139             jpeg_info.comp_info[2].h_samp_factor,
2140             jpeg_info.comp_info[2].v_samp_factor,
2141             jpeg_info.comp_info[3].h_samp_factor,
2142             jpeg_info.comp_info[3].v_samp_factor);
2143           break;
2144         }
2145       }
2146     }
2147   /*
2148     Write JPEG profiles.
2149   */
2150   value=GetImageProperty(image,"comment");
2151   if (value != (char *) NULL)
2152     for (i=0; i < (ssize_t) strlen(value); i+=65533L)
2153       jpeg_write_marker(&jpeg_info,JPEG_COM,(unsigned char *) value+i,
2154         (unsigned int) MagickMin((size_t) strlen(value+i),65533L));
2155   if (image->profiles != (void *) NULL)
2156     WriteProfile(&jpeg_info,image);
2157   /*
2158     Convert MIFF to JPEG raster pixels.
2159   */
2160   jpeg_pixels=(JSAMPLE *) AcquireQuantumMemory((size_t) image->columns,
2161     jpeg_info.input_components*sizeof(*jpeg_pixels));
2162   if (jpeg_pixels == (JSAMPLE *) NULL)
2163     ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2164   if (setjmp(error_manager.error_recovery) != 0)
2165     {
2166       jpeg_destroy_compress(&jpeg_info);
2167       if (jpeg_pixels != (unsigned char *) NULL)
2168         jpeg_pixels=(unsigned char *) RelinquishMagickMemory(jpeg_pixels);
2169       (void) CloseBlob(image);
2170       return(MagickFalse);
2171     }
2172   scanline[0]=(JSAMPROW) jpeg_pixels;
2173   if (jpeg_info.data_precision <= 8)
2174     {
2175       if ((jpeg_info.in_color_space == JCS_RGB) ||
2176           (jpeg_info.in_color_space == JCS_YCbCr))
2177         for (y=0; y < (ssize_t) image->rows; y++)
2178         {
2179           register const PixelPacket
2180             *p;
2181
2182           register ssize_t
2183             x;
2184
2185           p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2186           if (p == (const PixelPacket *) NULL)
2187             break;
2188           q=jpeg_pixels;
2189           for (x=0; x < (ssize_t) image->columns; x++)
2190           {
2191             *q++=(JSAMPLE) ScaleQuantumToChar(GetRedPixelComponent(p));
2192             *q++=(JSAMPLE) ScaleQuantumToChar(GetGreenPixelComponent(p));
2193             *q++=(JSAMPLE) ScaleQuantumToChar(GetBluePixelComponent(p));
2194             p++;
2195           }
2196           (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2197           status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2198             image->rows);
2199           if (status == MagickFalse)
2200             break;
2201         }
2202       else
2203         if (jpeg_info.in_color_space == JCS_GRAYSCALE)
2204           for (y=0; y < (ssize_t) image->rows; y++)
2205           {
2206             register const PixelPacket
2207               *p;
2208
2209             register ssize_t
2210               x;
2211
2212             p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2213             if (p == (const PixelPacket *) NULL)
2214               break;
2215             q=jpeg_pixels;
2216             for (x=0; x < (ssize_t) image->columns; x++)
2217             {
2218               *q++=(JSAMPLE) ScaleQuantumToChar(PixelIntensityToQuantum(p));
2219               p++;
2220             }
2221             (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2222             status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2223               image->rows);
2224             if (status == MagickFalse)
2225               break;
2226           }
2227         else
2228           for (y=0; y < (ssize_t) image->rows; y++)
2229           {
2230             register const IndexPacket
2231               *indexes;
2232
2233             register const PixelPacket
2234               *p;
2235
2236             register ssize_t
2237               x;
2238
2239             p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2240             if (p == (const PixelPacket *) NULL)
2241               break;
2242             q=jpeg_pixels;
2243             indexes=GetVirtualIndexQueue(image);
2244             for (x=0; x < (ssize_t) image->columns; x++)
2245             {
2246               /*
2247                 Convert DirectClass packets to contiguous CMYK scanlines.
2248               */
2249               *q++=(JSAMPLE) (ScaleQuantumToChar((Quantum) (QuantumRange-
2250                 GetRedPixelComponent(p))));
2251               *q++=(JSAMPLE) (ScaleQuantumToChar((Quantum) (QuantumRange-
2252                 GetGreenPixelComponent(p))));
2253               *q++=(JSAMPLE) (ScaleQuantumToChar((Quantum) (QuantumRange-
2254                 GetBluePixelComponent(p))));
2255               *q++=(JSAMPLE) (ScaleQuantumToChar((Quantum) (QuantumRange-
2256                 GetIndexPixelComponent(indexes+x))));
2257               p++;
2258             }
2259             (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2260             status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2261               image->rows);
2262             if (status == MagickFalse)
2263               break;
2264           }
2265     }
2266   else
2267     if (jpeg_info.in_color_space == JCS_GRAYSCALE)
2268       for (y=0; y < (ssize_t) image->rows; y++)
2269       {
2270         register const PixelPacket
2271           *p;
2272
2273         register ssize_t
2274           x;
2275
2276         p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2277         if (p == (const PixelPacket *) NULL)
2278           break;
2279         q=jpeg_pixels;
2280         for (x=0; x < (ssize_t) image->columns; x++)
2281         {
2282           *q++=(JSAMPLE) (ScaleQuantumToShort(PixelIntensityToQuantum(p)) >>
2283             4);
2284           p++;
2285         }
2286         (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2287         status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2288           image->rows);
2289         if (status == MagickFalse)
2290           break;
2291       }
2292     else
2293       if ((jpeg_info.in_color_space == JCS_RGB) ||
2294           (jpeg_info.in_color_space == JCS_YCbCr))
2295         for (y=0; y < (ssize_t) image->rows; y++)
2296         {
2297           register const PixelPacket
2298             *p;
2299
2300           register ssize_t
2301             x;
2302
2303           p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2304           if (p == (const PixelPacket *) NULL)
2305             break;
2306           q=jpeg_pixels;
2307           for (x=0; x < (ssize_t) image->columns; x++)
2308           {
2309             *q++=(JSAMPLE) (ScaleQuantumToShort(GetRedPixelComponent(p)) >>
2310               4);
2311             *q++=(JSAMPLE) (ScaleQuantumToShort(GetGreenPixelComponent(p)) >>
2312               4);
2313             *q++=(JSAMPLE) (ScaleQuantumToShort(GetBluePixelComponent(p)) >>
2314               4);
2315             p++;
2316           }
2317           (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2318           status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2319             image->rows);
2320           if (status == MagickFalse)
2321             break;
2322         }
2323       else
2324         for (y=0; y < (ssize_t) image->rows; y++)
2325         {
2326           register const IndexPacket
2327             *indexes;
2328
2329           register const PixelPacket
2330             *p;
2331
2332           register ssize_t
2333             x;
2334
2335           p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2336           if (p == (const PixelPacket *) NULL)
2337             break;
2338           q=jpeg_pixels;
2339           indexes=GetVirtualIndexQueue(image);
2340           for (x=0; x < (ssize_t) image->columns; x++)
2341           {
2342             /*
2343               Convert DirectClass packets to contiguous CMYK scanlines.
2344             */
2345             *q++=(JSAMPLE) (4095-(ScaleQuantumToShort(
2346               GetRedPixelComponent(p)) >> 4));
2347             *q++=(JSAMPLE) (4095-(ScaleQuantumToShort(
2348               GetGreenPixelComponent(p)) >> 4));
2349             *q++=(JSAMPLE) (4095-(ScaleQuantumToShort(
2350               GetBluePixelComponent(p)) >> 4));
2351             *q++=(JSAMPLE) (4095-(ScaleQuantumToShort(
2352               GetIndexPixelComponent(indexes+x)) >> 4));
2353             p++;
2354           }
2355           (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2356           status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2357             image->rows);
2358           if (status == MagickFalse)
2359             break;
2360         }
2361   if (y == (ssize_t) image->rows)
2362     jpeg_finish_compress(&jpeg_info);
2363   /*
2364     Relinquish resources.
2365   */
2366   jpeg_destroy_compress(&jpeg_info);
2367   jpeg_pixels=(unsigned char *) RelinquishMagickMemory(jpeg_pixels);
2368   (void) CloseBlob(image);
2369   return(MagickTrue);
2370 }
2371 #endif