2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 % Read/Write JPEG-2000 Image Format %
20 % Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "magick/studio.h"
43 #include "magick/attribute.h"
44 #include "magick/blob.h"
45 #include "magick/blob-private.h"
46 #include "magick/cache.h"
47 #include "magick/colorspace.h"
48 #include "magick/color.h"
49 #include "magick/color-private.h"
50 #include "magick/exception.h"
51 #include "magick/exception-private.h"
52 #include "magick/image.h"
53 #include "magick/image-private.h"
54 #include "magick/list.h"
55 #include "magick/magick.h"
56 #include "magick/memory_.h"
57 #include "magick/monitor.h"
58 #include "magick/monitor-private.h"
59 #include "magick/option.h"
60 #include "magick/profile.h"
61 #include "magick/quantum-private.h"
62 #include "magick/static.h"
63 #include "magick/statistic.h"
64 #include "magick/string_.h"
65 #include "magick/module.h"
66 #if defined(MAGICKCORE_JP2_DELEGATE)
67 #ifndef JAS_IMAGE_CM_GRAY
68 #define JAS_IMAGE_CM_GRAY JAS_IMAGE_CS_GRAY
70 #ifndef JAS_IMAGE_CM_RGB
71 #define JAS_IMAGE_CM_RGB JAS_IMAGE_CS_RGB
74 #define uchar unsigned char
77 #define ushort unsigned short
80 #define uint unsigned int
82 #if !defined(longlong)
83 #define longlong long long
85 #if !defined(ulonglong)
86 #define ulonglong unsigned long long
91 #undef PACKAGE_TARNAME
92 #undef PACKAGE_VERSION
93 #include "jasper/jasper.h"
96 #undef PACKAGE_TARNAME
97 #undef PACKAGE_VERSION
102 Forward declarations.
104 #if defined(MAGICKCORE_JP2_DELEGATE)
105 static MagickBooleanType
106 WriteJP2Image(const ImageInfo *,Image *);
108 static volatile MagickBooleanType
109 instantiate_jp2 = MagickFalse;
113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
121 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
123 % IsJP2() returns MagickTrue if the image format type, identified by the
124 % magick string, is JP2.
126 % The format of the IsJP2 method is:
128 % MagickBooleanType IsJP2(const unsigned char *magick,const size_t length)
130 % A description of each parameter follows:
132 % o magick: compare image format pattern against these bytes.
134 % o length: Specifies the length of the magick string.
137 static MagickBooleanType IsJP2(const unsigned char *magick,const size_t length)
141 if (memcmp(magick+4,"\152\120\040\040\015",5) == 0)
147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
155 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
157 % IsJPC()() returns MagickTrue if the image format type, identified by the
158 % magick string, is JPC.
160 % The format of the IsJPC method is:
162 % MagickBooleanType IsJPC(const unsigned char *magick,const size_t length)
164 % A description of each parameter follows:
166 % o magick: compare image format pattern against these bytes.
168 % o length: Specifies the length of the magick string.
171 static MagickBooleanType IsJPC(const unsigned char *magick,const size_t length)
175 if (memcmp(magick,"\377\117",2) == 0)
181 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
185 % R e a d J P 2 I m a g e %
189 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
191 % ReadJP2Image() reads a JPEG 2000 Image file (JP2) or JPEG 2000
192 % codestream (JPC) image file and returns it. It allocates the memory
193 % necessary for the new Image structure and returns a pointer to the new
194 % image or set of images.
196 % JP2 support is originally written by Nathan Brown, nathanbrown@letu.edu.
198 % The format of the ReadJP2Image method is:
200 % Image *ReadJP2Image(const ImageInfo *image_info,
201 % ExceptionInfo *exception)
203 % A description of each parameter follows:
205 % o image_info: the image info.
207 % o exception: return any errors or warnings in this structure.
210 #if defined(MAGICKCORE_JP2_DELEGATE)
212 typedef struct _StreamManager
221 static int BlobRead(jas_stream_obj_t *object,char *buffer,const int length)
229 source=(StreamManager *) object;
230 count=ReadBlob(source->image,(size_t) length,(unsigned char *) buffer);
234 static int BlobWrite(jas_stream_obj_t *object,char *buffer,const int length)
242 source=(StreamManager *) object;
243 count=WriteBlob(source->image,(size_t) length,(unsigned char *) buffer);
247 static long BlobSeek(jas_stream_obj_t *object,long offset,int origin)
252 source=(StreamManager *) object;
253 return((long) SeekBlob(source->image,offset,origin));
256 static int BlobClose(jas_stream_obj_t *object)
261 source=(StreamManager *) object;
262 (void) CloseBlob(source->image);
263 source=(StreamManager *) RelinquishMagickMemory(source);
267 static inline size_t MagickMax(const size_t x,const size_t y)
274 static inline size_t MagickMin(const size_t x,const size_t y)
281 static jas_stream_t *JP2StreamManager(Image *image)
283 static jas_stream_ops_t
298 stream=(jas_stream_t *) jas_malloc(sizeof(*stream));
299 if (stream == (jas_stream_t *) NULL)
300 return((jas_stream_t *) NULL);
301 (void) ResetMagickMemory(stream,0,sizeof(*stream));
302 stream->rwlimit_=(-1);
303 stream->obj_=(jas_stream_obj_t *) jas_malloc(sizeof(StreamManager));
304 if (stream->obj_ == (jas_stream_obj_t *) NULL)
305 return((jas_stream_t *) NULL);
306 (void) ResetMagickMemory(stream->obj_,0,sizeof(StreamManager));
307 stream->ops_=(&StreamOperators);
308 stream->openmode_=JAS_STREAM_READ | JAS_STREAM_WRITE | JAS_STREAM_BINARY;
309 stream->bufbase_=(unsigned char *) jas_malloc(JAS_STREAM_BUFSIZE+
310 JAS_STREAM_MAXPUTBACK);
311 if (stream->bufbase_ == (void *) NULL)
313 stream->bufbase_=stream->tinybuf_;
318 stream->bufmode_=JAS_STREAM_FREEBUF | JAS_STREAM_BUFMODEMASK;
319 stream->bufsize_=JAS_STREAM_BUFSIZE;
321 stream->bufstart_=(&stream->bufbase_[JAS_STREAM_MAXPUTBACK]);
322 stream->ptr_=stream->bufstart_;
324 source=(StreamManager *) stream->obj_;
329 static Image *ReadJP2Image(const ImageInfo *image_info,ExceptionInfo *exception)
368 maximum_component_depth,
376 assert(image_info != (const ImageInfo *) NULL);
377 assert(image_info->signature == MagickSignature);
378 if (image_info->debug != MagickFalse)
379 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
380 image_info->filename);
381 assert(exception != (ExceptionInfo *) NULL);
382 assert(exception->signature == MagickSignature);
383 image=AcquireImage(image_info);
384 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
385 if (status == MagickFalse)
387 image=DestroyImageList(image);
388 return((Image *) NULL);
391 Initialize JPEG 2000 API.
393 jp2_stream=JP2StreamManager(image);
394 if (jp2_stream == (jas_stream_t *) NULL)
395 ThrowReaderException(DelegateError,"UnableToManageJP2Stream");
396 jp2_image=jas_image_decode(jp2_stream,-1,0);
397 if (jp2_image == (jas_image_t *) NULL)
399 (void) jas_stream_close(jp2_stream);
400 ThrowReaderException(DelegateError,"UnableToDecodeImageFile");
402 switch (jas_clrspc_fam(jas_image_clrspc(jp2_image)))
404 case JAS_CLRSPC_FAM_RGB:
406 components[0]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_RGB_R);
407 components[1]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_RGB_G);
408 components[2]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_RGB_B);
409 if ((components[0] < 0) || (components[1] < 0) || (components[2] < 0))
411 (void) jas_stream_close(jp2_stream);
412 jas_image_destroy(jp2_image);
413 ThrowReaderException(CorruptImageError,"MissingImageChannel");
416 components[3]=jas_image_getcmptbytype(jp2_image,3);
417 if (components[3] > 0)
419 image->matte=MagickTrue;
424 case JAS_CLRSPC_FAM_GRAY:
426 components[0]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_GRAY_Y);
427 if (components[0] < 0)
429 (void) jas_stream_close(jp2_stream);
430 jas_image_destroy(jp2_image);
431 ThrowReaderException(CorruptImageError,"MissingImageChannel");
436 case JAS_CLRSPC_FAM_YCBCR:
438 components[0]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_YCBCR_Y);
439 components[1]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_YCBCR_CB);
440 components[2]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_YCBCR_CR);
441 if ((components[0] < 0) || (components[1] < 0) || (components[2] < 0))
443 (void) jas_stream_close(jp2_stream);
444 jas_image_destroy(jp2_image);
445 ThrowReaderException(CorruptImageError,"MissingImageChannel");
448 components[3]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_UNKNOWN);
449 if (components[3] > 0)
451 image->matte=MagickTrue;
454 image->colorspace=YCbCrColorspace;
459 (void) jas_stream_close(jp2_stream);
460 jas_image_destroy(jp2_image);
461 ThrowReaderException(CoderError,"ColorspaceModelIsNotSupported");
464 image->columns=jas_image_width(jp2_image);
465 image->rows=jas_image_height(jp2_image);
466 image->compression=JPEG2000Compression;
467 for (i=0; i < (long) number_components; i++)
473 width=(unsigned long) (jas_image_cmptwidth(jp2_image,components[i])*
474 jas_image_cmpthstep(jp2_image,components[i]));
475 height=(unsigned long) (jas_image_cmptheight(jp2_image,components[i])*
476 jas_image_cmptvstep(jp2_image,components[i]));
477 x_step[i]=(unsigned int) jas_image_cmpthstep(jp2_image,components[i]);
478 y_step[i]=(unsigned int) jas_image_cmptvstep(jp2_image,components[i]);
479 if ((width != image->columns) || (height != image->rows) ||
480 (jas_image_cmpttlx(jp2_image,components[i]) != 0) ||
481 (jas_image_cmpttly(jp2_image,components[i]) != 0) ||
482 (x_step[i] != 1) || (y_step[i] != 1) ||
483 (jas_image_cmptsgnd(jp2_image,components[i]) != MagickFalse))
485 (void) jas_stream_close(jp2_stream);
486 jas_image_destroy(jp2_image);
487 ThrowReaderException(CoderError,"IrregularChannelGeometryNotSupported");
491 Convert JPEG 2000 pixels.
493 image->matte=number_components > 3 ? MagickTrue : MagickFalse;
494 maximum_component_depth=0;
495 for (i=0; i < (long) number_components; i++)
497 maximum_component_depth=(unsigned int) MagickMax((size_t)
498 jas_image_cmptprec(jp2_image,components[i]),(size_t)
499 maximum_component_depth);
500 pixels[i]=jas_matrix_create(1,(int) (image->columns/x_step[i]));
501 if (pixels[i] == (jas_matrix_t *) NULL)
503 for (--i; i >= 0; i--)
504 jas_matrix_destroy(pixels[i]);
505 jas_image_destroy(jp2_image);
506 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
509 image->depth=maximum_component_depth;
510 if (image_info->ping != MagickFalse)
512 (void) jas_stream_close(jp2_stream);
513 jas_image_destroy(jp2_image);
514 return(GetFirstImageInList(image));
516 for (i=0; i < (long) number_components; i++)
517 range[i]=GetQuantumRange((unsigned long) jas_image_cmptprec(jp2_image,
519 for (y=0; y < (long) image->rows; y++)
521 q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
522 if (q == (PixelPacket *) NULL)
524 for (i=0; i < (long) number_components; i++)
525 (void) jas_image_readcmpt(jp2_image,(short) components[i],0,
526 ((unsigned int) y)/y_step[i],((unsigned int) image->columns)/x_step[i],
528 switch (number_components)
535 for (x=0; x < (long) image->columns; x++)
537 pixel=(QuantumAny) jas_matrix_getv(pixels[0],x/x_step[0]);
538 q->red=(Quantum) ScaleAnyToQuantum((QuantumAny) pixel,range[0]);
550 for (x=0; x < (long) image->columns; x++)
552 pixel=(QuantumAny) jas_matrix_getv(pixels[0],x/x_step[0]);
553 q->red=(Quantum) ScaleAnyToQuantum((QuantumAny) pixel,range[0]);
554 pixel=(QuantumAny) jas_matrix_getv(pixels[1],x/x_step[1]);
555 q->green=(Quantum) ScaleAnyToQuantum((QuantumAny) pixel,range[1]);
556 pixel=(QuantumAny) jas_matrix_getv(pixels[2],x/x_step[2]);
557 q->blue=(Quantum) ScaleAnyToQuantum((QuantumAny) pixel,range[2]);
567 for (x=0; x < (long) image->columns; x++)
569 pixel=(QuantumAny) jas_matrix_getv(pixels[0],x/x_step[0]);
570 q->red=(Quantum) ScaleAnyToQuantum((QuantumAny) pixel,range[0]);
571 pixel=(QuantumAny) jas_matrix_getv(pixels[1],x/x_step[1]);
572 q->green=(Quantum) ScaleAnyToQuantum((QuantumAny) pixel,range[1]);
573 pixel=(QuantumAny) jas_matrix_getv(pixels[2],x/x_step[2]);
574 q->blue=(Quantum) ScaleAnyToQuantum((QuantumAny) pixel,range[2]);
575 pixel=(QuantumAny) jas_matrix_getv(pixels[3],x/x_step[3]);
576 q->opacity=(Quantum) (QuantumRange-
577 ScaleAnyToQuantum((QuantumAny) pixel,range[3]));
583 if (SyncAuthenticPixels(image,exception) == MagickFalse)
585 status=SetImageProgress(image,LoadImageTag,y,image->rows);
586 if (status == MagickFalse)
589 cm_profile=jas_image_cmprof(jp2_image);
590 icc_profile=(jas_iccprof_t *) NULL;
591 if (cm_profile != (jas_cmprof_t *) NULL)
592 icc_profile=jas_iccprof_createfromcmprof(cm_profile);
593 if (icc_profile != (jas_iccprof_t *) NULL)
598 icc_stream=jas_stream_memopen(NULL,0);
599 if ((icc_stream != (jas_stream_t *) NULL) &&
600 (jas_iccprof_save(icc_profile,icc_stream) == 0) &&
601 (jas_stream_flush(icc_stream) == 0))
611 Extract the icc profile, handle errors without much noise.
613 blob=(jas_stream_memobj_t *) icc_stream->obj_;
614 if (image->debug != MagickFalse)
615 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
616 "Profile: ICC, %lu bytes",(unsigned long) blob->len_);
617 profile=AcquireStringInfo(blob->len_);
618 SetStringInfoDatum(profile,blob->buf_);
619 icc_profile=(StringInfo *) GetImageProfile(image,"icc");
620 if (icc_profile == (StringInfo *) NULL)
621 (void) SetImageProfile(image,"icc",profile);
623 (void) ConcatenateStringInfo(icc_profile,profile);
624 profile=DestroyStringInfo(profile);
625 (void) jas_stream_close(icc_stream);
628 (void) jas_stream_close(jp2_stream);
629 jas_image_destroy(jp2_image);
630 for (i=0; i < (long) number_components; i++)
631 jas_matrix_destroy(pixels[i]);
632 return(GetFirstImageInList(image));
637 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
641 % R e g i s t e r J P 2 I m a g e %
645 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
647 % RegisterJP2Image() adds attributes for the JP2 image format to the list of
648 % supported formats. The attributes include the image format tag, a method
649 % method to read and/or write the format, whether the format supports the
650 % saving of more than one frame to the same file or blob, whether the format
651 % supports native in-memory I/O, and a brief description of the format.
653 % The format of the RegisterJP2Image method is:
655 % unsigned long RegisterJP2Image(void)
658 ModuleExport unsigned long RegisterJP2Image(void)
663 entry=SetMagickInfo("JP2");
664 entry->description=ConstantString("JPEG-2000 File Format Syntax");
665 entry->module=ConstantString("JP2");
666 entry->magick=(IsImageFormatHandler *) IsJP2;
667 entry->adjoin=MagickFalse;
668 entry->seekable_stream=MagickTrue;
669 entry->thread_support=NoThreadSupport;
670 #if defined(MAGICKCORE_JP2_DELEGATE)
671 entry->decoder=(DecodeImageHandler *) ReadJP2Image;
672 entry->encoder=(EncodeImageHandler *) WriteJP2Image;
674 (void) RegisterMagickInfo(entry);
675 entry=SetMagickInfo("JPC");
676 entry->description=ConstantString("JPEG-2000 Code Stream Syntax");
677 entry->module=ConstantString("JP2");
678 entry->magick=(IsImageFormatHandler *) IsJPC;
679 entry->adjoin=MagickFalse;
680 entry->seekable_stream=MagickTrue;
681 entry->thread_support=NoThreadSupport;
682 #if defined(MAGICKCORE_JP2_DELEGATE)
683 entry->decoder=(DecodeImageHandler *) ReadJP2Image;
684 entry->encoder=(EncodeImageHandler *) WriteJP2Image;
686 (void) RegisterMagickInfo(entry);
687 entry=SetMagickInfo("J2C");
688 entry->description=ConstantString("JPEG-2000 Code Stream Syntax");
689 entry->module=ConstantString("JP2");
690 entry->magick=(IsImageFormatHandler *) IsJPC;
691 entry->adjoin=MagickFalse;
692 entry->seekable_stream=MagickTrue;
693 entry->thread_support=NoThreadSupport;
694 #if defined(MAGICKCORE_JP2_DELEGATE)
695 entry->decoder=(DecodeImageHandler *) ReadJP2Image;
696 entry->encoder=(EncodeImageHandler *) WriteJP2Image;
698 (void) RegisterMagickInfo(entry);
699 entry=SetMagickInfo("JPX");
700 entry->description=ConstantString("JPEG-2000 File Format Syntax");
701 entry->module=ConstantString("JP2");
702 entry->magick=(IsImageFormatHandler *) IsJPC;
703 entry->adjoin=MagickFalse;
704 entry->seekable_stream=MagickTrue;
705 entry->thread_support=NoThreadSupport;
706 #if defined(MAGICKCORE_JP2_DELEGATE)
707 entry->decoder=(DecodeImageHandler *) ReadJP2Image;
708 entry->encoder=(EncodeImageHandler *) WriteJP2Image;
710 (void) RegisterMagickInfo(entry);
711 entry=SetMagickInfo("PGX");
712 entry->description=ConstantString("JPEG-2000 VM Format");
713 entry->module=ConstantString("JP2");
714 entry->magick=(IsImageFormatHandler *) IsJPC;
715 entry->adjoin=MagickFalse;
716 entry->seekable_stream=MagickTrue;
717 entry->thread_support=NoThreadSupport;
718 #if defined(MAGICKCORE_JP2_DELEGATE)
719 entry->decoder=(DecodeImageHandler *) ReadJP2Image;
721 (void) RegisterMagickInfo(entry);
722 #if defined(MAGICKCORE_JP2_DELEGATE)
723 if (instantiate_jp2 == MagickFalse)
726 instantiate_jp2=MagickTrue;
729 return(MagickImageCoderSignature);
733 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
737 % U n r e g i s t e r J P 2 I m a g e %
741 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
743 % UnregisterJP2Image() removes format registrations made by the JP2 module
744 % from the list of supported formats.
746 % The format of the UnregisterJP2Image method is:
748 % UnregisterJP2Image(void)
751 ModuleExport void UnregisterJP2Image(void)
753 (void) UnregisterMagickInfo("PGX");
754 (void) UnregisterMagickInfo("J2C");
755 (void) UnregisterMagickInfo("JPC");
756 (void) UnregisterMagickInfo("JP2");
757 #if defined(MAGICKCORE_JP2_DELEGATE)
758 if (instantiate_jp2 != MagickFalse)
761 instantiate_jp2=MagickFalse;
766 #if defined(MAGICKCORE_JP2_DELEGATE)
768 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
772 % W r i t e J P 2 I m a g e %
776 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
778 % WriteJP2Image() writes an image in the JPEG 2000 image format.
780 % JP2 support originally written by Nathan Brown, nathanbrown@letu.edu
782 % The format of the WriteJP2Image method is:
784 % MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image)
786 % A description of each parameter follows.
788 % o image_info: the image info.
790 % o image: The image.
793 static MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image)
797 magick[MaxTextExtent],
825 register const PixelPacket
838 assert(image_info != (const ImageInfo *) NULL);
839 assert(image_info->signature == MagickSignature);
840 assert(image != (Image *) NULL);
841 assert(image->signature == MagickSignature);
842 if (image->debug != MagickFalse)
843 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
844 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
845 if (status == MagickFalse)
848 Intialize JPEG 2000 API.
850 if (image->colorspace != RGBColorspace)
851 (void) TransformImageColorspace(image,RGBColorspace);
852 jp2_stream=JP2StreamManager(image);
853 if (jp2_stream == (jas_stream_t *) NULL)
854 ThrowWriterException(DelegateError,"UnableToManageJP2Stream");
855 number_components=image->matte ? 4UL : 3UL;
856 if ((image_info->type != TrueColorType) &&
857 IsGrayImage(image,&image->exception))
859 if ((image->columns != (unsigned int) image->columns) ||
860 (image->rows != (unsigned int) image->rows))
861 ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
862 (void) ResetMagickMemory(&component_info,0,sizeof(component_info));
863 for (i=0; i < (long) number_components; i++)
865 component_info[i].tlx=0;
866 component_info[i].tly=0;
867 component_info[i].hstep=1;
868 component_info[i].vstep=1;
869 component_info[i].width=(unsigned int) image->columns;
870 component_info[i].height=(unsigned int) image->rows;
871 component_info[i].prec=(int) MagickMax(MagickMin(image->depth,16),2);
872 component_info[i].sgnd=MagickFalse;
874 jp2_image=jas_image_create((int) number_components,component_info,
876 if (jp2_image == (jas_image_t *) NULL)
877 ThrowWriterException(DelegateError,"UnableToCreateImage");
878 if (number_components == 1)
883 jas_image_setclrspc(jp2_image,JAS_CLRSPC_SGRAY);
884 jas_image_setcmpttype(jp2_image,0,
885 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y));
892 jas_image_setclrspc(jp2_image,JAS_CLRSPC_SRGB);
893 jas_image_setcmpttype(jp2_image,0,
894 (jas_image_cmpttype_t) JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));
895 jas_image_setcmpttype(jp2_image,1,
896 (jas_image_cmpttype_t) JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));
897 jas_image_setcmpttype(jp2_image,2,
898 (jas_image_cmpttype_t) JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));
899 if (number_components == 4)
900 jas_image_setcmpttype(jp2_image,3,JAS_IMAGE_CT_OPACITY);
903 Convert to JPEG 2000 pixels.
905 for (i=0; i < (long) number_components; i++)
907 pixels[i]=jas_matrix_create(1,(int) image->columns);
908 if (pixels[i] == (jas_matrix_t *) NULL)
910 for (x=0; x < i; x++)
911 jas_matrix_destroy(pixels[x]);
912 jas_image_destroy(jp2_image);
913 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
916 range=GetQuantumRange((unsigned long) component_info[0].prec);
917 for (y=0; y < (long) image->rows; y++)
919 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
920 if (p == (const PixelPacket *) NULL)
922 for (x=0; x < (long) image->columns; x++)
924 if (number_components == 1)
925 jas_matrix_setv(pixels[0],x,(jas_seqent_t) ScaleQuantumToAny(
926 PixelIntensityToQuantum(p),range));
929 jas_matrix_setv(pixels[0],x,(jas_seqent_t)
930 ScaleQuantumToAny(p->red,range));
931 jas_matrix_setv(pixels[1],x,(jas_seqent_t)
932 ScaleQuantumToAny(p->green,range));
933 jas_matrix_setv(pixels[2],x,(jas_seqent_t)
934 ScaleQuantumToAny(p->blue,range));
935 if (number_components > 3)
936 jas_matrix_setv(pixels[3],x,(jas_seqent_t)
937 ScaleQuantumToAny((Quantum) (GetAlphaPixelComponent(p)),range));
941 for (i=0; i < (long) number_components; i++)
942 (void) jas_image_writecmpt(jp2_image,(short) i,0,(unsigned int) y,
943 (unsigned int) image->columns,1,pixels[i]);
944 status=SetImageProgress(image,SaveImageTag,y,image->rows);
945 if (status == MagickFalse)
948 (void) CopyMagickString(magick,image_info->magick,MaxTextExtent);
949 if (LocaleCompare(magick,"J2C") == 0)
950 (void) CopyMagickString(magick,"JPC",MaxTextExtent);
952 format=jas_image_strtofmt(magick);
953 options=(char *) NULL;
954 ResetImageOptionIterator(image_info);
955 key=GetNextImageOption(image_info);
956 for ( ; key != (char *) NULL; key=GetNextImageOption(image_info))
958 option=GetImageOption(image_info,key);
959 if (option == (const char *) NULL)
961 if (LocaleNCompare(key,"jp2:",4) == 0)
963 (void) ConcatenateString(&options,key+4);
966 (void) ConcatenateString(&options,"=");
967 (void) ConcatenateString(&options,option);
969 (void) ConcatenateString(&options," ");
972 option=GetImageOption(image_info,"jp2:rate");
973 if ((option == (const char *) NULL) &&
974 (image_info->compression != LosslessJPEGCompression) &&
975 (image->quality != UndefinedCompressionQuality) &&
976 ((double) image->quality <= 99.5) &&
977 ((image->rows*image->columns) > 2500))
980 option[MaxTextExtent];
989 alpha=115.0-image->quality;
990 rate=100.0/(alpha*alpha);
992 header_size+=(number_components-1)*142;
993 number_pixels=(double) image->rows*image->columns*number_components*
994 (GetImageQuantumDepth(image,MagickTrue)/8);
995 target_size=(number_pixels*rate)+header_size;
996 rate=target_size/number_pixels;
997 (void) FormatMagickString(option,MaxTextExtent,"rate=%g",rate);
998 (void) ConcatenateString(&options,option);
1000 status=jas_image_encode(jp2_image,jp2_stream,format,options) != 0 ?
1001 MagickTrue : MagickFalse;
1002 (void) jas_stream_close(jp2_stream);
1003 for (i=0; i < (long) number_components; i++)
1004 jas_matrix_destroy(pixels[i]);
1005 jas_image_destroy(jp2_image);
1006 if (status != MagickFalse)
1007 ThrowWriterException(DelegateError,"UnableToEncodeImageFile");