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