1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                              JJJ  PPPP    222                               %
7 %                               J   P   P  2   2                              %
8 %                               J   PPPP     22                               %
9 %                            J  J   P       2                                 %
10 %                             JJ    P      22222                              %
11 %                                                                             %
12 %                                                                             %
13 %                     Read/Write JPEG-2000 Image Format                       %
14 %                                                                             %
15 %                                   Cristy                                    %
16 %                                Nathan Brown                                 %
17 %                                 June 2001                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2021 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    https://imagemagick.org/script/license.php                               %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 
39 /*
40   Include declarations.
41 */
42 #include "magick/studio.h"
43 #include "magick/artifact.h"
44 #include "magick/attribute.h"
45 #include "magick/blob.h"
46 #include "magick/blob-private.h"
47 #include "magick/cache.h"
48 #include "magick/colorspace.h"
49 #include "magick/colorspace-private.h"
50 #include "magick/color.h"
51 #include "magick/color-private.h"
52 #include "magick/exception.h"
53 #include "magick/exception-private.h"
54 #include "magick/image.h"
55 #include "magick/image-private.h"
56 #include "magick/list.h"
57 #include "magick/magick.h"
58 #include "magick/memory_.h"
59 #include "magick/monitor.h"
60 #include "magick/monitor-private.h"
61 #include "magick/option.h"
62 #include "magick/pixel-accessor.h"
63 #include "magick/profile.h"
64 #include "magick/property.h"
65 #include "magick/quantum-private.h"
66 #include "magick/resource_.h"
67 #include "magick/semaphore.h"
68 #include "magick/static.h"
69 #include "magick/statistic.h"
70 #include "magick/string_.h"
71 #include "magick/string-private.h"
72 #include "magick/module.h"
73 #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE)
74 #include <openjpeg.h>
75 #endif
76 
77 /*
78   Forward declarations.
79 */
80 #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE)
81 static MagickBooleanType
82   WriteJP2Image(const ImageInfo *,Image *);
83 #endif
84 
85 /*
86 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
87 %                                                                             %
88 %                                                                             %
89 %                                                                             %
90 %   I s J 2 K                                                                 %
91 %                                                                             %
92 %                                                                             %
93 %                                                                             %
94 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
95 %
96 %  IsJ2K() returns MagickTrue if the image format type, identified by the
97 %  magick string, is J2K.
98 %
99 %  The format of the IsJ2K method is:
100 %
101 %      MagickBooleanType IsJ2K(const unsigned char *magick,const size_t length)
102 %
103 %  A description of each parameter follows:
104 %
105 %    o magick: compare image format pattern against these bytes.
106 %
107 %    o length: Specifies the length of the magick string.
108 %
109 */
IsJ2K(const unsigned char * magick,const size_t length)110 static MagickBooleanType IsJ2K(const unsigned char *magick,const size_t length)
111 {
112   if (length < 4)
113     return(MagickFalse);
114   if (memcmp(magick,"\xff\x4f\xff\x51",4) == 0)
115     return(MagickTrue);
116   return(MagickFalse);
117 }
118 
119 /*
120 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
121 %                                                                             %
122 %                                                                             %
123 %                                                                             %
124 %   I s J P 2                                                                 %
125 %                                                                             %
126 %                                                                             %
127 %                                                                             %
128 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
129 %
130 %  IsJP2() returns MagickTrue if the image format type, identified by the
131 %  magick string, is JP2.
132 %
133 %  The format of the IsJP2 method is:
134 %
135 %      MagickBooleanType IsJP2(const unsigned char *magick,const size_t length)
136 %
137 %  A description of each parameter follows:
138 %
139 %    o magick: compare image format pattern against these bytes.
140 %
141 %    o length: Specifies the length of the magick string.
142 %
143 */
IsJP2(const unsigned char * magick,const size_t length)144 static MagickBooleanType IsJP2(const unsigned char *magick,const size_t length)
145 {
146   if (length < 4)
147     return(MagickFalse);
148   if (memcmp(magick,"\x0d\x0a\x87\x0a",4) == 0)
149     return(MagickTrue);
150   if (length < 12)
151     return(MagickFalse);
152   if (memcmp(magick,"\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a",12) == 0)
153     return(MagickTrue);
154   return(MagickFalse);
155 }
156 
157 /*
158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
159 %                                                                             %
160 %                                                                             %
161 %                                                                             %
162 %   R e a d J P 2 I m a g e                                                   %
163 %                                                                             %
164 %                                                                             %
165 %                                                                             %
166 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
167 %
168 %  ReadJP2Image() reads a JPEG 2000 Image file (JP2) or JPEG 2000
169 %  codestream (JPC) image file and returns it.  It allocates the memory
170 %  necessary for the new Image structure and returns a pointer to the new
171 %  image or set of images.
172 %
173 %  JP2 support is originally written by Nathan Brown, nathanbrown@letu.edu.
174 %
175 %  The format of the ReadJP2Image method is:
176 %
177 %      Image *ReadJP2Image(const ImageInfo *image_info,
178 %        ExceptionInfo *exception)
179 %
180 %  A description of each parameter follows:
181 %
182 %    o image_info: the image info.
183 %
184 %    o exception: return any errors or warnings in this structure.
185 %
186 */
187 #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE)
JP2ErrorHandler(const char * message,void * client_data)188 static void JP2ErrorHandler(const char *message,void *client_data)
189 {
190   ExceptionInfo
191     *exception;
192 
193   exception=(ExceptionInfo *) client_data;
194   (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
195     message,"`%s'","OpenJP2");
196 }
197 
JP2ReadHandler(void * buffer,OPJ_SIZE_T length,void * context)198 static OPJ_SIZE_T JP2ReadHandler(void *buffer,OPJ_SIZE_T length,void *context)
199 {
200   Image
201     *image;
202 
203   ssize_t
204     count;
205 
206   image=(Image *) context;
207   count=ReadBlob(image,(ssize_t) length,(unsigned char *) buffer);
208   if (count == 0)
209     return((OPJ_SIZE_T) -1);
210   return((OPJ_SIZE_T) count);
211 }
212 
JP2SeekHandler(OPJ_OFF_T offset,void * context)213 static OPJ_BOOL JP2SeekHandler(OPJ_OFF_T offset,void *context)
214 {
215   Image
216     *image;
217 
218   image=(Image *) context;
219   return(SeekBlob(image,offset,SEEK_SET) < 0 ? OPJ_FALSE : OPJ_TRUE);
220 }
221 
JP2SkipHandler(OPJ_OFF_T offset,void * context)222 static OPJ_OFF_T JP2SkipHandler(OPJ_OFF_T offset,void *context)
223 {
224   Image
225     *image;
226 
227   image=(Image *) context;
228   return(SeekBlob(image,offset,SEEK_CUR) < 0 ? -1 : offset);
229 }
230 
JP2WarningHandler(const char * message,void * client_data)231 static void JP2WarningHandler(const char *message,void *client_data)
232 {
233   ExceptionInfo
234     *exception;
235 
236   exception=(ExceptionInfo *) client_data;
237   (void) ThrowMagickException(exception,GetMagickModule(),CoderWarning,
238     message,"`%s'","OpenJP2");
239 }
240 
JP2WriteHandler(void * buffer,OPJ_SIZE_T length,void * context)241 static OPJ_SIZE_T JP2WriteHandler(void *buffer,OPJ_SIZE_T length,void *context)
242 {
243   Image
244     *image;
245 
246   ssize_t
247     count;
248 
249   image=(Image *) context;
250   count=WriteBlob(image,(ssize_t) length,(unsigned char *) buffer);
251   return((OPJ_SIZE_T) count);
252 }
253 
ReadJP2Image(const ImageInfo * image_info,ExceptionInfo * exception)254 static Image *ReadJP2Image(const ImageInfo *image_info,ExceptionInfo *exception)
255 {
256   const char
257     *option;
258 
259   Image
260     *image;
261 
262   int
263     jp2_status;
264 
265   MagickBooleanType
266     status;
267 
268   opj_codec_t
269     *jp2_codec;
270 
271   opj_dparameters_t
272     parameters;
273 
274   opj_image_t
275     *jp2_image;
276 
277   opj_stream_t
278     *jp2_stream;
279 
280   ssize_t
281     i;
282 
283   ssize_t
284     y;
285 
286   unsigned char
287     sans[4];
288 
289   /*
290     Open image file.
291   */
292   assert(image_info != (const ImageInfo *) NULL);
293   assert(image_info->signature == MagickCoreSignature);
294   if (image_info->debug != MagickFalse)
295     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
296       image_info->filename);
297   assert(exception != (ExceptionInfo *) NULL);
298   assert(exception->signature == MagickCoreSignature);
299   image=AcquireImage(image_info);
300   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
301   if (status == MagickFalse)
302     {
303       image=DestroyImageList(image);
304       return((Image *) NULL);
305     }
306   /*
307     Initialize JP2 codec.
308   */
309   if (ReadBlob(image,4,sans) != 4)
310     {
311       image=DestroyImageList(image);
312       return((Image *) NULL);
313     }
314   (void) SeekBlob(image,SEEK_SET,0);
315   if (LocaleCompare(image_info->magick,"JPT") == 0)
316     jp2_codec=opj_create_decompress(OPJ_CODEC_JPT);
317   else
318     if (IsJ2K(sans,4) != MagickFalse)
319       jp2_codec=opj_create_decompress(OPJ_CODEC_J2K);
320     else
321       jp2_codec=opj_create_decompress(OPJ_CODEC_JP2);
322   opj_set_warning_handler(jp2_codec,JP2WarningHandler,exception);
323   opj_set_error_handler(jp2_codec,JP2ErrorHandler,exception);
324   opj_set_default_decoder_parameters(&parameters);
325   option=GetImageOption(image_info,"jp2:reduce-factor");
326   if (option != (const char *) NULL)
327     parameters.cp_reduce=StringToInteger(option);
328   option=GetImageOption(image_info,"jp2:quality-layers");
329   if (option == (const char *) NULL)
330     option=GetImageOption(image_info,"jp2:layer-number");
331   if (option != (const char *) NULL)
332     parameters.cp_layer=StringToInteger(option);
333   if (opj_setup_decoder(jp2_codec,&parameters) == 0)
334     {
335       opj_destroy_codec(jp2_codec);
336       ThrowReaderException(DelegateError,"UnableToManageJP2Stream");
337     }
338   jp2_stream=opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE,OPJ_TRUE);
339   opj_stream_set_read_function(jp2_stream,JP2ReadHandler);
340   opj_stream_set_write_function(jp2_stream,JP2WriteHandler);
341   opj_stream_set_seek_function(jp2_stream,JP2SeekHandler);
342   opj_stream_set_skip_function(jp2_stream,JP2SkipHandler);
343   opj_stream_set_user_data(jp2_stream,image,NULL);
344   opj_stream_set_user_data_length(jp2_stream,GetBlobSize(image));
345   if (opj_read_header(jp2_stream,jp2_codec,&jp2_image) == 0)
346     {
347       opj_stream_destroy(jp2_stream);
348       opj_destroy_codec(jp2_codec);
349       ThrowReaderException(DelegateError,"UnableToDecodeImageFile");
350     }
351   if ((AcquireMagickResource(WidthResource,(size_t) jp2_image->comps[0].w) == MagickFalse) ||
352       (AcquireMagickResource(HeightResource,(size_t) jp2_image->comps[0].h) == MagickFalse))
353     {
354       opj_stream_destroy(jp2_stream);
355       opj_destroy_codec(jp2_codec);
356       opj_image_destroy(jp2_image);
357       ThrowReaderException(DelegateError,"UnableToDecodeImageFile");
358     }
359   jp2_status=OPJ_TRUE;
360   if (image->ping == MagickFalse)
361     {
362       if ((image->columns != 0) && (image->rows != 0))
363         /*
364           Extract an area from the image.
365         */
366         jp2_status=opj_set_decode_area(jp2_codec,jp2_image,
367           (OPJ_INT32) image->extract_info.x,(OPJ_INT32) image->extract_info.y,
368           (OPJ_INT32) image->extract_info.x+(ssize_t) image->columns,
369           (OPJ_INT32) image->extract_info.y+(ssize_t) image->rows);
370       else
371         jp2_status=opj_set_decode_area(jp2_codec,jp2_image,0,0,
372           jp2_image->comps[0].w,jp2_image->comps[0].h);
373       if (jp2_status == OPJ_FALSE)
374         {
375           opj_stream_destroy(jp2_stream);
376           opj_destroy_codec(jp2_codec);
377           opj_image_destroy(jp2_image);
378           ThrowReaderException(DelegateError,"UnableToDecodeImageFile");
379         }
380     }
381   if ((image_info->number_scenes != 0) && (image_info->scene != 0))
382     jp2_status=opj_get_decoded_tile(jp2_codec,jp2_stream,jp2_image,
383       (unsigned int) image_info->scene-1);
384   else
385     if (image->ping == MagickFalse)
386       {
387         jp2_status=opj_decode(jp2_codec,jp2_stream,jp2_image);
388         if (jp2_status != OPJ_FALSE)
389           jp2_status=opj_end_decompress(jp2_codec,jp2_stream);
390       }
391   if (jp2_status == OPJ_FALSE)
392     {
393       opj_stream_destroy(jp2_stream);
394       opj_destroy_codec(jp2_codec);
395       opj_image_destroy(jp2_image);
396       ThrowReaderException(DelegateError,"UnableToDecodeImageFile");
397     }
398   opj_stream_destroy(jp2_stream);
399   for (i=0; i < (ssize_t) jp2_image->numcomps; i++)
400   {
401     if ((jp2_image->comps[i].dx == 0) || (jp2_image->comps[i].dy == 0) ||
402         (jp2_image->comps[0].prec != jp2_image->comps[i].prec) ||
403         (jp2_image->comps[0].prec > 64) ||
404         (jp2_image->comps[0].sgnd != jp2_image->comps[i].sgnd) ||
405         ((image->ping == MagickFalse) && (jp2_image->comps[i].data == NULL)))
406       {
407         opj_destroy_codec(jp2_codec);
408         opj_image_destroy(jp2_image);
409         ThrowReaderException(CoderError,"IrregularChannelGeometryNotSupported")
410       }
411   }
412   /*
413     Convert JP2 image.
414   */
415   image->columns=(size_t) jp2_image->comps[0].w;
416   image->rows=(size_t) jp2_image->comps[0].h;
417   image->depth=jp2_image->comps[0].prec;
418   image->compression=JPEG2000Compression;
419   if (jp2_image->numcomps == 1)
420     SetImageColorspace(image,GRAYColorspace);
421   else
422     if (jp2_image->color_space == 2)
423       {
424         SetImageColorspace(image,GRAYColorspace);
425         if (jp2_image->numcomps > 1)
426           image->matte=MagickTrue;
427       }
428     else
429       if (jp2_image->color_space == 3)
430         SetImageColorspace(image,Rec601YCbCrColorspace);
431   if (jp2_image->numcomps > 3)
432     image->matte=MagickTrue;
433   if (jp2_image->icc_profile_buf != (unsigned char *) NULL)
434     {
435       StringInfo
436         *profile;
437 
438       profile=BlobToStringInfo(jp2_image->icc_profile_buf,
439         jp2_image->icc_profile_len);
440       if (profile != (StringInfo *) NULL)
441         {
442           SetImageProfile(image,"icc",profile);
443           profile=DestroyStringInfo(profile);
444         }
445     }
446   if (image->ping != MagickFalse)
447     {
448       opj_destroy_codec(jp2_codec);
449       opj_image_destroy(jp2_image);
450       return(GetFirstImageInList(image));
451     }
452   status=SetImageExtent(image,image->columns,image->rows);
453   if (status == MagickFalse)
454     {
455       opj_destroy_codec(jp2_codec);
456       opj_image_destroy(jp2_image);
457       InheritException(exception,&image->exception);
458       return(DestroyImageList(image));
459     }
460   for (y=0; y < (ssize_t) image->rows; y++)
461   {
462     PixelPacket
463       *magick_restrict q;
464 
465     ssize_t
466       x;
467 
468     q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
469     if (q == (PixelPacket *) NULL)
470       break;
471     for (x=0; x < (ssize_t) image->columns; x++)
472     {
473       ssize_t
474         i;
475 
476       for (i=0; i < (ssize_t) jp2_image->numcomps; i++)
477       {
478         double
479           pixel,
480           scale;
481 
482         ssize_t
483           index,
484           pad;
485 
486         pad=image->columns % jp2_image->comps[i].dx;
487         index=y/jp2_image->comps[i].dy*(image->columns+pad)/
488           jp2_image->comps[i].dx+x/jp2_image->comps[i].dx;
489         if ((index < 0) ||
490             (index >= (jp2_image->comps[i].h * jp2_image->comps[i].w)))
491           {
492             opj_destroy_codec(jp2_codec);
493             opj_image_destroy(jp2_image);
494             ThrowReaderException(CoderError,
495               "IrregularChannelGeometryNotSupported")
496           }
497         scale=QuantumRange/(double) ((1UL << jp2_image->comps[i].prec)-1);
498         pixel=scale*(jp2_image->comps[i].data[index]+
499           (jp2_image->comps[i].sgnd ? 1UL << (jp2_image->comps[i].prec-1) : 0));
500         switch (i)
501         {
502            case 0:
503            {
504              if (jp2_image->numcomps == 1)
505                {
506                  SetPixelGray(q,ClampToQuantum(pixel));
507                  SetPixelOpacity(q,OpaqueOpacity);
508                  break;
509                }
510              q->red=ClampToQuantum(pixel);
511              q->green=q->red;
512              q->blue=q->red;
513              q->opacity=OpaqueOpacity;
514              break;
515            }
516            case 1:
517            {
518              if (jp2_image->numcomps == 2)
519                {
520                  q->opacity=ClampToQuantum(QuantumRange-pixel);
521                  break;
522                }
523              q->green=ClampToQuantum(pixel);
524              break;
525            }
526            case 2:
527            {
528              q->blue=ClampToQuantum(pixel);
529              break;
530            }
531            case 3:
532            {
533              q->opacity=ClampToQuantum(QuantumRange-pixel);
534              break;
535            }
536         }
537       }
538       q++;
539     }
540     if (SyncAuthenticPixels(image,exception) == MagickFalse)
541       break;
542     status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
543       image->rows);
544     if (status == MagickFalse)
545       break;
546   }
547   /*
548     Free resources.
549   */
550   opj_destroy_codec(jp2_codec);
551   opj_image_destroy(jp2_image);
552   (void) CloseBlob(image);
553   if ((image_info->number_scenes != 0) && (image_info->scene != 0))
554     AppendImageToList(&image,CloneImage(image,0,0,MagickTrue,exception));
555   return(GetFirstImageInList(image));
556 }
557 #endif
558 
559 /*
560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
561 %                                                                             %
562 %                                                                             %
563 %                                                                             %
564 %   R e g i s t e r J P 2 I m a g e                                           %
565 %                                                                             %
566 %                                                                             %
567 %                                                                             %
568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
569 %
570 %  RegisterJP2Image() adds attributes for the JP2 image format to the list of
571 %  supported formats.  The attributes include the image format tag, a method
572 %  method to read and/or write the format, whether the format supports the
573 %  saving of more than one frame to the same file or blob, whether the format
574 %  supports native in-memory I/O, and a brief description of the format.
575 %
576 %  The format of the RegisterJP2Image method is:
577 %
578 %      size_t RegisterJP2Image(void)
579 %
580 */
RegisterJP2Image(void)581 ModuleExport size_t RegisterJP2Image(void)
582 {
583   char
584     version[MaxTextExtent];
585 
586   MagickInfo
587     *entry;
588 
589   *version='\0';
590 #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE)
591   (void) FormatLocaleString(version,MaxTextExtent,"%s",opj_version());
592 #endif
593   entry=SetMagickInfo("JP2");
594   entry->description=ConstantString("JPEG-2000 File Format Syntax");
595   if (*version != '\0')
596     entry->version=ConstantString(version);
597   entry->mime_type=ConstantString("image/jp2");
598   entry->magick_module=ConstantString("JP2");
599   entry->magick=(IsImageFormatHandler *) IsJP2;
600   entry->adjoin=MagickFalse;
601   entry->seekable_stream=MagickTrue;
602 #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE)
603   entry->decoder=(DecodeImageHandler *) ReadJP2Image;
604   entry->encoder=(EncodeImageHandler *) WriteJP2Image;
605 #endif
606   (void) RegisterMagickInfo(entry);
607   entry=SetMagickInfo("J2C");
608   entry->description=ConstantString("JPEG-2000 Code Stream Syntax");
609   if (*version != '\0')
610     entry->version=ConstantString(version);
611   entry->mime_type=ConstantString("image/jp2");
612   entry->magick_module=ConstantString("JP2");
613   entry->magick=(IsImageFormatHandler *) IsJ2K;
614   entry->adjoin=MagickFalse;
615   entry->seekable_stream=MagickTrue;
616 #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE)
617   entry->decoder=(DecodeImageHandler *) ReadJP2Image;
618   entry->encoder=(EncodeImageHandler *) WriteJP2Image;
619 #endif
620   (void) RegisterMagickInfo(entry);
621   entry=SetMagickInfo("J2K");
622   entry->description=ConstantString("JPEG-2000 Code Stream Syntax");
623   if (*version != '\0')
624     entry->version=ConstantString(version);
625   entry->mime_type=ConstantString("image/jp2");
626   entry->magick_module=ConstantString("JP2");
627   entry->magick=(IsImageFormatHandler *) IsJ2K;
628   entry->adjoin=MagickFalse;
629   entry->seekable_stream=MagickTrue;
630 #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE)
631   entry->decoder=(DecodeImageHandler *) ReadJP2Image;
632   entry->encoder=(EncodeImageHandler *) WriteJP2Image;
633 #endif
634   (void) RegisterMagickInfo(entry);
635   entry=SetMagickInfo("JPM");
636   entry->description=ConstantString("JPEG-2000 Code Stream Syntax");
637   if (*version != '\0')
638     entry->version=ConstantString(version);
639   entry->mime_type=ConstantString("image/jp2");
640   entry->magick_module=ConstantString("JP2");
641   entry->magick=(IsImageFormatHandler *) IsJP2;
642   entry->adjoin=MagickFalse;
643   entry->seekable_stream=MagickTrue;
644 #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE)
645   entry->decoder=(DecodeImageHandler *) ReadJP2Image;
646   entry->encoder=(EncodeImageHandler *) WriteJP2Image;
647 #endif
648   (void) RegisterMagickInfo(entry);
649   entry=SetMagickInfo("JPT");
650   entry->description=ConstantString("JPEG-2000 File Format Syntax");
651   if (*version != '\0')
652     entry->version=ConstantString(version);
653   entry->mime_type=ConstantString("image/jp2");
654   entry->magick_module=ConstantString("JP2");
655   entry->magick=(IsImageFormatHandler *) IsJP2;
656   entry->adjoin=MagickFalse;
657   entry->seekable_stream=MagickTrue;
658 #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE)
659   entry->decoder=(DecodeImageHandler *) ReadJP2Image;
660   entry->encoder=(EncodeImageHandler *) WriteJP2Image;
661 #endif
662   (void) RegisterMagickInfo(entry);
663   entry=SetMagickInfo("JPC");
664   entry->description=ConstantString("JPEG-2000 Code Stream Syntax");
665   if (*version != '\0')
666     entry->version=ConstantString(version);
667   entry->mime_type=ConstantString("image/jp2");
668   entry->magick_module=ConstantString("JP2");
669   entry->magick=(IsImageFormatHandler *) IsJP2;
670   entry->adjoin=MagickFalse;
671   entry->seekable_stream=MagickTrue;
672 #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE)
673   entry->decoder=(DecodeImageHandler *) ReadJP2Image;
674   entry->encoder=(EncodeImageHandler *) WriteJP2Image;
675 #endif
676   (void) RegisterMagickInfo(entry);
677   return(MagickImageCoderSignature);
678 }
679 
680 /*
681 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
682 %                                                                             %
683 %                                                                             %
684 %                                                                             %
685 %   U n r e g i s t e r J P 2 I m a g e                                       %
686 %                                                                             %
687 %                                                                             %
688 %                                                                             %
689 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
690 %
691 %  UnregisterJP2Image() removes format registrations made by the JP2 module
692 %  from the list of supported formats.
693 %
694 %  The format of the UnregisterJP2Image method is:
695 %
696 %      UnregisterJP2Image(void)
697 %
698 */
UnregisterJP2Image(void)699 ModuleExport void UnregisterJP2Image(void)
700 {
701   (void) UnregisterMagickInfo("JPC");
702   (void) UnregisterMagickInfo("JPT");
703   (void) UnregisterMagickInfo("JPM");
704   (void) UnregisterMagickInfo("JP2");
705   (void) UnregisterMagickInfo("J2K");
706 }
707 
708 #if defined(MAGICKCORE_LIBOPENJP2_DELEGATE)
709 /*
710 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
711 %                                                                             %
712 %                                                                             %
713 %                                                                             %
714 %   W r i t e J P 2 I m a g e                                                 %
715 %                                                                             %
716 %                                                                             %
717 %                                                                             %
718 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
719 %
720 %  WriteJP2Image() writes an image in the JPEG 2000 image format.
721 %
722 %  JP2 support originally written by Nathan Brown, nathanbrown@letu.edu
723 %
724 %  The format of the WriteJP2Image method is:
725 %
726 %      MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image)
727 %
728 %  A description of each parameter follows.
729 %
730 %    o image_info: the image info.
731 %
732 %    o image:  The image.
733 %
734 */
735 
CinemaProfileCompliance(const opj_image_t * jp2_image,opj_cparameters_t * parameters)736 static void CinemaProfileCompliance(const opj_image_t *jp2_image,
737   opj_cparameters_t *parameters)
738 {
739   /*
740     Digital Cinema 4K profile compliant codestream.
741   */
742   parameters->tile_size_on=OPJ_FALSE;
743   parameters->cp_tdx=1;
744   parameters->cp_tdy=1;
745   parameters->tp_flag='C';
746   parameters->tp_on=1;
747   parameters->cp_tx0=0;
748   parameters->cp_ty0=0;
749   parameters->image_offset_x0=0;
750   parameters->image_offset_y0=0;
751   parameters->cblockw_init=32;
752   parameters->cblockh_init=32;
753   parameters->csty|=0x01;
754   parameters->prog_order=OPJ_CPRL;
755   parameters->roi_compno=(-1);
756   parameters->subsampling_dx=1;
757   parameters->subsampling_dy=1;
758   parameters->irreversible=1;
759   if ((jp2_image->comps[0].w == 2048) || (jp2_image->comps[0].h == 1080))
760     {
761       /*
762         Digital Cinema 2K.
763       */
764       parameters->cp_cinema=OPJ_CINEMA2K_24;
765       parameters->cp_rsiz=OPJ_CINEMA2K;
766       parameters->max_comp_size=1041666;
767       if (parameters->numresolution > 6)
768         parameters->numresolution=6;
769 
770     }
771   if ((jp2_image->comps[0].w == 4096) || (jp2_image->comps[0].h == 2160))
772     {
773       /*
774         Digital Cinema 4K.
775       */
776       parameters->cp_cinema=OPJ_CINEMA4K_24;
777       parameters->cp_rsiz=OPJ_CINEMA4K;
778       parameters->max_comp_size=1041666;
779       if (parameters->numresolution < 1)
780         parameters->numresolution=1;
781       if (parameters->numresolution > 7)
782         parameters->numresolution=7;
783       parameters->numpocs=2;
784       parameters->POC[0].tile=1;
785       parameters->POC[0].resno0=0;
786       parameters->POC[0].compno0=0;
787       parameters->POC[0].layno1=1;
788       parameters->POC[0].resno1=parameters->numresolution-1;
789       parameters->POC[0].compno1=3;
790       parameters->POC[0].prg1=OPJ_CPRL;
791       parameters->POC[1].tile=1;
792       parameters->POC[1].resno0=parameters->numresolution-1;
793       parameters->POC[1].compno0=0;
794       parameters->POC[1].layno1=1;
795       parameters->POC[1].resno1=parameters->numresolution;
796       parameters->POC[1].compno1=3;
797       parameters->POC[1].prg1=OPJ_CPRL;
798     }
799   parameters->tcp_numlayers=1;
800   parameters->tcp_rates[0]=((float) (jp2_image->numcomps*jp2_image->comps[0].w*
801     jp2_image->comps[0].h*jp2_image->comps[0].prec))/(parameters->max_comp_size*
802     8*jp2_image->comps[0].dx*jp2_image->comps[0].dy);
803   parameters->cp_disto_alloc=1;
804 }
805 
CalculateNumResolutions(size_t width,size_t height)806 static inline int CalculateNumResolutions(size_t width,size_t height)
807 {
808   int
809     i;
810 
811   for (i=1; i < 6; i++)
812     if ((width < ((size_t) 1UL << i)) || (height < ((size_t) 1UL << i)))
813       break;
814   return(i);
815 }
816 
WriteJP2Image(const ImageInfo * image_info,Image * image)817 static MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image)
818 {
819   const char
820     *option,
821     *property;
822 
823   int
824     jp2_status;
825 
826   MagickBooleanType
827     status;
828 
829   opj_codec_t
830     *jp2_codec;
831 
832   OPJ_COLOR_SPACE
833     jp2_colorspace;
834 
835   opj_cparameters_t
836     *parameters;
837 
838   opj_image_cmptparm_t
839     jp2_info[5];
840 
841   opj_image_t
842     *jp2_image;
843 
844   opj_stream_t
845     *jp2_stream;
846 
847   ssize_t
848     i;
849 
850   ssize_t
851     y;
852 
853   unsigned int
854     channels;
855 
856   /*
857     Open image file.
858   */
859   assert(image_info != (const ImageInfo *) NULL);
860   assert(image_info->signature == MagickCoreSignature);
861   assert(image != (Image *) NULL);
862   assert(image->signature == MagickCoreSignature);
863   if (image->debug != MagickFalse)
864     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
865   status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
866   if (status == MagickFalse)
867     return(status);
868   /*
869     Initialize JPEG 2000 encoder parameters.
870   */
871   parameters=(opj_cparameters_t *) AcquireMagickMemory(sizeof(*parameters));
872   if (parameters == (opj_cparameters_t *) NULL)
873     ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
874   opj_set_default_encoder_parameters(parameters);
875   option=GetImageOption(image_info,"jp2:number-resolutions");
876   if (option != (const char *) NULL)
877     parameters->numresolution=StringToInteger(option);
878   else
879     parameters->numresolution=CalculateNumResolutions(image->columns,
880       image->rows);
881   parameters->tcp_numlayers=1;
882   parameters->tcp_rates[0]=0;  /* lossless */
883   parameters->cp_disto_alloc=1;
884   if ((image_info->quality != 0) && (image_info->quality != 100))
885     {
886       parameters->tcp_distoratio[0]=(double) image_info->quality;
887       parameters->cp_fixed_quality=OPJ_TRUE;
888       parameters->cp_disto_alloc=0;
889     }
890   if (image_info->extract != (char *) NULL)
891     {
892       RectangleInfo
893         geometry;
894 
895       int
896         flags;
897 
898       /*
899         Set tile size.
900       */
901       (void) memset(&geometry,0,sizeof(geometry));
902       flags=ParseAbsoluteGeometry(image_info->extract,&geometry);
903       parameters->cp_tdx=(int) geometry.width;
904       parameters->cp_tdy=(int) geometry.width;
905       if ((flags & HeightValue) != 0)
906         parameters->cp_tdy=(int) geometry.height;
907       if ((flags & XValue) != 0)
908         parameters->cp_tx0=geometry.x;
909       if ((flags & YValue) != 0)
910         parameters->cp_ty0=geometry.y;
911       parameters->tile_size_on=OPJ_TRUE;
912       parameters->numresolution=CalculateNumResolutions(parameters->cp_tdx,
913         parameters->cp_tdy);
914     }
915   option=GetImageOption(image_info,"jp2:quality");
916   if (option != (const char *) NULL)
917     {
918       const char
919         *p;
920 
921       /*
922         Set quality PSNR.
923       */
924       p=option;
925       for (i=0; sscanf(p,"%f",&parameters->tcp_distoratio[i]) == 1; i++)
926       {
927         if (i >= 100)
928           break;
929         while ((*p != '\0') && (*p != ','))
930           p++;
931         if (*p == '\0')
932           break;
933         p++;
934       }
935       parameters->tcp_numlayers=i+1;
936       parameters->cp_fixed_quality=OPJ_TRUE;
937       parameters->cp_disto_alloc=0;
938     }
939   option=GetImageOption(image_info,"jp2:progression-order");
940   if (option != (const char *) NULL)
941     {
942       if (LocaleCompare(option,"LRCP") == 0)
943         parameters->prog_order=OPJ_LRCP;
944       if (LocaleCompare(option,"RLCP") == 0)
945         parameters->prog_order=OPJ_RLCP;
946       if (LocaleCompare(option,"RPCL") == 0)
947         parameters->prog_order=OPJ_RPCL;
948       if (LocaleCompare(option,"PCRL") == 0)
949         parameters->prog_order=OPJ_PCRL;
950       if (LocaleCompare(option,"CPRL") == 0)
951         parameters->prog_order=OPJ_CPRL;
952     }
953   option=GetImageOption(image_info,"jp2:rate");
954   if (option != (const char *) NULL)
955     {
956       const char
957         *p;
958 
959       /*
960         Set compression rate.
961       */
962       p=option;
963       for (i=0; sscanf(p,"%f",&parameters->tcp_rates[i]) == 1; i++)
964       {
965         if (i > 100)
966           break;
967         while ((*p != '\0') && (*p != ','))
968           p++;
969         if (*p == '\0')
970           break;
971         p++;
972       }
973       parameters->tcp_numlayers=i+1;
974       parameters->cp_disto_alloc=OPJ_TRUE;
975     }
976   if (image_info->sampling_factor != (const char *) NULL)
977     (void) sscanf(image_info->sampling_factor,"%d,%d",
978       &parameters->subsampling_dx,&parameters->subsampling_dy);
979   property=GetImageProperty(image,"comment");
980   if (property != (const char *) NULL)
981     parameters->cp_comment=(char *) property;
982   channels=3;
983   jp2_colorspace=OPJ_CLRSPC_SRGB;
984   if (image->colorspace == YUVColorspace)
985     {
986       jp2_colorspace=OPJ_CLRSPC_SYCC;
987       parameters->subsampling_dx=2;
988     }
989   else
990     {
991       if (IsGrayColorspace(image->colorspace) != MagickFalse)
992         {
993           channels=1;
994           jp2_colorspace=OPJ_CLRSPC_GRAY;
995         }
996       else
997         if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
998           (void) TransformImageColorspace(image,sRGBColorspace);
999       if (image->matte != MagickFalse)
1000         channels++;
1001     }
1002   parameters->tcp_mct=channels == 3 ? 1 : 0;
1003   memset(jp2_info,0,sizeof(jp2_info));
1004   for (i=0; i < (ssize_t) channels; i++)
1005   {
1006     jp2_info[i].prec=(unsigned int) image->depth;
1007     jp2_info[i].bpp=(unsigned int) image->depth;
1008     if ((image->depth == 1) &&
1009         ((LocaleCompare(image_info->magick,"JPT") == 0) ||
1010          (LocaleCompare(image_info->magick,"JP2") == 0)))
1011       {
1012         jp2_info[i].prec++;  /* OpenJPEG returns exception for depth @ 1 */
1013         jp2_info[i].bpp++;
1014       }
1015     jp2_info[i].sgnd=0;
1016     jp2_info[i].dx=parameters->subsampling_dx;
1017     jp2_info[i].dy=parameters->subsampling_dy;
1018     jp2_info[i].w=(unsigned int) image->columns;
1019     jp2_info[i].h=(unsigned int) image->rows;
1020   }
1021   jp2_image=opj_image_create(channels,jp2_info,jp2_colorspace);
1022   if (jp2_image == (opj_image_t *) NULL)
1023     {
1024       parameters=(opj_cparameters_t *) RelinquishMagickMemory(parameters);
1025       ThrowWriterException(DelegateError,"UnableToEncodeImageFile");
1026     }
1027   jp2_image->x0=parameters->image_offset_x0;
1028   jp2_image->y0=parameters->image_offset_y0;
1029   jp2_image->x1=(unsigned int) (2*parameters->image_offset_x0+
1030     (image->columns-1)*parameters->subsampling_dx+1);
1031   jp2_image->y1=(unsigned int) (2*parameters->image_offset_y0+
1032     (image->rows-1)*parameters->subsampling_dx+1);
1033   if ((image->depth == 12) &&
1034       ((image->columns == 2048) || (image->rows == 1080) ||
1035        (image->columns == 4096) || (image->rows == 2160)))
1036     CinemaProfileCompliance(jp2_image,parameters);
1037   if (channels == 4)
1038     jp2_image->comps[3].alpha=1;
1039   else
1040    if ((channels == 2) && (jp2_colorspace == OPJ_CLRSPC_GRAY))
1041      jp2_image->comps[1].alpha=1;
1042   /*
1043     Convert to JP2 pixels.
1044   */
1045   for (y=0; y < (ssize_t) image->rows; y++)
1046   {
1047     const PixelPacket
1048       *p;
1049 
1050     ssize_t
1051       x;
1052 
1053     p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1054     if (p == (const PixelPacket *) NULL)
1055       break;
1056     for (x=0; x < (ssize_t) image->columns; x++)
1057     {
1058       for (i=0; i < (ssize_t) channels; i++)
1059       {
1060         double
1061           scale;
1062 
1063         int
1064           *q;
1065 
1066         scale=(double) (((size_t) 1UL << jp2_image->comps[i].prec)-1)/
1067           QuantumRange;
1068         q=jp2_image->comps[i].data+(ssize_t) (y*PerceptibleReciprocal(
1069           jp2_image->comps[i].dy)*image->columns*PerceptibleReciprocal(
1070           jp2_image->comps[i].dx)+x*PerceptibleReciprocal(
1071           jp2_image->comps[i].dx));
1072         switch (i)
1073         {
1074           case 0:
1075           {
1076             if (jp2_colorspace == OPJ_CLRSPC_GRAY)
1077               {
1078                 *q=(int) (scale*GetPixelGray(p));
1079                 break;
1080               }
1081             *q=(int) (scale*p->red);
1082             break;
1083           }
1084           case 1:
1085           {
1086             if (jp2_colorspace == OPJ_CLRSPC_GRAY)
1087               {
1088                 *q=(int) (scale*(QuantumRange-p->opacity));
1089                 break;
1090               }
1091             *q=(int) (scale*p->green);
1092             break;
1093           }
1094           case 2:
1095           {
1096             *q=(int) (scale*p->blue);
1097             break;
1098           }
1099           case 3:
1100           {
1101             *q=(int) (scale*(QuantumRange-p->opacity));
1102             break;
1103           }
1104         }
1105       }
1106       p++;
1107     }
1108     status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1109       image->rows);
1110     if (status == MagickFalse)
1111       break;
1112   }
1113   if (LocaleCompare(image_info->magick,"JPT") == 0)
1114     jp2_codec=opj_create_compress(OPJ_CODEC_JPT);
1115   else
1116     if (LocaleCompare(image_info->magick,"J2K") == 0)
1117       jp2_codec=opj_create_compress(OPJ_CODEC_J2K);
1118     else
1119       jp2_codec=opj_create_compress(OPJ_CODEC_JP2);
1120   opj_set_warning_handler(jp2_codec,JP2WarningHandler,&image->exception);
1121   opj_set_error_handler(jp2_codec,JP2ErrorHandler,&image->exception);
1122   opj_setup_encoder(jp2_codec,parameters,jp2_image);
1123   jp2_stream=opj_stream_create(OPJ_J2K_STREAM_CHUNK_SIZE,OPJ_FALSE);
1124   if (jp2_stream == (opj_stream_t *) NULL)
1125     {
1126       opj_destroy_codec(jp2_codec);
1127       opj_image_destroy(jp2_image);
1128       parameters=(opj_cparameters_t *) RelinquishMagickMemory(parameters);
1129       ThrowWriterException(DelegateError,"UnableToEncodeImageFile");
1130     }
1131   opj_stream_set_read_function(jp2_stream,JP2ReadHandler);
1132   opj_stream_set_write_function(jp2_stream,JP2WriteHandler);
1133   opj_stream_set_seek_function(jp2_stream,JP2SeekHandler);
1134   opj_stream_set_skip_function(jp2_stream,JP2SkipHandler);
1135   opj_stream_set_user_data(jp2_stream,image,NULL);
1136   jp2_status=opj_start_compress(jp2_codec,jp2_image,jp2_stream);
1137   if ((jp2_status == 0) || (opj_encode(jp2_codec,jp2_stream) == 0) ||
1138       (opj_end_compress(jp2_codec,jp2_stream) == 0))
1139     {
1140       opj_stream_destroy(jp2_stream);
1141       opj_destroy_codec(jp2_codec);
1142       opj_image_destroy(jp2_image);
1143       parameters=(opj_cparameters_t *) RelinquishMagickMemory(parameters);
1144       ThrowWriterException(DelegateError,"UnableToEncodeImageFile");
1145     }
1146   /*
1147     Free resources.
1148   */
1149   opj_stream_destroy(jp2_stream);
1150   opj_destroy_codec(jp2_codec);
1151   opj_image_destroy(jp2_image);
1152   parameters=(opj_cparameters_t *) RelinquishMagickMemory(parameters);
1153   (void) CloseBlob(image);
1154   return(MagickTrue);
1155 }
1156 #endif
1157