]> 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 "magick/studio.h"
47 #include "magick/blob.h"
48 #include "magick/blob-private.h"
49 #include "magick/cache.h"
50 #include "magick/color.h"
51 #include "magick/colormap-private.h"
52 #include "magick/color-private.h"
53 #include "magick/colormap.h"
54 #include "magick/colorspace.h"
55 #include "magick/constitute.h"
56 #include "magick/exception.h"
57 #include "magick/exception-private.h"
58 #include "magick/geometry.h"
59 #include "magick/image.h"
60 #include "magick/image-private.h"
61 #include "magick/list.h"
62 #include "magick/log.h"
63 #include "magick/magick.h"
64 #include "magick/memory_.h"
65 #include "magick/module.h"
66 #include "magick/monitor.h"
67 #include "magick/monitor-private.h"
68 #include "magick/option.h"
69 #include "magick/profile.h"
70 #include "magick/property.h"
71 #include "magick/quantum-private.h"
72 #include "magick/resource_.h"
73 #include "magick/splay-tree.h"
74 #include "magick/static.h"
75 #include "magick/string_.h"
76 #include "magick/string-private.h"
77 #include "magick/utility.h"
78 #include <setjmp.h>
79 #if defined(MAGICKCORE_JPEG_DELEGATE)
80 #define JPEG_INTERNAL_OPTIONS
81 #if defined(__MINGW32__)
82 # define XMD_H 1  /* Avoid conflicting typedef for INT32 */
83 typedef unsigned char boolean;
84 #define HAVE_BOOLEAN
85 #endif
86 #undef HAVE_STDLIB_H
87 #include "jpeglib.h"
88 #include "jerror.h"
89 #endif
90 \f
91 /*
92   Define declarations.
93 */
94 #define ICC_MARKER  (JPEG_APP0+2)
95 #define ICC_PROFILE  "ICC_PROFILE"
96 #define IPTC_MARKER  (JPEG_APP0+13)
97 #define XML_MARKER  (JPEG_APP0+1)
98 #define MaxBufferExtent  8192
99 \f
100 /*
101   Typedef declarations.
102 */
103 #if defined(MAGICKCORE_JPEG_DELEGATE)
104 typedef struct _DestinationManager
105 {
106   struct jpeg_destination_mgr
107     manager;
108
109   Image
110     *image;
111
112   JOCTET
113     *buffer;
114 } DestinationManager;
115
116 typedef struct _ErrorManager
117 {
118   Image
119     *image;
120
121   MagickBooleanType
122     finished;
123
124   jmp_buf
125     error_recovery;
126 } ErrorManager;
127
128 typedef struct _SourceManager
129 {
130   struct jpeg_source_mgr
131     manager;
132
133   Image
134     *image;
135
136   JOCTET
137     *buffer;
138
139   boolean
140     start_of_blob;
141 } SourceManager;
142 #endif
143 \f
144 /*
145   Forward declarations.
146 */
147 #if defined(MAGICKCORE_JPEG_DELEGATE)
148 static MagickBooleanType
149   WriteJPEGImage(const ImageInfo *,Image *);
150 #endif
151 \f
152 /*
153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
154 %                                                                             %
155 %                                                                             %
156 %                                                                             %
157 %   I s J P E G                                                               %
158 %                                                                             %
159 %                                                                             %
160 %                                                                             %
161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
162 %
163 %  IsJPEG() returns MagickTrue if the image format type, identified by the
164 %  magick string, is JPEG.
165 %
166 %  The format of the IsJPEG  method is:
167 %
168 %      MagickBooleanType IsJPEG(const unsigned char *magick,const size_t length)
169 %
170 %  A description of each parameter follows:
171 %
172 %    o magick: compare image format pattern against these bytes.
173 %
174 %    o length: Specifies the length of the magick string.
175 %
176 */
177 static MagickBooleanType IsJPEG(const unsigned char *magick,const size_t length)
178 {
179   if (length < 3)
180     return(MagickFalse);
181   if (memcmp(magick,"\377\330\377",3) == 0)
182     return(MagickTrue);
183   return(MagickFalse);
184 }
185 \f
186 #if defined(MAGICKCORE_JPEG_DELEGATE)
187 /*
188 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
189 %                                                                             %
190 %                                                                             %
191 %                                                                             %
192 %   R e a d J P E G I m a g e                                                 %
193 %                                                                             %
194 %                                                                             %
195 %                                                                             %
196 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
197 %
198 %  ReadJPEGImage() reads a JPEG image file and returns it.  It allocates
199 %  the memory necessary for the new Image structure and returns a pointer to
200 %  the new image.
201 %
202 %  The format of the ReadJPEGImage method is:
203 %
204 %      Image *ReadJPEGImage(const ImageInfo *image_info,
205 %        ExceptionInfo *exception)
206 %
207 %  A description of each parameter follows:
208 %
209 %    o image_info: the image info.
210 %
211 %    o exception: return any errors or warnings in this structure.
212 %
213 */
214
215 static boolean FillInputBuffer(j_decompress_ptr cinfo)
216 {
217   SourceManager
218     *source;
219
220   source=(SourceManager *) cinfo->src;
221   source->manager.bytes_in_buffer=(size_t) ReadBlob(source->image,
222     MaxBufferExtent,source->buffer);
223   if (source->manager.bytes_in_buffer == 0)
224     {
225       if (source->start_of_blob != 0)
226         ERREXIT(cinfo,JERR_INPUT_EMPTY);
227       WARNMS(cinfo,JWRN_JPEG_EOF);
228       source->buffer[0]=(JOCTET) 0xff;
229       source->buffer[1]=(JOCTET) JPEG_EOI;
230       source->manager.bytes_in_buffer=2;
231     }
232   source->manager.next_input_byte=source->buffer;
233   source->start_of_blob=FALSE;
234   return(TRUE);
235 }
236
237 static int GetCharacter(j_decompress_ptr jpeg_info)
238 {
239   if (jpeg_info->src->bytes_in_buffer == 0)
240     (void) (*jpeg_info->src->fill_input_buffer)(jpeg_info);
241   jpeg_info->src->bytes_in_buffer--;
242   return((int) GETJOCTET(*jpeg_info->src->next_input_byte++));
243 }
244
245 static void InitializeSource(j_decompress_ptr cinfo)
246 {
247   SourceManager
248     *source;
249
250   source=(SourceManager *) cinfo->src;
251   source->start_of_blob=TRUE;
252 }
253
254 static MagickBooleanType IsITUFaxImage(const Image *image)
255 {
256   const StringInfo
257     *profile;
258
259   const unsigned char
260     *datum;
261
262   profile=GetImageProfile(image,"8bim");
263   if (profile == (const StringInfo *) NULL)
264     return(MagickFalse);
265   if (GetStringInfoLength(profile) < 5)
266     return(MagickFalse);
267   datum=GetStringInfoDatum(profile);
268   if ((datum[0] == 0x47) && (datum[1] == 0x33) && (datum[2] == 0x46) &&
269       (datum[3] == 0x41) && (datum[4] == 0x58))
270     return(MagickTrue);
271   return(MagickFalse);
272 }
273
274 static MagickBooleanType JPEGErrorHandler(j_common_ptr jpeg_info)
275 {
276   char
277     message[JMSG_LENGTH_MAX];
278
279   ErrorManager
280     *error_manager;
281
282   Image
283     *image;
284
285   *message='\0';
286   error_manager=(ErrorManager *) jpeg_info->client_data;
287   image=error_manager->image;
288   if (image->debug != MagickFalse)
289     {
290       /*
291         Log trace message.
292       */
293       (jpeg_info->err->format_message)(jpeg_info,message);
294       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
295         "[%s] JPEG Trace: \"%s\"",image->filename,message);
296     }
297   if (error_manager->finished != MagickFalse)
298     ThrowBinaryException(CorruptImageWarning,(char *) message,image->filename)
299   else
300     ThrowBinaryException(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)
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) FormatMagickString(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) FormatMagickString(sampling_factor,MaxTextExtent,
844         "%dx%d,%dx%d,%dx%d,%dx%d",jpeg_info->comp_info[0].h_samp_factor,
845         jpeg_info->comp_info[0].v_samp_factor,
846         jpeg_info->comp_info[1].h_samp_factor,
847         jpeg_info->comp_info[1].v_samp_factor,
848         jpeg_info->comp_info[2].h_samp_factor,
849         jpeg_info->comp_info[2].v_samp_factor,
850         jpeg_info->comp_info[3].h_samp_factor,
851         jpeg_info->comp_info[3].v_samp_factor);
852       break;
853     }
854     case JCS_GRAYSCALE:
855     {
856       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
857         "Colorspace: GRAYSCALE");
858       (void) FormatMagickString(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) FormatMagickString(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) FormatMagickString(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   IndexPacket
912     index;
913
914   JSAMPLE
915     *jpeg_pixels;
916
917   JSAMPROW
918     scanline[1];
919
920   MagickBooleanType
921     debug,
922     status;
923
924   MagickSizeType
925     number_pixels;
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) FormatMagickString(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].opacity=OpaqueOpacity;
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].opacity=OpaqueOpacity;
1213         }
1214     }
1215   scanline[0]=(JSAMPROW) jpeg_pixels;
1216   for (y=0; y < (ssize_t) image->rows; y++)
1217   {
1218     register IndexPacket
1219       *restrict indexes;
1220
1221     register ssize_t
1222       x;
1223
1224     register PixelPacket
1225       *restrict q;
1226
1227     if (jpeg_read_scanlines(&jpeg_info,scanline,1) != 1)
1228       {
1229         (void) ThrowMagickException(exception,GetMagickModule(),
1230           CorruptImageWarning,"SkipToSyncByte","`%s'",image->filename);
1231         continue;
1232       }
1233     p=jpeg_pixels;
1234     q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1235     if (q == (PixelPacket *) NULL)
1236       break;
1237     indexes=GetAuthenticIndexQueue(image);
1238     if (jpeg_info.data_precision > 8)
1239       {
1240         if (jpeg_info.output_components == 1)
1241           for (x=0; x < (ssize_t) image->columns; x++)
1242           {
1243             size_t
1244               pixel;
1245
1246             if (precision != 16)
1247               pixel=(size_t) GETJSAMPLE(*p);
1248             else
1249               pixel=(size_t) ((GETJSAMPLE(*p) ^ 0x80) << 4);
1250             index=ConstrainColormapIndex(image,pixel);
1251             SetIndexPixelComponent(indexes+x,index);
1252             SetRedPixelComponent(q,image->colormap[(int) index].red);
1253             SetGreenPixelComponent(q,image->colormap[(int) index].green);
1254             SetBluePixelComponent(q,image->colormap[(int) index].blue);
1255             p++;
1256             q++;
1257           }
1258         else
1259           if (image->colorspace != CMYKColorspace)
1260             for (x=0; x < (ssize_t) image->columns; x++)
1261             {
1262               SetRedPixelComponent(q,ScaleShortToQuantum((unsigned char)
1263                 (GETJSAMPLE(*p++) << 4)));
1264               SetGreenPixelComponent(q,ScaleShortToQuantum((unsigned char)
1265                 (GETJSAMPLE(*p++) << 4)));
1266               SetBluePixelComponent(q,ScaleShortToQuantum((unsigned char)
1267                 (GETJSAMPLE(*p++) << 4)));
1268               SetOpacityPixelComponent(q,OpaqueOpacity);
1269               q++;
1270             }
1271           else
1272             for (x=0; x < (ssize_t) image->columns; x++)
1273             {
1274               SetCyanPixelComponent(q,QuantumRange-ScaleShortToQuantum(
1275                 (unsigned char) (GETJSAMPLE(*p++) << 4)));
1276               SetMagentaPixelComponent(q,QuantumRange-ScaleShortToQuantum(
1277                 (unsigned char) (GETJSAMPLE(*p++) << 4)));
1278               SetYellowPixelComponent(q,QuantumRange-ScaleShortToQuantum(
1279                 (unsigned char) (GETJSAMPLE(*p++) << 4)));
1280               SetBlackPixelComponent(indexes+x,QuantumRange-ScaleShortToQuantum(
1281                 (unsigned char) (GETJSAMPLE(*p++) << 4)));
1282               SetOpacityPixelComponent(q,OpaqueOpacity);
1283               q++;
1284             }
1285       }
1286     else
1287       if (jpeg_info.output_components == 1)
1288         for (x=0; x < (ssize_t) image->columns; x++)
1289         {
1290           index=ConstrainColormapIndex(image,(size_t) GETJSAMPLE(*p));
1291           SetIndexPixelComponent(indexes+x,index);
1292           SetRedPixelComponent(q,image->colormap[(int) index].red);
1293           SetGreenPixelComponent(q,image->colormap[(int) index].green);
1294           SetBluePixelComponent(q,image->colormap[(int) index].blue);
1295           p++;
1296           q++;
1297         }
1298       else
1299         if (image->colorspace != CMYKColorspace)
1300           for (x=0; x < (ssize_t) image->columns; x++)
1301           {
1302             SetRedPixelComponent(q,ScaleCharToQuantum((unsigned char)
1303               GETJSAMPLE(*p++)));
1304             SetGreenPixelComponent(q,ScaleCharToQuantum((unsigned char)
1305               GETJSAMPLE(*p++)));
1306             SetBluePixelComponent(q,ScaleCharToQuantum((unsigned char)
1307               GETJSAMPLE(*p++)));
1308             SetOpacityPixelComponent(q,OpaqueOpacity);
1309             q++;
1310           }
1311         else
1312           for (x=0; x < (ssize_t) image->columns; x++)
1313           {
1314             SetCyanPixelComponent(q,QuantumRange-ScaleCharToQuantum(
1315               (unsigned char) GETJSAMPLE(*p++)));
1316             SetMagentaPixelComponent(q,QuantumRange-ScaleCharToQuantum(
1317               (unsigned char) GETJSAMPLE(*p++)));
1318             SetYellowPixelComponent(q,QuantumRange-ScaleCharToQuantum(
1319               (unsigned char) GETJSAMPLE(*p++)));
1320             SetBlackPixelComponent(indexes+x,QuantumRange-ScaleCharToQuantum(
1321               (unsigned char) GETJSAMPLE(*p++)));
1322             SetOpacityPixelComponent(q,OpaqueOpacity);
1323             q++;
1324           }
1325     if (SyncAuthenticPixels(image,exception) == MagickFalse)
1326       break;
1327     status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
1328       image->rows);
1329     if (status == MagickFalse)
1330       {
1331         jpeg_abort_decompress(&jpeg_info);
1332         break;
1333       }
1334   }
1335   if (status != MagickFalse)
1336     {
1337       error_manager.finished=MagickTrue;
1338       if (setjmp(error_manager.error_recovery) == 0)
1339         (void) jpeg_finish_decompress(&jpeg_info);
1340     }
1341   /*
1342     Free jpeg resources.
1343   */
1344   jpeg_destroy_decompress(&jpeg_info);
1345   jpeg_pixels=(unsigned char *) RelinquishMagickMemory(jpeg_pixels);
1346   (void) CloseBlob(image);
1347   return(GetFirstImageInList(image));
1348 }
1349 #endif
1350 \f
1351 /*
1352 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1353 %                                                                             %
1354 %                                                                             %
1355 %                                                                             %
1356 %   R e g i s t e r J P E G I m a g e                                         %
1357 %                                                                             %
1358 %                                                                             %
1359 %                                                                             %
1360 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1361 %
1362 %  RegisterJPEGImage() adds properties for the JPEG image format to
1363 %  the list of supported formats.  The properties include the image format
1364 %  tag, a method to read and/or write the format, whether the format
1365 %  supports the saving of more than one frame to the same file or blob,
1366 %  whether the format supports native in-memory I/O, and a brief
1367 %  description of the format.
1368 %
1369 %  The format of the RegisterJPEGImage method is:
1370 %
1371 %      size_t RegisterJPEGImage(void)
1372 %
1373 */
1374 ModuleExport size_t RegisterJPEGImage(void)
1375 {
1376   char
1377     version[MaxTextExtent];
1378
1379   MagickInfo
1380     *entry;
1381
1382   static const char
1383     description[] = "Joint Photographic Experts Group JFIF format";
1384
1385   *version='\0';
1386 #if defined(JPEG_LIB_VERSION)
1387   (void) FormatMagickString(version,MaxTextExtent,"%d",JPEG_LIB_VERSION);
1388 #endif
1389   entry=SetMagickInfo("JPEG");
1390   entry->thread_support=NoThreadSupport;
1391 #if defined(MAGICKCORE_JPEG_DELEGATE)
1392   entry->decoder=(DecodeImageHandler *) ReadJPEGImage;
1393   entry->encoder=(EncodeImageHandler *) WriteJPEGImage;
1394 #endif
1395   entry->magick=(IsImageFormatHandler *) IsJPEG;
1396   entry->adjoin=MagickFalse;
1397   entry->description=ConstantString(description);
1398   if (*version != '\0')
1399     entry->version=ConstantString(version);
1400   entry->module=ConstantString("JPEG");
1401   (void) RegisterMagickInfo(entry);
1402   entry=SetMagickInfo("JPG");
1403   entry->thread_support=NoThreadSupport;
1404 #if defined(MAGICKCORE_JPEG_DELEGATE)
1405   entry->decoder=(DecodeImageHandler *) ReadJPEGImage;
1406   entry->encoder=(EncodeImageHandler *) WriteJPEGImage;
1407 #endif
1408   entry->adjoin=MagickFalse;
1409   entry->description=ConstantString(description);
1410   if (*version != '\0')
1411     entry->version=ConstantString(version);
1412   entry->module=ConstantString("JPEG");
1413   (void) RegisterMagickInfo(entry);
1414   entry=SetMagickInfo("PJPEG");
1415   entry->thread_support=NoThreadSupport;
1416 #if defined(MAGICKCORE_JPEG_DELEGATE)
1417   entry->decoder=(DecodeImageHandler *) ReadJPEGImage;
1418   entry->encoder=(EncodeImageHandler *) WriteJPEGImage;
1419 #endif
1420   entry->adjoin=MagickFalse;
1421   entry->description=ConstantString(description);
1422   if (*version != '\0')
1423     entry->version=ConstantString(version);
1424   entry->module=ConstantString("JPEG");
1425   (void) RegisterMagickInfo(entry);
1426   return(MagickImageCoderSignature);
1427 }
1428 \f
1429 /*
1430 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1431 %                                                                             %
1432 %                                                                             %
1433 %                                                                             %
1434 %   U n r e g i s t e r J P E G I m a g e                                     %
1435 %                                                                             %
1436 %                                                                             %
1437 %                                                                             %
1438 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1439 %
1440 %  UnregisterJPEGImage() removes format registrations made by the
1441 %  JPEG module from the list of supported formats.
1442 %
1443 %  The format of the UnregisterJPEGImage method is:
1444 %
1445 %      UnregisterJPEGImage(void)
1446 %
1447 */
1448 ModuleExport void UnregisterJPEGImage(void)
1449 {
1450   (void) UnregisterMagickInfo("PJPG");
1451   (void) UnregisterMagickInfo("JPEG");
1452   (void) UnregisterMagickInfo("JPG");
1453 }
1454 \f
1455 #if defined(MAGICKCORE_JPEG_DELEGATE)
1456 /*
1457 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1458 %                                                                             %
1459 %                                                                             %
1460 %                                                                             %
1461 %  W r i t e J P E G I m a g e                                                %
1462 %                                                                             %
1463 %                                                                             %
1464 %                                                                             %
1465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1466 %
1467 %  WriteJPEGImage() writes a JPEG image file and returns it.  It
1468 %  allocates the memory necessary for the new Image structure and returns a
1469 %  pointer to the new image.
1470 %
1471 %  The format of the WriteJPEGImage method is:
1472 %
1473 %      MagickBooleanType WriteJPEGImage(const ImageInfo *image_info,
1474 %        Image *image)
1475 %
1476 %  A description of each parameter follows:
1477 %
1478 %    o image_info: the image info.
1479 %
1480 %    o jpeg_image:  The image.
1481 %
1482 %
1483 */
1484
1485 static boolean EmptyOutputBuffer(j_compress_ptr cinfo)
1486 {
1487   DestinationManager
1488     *destination;
1489
1490   destination=(DestinationManager *) cinfo->dest;
1491   destination->manager.free_in_buffer=(size_t) WriteBlob(destination->image,
1492     MaxBufferExtent,destination->buffer);
1493   if (destination->manager.free_in_buffer != MaxBufferExtent)
1494     ERREXIT(cinfo,JERR_FILE_WRITE);
1495   destination->manager.next_output_byte=destination->buffer;
1496   return(TRUE);
1497 }
1498
1499 static void InitializeDestination(j_compress_ptr cinfo)
1500 {
1501   DestinationManager
1502     *destination;
1503
1504   destination=(DestinationManager *) cinfo->dest;
1505   destination->buffer=(JOCTET *) (*cinfo->mem->alloc_small)
1506     ((j_common_ptr) cinfo,JPOOL_IMAGE,MaxBufferExtent*sizeof(JOCTET));
1507   destination->manager.next_output_byte=destination->buffer;
1508   destination->manager.free_in_buffer=MaxBufferExtent;
1509 }
1510
1511 static inline size_t MagickMin(const size_t x,const size_t y)
1512 {
1513   if (x < y)
1514     return(x);
1515   return(y);
1516 }
1517
1518 static void TerminateDestination(j_compress_ptr cinfo)
1519 {
1520   DestinationManager
1521     *destination;
1522
1523   destination=(DestinationManager *) cinfo->dest;
1524   if ((MaxBufferExtent-(int) destination->manager.free_in_buffer) > 0)
1525     {
1526       ssize_t
1527         count;
1528
1529       count=WriteBlob(destination->image,MaxBufferExtent-
1530         destination->manager.free_in_buffer,destination->buffer);
1531       if (count != (ssize_t)
1532           (MaxBufferExtent-destination->manager.free_in_buffer))
1533         ERREXIT(cinfo,JERR_FILE_WRITE);
1534     }
1535 }
1536
1537 static void WriteProfile(j_compress_ptr jpeg_info,Image *image)
1538 {
1539   const char
1540     *name;
1541
1542   const StringInfo
1543     *profile;
1544
1545   MagickBooleanType
1546     iptc;
1547
1548   register ssize_t
1549     i;
1550
1551   size_t
1552     length,
1553     tag_length;
1554
1555   StringInfo
1556     *custom_profile;
1557
1558   /*
1559     Save image profile as a APP marker.
1560   */
1561   iptc=MagickFalse;
1562   custom_profile=AcquireStringInfo(65535L);
1563   ResetImageProfileIterator(image);
1564   for (name=GetNextImageProfile(image); name != (const char *) NULL; )
1565   {
1566     register unsigned char
1567       *p;
1568
1569     profile=GetImageProfile(image,name);
1570     p=GetStringInfoDatum(custom_profile);
1571     if (LocaleCompare(name,"EXIF") == 0)
1572       for (i=0; i < (ssize_t) GetStringInfoLength(profile); i+=65533L)
1573       {
1574         length=MagickMin(GetStringInfoLength(profile)-i,65533L);
1575         jpeg_write_marker(jpeg_info,XML_MARKER,GetStringInfoDatum(profile)+i,
1576           (unsigned int) length);
1577       }
1578     if (LocaleCompare(name,"ICC") == 0)
1579       {
1580         register unsigned char
1581           *p;
1582
1583         tag_length=14;
1584         p=GetStringInfoDatum(custom_profile);
1585         (void) CopyMagickMemory(p,ICC_PROFILE,tag_length);
1586         for (i=0; i < (ssize_t) GetStringInfoLength(profile); i+=65519L)
1587         {
1588           length=MagickMin(GetStringInfoLength(profile)-i,65519L);
1589           p[12]=(unsigned char) ((i/65519L)+1);
1590           p[13]=(unsigned char) (GetStringInfoLength(profile)/65519L+1);
1591           (void) CopyMagickMemory(p+tag_length,GetStringInfoDatum(profile)+i,
1592             length);
1593           jpeg_write_marker(jpeg_info,ICC_MARKER,GetStringInfoDatum(
1594             custom_profile),(unsigned int) (length+tag_length));
1595         }
1596       }
1597     if (((LocaleCompare(name,"IPTC") == 0) ||
1598         (LocaleCompare(name,"8BIM") == 0)) && (iptc == MagickFalse))
1599       {
1600         size_t
1601           roundup;
1602
1603         iptc=MagickTrue;
1604         for (i=0; i < (ssize_t) GetStringInfoLength(profile); i+=65500L)
1605         {
1606           length=MagickMin(GetStringInfoLength(profile)-i,65500L);
1607           roundup=(size_t) (length & 0x01);
1608           if (LocaleNCompare((char *) GetStringInfoDatum(profile),"8BIM",4) == 0)
1609             {
1610               (void) memcpy(p,"Photoshop 3.0 ",14);
1611               tag_length=14;
1612             }
1613           else
1614             {
1615               (void) CopyMagickMemory(p,"Photoshop 3.0 8BIM\04\04\0\0\0\0",24);
1616               tag_length=26;
1617               p[24]=(unsigned char) (length >> 8);
1618               p[25]=(unsigned char) (length & 0xff);
1619             }
1620           p[13]=0x00;
1621           (void) memcpy(p+tag_length,GetStringInfoDatum(profile)+i,length);
1622           if (roundup != 0)
1623             p[length+tag_length]='\0';
1624           jpeg_write_marker(jpeg_info,IPTC_MARKER,GetStringInfoDatum(
1625             custom_profile),(unsigned int) (length+tag_length+roundup));
1626         }
1627       }
1628     if (LocaleCompare(name,"XMP") == 0)
1629       {
1630         StringInfo
1631           *xmp_profile;
1632
1633         /*
1634           Add namespace to XMP profile.
1635         */
1636         xmp_profile=StringToStringInfo("http://ns.adobe.com/xap/1.0/");
1637         ConcatenateStringInfo(xmp_profile,profile);
1638         GetStringInfoDatum(xmp_profile)[28]='\0';
1639         for (i=0; i < (ssize_t) GetStringInfoLength(xmp_profile); i+=65533L)
1640         {
1641           length=MagickMin(GetStringInfoLength(xmp_profile)-i,65533L);
1642           jpeg_write_marker(jpeg_info,XML_MARKER,
1643             GetStringInfoDatum(xmp_profile)+i,(unsigned int) length);
1644         }
1645         xmp_profile=DestroyStringInfo(xmp_profile);
1646       }
1647     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1648       "%s profile: %.20g bytes",name,(double) GetStringInfoLength(profile));
1649     name=GetNextImageProfile(image);
1650   }
1651   custom_profile=DestroyStringInfo(custom_profile);
1652 }
1653
1654 static void JPEGDestinationManager(j_compress_ptr cinfo,Image * image)
1655 {
1656   DestinationManager
1657     *destination;
1658
1659   cinfo->dest=(struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small)
1660     ((j_common_ptr) cinfo,JPOOL_IMAGE,sizeof(DestinationManager));
1661   destination=(DestinationManager *) cinfo->dest;
1662   destination->manager.init_destination=InitializeDestination;
1663   destination->manager.empty_output_buffer=EmptyOutputBuffer;
1664   destination->manager.term_destination=TerminateDestination;
1665   destination->image=image;
1666 }
1667
1668 static char **SamplingFactorToList(const char *text)
1669 {
1670   char
1671     **textlist;
1672
1673   register char
1674     *q;
1675
1676   register const char
1677     *p;
1678
1679   register ssize_t
1680     i;
1681
1682   size_t
1683     lines;
1684
1685   if (text == (char *) NULL)
1686     return((char **) NULL);
1687   /*
1688     Convert string to an ASCII list.
1689   */
1690   lines=1;
1691   for (p=text; *p != '\0'; p++)
1692     if (*p == ',')
1693       lines++;
1694   textlist=(char **) AcquireQuantumMemory((size_t) lines+MaxTextExtent,
1695     sizeof(*textlist));
1696   if (textlist == (char **) NULL)
1697     ThrowFatalException(ResourceLimitFatalError,"UnableToConvertText");
1698   p=text;
1699   for (i=0; i < (ssize_t) lines; i++)
1700   {
1701     for (q=(char *) p; *q != '\0'; q++)
1702       if (*q == ',')
1703         break;
1704     textlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent,
1705       sizeof(*textlist[i]));
1706     if (textlist[i] == (char *) NULL)
1707       ThrowFatalException(ResourceLimitFatalError,"UnableToConvertText");
1708     (void) CopyMagickString(textlist[i],p,(size_t) (q-p+1));
1709     if (*q == '\r')
1710       q++;
1711     p=q+1;
1712   }
1713   textlist[i]=(char *) NULL;
1714   return(textlist);
1715 }
1716
1717 static MagickBooleanType WriteJPEGImage(const ImageInfo *image_info,
1718   Image *image)
1719 {
1720   const char
1721     *option,
1722     *sampling_factor,
1723     *value;
1724
1725   ErrorManager
1726     error_manager;
1727
1728   JSAMPLE
1729     *jpeg_pixels;
1730
1731   JSAMPROW
1732     scanline[1];
1733
1734   MagickBooleanType
1735     status;
1736
1737   register JSAMPLE
1738     *q;
1739
1740   register ssize_t
1741     i;
1742
1743   ssize_t
1744     y;
1745
1746   struct jpeg_compress_struct
1747     jpeg_info;
1748
1749   struct jpeg_error_mgr
1750     jpeg_error;
1751
1752   /*
1753     Open image file.
1754   */
1755   assert(image_info != (const ImageInfo *) NULL);
1756   assert(image_info->signature == MagickSignature);
1757   assert(image != (Image *) NULL);
1758   assert(image->signature == MagickSignature);
1759   if (image->debug != MagickFalse)
1760     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1761   status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1762   if (status == MagickFalse)
1763     return(status);
1764   /*
1765     Initialize JPEG parameters.
1766   */
1767   (void) ResetMagickMemory(&error_manager,0,sizeof(error_manager));
1768   (void) ResetMagickMemory(&jpeg_info,0,sizeof(jpeg_info));
1769   (void) ResetMagickMemory(&jpeg_error,0,sizeof(jpeg_error));
1770   jpeg_info.client_data=(void *) image;
1771   jpeg_info.err=jpeg_std_error(&jpeg_error);
1772   jpeg_info.err->emit_message=(void (*)(j_common_ptr,int)) JPEGWarningHandler;
1773   jpeg_info.err->error_exit=(void (*)(j_common_ptr)) JPEGErrorHandler;
1774   error_manager.image=image;
1775   jpeg_pixels=(JSAMPLE *) NULL;
1776   if (setjmp(error_manager.error_recovery) != 0)
1777     {
1778       jpeg_destroy_compress(&jpeg_info);
1779       (void) CloseBlob(image);
1780       return(MagickFalse);
1781     }
1782   jpeg_info.client_data=(void *) &error_manager;
1783   jpeg_create_compress(&jpeg_info);
1784   JPEGDestinationManager(&jpeg_info,image);
1785   if ((image->columns != (unsigned int) image->columns) ||
1786       (image->rows != (unsigned int) image->rows))
1787     ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
1788   jpeg_info.image_width=(unsigned int) image->columns;
1789   jpeg_info.image_height=(unsigned int) image->rows;
1790   jpeg_info.input_components=3;
1791   jpeg_info.data_precision=8;
1792   jpeg_info.in_color_space=JCS_RGB;
1793   switch (image->colorspace)
1794   {
1795     case CMYKColorspace:
1796     {
1797       jpeg_info.input_components=4;
1798       jpeg_info.in_color_space=JCS_CMYK;
1799       break;
1800     }
1801     case YCbCrColorspace:
1802     case Rec601YCbCrColorspace:
1803     case Rec709YCbCrColorspace:
1804     {
1805       jpeg_info.in_color_space=JCS_YCbCr;
1806       break;
1807     }
1808     case GRAYColorspace:
1809     case Rec601LumaColorspace:
1810     case Rec709LumaColorspace:
1811     {
1812       jpeg_info.input_components=1;
1813       jpeg_info.in_color_space=JCS_GRAYSCALE;
1814       break;
1815     }
1816     default:
1817     {
1818       if (image->colorspace != RGBColorspace)
1819         (void) TransformImageColorspace(image,RGBColorspace);
1820       break;
1821     }
1822   }
1823   if ((image_info->type != TrueColorType) &&
1824       (IsGrayImage(image,&image->exception) != MagickFalse))
1825     {
1826       jpeg_info.input_components=1;
1827       jpeg_info.in_color_space=JCS_GRAYSCALE;
1828     }
1829   jpeg_set_defaults(&jpeg_info);
1830   if ((jpeg_info.data_precision != 12) && (image->depth <= 8))
1831     jpeg_info.data_precision=8;
1832   else
1833     if (sizeof(JSAMPLE) > 1)
1834       jpeg_info.data_precision=12;
1835   jpeg_info.density_unit=(UINT8) 1;
1836   if (image->debug != MagickFalse)
1837     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1838       "Image resolution: %.20g,%.20g",floor(image->x_resolution+0.5),
1839       floor(image->y_resolution+0.5));
1840   if ((image->x_resolution != 0.0) && (image->y_resolution != 0.0))
1841     {
1842       /*
1843         Set image resolution.
1844       */
1845       jpeg_info.write_JFIF_header=MagickTrue;
1846       jpeg_info.X_density=(UINT16) floor(image->x_resolution+0.5);
1847       jpeg_info.Y_density=(UINT16) floor(image->y_resolution+0.5);
1848       if (image->units == PixelsPerInchResolution)
1849         jpeg_info.density_unit=(UINT8) 1;
1850       if (image->units == PixelsPerCentimeterResolution)
1851         jpeg_info.density_unit=(UINT8) 2;
1852     }
1853   option=GetImageOption(image_info,"jpeg:dct-method");
1854   if (option != (const char *) NULL)
1855     switch (*option)
1856     {
1857       case 'D':
1858       case 'd':
1859       {
1860         if (LocaleCompare(option,"default") == 0)
1861           jpeg_info.dct_method=JDCT_DEFAULT;
1862         break;
1863       }
1864       case 'F':
1865       case 'f':
1866       {
1867         if (LocaleCompare(option,"fastest") == 0)
1868           jpeg_info.dct_method=JDCT_FASTEST;
1869         if (LocaleCompare(option,"float") == 0)
1870           jpeg_info.dct_method=JDCT_FLOAT;
1871         break;
1872       }
1873       case 'I':
1874       case 'i':
1875       {
1876         if (LocaleCompare(option,"ifast") == 0)
1877           jpeg_info.dct_method=JDCT_IFAST;
1878         if (LocaleCompare(option,"islow") == 0)
1879           jpeg_info.dct_method=JDCT_ISLOW;
1880         break;
1881       }
1882     }
1883   option=GetImageOption(image_info,"jpeg:optimize-coding");
1884   if (option != (const char *) NULL)
1885     {
1886       jpeg_info.optimize_coding=MagickFalse;
1887       if (IsMagickTrue(option) != MagickFalse)
1888         jpeg_info.optimize_coding=MagickTrue;
1889     }
1890   else
1891     {
1892       MagickSizeType
1893         length;
1894
1895       length=(MagickSizeType) jpeg_info.input_components*image->columns*
1896         image->rows*sizeof(JSAMPLE);
1897       if (length == (MagickSizeType) ((size_t) length))
1898         {
1899           /*
1900             Perform optimization only if available memory resources permit it.
1901           */
1902           status=AcquireMagickResource(MemoryResource,length);
1903           if (status != MagickFalse)
1904             jpeg_info.optimize_coding=MagickTrue;
1905           RelinquishMagickResource(MemoryResource,length);
1906         }
1907     }
1908 #if (JPEG_LIB_VERSION >= 61) && defined(C_PROGRESSIVE_SUPPORTED)
1909   if ((LocaleCompare(image_info->magick,"PJPEG") == 0) ||
1910       (image_info->interlace != NoInterlace))
1911     {
1912       if (image->debug != MagickFalse)
1913         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1914           "Interlace: progressive");
1915       jpeg_simple_progression(&jpeg_info);
1916     }
1917   else
1918     if (image->debug != MagickFalse)
1919       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1920         "Interlace: non-progressive");
1921 #else
1922   if (image->debug != MagickFalse)
1923     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1924       "Interlace: nonprogressive");
1925 #endif
1926   option=GetImageOption(image_info,"jpeg:extent");
1927   if (option != (const char *) NULL)
1928     {
1929       Image
1930         *jpeg_image;
1931
1932       ImageInfo
1933         *jpeg_info;
1934
1935       jpeg_info=CloneImageInfo(image_info);
1936       jpeg_image=CloneImage(image,0,0,MagickTrue,&image->exception);
1937       if (jpeg_image != (Image *) NULL)
1938         {
1939           MagickSizeType
1940             extent;
1941
1942           size_t
1943             maximum,
1944             minimum;
1945
1946           /*
1947             Search for compression quality that does not exceed image extent.
1948           */
1949           jpeg_info->quality=0;
1950           extent=(MagickSizeType) SiPrefixToDouble(option,100.0);
1951           (void) DeleteImageOption(jpeg_info,"jpeg:extent");
1952           (void) AcquireUniqueFilename(jpeg_image->filename);
1953           maximum=101;
1954           for (minimum=0; minimum != maximum; )
1955           {
1956             jpeg_image->quality=minimum+(maximum-minimum)/2;
1957             status=WriteJPEGImage(jpeg_info,jpeg_image);
1958             if (GetBlobSize(jpeg_image) <= extent)
1959               minimum=jpeg_image->quality+1;
1960             else
1961               maximum=jpeg_image->quality-1;
1962           }
1963           (void) RelinquishUniqueFileResource(jpeg_image->filename);
1964           image->quality=minimum-1;
1965           jpeg_image=DestroyImage(jpeg_image);
1966         }
1967       jpeg_info=DestroyImageInfo(jpeg_info);
1968     }
1969   if ((image_info->compression != LosslessJPEGCompression) &&
1970       (image->quality <= 100))
1971     {
1972       if (image->quality == UndefinedCompressionQuality)
1973         jpeg_set_quality(&jpeg_info,92,MagickTrue);
1974       else
1975         jpeg_set_quality(&jpeg_info,(int) image->quality,MagickTrue);
1976       if (image->debug != MagickFalse)
1977         (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Quality: %.20g",
1978           (double) image->quality);
1979     }
1980   else
1981     {
1982 #if !defined(C_LOSSLESS_SUPPORTED)
1983       jpeg_set_quality(&jpeg_info,100,MagickTrue);
1984       if (image->debug != MagickFalse)
1985         (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Quality: 100");
1986 #else
1987       if (image->quality < 100)
1988         (void) ThrowMagickException(&image->exception,GetMagickModule(),
1989           CoderWarning,"LosslessToLossyJPEGConversion",image->filename);
1990       else
1991         {
1992           int
1993             point_transform,
1994             predictor;
1995
1996           predictor=image->quality/100;  /* range 1-7 */
1997           point_transform=image->quality % 20;  /* range 0-15 */
1998           jpeg_simple_lossless(&jpeg_info,predictor,point_transform);
1999           if (image->debug != MagickFalse)
2000             {
2001               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2002                 "Compression: lossless");
2003               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2004                 "Predictor: %d",predictor);
2005               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2006                 "Point Transform: %d",point_transform);
2007             }
2008         }
2009 #endif
2010     }
2011   sampling_factor=(const char *) NULL;
2012   value=GetImageProperty(image,"jpeg:sampling-factor");
2013   if (value != (char *) NULL)
2014     {
2015       sampling_factor=value;
2016       if (image->debug != MagickFalse)
2017         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2018           "  Input sampling-factors=%s",sampling_factor);
2019     }
2020   if (image_info->sampling_factor != (char *) NULL)
2021     sampling_factor=image_info->sampling_factor;
2022   if (sampling_factor == (const char *) NULL)
2023     {
2024       if (image->quality >= 90)
2025         for (i=0; i < MAX_COMPONENTS; i++)
2026         {
2027           jpeg_info.comp_info[i].h_samp_factor=1;
2028           jpeg_info.comp_info[i].v_samp_factor=1;
2029         }
2030     }
2031   else
2032     {
2033       char
2034         **factors;
2035
2036       GeometryInfo
2037         geometry_info;
2038
2039       MagickStatusType
2040         flags;
2041
2042       /*
2043         Set sampling factor.
2044       */
2045       i=0;
2046       factors=SamplingFactorToList(sampling_factor);
2047       if (factors != (char **) NULL)
2048         {
2049           for (i=0; i < MAX_COMPONENTS; i++)
2050           {
2051             if (factors[i] == (char *) NULL)
2052               break;
2053             flags=ParseGeometry(factors[i],&geometry_info);
2054             if ((flags & SigmaValue) == 0)
2055               geometry_info.sigma=geometry_info.rho;
2056             jpeg_info.comp_info[i].h_samp_factor=(int) geometry_info.rho;
2057             jpeg_info.comp_info[i].v_samp_factor=(int) geometry_info.sigma;
2058             factors[i]=(char *) RelinquishMagickMemory(factors[i]);
2059           }
2060           factors=(char **) RelinquishMagickMemory(factors);
2061         }
2062       for ( ; i < MAX_COMPONENTS; i++)
2063       {
2064         jpeg_info.comp_info[i].h_samp_factor=1;
2065         jpeg_info.comp_info[i].v_samp_factor=1;
2066       }
2067     }
2068   if (jpeg_info.input_components == 1)
2069     for (i=0; i < MAX_COMPONENTS; i++)
2070     {
2071       jpeg_info.comp_info[i].h_samp_factor=1;
2072       jpeg_info.comp_info[i].v_samp_factor=1;
2073     }
2074   jpeg_start_compress(&jpeg_info,MagickTrue);
2075   if (image->debug != MagickFalse)
2076     {
2077       if (image->storage_class == PseudoClass)
2078         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2079           "Storage class: PseudoClass");
2080       else
2081         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2082           "Storage class: DirectClass");
2083       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Depth: %.20g",
2084         (double) image->depth);
2085       if (image->colors != 0)
2086         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2087           "Number of colors: %.20g",(double) image->colors);
2088       else
2089         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2090           "Number of colors: unspecified");
2091       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2092         "JPEG data precision: %d",(int) jpeg_info.data_precision);
2093       switch (image->colorspace)
2094       {
2095         case CMYKColorspace:
2096         {
2097           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2098             "Storage class: DirectClass");
2099           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2100             "Colorspace: CMYK");
2101           break;
2102         }
2103         case YCbCrColorspace:
2104         case Rec601YCbCrColorspace:
2105         case Rec709YCbCrColorspace:
2106         {
2107           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2108             "Colorspace: YCbCr");
2109           break;
2110         }
2111         default:
2112           break;
2113       }
2114       switch (image->colorspace)
2115       {
2116         case CMYKColorspace:
2117         {
2118           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2119             "Colorspace: CMYK");
2120           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2121             "Sampling factors: %dx%d,%dx%d,%dx%d,%dx%d",
2122             jpeg_info.comp_info[0].h_samp_factor,
2123             jpeg_info.comp_info[0].v_samp_factor,
2124             jpeg_info.comp_info[1].h_samp_factor,
2125             jpeg_info.comp_info[1].v_samp_factor,
2126             jpeg_info.comp_info[2].h_samp_factor,
2127             jpeg_info.comp_info[2].v_samp_factor,
2128             jpeg_info.comp_info[3].h_samp_factor,
2129             jpeg_info.comp_info[3].v_samp_factor);
2130           break;
2131         }
2132         case GRAYColorspace:
2133         case Rec601LumaColorspace:
2134         case Rec709LumaColorspace:
2135         {
2136           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2137             "Colorspace: GRAY");
2138           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2139             "Sampling factors: %dx%d",jpeg_info.comp_info[0].h_samp_factor,
2140             jpeg_info.comp_info[0].v_samp_factor);
2141           break;
2142         }
2143         case RGBColorspace:
2144         {
2145           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2146             "Image colorspace is RGB");
2147           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2148             "Sampling factors: %dx%d,%dx%d,%dx%d",
2149             jpeg_info.comp_info[0].h_samp_factor,
2150             jpeg_info.comp_info[0].v_samp_factor,
2151             jpeg_info.comp_info[1].h_samp_factor,
2152             jpeg_info.comp_info[1].v_samp_factor,
2153             jpeg_info.comp_info[2].h_samp_factor,
2154             jpeg_info.comp_info[2].v_samp_factor);
2155           break;
2156         }
2157         case YCbCrColorspace:
2158         case Rec601YCbCrColorspace:
2159         case Rec709YCbCrColorspace:
2160         {
2161           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2162             "Colorspace: YCbCr");
2163           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2164             "Sampling factors: %dx%d,%dx%d,%dx%d",
2165             jpeg_info.comp_info[0].h_samp_factor,
2166             jpeg_info.comp_info[0].v_samp_factor,
2167             jpeg_info.comp_info[1].h_samp_factor,
2168             jpeg_info.comp_info[1].v_samp_factor,
2169             jpeg_info.comp_info[2].h_samp_factor,
2170             jpeg_info.comp_info[2].v_samp_factor);
2171           break;
2172         }
2173         default:
2174         {
2175           (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Colorspace: %d",
2176             image->colorspace);
2177           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2178             "Sampling factors: %dx%d,%dx%d,%dx%d,%dx%d",
2179             jpeg_info.comp_info[0].h_samp_factor,
2180             jpeg_info.comp_info[0].v_samp_factor,
2181             jpeg_info.comp_info[1].h_samp_factor,
2182             jpeg_info.comp_info[1].v_samp_factor,
2183             jpeg_info.comp_info[2].h_samp_factor,
2184             jpeg_info.comp_info[2].v_samp_factor,
2185             jpeg_info.comp_info[3].h_samp_factor,
2186             jpeg_info.comp_info[3].v_samp_factor);
2187           break;
2188         }
2189       }
2190     }
2191   /*
2192     Write JPEG profiles.
2193   */
2194   value=GetImageProperty(image,"comment");
2195   if (value != (char *) NULL)
2196     for (i=0; i < (ssize_t) strlen(value); i+=65533L)
2197       jpeg_write_marker(&jpeg_info,JPEG_COM,(unsigned char *) value+i,
2198         (unsigned int) MagickMin((size_t) strlen(value+i),65533L));
2199   if (image->profiles != (void *) NULL)
2200     WriteProfile(&jpeg_info,image);
2201   /*
2202     Convert MIFF to JPEG raster pixels.
2203   */
2204   jpeg_pixels=(JSAMPLE *) AcquireQuantumMemory((size_t) image->columns,
2205     jpeg_info.input_components*sizeof(*jpeg_pixels));
2206   if (jpeg_pixels == (JSAMPLE *) NULL)
2207     ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2208   if (setjmp(error_manager.error_recovery) != 0)
2209     {
2210       jpeg_destroy_compress(&jpeg_info);
2211       if (jpeg_pixels != (unsigned char *) NULL)
2212         jpeg_pixels=(unsigned char *) RelinquishMagickMemory(jpeg_pixels);
2213       (void) CloseBlob(image);
2214       return(MagickFalse);
2215     }
2216   scanline[0]=(JSAMPROW) jpeg_pixels;
2217   if (jpeg_info.data_precision <= 8)
2218     {
2219       if ((jpeg_info.in_color_space == JCS_RGB) ||
2220           (jpeg_info.in_color_space == JCS_YCbCr))
2221         for (y=0; y < (ssize_t) image->rows; y++)
2222         {
2223           register const PixelPacket
2224             *p;
2225
2226           register ssize_t
2227             x;
2228
2229           p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2230           if (p == (const PixelPacket *) NULL)
2231             break;
2232           q=jpeg_pixels;
2233           for (x=0; x < (ssize_t) image->columns; x++)
2234           {
2235             *q++=(JSAMPLE) ScaleQuantumToChar(GetRedPixelComponent(p));
2236             *q++=(JSAMPLE) ScaleQuantumToChar(GetGreenPixelComponent(p));
2237             *q++=(JSAMPLE) ScaleQuantumToChar(GetBluePixelComponent(p));
2238             p++;
2239           }
2240           (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2241           status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2242             image->rows);
2243           if (status == MagickFalse)
2244             break;
2245         }
2246       else
2247         if (jpeg_info.in_color_space == JCS_GRAYSCALE)
2248           for (y=0; y < (ssize_t) image->rows; y++)
2249           {
2250             register const PixelPacket
2251               *p;
2252
2253             register ssize_t
2254               x;
2255
2256             p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2257             if (p == (const PixelPacket *) NULL)
2258               break;
2259             q=jpeg_pixels;
2260             for (x=0; x < (ssize_t) image->columns; x++)
2261             {
2262               *q++=(JSAMPLE) ScaleQuantumToChar(PixelIntensityToQuantum(p));
2263               p++;
2264             }
2265             (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2266             status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2267               image->rows);
2268             if (status == MagickFalse)
2269               break;
2270           }
2271         else
2272           for (y=0; y < (ssize_t) image->rows; y++)
2273           {
2274             register const IndexPacket
2275               *indexes;
2276
2277             register const PixelPacket
2278               *p;
2279
2280             register ssize_t
2281               x;
2282
2283             p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2284             if (p == (const PixelPacket *) NULL)
2285               break;
2286             q=jpeg_pixels;
2287             indexes=GetVirtualIndexQueue(image);
2288             for (x=0; x < (ssize_t) image->columns; x++)
2289             {
2290               /*
2291                 Convert DirectClass packets to contiguous CMYK scanlines.
2292               */
2293               *q++=(JSAMPLE) (ScaleQuantumToChar((Quantum) (QuantumRange-
2294                 GetRedPixelComponent(p))));
2295               *q++=(JSAMPLE) (ScaleQuantumToChar((Quantum) (QuantumRange-
2296                 GetGreenPixelComponent(p))));
2297               *q++=(JSAMPLE) (ScaleQuantumToChar((Quantum) (QuantumRange-
2298                 GetBluePixelComponent(p))));
2299               *q++=(JSAMPLE) (ScaleQuantumToChar((Quantum) (QuantumRange-
2300                 GetIndexPixelComponent(indexes+x))));
2301               p++;
2302             }
2303             (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2304             status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2305               image->rows);
2306             if (status == MagickFalse)
2307               break;
2308           }
2309     }
2310   else
2311     if (jpeg_info.in_color_space == JCS_GRAYSCALE)
2312       for (y=0; y < (ssize_t) image->rows; y++)
2313       {
2314         register const PixelPacket
2315           *p;
2316
2317         register ssize_t
2318           x;
2319
2320         p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2321         if (p == (const PixelPacket *) NULL)
2322           break;
2323         q=jpeg_pixels;
2324         for (x=0; x < (ssize_t) image->columns; x++)
2325         {
2326           *q++=(JSAMPLE) (ScaleQuantumToShort(PixelIntensityToQuantum(p)) >>
2327             4);
2328           p++;
2329         }
2330         (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2331         status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2332           image->rows);
2333         if (status == MagickFalse)
2334           break;
2335       }
2336     else
2337       if ((jpeg_info.in_color_space == JCS_RGB) ||
2338           (jpeg_info.in_color_space == JCS_YCbCr))
2339         for (y=0; y < (ssize_t) image->rows; y++)
2340         {
2341           register const PixelPacket
2342             *p;
2343
2344           register ssize_t
2345             x;
2346
2347           p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2348           if (p == (const PixelPacket *) NULL)
2349             break;
2350           q=jpeg_pixels;
2351           for (x=0; x < (ssize_t) image->columns; x++)
2352           {
2353             *q++=(JSAMPLE) (ScaleQuantumToShort(GetRedPixelComponent(p)) >>
2354               4);
2355             *q++=(JSAMPLE) (ScaleQuantumToShort(GetGreenPixelComponent(p)) >>
2356               4);
2357             *q++=(JSAMPLE) (ScaleQuantumToShort(GetBluePixelComponent(p)) >>
2358               4);
2359             p++;
2360           }
2361           (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2362           status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2363             image->rows);
2364           if (status == MagickFalse)
2365             break;
2366         }
2367       else
2368         for (y=0; y < (ssize_t) image->rows; y++)
2369         {
2370           register const IndexPacket
2371             *indexes;
2372
2373           register const PixelPacket
2374             *p;
2375
2376           register ssize_t
2377             x;
2378
2379           p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2380           if (p == (const PixelPacket *) NULL)
2381             break;
2382           q=jpeg_pixels;
2383           indexes=GetVirtualIndexQueue(image);
2384           for (x=0; x < (ssize_t) image->columns; x++)
2385           {
2386             /*
2387               Convert DirectClass packets to contiguous CMYK scanlines.
2388             */
2389             *q++=(JSAMPLE) (4095-(ScaleQuantumToShort(
2390               GetRedPixelComponent(p)) >> 4));
2391             *q++=(JSAMPLE) (4095-(ScaleQuantumToShort(
2392               GetGreenPixelComponent(p)) >> 4));
2393             *q++=(JSAMPLE) (4095-(ScaleQuantumToShort(
2394               GetBluePixelComponent(p)) >> 4));
2395             *q++=(JSAMPLE) (4095-(ScaleQuantumToShort(
2396               GetIndexPixelComponent(indexes+x)) >> 4));
2397             p++;
2398           }
2399           (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2400           status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2401             image->rows);
2402           if (status == MagickFalse)
2403             break;
2404         }
2405   if (y == (ssize_t) image->rows)
2406     jpeg_finish_compress(&jpeg_info);
2407   /*
2408     Relinquish resources.
2409   */
2410   jpeg_destroy_compress(&jpeg_info);
2411   jpeg_pixels=(unsigned char *) RelinquishMagickMemory(jpeg_pixels);
2412   (void) CloseBlob(image);
2413   return(MagickTrue);
2414 }
2415 #endif