root / ImageMagick / trunk / coders / jpeg.c

Revision 12601, 68.1 kB (checked in by cristy, 6 days ago)
Line 
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%                        JJJJJ  PPPP   EEEEE   GGGG                           %
7%                          J    P   P  E      G                               %
8%                          J    PPPP   EEE    G  GG                           %
9%                        J J    P      E      G   G                           %
10%                        JJJ    P      EEEEE   GGG                            %
11%                                                                             %
12%                                                                             %
13%                       Read/Write JPEG Image Format.                         %
14%                                                                             %
15%                              Software Design                                %
16%                                John Cristy                                  %
17%                                 July 1992                                   %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2008 ImageMagick Studio LLC, a non-profit organization      %
21%  dedicated to making software imaging solutions freely available.           %
22%                                                                             %
23%  You may not use this file except in compliance with the License.  You may  %
24%  obtain a copy of the License at                                            %
25%                                                                             %
26%    http://www.imagemagick.org/script/license.php                            %
27%                                                                             %
28%  Unless required by applicable law or agreed to in writing, software        %
29%  distributed under the License is distributed on an "AS IS" BASIS,          %
30%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31%  See the License for the specific language governing permissions and        %
32%  limitations under the License.                                             %
33%                                                                             %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36% This software is based in part on the work of the Independent JPEG Group.
37% See ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz for copyright and
38% licensing restrictions.  Blob support contributed by Glenn Randers-Pehrson.
39%
40%
41*/
42
43/*
44  Include declarations.
45*/
46#include "magick/studio.h"
47#include "magick/blob.h"
48#include "magick/blob-private.h"
49#include "magick/color.h"
50#include "magick/color-private.h"
51#include "magick/colorspace.h"
52#include "magick/constitute.h"
53#include "magick/exception.h"
54#include "magick/exception-private.h"
55#include "magick/geometry.h"
56#include "magick/image.h"
57#include "magick/image-private.h"
58#include "magick/list.h"
59#include "magick/log.h"
60#include "magick/magick.h"
61#include "magick/memory_.h"
62#include "magick/monitor.h"
63#include "magick/monitor-private.h"
64#include "magick/option.h"
65#include "magick/profile.h"
66#include "magick/property.h"
67#include "magick/quantum-private.h"
68#include "magick/resource_.h"
69#include "magick/splay-tree.h"
70#include "magick/static.h"
71#include "magick/string_.h"
72#include "magick/module.h"
73#include "magick/utility.h"
74#include <setjmp.h>
75#if defined(MAGICKCORE_JPEG_DELEGATE)
76#define JPEG_INTERNAL_OPTIONS
77#if defined(__MINGW32__)
78# define XMD_H 1  /* Avoid conflicting typedef for INT32 */
79#endif
80#undef HAVE_STDLIB_H
81#include "jpeglib.h"
82#include "jerror.h"
83#endif
84
85/*
86  Define declarations.
87*/
88#define ICC_MARKER  (JPEG_APP0+2)
89#define ICC_PROFILE  "ICC_PROFILE"
90#define IPTC_MARKER  (JPEG_APP0+13)
91#define XML_MARKER  (JPEG_APP0+1)
92#define MaxBufferExtent  8192
93
94/*
95  Typedef declarations.
96*/
97#if defined(MAGICKCORE_JPEG_DELEGATE)
98typedef struct _DestinationManager
99{
100  struct jpeg_destination_mgr
101    manager;
102
103  Image
104    *image;
105
106  JOCTET
107    *buffer;
108} DestinationManager;
109
110typedef struct _ErrorManager
111{
112  Image
113    *image;
114
115  jmp_buf
116    error_recovery;
117} ErrorManager;
118
119typedef struct _SourceManager
120{
121  struct jpeg_source_mgr
122    manager;
123
124  Image
125    *image;
126
127  JOCTET
128    *buffer;
129
130  boolean
131    start_of_blob;
132} SourceManager;
133#endif
134
135/*
136  Forward declarations.
137*/
138#if defined(MAGICKCORE_JPEG_DELEGATE)
139static MagickBooleanType
140  WriteJPEGImage(const ImageInfo *,Image *);
141#endif
142
143/*
144%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
145%                                                                             %
146%                                                                             %
147%                                                                             %
148%   I s J P E G                                                               %
149%                                                                             %
150%                                                                             %
151%                                                                             %
152%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
153%
154%  IsJPEG() returns MagickTrue if the image format type, identified by the
155%  magick string, is JPEG.
156%
157%  The format of the IsJPEG  method is:
158%
159%      MagickBooleanType IsJPEG(const unsigned char *magick,const size_t length)
160%
161%  A description of each parameter follows:
162%
163%    o magick: This string is generally the first few bytes of an image file
164%      or blob.
165%
166%    o length: Specifies the length of the magick string.
167%
168*/
169static MagickBooleanType IsJPEG(const unsigned char *magick,const size_t length)
170{
171  if (length < 3)
172    return(MagickFalse);
173  if (memcmp(magick,"\377\330\377",3) == 0)
174    return(MagickTrue);
175  return(MagickFalse);
176}
177
178#if defined(MAGICKCORE_JPEG_DELEGATE)
179/*
180%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
181%                                                                             %
182%                                                                             %
183%                                                                             %
184%   R e a d J P E G I m a g e                                                 %
185%                                                                             %
186%                                                                             %
187%                                                                             %
188%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
189%
190%  ReadJPEGImage() reads a JPEG image file and returns it.  It allocates
191%  the memory necessary for the new Image structure and returns a pointer to
192%  the new image.
193%
194%  The format of the ReadJPEGImage method is:
195%
196%      Image *ReadJPEGImage(const ImageInfo *image_info,
197%        ExceptionInfo *exception)
198%
199%  A description of each parameter follows:
200%
201%    o image_info: the image info.
202%
203%    o exception: return any errors or warnings in this structure.
204%
205*/
206
207static MagickBooleanType EmitMessage(j_common_ptr jpeg_info,int level)
208{
209  char
210    message[JMSG_LENGTH_MAX];
211
212  ErrorManager
213    *error_manager;
214
215  Image
216    *image;
217
218  (jpeg_info->err->format_message)(jpeg_info,message);
219  error_manager=(ErrorManager *) jpeg_info->client_data;
220  image=error_manager->image;
221  if (level < 0)
222    {
223      if ((jpeg_info->err->num_warnings == 0) ||
224          (jpeg_info->err->trace_level >= 3))
225        ThrowBinaryException(CorruptImageWarning,(char *) message,
226          image->filename);
227      jpeg_info->err->num_warnings++;
228    }
229  else
230    if (jpeg_info->err->trace_level >= level)
231      ThrowBinaryException(CoderError,(char *) message,image->filename);
232  return(MagickTrue);
233}
234
235static boolean FillInputBuffer(j_decompress_ptr cinfo)
236{
237  SourceManager
238    *source;
239
240  source=(SourceManager *) cinfo->src;
241  source->manager.bytes_in_buffer=(size_t)
242    ReadBlob(source->image,MaxBufferExtent,source->buffer);
243  if (source->manager.bytes_in_buffer == 0)
244    {
245      if (source->start_of_blob != 0)
246        ERREXIT(cinfo,JERR_INPUT_EMPTY);
247      WARNMS(cinfo,JWRN_JPEG_EOF);
248      source->buffer[0]=(JOCTET) 0xff;
249      source->buffer[1]=(JOCTET) JPEG_EOI;
250      source->manager.bytes_in_buffer=2;
251    }
252  source->manager.next_input_byte=source->buffer;
253  source->start_of_blob=FALSE;
254  return(TRUE);
255}
256
257static int GetCharacter(j_decompress_ptr jpeg_info)
258{
259  if (jpeg_info->src->bytes_in_buffer == 0)
260    (void) (*jpeg_info->src->fill_input_buffer)(jpeg_info);
261  jpeg_info->src->bytes_in_buffer--;
262  return((int) GETJOCTET(*jpeg_info->src->next_input_byte++));
263}
264
265static void InitializeSource(j_decompress_ptr cinfo)
266{
267  SourceManager
268    *source;
269
270  source=(SourceManager *) cinfo->src;
271  source->start_of_blob=TRUE;
272}
273
274static void JPEGErrorHandler(j_common_ptr jpeg_info)
275{
276  ErrorManager
277    *error_manager;
278
279  (void) EmitMessage(jpeg_info,0);
280  error_manager=(ErrorManager *) jpeg_info->client_data;
281  longjmp(error_manager->error_recovery,1);
282}
283
284static boolean ReadComment(j_decompress_ptr jpeg_info)
285{
286  char
287    *comment;
288
289  ErrorManager
290    *error_manager;
291
292  Image
293    *image;
294
295  register char
296    *p;
297
298  register long
299    i;
300
301  size_t
302    length;
303
304  /*
305    Determine length of comment.
306  */
307  error_manager=(ErrorManager *) jpeg_info->client_data;
308  image=error_manager->image;
309  length=(size_t) ((unsigned long) GetCharacter(jpeg_info) << 8);
310  length+=GetCharacter(jpeg_info);
311  length-=2;
312  if (length <= 0)
313    return(MagickTrue);
314  comment=(char *) NULL;
315  if (~length >= MaxTextExtent)
316    comment=(char *) AcquireQuantumMemory(length+MaxTextExtent,
317      sizeof(*comment));
318  if (comment == (char *) NULL)
319    ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
320      image->filename);
321  /*
322    Read comment.
323  */
324  i=(long) length-1;
325  for (p=comment; i-- >= 0; p++)
326    *p=(char) GetCharacter(jpeg_info);
327  *p='\0';
328  (void) SetImageProperty(image,"comment",comment);
329  comment=DestroyString(comment);
330  return(MagickTrue);
331}
332
333static boolean ReadICCProfile(j_decompress_ptr jpeg_info)
334{
335  char
336    magick[12];
337
338  ErrorManager
339    *error_manager;
340
341  Image
342    *image;
343
344  MagickBooleanType
345    status;
346
347  register long
348    i;
349
350  register unsigned char
351    *p;
352
353  size_t
354    length;
355
356  StringInfo
357    *icc_profile,
358    *profile;
359
360  /*
361    Read color profile.
362  */
363  length=(size_t) ((unsigned long) GetCharacter(jpeg_info) << 8);
364  length+=(size_t) GetCharacter(jpeg_info);
365  length-=2;
366  if (length <= 14)
367    {
368      while (length-- > 0)
369        (void) GetCharacter(jpeg_info);
370      return(MagickTrue);
371    }
372  for (i=0; i < 12; i++)
373    magick[i]=(char) GetCharacter(jpeg_info);
374  if (LocaleCompare(magick,ICC_PROFILE) != 0)
375    {
376      /*
377        Not a ICC profile, return.
378      */
379      for (i=0; i < (long) (length-12); i++)
380        (void) GetCharacter(jpeg_info);
381      return(MagickTrue);
382    }
383  (void) GetCharacter(jpeg_info);  /* id */
384  (void) GetCharacter(jpeg_info);  /* markers */
385  length-=14;
386  error_manager=(ErrorManager *) jpeg_info->client_data;
387  image=error_manager->image;
388  profile=AcquireStringInfo(length);
389  if (profile == (StringInfo *) NULL)
390    ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
391      image->filename);
392  p=GetStringInfoDatum(profile);
393  for (i=(long) GetStringInfoLength(profile)-1; i >= 0; i--)
394    *p++=(unsigned char) GetCharacter(jpeg_info);
395  icc_profile=(StringInfo *) GetImageProfile(image,"icc");
396  if (icc_profile != (StringInfo *) NULL)
397    {
398      ConcatenateStringInfo(icc_profile,profile);
399      profile=DestroyStringInfo(profile);
400    }
401  else
402    {
403      status=SetImageProfile(image,"icc",profile);
404      profile=DestroyStringInfo(profile);
405      if (status == MagickFalse)
406        ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
407          image->filename);
408    }
409  if (image->debug != MagickFalse)
410    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
411      "Profile: ICC, %lu bytes",(unsigned long) length);
412  return(MagickTrue);
413}
414
415static boolean ReadIPTCProfile(j_decompress_ptr jpeg_info)
416{
417  char
418    magick[MaxTextExtent];
419
420  ErrorManager
421    *error_manager;
422
423  Image
424    *image;
425
426  MagickBooleanType
427    status;
428
429  register long
430    i;
431
432  register unsigned char
433    *p;
434
435  size_t
436    length;
437
438  StringInfo
439    *iptc_profile,
440    *profile;
441
442  /*
443    Determine length of binary data stored here.
444  */
445  length=(size_t) ((unsigned long) GetCharacter(jpeg_info) << 8);
446  length+=(size_t) GetCharacter(jpeg_info);
447  length-=2;
448  if (length <= 14)
449    {
450      while (length-- > 0)
451        (void) GetCharacter(jpeg_info);
452      return(MagickTrue);
453    }
454  /*
455    Validate that this was written as a Photoshop resource format slug.
456  */
457  for (i=0; i < 10; i++)
458    magick[i]=(char) GetCharacter(jpeg_info);
459  magick[10]='\0';
460  if (length <= 10)
461    return(MagickTrue);
462  length-=10;
463  if (LocaleCompare(magick,"Photoshop ") != 0)
464    {
465      /*
466        Not a IPTC profile, return.
467      */
468      for (i=0; i < (long) length; i++)
469        (void) GetCharacter(jpeg_info);
470      return(MagickTrue);
471    }
472  /*
473    Remove the version number.
474  */
475  for (i=0; i < 4; i++)
476    (void) GetCharacter(jpeg_info);
477  if (length <= 4)
478    return(MagickTrue);
479  length-=4;
480  if (length == 0)
481    return(MagickTrue);
482  error_manager=(ErrorManager *) jpeg_info->client_data;
483  image=error_manager->image;
484  profile=AcquireStringInfo(length);
485  if (profile == (StringInfo *) NULL)
486    ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
487      image->filename);
488  p=GetStringInfoDatum(profile);
489  for (i=(long) GetStringInfoLength(profile)-1; i >= 0; i--)
490    *p++=(unsigned char) GetCharacter(jpeg_info);
491  iptc_profile=(StringInfo *) GetImageProfile(image,"8bim");
492  if (iptc_profile != (StringInfo *) NULL)
493    {
494      ConcatenateStringInfo(iptc_profile,profile);
495      profile=DestroyStringInfo(profile);
496    }
497  else
498    {
499      status=SetImageProfile(image,"8bim",profile);
500      profile=DestroyStringInfo(profile);
501      if (status == MagickFalse)
502        ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
503          image->filename);
504    }
505  if (image->debug != MagickFalse)
506    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
507      "Profile: iptc, %lu bytes",(unsigned long) length);
508  return(MagickTrue);
509}
510
511static boolean ReadProfile(j_decompress_ptr jpeg_info)
512{
513  char
514    name[MaxTextExtent];
515
516  ErrorManager
517    *error_manager;
518
519  Image
520    *image;
521
522  int
523    marker;
524
525  MagickBooleanType
526    status;
527
528  register long
529    i;
530
531  register unsigned char
532    *p;
533
534  size_t
535    length;
536
537  StringInfo
538    *profile;
539
540  /*
541    Read generic profile.
542  */
543  length=(size_t) ((unsigned long) GetCharacter(jpeg_info) << 8);
544  length+=(size_t) GetCharacter(jpeg_info);
545  if (length <= 2)
546    return(MagickTrue);
547  length-=2;
548  marker=jpeg_info->unread_marker-JPEG_APP0;
549  (void) FormatMagickString(name,MaxTextExtent,"APP%d",marker);
550  error_manager=(ErrorManager *) jpeg_info->client_data;
551  image=error_manager->image;
552  profile=AcquireStringInfo(length);
553  if (profile == (StringInfo *) NULL)
554    ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
555      image->filename);
556  p=GetStringInfoDatum(profile);
557  for (i=(long) GetStringInfoLength(profile)-1; i >= 0; i--)
558    *p++=(unsigned char) GetCharacter(jpeg_info);
559  if (marker == 1)
560    {
561      p=GetStringInfoDatum(profile);
562      if ((length > 4) && (LocaleNCompare((char *) p,"exif",4) == 0))
563        (void) CopyMagickString(name,"exif",MaxTextExtent);
564      if ((length > 5) && (LocaleNCompare((char *) p,"http:",5) == 0))
565        {
566          ssize_t
567            i;
568
569          /*
570            Extract namespace from XMP profile.
571          */
572          p=GetStringInfoDatum(profile);
573          for (i=0; i < (long) GetStringInfoLength(profile); i++)
574          {
575            if (*p == '\0')
576              break;
577            p++;
578          }
579          if (*p == '\0')
580            DestroyStringInfo(SplitStringInfo(profile,i+1));
581          (void) CopyMagickString(name,"xmp",MaxTextExtent);
582        }
583    }
584  status=SetImageProfile(image,name,profile);
585  profile=DestroyStringInfo(profile);
586  if (status == MagickFalse)
587    ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
588      image->filename);
589  if (image->debug != MagickFalse)
590    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
591      "Profile: %s, %lu bytes",name,(unsigned long) length);
592  return(MagickTrue);
593}
594
595static void SkipInputData(j_decompress_ptr cinfo,long number_bytes)
596{
597  SourceManager
598    *source;
599
600  if (number_bytes <= 0)
601    return;
602  source=(SourceManager *) cinfo->src;
603  while (number_bytes > (long) source->manager.bytes_in_buffer)
604  {
605    number_bytes-=(long) source->manager.bytes_in_buffer;
606    (void) FillInputBuffer(cinfo);
607  }
608  source->manager.next_input_byte+=(size_t) number_bytes;
609  source->manager.bytes_in_buffer-=(size_t) number_bytes;
610}
611
612static void TerminateSource(j_decompress_ptr cinfo)
613{
614  cinfo=cinfo;
615}
616
617static void JPEGSourceManager(j_decompress_ptr cinfo,Image *image)
618{
619  SourceManager
620    *source;
621
622  cinfo->src=(struct jpeg_source_mgr *) (*cinfo->mem->alloc_small)
623    ((j_common_ptr) cinfo,JPOOL_IMAGE,sizeof(SourceManager));
624  source=(SourceManager *) cinfo->src;
625  source->buffer=(JOCTET *) (*cinfo->mem->alloc_small)
626    ((j_common_ptr) cinfo,JPOOL_IMAGE,MaxBufferExtent*sizeof(JOCTET));
627  source=(SourceManager *) cinfo->src;
628  source->manager.init_source=InitializeSource;
629  source->manager.fill_input_buffer=FillInputBuffer;
630  source->manager.skip_input_data=SkipInputData;
631  source->manager.resync_to_restart=jpeg_resync_to_restart;
632  source->manager.term_source=TerminateSource;
633  source->manager.bytes_in_buffer=0;
634  source->manager.next_input_byte=NULL;
635  source->image=image;
636}
637
638static Image *ReadJPEGImage(const ImageInfo *image_info,
639  ExceptionInfo *exception)
640{
641  char
642    sampling_factor[MaxTextExtent],
643    value[MaxTextExtent];
644
645  ErrorManager
646    error_manager;
647
648  IndexPacket
649    index;
650
651  Image
652    *image;
653
654  long
655    x,
656    y;
657
658  JSAMPLE
659    *jpeg_pixels;
660
661  JSAMPROW
662    scanline[1];
663
664  MagickBooleanType
665    debug,
666    status;
667
668  MagickSizeType
669    number_pixels;
670
671  register IndexPacket
672    *indexes;
673
674  register long
675    i;
676
677  struct jpeg_decompress_struct
678    jpeg_info;
679
680  struct jpeg_error_mgr
681    jpeg_error;
682
683  register JSAMPLE
684    *p;
685
686  register PixelPacket
687    *q;
688
689  unsigned long
690    precision,
691    units;
692
693  /*
694    Open image file.
695  */
696  assert(image_info != (const ImageInfo *) NULL);
697  assert(image_info->signature == MagickSignature);
698  if (image_info->debug != MagickFalse)
699    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
700      image_info->filename);
701  assert(exception != (ExceptionInfo *) NULL);
702  assert(exception->signature == MagickSignature);
703  debug=IsEventLogging();
704  image=AcquireImage(image_info);
705  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
706  if (status == MagickFalse)
707    {
708      image=DestroyImageList(image);
709      return((Image *) NULL);
710    }
711  /*
712    Initialize JPEG parameters.
713  */
714  (void) ResetMagickMemory(&jpeg_info,0,sizeof(jpeg_info));
715  (void) ResetMagickMemory(&jpeg_error,0,sizeof(jpeg_error));
716  jpeg_info.err=jpeg_std_error(&jpeg_error);
717  jpeg_info.err->emit_message=(void (*)(j_common_ptr,int)) EmitMessage;
718  jpeg_info.err->error_exit=(void (*)(j_common_ptr)) JPEGErrorHandler;
719  jpeg_pixels=(JSAMPLE *) NULL;
720  error_manager.image=image;
721  if (setjmp(error_manager.error_recovery) != 0)
722    {
723      jpeg_destroy_decompress(&jpeg_info);
724      InheritException(exception,&image->exception);
725      (void) CloseBlob(image);
726      number_pixels=(MagickSizeType) image->columns*image->rows;
727      if (number_pixels != 0)
728        return(GetFirstImageInList(image));
729      image=DestroyImage(image);
730      return(image);
731    }
732  jpeg_info.client_data=(void *) &error_manager;
733  jpeg_create_decompress(&jpeg_info);
734  JPEGSourceManager(&jpeg_info,image);
735  jpeg_set_marker_processor(&jpeg_info,JPEG_COM,ReadComment);
736  jpeg_set_marker_processor(&jpeg_info,ICC_MARKER,ReadICCProfile);
737  jpeg_set_marker_processor(&jpeg_info,IPTC_MARKER,ReadIPTCProfile);
738  for (i=1; i < 16; i++)
739    if ((i != 2) && (i != 13) && (i != 14))
740      jpeg_set_marker_processor(&jpeg_info,(int) (JPEG_APP0+i),ReadProfile);
741  i=jpeg_read_header(&jpeg_info,MagickTrue);
742  if ((image->colorspace == YCbCrColorspace) ||
743      (image->colorspace == Rec601YCbCrColorspace) ||
744      (image->colorspace == Rec709YCbCrColorspace))
745    {
746      jpeg_info.out_color_space=JCS_YCbCr;
747      image->colorspace=YCbCrColorspace;
748    }
749  if (jpeg_info.out_color_space == JCS_CMYK)
750    image->colorspace=CMYKColorspace;
751  /*
752    Set image resolution.
753  */
754  units=0;
755  if ((jpeg_info.saw_JFIF_marker != 0) && (jpeg_info.X_density != 1) &&
756      (jpeg_info.Y_density != 1))
757    {
758      image->x_resolution=(double) jpeg_info.X_density;
759      image->y_resolution=(double) jpeg_info.Y_density;
760      units=(unsigned long) jpeg_info.density_unit;
761    }
762  if (units == 1)
763    image->units=PixelsPerInchResolution;
764  if (units == 2)
765    image->units=PixelsPerCentimeterResolution;
766  number_pixels=(MagickSizeType) image->columns*image->rows;
767  if (image_info->size != (char *) NULL)
768    {
769      double
770        scale_factor;
771
772      /*
773        Let the JPEG library subsample for us.
774      */
775      jpeg_calc_output_dimensions(&jpeg_info);
776      image->magick_columns=jpeg_info.output_width;
777      image->magick_rows=jpeg_info.output_height;
778      scale_factor=(double) jpeg_info.output_width/image->columns;
779      if (scale_factor > ((double) jpeg_info.output_height/image->rows))
780        scale_factor=(double) jpeg_info.output_height/image->rows;
781      jpeg_info.scale_denom=(unsigned int) scale_factor;
782      jpeg_calc_output_dimensions(&jpeg_info);
783      if (image->debug != MagickFalse)
784        (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Scale factor: %ld",
785          (long) scale_factor);
786    }
787  if (image_info->subrange != 0)
788    {
789      jpeg_info.scale_denom=(unsigned int) image_info->subrange;
790      jpeg_calc_output_dimensions(&jpeg_info);
791    }
792  precision=jpeg_info.data_precision;
793#if (JPEG_LIB_VERSION >= 61) && defined(D_PROGRESSIVE_SUPPORTED)
794#if defined(D_LOSSLESS_SUPPORTED)
795  image->interlace=jpeg_info.process == JPROC_PROGRESSIVE ?
796    JPEGInterlace : NoInterlace;
797  image->compression=jpeg_info.process == JPROC_LOSSLESS ?
798    LosslessJPEGCompression : JPEGCompression;
799  if (jpeg_info.data_precision > 8)
800    (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
801      "12-bit JPEG not supported. Reducing pixel data to 8 bits","`%s'",
802      image->filename);
803  if (jpeg_info.data_precision == 16)
804    jpeg_info.data_precision=12;
805#else
806  image->interlace=jpeg_info.progressive_mode != 0 ? JPEGInterlace :
807    NoInterlace;
808  image->compression=JPEGCompression;
809#endif
810#else
811  image->compression=JPEGCompression;
812  image->interlace=JPEGInterlace;
813#endif
814  if ((image_info->colors != 0) && (image_info->colors <= 256))
815    {
816      /*
817        Let the JPEG library quantize for us.
818      */
819      jpeg_info.quantize_colors=MagickTrue;
820      jpeg_info.desired_number_of_colors=(int) image_info->colors;
821    }
822  (void) jpeg_start_decompress(&jpeg_info);
823  image->columns=jpeg_info.output_width;
824  image->rows=jpeg_info.output_height;
825  image->depth=(unsigned long) jpeg_info.data_precision;
826  if ((image_info->colors != 0) && (image_info->colors <= 256))
827    if (AcquireImageColormap(image,image_info->colors) == MagickFalse)
828      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
829  if ((jpeg_info.output_components == 1) &&
830      (jpeg_info.quantize_colors == MagickFalse))
831    {
832      unsigned long
833        colors;
834
835      colors=(unsigned long) GetQuantumRange(image->depth)+1;
836      if (AcquireImageColormap(image,colors) == MagickFalse)
837        ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
838    }
839  if (image->debug != MagickFalse)
840    {
841      if (image->interlace != NoInterlace)
842        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
843          "Interlace: progressive");
844      else
845        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
846          "Interlace: nonprogressive");
847      (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Data precision: %d",
848        (int) jpeg_info.data_precision);
849      (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Geometry: %dx%d",
850        (int) jpeg_info.output_width,(int) jpeg_info.output_height);
851    }
852  image->quality=UndefinedCompressionQuality;
853#if defined(D_PROGRESSIVE_SUPPORTED)
854  if (image->compression == LosslessJPEGCompression)
855    {
856      image->quality=100;
857      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
858        "Quality: 100 (lossless)");
859    }
860  else
861#endif
862  {
863    long
864      value,
865      sum;
866
867    register long
868      j;
869
870    /*
871      Determine the JPEG compression quality from the quantization tables.
872    */
873    sum=0;
874    for (i=0; i < NUM_QUANT_TBLS; i++)
875    {
876      if (jpeg_info.quant_tbl_ptrs[i] != NULL)
877        for (j=0; j < DCTSIZE2; j++)
878          sum+=jpeg_info.quant_tbl_ptrs[i]->quantval[j];
879     }
880     if ((jpeg_info.quant_tbl_ptrs[0] != NULL) &&
881         (jpeg_info.quant_tbl_ptrs[1] != NULL))
882       {
883         long
884           hash[101] =
885           {
886             1020, 1015,  932,  848,  780,  735,  702,  679,  660,  645,
887              632,  623,  613,  607,  600,  594,  589,  585,  581,  571,
888              555,  542,  529,  514,  494,  474,  457,  439,  424,  410,
889              397,  386,  373,  364,  351,  341,  334,  324,  317,  309,
890              299,  294,  287,  279,  274,  267,  262,  257,  251,  247,
891              243,  237,  232,  227,  222,  217,  213,  207,  202,  198,
892              192,  188,  183,  177,  173,  168,  163,  157,  153,  148,
893              143,  139,  132,  128,  125,  119,  115,  108,  104,   99,
894               94,   90,   84,   79,   74,   70,   64,   59,   55,   49,
895               45,   40,   34,   30,   25,   20,   15,   11,    6,    4,
896                0
897           },
898           sums[101] =
899           {
900             32640, 32635, 32266, 31495, 30665, 29804, 29146, 28599, 28104,
901             27670, 27225, 26725, 26210, 25716, 25240, 24789, 24373, 23946,
902             23572, 22846, 21801, 20842, 19949, 19121, 18386, 17651, 16998,
903             16349, 15800, 15247, 14783, 14321, 13859, 13535, 13081, 12702,
904             12423, 12056, 11779, 11513, 11135, 10955, 10676, 10392, 10208,
905              9928,  9747,  9564,  9369,  9193,  9017,  8822,  8639,  8458,
906              8270,  8084,  7896,  7710,  7527,  7347,  7156,  6977,  6788,
907              6607,  6422,  6236,  6054,  5867,  5684,  5495,  5305,  5128,
908              4945,  4751,  4638,  4442,  4248,  4065,  3888,  3698,  3509,
909              3326,  3139,  2957,  2775,  2586,  2405,  2216,  2037,  1846,
910              1666,  1483,  1297,  1109,   927,   735,   554,   375,   201,
911               128,     0
912           };
913
914         value=(long) (jpeg_info.quant_tbl_ptrs[0]->quantval[2]+
915           jpeg_info.quant_tbl_ptrs[0]->quantval[53]+
916           jpeg_info.quant_tbl_ptrs[1]->quantval[0]+
917           jpeg_info.quant_tbl_ptrs[1]->quantval[DCTSIZE2-1]);
918         for (i=0; i < 100; i++)
919         {
920           if ((value < hash[i]) && (sum < sums[i]))
921             continue;
922           if ((value <= hash[i]) && (sum <= sums[i]))
923             image->quality=(unsigned long) i+1;
924           if (image->debug != MagickFalse)
925             {
926               if ((value > hash[i]) || (sum > sums[i]))
927                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
928                   "Quality: %ld",image->quality);
929               else
930                 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
931                   "Quality: %ld (approximate)",i+1);
932             }
933           break;
934         }
935       }
936     else
937       if (jpeg_info.quant_tbl_ptrs[0] != NULL)
938         {
939           long
940             hash[101] =
941             {
942               510,  505,  422,  380,  355,  338,  326,  318,  311,  305,
943               300,  297,  293,  291,  288,  286,  284,  283,  281,  280,
944               279,  278,  277,  273,  262,  251,  243,  233,  225,  218,
945               211,  205,  198,  193,  186,  181,  177,  172,  168,  164,
946               158,  156,  152,  148,  145,  142,  139,  136,  133,  131,
947               129,  126,  123,  120,  118,  115,  113,  110,  107,  105,
948               102,  100,   97,   94,   92,   89,   87,   83,   81,   79,
949                76,   74,   70,   68,   66,   63,   61,   57,   55,   52,
950                50,   48,   44,   42,   39,   37,   34,   31,   29,   26,
951                24,   21,   18,   16,   13,   11,    8,    6,    3,    2,
952                 0
953             },
954             sums[101] =
955             {
956               16320, 16315, 15946, 15277, 14655, 14073, 13623, 13230, 12859,
957               12560, 12240, 11861, 11456, 11081, 10714, 10360, 10027,  9679,
958                9368,  9056,  8680,  8331,  7995,  7668,  7376,  7084,  6823,
959                6562,  6345,  6125,  5939,  5756,  5571,  5421,  5240,  5086,
960                4976,  4829,  4719,  4616,  4463,  4393,  4280,  4166,  4092,
961                3980,  3909,  3835,  3755,  3688,  3621,  3541,  3467,  3396,
962                3323,  3247,  3170,  3096,  3021,  2952,  2874,  2804,  2727,
963                2657,  2583,  2509,  2437,  2362,  2290,  2211,  2136,  2068,
964                1996,  1915,  1858,  1773,  1692,  1620,  1552,  1477,  1398,
965                1326,  1251,  1179,  1109,  1031,   961,   884,   814,   736,
966                 667,   592,   518,   441,   369,   292,   221,   151,    86,
967                  64,     0
968             };
969
970           value=(long) (jpeg_info.quant_tbl_ptrs[0]->quantval[2]+
971             jpeg_info.quant_tbl_ptrs[0]->quantval[53]);
972           for (i=0; i < 100; i++)
973           {
974             if ((value < hash[i]) && (sum < sums[i]))
975               continue;
976             image->quality=(unsigned long) i+1;
977             if (image->debug != MagickFalse)
978               {
979                 if ((value > hash[i]) || (sum > sums[i]))
980                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
981                     "Quality: %ld (approximate)",i+1);
982                 else
983                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
984                     "Quality: %ld",i+1);
985               }
986             break;
987           }
988         }
989  }
990  (void) FormatMagickString(value,MaxTextExtent,"%ld",(long)
991    jpeg_info.out_color_space);
992  (void) SetImageProperty(image,"jpeg:colorspace",value);
993  /*
994    Set image sampling factors.
995  */
996  switch (jpeg_info.out_color_space)
997  {
998    case JCS_CMYK:
999    {
1000      (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Colorspace: CMYK");
1001      (void) FormatMagickString(sampling_factor,MaxTextExtent,
1002        "%dx%d,%dx%d,%dx%d,%dx%d",jpeg_info.comp_info[0].h_samp_factor,
1003        jpeg_info.comp_info[0].v_samp_factor,
1004        jpeg_info.comp_info[1].h_samp_factor,
1005        jpeg_info.comp_info[1].v_samp_factor,
1006        jpeg_info.comp_info[2].h_samp_factor,
1007        jpeg_info.comp_info[2].v_samp_factor,
1008        jpeg_info.comp_info[3].h_samp_factor,
1009        jpeg_info.comp_info[3].v_samp_factor);
1010        break;
1011    }
1012    case JCS_GRAYSCALE:
1013    {
1014      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1015        "Colorspace: GRAYSCALE");
1016      (void) FormatMagickString(sampling_factor,MaxTextExtent,"%dx%d",
1017        jpeg_info.comp_info[0].h_samp_factor,
1018        jpeg_info.comp_info[0].v_samp_factor);
1019      break;
1020    }
1021    case JCS_RGB:
1022    {
1023      (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Colorspace: RGB");
1024      (void) FormatMagickString(sampling_factor,MaxTextExtent,
1025        "%dx%d,%dx%d,%dx%d",jpeg_info.comp_info[0].h_samp_factor,
1026        jpeg_info.comp_info[0].v_samp_factor,
1027        jpeg_info.comp_info[1].h_samp_factor,
1028        jpeg_info.comp_info[1].v_samp_factor,
1029        jpeg_info.comp_info[2].h_samp_factor,
1030        jpeg_info.comp_info[2].v_samp_factor);
1031      break;
1032    }
1033    default:
1034    {
1035      (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Colorspace: %d",
1036        jpeg_info.out_color_space);
1037      (void) FormatMagickString(sampling_factor,MaxTextExtent,
1038        "%dx%d,%dx%d,%dx%d,%dx%d",jpeg_info.comp_info[0].h_samp_factor,
1039        jpeg_info.comp_info[0].v_samp_factor,
1040        jpeg_info.comp_info[1].h_samp_factor,
1041        jpeg_info.comp_info[1].v_samp_factor,
1042        jpeg_info.comp_info[2].h_samp_factor,
1043        jpeg_info.c