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