Coverage Report

Created: 2026-05-24 07:45

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