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