]> 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-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/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 long
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) ((unsigned long) 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=(long) 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 long
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) ((unsigned long) 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 < (long) (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=(long) 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, %lu bytes",(unsigned long) 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 long
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) ((unsigned long) 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 < (long) 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=(long) GetStringInfoLength(profile)-1; i >= 0; 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, %lu bytes",(unsigned long) 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 long
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) ((unsigned long) 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=(long) 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           long
591             j;
592
593           /*
594             Extract namespace from XMP profile.
595           */
596           p=GetStringInfoDatum(profile);
597           for (j=0; j < (long) GetStringInfoLength(profile); j++)
598           {
599             if (*p == '\0')
600               break;
601             p++;
602           }
603           if (j < (long) 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, %lu bytes",name,(unsigned long) 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+=(size_t) number_bytes;
633   source->manager.bytes_in_buffer-=(size_t) 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     long
677       j,
678       qvalue,
679       sum;
680
681     register long
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          long
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=(long) (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=(unsigned long) i+1;
738            if (image->debug != MagickFalse)
739              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
740                "Quality: %ld (%s)",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            long
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=(long) (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=(unsigned long) i+1;
787              if (image->debug != MagickFalse)
788                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
789                  "Quality: %ld (%s)",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   long
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 long
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   unsigned long
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   image=AcquireImage(image_info);
922   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
923   if (status == MagickFalse)
924     {
925       image=DestroyImageList(image);
926       return((Image *) NULL);
927     }
928   /*
929     Initialize JPEG parameters.
930   */
931   (void) ResetMagickMemory(&jpeg_info,0,sizeof(jpeg_info));
932   (void) ResetMagickMemory(&jpeg_error,0,sizeof(jpeg_error));
933   jpeg_info.err=jpeg_std_error(&jpeg_error);
934   jpeg_info.err->emit_message=(void (*)(j_common_ptr,int)) EmitMessage;
935   jpeg_info.err->error_exit=(void (*)(j_common_ptr)) JPEGErrorHandler;
936   jpeg_pixels=(JSAMPLE *) NULL;
937   error_manager.image=image;
938   if (setjmp(error_manager.error_recovery) != 0)
939     {
940       jpeg_destroy_decompress(&jpeg_info);
941       (void) CloseBlob(image);
942       number_pixels=(MagickSizeType) image->columns*image->rows;
943       if (number_pixels != 0)
944         return(GetFirstImageInList(image));
945       InheritException(exception,&image->exception);
946       return(DestroyImage(image));
947     }
948   jpeg_info.client_data=(void *) &error_manager;
949   jpeg_create_decompress(&jpeg_info);
950   JPEGSourceManager(&jpeg_info,image);
951   jpeg_set_marker_processor(&jpeg_info,JPEG_COM,ReadComment);
952   jpeg_set_marker_processor(&jpeg_info,ICC_MARKER,ReadICCProfile);
953   jpeg_set_marker_processor(&jpeg_info,IPTC_MARKER,ReadIPTCProfile);
954   for (i=1; i < 16; i++)
955     if ((i != 2) && (i != 13) && (i != 14))
956       jpeg_set_marker_processor(&jpeg_info,(int) (JPEG_APP0+i),ReadProfile);
957   i=jpeg_read_header(&jpeg_info,MagickTrue);
958   if ((image_info->colorspace == YCbCrColorspace) ||
959       (image_info->colorspace == Rec601YCbCrColorspace) ||
960       (image_info->colorspace == Rec709YCbCrColorspace))
961     jpeg_info.out_color_space=JCS_YCbCr;
962   if (IsITUFaxImage(image) != MagickFalse)
963     {
964       image->colorspace=LabColorspace;
965       jpeg_info.out_color_space=JCS_YCbCr;
966     }
967   else
968     if (jpeg_info.out_color_space == JCS_CMYK)
969       image->colorspace=CMYKColorspace;
970   /*
971     Set image resolution.
972   */
973   units=0;
974   if ((jpeg_info.saw_JFIF_marker != 0) && (jpeg_info.X_density != 1) &&
975       (jpeg_info.Y_density != 1))
976     {
977       image->x_resolution=(double) jpeg_info.X_density;
978       image->y_resolution=(double) jpeg_info.Y_density;
979       units=(unsigned long) jpeg_info.density_unit;
980     }
981   if (units == 1)
982     image->units=PixelsPerInchResolution;
983   if (units == 2)
984     image->units=PixelsPerCentimeterResolution;
985   number_pixels=(MagickSizeType) image->columns*image->rows;
986   option=GetImageOption(image_info,"jpeg:size");
987   if (option != (const char *) NULL)
988     {
989       double
990         scale_factor;
991
992       GeometryInfo
993         geometry_info;
994
995       MagickStatusType
996         flags;
997
998       /*
999         Scale the image.
1000       */
1001       flags=ParseGeometry(option,&geometry_info);
1002       if ((flags & SigmaValue) == 0)
1003         geometry_info.sigma=geometry_info.rho;
1004       jpeg_calc_output_dimensions(&jpeg_info);
1005       image->magick_columns=jpeg_info.output_width;
1006       image->magick_rows=jpeg_info.output_height;
1007       scale_factor=1.0;
1008       if (geometry_info.rho != 0.0)
1009         scale_factor=jpeg_info.output_width/geometry_info.rho;
1010       if ((geometry_info.sigma != 0.0) &&
1011           (scale_factor > (jpeg_info.output_height/geometry_info.sigma)))
1012         scale_factor=jpeg_info.output_height/geometry_info.sigma;
1013       jpeg_info.scale_num=1U;
1014       jpeg_info.scale_denom=(unsigned int) scale_factor;
1015       jpeg_calc_output_dimensions(&jpeg_info);
1016       if (image->debug != MagickFalse)
1017         (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Scale factor: %ld",
1018           (long) scale_factor);
1019     }
1020   precision=(unsigned long) jpeg_info.data_precision;
1021 #if (JPEG_LIB_VERSION >= 61) && defined(D_PROGRESSIVE_SUPPORTED)
1022 #if defined(D_LOSSLESS_SUPPORTED)
1023   image->interlace=jpeg_info.process == JPROC_PROGRESSIVE ?
1024     JPEGInterlace : NoInterlace;
1025   image->compression=jpeg_info.process == JPROC_LOSSLESS ?
1026     LosslessJPEGCompression : JPEGCompression;
1027   if (jpeg_info.data_precision > 8)
1028     (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
1029       "12-bit JPEG not supported. Reducing pixel data to 8 bits","`%s'",
1030       image->filename);
1031   if (jpeg_info.data_precision == 16)
1032     jpeg_info.data_precision=12;
1033 #else
1034   image->interlace=jpeg_info.progressive_mode != 0 ? JPEGInterlace :
1035     NoInterlace;
1036   image->compression=JPEGCompression;
1037 #endif
1038 #else
1039   image->compression=JPEGCompression;
1040   image->interlace=JPEGInterlace;
1041 #endif
1042   if ((image_info->colors > 8) && (image_info->colors <= 256))
1043     {
1044       /*
1045         Let the JPEG library quantize for us.
1046       */
1047       jpeg_info.quantize_colors=MagickTrue;
1048       jpeg_info.desired_number_of_colors=(int) image_info->colors;
1049     }
1050   option=GetImageOption(image_info,"jpeg:block-smoothing");
1051   if (option != (const char *) NULL)
1052     {
1053       jpeg_info.do_block_smoothing=MagickFalse;
1054       if (IsMagickTrue(option) != MagickFalse)
1055         jpeg_info.do_block_smoothing=MagickTrue;
1056     }
1057   option=GetImageOption(image_info,"jpeg:dct-method");
1058   if (option != (const char *) NULL)
1059     switch (*option)
1060     {
1061       case 'D':
1062       case 'd':
1063       {
1064         if (LocaleCompare(option,"default") == 0)
1065           jpeg_info.dct_method=JDCT_DEFAULT;
1066         break;
1067       }
1068       case 'F':
1069       case 'f':
1070       {
1071         if (LocaleCompare(option,"fastest") == 0)
1072           jpeg_info.dct_method=JDCT_FASTEST;
1073         if (LocaleCompare(option,"float") == 0)
1074           jpeg_info.dct_method=JDCT_FLOAT;
1075         break;
1076       }
1077       case 'I':
1078       case 'i':
1079       {
1080         if (LocaleCompare(option,"ifast") == 0)
1081           jpeg_info.dct_method=JDCT_IFAST;
1082         if (LocaleCompare(option,"islow") == 0)
1083           jpeg_info.dct_method=JDCT_ISLOW;
1084         break;
1085       }
1086     }
1087   option=GetImageOption(image_info,"jpeg:fancy-upsampling");
1088   if (option != (const char *) NULL)
1089     {
1090       jpeg_info.do_fancy_upsampling=MagickFalse;
1091       if (IsMagickTrue(option) != MagickFalse)
1092         jpeg_info.do_fancy_upsampling=MagickTrue;
1093     }
1094   (void) jpeg_start_decompress(&jpeg_info);
1095   image->columns=jpeg_info.output_width;
1096   image->rows=jpeg_info.output_height;
1097   image->depth=(unsigned long) jpeg_info.data_precision;
1098   if (jpeg_info.out_color_space == JCS_YCbCr)
1099     image->colorspace=YCbCrColorspace;
1100   if (jpeg_info.out_color_space == JCS_CMYK)
1101     image->colorspace=CMYKColorspace;
1102   if ((image_info->colors != 0) && (image_info->colors <= 256))
1103     if (AcquireImageColormap(image,image_info->colors) == MagickFalse)
1104       ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1105   if ((jpeg_info.output_components == 1) &&
1106       (jpeg_info.quantize_colors == MagickFalse))
1107     {
1108       unsigned long
1109         colors;
1110
1111       colors=(unsigned long) GetQuantumRange(image->depth)+1;
1112       if (AcquireImageColormap(image,colors) == MagickFalse)
1113         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1114     }
1115   if (image->debug != MagickFalse)
1116     {
1117       if (image->interlace != NoInterlace)
1118         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1119           "Interlace: progressive");
1120       else
1121         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1122           "Interlace: nonprogressive");
1123       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Data precision: %d",
1124         (int) jpeg_info.data_precision);
1125       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Geometry: %dx%d",
1126         (int) jpeg_info.output_width,(int) jpeg_info.output_height);
1127     }
1128   JPEGSetImageQuality(&jpeg_info,image);
1129   JPEGSetImageSamplingFactor(&jpeg_info,image);
1130   (void) FormatMagickString(value,MaxTextExtent,"%ld",(long)
1131     jpeg_info.out_color_space);
1132   (void) SetImageProperty(image,"jpeg:colorspace",value);
1133   if (image_info->ping != MagickFalse)
1134     {
1135       jpeg_destroy_decompress(&jpeg_info);
1136       (void) CloseBlob(image);
1137       return(GetFirstImageInList(image));
1138     }
1139   jpeg_pixels=(JSAMPLE *) AcquireQuantumMemory((size_t) image->columns,
1140     jpeg_info.output_components*sizeof(JSAMPLE));
1141   if (jpeg_pixels == (JSAMPLE *) NULL)
1142     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1143   /*
1144     Convert JPEG pixels to pixel packets.
1145   */
1146   if (setjmp(error_manager.error_recovery) != 0)
1147     {
1148       if (jpeg_pixels != (unsigned char *) NULL)
1149         jpeg_pixels=(unsigned char *) RelinquishMagickMemory(jpeg_pixels);
1150       jpeg_destroy_decompress(&jpeg_info);
1151       (void) CloseBlob(image);
1152       number_pixels=(MagickSizeType) image->columns*image->rows;
1153       if (number_pixels != 0)
1154         return(GetFirstImageInList(image));
1155       return(DestroyImage(image));
1156     }
1157   if (jpeg_info.quantize_colors != MagickFalse)
1158     {
1159       image->colors=(unsigned long) jpeg_info.actual_number_of_colors;
1160       if (jpeg_info.out_color_space == JCS_GRAYSCALE)
1161         for (i=0; i < (long) image->colors; i++)
1162         {
1163           image->colormap[i].red=ScaleCharToQuantum(jpeg_info.colormap[0][i]);
1164           image->colormap[i].green=image->colormap[i].red;
1165           image->colormap[i].blue=image->colormap[i].red;
1166           image->colormap[i].opacity=OpaqueOpacity;
1167         }
1168       else
1169         for (i=0; i < (long) image->colors; i++)
1170         {
1171           image->colormap[i].red=ScaleCharToQuantum(jpeg_info.colormap[0][i]);
1172           image->colormap[i].green=ScaleCharToQuantum(jpeg_info.colormap[1][i]);
1173           image->colormap[i].blue=ScaleCharToQuantum(jpeg_info.colormap[2][i]);
1174           image->colormap[i].opacity=OpaqueOpacity;
1175         }
1176     }
1177   scanline[0]=(JSAMPROW) jpeg_pixels;
1178   for (y=0; y < (long) image->rows; y++)
1179   {
1180     register IndexPacket
1181       *restrict indexes;
1182
1183     register long
1184       x;
1185
1186     register PixelPacket
1187       *restrict q;
1188
1189     if (jpeg_read_scanlines(&jpeg_info,scanline,1) != 1)
1190       {
1191         (void) ThrowMagickException(exception,GetMagickModule(),
1192           CorruptImageWarning,"SkipToSyncByte","`%s'",image->filename);
1193         continue;
1194       }
1195     p=jpeg_pixels;
1196     q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
1197     if (q == (PixelPacket *) NULL)
1198       break;
1199     indexes=GetAuthenticIndexQueue(image);
1200     if (jpeg_info.data_precision > 8)
1201       {
1202         if (jpeg_info.output_components == 1)
1203           for (x=0; x < (long) image->columns; x++)
1204           {
1205             unsigned long
1206               pixel;
1207
1208             if (precision != 16)
1209               pixel=(unsigned long) GETJSAMPLE(*p);
1210             else
1211               pixel=(unsigned long) ((GETJSAMPLE(*p) ^ 0x80) << 4);
1212             index=ConstrainColormapIndex(image,pixel);
1213             indexes[x]=index;
1214             *q++=image->colormap[(int) index];
1215             p++;
1216           }
1217         else
1218           if (image->colorspace != CMYKColorspace)
1219             for (x=0; x < (long) image->columns; x++)
1220             {
1221               q->red=ScaleShortToQuantum((unsigned char)
1222                 (GETJSAMPLE(*p++) << 4));
1223               q->green=ScaleShortToQuantum((unsigned char)
1224                 (GETJSAMPLE(*p++) << 4));
1225               q->blue=ScaleShortToQuantum((unsigned char)
1226                 (GETJSAMPLE(*p++) << 4));
1227               SetOpacityPixelComponent(q,OpaqueOpacity);
1228               q++;
1229             }
1230           else
1231             for (x=0; x < (long) image->columns; x++)
1232             {
1233               q->red=(Quantum) QuantumRange-ScaleShortToQuantum((unsigned char)
1234                 (GETJSAMPLE(*p++) << 4));
1235               q->green=(Quantum) QuantumRange-ScaleShortToQuantum(
1236                 (unsigned char) (GETJSAMPLE(*p++) << 4));
1237               q->blue=(Quantum) QuantumRange-ScaleShortToQuantum((unsigned char)
1238                 (GETJSAMPLE(*p++) << 4));
1239               SetOpacityPixelComponent(q,OpaqueOpacity);
1240               indexes[x]=(IndexPacket) QuantumRange-ScaleShortToQuantum(
1241                 (unsigned char) (GETJSAMPLE(*p++) << 4));
1242               q++;
1243             }
1244       }
1245     else
1246       if (jpeg_info.output_components == 1)
1247         for (x=0; x < (long) image->columns; x++)
1248         {
1249           index=ConstrainColormapIndex(image,(unsigned long) GETJSAMPLE(*p));
1250           indexes[x]=(IndexPacket) index;
1251           *q++=image->colormap[(int) index];
1252           p++;
1253         }
1254       else
1255         if (image->colorspace != CMYKColorspace)
1256           for (x=0; x < (long) image->columns; x++)
1257           {
1258             q->red=ScaleCharToQuantum((unsigned char) GETJSAMPLE(*p++));
1259             q->green=ScaleCharToQuantum((unsigned char) GETJSAMPLE(*p++));
1260             q->blue=ScaleCharToQuantum((unsigned char) GETJSAMPLE(*p++));
1261             SetOpacityPixelComponent(q,OpaqueOpacity);
1262             q++;
1263           }
1264         else
1265           for (x=0; x < (long) image->columns; x++)
1266           {
1267             q->red=(Quantum) QuantumRange-ScaleCharToQuantum((unsigned char)
1268               GETJSAMPLE(*p++));
1269             q->green=(Quantum) QuantumRange-ScaleCharToQuantum((unsigned char)
1270               GETJSAMPLE(*p++));
1271             q->blue=(Quantum) QuantumRange-ScaleCharToQuantum((unsigned char)
1272               GETJSAMPLE(*p++));
1273             SetOpacityPixelComponent(q,OpaqueOpacity);
1274             indexes[x]=(IndexPacket) QuantumRange-ScaleCharToQuantum(
1275               (unsigned char) GETJSAMPLE(*p++));
1276             q++;
1277           }
1278     if (SyncAuthenticPixels(image,exception) == MagickFalse)
1279       break;
1280     if (SetImageProgress(image,LoadImageTag,y,image->rows) == MagickFalse)
1281       break;
1282   }
1283   /*
1284     Free jpeg resources.
1285   */
1286   (void) jpeg_finish_decompress(&jpeg_info);
1287   jpeg_destroy_decompress(&jpeg_info);
1288   jpeg_pixels=(unsigned char *) RelinquishMagickMemory(jpeg_pixels);
1289   (void) CloseBlob(image);
1290   return(GetFirstImageInList(image));
1291 }
1292 #endif
1293 \f
1294 /*
1295 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1296 %                                                                             %
1297 %                                                                             %
1298 %                                                                             %
1299 %   R e g i s t e r J P E G I m a g e                                         %
1300 %                                                                             %
1301 %                                                                             %
1302 %                                                                             %
1303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1304 %
1305 %  RegisterJPEGImage() adds properties for the JPEG image format to
1306 %  the list of supported formats.  The properties include the image format
1307 %  tag, a method to read and/or write the format, whether the format
1308 %  supports the saving of more than one frame to the same file or blob,
1309 %  whether the format supports native in-memory I/O, and a brief
1310 %  description of the format.
1311 %
1312 %  The format of the RegisterJPEGImage method is:
1313 %
1314 %      unsigned long RegisterJPEGImage(void)
1315 %
1316 */
1317 ModuleExport unsigned long RegisterJPEGImage(void)
1318 {
1319   char
1320     version[MaxTextExtent];
1321
1322   MagickInfo
1323     *entry;
1324
1325   static const char
1326     description[] = "Joint Photographic Experts Group JFIF format";
1327
1328   *version='\0';
1329 #if defined(JPEG_LIB_VERSION)
1330   (void) FormatMagickString(version,MaxTextExtent,"%d",JPEG_LIB_VERSION);
1331 #endif
1332   entry=SetMagickInfo("JPEG");
1333   entry->thread_support=NoThreadSupport;
1334 #if defined(MAGICKCORE_JPEG_DELEGATE)
1335   entry->decoder=(DecodeImageHandler *) ReadJPEGImage;
1336   entry->encoder=(EncodeImageHandler *) WriteJPEGImage;
1337 #endif
1338   entry->magick=(IsImageFormatHandler *) IsJPEG;
1339   entry->adjoin=MagickFalse;
1340   entry->description=ConstantString(description);
1341   if (*version != '\0')
1342     entry->version=ConstantString(version);
1343   entry->module=ConstantString("JPEG");
1344   (void) RegisterMagickInfo(entry);
1345   entry=SetMagickInfo("JPG");
1346   entry->thread_support=NoThreadSupport;
1347 #if defined(MAGICKCORE_JPEG_DELEGATE)
1348   entry->decoder=(DecodeImageHandler *) ReadJPEGImage;
1349   entry->encoder=(EncodeImageHandler *) WriteJPEGImage;
1350 #endif
1351   entry->adjoin=MagickFalse;
1352   entry->description=ConstantString(description);
1353   if (*version != '\0')
1354     entry->version=ConstantString(version);
1355   entry->module=ConstantString("JPEG");
1356   (void) RegisterMagickInfo(entry);
1357   entry=SetMagickInfo("PJPEG");
1358   entry->thread_support=NoThreadSupport;
1359 #if defined(MAGICKCORE_JPEG_DELEGATE)
1360   entry->decoder=(DecodeImageHandler *) ReadJPEGImage;
1361   entry->encoder=(EncodeImageHandler *) WriteJPEGImage;
1362 #endif
1363   entry->adjoin=MagickFalse;
1364   entry->description=ConstantString(description);
1365   if (*version != '\0')
1366     entry->version=ConstantString(version);
1367   entry->module=ConstantString("JPEG");
1368   (void) RegisterMagickInfo(entry);
1369   return(MagickImageCoderSignature);
1370 }
1371 \f
1372 /*
1373 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1374 %                                                                             %
1375 %                                                                             %
1376 %                                                                             %
1377 %   U n r e g i s t e r J P E G I m a g e                                     %
1378 %                                                                             %
1379 %                                                                             %
1380 %                                                                             %
1381 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1382 %
1383 %  UnregisterJPEGImage() removes format registrations made by the
1384 %  JPEG module from the list of supported formats.
1385 %
1386 %  The format of the UnregisterJPEGImage method is:
1387 %
1388 %      UnregisterJPEGImage(void)
1389 %
1390 */
1391 ModuleExport void UnregisterJPEGImage(void)
1392 {
1393   (void) UnregisterMagickInfo("PJPG");
1394   (void) UnregisterMagickInfo("JPEG");
1395   (void) UnregisterMagickInfo("JPG");
1396 }
1397 \f
1398 #if defined(MAGICKCORE_JPEG_DELEGATE)
1399 /*
1400 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1401 %                                                                             %
1402 %                                                                             %
1403 %                                                                             %
1404 %  W r i t e J P E G I m a g e                                                %
1405 %                                                                             %
1406 %                                                                             %
1407 %                                                                             %
1408 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1409 %
1410 %  WriteJPEGImage() writes a JPEG image file and returns it.  It
1411 %  allocates the memory necessary for the new Image structure and returns a
1412 %  pointer to the new image.
1413 %
1414 %  The format of the WriteJPEGImage method is:
1415 %
1416 %      MagickBooleanType WriteJPEGImage(const ImageInfo *image_info,Image *image)
1417 %
1418 %  A description of each parameter follows:
1419 %
1420 %    o image_info: the image info.
1421 %
1422 %    o jpeg_image:  The image.
1423 %
1424 %
1425 */
1426
1427 static boolean EmptyOutputBuffer(j_compress_ptr cinfo)
1428 {
1429   DestinationManager
1430     *destination;
1431
1432   destination=(DestinationManager *) cinfo->dest;
1433   destination->manager.free_in_buffer=(size_t) WriteBlob(destination->image,
1434     MaxBufferExtent,destination->buffer);
1435   if (destination->manager.free_in_buffer != MaxBufferExtent)
1436     ERREXIT(cinfo,JERR_FILE_WRITE);
1437   destination->manager.next_output_byte=destination->buffer;
1438   return(TRUE);
1439 }
1440
1441 static void InitializeDestination(j_compress_ptr cinfo)
1442 {
1443   DestinationManager
1444     *destination;
1445
1446   destination=(DestinationManager *) cinfo->dest;
1447   destination->buffer=(JOCTET *) (*cinfo->mem->alloc_small)
1448     ((j_common_ptr) cinfo,JPOOL_IMAGE,MaxBufferExtent*sizeof(JOCTET));
1449   destination->manager.next_output_byte=destination->buffer;
1450   destination->manager.free_in_buffer=MaxBufferExtent;
1451 }
1452
1453 static inline size_t MagickMin(const size_t x,const size_t y)
1454 {
1455   if (x < y)
1456     return(x);
1457   return(y);
1458 }
1459
1460 static void TerminateDestination(j_compress_ptr cinfo)
1461 {
1462   DestinationManager
1463     *destination;
1464
1465   destination=(DestinationManager *) cinfo->dest;
1466   if ((MaxBufferExtent-(int) destination->manager.free_in_buffer) > 0)
1467     {
1468       ssize_t
1469         count;
1470
1471       count=WriteBlob(destination->image,MaxBufferExtent-
1472         destination->manager.free_in_buffer,destination->buffer);
1473       if (count != (ssize_t)
1474           (MaxBufferExtent-destination->manager.free_in_buffer))
1475         ERREXIT(cinfo,JERR_FILE_WRITE);
1476     }
1477 }
1478
1479 static void WriteProfile(j_compress_ptr jpeg_info,Image *image)
1480 {
1481   const char
1482     *name;
1483
1484   const StringInfo
1485     *profile;
1486
1487   MagickBooleanType
1488     iptc;
1489
1490   register long
1491     i;
1492
1493   size_t
1494     length;
1495
1496   StringInfo
1497     *custom_profile;
1498
1499   unsigned long
1500     tag_length;
1501
1502   /*
1503     Save image profile as a APP marker.
1504   */
1505   iptc=MagickFalse;
1506   custom_profile=AcquireStringInfo(65535L);
1507   ResetImageProfileIterator(image);
1508   for (name=GetNextImageProfile(image); name != (const char *) NULL; )
1509   {
1510     profile=GetImageProfile(image,name);
1511     if (LocaleCompare(name,"EXIF") == 0)
1512       for (i=0; i < (long) GetStringInfoLength(profile); i+=65533L)
1513       {
1514         length=MagickMin(GetStringInfoLength(profile)-i,65533L);
1515         jpeg_write_marker(jpeg_info,XML_MARKER,GetStringInfoDatum(profile)+i,
1516           (unsigned int) length);
1517       }
1518     if (LocaleCompare(name,"ICC") == 0)
1519       {
1520         register unsigned char
1521           *p;
1522
1523         tag_length=14;
1524         p=GetStringInfoDatum(custom_profile);
1525         (void) CopyMagickMemory(p,ICC_PROFILE,tag_length);
1526         for (i=0; i < (long) GetStringInfoLength(profile); i+=65519L)
1527         {
1528           length=MagickMin(GetStringInfoLength(profile)-i,65519L);
1529           p=GetStringInfoDatum(custom_profile);
1530           p[12]=(unsigned char) ((i/65519L)+1);
1531           p[13]=(unsigned char) (GetStringInfoLength(profile)/65519L+1);
1532           (void) CopyMagickMemory(p+tag_length,GetStringInfoDatum(profile)+i,
1533             length);
1534           jpeg_write_marker(jpeg_info,ICC_MARKER,GetStringInfoDatum(
1535             custom_profile),(unsigned int) (length+tag_length));
1536         }
1537       }
1538     if (((LocaleCompare(name,"IPTC") == 0) ||
1539         (LocaleCompare(name,"8BIM") == 0)) && (iptc == MagickFalse))
1540       {
1541         register unsigned char
1542           *p;
1543
1544         unsigned long
1545           roundup;
1546
1547         iptc=MagickTrue;
1548         p=GetStringInfoDatum(custom_profile);
1549         if (LocaleNCompare((char *) GetStringInfoDatum(profile),"8BIM",4) == 0)
1550           {
1551             (void) CopyMagickMemory(p,"Photoshop 3.0\0",14);
1552             tag_length=14;
1553           }
1554         else
1555           {
1556             (void) CopyMagickMemory(p,"Photoshop 3.0\08BIM\04\04\0\0\0\0",24);
1557             p[13]=0x00;
1558             p[24]=(unsigned char) (GetStringInfoLength(profile) >> 8);
1559             p[25]=(unsigned char) (GetStringInfoLength(profile) & 0xff);
1560             tag_length=26;
1561           }
1562         for (i=0; i < (long) GetStringInfoLength(profile); i+=65500L)
1563         {
1564           length=MagickMin(GetStringInfoLength(profile)-i,65500L);
1565           roundup=(unsigned long) (length & 0x01);
1566           (void) CopyMagickMemory(p+tag_length,GetStringInfoDatum(profile)+i,
1567             length);
1568           if (roundup != 0)
1569             p[length+tag_length]='\0';
1570           jpeg_write_marker(jpeg_info,IPTC_MARKER,GetStringInfoDatum(
1571             custom_profile),(unsigned int) (length+tag_length+roundup));
1572         }
1573       }
1574     if (LocaleCompare(name,"XMP") == 0)
1575       {
1576         StringInfo
1577           *xmp_profile;
1578
1579         /*
1580           Add namespace to XMP profile.
1581         */
1582         xmp_profile=StringToStringInfo("http://ns.adobe.com/xap/1.0/");
1583         ConcatenateStringInfo(xmp_profile,profile);
1584         GetStringInfoDatum(xmp_profile)[28]='\0';
1585         for (i=0; i < (long) GetStringInfoLength(xmp_profile); i+=65533L)
1586         {
1587           length=MagickMin(GetStringInfoLength(xmp_profile)-i,65533L);
1588           jpeg_write_marker(jpeg_info,XML_MARKER,
1589             GetStringInfoDatum(xmp_profile)+i,(unsigned int) length);
1590         }
1591         xmp_profile=DestroyStringInfo(xmp_profile);
1592       }
1593     (void) LogMagickEvent(CoderEvent,GetMagickModule(),"%s profile: %lu bytes",
1594       name,(unsigned long) GetStringInfoLength(profile));
1595     name=GetNextImageProfile(image);
1596   }
1597   custom_profile=DestroyStringInfo(custom_profile);
1598 }
1599
1600 static void JPEGDestinationManager(j_compress_ptr cinfo,Image * image)
1601 {
1602   DestinationManager
1603     *destination;
1604
1605   cinfo->dest=(struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small)
1606     ((j_common_ptr) cinfo,JPOOL_IMAGE,sizeof(DestinationManager));
1607   destination=(DestinationManager *) cinfo->dest;
1608   destination->manager.init_destination=InitializeDestination;
1609   destination->manager.empty_output_buffer=EmptyOutputBuffer;
1610   destination->manager.term_destination=TerminateDestination;
1611   destination->image=image;
1612 }
1613
1614 static char **SamplingFactorToList(const char *text)
1615 {
1616   char
1617     **textlist;
1618
1619   register char
1620     *q;
1621
1622   register const char
1623     *p;
1624
1625   register long
1626     i;
1627
1628   unsigned long
1629     lines;
1630
1631   if (text == (char *) NULL)
1632     return((char **) NULL);
1633   /*
1634     Convert string to an ASCII list.
1635   */
1636   lines=1;
1637   for (p=text; *p != '\0'; p++)
1638     if (*p == ',')
1639       lines++;
1640   textlist=(char **) AcquireQuantumMemory((size_t) lines+MaxTextExtent,
1641     sizeof(*textlist));
1642   if (textlist == (char **) NULL)
1643     ThrowFatalException(ResourceLimitFatalError,"UnableToConvertText");
1644   p=text;
1645   for (i=0; i < (long) lines; i++)
1646   {
1647     for (q=(char *) p; *q != '\0'; q++)
1648       if (*q == ',')
1649         break;
1650     textlist[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent,
1651       sizeof(*textlist[i]));
1652     if (textlist[i] == (char *) NULL)
1653       ThrowFatalException(ResourceLimitFatalError,"UnableToConvertText");
1654     (void) CopyMagickString(textlist[i],p,(size_t) (q-p+1));
1655     if (*q == '\r')
1656       q++;
1657     p=q+1;
1658   }
1659   textlist[i]=(char *) NULL;
1660   return(textlist);
1661 }
1662
1663 static MagickBooleanType WriteJPEGImage(const ImageInfo *image_info,
1664   Image *image)
1665 {
1666   const char
1667     *option,
1668     *sampling_factor,
1669     *value;
1670
1671   ErrorManager
1672     error_manager;
1673
1674   JSAMPLE
1675     *jpeg_pixels;
1676
1677   JSAMPROW
1678     scanline[1];
1679
1680   long
1681     y;
1682
1683   MagickBooleanType
1684     status;
1685
1686   register JSAMPLE
1687     *q;
1688
1689   register long
1690     i;
1691
1692   struct jpeg_compress_struct
1693     jpeg_info;
1694
1695   struct jpeg_error_mgr
1696     jpeg_error;
1697
1698   /*
1699     Open image file.
1700   */
1701   assert(image_info != (const ImageInfo *) NULL);
1702   assert(image_info->signature == MagickSignature);
1703   assert(image != (Image *) NULL);
1704   assert(image->signature == MagickSignature);
1705   if (image->debug != MagickFalse)
1706     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1707   status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1708   if (status == MagickFalse)
1709     return(status);
1710   /*
1711     Initialize JPEG parameters.
1712   */
1713   (void) ResetMagickMemory(&jpeg_info,0,sizeof(jpeg_info));
1714   (void) ResetMagickMemory(&jpeg_error,0,sizeof(jpeg_error));
1715   jpeg_info.client_data=(void *) image;
1716   jpeg_info.err=jpeg_std_error(&jpeg_error);
1717   jpeg_info.err->emit_message=(void (*)(j_common_ptr,int)) EmitMessage;
1718   jpeg_info.err->error_exit=(void (*)(j_common_ptr)) JPEGErrorHandler;
1719   error_manager.image=image;
1720   jpeg_pixels=(JSAMPLE *) NULL;
1721   if (setjmp(error_manager.error_recovery) != 0)
1722     {
1723       jpeg_destroy_compress(&jpeg_info);
1724       (void) CloseBlob(image);
1725       return(MagickFalse);
1726     }
1727   jpeg_info.client_data=(void *) &error_manager;
1728   jpeg_create_compress(&jpeg_info);
1729   JPEGDestinationManager(&jpeg_info,image);
1730   if ((image->columns != (unsigned int) image->columns) ||
1731       (image->rows != (unsigned int) image->rows))
1732     ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
1733   jpeg_info.image_width=(unsigned int) image->columns;
1734   jpeg_info.image_height=(unsigned int) image->rows;
1735   jpeg_info.input_components=3;
1736   jpeg_info.data_precision=8;
1737   jpeg_info.in_color_space=JCS_RGB;
1738   switch (image->colorspace)
1739   {
1740     case CMYKColorspace:
1741     {
1742       jpeg_info.input_components=4;
1743       jpeg_info.in_color_space=JCS_CMYK;
1744       break;
1745     }
1746     case YCbCrColorspace:
1747     case Rec601YCbCrColorspace:
1748     case Rec709YCbCrColorspace:
1749     {
1750       jpeg_info.in_color_space=JCS_YCbCr;
1751       break;
1752     }
1753     case GRAYColorspace:
1754     case Rec601LumaColorspace:
1755     case Rec709LumaColorspace:
1756     {
1757       jpeg_info.input_components=1;
1758       jpeg_info.in_color_space=JCS_GRAYSCALE;
1759       break;
1760     }
1761     default:
1762     {
1763       if (image->colorspace != RGBColorspace)
1764         (void) TransformImageColorspace(image,RGBColorspace);
1765       break;
1766     }
1767   }
1768   if ((image_info->type != TrueColorType) &&
1769       (IsGrayImage(image,&image->exception) != MagickFalse))
1770     {
1771       jpeg_info.input_components=1;
1772       jpeg_info.in_color_space=JCS_GRAYSCALE;
1773     }
1774   jpeg_set_defaults(&jpeg_info);
1775   if ((jpeg_info.data_precision != 12) && (image->depth <= 8))
1776     jpeg_info.data_precision=8;
1777   else
1778     if (sizeof(JSAMPLE) > 1)
1779       jpeg_info.data_precision=12;
1780   jpeg_info.density_unit=(UINT8) 1;
1781   if (image->debug != MagickFalse)
1782     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1783       "Image resolution: %ld,%ld",(long) floor(image->x_resolution+0.5),
1784       (long) floor(image->y_resolution+0.5));
1785   if ((image->x_resolution != 0.0) && (image->y_resolution != 0.0))
1786     {
1787       /*
1788         Set image resolution.
1789       */
1790       jpeg_info.write_JFIF_header=MagickTrue;
1791       jpeg_info.X_density=(UINT16) image->x_resolution;
1792       jpeg_info.Y_density=(UINT16) image->y_resolution;
1793       if (image->units == PixelsPerInchResolution)
1794         jpeg_info.density_unit=(UINT8) 1;
1795       if (image->units == PixelsPerCentimeterResolution)
1796         jpeg_info.density_unit=(UINT8) 2;
1797     }
1798   option=GetImageOption(image_info,"jpeg:dct-method");
1799   if (option != (const char *) NULL)
1800     switch (*option)
1801     {
1802       case 'D':
1803       case 'd':
1804       {
1805         if (LocaleCompare(option,"default") == 0)
1806           jpeg_info.dct_method=JDCT_DEFAULT;
1807         break;
1808       }
1809       case 'F':
1810       case 'f':
1811       {
1812         if (LocaleCompare(option,"fastest") == 0)
1813           jpeg_info.dct_method=JDCT_FASTEST;
1814         if (LocaleCompare(option,"float") == 0)
1815           jpeg_info.dct_method=JDCT_FLOAT;
1816         break;
1817       }
1818       case 'I':
1819       case 'i':
1820       {
1821         if (LocaleCompare(option,"ifast") == 0)
1822           jpeg_info.dct_method=JDCT_IFAST;
1823         if (LocaleCompare(option,"islow") == 0)
1824           jpeg_info.dct_method=JDCT_ISLOW;
1825         break;
1826       }
1827     }
1828   option=GetImageOption(image_info,"jpeg:optimize-coding");
1829   if (option != (const char *) NULL)
1830     {
1831       jpeg_info.optimize_coding=MagickFalse;
1832       if (IsMagickTrue(option) != MagickFalse)
1833         jpeg_info.optimize_coding=MagickTrue;
1834     }
1835   else
1836     {
1837       MagickSizeType
1838         length;
1839
1840       length=(MagickSizeType) jpeg_info.input_components*image->columns*
1841         image->rows*sizeof(JSAMPLE);
1842       if (length == (MagickSizeType) ((size_t) length))
1843         {
1844           /*
1845             Perform optimization only if available memory resources permit it.
1846           */
1847           status=AcquireMagickResource(MemoryResource,length);
1848           if (status != MagickFalse)
1849             jpeg_info.optimize_coding=MagickTrue;
1850           RelinquishMagickResource(MemoryResource,length);
1851         }
1852     }
1853 #if (JPEG_LIB_VERSION >= 61) && defined(C_PROGRESSIVE_SUPPORTED)
1854   if ((LocaleCompare(image_info->magick,"PJPEG") == 0) ||
1855       (image_info->interlace != NoInterlace))
1856     {
1857       if (image->debug != MagickFalse)
1858         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1859           "Interlace: progressive");
1860       jpeg_simple_progression(&jpeg_info);
1861     }
1862   else
1863     if (image->debug != MagickFalse)
1864       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1865         "Interlace: non-progressive");
1866 #else
1867   if (image->debug != MagickFalse)
1868     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1869       "Interlace: nonprogressive");
1870 #endif
1871   option=GetImageOption(image_info,"jpeg:extent");
1872   if (option != (const char *) NULL)
1873     {
1874       Image
1875         *jpeg_image;
1876
1877       ImageInfo
1878         *jpeg_info;
1879
1880       jpeg_info=CloneImageInfo(image_info);
1881       jpeg_image=CloneImage(image,0,0,MagickTrue,&image->exception);
1882       if (jpeg_image != (Image *) NULL)
1883         {
1884           MagickSizeType
1885             extent;
1886
1887           size_t
1888             maximum,
1889             minimum;
1890
1891           /*
1892             Search for compression quality that does not exceed image extent.
1893           */
1894           jpeg_info->quality=0;
1895           extent=(MagickSizeType) SiPrefixToDouble(option,100.0);
1896           (void) DeleteImageOption(jpeg_info,"jpeg:extent");
1897           (void) AcquireUniqueFilename(jpeg_image->filename);
1898           maximum=101;
1899           for (minimum=0; minimum != maximum; )
1900           {
1901             jpeg_image->quality=minimum+(maximum-minimum)/2;
1902             status=WriteJPEGImage(jpeg_info,jpeg_image);
1903             if (GetBlobSize(jpeg_image) <= extent)
1904               minimum=jpeg_image->quality+1;
1905             else
1906               maximum=jpeg_image->quality-1;
1907           }
1908           (void) RelinquishUniqueFileResource(jpeg_image->filename);
1909           image->quality=minimum-1;
1910           jpeg_image=DestroyImage(jpeg_image);
1911         }
1912       jpeg_info=DestroyImageInfo(jpeg_info);
1913     }
1914   if ((image_info->compression != LosslessJPEGCompression) &&
1915       (image->quality <= 100))
1916     {
1917       if (image->quality == UndefinedCompressionQuality)
1918         jpeg_set_quality(&jpeg_info,92,MagickTrue);
1919       else
1920         jpeg_set_quality(&jpeg_info,(int) image->quality,MagickTrue);
1921       if (image->debug != MagickFalse)
1922         (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Quality: %lu",
1923           image->quality);
1924     }
1925   else
1926     {
1927 #if !defined(C_LOSSLESS_SUPPORTED)
1928       jpeg_set_quality(&jpeg_info,100,MagickTrue);
1929       if (image->debug != MagickFalse)
1930         (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Quality: 100");
1931 #else
1932       if (image->quality < 100)
1933         (void) ThrowMagickException(&image->exception,GetMagickModule(),
1934           CoderWarning,"LosslessToLossyJPEGConversion",image->filename);
1935       else
1936         {
1937           int
1938             point_transform,
1939             predictor;
1940
1941           predictor=image->quality/100;  /* range 1-7 */
1942           point_transform=image->quality % 20;  /* range 0-15 */
1943           jpeg_simple_lossless(&jpeg_info,predictor,point_transform);
1944           if (image->debug != MagickFalse)
1945             {
1946               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1947                 "Compression: lossless");
1948               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1949                 "Predictor: %d",predictor);
1950               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1951                 "Point Transform: %d",point_transform);
1952             }
1953         }
1954 #endif
1955     }
1956   sampling_factor=(const char *) NULL;
1957   value=GetImageProperty(image,"jpeg:sampling-factor");
1958   if (value != (char *) NULL)
1959     {
1960       sampling_factor=value;
1961       if (image->debug != MagickFalse)
1962         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1963           "  Input sampling-factors=%s",sampling_factor);
1964     }
1965   if (image_info->sampling_factor != (char *) NULL)
1966     sampling_factor=image_info->sampling_factor;
1967   if (sampling_factor == (const char *) NULL)
1968     {
1969       if (image->quality >= 90)
1970         for (i=0; i < MAX_COMPONENTS; i++)
1971         {
1972           jpeg_info.comp_info[i].h_samp_factor=1;
1973           jpeg_info.comp_info[i].v_samp_factor=1;
1974         }
1975     }
1976   else
1977     {
1978       char
1979         **factors;
1980
1981       GeometryInfo
1982         geometry_info;
1983
1984       MagickStatusType
1985         flags;
1986
1987       /*
1988         Set sampling factor.
1989       */
1990       i=0;
1991       factors=SamplingFactorToList(sampling_factor);
1992       if (factors != (char **) NULL)
1993         {
1994           for (i=0; i < MAX_COMPONENTS; i++)
1995           {
1996             if (factors[i] == (char *) NULL)
1997               break;
1998             flags=ParseGeometry(factors[i],&geometry_info);
1999             if ((flags & SigmaValue) == 0)
2000               geometry_info.sigma=geometry_info.rho;
2001             jpeg_info.comp_info[i].h_samp_factor=(int) geometry_info.rho;
2002             jpeg_info.comp_info[i].v_samp_factor=(int) geometry_info.sigma;
2003             factors[i]=(char *) RelinquishMagickMemory(factors[i]);
2004           }
2005           factors=(char **) RelinquishMagickMemory(factors);
2006         }
2007       for ( ; i < MAX_COMPONENTS; i++)
2008       {
2009         jpeg_info.comp_info[i].h_samp_factor=1;
2010         jpeg_info.comp_info[i].v_samp_factor=1;
2011       }
2012     }
2013   if (jpeg_info.input_components == 1)
2014     for (i=0; i < MAX_COMPONENTS; i++)
2015     {
2016       jpeg_info.comp_info[i].h_samp_factor=1;
2017       jpeg_info.comp_info[i].v_samp_factor=1;
2018     }
2019   jpeg_start_compress(&jpeg_info,MagickTrue);
2020   if (image->debug != MagickFalse)
2021     {
2022       if (image->storage_class == PseudoClass)
2023         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2024           "Storage class: PseudoClass");
2025       else
2026         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2027           "Storage class: DirectClass");
2028       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Depth: %lu",
2029         image->depth);
2030       if (image->colors != 0)
2031         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2032           "Number of colors: %lu",image->colors);
2033       else
2034         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2035           "Number of colors: unspecified");
2036       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2037         "JPEG data precision: %d",(int) jpeg_info.data_precision);
2038       switch (image->colorspace)
2039       {
2040         case CMYKColorspace:
2041         {
2042           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2043             "Storage class: DirectClass");
2044           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2045             "Colorspace: CMYK");
2046           break;
2047         }
2048         case YCbCrColorspace:
2049         case Rec601YCbCrColorspace:
2050         case Rec709YCbCrColorspace:
2051         {
2052           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2053             "Colorspace: YCbCr");
2054           break;
2055         }
2056         default:
2057           break;
2058       }
2059       switch (image->colorspace)
2060       {
2061         case CMYKColorspace:
2062         {
2063           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2064             "Colorspace: CMYK");
2065           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2066             "Sampling factors: %dx%d,%dx%d,%dx%d,%dx%d",
2067             jpeg_info.comp_info[0].h_samp_factor,
2068             jpeg_info.comp_info[0].v_samp_factor,
2069             jpeg_info.comp_info[1].h_samp_factor,
2070             jpeg_info.comp_info[1].v_samp_factor,
2071             jpeg_info.comp_info[2].h_samp_factor,
2072             jpeg_info.comp_info[2].v_samp_factor,
2073             jpeg_info.comp_info[3].h_samp_factor,
2074             jpeg_info.comp_info[3].v_samp_factor);
2075           break;
2076         }
2077         case GRAYColorspace:
2078         case Rec601LumaColorspace:
2079         case Rec709LumaColorspace:
2080         {
2081           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2082             "Colorspace: GRAY");
2083           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2084             "Sampling factors: %dx%d",jpeg_info.comp_info[0].h_samp_factor,
2085             jpeg_info.comp_info[0].v_samp_factor);
2086           break;
2087         }
2088         case RGBColorspace:
2089         {
2090           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2091             "Image colorspace is RGB");
2092           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2093             "Sampling factors: %dx%d,%dx%d,%dx%d",
2094             jpeg_info.comp_info[0].h_samp_factor,
2095             jpeg_info.comp_info[0].v_samp_factor,
2096             jpeg_info.comp_info[1].h_samp_factor,
2097             jpeg_info.comp_info[1].v_samp_factor,
2098             jpeg_info.comp_info[2].h_samp_factor,
2099             jpeg_info.comp_info[2].v_samp_factor);
2100           break;
2101         }
2102         case YCbCrColorspace:
2103         case Rec601YCbCrColorspace:
2104         case Rec709YCbCrColorspace:
2105         {
2106           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2107             "Colorspace: YCbCr");
2108           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2109             "Sampling factors: %dx%d,%dx%d,%dx%d",
2110             jpeg_info.comp_info[0].h_samp_factor,
2111             jpeg_info.comp_info[0].v_samp_factor,
2112             jpeg_info.comp_info[1].h_samp_factor,
2113             jpeg_info.comp_info[1].v_samp_factor,
2114             jpeg_info.comp_info[2].h_samp_factor,
2115             jpeg_info.comp_info[2].v_samp_factor);
2116           break;
2117         }
2118         default:
2119         {
2120           (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Colorspace: %d",
2121             image->colorspace);
2122           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2123             "Sampling factors: %dx%d,%dx%d,%dx%d,%dx%d",
2124             jpeg_info.comp_info[0].h_samp_factor,
2125             jpeg_info.comp_info[0].v_samp_factor,
2126             jpeg_info.comp_info[1].h_samp_factor,
2127             jpeg_info.comp_info[1].v_samp_factor,
2128             jpeg_info.comp_info[2].h_samp_factor,
2129             jpeg_info.comp_info[2].v_samp_factor,
2130             jpeg_info.comp_info[3].h_samp_factor,
2131             jpeg_info.comp_info[3].v_samp_factor);
2132           break;
2133         }
2134       }
2135     }
2136   /*
2137     Write JPEG profiles.
2138   */
2139   value=GetImageProperty(image,"comment");
2140   if (value != (char *) NULL)
2141     for (i=0; i < (long) strlen(value); i+=65533L)
2142       jpeg_write_marker(&jpeg_info,JPEG_COM,(unsigned char *) value+i,
2143         (unsigned int) MagickMin((size_t) strlen(value+i),65533L));
2144   if (image->profiles != (void *) NULL)
2145     WriteProfile(&jpeg_info,image);
2146   /*
2147     Convert MIFF to JPEG raster pixels.
2148   */
2149   jpeg_pixels=(JSAMPLE *) AcquireQuantumMemory((size_t) image->columns,
2150     jpeg_info.input_components*sizeof(*jpeg_pixels));
2151   if (jpeg_pixels == (JSAMPLE *) NULL)
2152     ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2153   if (setjmp(error_manager.error_recovery) != 0)
2154     {
2155       jpeg_destroy_compress(&jpeg_info);
2156       if (jpeg_pixels != (unsigned char *) NULL)
2157         jpeg_pixels=(unsigned char *) RelinquishMagickMemory(jpeg_pixels);
2158       (void) CloseBlob(image);
2159       return(MagickFalse);
2160     }
2161   scanline[0]=(JSAMPROW) jpeg_pixels;
2162   if (jpeg_info.data_precision <= 8)
2163     {
2164       if ((jpeg_info.in_color_space == JCS_RGB) ||
2165           (jpeg_info.in_color_space == JCS_YCbCr))
2166         for (y=0; y < (long) image->rows; y++)
2167         {
2168           register const PixelPacket
2169             *p;
2170
2171           register long
2172             x;
2173
2174           p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2175           if (p == (const PixelPacket *) NULL)
2176             break;
2177           q=jpeg_pixels;
2178           for (x=0; x < (long) image->columns; x++)
2179           {
2180             *q++=(JSAMPLE) ScaleQuantumToChar(GetRedPixelComponent(p));
2181             *q++=(JSAMPLE) ScaleQuantumToChar(GetGreenPixelComponent(p));
2182             *q++=(JSAMPLE) ScaleQuantumToChar(GetBluePixelComponent(p));
2183             p++;
2184           }
2185           (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2186           if (SetImageProgress(image,SaveImageTag,y,image->rows) == MagickFalse)
2187             break;
2188         }
2189       else
2190         if (jpeg_info.in_color_space == JCS_GRAYSCALE)
2191           for (y=0; y < (long) image->rows; y++)
2192           {
2193             register const PixelPacket
2194               *p;
2195
2196             register long
2197               x;
2198
2199             p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2200             if (p == (const PixelPacket *) NULL)
2201               break;
2202             q=jpeg_pixels;
2203             for (x=0; x < (long) image->columns; x++)
2204             {
2205               *q++=(JSAMPLE) ScaleQuantumToChar(PixelIntensityToQuantum(p));
2206               p++;
2207             }
2208             (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2209             if (SetImageProgress(image,SaveImageTag,y,image->rows) == 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) (ScaleQuantumToChar((Quantum) (QuantumRange-
2235                 GetRedPixelComponent(p))));
2236               *q++=(JSAMPLE) (ScaleQuantumToChar((Quantum) (QuantumRange-
2237                 GetGreenPixelComponent(p))));
2238               *q++=(JSAMPLE) (ScaleQuantumToChar((Quantum) (QuantumRange-
2239                 GetBluePixelComponent(p))));
2240               *q++=(JSAMPLE) (ScaleQuantumToChar((Quantum) (QuantumRange-
2241                 indexes[x])));
2242               p++;
2243             }
2244             (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2245             if (SetImageProgress(image,SaveImageTag,y,image->rows) == MagickFalse)
2246               break;
2247           }
2248     }
2249   else
2250     if (jpeg_info.in_color_space == JCS_GRAYSCALE)
2251       for (y=0; y < (long) image->rows; y++)
2252       {
2253         register const PixelPacket
2254           *p;
2255
2256         register long
2257           x;
2258
2259         p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2260         if (p == (const PixelPacket *) NULL)
2261           break;
2262         q=jpeg_pixels;
2263         for (x=0; x < (long) image->columns; x++)
2264         {
2265           *q++=(JSAMPLE) (ScaleQuantumToShort(PixelIntensityToQuantum(p)) >>
2266             4);
2267           p++;
2268         }
2269         (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2270         if (SetImageProgress(image,SaveImageTag,y,image->rows) == MagickFalse)
2271           break;
2272       }
2273     else
2274       if ((jpeg_info.in_color_space == JCS_RGB) ||
2275           (jpeg_info.in_color_space == JCS_YCbCr))
2276         for (y=0; y < (long) image->rows; y++)
2277         {
2278           register const PixelPacket
2279             *p;
2280
2281           register long
2282             x;
2283
2284           p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2285           if (p == (const PixelPacket *) NULL)
2286             break;
2287           q=jpeg_pixels;
2288           for (x=0; x < (long) image->columns; x++)
2289           {
2290             *q++=(JSAMPLE) (ScaleQuantumToShort(GetRedPixelComponent(p)) >>
2291               4);
2292             *q++=(JSAMPLE) (ScaleQuantumToShort(GetGreenPixelComponent(p)) >>
2293               4);
2294             *q++=(JSAMPLE) (ScaleQuantumToShort(GetBluePixelComponent(p)) >>
2295               4);
2296             p++;
2297           }
2298           (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2299           status=SetImageProgress(image,SaveImageTag,y,image->rows);
2300           if (status == MagickFalse)
2301             break;
2302         }
2303       else
2304         for (y=0; y < (long) image->rows; y++)
2305         {
2306           register const IndexPacket
2307             *indexes;
2308
2309           register const PixelPacket
2310             *p;
2311
2312           register long
2313             x;
2314
2315           p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2316           if (p == (const PixelPacket *) NULL)
2317             break;
2318           q=jpeg_pixels;
2319           indexes=GetVirtualIndexQueue(image);
2320           for (x=0; x < (long) image->columns; x++)
2321           {
2322             /*
2323               Convert DirectClass packets to contiguous CMYK scanlines.
2324             */
2325             *q++=(JSAMPLE) (4095-(ScaleQuantumToShort(
2326               GetRedPixelComponent(p)) >> 4));
2327             *q++=(JSAMPLE) (4095-(ScaleQuantumToShort(
2328               GetGreenPixelComponent(p)) >> 4));
2329             *q++=(JSAMPLE) (4095-(ScaleQuantumToShort(
2330               GetBluePixelComponent(p)) >> 4));
2331             *q++=(JSAMPLE) (4095-(ScaleQuantumToShort(indexes[x]) >> 4));
2332             p++;
2333           }
2334           (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2335           status=SetImageProgress(image,SaveImageTag,y,image->rows);
2336           if (status == MagickFalse)
2337             break;
2338         }
2339   if (y == (long) 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