1 /*
2 % Copyright (C) 2003-2020 GraphicsMagick Group
3 % Copyright (C) 2002 ImageMagick Studio
4 % Copyright 1991-1999 E. I. du Pont de Nemours and Company
5 %
6 % This program is covered by multiple licenses, which are described in
7 % Copyright.txt. You should have received a copy of Copyright.txt with this
8 % package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
9 %
10 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11 %                                                                             %
12 %                                                                             %
13 %                                                                             %
14 %                        JJJJJ  PPPP   EEEEE   GGGG                           %
15 %                          J    P   P  E      G                               %
16 %                          J    PPPP   EEE    G  GG                           %
17 %                        J J    P      E      G   G                           %
18 %                        JJJ    P      EEEEE   GGG                            %
19 %                                                                             %
20 %                                                                             %
21 %                       Read/Write JPEG Image Format.                         %
22 %                                                                             %
23 %                                                                             %
24 %                              Software Design                                %
25 %                                John Cristy                                  %
26 %                                 July 1992                                   %
27 %                                                                             %
28 %                                                                             %
29 %                                                                             %
30 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
31 %
32 % This software is based in part on the work of the Independent JPEG Group.
33 % See ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz for copyright and
34 % licensing restrictions.  Blob support contributed by Glenn Randers-Pehrson.
35 %
36 %
37 */
38 
39 /*
40   Include declarations.
41 */
42 #include "magick/studio.h"
43 #include "magick/analyze.h"
44 #include "magick/attribute.h"
45 #include "magick/blob.h"
46 #include "magick/colormap.h"
47 #include "magick/enum_strings.h"
48 #include "magick/log.h"
49 #include "magick/magick.h"
50 #include "magick/monitor.h"
51 #include "magick/pixel_cache.h"
52 #include "magick/profile.h"
53 #include "magick/resource.h"
54 #include "magick/utility.h"
55 
56 /*
57   Forward declarations.
58 */
59 static unsigned int
60   WriteJPEGImage(const ImageInfo *,Image *);
61 
62 /*
63 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
64 %                                                                             %
65 %                                                                             %
66 %                                                                             %
67 %   I s J P E G                                                               %
68 %                                                                             %
69 %                                                                             %
70 %                                                                             %
71 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
72 %
73 %  Method IsJPEG returns True if the image format type, identified by the
74 %  magick string, is JPEG.
75 %
76 %  The format of the IsJPEG  method is:
77 %
78 %      unsigned int IsJPEG(const unsigned char *magick,const size_t length)
79 %
80 %  A description of each parameter follows:
81 %
82 %    o status:  Method IsJPEG returns True if the image format type is JPEG.
83 %
84 %    o magick: This string is generally the first few bytes of an image file
85 %      or blob.
86 %
87 %    o length: Specifies the length of the magick string.
88 %
89 %
90 */
IsJPEG(const unsigned char * magick,const size_t length)91 static unsigned int IsJPEG(const unsigned char *magick,const size_t length)
92 {
93   if (length < 3)
94     return(False);
95   if (memcmp(magick,"\377\330\377",3) == 0)
96     return(True);
97   return(False);
98 }
99 
100 #if defined(HasJPEG)
101 #define JPEG_INTERNAL_OPTIONS
102 /*
103   Avoid conflicting typedef for INT32
104 */
105 #if defined(__MINGW32__)
106 # define XMD_H 1
107 #endif
108 /*
109   The JPEG headers have the annoying problem that they define
110   HAVE_STDLIB_H and we do too.  The define isn't actually used
111   so just undef it.
112 */
113 #undef HAVE_STDLIB_H
114 #include <setjmp.h>
115 #include "jpeglib.h"
116 #include "jerror.h"
117 
118 /*
119   Define declarations.
120 */
121 #define ICC_MARKER  (JPEG_APP0+2)
122 #define IPTC_MARKER  (JPEG_APP0+13)
123 #define XML_MARKER  (JPEG_APP0+1)
124 #define MaxBufferExtent  8192
125 #define JPEG_MARKER_MAX_SIZE 65533
126 #define MaxWarningCount 3
127 
128 /*
129   Set to 1 to use libjpeg callback for progress indication.  This is
130   not enabled by default since it outputs multiple progress
131   indications, which may be confusing for the user.  However, the
132   libjpeg method provides more detailed progress.
133 */
134 #define USE_LIBJPEG_PROGRESS 0 /* Use libjpeg callback for progress */
135 
136 static const char xmp_std_header[]="http://ns.adobe.com/xap/1.0/";
137 
138 
139 typedef struct _DestinationManager
140 {
141   struct jpeg_destination_mgr
142     manager;
143 
144   Image
145     *image;
146 
147   JOCTET
148     *buffer;
149 
150 } DestinationManager;
151 
152 typedef struct _ErrorManager
153 {
154   Image
155     *image;
156 
157   MagickBool
158     ping;
159 
160   MagickBool
161     completed;
162 
163   jmp_buf
164     error_recovery;
165 
166   unsigned int
167     max_warning_count;
168 
169   magick_uint16_t
170     warning_counts[JMSG_LASTMSGCODE];
171 
172   int
173     max_scan_number;
174 
175   unsigned char
176     buffer[65537+200];
177 
178 } ErrorManager;
179 
180 typedef struct _SourceManager
181 {
182   struct jpeg_source_mgr
183     manager;
184 
185   Image
186     *image;
187 
188   JOCTET
189     *buffer;
190 
191   boolean
192     start_of_blob;
193 } SourceManager;
194 
195 /*
196 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
197 %                                                                             %
198 %                                                                             %
199 %                                                                             %
200 %   R e a d J P E G I m a g e                                                 %
201 %                                                                             %
202 %                                                                             %
203 %                                                                             %
204 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
205 %
206 %  Method ReadJPEGImage reads a JPEG image file and returns it.  It allocates
207 %  the memory necessary for the new Image structure and returns a pointer to
208 %  the new image.
209 %
210 %  The format of the ReadJPEGImage method is:
211 %
212 %      Image *ReadJPEGImage(const ImageInfo *image_info,
213 %        ExceptionInfo *exception)
214 %
215 %  A description of each parameter follows:
216 %
217 %    o image:  Method ReadJPEGImage returns a pointer to the image after
218 %      reading.  A null image is returned if there is a memory shortage or
219 %      if the image cannot be read.
220 %
221 %    o image_info: Specifies a pointer to a ImageInfo structure.
222 %
223 %    o exception: return any errors or warnings in this structure.
224 %
225 %
226 */
227 
228 
229 /*
230   Format a libjpeg warning or trace event while decoding.  Warnings
231   are converted to GraphicsMagick warning exceptions while traces are
232   optionally logged.
233 
234   JPEG message codes range from 0 to JMSG_LASTMSGCODE
235 */
JPEGDecodeMessageHandler(j_common_ptr jpeg_info,int msg_level)236 static void JPEGDecodeMessageHandler(j_common_ptr jpeg_info,int msg_level)
237 {
238   char
239     message[JMSG_LENGTH_MAX];
240 
241   struct jpeg_error_mgr
242     *err;
243 
244   ErrorManager
245     *error_manager;
246 
247   Image
248     *image;
249 
250   message[0]='\0';
251   err=jpeg_info->err;
252   error_manager=(ErrorManager *) jpeg_info->client_data;
253   image=error_manager->image;
254   /* msg_level is -1 for warnings, 0 and up for trace messages. */
255   if (msg_level < 0)
256     {
257       unsigned int strikes = 0;
258       /* A warning */
259       (err->format_message)(jpeg_info,message);
260 
261       if ((err->msg_code >= 0) &&
262           ((size_t) err->msg_code < ArraySize(error_manager->warning_counts)))
263         {
264           error_manager->warning_counts[err->msg_code]++;
265           strikes=error_manager->warning_counts[err->msg_code];
266         }
267 
268       if (image->logging)
269         {
270           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
271                                 "[%s] JPEG Warning[%u]: \"%s\""
272                                 " (code=%d "
273                                 "parms=0x%02x,0x%02x,"
274                                 "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)",
275                                 image->filename,
276                                 strikes,
277                                 message,err->msg_code,
278                                 err->msg_parm.i[0], err->msg_parm.i[1],
279                                 err->msg_parm.i[2], err->msg_parm.i[3],
280                                 err->msg_parm.i[4], err->msg_parm.i[5],
281                                 err->msg_parm.i[6], err->msg_parm.i[7]);
282         }
283       if (strikes > error_manager->max_warning_count)
284         {
285           ThrowException2(&image->exception,CorruptImageError,(char *) message,
286                           image->filename);
287           longjmp(error_manager->error_recovery,1);
288         }
289 
290       if ((err->num_warnings == 0) ||
291           (err->trace_level >= 3))
292         ThrowException2(&image->exception,CorruptImageWarning,message,
293                         image->filename);
294       /* JWRN_JPEG_EOF - "Premature end of JPEG file" */
295       err->num_warnings++;
296       return /* False */;
297     }
298   else
299     {
300       /* A trace message */
301       if ((image->logging) && (msg_level >= err->trace_level))
302         {
303           (err->format_message)(jpeg_info,message);
304           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
305                                 "[%s] JPEG Trace: \"%s\"",image->filename,
306                                 message);
307         }
308     }
309   return /* True */;
310 }
311 
JPEGDecodeProgressMonitor(j_common_ptr cinfo)312 static void JPEGDecodeProgressMonitor(j_common_ptr cinfo)
313 {
314   ErrorManager *error_manager = (ErrorManager *) cinfo->client_data;
315   Image *image = error_manager->image;
316   const int max_scan_number = error_manager->max_scan_number;
317 
318 #if USE_LIBJPEG_PROGRESS
319   {
320     struct jpeg_progress_mgr *p = cinfo->progress;
321 
322 #if 0
323     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
324                           "Progress: pass_counter=%ld, pass_limit=%ld,"
325                           " completed_passes=%d, total_passes=%d, filename=%s",
326                           p->pass_counter, p->pass_limit,
327                           p->completed_passes, p->total_passes, image->filename);
328 #endif
329 
330     if (QuantumTick(p->pass_counter,p->pass_limit))
331       if (!MagickMonitorFormatted(p->pass_counter,p->pass_limit,&image->exception,
332                                   "[%s] Loading image: %lux%lu (pass %d of %d)...  ",
333                                   image->filename,
334                                   image->columns,image->rows,
335                                   p->completed_passes+1, p->total_passes))
336         {
337           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
338                                 "Quitting due to progress monitor");
339           longjmp(error_manager->error_recovery,1);
340         }
341   }
342 #endif /* USE_LIBJPEG_PROGRESS */
343 
344   if (cinfo->is_decompressor)
345     {
346       int scan_no = ((j_decompress_ptr) cinfo)->input_scan_number;
347 
348       if (scan_no > max_scan_number)
349         {
350           char message[MaxTextExtent];
351           FormatString(message,"Scan number %d exceeds maximum scans (%d)",
352                        scan_no, max_scan_number);
353           (void) LogMagickEvent(CoderEvent,GetMagickModule(),"%s", message);
354           ThrowException2(&image->exception,CorruptImageError,(char *) message,
355                           image->filename);
356           longjmp(error_manager->error_recovery,1);
357         }
358     }
359 }
360 
FillInputBuffer(j_decompress_ptr cinfo)361 static boolean FillInputBuffer(j_decompress_ptr cinfo)
362 {
363   SourceManager
364     *source;
365 
366   source=(SourceManager *) cinfo->src;
367   source->manager.bytes_in_buffer=
368     ReadBlob(source->image,MaxBufferExtent,(char *) source->buffer);
369   if (source->manager.bytes_in_buffer == 0)
370     {
371       if (source->start_of_blob)
372         ERREXIT(cinfo,JERR_INPUT_EMPTY);
373       WARNMS(cinfo,JWRN_JPEG_EOF);
374       source->buffer[0]=(JOCTET) 0xff;
375       source->buffer[1]=(JOCTET) JPEG_EOI;
376       source->manager.bytes_in_buffer=2;
377     }
378   source->manager.next_input_byte=source->buffer;
379   source->start_of_blob=FALSE;
380   return(TRUE);
381 }
382 
GetCharacter(j_decompress_ptr jpeg_info)383 static int GetCharacter(j_decompress_ptr jpeg_info)
384 {
385   if (jpeg_info->src->bytes_in_buffer == 0)
386     if ((!((*jpeg_info->src->fill_input_buffer)(jpeg_info))) ||
387         (jpeg_info->src->bytes_in_buffer == 0))
388       return EOF;
389   jpeg_info->src->bytes_in_buffer--;
390   return(GETJOCTET(*jpeg_info->src->next_input_byte++));
391 }
392 
InitializeSource(j_decompress_ptr cinfo)393 static void InitializeSource(j_decompress_ptr cinfo)
394 {
395   SourceManager
396     *source;
397 
398   source=(SourceManager *) cinfo->src;
399   source->start_of_blob=TRUE;
400 }
401 
402 /*
403   Format and report a libjpeg error event.  Errors are reported via a
404   GraphicsMagick error exception. The function terminates with
405   longjmp() so it never returns to the caller.
406 */
407 static void JPEGErrorHandler(j_common_ptr jpeg_info) MAGICK_FUNC_NORETURN;
408 
JPEGErrorHandler(j_common_ptr jpeg_info)409 static void JPEGErrorHandler(j_common_ptr jpeg_info)
410 {
411   char
412     message[JMSG_LENGTH_MAX];
413 
414   struct jpeg_error_mgr
415     *err;
416 
417   ErrorManager
418     *error_manager;
419 
420   Image
421     *image;
422 
423   message[0]='\0';
424   err=jpeg_info->err;
425   error_manager=(ErrorManager *) jpeg_info->client_data;
426   image=error_manager->image;
427   (err->format_message)(jpeg_info,message);
428   if (image->logging)
429     {
430       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
431                             "[%s] JPEG Error: \"%s\" (code=%d, "
432                             "parms=0x%02x,0x%02x,"
433                             "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)",
434                             image->filename,message,err->msg_code,
435                             err->msg_parm.i[0], err->msg_parm.i[1],
436                             err->msg_parm.i[2], err->msg_parm.i[3],
437                             err->msg_parm.i[4], err->msg_parm.i[5],
438                             err->msg_parm.i[6], err->msg_parm.i[7]);
439     }
440   if (error_manager->completed)
441     ThrowException2(&image->exception,CoderWarning,(char *) message,
442                     image->filename);
443   else
444     ThrowException2(&image->exception,CoderError,(char *) message,
445                     image->filename);
446   longjmp(error_manager->error_recovery,1);
447 }
448 
449 #define GetProfileLength(jpeg_info, length)                             \
450   do {                                                                  \
451     int                                                                 \
452       _c;                                                               \
453                                                                         \
454     if (((_c = GetCharacter(jpeg_info)) != EOF) && (_c >= 0))           \
455       {                                                                 \
456         length=_c*256;                                                  \
457         if (((_c = GetCharacter(jpeg_info)) != EOF) && (_c >= 0))       \
458           length+=_c;                                                   \
459         else                                                            \
460           length=0;                                                     \
461       }                                                                 \
462     else                                                                \
463       {                                                                 \
464         length=0;                                                       \
465       }                                                                 \
466   } while(0)
467 
ReadComment(j_decompress_ptr jpeg_info)468 static boolean ReadComment(j_decompress_ptr jpeg_info)
469 {
470   char
471     *comment;
472 
473   ErrorManager
474     *error_manager;
475 
476   Image
477     *image;
478 
479   register char
480     *p;
481 
482   size_t
483     i,
484     length;
485 
486   int
487     c;
488 
489   /*
490     Determine length of comment.
491   */
492   error_manager=(ErrorManager *) jpeg_info->client_data;
493   image=error_manager->image;
494   GetProfileLength(jpeg_info, length);
495   if (length <= 2)
496     return(True);
497   length-=2;
498   comment=(char *) error_manager->buffer;
499   /*
500     Read comment.
501   */
502   p=comment;
503   for (i=0; i < length; i++)
504     {
505       if ((c=GetCharacter(jpeg_info)) == EOF)
506         break;
507       *p=c;
508       p++;
509     }
510   *p='\0';
511   (void) SetImageAttribute(image,"comment",comment);
512   return(True);
513 }
514 
ReadGenericProfile(j_decompress_ptr jpeg_info)515 static boolean ReadGenericProfile(j_decompress_ptr jpeg_info)
516 {
517   ErrorManager
518     *error_manager;
519 
520   Image
521     *image;
522 
523   size_t
524     header_length=0,
525     length;
526 
527   register size_t
528     i;
529 
530   char
531     profile_name[MaxTextExtent];
532 
533   unsigned char
534     *profile;
535 
536   int
537     c,
538     marker;
539 
540   /*
541     Determine length of generic profile.
542   */
543   GetProfileLength(jpeg_info, length);
544   if (length <= 2)
545     return(True);
546   length-=2;
547 
548   marker=jpeg_info->unread_marker-JPEG_APP0;
549 
550   /*
551     Compute generic profile name.
552   */
553   FormatString(profile_name,"APP%d",marker);
554 
555   /*
556     Obtain Image.
557   */
558   error_manager=(ErrorManager *) jpeg_info->client_data;
559   image=error_manager->image;
560 
561   /*
562     Copy profile from JPEG to allocated memory.
563   */
564   profile=error_manager->buffer;
565 
566   for (i=0 ; i < length ; i++)
567     {
568       if ((c=GetCharacter(jpeg_info)) != EOF)
569         profile[i]=c;
570       else
571         break;
572     }
573   if (i != length)
574     return True;
575 
576   /*
577     Detect EXIF and XMP profiles.
578   */
579   if ((marker == 1) && (length > 4) &&
580       (strncmp((char *) profile,"Exif",4) == 0))
581     {
582       FormatString(profile_name,"EXIF");
583     }
584   else if (((marker == 1) && (length > strlen(xmp_std_header)+1)) &&
585            (memcmp(profile, xmp_std_header, strlen(xmp_std_header)+1) == 0))
586     {
587       /*
588         XMP is required to fit in one 64KB chunk.  Strip off its JPEG
589          namespace header.
590       */
591       header_length=strlen(xmp_std_header)+1;
592       FormatString((char *) profile_name,"XMP");
593     }
594 
595   /*
596     Store profile in Image.
597   */
598   (void) AppendImageProfile(image,profile_name,profile+header_length,
599                             length-header_length);
600 
601   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
602                         "Profile: %s, header %" MAGICK_SIZE_T_F "u bytes, "
603                         "data %" MAGICK_SIZE_T_F "u bytes",
604                         profile_name, (MAGICK_SIZE_T) header_length,
605                         (MAGICK_SIZE_T) length-header_length);
606 
607   return (True);
608 }
609 
ReadICCProfile(j_decompress_ptr jpeg_info)610 static boolean ReadICCProfile(j_decompress_ptr jpeg_info)
611 {
612   char
613     magick[12];
614 
615   ErrorManager
616     *error_manager;
617 
618   Image
619     *image;
620 
621   unsigned char
622     *profile;
623 
624   long
625     length;
626 
627   register long
628     i;
629 
630   int
631     c;
632 
633   /*
634     Determine length of color profile.
635   */
636   GetProfileLength(jpeg_info, length);
637   length-=2;
638   if (length <= 14)
639     {
640       while (--length >= 0)
641         (void) GetCharacter(jpeg_info);
642       return(True);
643     }
644   for (i=0; i < 12; i++)
645     magick[i]=GetCharacter(jpeg_info);
646   if (LocaleCompare(magick,"ICC_PROFILE") != 0)
647     {
648       /*
649         Not a ICC profile, return.
650       */
651       for (i=0; i < length-12; i++)
652         (void) GetCharacter(jpeg_info);
653       return(True);
654     }
655   (void) GetCharacter(jpeg_info);  /* id */
656   (void) GetCharacter(jpeg_info);  /* markers */
657   length-=14;
658   error_manager=(ErrorManager *) jpeg_info->client_data;
659   image=error_manager->image;
660 
661   /*
662     Read color profile.
663   */
664   profile=error_manager->buffer;
665 
666   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
667                         "ICC profile chunk: %ld bytes",
668     length);
669 
670   for (i=0 ; i < length; i++)
671     {
672       if ((c=GetCharacter(jpeg_info)) != EOF)
673         profile[i]=c;
674       else
675         break;
676     }
677   if (i == length)
678     (void) AppendImageProfile(image,"ICM",profile,length);
679 
680   return(True);
681 }
682 
ReadIPTCProfile(j_decompress_ptr jpeg_info)683 static boolean ReadIPTCProfile(j_decompress_ptr jpeg_info)
684 {
685   ErrorManager
686     *error_manager;
687 
688   Image
689     *image;
690 
691   long
692     length,
693     tag_length;
694 
695   unsigned char
696     *profile;
697 
698   register long
699     i;
700 
701 #ifdef GET_ONLY_IPTC_DATA
702   unsigned char
703     tag[MaxTextExtent];
704 #endif
705 
706   int
707     c;
708 
709   /*
710     Determine length of binary data stored here.
711   */
712   GetProfileLength(jpeg_info, length);
713   length-=2;
714   if (length <= 0)
715     return(True);
716   tag_length=0;
717 #ifdef GET_ONLY_IPTC_DATA
718   *tag='\0';
719 #endif
720   error_manager=(ErrorManager *) jpeg_info->client_data;
721   image=error_manager->image;
722 #ifdef GET_ONLY_IPTC_DATA
723   /*
724     Find the beginning of the IPTC portion of the binary data.
725   */
726   for (*tag='\0'; length > 0; )
727     {
728       *tag=GetCharacter(jpeg_info);
729       *(tag+1)=GetCharacter(jpeg_info);
730       length-=2;
731       if ((*tag == 0x1c) && (*(tag+1) == 0x02))
732         break;
733     }
734   tag_length=2;
735 #else
736   /*
737     Validate that this was written as a Photoshop resource format slug.
738   */
739   {
740     char
741       magick[MaxTextExtent];
742 
743     for (i=0; i < 10; i++)
744       magick[i]=GetCharacter(jpeg_info);
745     magick[10]='\0';
746     length-=10;
747     if (LocaleCompare(magick,"Photoshop ") != 0)
748       {
749         /*
750           Not a ICC profile, return.
751         */
752         for (i=0; i < length; i++)
753           (void) GetCharacter(jpeg_info);
754         return(True);
755       }
756   }
757   /*
758     Remove the version number.
759   */
760   for (i=0; i < 4; i++)
761     (void) GetCharacter(jpeg_info);
762   length-=4;
763   tag_length=0;
764 #endif
765   if (length <= 0)
766     return(True);
767 
768   if ((size_t) length+tag_length > sizeof(error_manager->buffer))
769     ThrowBinaryException(ResourceLimitError,MemoryAllocationFailed,
770       (char *) NULL);
771   profile=error_manager->buffer;
772   /*
773     Read the payload of this binary data.
774   */
775   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
776                         "Profile: IPTC, %ld bytes",
777     length);
778 
779   for (i=0; i < length; i++)
780     {
781       if ((c=GetCharacter(jpeg_info)) != EOF)
782         profile[i]=c;
783       else
784         break;
785     }
786   if (i == length)
787     (void) AppendImageProfile(image,"IPTC",profile,length);
788 
789   return(True);
790 }
791 
SkipInputData(j_decompress_ptr cinfo,long number_bytes)792 static void SkipInputData(j_decompress_ptr cinfo,long number_bytes)
793 {
794   SourceManager
795     *source;
796 
797   if (number_bytes <= 0)
798     return;
799   source=(SourceManager *) cinfo->src;
800   while (number_bytes > (long) source->manager.bytes_in_buffer)
801   {
802     number_bytes-=(long) source->manager.bytes_in_buffer;
803     (void) FillInputBuffer(cinfo);
804   }
805   source->manager.next_input_byte+=(size_t) number_bytes;
806   source->manager.bytes_in_buffer-=(size_t) number_bytes;
807 }
808 
TerminateSource(j_decompress_ptr cinfo)809 static void TerminateSource(j_decompress_ptr cinfo)
810 {
811   (void) cinfo;
812 }
813 
JPEGSourceManager(j_decompress_ptr cinfo,Image * image)814 static void JPEGSourceManager(j_decompress_ptr cinfo,Image *image)
815 {
816   SourceManager
817     *source;
818 
819   cinfo->src=(struct jpeg_source_mgr *) (*cinfo->mem->alloc_small)
820     ((j_common_ptr) cinfo,JPOOL_IMAGE,sizeof(SourceManager));
821   source=(SourceManager *) cinfo->src;
822   source->buffer=(JOCTET *) (*cinfo->mem->alloc_small)
823     ((j_common_ptr) cinfo,JPOOL_IMAGE,MaxBufferExtent*sizeof(JOCTET));
824   source=(SourceManager *) cinfo->src;
825   source->manager.init_source=InitializeSource;
826   source->manager.fill_input_buffer=FillInputBuffer;
827   source->manager.skip_input_data=SkipInputData;
828   source->manager.resync_to_restart=jpeg_resync_to_restart;
829   source->manager.term_source=TerminateSource;
830   source->manager.bytes_in_buffer=0;
831   source->manager.next_input_byte=NULL;
832   source->image=image;
833 }
834 
835 /*
836   Estimate the IJG quality factor used when saving the file.
837 */
838 static int
EstimateJPEGQuality(const struct jpeg_decompress_struct * jpeg_info,Image * image)839 EstimateJPEGQuality(const struct jpeg_decompress_struct *jpeg_info,
840                     Image *image)
841 {
842   int
843     save_quality;
844 
845   register long
846     i;
847 
848   save_quality=0;
849 #ifdef D_LOSSLESS_SUPPORTED
850   if (image->compression==LosslessJPEGCompression)
851     {
852       save_quality=100;
853       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
854                             "Quality: 100 (lossless)");
855     }
856   else
857 #endif
858 
859     {
860       int
861         hashval,
862         sum;
863 
864       /*
865         Log the JPEG quality that was used for compression.
866       */
867       sum=0;
868       for (i=0; i < NUM_QUANT_TBLS; i++)
869         {
870           int
871             j;
872 
873           if (jpeg_info->quant_tbl_ptrs[i] != NULL)
874             for (j=0; j < DCTSIZE2; j++)
875               {
876                 UINT16 *c;
877                 c=jpeg_info->quant_tbl_ptrs[i]->quantval;
878                 sum+=c[j];
879               }
880         }
881       if ((jpeg_info->quant_tbl_ptrs[0] != NULL) &&
882           (jpeg_info->quant_tbl_ptrs[1] != NULL))
883         {
884           int
885             hash[] =
886             {
887               1020, 1015,  932,  848,  780,  735,  702,  679,  660,  645,
888               632,  623,  613,  607,  600,  594,  589,  585,  581,  571,
889               555,  542,  529,  514,  494,  474,  457,  439,  424,  410,
890               397,  386,  373,  364,  351,  341,  334,  324,  317,  309,
891               299,  294,  287,  279,  274,  267,  262,  257,  251,  247,
892               243,  237,  232,  227,  222,  217,  213,  207,  202,  198,
893               192,  188,  183,  177,  173,  168,  163,  157,  153,  148,
894               143,  139,  132,  128,  125,  119,  115,  108,  104,   99,
895               94,   90,   84,   79,   74,   70,   64,   59,   55,   49,
896               45,   40,   34,   30,   25,   20,   15,   11,    6,    4,
897               0
898             };
899 
900           int
901             sums[] =
902             {
903               32640,32635,32266,31495,30665,29804,29146,28599,28104,27670,
904               27225,26725,26210,25716,25240,24789,24373,23946,23572,22846,
905               21801,20842,19949,19121,18386,17651,16998,16349,15800,15247,
906               14783,14321,13859,13535,13081,12702,12423,12056,11779,11513,
907               11135,10955,10676,10392,10208, 9928, 9747, 9564, 9369, 9193,
908               9017, 8822, 8639, 8458, 8270, 8084, 7896, 7710, 7527, 7347,
909               7156, 6977, 6788, 6607, 6422, 6236, 6054, 5867, 5684, 5495,
910               5305, 5128, 4945, 4751, 4638, 4442, 4248, 4065, 3888, 3698,
911               3509, 3326, 3139, 2957, 2775, 2586, 2405, 2216, 2037, 1846,
912               1666, 1483, 1297, 1109,  927,  735,  554,  375,  201,  128,
913               0
914             };
915 
916           hashval=(jpeg_info->quant_tbl_ptrs[0]->quantval[2]+
917                    jpeg_info->quant_tbl_ptrs[0]->quantval[53]+
918                    jpeg_info->quant_tbl_ptrs[1]->quantval[0]+
919                    jpeg_info->quant_tbl_ptrs[1]->quantval[DCTSIZE2-1]);
920           for (i=0; i < 100; i++)
921             {
922               if ((hashval >= hash[i]) || (sum >= sums[i]))
923                 {
924                   save_quality=i+1;
925                   if (image->logging)
926                     {
927                       if ((hashval > hash[i]) || (sum > sums[i]))
928                         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
929                                               "Quality: %d (approximate)",
930                                               save_quality);
931                       else
932                         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
933                                               "Quality: %d",save_quality);
934                     }
935                   break;
936                 }
937             }
938         }
939       else
940         if (jpeg_info->quant_tbl_ptrs[0] != NULL)
941           {
942             int
943               bwhash[] =
944               {
945                 510,  505,  422,  380,  355,  338,  326,  318,  311,  305,
946                 300,  297,  293,  291,  288,  286,  284,  283,  281,  280,
947                 279,  278,  277,  273,  262,  251,  243,  233,  225,  218,
948                 211,  205,  198,  193,  186,  181,  177,  172,  168,  164,
949                 158,  156,  152,  148,  145,  142,  139,  136,  133,  131,
950                 129,  126,  123,  120,  118,  115,  113,  110,  107,  105,
951                 102,  100,   97,   94,   92,   89,   87,   83,   81,   79,
952                 76,   74,   70,   68,   66,   63,   61,   57,   55,   52,
953                 50,   48,   44,   42,   39,   37,   34,   31,   29,   26,
954                 24,   21,   18,   16,   13,   11,    8,    6,    3,    2,
955                 0
956               };
957 
958             int
959               bwsum[] =
960               {
961                 16320,16315,15946,15277,14655,14073,13623,13230,12859,12560,
962                 12240,11861,11456,11081,10714,10360,10027, 9679, 9368, 9056,
963                 8680, 8331, 7995, 7668, 7376, 7084, 6823, 6562, 6345, 6125,
964                 5939, 5756, 5571, 5421, 5240, 5086, 4976, 4829, 4719, 4616,
965                 4463, 4393, 4280, 4166, 4092, 3980, 3909, 3835, 3755, 3688,
966                 3621, 3541, 3467, 3396, 3323, 3247, 3170, 3096, 3021, 2952,
967                 2874, 2804, 2727, 2657, 2583, 2509, 2437, 2362, 2290, 2211,
968                 2136, 2068, 1996, 1915, 1858, 1773, 1692, 1620, 1552, 1477,
969                 1398, 1326, 1251, 1179, 1109, 1031,  961,  884,  814,  736,
970                 667,  592,  518,  441,  369,  292,  221,  151,   86,   64,
971                 0
972               };
973 
974             hashval=(jpeg_info->quant_tbl_ptrs[0]->quantval[2]+
975                      jpeg_info->quant_tbl_ptrs[0]->quantval[53]);
976             for (i=0; i < 100; i++)
977               {
978                 if ((hashval >= bwhash[i]) || (sum >= bwsum[i]))
979                   {
980                     save_quality=i+1;
981                     if (image->logging)
982                       {
983                         if ((hashval > bwhash[i]) || (sum > bwsum[i]))
984                           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
985                                                 "Quality: %ld (approximate)",
986                                                 i+1);
987                         else
988                           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
989                                                 "Quality: %ld",i+1);
990                       }
991                     break;
992                   }
993               }
994           }
995     }
996 
997   return save_quality;
998 }
999 
1000 /*
1001   Format JPEG color space to a string.
1002 */
1003 static void
FormatJPEGColorSpace(const J_COLOR_SPACE colorspace,char * colorspace_name)1004 FormatJPEGColorSpace(const J_COLOR_SPACE colorspace,
1005                      char *colorspace_name)
1006 {
1007   const char
1008     *s = NULL;
1009 
1010   switch (colorspace)
1011     {
1012     default:
1013     case JCS_UNKNOWN:
1014       s = "UNKNOWN";
1015       break;
1016     case JCS_GRAYSCALE:
1017       s = "GRAYSCALE";
1018       break;
1019     case JCS_RGB:
1020       s = "RGB";
1021       break;
1022     case JCS_YCbCr:
1023       s = "YCbCr";
1024       break;
1025     case JCS_CMYK:
1026       s = "CMYK";
1027       break;
1028     case JCS_YCCK:
1029       s = "YCCK";
1030       break;
1031     }
1032   (void) strlcpy(colorspace_name,s,MaxTextExtent);
1033 }
1034 
1035 /*
1036   Format JPEG sampling factors to a string.
1037 */
1038 static void
FormatJPEGSamplingFactors(const struct jpeg_decompress_struct * jpeg_info,char * sampling_factors)1039 FormatJPEGSamplingFactors(const struct jpeg_decompress_struct *jpeg_info,
1040                           char *sampling_factors)
1041 {
1042   switch (jpeg_info->out_color_space)
1043     {
1044     case JCS_CMYK:
1045       {
1046         (void) FormatString(sampling_factors,"%dx%d,%dx%d,%dx%d,%dx%d",
1047                             jpeg_info->comp_info[0].h_samp_factor,
1048                             jpeg_info->comp_info[0].v_samp_factor,
1049                             jpeg_info->comp_info[1].h_samp_factor,
1050                             jpeg_info->comp_info[1].v_samp_factor,
1051                             jpeg_info->comp_info[2].h_samp_factor,
1052                             jpeg_info->comp_info[2].v_samp_factor,
1053                             jpeg_info->comp_info[3].h_samp_factor,
1054                             jpeg_info->comp_info[3].v_samp_factor);
1055         break;
1056       }
1057     case JCS_GRAYSCALE:
1058       {
1059         (void) FormatString(sampling_factors,"%dx%d",
1060                             jpeg_info->comp_info[0].h_samp_factor,
1061                             jpeg_info->comp_info[0].v_samp_factor);
1062         break;
1063       }
1064     case JCS_RGB:
1065       {
1066         (void) FormatString(sampling_factors,"%dx%d,%dx%d,%dx%d",
1067                             jpeg_info->comp_info[0].h_samp_factor,
1068                             jpeg_info->comp_info[0].v_samp_factor,
1069                             jpeg_info->comp_info[1].h_samp_factor,
1070                             jpeg_info->comp_info[1].v_samp_factor,
1071                             jpeg_info->comp_info[2].h_samp_factor,
1072                             jpeg_info->comp_info[2].v_samp_factor);
1073         break;
1074       }
1075     default:
1076       {
1077         (void) FormatString(sampling_factors,"%dx%d,%dx%d,%dx%d,%dx%d",
1078                             jpeg_info->comp_info[0].h_samp_factor,
1079                             jpeg_info->comp_info[0].v_samp_factor,
1080                             jpeg_info->comp_info[1].h_samp_factor,
1081                             jpeg_info->comp_info[1].v_samp_factor,
1082                             jpeg_info->comp_info[2].h_samp_factor,
1083                             jpeg_info->comp_info[2].v_samp_factor,
1084                             jpeg_info->comp_info[3].h_samp_factor,
1085                             jpeg_info->comp_info[3].v_samp_factor);
1086         break;
1087       }
1088     }
1089 }
1090 
1091 static MagickBool
IsITUFax(const Image * image)1092 IsITUFax(const Image* image)
1093 {
1094   size_t
1095     profile_length;
1096 
1097   const unsigned char
1098     *profile;
1099 
1100   MagickBool
1101     status;
1102 
1103   status=MagickFalse;
1104   if ((profile=GetImageProfile(image,"APP1",&profile_length)) &&
1105       (profile_length >= 5))
1106     {
1107       if (profile[0] == 0x47 &&
1108           profile[1] == 0x33 &&
1109           profile[2] == 0x46 &&
1110           profile[3] == 0x41 &&
1111           profile[4] == 0x58)
1112       status=MagickTrue;
1113     }
1114 
1115     return status;
1116 }
1117 
ReadJPEGImage(const ImageInfo * image_info,ExceptionInfo * exception)1118 static Image *ReadJPEGImage(const ImageInfo *image_info,
1119                             ExceptionInfo *exception)
1120 {
1121   Image
1122     *image;
1123 
1124   ErrorManager
1125     error_manager;
1126 
1127   IndexPacket
1128     index;
1129 
1130   long
1131     y;
1132 
1133   JSAMPLE
1134     *jpeg_pixels;
1135 
1136   JSAMPROW
1137     scanline[1];
1138 
1139   const char
1140     *value;
1141 
1142   register long
1143     i;
1144 
1145   struct jpeg_error_mgr
1146     jpeg_error;
1147 
1148   struct jpeg_progress_mgr
1149     jpeg_progress;
1150 
1151   struct jpeg_decompress_struct
1152     jpeg_info;
1153 
1154   register JSAMPLE
1155     *p;
1156 
1157   MagickPassFail
1158     status;
1159 
1160   unsigned long
1161     number_pixels;
1162 
1163   /*
1164     Open image file.
1165   */
1166   assert(image_info != (const ImageInfo *) NULL);
1167   assert(image_info->signature == MagickSignature);
1168   assert(exception != (ExceptionInfo *) NULL);
1169   assert(exception->signature == MagickSignature);
1170   image=AllocateImage(image_info);
1171   if (image == (Image *) NULL)
1172     ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
1173   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
1174   if (status == MagickFail)
1175     ThrowReaderException(FileOpenError,UnableToOpenFile,image);
1176   if (BlobIsSeekable(image) && GetBlobSize(image) < 107)
1177     ThrowReaderException(CorruptImageError,InsufficientImageDataInFile,image);
1178   /*
1179     Initialize structures.
1180   */
1181   (void) memset(&error_manager,0,sizeof(error_manager));
1182   (void) memset(&jpeg_progress,0,sizeof(jpeg_progress));
1183   (void) memset(&jpeg_info,0,sizeof(jpeg_info));
1184   (void) memset(&jpeg_error,0,sizeof(jpeg_error));
1185   jpeg_info.err=jpeg_std_error(&jpeg_error);
1186   jpeg_info.err->emit_message=/*(void (*)(j_common_ptr,int))*/ JPEGDecodeMessageHandler;
1187   jpeg_info.err->error_exit=(void (*)(j_common_ptr)) JPEGErrorHandler;
1188   jpeg_pixels=(JSAMPLE *) NULL;
1189   error_manager.image=image;
1190   error_manager.ping=image_info->ping;
1191   error_manager.max_scan_number=100;
1192   error_manager.max_warning_count=MaxWarningCount;
1193 
1194   /*
1195     Allow the user to set how many warnings of any given type are
1196     allowed before promotion of the warning to a hard error.
1197   */
1198   if ((value=AccessDefinition(image_info,"jpeg","max-warnings")))
1199     error_manager.max_warning_count=strtol(value,(char **) NULL, 10);
1200 
1201   /*
1202     Set initial longjmp based error handler.
1203   */
1204   if (setjmp(error_manager.error_recovery))
1205     {
1206       jpeg_destroy_decompress(&jpeg_info);
1207       GetImageException(image,exception);
1208       CloseBlob(image);
1209       if (exception->severity < ErrorException)
1210         return(image);
1211       DestroyImage(image);
1212       return((Image *) NULL);
1213     }
1214   jpeg_info.client_data=(void *) &error_manager;
1215 
1216   jpeg_create_decompress(&jpeg_info);
1217   /*
1218     Specify a memory limit for libjpeg which is 1/5th the absolute
1219     limit.  Don't actually consume the resource since we don't know
1220     how much libjpeg will actually consume.
1221   */
1222   jpeg_info.mem->max_memory_to_use=(long) (GetMagickResourceLimit(MemoryResource) -
1223                                            GetMagickResource(MemoryResource))/5U;
1224   if (image->logging)
1225     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1226                           "Memory capped to %ld bytes", jpeg_info.mem->max_memory_to_use);
1227   /*
1228     Register our progress monitor
1229   */
1230   jpeg_progress.progress_monitor=(void (*)(j_common_ptr)) JPEGDecodeProgressMonitor;
1231   jpeg_info.progress=&jpeg_progress;
1232 
1233   JPEGSourceManager(&jpeg_info,image);
1234   jpeg_set_marker_processor(&jpeg_info,JPEG_COM,ReadComment);
1235   jpeg_set_marker_processor(&jpeg_info,ICC_MARKER,ReadICCProfile);
1236   jpeg_set_marker_processor(&jpeg_info,IPTC_MARKER,ReadIPTCProfile);
1237   for (i=1; i < 16; i++)
1238     if ((i != 2) && (i != 13) && (i != 14))
1239       jpeg_set_marker_processor(&jpeg_info,JPEG_APP0+i,ReadGenericProfile);
1240   if (image->logging)
1241     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1242                           "Reading JPEG header...");
1243   i=jpeg_read_header(&jpeg_info,True);
1244   if (image->logging)
1245     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1246                           "Done with reading JPEG header");
1247   if (IsITUFax(image))
1248     {
1249       if (image->logging)
1250         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1251                               "Image colorspace set to LAB");
1252       image->colorspace=LABColorspace;
1253       jpeg_info.out_color_space = JCS_YCbCr;
1254     }
1255   else if (jpeg_info.out_color_space == JCS_CMYK)
1256     {
1257       if (image->logging)
1258         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1259                               "Image colorspace set to CMYK");
1260       image->colorspace=CMYKColorspace;
1261     }
1262   if (jpeg_info.saw_JFIF_marker)
1263     {
1264       if ((jpeg_info.X_density != 1U) && (jpeg_info.Y_density != 1U))
1265         {
1266           /*
1267             Set image resolution.
1268           */
1269           image->x_resolution=jpeg_info.X_density;
1270           image->y_resolution=jpeg_info.Y_density;
1271           if (jpeg_info.density_unit == 1)
1272             image->units=PixelsPerInchResolution;
1273           if (jpeg_info.density_unit == 2)
1274             image->units=PixelsPerCentimeterResolution;
1275           if (image->logging)
1276             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1277                                   "Image resolution set to %gx%g %s",
1278                                   image->x_resolution,
1279                                   image->y_resolution,
1280                                   ResolutionTypeToString(image->units));
1281         }
1282     }
1283 
1284   /*
1285     If the desired image size is pre-set (e.g. by using -size), then
1286     let the JPEG library subsample for us.
1287   */
1288   number_pixels=image->columns*image->rows;
1289   if (number_pixels != 0)
1290     {
1291       double
1292         scale_factor;
1293 
1294 
1295       if (image->logging)
1296         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1297                               "Requested Geometry: %lux%lu",
1298                               image->columns,image->rows);
1299       jpeg_calc_output_dimensions(&jpeg_info);
1300       image->magick_columns=jpeg_info.output_width;
1301       image->magick_rows=jpeg_info.output_height;
1302       if (image->logging)
1303         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1304                               "magick_geometry=%lux%lu",
1305                               image->magick_columns, image->magick_rows);
1306       scale_factor=(double) jpeg_info.output_width/image->columns;
1307       if (scale_factor > ((double) jpeg_info.output_height/image->rows))
1308         scale_factor=(double) jpeg_info.output_height/image->rows;
1309       jpeg_info.scale_denom *=(unsigned int) scale_factor;
1310       jpeg_calc_output_dimensions(&jpeg_info);
1311       if (image->logging)
1312         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1313                               "Original Geometry: %lux%lu,"
1314                               " Scale_factor: %ld (scale_num=%d,"
1315                               " scale_denom=%d)",
1316                               image->magick_columns, image->magick_rows,
1317                               (long) scale_factor,
1318                               jpeg_info.scale_num,jpeg_info.scale_denom);
1319     }
1320 #if 0
1321   /*
1322     The subrange parameter is set by the filename array syntax similar
1323     to the way an image is requested from a list (e.g. myfile.jpg[2]).
1324     Argument values other than zero are used to scale the image down
1325     by that factor.  IJG JPEG 62 (6b) supports values of 1,2,4, or 8
1326     while IJG JPEG 70 supports all values in the range 1-16.  This
1327     feature is useful in case you want to view all of the images with
1328     a consistent ratio.  Unfortunately, it uses the same syntax as
1329     list member access.
1330   */
1331   else if (image_info->subrange != 0)
1332     {
1333       jpeg_info.scale_denom *=(int) image_info->subrange;
1334       jpeg_calc_output_dimensions(&jpeg_info);
1335       if (image->logging)
1336         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1337                               "Requested Scaling Denominator: %d "
1338                               "(scale_num=%d, scale_denom=%d)",
1339                               (int) image_info->subrange,
1340                               jpeg_info.scale_num,jpeg_info.scale_denom);
1341 
1342     }
1343 #endif
1344 #if (JPEG_LIB_VERSION >= 61) && defined(D_PROGRESSIVE_SUPPORTED)
1345 #ifdef D_LOSSLESS_SUPPORTED
1346   image->interlace=
1347     jpeg_info.process == JPROC_PROGRESSIVE ? LineInterlace : NoInterlace;
1348   image->compression=jpeg_info.process == JPROC_LOSSLESS ?
1349     LosslessJPEGCompression : JPEGCompression;
1350   if (jpeg_info.data_precision > 8)
1351     MagickError2(OptionError,
1352                  "12-bit JPEG not supported. Reducing pixel data to 8 bits",
1353                  (char *) NULL);
1354 #else
1355   image->interlace=jpeg_info.progressive_mode ? LineInterlace : NoInterlace;
1356   image->compression=JPEGCompression;
1357 #endif
1358 #else
1359   image->compression=JPEGCompression;
1360   image->interlace=LineInterlace;
1361 #endif
1362 
1363   /*
1364     Allow the user to enable/disable block smoothing.
1365   */
1366   if ((value=AccessDefinition(image_info,"jpeg","block-smoothing")))
1367     {
1368       if (LocaleCompare(value,"FALSE") == 0)
1369         jpeg_info.do_block_smoothing=False;
1370       else
1371         jpeg_info.do_block_smoothing=True;
1372     }
1373 
1374   /*
1375     Allow the user to select the DCT decoding algorithm.
1376   */
1377   if ((value=AccessDefinition(image_info,"jpeg","dct-method")))
1378     {
1379       if (LocaleCompare(value,"ISLOW") == 0)
1380         jpeg_info.dct_method=JDCT_ISLOW;
1381       else if (LocaleCompare(value,"IFAST") == 0)
1382         jpeg_info.dct_method=JDCT_IFAST;
1383       else if (LocaleCompare(value,"FLOAT") == 0)
1384         jpeg_info.dct_method=JDCT_FLOAT;
1385       else if (LocaleCompare(value,"DEFAULT") == 0)
1386         jpeg_info.dct_method=JDCT_DEFAULT;
1387       else if (LocaleCompare(value,"FASTEST") == 0)
1388         jpeg_info.dct_method=JDCT_FASTEST;
1389     }
1390 
1391   /*
1392     Allow the user to enable/disable fancy upsampling.
1393   */
1394   if ((value=AccessDefinition(image_info,"jpeg","fancy-upsampling")))
1395     {
1396       if (LocaleCompare(value,"FALSE") == 0)
1397         jpeg_info.do_fancy_upsampling=False;
1398       else
1399         jpeg_info.do_fancy_upsampling=True;
1400     }
1401 
1402   /*
1403     Allow the user to adjust the maximum JPEG scan number
1404   */
1405   if ((value=AccessDefinition(image_info,"jpeg","max-scan-number")))
1406     {
1407       error_manager.max_scan_number=strtol(value,(char **) NULL, 10);
1408       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1409                             "JPEG max-scan-number set to %d",
1410                             error_manager.max_scan_number);
1411     }
1412 
1413   jpeg_calc_output_dimensions(&jpeg_info);
1414   image->columns=jpeg_info.output_width;
1415   image->rows=jpeg_info.output_height;
1416   image->storage_class = jpeg_info.output_components == 1 ? PseudoClass : DirectClass;
1417   image->depth=Min(jpeg_info.data_precision,QuantumDepth);
1418 
1419   if (image->logging)
1420     {
1421       if (image->interlace == LineInterlace)
1422         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1423                               "Interlace: progressive");
1424       else
1425         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1426                               "Interlace: nonprogressive");
1427       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Data precision: %d",
1428                             (int) jpeg_info.data_precision);
1429       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Components: %d",
1430                             (int) jpeg_info.output_components);
1431       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Geometry: %dx%d",
1432                             (int) jpeg_info.output_width,
1433                             (int) jpeg_info.output_height);
1434       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"DCT Method: %d",
1435                             jpeg_info.dct_method);
1436       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Fancy Upsampling: %s",
1437                             (jpeg_info.do_fancy_upsampling ? "true" : "false"));
1438       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Block Smoothing: %s",
1439                             (jpeg_info.do_block_smoothing ? "true" : "false"));
1440     }
1441 
1442   if (CheckImagePixelLimits(image, exception) != MagickPass)
1443     {
1444       jpeg_destroy_decompress(&jpeg_info);
1445       ThrowReaderException(ResourceLimitError,ImagePixelLimitExceeded,image);
1446     }
1447 
1448   if (image->logging)
1449     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1450                           "Starting JPEG decompression...");
1451   (void) jpeg_start_decompress(&jpeg_info);
1452   image->columns=jpeg_info.output_width;
1453   image->rows=jpeg_info.output_height;
1454   {
1455     char
1456       attribute[MaxTextExtent];
1457 
1458     /*
1459       Estimate and retain JPEG properties as attributes.
1460     */
1461     FormatString(attribute,"%d",EstimateJPEGQuality(&jpeg_info,image));
1462     (void) SetImageAttribute(image,"JPEG-Quality",attribute);
1463 
1464     FormatString(attribute,"%ld",(long)jpeg_info.out_color_space);
1465     (void) SetImageAttribute(image,"JPEG-Colorspace",attribute);
1466 
1467     FormatJPEGColorSpace(jpeg_info.out_color_space,attribute);
1468     (void) SetImageAttribute(image,"JPEG-Colorspace-Name",attribute);
1469     if (image->logging)
1470       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1471                             "Colorspace: %s (%d)", attribute,
1472                             jpeg_info.out_color_space);
1473 
1474     FormatJPEGSamplingFactors(&jpeg_info,attribute);
1475     (void) SetImageAttribute(image,"JPEG-Sampling-factors",attribute);
1476     if (image->logging)
1477       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1478                             "Sampling Factors: %s", attribute);
1479   }
1480 
1481   image->depth=Min(jpeg_info.data_precision,QuantumDepth);
1482   if (jpeg_info.out_color_space == JCS_GRAYSCALE)
1483     if (!AllocateImageColormap(image,1 << image->depth))
1484       {
1485         jpeg_destroy_decompress(&jpeg_info);
1486         ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
1487       }
1488   if (image_info->ping)
1489     {
1490       jpeg_destroy_decompress(&jpeg_info);
1491       CloseBlob(image);
1492       return(image);
1493     }
1494   if (CheckImagePixelLimits(image, exception) != MagickPass)
1495     {
1496       jpeg_destroy_decompress(&jpeg_info);
1497       ThrowReaderException(ResourceLimitError,ImagePixelLimitExceeded,image);
1498     }
1499 
1500   /*
1501     Verify that we support the number of output components.
1502   */
1503   if ((jpeg_info.output_components != 1) &&
1504       (jpeg_info.output_components != 3) &&
1505       (jpeg_info.output_components != 4))
1506     {
1507       jpeg_destroy_decompress(&jpeg_info);
1508       ThrowReaderException(CoderError,ImageTypeNotSupported,image);
1509     }
1510   /*
1511     Verify that file size is reasonable (if we can)
1512   */
1513   if (BlobIsSeekable(image))
1514     {
1515       magick_off_t
1516         blob_size;
1517 
1518       double
1519         ratio = 0;
1520 
1521       blob_size = GetBlobSize(image);
1522 
1523       if (blob_size != 0)
1524         {
1525           /* magick columns/rows are only set if size was specified! */
1526           if (image->magick_columns && image->magick_rows)
1527             ratio = ((double) image->magick_columns*image->magick_rows*
1528                      jpeg_info.output_components/blob_size);
1529           else
1530             ratio = ((double) image->columns*image->rows*
1531                      jpeg_info.output_components/blob_size);
1532         }
1533 
1534       /* All-black JPEG can produce tremendous compression ratios.
1535          Allow for it. */
1536       if ((blob_size == 0) || (ratio > 2500.0))
1537         {
1538           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1539                                 "Unreasonable dimensions: "
1540                                 "geometry=%lux%lu,"
1541                                 " magick_geometry=%lux%lu,"
1542                                 " components=%d, "
1543                                 "blob size=%" MAGICK_OFF_F "d bytes, "
1544                                 "compression ratio %g",
1545                                 image->columns, image->rows,
1546                                 image->magick_columns, image->magick_rows,
1547                                 jpeg_info.output_components, blob_size, ratio);
1548 
1549           jpeg_destroy_decompress(&jpeg_info);
1550           ThrowReaderException(CorruptImageError,InsufficientImageDataInFile,image);
1551         }
1552     }
1553 
1554   jpeg_pixels=MagickAllocateResourceLimitedArray(JSAMPLE *,
1555                                   jpeg_info.output_components,
1556                                   MagickArraySize(image->columns,
1557                                                   sizeof(JSAMPLE)));
1558   if (jpeg_pixels == (JSAMPLE *) NULL)
1559     {
1560       jpeg_destroy_decompress(&jpeg_info);
1561       ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
1562     }
1563   (void) memset(jpeg_pixels,0,MagickArraySize(jpeg_info.output_components,
1564                                               MagickArraySize(image->columns,
1565                                                               sizeof(JSAMPLE))));
1566 
1567   /*
1568     Extended longjmp-based error handler (with jpeg_pixels)
1569   */
1570   if (setjmp(error_manager.error_recovery))
1571     {
1572       /* Error handling code executed if longjmp was invoked */
1573       MagickFreeResourceLimitedMemory(jpeg_pixels);
1574       jpeg_destroy_decompress(&jpeg_info);
1575       if (image->exception.severity > exception->severity)
1576         CopyException(exception,&image->exception);
1577       CloseBlob(image);
1578       number_pixels=image->columns*image->rows;
1579       if (number_pixels != 0)
1580         return(image);
1581       DestroyImage(image);
1582       return((Image *) NULL);
1583     }
1584 
1585   /*
1586     Convert JPEG pixels to pixel packets.
1587   */
1588   scanline[0]=(JSAMPROW) jpeg_pixels;
1589   for (y=0; y < (long) image->rows; y++)
1590     {
1591       register IndexPacket
1592         *indexes;
1593 
1594       register long
1595         x;
1596 
1597       register PixelPacket
1598         *q;
1599 
1600       /*
1601         Read scanlines. Stop at first serious error.
1602        */
1603       if ((jpeg_read_scanlines(&jpeg_info,scanline,1) != 1) ||
1604           (image->exception.severity >= ErrorException))
1605         {
1606           status=MagickFail;
1607           break;
1608         }
1609 
1610       q=SetImagePixels(image,0,y,image->columns,1);
1611       if (q == (PixelPacket *) NULL)
1612         {
1613           status=MagickFail;
1614           break;
1615         }
1616       indexes=AccessMutableIndexes(image);
1617 
1618       p=jpeg_pixels;
1619 
1620       if (jpeg_info.output_components == 1)
1621         {
1622           for (x=0; x < (long) image->columns; x++)
1623             {
1624               index=(IndexPacket) (GETJSAMPLE(*p++));
1625               VerifyColormapIndex(image,index);
1626               indexes[x]=index;
1627               *q++=image->colormap[index];
1628             }
1629         }
1630       else if ((jpeg_info.output_components == 3) ||
1631                (jpeg_info.output_components == 4))
1632         {
1633           if (jpeg_info.data_precision > 8)
1634             {
1635               unsigned int
1636                 scale_short;
1637 
1638               scale_short=65535U/MaxValueGivenBits(jpeg_info.data_precision);
1639               for (x=0; x < (long) image->columns; x++)
1640                 {
1641                   q->red=ScaleShortToQuantum(scale_short*GETJSAMPLE(*p++));
1642                   q->green=ScaleShortToQuantum(scale_short*GETJSAMPLE(*p++));
1643                   q->blue=ScaleShortToQuantum(scale_short*GETJSAMPLE(*p++));
1644                   if (jpeg_info.output_components > 3)
1645                     q->opacity=ScaleShortToQuantum(scale_short*GETJSAMPLE(*p++));
1646                   else
1647                     q->opacity=OpaqueOpacity;
1648                   q++;
1649                 }
1650             }
1651           else
1652             {
1653               for (x=0; x < (long) image->columns; x++)
1654                 {
1655                   q->red=ScaleCharToQuantum(GETJSAMPLE(*p++));
1656                   q->green=ScaleCharToQuantum(GETJSAMPLE(*p++));
1657                   q->blue=ScaleCharToQuantum(GETJSAMPLE(*p++));
1658                   if (jpeg_info.output_components > 3)
1659                     q->opacity=ScaleCharToQuantum(GETJSAMPLE(*p++));
1660                   else
1661                     q->opacity=OpaqueOpacity;
1662                   q++;
1663                 }
1664             }
1665           if (image->colorspace == CMYKColorspace)
1666             {
1667               /*
1668                 CMYK pixels are inverted.
1669               */
1670               q=AccessMutablePixels(image);
1671               for (x=0; x < (long) image->columns; x++)
1672                 {
1673                   q->red=MaxRGB-q->red;
1674                   q->green=MaxRGB-q->green;
1675                   q->blue=MaxRGB-q->blue;
1676                   q->opacity=MaxRGB-q->opacity;
1677                   q++;
1678                 }
1679             }
1680         }
1681       if (!SyncImagePixels(image))
1682         {
1683           status=MagickFail;
1684           break;
1685         }
1686 #if !USE_LIBJPEG_PROGRESS
1687       if (QuantumTick(y,image->rows))
1688         if (!MagickMonitorFormatted(y,image->rows,exception,LoadImageText,
1689                                     image->filename,
1690                                     image->columns,image->rows))
1691           {
1692             status=MagickFail;
1693             jpeg_abort_decompress(&jpeg_info);
1694             break;
1695           }
1696 #endif /* !USE_LIBJPEG_PROGRESS */
1697     }
1698   /*
1699     Free jpeg resources.
1700   */
1701   if (status == MagickPass)
1702     {
1703       /*
1704         jpeg_finish_decompress() may throw an exception while it is
1705         finishing the remainder of the JPEG file.  At this point we
1706         have already decoded the image so we handle exceptions from
1707         jpeg_finish_decompress() specially, mapping reported
1708         exceptions as warnings rather than errors.  We try using
1709         jpeg_finish_decompress() and if it results in a longjmp(),
1710         then we skip over it again.
1711       */
1712       error_manager.completed=MagickTrue;
1713       if (!setjmp(error_manager.error_recovery))
1714         (void) jpeg_finish_decompress(&jpeg_info);
1715     }
1716   jpeg_destroy_decompress(&jpeg_info);
1717   MagickFreeResourceLimitedMemory(jpeg_pixels);
1718   CloseBlob(image);
1719 
1720   /*
1721     Retrieve image orientation from EXIF (if present) and store in
1722     image.
1723 
1724     EXIF orienation enumerations match TIFF enumerations, which happen
1725     to match the enumeration values used by GraphicsMagick.
1726   */
1727   if (status == MagickPass)
1728     {
1729       const ImageAttribute
1730         *attribute;
1731 
1732       attribute = GetImageAttribute(image,"EXIF:Orientation");
1733       if ((attribute != (const ImageAttribute *) NULL) &&
1734           (attribute->value != (char *) NULL))
1735         {
1736           int
1737             orientation;
1738 
1739           orientation=MagickAtoI(attribute->value);
1740           if ((orientation > UndefinedOrientation) &&
1741               (orientation <= LeftBottomOrientation))
1742             image->orientation=(OrientationType) orientation;
1743         }
1744     }
1745   if (image->logging)
1746     (void) LogMagickEvent(CoderEvent,GetMagickModule(),"return");
1747   GetImageException(image,exception);
1748   StopTimer(&image->timer);
1749   return(image);
1750 }
1751 #endif
1752 
1753 /*
1754 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1755 %                                                                             %
1756 %                                                                             %
1757 %                                                                             %
1758 %   R e g i s t e r J P E G I m a g e                                         %
1759 %                                                                             %
1760 %                                                                             %
1761 %                                                                             %
1762 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1763 %
1764 %  Method RegisterJPEGImage adds attributes for the JPEG image format to
1765 %  the list of supported formats.  The attributes include the image format
1766 %  tag, a method to read and/or write the format, whether the format
1767 %  supports the saving of more than one frame to the same file or blob,
1768 %  whether the format supports native in-memory I/O, and a brief
1769 %  description of the format.
1770 %
1771 %  The format of the RegisterJPEGImage method is:
1772 %
1773 %      RegisterJPEGImage(void)
1774 %
1775 */
RegisterJPEGImage(void)1776 ModuleExport void RegisterJPEGImage(void)
1777 {
1778   static const char
1779     description[]="Joint Photographic Experts Group JFIF format";
1780 
1781 #if defined(HasJPEG) && defined(JPEG_LIB_VERSION)
1782   static const char
1783     version[] = "IJG JPEG " DefineValueToString(JPEG_LIB_VERSION);
1784 #define HAVE_JPEG_VERSION
1785 #endif
1786 
1787   MagickInfo
1788     *entry;
1789 
1790   MagickBool
1791     thread_support;
1792 
1793 #if defined(SETJMP_IS_THREAD_SAFE) && (SETJMP_IS_THREAD_SAFE)
1794   thread_support=MagickTrue;  /* libjpeg is thread safe */
1795 #else
1796   thread_support=MagickFalse; /* libjpeg is not thread safe */
1797 #endif
1798 
1799   entry=SetMagickInfo("JPEG");
1800   entry->thread_support=thread_support;
1801 #if defined(HasJPEG)
1802   entry->decoder=(DecoderHandler) ReadJPEGImage;
1803   entry->encoder=(EncoderHandler) WriteJPEGImage;
1804 #endif
1805   entry->magick=(MagickHandler) IsJPEG;
1806   entry->adjoin=False;
1807   entry->description=description;
1808 #if defined(HAVE_JPEG_VERSION)
1809     entry->version=version;
1810 #endif
1811   entry->module="JPEG";
1812   entry->coder_class=PrimaryCoderClass;
1813   (void) RegisterMagickInfo(entry);
1814 
1815   entry=SetMagickInfo("JPG");
1816   entry->thread_support=thread_support;
1817 #if defined(HasJPEG)
1818   entry->decoder=(DecoderHandler) ReadJPEGImage;
1819   entry->encoder=(EncoderHandler) WriteJPEGImage;
1820 #endif
1821   entry->adjoin=False;
1822   entry->description=description;
1823 #if defined(HAVE_JPEG_VERSION)
1824     entry->version=version;
1825 #endif
1826   entry->module="JPEG";
1827   entry->coder_class=PrimaryCoderClass;
1828   (void) RegisterMagickInfo(entry);
1829 }
1830 
1831 /*
1832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1833 %                                                                             %
1834 %                                                                             %
1835 %                                                                             %
1836 %   U n r e g i s t e r J P E G I m a g e                                     %
1837 %                                                                             %
1838 %                                                                             %
1839 %                                                                             %
1840 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1841 %
1842 %  Method UnregisterJPEGImage removes format registrations made by the
1843 %  JPEG module from the list of supported formats.
1844 %
1845 %  The format of the UnregisterJPEGImage method is:
1846 %
1847 %      UnregisterJPEGImage(void)
1848 %
1849 */
UnregisterJPEGImage(void)1850 ModuleExport void UnregisterJPEGImage(void)
1851 {
1852   (void) UnregisterMagickInfo("JPEG");
1853   (void) UnregisterMagickInfo("JPG");
1854 }
1855 
1856 #if defined(HasJPEG)
1857 /*
1858 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1859 %                                                                             %
1860 %                                                                             %
1861 %                                                                             %
1862 %  W r i t e J P E G I m a g e                                                %
1863 %                                                                             %
1864 %                                                                             %
1865 %                                                                             %
1866 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1867 %
1868 %  Method WriteJPEGImage writes a JPEG image file and returns it.  It
1869 %  allocates the memory necessary for the new Image structure and returns a
1870 %  pointer to the new image.
1871 %
1872 %  The format of the WriteJPEGImage method is:
1873 %
1874 %      unsigned int WriteJPEGImage(const ImageInfo *image_info,Image *image)
1875 %
1876 %  A description of each parameter follows:
1877 %
1878 %    o status:  Method WriteJPEGImage return True if the image is written.
1879 %      False is returned is there is of a memory shortage or if the image
1880 %      file cannot be opened for writing.
1881 %
1882 %    o image_info: Specifies a pointer to a ImageInfo structure.
1883 %
1884 %    o jpeg_image:  A pointer to an Image structure.
1885 %
1886 %
1887 */
1888 
EmptyOutputBuffer(j_compress_ptr cinfo)1889 static boolean EmptyOutputBuffer(j_compress_ptr cinfo)
1890 {
1891   DestinationManager
1892     *destination;
1893 
1894   destination=(DestinationManager *) cinfo->dest;
1895   destination->manager.free_in_buffer=WriteBlob(destination->image,
1896     MaxBufferExtent,(char *) destination->buffer);
1897   if (destination->manager.free_in_buffer != MaxBufferExtent)
1898     ERREXIT(cinfo,JERR_FILE_WRITE);
1899   destination->manager.next_output_byte=destination->buffer;
1900   return(TRUE);
1901 }
1902 
InitializeDestination(j_compress_ptr cinfo)1903 static void InitializeDestination(j_compress_ptr cinfo)
1904 {
1905   DestinationManager
1906     *destination;
1907 
1908   destination=(DestinationManager *) cinfo->dest;
1909   destination->buffer=(JOCTET *) (*cinfo->mem->alloc_small)
1910     ((j_common_ptr) cinfo,JPOOL_IMAGE,MaxBufferExtent*sizeof(JOCTET));
1911   destination->manager.next_output_byte=destination->buffer;
1912   destination->manager.free_in_buffer=MaxBufferExtent;
1913 }
1914 
TerminateDestination(j_compress_ptr cinfo)1915 static void TerminateDestination(j_compress_ptr cinfo)
1916 {
1917   DestinationManager
1918     *destination;
1919 
1920   destination=(DestinationManager *) cinfo->dest;
1921   if ((MaxBufferExtent-(int) destination->manager.free_in_buffer) > 0)
1922     {
1923       size_t
1924         number_bytes;
1925 
1926       number_bytes=WriteBlob(destination->image,MaxBufferExtent-
1927         destination->manager.free_in_buffer,(char *) destination->buffer);
1928       if (number_bytes != (MaxBufferExtent-destination->manager.free_in_buffer))
1929         ERREXIT(cinfo,JERR_FILE_WRITE);
1930     }
1931 }
1932 
1933 /*
1934   Output generic APPN profile
1935 */
WriteAPPNProfile(j_compress_ptr jpeg_info,const unsigned char * profile,const size_t profile_length,const char * profile_name)1936 static void WriteAPPNProfile(j_compress_ptr jpeg_info,
1937                               const unsigned char *profile,
1938                               const size_t profile_length,
1939                               const char * profile_name)
1940 {
1941   size_t
1942     j;
1943 
1944   int
1945     marker_id;
1946 
1947   marker_id=JPEG_APP0+(int) MagickAtoL(profile_name+3);
1948   for (j=0; j < profile_length; j+=65533L)
1949     jpeg_write_marker(jpeg_info,marker_id,
1950                       profile+j,(int)
1951                       Min(profile_length-j,65533L));
1952 }
1953 
1954 /*
1955   Output EXIF profile
1956 */
WriteEXIFProfile(j_compress_ptr jpeg_info,const unsigned char * profile,const size_t profile_length)1957 static void WriteEXIFProfile(j_compress_ptr jpeg_info,
1958                               const unsigned char *profile,
1959                               const size_t profile_length)
1960 {
1961   size_t
1962     j;
1963 
1964   for (j=0; j < profile_length; j+=65533L)
1965     jpeg_write_marker(jpeg_info,JPEG_APP0+1,
1966                       profile+j,(int)
1967                       Min(profile_length-j,65533L));
1968 }
1969 
1970 /*
1971   Output ICC color profile as a APP marker.
1972 */
WriteICCProfile(j_compress_ptr jpeg_info,const unsigned char * color_profile,const size_t profile_length)1973 static void WriteICCProfile(j_compress_ptr jpeg_info,
1974                             const unsigned char *color_profile,
1975                             const size_t profile_length)
1976 {
1977   register long
1978     i,
1979     j;
1980 
1981   for (i=0; i < (long) profile_length; i+=65519)
1982   {
1983     unsigned char
1984       *profile;
1985 
1986     size_t
1987       length=0;
1988 
1989 
1990     length=Min(profile_length-i,65519);
1991     profile=MagickAllocateResourceLimitedMemory(unsigned char *,length+14);
1992     if (profile == (unsigned char *) NULL)
1993       break;
1994     (void) strcpy((char *) profile,"ICC_PROFILE");
1995     profile[12]=(unsigned char) ((i/65519)+1);
1996     profile[13]=(unsigned char) ((profile_length/65519)+1);
1997     for (j=0; j < (long) length; j++)
1998       profile[j+14]=color_profile[i+j];
1999     jpeg_write_marker(jpeg_info,ICC_MARKER,profile,(unsigned int) length+14);
2000     MagickFreeResourceLimitedMemory(profile);
2001   }
2002 }
2003 
2004 /*
2005   Output binary Photoshop resource data using an APP marker.
2006 */
WriteIPTCProfile(j_compress_ptr jpeg_info,const unsigned char * iptc_profile,const size_t profile_length)2007 static void WriteIPTCProfile(j_compress_ptr jpeg_info,
2008                             const unsigned char *iptc_profile,
2009                             const size_t profile_length)
2010 {
2011   register long
2012     i;
2013 
2014   unsigned long
2015     roundup,
2016     tag_length;
2017 
2018 #ifdef GET_ONLY_IPTC_DATA
2019   tag_length=26;
2020 #else
2021   tag_length=14;
2022 #endif
2023   for (i=0; i < (long) profile_length; i+=65500)
2024   {
2025     size_t
2026       length;
2027 
2028     unsigned char
2029       *profile;
2030 
2031     length=Min(profile_length-i,65500);
2032     roundup=(length & 0x01); /* round up for Photoshop */
2033     profile=MagickAllocateResourceLimitedMemory(unsigned char *,length+roundup+tag_length);
2034     if (profile == (unsigned char *) NULL)
2035       break;
2036 #ifdef GET_ONLY_IPTC_DATA
2037     (void) memcpy(profile,"Photoshop 3.0 8BIM\04\04\0\0\0\0",24);
2038     profile[13]=0x00;
2039     profile[24]=length >> 8;
2040     profile[25]=length & 0xff;
2041 #else
2042     (void) memcpy(profile,"Photoshop 3.0 ",14);
2043     profile[13]=0x00;
2044 #endif
2045     (void) memcpy(&(profile[tag_length]),&(iptc_profile[i]),length);
2046     if (roundup)
2047       profile[length+tag_length]=0;
2048     jpeg_write_marker(jpeg_info,IPTC_MARKER,profile,(unsigned int)
2049       (length+roundup+tag_length));
2050     MagickFreeResourceLimitedMemory(profile);
2051   }
2052 }
2053 
2054 /*
2055   Output Adobe XMP XML profile.
2056 */
WriteXMPProfile(j_compress_ptr jpeg_info,const unsigned char * profile,const size_t profile_length)2057 static void WriteXMPProfile(j_compress_ptr jpeg_info,
2058                             const unsigned char *profile,
2059                             const size_t profile_length)
2060 {
2061   size_t
2062     count,
2063     index,
2064         header_length,
2065         total_length;
2066 
2067   unsigned int
2068         marker_length,
2069         remaining;
2070 
2071   header_length=strlen(xmp_std_header)+1; /* Include terminating null */
2072   total_length=header_length+profile_length;
2073   /* XMP profile must be no larger than range of 'unsigned int' */
2074   remaining=(unsigned int) Min(UINT_MAX,total_length);
2075 
2076   marker_length=Min(remaining,JPEG_MARKER_MAX_SIZE);
2077   jpeg_write_m_header(jpeg_info,XML_MARKER,marker_length);
2078   count=marker_length;
2079   {
2080     for (index=0 ; index < header_length; index++)
2081       {
2082         jpeg_write_m_byte(jpeg_info,xmp_std_header[index]);
2083         --remaining;
2084         --count;
2085       }
2086   }
2087 
2088   for (index=0; remaining > 0; --remaining)
2089     {
2090       if (count == 0)
2091         {
2092           marker_length=Min(remaining,JPEG_MARKER_MAX_SIZE);
2093           jpeg_write_m_header(jpeg_info,XML_MARKER,marker_length);
2094           count=marker_length;
2095         }
2096       jpeg_write_m_byte(jpeg_info,profile[index]);
2097       index++;
2098       count--;
2099     }
2100 }
2101 
2102 /*
2103   Output profiles to JPEG stream.
2104 */
WriteProfiles(j_compress_ptr jpeg_info,Image * image)2105 static void WriteProfiles(j_compress_ptr jpeg_info,Image *image)
2106 {
2107   const char
2108     *profile_name;
2109 
2110   const unsigned char *
2111     profile;
2112 
2113   ImageProfileIterator
2114     profile_iterator;
2115 
2116   size_t
2117     profile_length=0;
2118 
2119   profile_iterator=AllocateImageProfileIterator(image);
2120   while(NextImageProfile(profile_iterator,&profile_name,&profile,
2121                          &profile_length) != MagickFail)
2122     {
2123       if (LocaleNCompare(profile_name,"APP",3) == 0)
2124         {
2125           WriteAPPNProfile(jpeg_info, profile, profile_length, profile_name);
2126         }
2127       else if (LocaleCompare(profile_name,"EXIF") == 0)
2128         {
2129           WriteEXIFProfile(jpeg_info, profile, profile_length);
2130         }
2131       else if ((LocaleCompare(profile_name,"ICM") == 0) ||
2132                (LocaleCompare(profile_name,"ICC") == 0))
2133         {
2134           WriteICCProfile(jpeg_info, profile, profile_length);
2135         }
2136       else if ((LocaleCompare(profile_name,"IPTC") == 0) ||
2137                (LocaleCompare(profile_name,"8BIM") == 0))
2138         {
2139           WriteIPTCProfile(jpeg_info, profile, profile_length);
2140         }
2141       else if (LocaleCompare(profile_name,"XMP") == 0)
2142         {
2143           WriteXMPProfile(jpeg_info, profile, profile_length);
2144         }
2145       else
2146         {
2147           /*
2148             Skip unknown profile type
2149           */
2150           if (image->logging)
2151             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2152                                   "Skipped Profile: %s, %"
2153                                   MAGICK_SIZE_T_F "u bytes",
2154                                   profile_name,
2155                                   (MAGICK_SIZE_T) profile_length);
2156           continue;
2157         }
2158 
2159       if (image->logging)
2160         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2161                               "Wrote Profile: %s, %"
2162                               MAGICK_SIZE_T_F "u bytes",profile_name,
2163                               (MAGICK_SIZE_T) profile_length);
2164     }
2165   DeallocateImageProfileIterator(profile_iterator);
2166 }
2167 
JPEGDestinationManager(j_compress_ptr cinfo,Image * image)2168 static void JPEGDestinationManager(j_compress_ptr cinfo,Image * image)
2169 {
2170   DestinationManager
2171     *destination;
2172 
2173   cinfo->dest=(struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small)
2174     ((j_common_ptr) cinfo,JPOOL_IMAGE,sizeof(DestinationManager));
2175   destination=(DestinationManager *) cinfo->dest;
2176   destination->manager.init_destination=InitializeDestination;
2177   destination->manager.empty_output_buffer=EmptyOutputBuffer;
2178   destination->manager.term_destination=TerminateDestination;
2179   destination->image=image;
2180 }
2181 
2182 /*
2183   Format a libjpeg warning or trace event while encoding.  Warnings
2184   are converted to GraphicsMagick warning exceptions while traces are
2185   optionally logged.
2186 
2187   JPEG message codes range from 0 to JMSG_LASTMSGCODE
2188 */
JPEGEncodeMessageHandler(j_common_ptr jpeg_info,int msg_level)2189 static void JPEGEncodeMessageHandler(j_common_ptr jpeg_info,int msg_level)
2190 {
2191   char
2192     message[JMSG_LENGTH_MAX];
2193 
2194   struct jpeg_error_mgr
2195     *err;
2196 
2197   ErrorManager
2198     *error_manager;
2199 
2200   Image
2201     *image;
2202 
2203   message[0]='\0';
2204   err=jpeg_info->err;
2205   error_manager=(ErrorManager *) jpeg_info->client_data;
2206   image=error_manager->image;
2207   /* msg_level is -1 for warnings, 0 and up for trace messages. */
2208   if (msg_level < 0)
2209     {
2210       unsigned int strikes = 0;
2211       /* A warning */
2212       (err->format_message)(jpeg_info,message);
2213 
2214       if ((err->msg_code >= 0) &&
2215           ((size_t) err->msg_code < ArraySize(error_manager->warning_counts)))
2216         {
2217           error_manager->warning_counts[err->msg_code]++;
2218           strikes=error_manager->warning_counts[err->msg_code];
2219         }
2220 
2221       if (image->logging)
2222         {
2223           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2224                                 "[%s] JPEG Warning[%u]: \"%s\""
2225                                 " (code=%d "
2226                                 "parms=0x%02x,0x%02x,"
2227                                 "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)",
2228                                 image->filename,
2229                                 strikes,
2230                                 message,err->msg_code,
2231                                 err->msg_parm.i[0], err->msg_parm.i[1],
2232                                 err->msg_parm.i[2], err->msg_parm.i[3],
2233                                 err->msg_parm.i[4], err->msg_parm.i[5],
2234                                 err->msg_parm.i[6], err->msg_parm.i[7]);
2235         }
2236       /*
2237       if (strikes > error_manager->max_warning_count)
2238         {
2239           ThrowException2(&image->exception,CorruptImageError,(char *) message,
2240                           image->filename);
2241           longjmp(error_manager->error_recovery,1);
2242         }
2243 
2244       if ((err->num_warnings == 0) ||
2245           (err->trace_level >= 3))
2246         ThrowException2(&image->exception,CorruptImageWarning,message,
2247                         image->filename);
2248       */
2249       /* JWRN_JPEG_EOF - "Premature end of JPEG file" */
2250       err->num_warnings++;
2251       return /* False */;
2252     }
2253   else
2254     {
2255       /* A trace message */
2256       if ((image->logging) && (msg_level >= err->trace_level))
2257         {
2258           (err->format_message)(jpeg_info,message);
2259           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2260                                 "[%s] JPEG Trace: \"%s\"",image->filename,
2261                                 message);
2262         }
2263     }
2264   return /* True */;
2265 }
2266 
2267 
JPEGEncodeProgressMonitor(j_common_ptr cinfo)2268 static void JPEGEncodeProgressMonitor(j_common_ptr cinfo)
2269 {
2270 #if USE_LIBJPEG_PROGRESS
2271   struct jpeg_progress_mgr *p = cinfo->progress;
2272   ErrorManager *error_manager = (ErrorManager *) cinfo->client_data;
2273   Image *image = error_manager->image;
2274 
2275 #if 0
2276   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2277                         "Progress: pass_counter=%ld, pass_limit=%ld,"
2278                         " completed_passes=%d, total_passes=%d, filename=%s",
2279                         p->pass_counter, p->pass_limit,
2280                         p->completed_passes, p->total_passes, image->filename);
2281 #endif
2282 
2283   if (QuantumTick(p->pass_counter,p->pass_limit))
2284     if (!MagickMonitorFormatted(p->pass_counter,p->pass_limit,&image->exception,
2285                                 "[%s] Saving image: %lux%lu (pass %d of %d)...  ",
2286                                 image->filename,
2287                                 image->columns,image->rows,
2288                                 p->completed_passes+1, p->total_passes))
2289       {
2290         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2291                               "Quitting due to progress monitor");
2292         longjmp(error_manager->error_recovery,1);
2293       }
2294 #else
2295   (void) cinfo;
2296 #endif /* USE_LIBJPEG_PROGRESS */
2297 }
2298 
2299 
WriteJPEGImage(const ImageInfo * image_info,Image * imagep)2300 static MagickPassFail WriteJPEGImage(const ImageInfo *image_info,Image *imagep)
2301 {
2302   Image
2303     * volatile imagev = imagep,  /* volatile to avoid "clobber" */
2304     *image;
2305 
2306   ErrorManager
2307     error_manager;
2308 
2309   const ImageAttribute
2310     *attribute;
2311 
2312   JSAMPLE
2313     *jpeg_pixels;
2314 
2315   JSAMPROW
2316     scanline[1];
2317 
2318   char
2319     *sampling_factors,
2320     *preserve_settings;
2321 
2322   const char
2323     *value;
2324 
2325   long
2326     y;
2327 
2328   register const PixelPacket
2329     *p;
2330 
2331   register JSAMPLE
2332     *q;
2333 
2334   register long
2335     i,
2336     x;
2337 
2338   struct jpeg_error_mgr
2339     jpeg_error;
2340 
2341   struct jpeg_progress_mgr
2342     jpeg_progress;
2343 
2344   struct jpeg_compress_struct
2345     jpeg_info;
2346 
2347   MagickPassFail
2348     status;
2349 
2350   unsigned long
2351     input_colorspace;
2352 
2353   unsigned long
2354     quality;
2355 
2356   magick_int64_t
2357     huffman_memory;
2358 
2359   ImageCharacteristics
2360     characteristics;
2361 
2362   /*
2363     Open image file.
2364   */
2365   assert(image_info != (const ImageInfo *) NULL);
2366   assert(image_info->signature == MagickSignature);
2367   assert(imagep != (Image *) NULL);
2368   assert(imagep->signature == MagickSignature);
2369   status=OpenBlob(image_info,imagev,WriteBinaryBlobMode,&imagev->exception);
2370   if (status == False)
2371     ThrowWriterException(FileOpenError,UnableToOpenFile,imagev);
2372 
2373   (void) memset(&error_manager,0,sizeof(error_manager));
2374   (void) memset(&jpeg_progress,0,sizeof(jpeg_progress));
2375   (void) memset(&jpeg_info,0,sizeof(jpeg_info));
2376   (void) memset(&jpeg_error,0,sizeof(jpeg_error));
2377 
2378   /*
2379     Set initial longjmp based error handler.
2380   */
2381   jpeg_info.client_data=(void *) imagev;
2382   jpeg_info.err=jpeg_std_error(&jpeg_error);
2383   jpeg_info.err->emit_message=/*(void (*)(j_common_ptr,int))*/ JPEGEncodeMessageHandler;
2384   jpeg_info.err->error_exit=(void (*)(j_common_ptr)) JPEGErrorHandler;
2385   error_manager.image=imagev;
2386   error_manager.max_warning_count=MaxWarningCount;
2387   /*
2388     Allow the user to set how many warnings of any given type are
2389     allowed before promotion of the warning to a hard error.
2390   */
2391   if ((value=AccessDefinition(image_info,"jpeg","max-warnings")))
2392     error_manager.max_warning_count=strtol(value,(char **) NULL, 10);
2393   jpeg_info.client_data=(void *) &error_manager;
2394   if (setjmp(error_manager.error_recovery))
2395     {
2396       jpeg_destroy_compress(&jpeg_info);
2397       CloseBlob(imagev);
2398       return MagickFail ;
2399     }
2400   image=imagev;  /* Use 'image' after this point for optimization */
2401 
2402   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2403      "  Write JPEG Image: image->orientation = %d",image->orientation);
2404 
2405   /*
2406     Transform image to user-requested colorspace.
2407   */
2408   if (UndefinedColorspace != image_info->colorspace)
2409     {
2410       (void) TransformColorspace(image,image_info->colorspace);
2411     }
2412   /*
2413     Convert RGB-compatible colorspaces (e.g. CineonLog) to RGB by
2414     default.  User can still override it by explicitly specifying the
2415     desired colorspace.
2416   */
2417   else if (IsRGBCompatibleColorspace(image->colorspace) &&
2418            !IsRGBColorspace(image->colorspace))
2419     {
2420       (void) TransformColorspace(image,RGBColorspace);
2421     }
2422 
2423   /*
2424     Analyze image to be written.
2425   */
2426   if (!GetImageCharacteristics(image,&characteristics,
2427                                (OptimizeType == image_info->type),
2428                                &image->exception))
2429     {
2430       CloseBlob(image);
2431       return MagickFail;
2432     }
2433 
2434   jpeg_create_compress(&jpeg_info);
2435   JPEGDestinationManager(&jpeg_info,image);
2436   jpeg_info.image_width=(unsigned int) image->columns;
2437   jpeg_info.image_height=(unsigned int) image->rows;
2438   jpeg_info.input_components=3;
2439   jpeg_info.in_color_space=JCS_RGB;
2440 
2441   /*
2442     Register our progress monitor
2443   */
2444   jpeg_progress.progress_monitor=(void (*)(j_common_ptr)) JPEGEncodeProgressMonitor;
2445   jpeg_info.progress=&jpeg_progress;
2446 
2447   /*
2448     Set JPEG colorspace as per user request.
2449   */
2450   {
2451     MagickBool
2452       colorspace_set=MagickFalse;
2453 
2454     if (IsCMYKColorspace(image_info->colorspace))
2455       {
2456         jpeg_info.input_components=4;
2457         jpeg_info.in_color_space=JCS_CMYK;
2458         colorspace_set=MagickTrue;
2459       }
2460     else if (IsYCbCrColorspace(image_info->colorspace))
2461       {
2462         jpeg_info.input_components=3;
2463         jpeg_info.in_color_space=JCS_YCbCr;
2464         colorspace_set=MagickTrue;
2465       }
2466     else if (IsGrayColorspace(image_info->colorspace))
2467       {
2468         jpeg_info.input_components=1;
2469         jpeg_info.in_color_space=JCS_GRAYSCALE;
2470         colorspace_set=MagickTrue;
2471       }
2472 
2473     if (!colorspace_set)
2474       {
2475         if (IsCMYKColorspace(image->colorspace))
2476           {
2477             jpeg_info.input_components=4;
2478             jpeg_info.in_color_space=JCS_CMYK;
2479           }
2480         else if (IsYCbCrColorspace(image->colorspace))
2481           {
2482             jpeg_info.input_components=3;
2483             jpeg_info.in_color_space=JCS_YCbCr;
2484           }
2485         else if ((IsGrayColorspace(image->colorspace) ||
2486                   (characteristics.grayscale)))
2487           {
2488             jpeg_info.input_components=1;
2489             jpeg_info.in_color_space=JCS_GRAYSCALE;
2490           }
2491         else
2492           {
2493             jpeg_info.input_components=3;
2494             jpeg_info.in_color_space=JCS_RGB;
2495           }
2496       }
2497   }
2498 
2499   input_colorspace=UndefinedColorspace;
2500   quality=image_info->quality;
2501   /* Check for -define jpeg:preserve-settings */
2502   /* ImageMagick:
2503     GetImageOption();
2504   */
2505   /* GraphicsMagick */
2506   preserve_settings=(char *) AccessDefinition(image_info,"jpeg",
2507      "preserve-settings");
2508 
2509   sampling_factors=image_info->sampling_factor;
2510 
2511   if (preserve_settings)
2512     {
2513       if (image->logging)
2514         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2515             "  JPEG:preserve-settings flag is defined.");
2516 
2517       /* Retrieve input file quality */
2518       attribute=GetImageAttribute(image,"JPEG-Quality");
2519       if ((attribute != (const ImageAttribute *) NULL) &&
2520           (attribute->value != (char *) NULL))
2521         {
2522           (void) sscanf(attribute->value,"%lu",&quality);
2523           if (image->logging)
2524             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2525                 "  Input quality=%lu",quality);
2526         }
2527 
2528       /* Retrieve input file colorspace */
2529       attribute=GetImageAttribute(image,"JPEG-Colorspace");
2530       if ((attribute != (const ImageAttribute *) NULL) &&
2531           (attribute->value != (char *) NULL))
2532         {
2533           (void) sscanf(attribute->value,"%lu",&input_colorspace);
2534           if (image->logging)
2535             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2536                 "  Input colorspace=%lu",input_colorspace);
2537         }
2538 
2539       if (input_colorspace == (unsigned long) jpeg_info.in_color_space)
2540         {
2541           /* Retrieve input sampling factors */
2542           attribute=GetImageAttribute(image,"JPEG-Sampling-factors");
2543           if ((attribute != (const ImageAttribute *) NULL) &&
2544               (attribute->value != (char *) NULL))
2545             {
2546               sampling_factors=attribute->value;
2547               if (image->logging)
2548                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2549                     "  Input sampling-factors=%s",sampling_factors);
2550             }
2551         }
2552       else
2553         {
2554           if (image->logging)
2555             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2556                 "  Input colorspace (%lu) != Output colorspace (%d)",
2557                 input_colorspace,jpeg_info.in_color_space);
2558         }
2559     }
2560 
2561   jpeg_set_defaults(&jpeg_info);
2562 
2563   /*
2564     Determine bit depth.
2565   */
2566   {
2567     int
2568       sample_size;
2569 
2570     sample_size=sizeof(JSAMPLE)*8;
2571     if (sample_size > 8)
2572       sample_size=12;
2573     if ((jpeg_info.data_precision != 12) &&
2574         (image->depth <= 8))
2575       sample_size=8;
2576     jpeg_info.data_precision=sample_size;
2577   }
2578   if ((image->x_resolution == 0) || (image->y_resolution == 0))
2579     {
2580       image->x_resolution=72.0;
2581       image->y_resolution=72.0;
2582       image->units=PixelsPerInchResolution;
2583     }
2584   if (image_info->density != (char *) NULL)
2585     {
2586       int
2587         count;
2588 
2589       /* FIXME: density should not be set via image_info->density
2590          but removing this support may break some applications. */
2591       count=GetMagickDimension(image_info->density,&image->x_resolution,
2592         &image->y_resolution,NULL,NULL);
2593       if (count == 1 )
2594         image->y_resolution=image->x_resolution;
2595     }
2596   jpeg_info.density_unit=1;  /* default to DPI */
2597   if (image->logging)
2598     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2599       "Image resolution: %ld,%ld",(long) image->x_resolution,
2600       (long) image->y_resolution);
2601   if ((image->x_resolution != 0) && (image->y_resolution != 0))
2602     {
2603       /*
2604         Set image resolution.
2605       */
2606       jpeg_info.write_JFIF_header=True;
2607       jpeg_info.X_density=(short) image->x_resolution;
2608       jpeg_info.Y_density=(short) image->y_resolution;
2609       if (image->units == PixelsPerInchResolution)
2610         jpeg_info.density_unit=1;
2611       if (image->units == PixelsPerCentimeterResolution)
2612         jpeg_info.density_unit=2;
2613     }
2614 
2615   {
2616     const char
2617       *value;
2618 
2619     /*
2620       Allow the user to select the DCT encoding algorithm.
2621     */
2622     if ((value=AccessDefinition(image_info,"jpeg","dct-method")))
2623       {
2624         if (LocaleCompare(value,"ISLOW") == 0)
2625           jpeg_info.dct_method=JDCT_ISLOW;
2626         else if (LocaleCompare(value,"IFAST") == 0)
2627           jpeg_info.dct_method=JDCT_IFAST;
2628         else if (LocaleCompare(value,"FLOAT") == 0)
2629           jpeg_info.dct_method=JDCT_FLOAT;
2630         else if (LocaleCompare(value,"DEFAULT") == 0)
2631           jpeg_info.dct_method=JDCT_DEFAULT;
2632         else if (LocaleCompare(value,"FASTEST") == 0)
2633           jpeg_info.dct_method=JDCT_FASTEST;
2634       }
2635   }
2636 
2637 {
2638   const char
2639     *value;
2640 
2641   huffman_memory=0;
2642   if ((value=AccessDefinition(image_info,"jpeg","optimize-coding")))
2643     {
2644       if (LocaleCompare(value,"FALSE") == 0)
2645         jpeg_info.optimize_coding=MagickFalse;
2646       else
2647         jpeg_info.optimize_coding=MagickTrue;
2648     }
2649   else
2650     {
2651       /*
2652         Huffman optimization requires that the whole image be buffered in
2653         memory.  Since this is such a large consumer, obtain a memory
2654         resource for the memory to be consumed.  If the memory resource
2655         fails to be acquired, then don't enable huffman optimization.
2656       */
2657       huffman_memory=(magick_int64_t) jpeg_info.input_components*
2658         image->columns*image->rows*sizeof(JSAMPLE);
2659       jpeg_info.optimize_coding=AcquireMagickResource(MemoryResource,
2660                                                       huffman_memory);
2661     }
2662   if (!jpeg_info.optimize_coding)
2663     huffman_memory=0;
2664   if (image->logging)
2665     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2666                           "Huffman optimization is %s",
2667                           (jpeg_info.optimize_coding ? "enabled" : "disabled"));
2668  }
2669 
2670 #if (JPEG_LIB_VERSION >= 61) && defined(C_PROGRESSIVE_SUPPORTED)
2671  if (image_info->interlace == LineInterlace)
2672    jpeg_simple_progression(&jpeg_info);
2673  if (image->logging)
2674    {
2675      if (image_info->interlace == LineInterlace)
2676        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2677                              "Interlace: progressive");
2678      else
2679        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2680                              "Interlace: nonprogressive");
2681    }
2682 #else
2683   if (image->logging)
2684     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2685       "Interlace:  nonprogressive");
2686 #endif
2687   if ((image->compression == LosslessJPEGCompression) ||
2688       (quality > 100))
2689     {
2690 #if defined(C_LOSSLESS_SUPPORTED)
2691       if (quality < 100)
2692         ThrowException(&image->exception,CoderWarning,
2693                        LosslessToLossyJPEGConversion,(char *) NULL);
2694       else
2695         {
2696           int
2697             point_transform,
2698             predictor;
2699 
2700           predictor=quality/100;  /* range 1-7 */
2701           point_transform=quality % 20;  /* range 0-15 */
2702           jpeg_simple_lossless(&jpeg_info,predictor,point_transform);
2703           if (image->logging)
2704             {
2705               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2706                 "Compression: lossless");
2707               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2708                 "Predictor: %d",predictor);
2709               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2710                 "Point Transform: %d",point_transform);
2711             }
2712         }
2713 #else
2714         {
2715           jpeg_set_quality(&jpeg_info,100,True);
2716           if (image->logging)
2717             (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Quality: 100");
2718         }
2719 #endif
2720     }
2721   else
2722     {
2723       jpeg_set_quality(&jpeg_info,(int) quality,True);
2724       if (image->logging)
2725         (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Quality: %lu",
2726           quality);
2727     }
2728   if (sampling_factors != (char *) NULL)
2729     {
2730       double
2731         hs[4]={1.0, 1.0, 1.0, 1.0},
2732         vs[4]={1.0, 1.0, 1.0, 1.0};
2733 
2734       long
2735         count;
2736 
2737       /*
2738         Set sampling factors.
2739       */
2740       count=sscanf(sampling_factors,"%lfx%lf,%lfx%lf,%lfx%lf,%lfx%lf",
2741         &hs[0],&vs[0],&hs[1],&vs[1],&hs[2],&vs[2],&hs[3],&vs[3]);
2742 
2743       if (count%2 == 1)
2744         vs[count/2]=hs[count/2];
2745 
2746       for (i=0; i < 4; i++)
2747       {
2748         jpeg_info.comp_info[i].h_samp_factor=(int) hs[i];
2749         jpeg_info.comp_info[i].v_samp_factor=(int) vs[i];
2750       }
2751       for (; i < MAX_COMPONENTS; i++)
2752       {
2753         jpeg_info.comp_info[i].h_samp_factor=1;
2754         jpeg_info.comp_info[i].v_samp_factor=1;
2755       }
2756     }
2757    else
2758     {
2759       if (quality >= 90)
2760         for (i=0; i < MAX_COMPONENTS; i++)
2761         {
2762           jpeg_info.comp_info[i].h_samp_factor=1;
2763           jpeg_info.comp_info[i].v_samp_factor=1;
2764         }
2765     }
2766 
2767   if (image->logging)
2768     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2769                           "Starting JPEG compression");
2770   jpeg_start_compress(&jpeg_info,True);
2771   if (image->logging)
2772     {
2773       if (image->storage_class == PseudoClass)
2774         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2775           "Storage class: PseudoClass");
2776       else
2777         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2778           "Storage class: DirectClass");
2779       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Depth: %u",
2780         image->depth);
2781       if (image->colors)
2782         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2783           "Number of colors: %u",image->colors);
2784       else
2785         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2786           "Number of colors: unspecified");
2787       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2788         "JPEG data precision: %d",(int) jpeg_info.data_precision);
2789       if (IsCMYKColorspace(image_info->colorspace))
2790         {
2791           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2792                                 "Storage class: DirectClass");
2793           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2794                                 "Colorspace: CMYK");
2795         }
2796       else if (IsYCbCrColorspace(image_info->colorspace))
2797         {
2798           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2799                                 "Colorspace: YCbCr");
2800         }
2801       if (IsCMYKColorspace(image->colorspace))
2802         {
2803           /* A CMYK space */
2804           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2805                                 "Colorspace: CMYK");
2806           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2807                                 "Sampling factors: %dx%d,%dx%d,%dx%d,%dx%d",
2808                                 jpeg_info.comp_info[0].h_samp_factor,
2809                                 jpeg_info.comp_info[0].v_samp_factor,
2810                                 jpeg_info.comp_info[1].h_samp_factor,
2811                                 jpeg_info.comp_info[1].v_samp_factor,
2812                                 jpeg_info.comp_info[2].h_samp_factor,
2813                                 jpeg_info.comp_info[2].v_samp_factor,
2814                                 jpeg_info.comp_info[3].h_samp_factor,
2815                                 jpeg_info.comp_info[3].v_samp_factor);
2816         }
2817       else if (IsGrayColorspace(image->colorspace))
2818         {
2819           /* A gray space */
2820           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2821                                 "Colorspace: GRAY");
2822           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2823                                 "Sampling factors: %dx%d",
2824                                 jpeg_info.comp_info[0].h_samp_factor,
2825                                 jpeg_info.comp_info[0].v_samp_factor);
2826         }
2827       else if (IsRGBCompatibleColorspace(image->colorspace))
2828         {
2829           /* An RGB space */
2830           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2831                                 " Image colorspace is RGB");
2832           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2833                                 "Sampling factors: %dx%d,%dx%d,%dx%d",
2834                                 jpeg_info.comp_info[0].h_samp_factor,
2835                                 jpeg_info.comp_info[0].v_samp_factor,
2836                                 jpeg_info.comp_info[1].h_samp_factor,
2837                                 jpeg_info.comp_info[1].v_samp_factor,
2838                                 jpeg_info.comp_info[2].h_samp_factor,
2839                                 jpeg_info.comp_info[2].v_samp_factor);
2840         }
2841       else if (IsYCbCrColorspace(image->colorspace))
2842         {
2843           /* A YCbCr space */
2844           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2845                                 "Colorspace: YCbCr");
2846           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2847                                 "Sampling factors: %dx%d,%dx%d,%dx%d",
2848                                 jpeg_info.comp_info[0].h_samp_factor,
2849                                 jpeg_info.comp_info[0].v_samp_factor,
2850                                 jpeg_info.comp_info[1].h_samp_factor,
2851                                 jpeg_info.comp_info[1].v_samp_factor,
2852                                 jpeg_info.comp_info[2].h_samp_factor,
2853                                 jpeg_info.comp_info[2].v_samp_factor);
2854         }
2855       else
2856         {
2857           /* Some other color space */
2858           (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Colorspace: %d",
2859                                 image->colorspace);
2860           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2861                                 "Sampling factors: %dx%d,%dx%d,%dx%d,%dx%d",
2862                                 jpeg_info.comp_info[0].h_samp_factor,
2863                                 jpeg_info.comp_info[0].v_samp_factor,
2864                                 jpeg_info.comp_info[1].h_samp_factor,
2865                                 jpeg_info.comp_info[1].v_samp_factor,
2866                                 jpeg_info.comp_info[2].h_samp_factor,
2867                                 jpeg_info.comp_info[2].v_samp_factor,
2868                                 jpeg_info.comp_info[3].h_samp_factor,
2869                                 jpeg_info.comp_info[3].v_samp_factor);
2870         }
2871     }
2872   /*
2873     Write JPEG profiles.
2874   */
2875   attribute=GetImageAttribute(image,"comment");
2876   if ((attribute != (const ImageAttribute *) NULL) &&
2877     (attribute->value != (char *) NULL))
2878     for (i=0; i < (long) strlen(attribute->value); i+=65533L)
2879       jpeg_write_marker(&jpeg_info,JPEG_COM,(unsigned char *) attribute->value+
2880         i,(int) Min(strlen(attribute->value+i),65533L));
2881 #if 0
2882   WriteICCProfile(&jpeg_info,image);
2883   WriteIPTCProfile(&jpeg_info,image);
2884   WriteXMPProfile(&jpeg_info,image);
2885 #endif
2886   WriteProfiles(&jpeg_info,image);
2887   /*
2888     Convert MIFF to JPEG raster pixels.
2889   */
2890   jpeg_pixels=MagickAllocateResourceLimitedArray(JSAMPLE *,
2891     jpeg_info.input_components*image->columns,sizeof(JSAMPLE));
2892   if (jpeg_pixels == (JSAMPLE *) NULL)
2893     {
2894       if (huffman_memory)
2895         LiberateMagickResource(MemoryResource,huffman_memory);
2896       ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
2897     }
2898   scanline[0]=(JSAMPROW) jpeg_pixels;
2899   if (jpeg_info.data_precision > 8)
2900     {
2901       unsigned int
2902         scale_short;
2903 
2904       scale_short=65535U/MaxValueGivenBits(jpeg_info.data_precision);
2905 
2906       if (jpeg_info.in_color_space == JCS_GRAYSCALE)
2907         {
2908           if (image->logging)
2909             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2910                                   "Writing %d bit JCS_GRAYSCALE samples",
2911                                   jpeg_info.data_precision);
2912           for (y=0; y < (long) image->rows; y++)
2913             {
2914               p=AcquireImagePixels(image,0,y,image->columns,1,
2915                                    &image->exception);
2916               if (p == (const PixelPacket *) NULL)
2917                 break;
2918               q=jpeg_pixels;
2919               if (image->is_grayscale)
2920                 {
2921                   for (x=0; x < (long) image->columns; x++)
2922                     {
2923                       *q++=(JSAMPLE) (ScaleQuantumToShort(GetGraySample(p))/
2924                                       scale_short);
2925                       p++;
2926                     }
2927                 }
2928               else
2929                 {
2930                   for (x=0; x < (long) image->columns; x++)
2931                     {
2932                       *q++=(JSAMPLE)
2933                         (ScaleQuantumToShort(PixelIntensityToQuantum(p))/scale_short);
2934                       p++;
2935                     }
2936                 }
2937               (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2938 #if !USE_LIBJPEG_PROGRESS
2939               if (QuantumTick(y,image->rows))
2940                 if (!MagickMonitorFormatted(y,image->rows,&image->exception,
2941                                             SaveImageText,image->filename,
2942                                             image->columns,image->rows))
2943                   break;
2944 #endif /* !USE_LIBJPEG_PROGRESS */
2945             }
2946         }
2947       else
2948         if ((jpeg_info.in_color_space == JCS_RGB) ||
2949             (jpeg_info.in_color_space == JCS_YCbCr))
2950           {
2951             if (image->logging)
2952               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2953                                     "Writing %d bit JCS_RGB or "
2954                                     "JCS_YCbCr samples",
2955                                     jpeg_info.data_precision);
2956             for (y=0; y < (long) image->rows; y++)
2957               {
2958                 p=AcquireImagePixels(image,0,y,image->columns,1,
2959                                      &image->exception);
2960                 if (p == (const PixelPacket *) NULL)
2961                   break;
2962                 q=jpeg_pixels;
2963                 for (x=0; x < (long) image->columns; x++)
2964                   {
2965                     *q++=(JSAMPLE) (ScaleQuantumToShort(p->red)/16);
2966                     *q++=(JSAMPLE) (ScaleQuantumToShort(p->green)/16);
2967                     *q++=(JSAMPLE) (ScaleQuantumToShort(p->blue)/16);
2968                     p++;
2969                   }
2970                 (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
2971 #if !USE_LIBJPEG_PROGRESS
2972                 if (QuantumTick(y,image->rows))
2973                   if (!MagickMonitorFormatted(y,image->rows,&image->exception,
2974                                               SaveImageText,image->filename,
2975                                               image->columns,image->rows))
2976                     break;
2977 #endif /* !USE_LIBJPEG_PROGRESS */
2978               }
2979           }
2980         else
2981           {
2982             if (image->logging)
2983               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
2984                                     "Writing %d bit JCS_CMYK samples",
2985                                     jpeg_info.data_precision);
2986             for (y=0; y < (long) image->rows; y++)
2987               {
2988                 p=AcquireImagePixels(image,0,y,image->columns,1,
2989                                      &image->exception);
2990                 if (p == (const PixelPacket *) NULL)
2991                   break;
2992                 q=jpeg_pixels;
2993                 for (x=0; x < (long) image->columns; x++)
2994                   {
2995                     /*
2996                       Convert DirectClass packets to contiguous CMYK scanlines.
2997                     */
2998                     *q++=(JSAMPLE) (4095-ScaleQuantumToShort(p->red)/16);
2999                     *q++=(JSAMPLE) (4095-ScaleQuantumToShort(p->green)/16);
3000                     *q++=(JSAMPLE) (4095-ScaleQuantumToShort(p->blue)/16);
3001                     *q++=(JSAMPLE) (4095-ScaleQuantumToShort(p->opacity)/16);
3002                     p++;
3003                   }
3004                 (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
3005 #if !USE_LIBJPEG_PROGRESS
3006                 if (QuantumTick(y,image->rows))
3007                   if (!MagickMonitorFormatted(y,image->rows,&image->exception,
3008                                               SaveImageText,image->filename,
3009                                               image->columns,image->rows))
3010                     break;
3011 #endif /* !USE_LIBJPEG_PROGRESS */
3012               }
3013           }
3014     }
3015   else
3016     if (jpeg_info.in_color_space == JCS_GRAYSCALE)
3017       {
3018         if (image->logging)
3019           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3020                                 "Writing %d bit JCS_GRAYSCALE samples",
3021                                 jpeg_info.data_precision);
3022         for (y=0; y < (long) image->rows; y++)
3023           {
3024             p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
3025             if (p == (const PixelPacket *) NULL)
3026               break;
3027             q=jpeg_pixels;
3028             if (image->is_grayscale)
3029                 {
3030                   for (x=0; x < (long) image->columns; x++)
3031                   {
3032                     *q++=(JSAMPLE) ScaleQuantumToChar(GetGraySample(p));
3033                     p++;
3034                   }
3035                 }
3036             else
3037               {
3038                 for (x=0; x < (long) image->columns; x++)
3039                   {
3040                     *q++=(JSAMPLE)
3041                       ScaleQuantumToChar(PixelIntensityToQuantum(p));
3042                     p++;
3043                   }
3044               }
3045             (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
3046 #if !USE_LIBJPEG_PROGRESS
3047             if (QuantumTick(y,image->rows))
3048               if (!MagickMonitorFormatted(y,image->rows,&image->exception,
3049                                           SaveImageText,image->filename,
3050                                           image->columns,image->rows))
3051                 break;
3052 #endif /* !USE_LIBJPEG_PROGRESS */
3053           }
3054       }
3055     else
3056       if ((jpeg_info.in_color_space == JCS_RGB) ||
3057           (jpeg_info.in_color_space == JCS_YCbCr))
3058         {
3059           if (image->logging)
3060             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3061                                   "Writing %d bit JCS_RGB or JCS_YCbCr samples",
3062                                   jpeg_info.data_precision);
3063           for (y=0; y < (long) image->rows; y++)
3064             {
3065               p=AcquireImagePixels(image,0,y,image->columns,1,
3066                                    &image->exception);
3067               if (p == (const PixelPacket *) NULL)
3068                 break;
3069               q=jpeg_pixels;
3070               for (x=0; x < (long) image->columns; x++)
3071                 {
3072                   *q++=(JSAMPLE) ScaleQuantumToChar(p->red);
3073                   *q++=(JSAMPLE) ScaleQuantumToChar(p->green);
3074                   *q++=(JSAMPLE) ScaleQuantumToChar(p->blue);
3075                   p++;
3076                 }
3077               (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
3078 #if !USE_LIBJPEG_PROGRESS
3079               if (QuantumTick(y,image->rows))
3080                 if (!MagickMonitorFormatted(y,image->rows,&image->exception,
3081                                             SaveImageText,image->filename,
3082                                             image->columns,image->rows))
3083                   break;
3084 #endif /* !USE_LIBJPEG_PROGRESS */
3085             }
3086         }
3087       else
3088         {
3089           if (image->logging)
3090             (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3091                                   "Writing %d bit JCS_CMYK samples",
3092                                   jpeg_info.data_precision);
3093           for (y=0; y < (long) image->rows; y++)
3094             {
3095               p=AcquireImagePixels(image,0,y,image->columns,1,
3096                                    &image->exception);
3097               if (p == (const PixelPacket *) NULL)
3098                 break;
3099               q=jpeg_pixels;
3100               for (x=0; x < (long) image->columns; x++)
3101                 {
3102                   /*
3103                     Convert DirectClass packets to contiguous CMYK scanlines.
3104                   */
3105                   *q++=(JSAMPLE) (ScaleQuantumToChar(MaxRGB-p->red));
3106                   *q++=(JSAMPLE) (ScaleQuantumToChar(MaxRGB-p->green));
3107                   *q++=(JSAMPLE) (ScaleQuantumToChar(MaxRGB-p->blue));
3108                   *q++=(JSAMPLE) (ScaleQuantumToChar(MaxRGB-p->opacity));
3109                   p++;
3110                 }
3111               (void) jpeg_write_scanlines(&jpeg_info,scanline,1);
3112 #if !USE_LIBJPEG_PROGRESS
3113               if (QuantumTick(y,image->rows))
3114                 if (!MagickMonitorFormatted(y,image->rows,&image->exception,
3115                                             SaveImageText,image->filename,
3116                                             image->columns,image->rows))
3117                   break;
3118 #endif /* !USE_LIBJPEG_PROGRESS */
3119             }
3120         }
3121   if (image->logging)
3122     (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3123                           "Finishing JPEG compression");
3124   jpeg_finish_compress(&jpeg_info);
3125   /*
3126     Free memory.
3127   */
3128   if (huffman_memory)
3129     LiberateMagickResource(MemoryResource,huffman_memory);
3130   jpeg_destroy_compress(&jpeg_info);
3131   MagickFreeResourceLimitedMemory(jpeg_pixels);
3132   CloseBlob(image);
3133   return(True);
3134 }
3135 #endif
3136