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