]> 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) 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   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) 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].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             SetRGBOPixelComponent(q,image->colormap+index);
1253             p++;
1254             q++;
1255           }
1256         else
1257           if (image->colorspace != CMYKColorspace)
1258             for (x=0; x < (ssize_t) image->columns; x++)
1259             {
1260               SetRedPixelComponent(q,ScaleShortToQuantum((unsigned char)
1261                 (GETJSAMPLE(*p++) << 4)));
1262               SetGreenPixelComponent(q,ScaleShortToQuantum((unsigned char)
1263                 (GETJSAMPLE(*p++) << 4)));
1264               SetBluePixelComponent(q,ScaleShortToQuantum((unsigned char)
1265                 (GETJSAMPLE(*p++) << 4)));
1266               SetOpacityPixelComponent(q,OpaqueOpacity);
1267               q++;
1268             }
1269           else
1270             for (x=0; x < (ssize_t) image->columns; x++)
1271             {
1272               SetCyanPixelComponent(q,QuantumRange-ScaleShortToQuantum(
1273                 (unsigned char) (GETJSAMPLE(*p++) << 4)));
1274               SetMagentaPixelComponent(q,QuantumRange-ScaleShortToQuantum(
1275                 (unsigned char) (GETJSAMPLE(*p++) << 4)));
1276               SetYellowPixelComponent(q,QuantumRange-ScaleShortToQuantum(
1277                 (unsigned char) (GETJSAMPLE(*p++) << 4)));
1278               SetBlackPixelComponent(indexes+x,QuantumRange-ScaleShortToQuantum(
1279                 (unsigned char) (GETJSAMPLE(*p++) << 4)));
1280               SetOpacityPixelComponent(q,OpaqueOpacity);
1281               q++;
1282             }
1283       }
1284     else
1285       if (jpeg_info.output_components == 1)
1286         for (x=0; x < (ssize_t) image->columns; x++)
1287         {
1288           index=ConstrainColormapIndex(image,(size_t) GETJSAMPLE(*p));
1289           SetIndexPixelComponent(indexes+x,index);
1290           SetRGBOPixelComponent(q,image->colormap+index);
1291           p++;
1292           q++;
1293         }
1294       else
1295         if (image->colorspace != CMYKColorspace)
1296           for (x=0; x < (ssize_t) image->columns; x++)
1297           {
1298             SetRedPixelComponent(q,ScaleCharToQuantum((unsigned char)
1299               GETJSAMPLE(*p++)));
1300             SetGreenPixelComponent(q,ScaleCharToQuantum((unsigned char)
1301               GETJSAMPLE(*p++)));
1302             SetBluePixelComponent(q,ScaleCharToQuantum((unsigned char)
1303               GETJSAMPLE(*p++)));
1304             SetOpacityPixelComponent(q,OpaqueOpacity);
1305             q++;
1306           }
1307         else
1308           for (x=0; x < (ssize_t) image->columns; x++)
1309           {
1310             SetCyanPixelComponent(q,QuantumRange-ScaleCharToQuantum(
1311               (unsigned char) GETJSAMPLE(*p++)));
1312             SetMagentaPixelComponent(q,QuantumRange-ScaleCharToQuantum(
1313               (unsigned char) GETJSAMPLE(*p++)));
1314             SetYellowPixelComponent(q,QuantumRange-ScaleCharToQuantum(
1315               (unsigned char) GETJSAMPLE(*p++)));
1316             SetBlackPixelComponent(indexes+x,QuantumRange-ScaleCharToQuantum(
1317               (unsigned char) GETJSAMPLE(*p++)));
1318             SetOpacityPixelComponent(q,OpaqueOpacity);
1319             q++;
1320           }
1321     if (SyncAuthenticPixels(image,exception) == MagickFalse)
1322       break;
1323     status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
1324       image->rows);
1325     if (status == MagickFalse)
1326       {
1327         jpeg_abort_decompress(&jpeg_info);
1328         break;
1329       }
1330   }
1331   if (status != MagickFalse)
1332     {
1333       error_manager.finished=MagickTrue;
1334       if (setjmp(error_manager.error_recovery) == 0)
1335         (void) jpeg_finish_decompress(&jpeg_info);
1336     }
1337   /*
1338     Free jpeg resources.
1339   */
1340   jpeg_destroy_decompress(&jpeg_info);
1341   jpeg_pixels=(unsigned char *) RelinquishMagickMemory(jpeg_pixels);
1342   (void) CloseBlob(image);
1343   return(GetFirstImageInList(image));
1344 }
1345 #endif
1346 \f
1347 /*
1348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1349 %                                                                             %
1350 %                                                                             %
1351 %                                                                             %
1352 %   R e g i s t e r J P E G I m a g e                                         %
1353 %                                                                             %
1354 %                                                                             %
1355 %                                                                             %
1356 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1357 %
1358 %  RegisterJPEGImage() adds properties for the JPEG image format to
1359 %  the list of supported formats.  The properties include the image format
1360 %  tag, a method to read and/or write the format, whether the format
1361 %  supports the saving of more than one frame to the same file or blob,
1362 %  whether the format supports native in-memory I/O, and a brief
1363 %  description of the format.
1364 %
1365 %  The format of the RegisterJPEGImage method is:
1366 %
1367 %      size_t RegisterJPEGImage(void)
1368 %
1369 */
1370 ModuleExport size_t RegisterJPEGImage(void)
1371 {
1372   char
1373     version[MaxTextExtent];
1374
1375   MagickInfo
1376     *entry;
1377
1378   static const char
1379     description[] = "Joint Photographic Experts Group JFIF format";
1380
1381   *version='\0';
1382 #if defined(JPEG_LIB_VERSION)
1383   (void) FormatLocaleString(version,MaxTextExtent,"%d",JPEG_LIB_VERSION);
1384 #endif
1385   entry=SetMagickInfo("JPEG");
1386   entry->thread_support=NoThreadSupport;
1387 #if defined(MAGICKCORE_JPEG_DELEGATE)
1388   entry->decoder=(DecodeImageHandler *) ReadJPEGImage;
1389   entry->encoder=(EncodeImageHandler *) WriteJPEGImage;
1390 #endif
1391   entry->magick=(IsImageFormatHandler *) IsJPEG;
1392   entry->adjoin=MagickFalse;
1393   entry->description=ConstantString(description);
1394   if (*version != '\0')
1395     entry->version=ConstantString(version);
1396   entry->module=ConstantString("JPEG");
1397   (void) RegisterMagickInfo(entry);
1398   entry=SetMagickInfo("JPG");
1399   entry->thread_support=NoThreadSupport;
1400 #if defined(MAGICKCORE_JPEG_DELEGATE)
1401   entry->decoder=(DecodeImageHandler *) ReadJPEGImage;
1402   entry->encoder=(EncodeImageHandler *) WriteJPEGImage;
1403 #endif
1404   entry->adjoin=MagickFalse;
1405   entry->description=ConstantString(description);
1406   if (*version != '\0')
1407     entry->version=ConstantString(version);
1408   entry->module=ConstantString("JPEG");
1409   (void) RegisterMagickInfo(entry);
1410   entry=SetMagickInfo("PJPEG");
1411   entry->thread_support=NoThreadSupport;
1412 #if defined(MAGICKCORE_JPEG_DELEGATE)
1413   entry->decoder=(DecodeImageHandler *) ReadJPEGImage;
1414   entry->encoder=(EncodeImageHandler *) WriteJPEGImage;
1415 #endif
1416   entry->adjoin=MagickFalse;
1417   entry->description=ConstantString(description);
1418   if (*version != '\0')
1419     entry->version=ConstantString(version);
1420   entry->module=ConstantString("JPEG");
1421   (void) RegisterMagickInfo(entry);
1422   return(MagickImageCoderSignature);
1423 }
1424 \f
1425 /*
1426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1427 %                                                                             %
1428 %                                                                             %
1429 %                                                                             %
1430 %   U n r e g i s t e r J P E G I m a g e                                     %
1431 %                                                                             %
1432 %                                                                             %
1433 %                                                                             %
1434 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1435 %
1436 %  UnregisterJPEGImage() removes format registrations made by the
1437 %  JPEG module from the list of supported formats.
1438 %
1439 %  The format of the UnregisterJPEGImage method is:
1440 %
1441 %      UnregisterJPEGImage(void)
1442 %
1443 */
1444 ModuleExport void UnregisterJPEGImage(void)
1445 {
1446   (void) UnregisterMagickInfo("PJPG");
1447   (void) UnregisterMagickInfo("JPEG");
1448   (void) UnregisterMagickInfo("JPG");
1449 }
1450 \f
1451 #if defined(MAGICKCORE_JPEG_DELEGATE)
1452 /*
1453 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1454 %                                                                             %
1455 %                                                                             %
1456 %                                                                             %
1457 %  W r i t e J P E G I m a g e                                                %
1458 %                                                                             %
1459 %                                                                             %
1460 %                                                                             %
1461 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1462 %
1463 %  WriteJPEGImage() writes a JPEG image file and returns it.  It
1464 %  allocates the memory necessary for the new Image structure and returns a
1465 %  pointer to the new image.
1466 %
1467 %  The format of the WriteJPEGImage method is:
1468 %
1469 %      MagickBooleanType WriteJPEGImage(const ImageInfo *image_info,
1470 %        Image *image)
1471 %
1472 %  A description of each parameter follows:
1473 %
1474 %    o image_info: the image info.
1475 %
1476 %    o jpeg_image:  The image.
1477 %
1478 %
1479 */
1480
1481 static boolean EmptyOutputBuffer(j_compress_ptr cinfo)
1482 {
1483   DestinationManager
1484     *destination;
1485
1486   destination=(DestinationManager *) cinfo->dest;
1487   destination->manager.free_in_buffer=(size_t) WriteBlob(destination->image,
1488     MaxBufferExtent,destination->buffer);
1489   if (destination->manager.free_in_buffer != MaxBufferExtent)
1490     ERREXIT(cinfo,JERR_FILE_WRITE);
1491   destination->manager.next_output_byte=destination->buffer;
1492   return(TRUE);
1493 }
1494
1495 static void InitializeDestination(j_compress_ptr cinfo)
1496 {
1497   DestinationManager
1498     *destination;
1499
1500   destination=(DestinationManager *) cinfo->dest;
1501   destination->buffer=(JOCTET *) (*cinfo->mem->alloc_small)
1502     ((j_common_ptr) cinfo,JPOOL_IMAGE,MaxBufferExtent*sizeof(JOCTET));
1503   destination->manager.next_output_byte=destination->buffer;
1504   destination->manager.free_in_buffer=MaxBufferExtent;
1505 }
1506
1507 static inline size_t MagickMin(const size_t x,const size_t y)
1508 {
1509   if (x < y)
1510     return(x);
1511   return(y);
1512 }
1513
1514 static void TerminateDestination(j_compress_ptr cinfo)
1515 {
1516   DestinationManager
1517     *destination;
1518
1519   destination=(DestinationManager *) cinfo->dest;
1520   if ((MaxBufferExtent-(int) destination->manager.free_in_buffer) > 0)
1521     {
1522       ssize_t
1523         count;
1524
1525       count=WriteBlob(destination->image,MaxBufferExtent-
1526         destination->manager.free_in_buffer,destination->buffer);
1527       if (count != (ssize_t)
1528           (MaxBufferExtent-destination->manager.free_in_buffer))
1529         ERREXIT(cinfo,JERR_FILE_WRITE);
1530     }
1531 }
1532
1533 static void WriteProfile(j_compress_ptr jpeg_info,Image *image)
1534 {
1535   const char
1536     *name;
1537
1538   const StringInfo
1539     *profile;
1540
1541   MagickBooleanType
1542     iptc;
1543
1544   register ssize_t
1545     i;
1546
1547   size_t
1548     length,
1549     tag_length;
1550
1551   StringInfo
1552     *custom_profile;
1553
1554   /*
1555     Save image profile as a APP marker.
1556   */
1557   iptc=MagickFalse;
1558   custom_profile=AcquireStringInfo(65535L);
1559   ResetImageProfileIterator(image);
1560   for (name=GetNextImageProfile(image); name != (const char *) NULL; )
1561   {
1562     register unsigned char
1563       *p;
1564
1565     profile=GetImageProfile(image,name);
1566     p=GetStringInfoDatum(custom_profile);
1567     if (LocaleCompare(name,"EXIF") == 0)
1568       for (i=0; i < (ssize_t) GetStringInfoLength(profile); i+=65533L)
1569       {
1570         length=MagickMin(GetStringInfoLength(profile)-i,65533L);
1571         jpeg_write_marker(jpeg_info,XML_MARKER,GetStringInfoDatum(profile)+i,
1572           (unsigned int) length);
1573       }
1574     if (LocaleCompare(name,"ICC") == 0)
1575       {
1576         register unsigned char
1577           *p;
1578
1579         tag_length=14;
1580         p=GetStringInfoDatum(custom_profile);
1581         (void) CopyMagickMemory(p,ICC_PROFILE,tag_length);
1582         for (i=0; i < (ssize_t) GetStringInfoLength(profile); i+=65519L)
1583         {
1584           length=MagickMin(GetStringInfoLength(profile)-i,65519L);
1585           p[12]=(unsigned char) ((i/65519L)+1);
1586           p[13]=(unsigned char) (GetStringInfoLength(profile)/65519L+1);
1587           (void) CopyMagickMemory(p+tag_length,GetStringInfoDatum(profile)+i,
1588             length);
1589           jpeg_write_marker(jpeg_info,ICC_MARKER,GetStringInfoDatum(
1590             custom_profile),(unsigned int) (length+tag_length));
1591         }
1592       }
1593     if (((LocaleCompare(name,"IPTC") == 0) ||
1594         (LocaleCompare(name,"8BIM") == 0)) && (iptc == MagickFalse))
1595       {
1596         size_t
1597           roundup;
1598
1599         iptc=MagickTrue;
1600         for (i=0; i < (ssize_t) GetStringInfoLength(profile); i+=65500L)
1601         {
1602           length=MagickMin(GetStringInfoLength(profile)-i,65500L);
1603           roundup=(size_t) (length & 0x01);
1604           if (LocaleNCompare((char *) GetStringInfoDatum(profile),"8BIM",4) == 0)
1605             {
1606               (void) memcpy(p,"Photoshop 3.0 ",14);
1607               tag_length=14;
1608             }
1609           else
1610             {
1611               (void) CopyMagickMemory(p,"Photoshop 3.0 8BIM\04\04\0\0\0\0",24);
1612               tag_length=26;
1613               p[24]=(unsigned char) (length >> 8);
1614               p[25]=(unsigned char) (length & 0xff);
1615             }
1616           p[13]=0x00;
1617           (void) memcpy(p+tag_length,GetStringInfoDatum(profile)+i,length);
1618           if (roundup != 0)
1619             p[length+tag_length]='\0';
1620           jpeg_write_marker(jpeg_info,IPTC_MARKER,GetStringInfoDatum(
1621             custom_profile),(unsigned int) (length+tag_length+roundup));
1622         }
1623       }
1624     if (LocaleCompare(name,"XMP") == 0)
1625       {
1626         StringInfo
1627           *xmp_profile;
1628
1629         /*
1630           Add namespace to XMP profile.
1631         */
1632         xmp_profile=StringToStringInfo("http://ns.adobe.com/xap/1.0/");
1633         ConcatenateStringInfo(xmp_profile,profile);
1634         GetStringInfoDatum(xmp_profile)[28]='\0';
1635         for (i=0; i < (ssize_t) GetStringInfoLength(xmp_profile); i+=65533L)
1636         {
1637           length=MagickMin(GetStringInfoLength(xmp_profile)-i,65533L);
1638           jpeg_write_marker(jpeg_info,XML_MARKER,
1639             GetStringInfoDatum(xmp_profile)+i,(unsigned int) length);
1640         }
1641         xmp_profile=DestroyStringInfo(xmp_profile);
1642       }
1643     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1644       "%s profile: %.20g bytes",name,(double) GetStringInfoLength(profile));
1645     name=GetNextImageProfile(image);
1646   }
1647   custom_profile=DestroyStringInfo(custom_profile);
1648 }
1649
1650 static void JPEGDestinationManager(j_compress_ptr cinfo,Image * image)
1651 {
1652   DestinationManager
1653     *destination;
1654
1655   cinfo->dest=(struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small)
1656     ((j_common_ptr) cinfo,JPOOL_IMAGE,sizeof(DestinationManager));
1657   destination=(DestinationManager *) cinfo->dest;
1658   destination->manager.init_destination=InitializeDestination;
1659   destination->manager.empty_output_buffer=EmptyOutputBuffer;
1660   destination->manager.term_destination=TerminateDestination;
1661   destination->image=image;
1662 }
1663
1664 static char **SamplingFactorToList(const char *text)
1665 {
1666   char
1667     **textlist;
1668
1669   register char
1670     *q;
1671
1672   register const char
1673     *p;
1674
1675   register ssize_t
1676     i;
1677
1678   size_t
1679     lines;
1680
1681   if (text == (char *) NULL)
1682     return((char **) NULL);
1683   /*
1684     Convert string to an ASCII list.
1685   */
1686   lines=1;
1687   for (p=text; *p != '\0'; p++)
1688     if (*p == ',')
1689       lines++;
1690   textlist=(char **) AcquireQuantumMemory((size_t) lines+MaxTextExtent,
1691     sizeof(*textlist));
1692   if (textlist == (char **) NULL)
1693     ThrowFatalException(ResourceLimitFatalError,"UnableToConvertText");
1694   p=text;
1695   for (i=0; i < (ssize_t) lines; i++)
1696   {
1697     for (q=(char *) p; *q != '\0'; q++)
1698       if (*q == ',')
1699         break;
1700     textlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent,
1701       sizeof(*textlist[i]));
1702     if (textlist[i] == (char *) NULL)
1703       ThrowFatalException(ResourceLimitFatalError,"UnableToConvertText");
1704     (void) CopyMagickString(textlist[i],p,(size_t) (q-p+1));
1705     if (*q == '\r')
1706       q++;
1707     p=q+1;
1708   }
1709   textlist[i]=(char *) NULL;
1710   return(textlist);
1711 }
1712
1713 static MagickBooleanType WriteJPEGImage(const ImageInfo *image_info,
1714   Image *image)
1715 {
1716   const char
1717     *option,
1718     *sampling_factor,
1719     *value;
1720
1721   ErrorManager
1722     error_manager;
1723
1724   JSAMPLE
1725     *jpeg_pixels;
1726
1727   JSAMPROW
1728     scanline[1];
1729
1730   MagickBooleanType
1731     status;
1732
1733   register JSAMPLE
1734     *q;
1735
1736   register ssize_t
1737     i;
1738
1739   ssize_t
1740     y;
1741
1742   struct jpeg_compress_struct
1743     jpeg_info;
1744
1745   struct jpeg_error_mgr
1746     jpeg_error;
1747
1748   /*
1749     Open image file.
1750   */
1751   assert(image_info != (const ImageInfo *) NULL);
1752   assert(image_info->signature == MagickSignature);
1753   assert(image != (Image *) NULL);
1754   assert(image->signature == MagickSignature);
1755   if (image->debug != MagickFalse)
1756     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1757   status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1758   if (status == MagickFalse)
1759     return(status);
1760   /*
1761     Initialize JPEG parameters.
1762   */
1763   (void) ResetMagickMemory(&error_manager,0,sizeof(error_manager));
1764   (void) ResetMagickMemory(&jpeg_info,0,sizeof(jpeg_info));
1765   (void) ResetMagickMemory(&jpeg_error,0,sizeof(jpeg_error));
1766   jpeg_info.client_data=(void *) image;
1767   jpeg_info.err=jpeg_std_error(&jpeg_error);
1768   jpeg_info.err->emit_message=(void (*)(j_common_ptr,int)) JPEGWarningHandler;
1769   jpeg_info.err->error_exit=(void (*)(j_common_ptr)) JPEGErrorHandler;
1770   error_manager.image=image;
1771   jpeg_pixels=(JSAMPLE *) NULL;
1772   if (setjmp(error_manager.error_recovery) != 0)
1773     {
1774       jpeg_destroy_compress(&jpeg_info);
1775       (void) CloseBlob(image);
1776       return(MagickFalse);
1777     }
1778   jpeg_info.client_data=(void *) &error_manager;
1779   jpeg_create_compress(&jpeg_info);
1780   JPEGDestinationManager(&jpeg_info,image);
1781   if ((image->columns != (unsigned int) image->columns) ||
1782       (image->rows != (unsigned int) image->rows))
1783     ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
1784   jpeg_info.image_width=(unsigned int) image->columns;
1785   jpeg_info.image_height=(unsigned int) image->rows;
1786   jpeg_info.input_components=3;
1787   jpeg_info.data_precision=8;
1788   jpeg_info.in_color_space=JCS_RGB;
1789   switch (image->colorspace)
1790   {
1791     case CMYKColorspace:
1792     {
1793       jpeg_info.input_components=4;
1794       jpeg_info.in_color_space=JCS_CMYK;
1795       break;
1796     }
1797     case YCbCrColorspace:
1798     case Rec601YCbCrColorspace:
1799     case Rec709YCbCrColorspace:
1800     {
1801       jpeg_info.in_color_space=JCS_YCbCr;
1802       break;
1803     }
1804     case GRAYColorspace:
1805     case Rec601LumaColorspace:
1806     case Rec709LumaColorspace:
1807     {
1808       jpeg_info.input_components=1;
1809       jpeg_info.in_color_space=JCS_GRAYSCALE;
1810       break;
1811     }
1812     default:
1813     {
1814       if (image->colorspace != RGBColorspace)
1815         (void) TransformImageColorspace(image,RGBColorspace);
1816       break;
1817     }
1818   }
1819   if ((image_info->type != TrueColorType) &&
1820       (IsGrayImage(image,&image->exception) != MagickFalse))
1821     {
1822       jpeg_info.input_components=1;
1823       jpeg_info.in_color_space=JCS_GRAYSCALE;
1824     }
1825   jpeg_set_defaults(&jpeg_info);
1826   if ((jpeg_info.data_precision != 12) && (image->depth <= 8))
1827     jpeg_info.data_precision=8;
1828   else
1829     if (sizeof(JSAMPLE) > 1)
1830       jpeg_info.data_precision=12;
1831   jpeg_info.density_unit=(UINT8) 1;
1832   if (image->debug != MagickFalse)
1833     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1834       "Image resolution: %.20g,%.20g",floor(image->x_resolution+0.5),
1835       floor(image->y_resolution+0.5));
1836   if ((image->x_resolution != 0.0) && (image->y_resolution != 0.0))
1837     {
1838       /*
1839         Set image resolution.
1840       */
1841       jpeg_info.write_JFIF_header=MagickTrue;
1842       jpeg_info.X_density=(UINT16) floor(image->x_resolution+0.5);
1843       jpeg_info.Y_density=(UINT16) floor(image->y_resolution+0.5);
1844       if (image->units == PixelsPerInchResolution)
1845         jpeg_info.density_unit=(UINT8) 1;
1846       if (image->units == PixelsPerCentimeterResolution)
1847         jpeg_info.density_unit=(UINT8) 2;
1848     }
1849   option=GetImageOption(image_info,"jpeg:dct-method");
1850   if (option != (const char *) NULL)
1851     switch (*option)
1852     {
1853       case 'D':
1854       case 'd':
1855       {
1856         if (LocaleCompare(option,"default") == 0)
1857           jpeg_info.dct_method=JDCT_DEFAULT;
1858         break;
1859       }
1860       case 'F':
1861       case 'f':
1862       {
1863         if (LocaleCompare(option,"fastest") == 0)
1864           jpeg_info.dct_method=JDCT_FASTEST;
1865         if (LocaleCompare(option,"float") == 0)
1866           jpeg_info.dct_method=JDCT_FLOAT;
1867         break;
1868       }
1869       case 'I':
1870       case 'i':
1871       {
1872         if (LocaleCompare(option,"ifast") == 0)
1873           jpeg_info.dct_method=JDCT_IFAST;
1874         if (LocaleCompare(option,"islow") == 0)
1875           jpeg_info.dct_method=JDCT_ISLOW;
1876         break;
1877       }
1878     }
1879   option=GetImageOption(image_info,"jpeg:optimize-coding");
1880   if (option != (const char *) NULL)
1881     {
1882       jpeg_info.optimize_coding=MagickFalse;
1883       if (IsMagickTrue(option) != MagickFalse)
1884         jpeg_info.optimize_coding=MagickTrue;
1885     }
1886   else
1887     {
1888       MagickSizeType
1889         length;
1890
1891       length=(MagickSizeType) jpeg_info.input_components*image->columns*
1892         image->rows*sizeof(JSAMPLE);
1893       if (length == (MagickSizeType) ((size_t) length))
1894         {
1895           /*
1896             Perform optimization only if available memory resources permit it.
1897           */
1898           status=AcquireMagickResource(MemoryResource,length);
1899           if (status != MagickFalse)
1900             jpeg_info.optimize_coding=MagickTrue;
1901           RelinquishMagickResource(MemoryResource,length);
1902         }
1903     }
1904 #if (JPEG_LIB_VERSION >= 61) && defined(C_PROGRESSIVE_SUPPORTED)
1905   if ((LocaleCompare(image_info->magick,"PJPEG") == 0) ||
1906       (image_info->interlace != NoInterlace))
1907     {
1908       if (image->debug != MagickFalse)
1909         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1910           "Interlace: progressive");
1911       jpeg_simple_progression(&jpeg_info);
1912     }
1913   else
1914     if (image->debug != MagickFalse)
1915       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1916         "Interlace: non-progressive");
1917 #else
1918   if (image->debug != MagickFalse)
1919     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1920       "Interlace: nonprogressive");
1921 #endif
1922   option=GetImageOption(image_info,"jpeg:extent");
1923   if (option != (const char *) NULL)
1924     {
1925       Image
1926         *jpeg_image;
1927
1928       ImageInfo
1929         *jpeg_info;
1930
1931       jpeg_info=CloneImageInfo(image_info);
1932       jpeg_image=CloneImage(image,0,0,MagickTrue,&image->exception);
1933       if (jpeg_image != (Image *) NULL)
1934         {
1935           MagickSizeType
1936             extent;
1937
1938           size_t
1939             maximum,
1940             minimum;
1941
1942           /*
1943             Search for compression quality that does not exceed image extent.
1944           */
1945           jpeg_info->quality=0;
1946           extent=(MagickSizeType) SiPrefixToDouble(option,100.0);
1947           (void) DeleteImageOption(jpeg_info,"jpeg:extent");
1948           (void) AcquireUniqueFilename(jpeg_image->filename);
1949           maximum=101;
1950           for (minimum=0; minimum != maximum; )
1951           {
1952             jpeg_image->quality=minimum+(maximum-minimum)/2;
1953             status=WriteJPEGImage(jpeg_info,jpeg_image);
1954             if (GetBlobSize(jpeg_image) <= extent)
1955               minimum=jpeg_image->quality+1;
1956             else
1957               maximum=jpeg_image->quality-1;
1958           }
1959           (void) RelinquishUniqueFileResource(jpeg_image->filename);
1960           image->quality=minimum-1;
1961           jpeg_image=DestroyImage(jpeg_image);
1962         }
1963       jpeg_info=DestroyImageInfo(jpeg_info);
1964     }
1965   if ((image_info->compression != LosslessJPEGCompression) &&
1966       (image->quality <= 100))
1967     {
1968       if (image->quality == UndefinedCompressionQuality)
1969         jpeg_set_quality(&jpeg_info,92,MagickTrue);
1970       else
1971         jpeg_set_quality(&jpeg_info,(int) image->quality,MagickTrue);
1972       if (image->debug != MagickFalse)
1973         (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Quality: %.20g",
1974           (double) image->quality);
1975     }
1976   else
1977     {
1978 #if !defined(C_LOSSLESS_SUPPORTED)
1979       jpeg_set_quality(&jpeg_info,100,MagickTrue);
1980       if (image->debug != MagickFalse)
1981         (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Quality: 100");
1982 #else
1983       if (image->quality < 100)
1984         (void) ThrowMagickException(&image->exception,GetMagickModule(),
1985           CoderWarning,"LosslessToLossyJPEGConversion",image->filename);
1986       else
1987         {
1988           int
1989             point_transform,
1990             predictor;
1991
1992           predictor=image->quality/100;  /* range 1-7 */
1993           point_transform=image->quality % 20;  /* range 0-15 */
1994           jpeg_simple_lossless(&jpeg_info,predictor,point_transform);
1995           if (image->debug != MagickFalse)
1996             {
1997               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1998                 "Compression: lossless");
1999               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2000                 "Predictor: %d",predictor);
2001               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2002                 "Point Transform: %d",point_transform);
2003             }
2004         }
2005 #endif
2006     }
2007   sampling_factor=(const char *) NULL;
2008   value=GetImageProperty(image,"jpeg:sampling-factor");
2009   if (value != (char *) NULL)
2010     {
2011       sampling_factor=value;
2012       if (image->debug != MagickFalse)
2013         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2014           "  Input sampling-factors=%s",sampling_factor);
2015     }
2016   if (image_info->sampling_factor != (char *) NULL)
2017     sampling_factor=image_info->sampling_factor;
2018   if (sampling_factor == (const char *) NULL)
2019     {
2020       if (image->quality >= 90)
2021         for (i=0; i < MAX_COMPONENTS; i++)
2022         {
2023           jpeg_info.comp_info[i].h_samp_factor=1;
2024           jpeg_info.comp_info[i].v_samp_factor=1;
2025         }
2026     }
2027   else
2028     {
2029       char
2030         **factors;
2031
2032       GeometryInfo
2033         geometry_info;
2034
2035       MagickStatusType
2036         flags;
2037
2038       /*
2039         Set sampling factor.
2040       */
2041       i=0;
2042       factors=SamplingFactorToList(sampling_factor);
2043       if (factors != (char **) NULL)
2044         {
2045           for (i=0; i < MAX_COMPONENTS; i++)
2046           {
2047             if (factors[i] == (char *) NULL)
2048               break;
2049             flags=ParseGeometry(factors[i],&geometry_info);
2050             if ((flags & SigmaValue) == 0)
2051               geometry_info.sigma=geometry_info.rho;
2052             jpeg_info.comp_info[i].h_samp_factor=(int) geometry_info.rho;
2053             jpeg_info.comp_info[i].v_samp_factor=(int) geometry_info.sigma;
2054             factors[i]=(char *) RelinquishMagickMemory(factors[i]);
2055           }
2056           factors=(char **) RelinquishMagickMemory(factors);
2057         }
2058       for ( ; i < MAX_COMPONENTS; i++)
2059       {
2060         jpeg_info.comp_info[i].h_samp_factor=1;
2061         jpeg_info.comp_info[i].v_samp_factor=1;
2062       }
2063     }
2064   if (jpeg_info.input_components == 1)
2065     for (i=0; i < MAX_COMPONENTS; i++)
2066     {
2067       jpeg_info.comp_info[i].h_samp_factor=1;
2068       jpeg_info.comp_info[i].v_samp_factor=1;
2069     }
2070   jpeg_start_compress(&jpeg_info,MagickTrue);
2071   if (image->debug != MagickFalse)
2072     {
2073       if (image->storage_class == PseudoClass)
2074         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2075           "Storage class: PseudoClass");
2076       else
2077         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2078           "Storage class: DirectClass");
2079       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Depth: %.20g",
2080         (double) image->depth);
2081       if (image->colors != 0)
2082         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2083           "Number of colors: %.20g",(double) image->colors);
2084       else
2085         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2086           "Number of colors: unspecified");
2087       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2088         "JPEG data precision: %d",(int) jpeg_info.data_precision);
2089       switch (image->colorspace)
2090       {
2091         case CMYKColorspace:
2092         {
2093           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2094             "Storage class: DirectClass");
2095           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2096             "Colorspace: CMYK");
2097           break;
2098         }
2099         case YCbCrColorspace:
2100         case Rec601YCbCrColorspace:
2101         case Rec709YCbCrColorspace:
2102         {
2103           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2104             "Colorspace: YCbCr");
2105           break;
2106         }
2107         default:
2108           break;
2109       }
2110       switch (image->colorspace)
2111       {
2112         case CMYKColorspace:
2113         {
2114           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2115             "Colorspace: CMYK");
2116           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2117             "Sampling factors: %dx%d,%dx%d,%dx%d,%dx%d",
2118             jpeg_info.comp_info[0].h_samp_factor,
2119             jpeg_info.comp_info[0].v_samp_factor,
2120             jpeg_info.comp_info[1].h_samp_factor,
2121             jpeg_info.comp_info[1].v_samp_factor,
2122             jpeg_info.comp_info[2].h_samp_factor,
2123             jpeg_info.comp_info[2].v_samp_factor,
2124             jpeg_info.comp_info[3].h_samp_factor,
2125             jpeg_info.comp_info[3].v_samp_factor);
2126           break;
2127         }
2128         case GRAYColorspace:
2129         case Rec601LumaColorspace:
2130         case Rec709LumaColorspace:
2131         {
2132           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2133             "Colorspace: GRAY");
2134           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2135             "Sampling factors: %dx%d",jpeg_info.comp_info[0].h_samp_factor,
2136             jpeg_info.comp_info[0].v_samp_factor);
2137           break;
2138         }
2139         case RGBColorspace:
2140         {
2141           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2142             "Image colorspace is RGB");
2143           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2144             "Sampling factors: %dx%d,%dx%d,%dx%d",
2145             jpeg_info.comp_info[0].h_samp_factor,
2146             jpeg_info.comp_info[0].v_samp_factor,
2147             jpeg_info.comp_info[1].h_samp_factor,
2148             jpeg_info.comp_info[1].v_samp_factor,
2149             jpeg_info.comp_info[2].h_samp_factor,
2150             jpeg_info.comp_info[2].v_samp_factor);
2151           break;
2152         }
2153         case YCbCrColorspace:
2154         case Rec601YCbCrColorspace:
2155         case Rec709YCbCrColorspace:
2156         {
2157           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2158             "Colorspace: YCbCr");
2159           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2160             "Sampling factors: %dx%d,%dx%d,%dx%d",
2161             jpeg_info.comp_info[0].h_samp_factor,
2162             jpeg_info.comp_info[0].v_samp_factor,
2163             jpeg_info.comp_info[1].h_samp_factor,
2164             jpeg_info.comp_info[1].v_samp_factor,
2165             jpeg_info.comp_info[2].h_samp_factor,
2166             jpeg_info.comp_info[2].v_samp_factor);
2167           break;
2168         }
2169         default:
2170         {
2171           (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Colorspace: %d",
2172             image->colorspace);
2173           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2174             "Sampling factors: %dx%d,%dx%d,%dx%d,%dx%d",
2175             jpeg_info.comp_info[0].h_samp_factor,
2176             jpeg_info.comp_info[0].v_samp_factor,
2177             jpeg_info.comp_info[1].h_samp_factor,
2178             jpeg_info.comp_info[1].v_samp_factor,
2179             jpeg_info.comp_info[2].h_samp_factor,
2180             jpeg_info.comp_info[2].v_samp_factor,
2181             jpeg_info.comp_info[3].h_samp_factor,
2182             jpeg_info.comp_info[3].v_samp_factor);
2183           break;
2184         }
2185       }
2186     }
2187   /*
2188     Write JPEG profiles.
2189   */
2190   value=GetImageProperty(image,"comment");
2191   if (value != (char *) NULL)
2192     for (i=0; i < (ssize_t) strlen(value); i+=65533L)
2193       jpeg_write_marker(&jpeg_info,JPEG_COM,(unsigned char *) value+i,
2194         (unsigned int) MagickMin((size_t) strlen(value+i),65533L));
2195   if (image->profiles != (void *) NULL)
2196     WriteProfile(&jpeg_info,image);
2197   /*
2198     Convert MIFF to JPEG raster pixels.
2199   */
2200   jpeg_pixels=(JSAMPLE *) AcquireQuantumMemory((size_t) image->columns,
2201     jpeg_info.input_components*sizeof(*jpeg_pixels));
2202   if (jpeg_pixels == (JSAMPLE *) NULL)
2203     ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2204   if (setjmp(error_manager.error_recovery) != 0)
2205     {
2206       jpeg_destroy_compress(&jpeg_info);
2207       if (jpeg_pixels != (unsigned char *) NULL)
2208         jpeg_pixels=(unsigned char *) RelinquishMagickMemory(jpeg_pixels);
2209       (void) CloseBlob(image);
2210       return(MagickFalse);
2211     }
2212   scanline[0]=(JSAMPROW) jpeg_pixels;
2213   if (jpeg_info.data_precision <= 8)
2214     {
2215       if ((jpeg_info.in_color_space == JCS_RGB) ||
2216           (jpeg_info.in_color_space == JCS_YCbCr))
2217         for (y=0; y < (ssize_t) image->rows; y++)
2218         {
2219           register const PixelPacket
2220             *p;
2221
2222           register ssize_t
2223             x;
2224
2225           p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2226           if (p == (const PixelPacket *) NULL)
2227             break;
2228           q=jpeg_pixels;
2229           for (x=0; x < (ssize_t) image->columns; x++)
2230           {
2231             *q++=(JSAMPLE) ScaleQuantumToChar(GetRedPixelComponent(p));
2232             *q++=(JSAMPLE) ScaleQuantumToChar(GetGreenPixelComponent(p));
2233             *q++=(JSAMPLE) ScaleQuantumToChar(GetBluePixelComponent(p));
2234             p++;
2235           }
2236           (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2237           status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2238             image->rows);
2239           if (status == MagickFalse)
2240             break;
2241         }
2242       else
2243         if (jpeg_info.in_color_space == JCS_GRAYSCALE)
2244           for (y=0; y < (ssize_t) image->rows; y++)
2245           {
2246             register const PixelPacket
2247               *p;
2248
2249             register ssize_t
2250               x;
2251
2252             p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2253             if (p == (const PixelPacket *) NULL)
2254               break;
2255             q=jpeg_pixels;
2256             for (x=0; x < (ssize_t) image->columns; x++)
2257             {
2258               *q++=(JSAMPLE) ScaleQuantumToChar(PixelIntensityToQuantum(p));
2259               p++;
2260             }
2261             (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2262             status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2263               image->rows);
2264             if (status == MagickFalse)
2265               break;
2266           }
2267         else
2268           for (y=0; y < (ssize_t) image->rows; y++)
2269           {
2270             register const IndexPacket
2271               *indexes;
2272
2273             register const PixelPacket
2274               *p;
2275
2276             register ssize_t
2277               x;
2278
2279             p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2280             if (p == (const PixelPacket *) NULL)
2281               break;
2282             q=jpeg_pixels;
2283             indexes=GetVirtualIndexQueue(image);
2284             for (x=0; x < (ssize_t) image->columns; x++)
2285             {
2286               /*
2287                 Convert DirectClass packets to contiguous CMYK scanlines.
2288               */
2289               *q++=(JSAMPLE) (ScaleQuantumToChar((Quantum) (QuantumRange-
2290                 GetRedPixelComponent(p))));
2291               *q++=(JSAMPLE) (ScaleQuantumToChar((Quantum) (QuantumRange-
2292                 GetGreenPixelComponent(p))));
2293               *q++=(JSAMPLE) (ScaleQuantumToChar((Quantum) (QuantumRange-
2294                 GetBluePixelComponent(p))));
2295               *q++=(JSAMPLE) (ScaleQuantumToChar((Quantum) (QuantumRange-
2296                 GetIndexPixelComponent(indexes+x))));
2297               p++;
2298             }
2299             (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2300             status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2301               image->rows);
2302             if (status == MagickFalse)
2303               break;
2304           }
2305     }
2306   else
2307     if (jpeg_info.in_color_space == JCS_GRAYSCALE)
2308       for (y=0; y < (ssize_t) image->rows; y++)
2309       {
2310         register const PixelPacket
2311           *p;
2312
2313         register ssize_t
2314           x;
2315
2316         p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2317         if (p == (const PixelPacket *) NULL)
2318           break;
2319         q=jpeg_pixels;
2320         for (x=0; x < (ssize_t) image->columns; x++)
2321         {
2322           *q++=(JSAMPLE) (ScaleQuantumToShort(PixelIntensityToQuantum(p)) >>
2323             4);
2324           p++;
2325         }
2326         (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2327         status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2328           image->rows);
2329         if (status == MagickFalse)
2330           break;
2331       }
2332     else
2333       if ((jpeg_info.in_color_space == JCS_RGB) ||
2334           (jpeg_info.in_color_space == JCS_YCbCr))
2335         for (y=0; y < (ssize_t) image->rows; y++)
2336         {
2337           register const PixelPacket
2338             *p;
2339
2340           register ssize_t
2341             x;
2342
2343           p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2344           if (p == (const PixelPacket *) NULL)
2345             break;
2346           q=jpeg_pixels;
2347           for (x=0; x < (ssize_t) image->columns; x++)
2348           {
2349             *q++=(JSAMPLE) (ScaleQuantumToShort(GetRedPixelComponent(p)) >>
2350               4);
2351             *q++=(JSAMPLE) (ScaleQuantumToShort(GetGreenPixelComponent(p)) >>
2352               4);
2353             *q++=(JSAMPLE) (ScaleQuantumToShort(GetBluePixelComponent(p)) >>
2354               4);
2355             p++;
2356           }
2357           (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2358           status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2359             image->rows);
2360           if (status == MagickFalse)
2361             break;
2362         }
2363       else
2364         for (y=0; y < (ssize_t) image->rows; y++)
2365         {
2366           register const IndexPacket
2367             *indexes;
2368
2369           register const PixelPacket
2370             *p;
2371
2372           register ssize_t
2373             x;
2374
2375           p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2376           if (p == (const PixelPacket *) NULL)
2377             break;
2378           q=jpeg_pixels;
2379           indexes=GetVirtualIndexQueue(image);
2380           for (x=0; x < (ssize_t) image->columns; x++)
2381           {
2382             /*
2383               Convert DirectClass packets to contiguous CMYK scanlines.
2384             */
2385             *q++=(JSAMPLE) (4095-(ScaleQuantumToShort(
2386               GetRedPixelComponent(p)) >> 4));
2387             *q++=(JSAMPLE) (4095-(ScaleQuantumToShort(
2388               GetGreenPixelComponent(p)) >> 4));
2389             *q++=(JSAMPLE) (4095-(ScaleQuantumToShort(
2390               GetBluePixelComponent(p)) >> 4));
2391             *q++=(JSAMPLE) (4095-(ScaleQuantumToShort(
2392               GetIndexPixelComponent(indexes+x)) >> 4));
2393             p++;
2394           }
2395           (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2396           status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
2397             image->rows);
2398           if (status == MagickFalse)
2399             break;
2400         }
2401   if (y == (ssize_t) image->rows)
2402     jpeg_finish_compress(&jpeg_info);
2403   /*
2404     Relinquish resources.
2405   */
2406   jpeg_destroy_compress(&jpeg_info);
2407   jpeg_pixels=(unsigned char *) RelinquishMagickMemory(jpeg_pixels);
2408   (void) CloseBlob(image);
2409   return(MagickTrue);
2410 }
2411 #endif