2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 % Read/Write JPEG-2000 Image Format %
20 % Copyright 1999-2011 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(ssize_tssize_t)
83 #define ssize_tssize_t long long
85 #if !defined(ussize_tssize_t)
86 #define ussize_tssize_t 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);
264 source=(StreamManager *) NULL;
268 static inline size_t MagickMax(const size_t x,const size_t y)
275 static inline size_t MagickMin(const size_t x,const size_t y)
282 static jas_stream_t *JP2StreamManager(Image *image)
284 static jas_stream_ops_t
299 stream=(jas_stream_t *) jas_malloc(sizeof(*stream));
300 if (stream == (jas_stream_t *) NULL)
301 return((jas_stream_t *) NULL);
302 (void) ResetMagickMemory(stream,0,sizeof(*stream));
303 stream->rwlimit_=(-1);
304 stream->obj_=(jas_stream_obj_t *) jas_malloc(sizeof(StreamManager));
305 if (stream->obj_ == (jas_stream_obj_t *) NULL)
306 return((jas_stream_t *) NULL);
307 (void) ResetMagickMemory(stream->obj_,0,sizeof(StreamManager));
308 stream->ops_=(&StreamOperators);
309 stream->openmode_=JAS_STREAM_READ | JAS_STREAM_WRITE | JAS_STREAM_BINARY;
310 stream->bufbase_=(unsigned char *) jas_malloc(JAS_STREAM_BUFSIZE+
311 JAS_STREAM_MAXPUTBACK);
312 if (stream->bufbase_ == (void *) NULL)
314 stream->bufbase_=stream->tinybuf_;
319 stream->bufmode_=JAS_STREAM_FREEBUF | JAS_STREAM_BUFMODEMASK;
320 stream->bufsize_=JAS_STREAM_BUFSIZE;
322 stream->bufstart_=(&stream->bufbase_[JAS_STREAM_MAXPUTBACK]);
323 stream->ptr_=stream->bufstart_;
325 source=(StreamManager *) stream->obj_;
330 static Image *ReadJP2Image(const ImageInfo *image_info,ExceptionInfo *exception)
369 maximum_component_depth,
377 assert(image_info != (const ImageInfo *) NULL);
378 assert(image_info->signature == MagickSignature);
379 if (image_info->debug != MagickFalse)
380 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
381 image_info->filename);
382 assert(exception != (ExceptionInfo *) NULL);
383 assert(exception->signature == MagickSignature);
384 image=AcquireImage(image_info);
385 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
386 if (status == MagickFalse)
388 image=DestroyImageList(image);
389 return((Image *) NULL);
392 Initialize JPEG 2000 API.
394 jp2_stream=JP2StreamManager(image);
395 if (jp2_stream == (jas_stream_t *) NULL)
396 ThrowReaderException(DelegateError,"UnableToManageJP2Stream");
397 jp2_image=jas_image_decode(jp2_stream,-1,0);
398 if (jp2_image == (jas_image_t *) NULL)
400 (void) jas_stream_close(jp2_stream);
401 ThrowReaderException(DelegateError,"UnableToDecodeImageFile");
403 switch (jas_clrspc_fam(jas_image_clrspc(jp2_image)))
405 case JAS_CLRSPC_FAM_RGB:
407 components[0]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_RGB_R);
408 components[1]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_RGB_G);
409 components[2]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_RGB_B);
410 if ((components[0] < 0) || (components[1] < 0) || (components[2] < 0))
412 (void) jas_stream_close(jp2_stream);
413 jas_image_destroy(jp2_image);
414 ThrowReaderException(CorruptImageError,"MissingImageChannel");
417 components[3]=jas_image_getcmptbytype(jp2_image,3);
418 if (components[3] > 0)
420 image->matte=MagickTrue;
425 case JAS_CLRSPC_FAM_GRAY:
427 components[0]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_GRAY_Y);
428 if (components[0] < 0)
430 (void) jas_stream_close(jp2_stream);
431 jas_image_destroy(jp2_image);
432 ThrowReaderException(CorruptImageError,"MissingImageChannel");
437 case JAS_CLRSPC_FAM_YCBCR:
439 components[0]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_YCBCR_Y);
440 components[1]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_YCBCR_CB);
441 components[2]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_YCBCR_CR);
442 if ((components[0] < 0) || (components[1] < 0) || (components[2] < 0))
444 (void) jas_stream_close(jp2_stream);
445 jas_image_destroy(jp2_image);
446 ThrowReaderException(CorruptImageError,"MissingImageChannel");
449 components[3]=jas_image_getcmptbytype(jp2_image,JAS_IMAGE_CT_UNKNOWN);
450 if (components[3] > 0)
452 image->matte=MagickTrue;
455 image->colorspace=YCbCrColorspace;
460 (void) jas_stream_close(jp2_stream);
461 jas_image_destroy(jp2_image);
462 ThrowReaderException(CoderError,"ColorspaceModelIsNotSupported");
465 image->columns=jas_image_width(jp2_image);
466 image->rows=jas_image_height(jp2_image);
467 image->compression=JPEG2000Compression;
468 for (i=0; i < (ssize_t) number_components; i++)
474 width=(size_t) (jas_image_cmptwidth(jp2_image,components[i])*
475 jas_image_cmpthstep(jp2_image,components[i]));
476 height=(size_t) (jas_image_cmptheight(jp2_image,components[i])*
477 jas_image_cmptvstep(jp2_image,components[i]));
478 x_step[i]=(unsigned int) jas_image_cmpthstep(jp2_image,components[i]);
479 y_step[i]=(unsigned int) jas_image_cmptvstep(jp2_image,components[i]);
480 if ((width != image->columns) || (height != image->rows) ||
481 (jas_image_cmpttlx(jp2_image,components[i]) != 0) ||
482 (jas_image_cmpttly(jp2_image,components[i]) != 0) ||
483 (x_step[i] != 1) || (y_step[i] != 1) ||
484 (jas_image_cmptsgnd(jp2_image,components[i]) != MagickFalse))
486 (void) jas_stream_close(jp2_stream);
487 jas_image_destroy(jp2_image);
488 ThrowReaderException(CoderError,"IrregularChannelGeometryNotSupported");
492 Convert JPEG 2000 pixels.
494 image->matte=number_components > 3 ? MagickTrue : MagickFalse;
495 maximum_component_depth=0;
496 for (i=0; i < (ssize_t) number_components; i++)
498 maximum_component_depth=(unsigned int) MagickMax((size_t)
499 jas_image_cmptprec(jp2_image,components[i]),(size_t)
500 maximum_component_depth);
501 pixels[i]=jas_matrix_create(1,(int) (image->columns/x_step[i]));
502 if (pixels[i] == (jas_matrix_t *) NULL)
504 for (--i; i >= 0; i--)
505 jas_matrix_destroy(pixels[i]);
506 jas_image_destroy(jp2_image);
507 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
510 image->depth=maximum_component_depth;
511 if (image_info->ping != MagickFalse)
513 (void) jas_stream_close(jp2_stream);
514 jas_image_destroy(jp2_image);
515 return(GetFirstImageInList(image));
517 for (i=0; i < (ssize_t) number_components; i++)
518 range[i]=GetQuantumRange((size_t) jas_image_cmptprec(jp2_image,
520 for (y=0; y < (ssize_t) image->rows; y++)
522 q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
523 if (q == (PixelPacket *) NULL)
525 for (i=0; i < (ssize_t) number_components; i++)
526 (void) jas_image_readcmpt(jp2_image,(short) components[i],0,
527 (jas_image_coord_t) (y/y_step[i]),(jas_image_coord_t) (image->columns/
528 x_step[i]),1,pixels[i]);
529 switch (number_components)
536 for (x=0; x < (ssize_t) image->columns; x++)
538 pixel=(QuantumAny) jas_matrix_getv(pixels[0],x/x_step[0]);
539 q->red=(Quantum) ScaleAnyToQuantum((QuantumAny) pixel,range[0]);
540 SetGreenPixelComponent(q,GetRedPixelComponent(q));
541 SetBluePixelComponent(q,GetRedPixelComponent(q));
551 for (x=0; x < (ssize_t) image->columns; x++)
553 pixel=(QuantumAny) jas_matrix_getv(pixels[0],x/x_step[0]);
554 q->red=(Quantum) ScaleAnyToQuantum((QuantumAny) pixel,range[0]);
555 pixel=(QuantumAny) jas_matrix_getv(pixels[1],x/x_step[1]);
556 q->green=(Quantum) ScaleAnyToQuantum((QuantumAny) pixel,range[1]);
557 pixel=(QuantumAny) jas_matrix_getv(pixels[2],x/x_step[2]);
558 q->blue=(Quantum) ScaleAnyToQuantum((QuantumAny) pixel,range[2]);
568 for (x=0; x < (ssize_t) image->columns; x++)
570 pixel=(QuantumAny) jas_matrix_getv(pixels[0],x/x_step[0]);
571 q->red=(Quantum) ScaleAnyToQuantum((QuantumAny) pixel,range[0]);
572 pixel=(QuantumAny) jas_matrix_getv(pixels[1],x/x_step[1]);
573 q->green=(Quantum) ScaleAnyToQuantum((QuantumAny) pixel,range[1]);
574 pixel=(QuantumAny) jas_matrix_getv(pixels[2],x/x_step[2]);
575 q->blue=(Quantum) ScaleAnyToQuantum((QuantumAny) pixel,range[2]);
576 pixel=(QuantumAny) jas_matrix_getv(pixels[3],x/x_step[3]);
577 q->opacity=(Quantum) (QuantumRange-
578 ScaleAnyToQuantum((QuantumAny) pixel,range[3]));
584 if (SyncAuthenticPixels(image,exception) == MagickFalse)
586 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
588 if (status == MagickFalse)
591 cm_profile=jas_image_cmprof(jp2_image);
592 icc_profile=(jas_iccprof_t *) NULL;
593 if (cm_profile != (jas_cmprof_t *) NULL)
594 icc_profile=jas_iccprof_createfromcmprof(cm_profile);
595 if (icc_profile != (jas_iccprof_t *) NULL)
600 icc_stream=jas_stream_memopen(NULL,0);
601 if ((icc_stream != (jas_stream_t *) NULL) &&
602 (jas_iccprof_save(icc_profile,icc_stream) == 0) &&
603 (jas_stream_flush(icc_stream) == 0))
613 Extract the icc profile, handle errors without much noise.
615 blob=(jas_stream_memobj_t *) icc_stream->obj_;
616 if (image->debug != MagickFalse)
617 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
618 "Profile: ICC, %.20g bytes",(double) blob->len_);
619 profile=AcquireStringInfo(blob->len_);
620 SetStringInfoDatum(profile,blob->buf_);
621 icc_profile=(StringInfo *) GetImageProfile(image,"icc");
622 if (icc_profile == (StringInfo *) NULL)
623 (void) SetImageProfile(image,"icc",profile);
625 (void) ConcatenateStringInfo(icc_profile,profile);
626 profile=DestroyStringInfo(profile);
627 (void) jas_stream_close(icc_stream);
630 (void) jas_stream_close(jp2_stream);
631 jas_image_destroy(jp2_image);
632 for (i=0; i < (ssize_t) number_components; i++)
633 jas_matrix_destroy(pixels[i]);
634 return(GetFirstImageInList(image));
639 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
643 % R e g i s t e r J P 2 I m a g e %
647 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
649 % RegisterJP2Image() adds attributes for the JP2 image format to the list of
650 % supported formats. The attributes include the image format tag, a method
651 % method to read and/or write the format, whether the format supports the
652 % saving of more than one frame to the same file or blob, whether the format
653 % supports native in-memory I/O, and a brief description of the format.
655 % The format of the RegisterJP2Image method is:
657 % size_t RegisterJP2Image(void)
660 ModuleExport size_t RegisterJP2Image(void)
665 entry=SetMagickInfo("JP2");
666 entry->description=ConstantString("JPEG-2000 File Format Syntax");
667 entry->module=ConstantString("JP2");
668 entry->magick=(IsImageFormatHandler *) IsJP2;
669 entry->adjoin=MagickFalse;
670 entry->seekable_stream=MagickTrue;
671 entry->thread_support=NoThreadSupport;
672 #if defined(MAGICKCORE_JP2_DELEGATE)
673 entry->decoder=(DecodeImageHandler *) ReadJP2Image;
674 entry->encoder=(EncodeImageHandler *) WriteJP2Image;
676 (void) RegisterMagickInfo(entry);
677 entry=SetMagickInfo("JPC");
678 entry->description=ConstantString("JPEG-2000 Code Stream Syntax");
679 entry->module=ConstantString("JP2");
680 entry->magick=(IsImageFormatHandler *) IsJPC;
681 entry->adjoin=MagickFalse;
682 entry->seekable_stream=MagickTrue;
683 entry->thread_support=NoThreadSupport;
684 #if defined(MAGICKCORE_JP2_DELEGATE)
685 entry->decoder=(DecodeImageHandler *) ReadJP2Image;
686 entry->encoder=(EncodeImageHandler *) WriteJP2Image;
688 (void) RegisterMagickInfo(entry);
689 entry=SetMagickInfo("J2C");
690 entry->description=ConstantString("JPEG-2000 Code Stream Syntax");
691 entry->module=ConstantString("JP2");
692 entry->magick=(IsImageFormatHandler *) IsJPC;
693 entry->adjoin=MagickFalse;
694 entry->seekable_stream=MagickTrue;
695 entry->thread_support=NoThreadSupport;
696 #if defined(MAGICKCORE_JP2_DELEGATE)
697 entry->decoder=(DecodeImageHandler *) ReadJP2Image;
698 entry->encoder=(EncodeImageHandler *) WriteJP2Image;
700 (void) RegisterMagickInfo(entry);
701 entry=SetMagickInfo("JPX");
702 entry->description=ConstantString("JPEG-2000 File Format Syntax");
703 entry->module=ConstantString("JP2");
704 entry->magick=(IsImageFormatHandler *) IsJPC;
705 entry->adjoin=MagickFalse;
706 entry->seekable_stream=MagickTrue;
707 entry->thread_support=NoThreadSupport;
708 #if defined(MAGICKCORE_JP2_DELEGATE)
709 entry->decoder=(DecodeImageHandler *) ReadJP2Image;
710 entry->encoder=(EncodeImageHandler *) WriteJP2Image;
712 (void) RegisterMagickInfo(entry);
713 entry=SetMagickInfo("PGX");
714 entry->description=ConstantString("JPEG-2000 VM Format");
715 entry->module=ConstantString("JP2");
716 entry->magick=(IsImageFormatHandler *) IsJPC;
717 entry->adjoin=MagickFalse;
718 entry->seekable_stream=MagickTrue;
719 entry->thread_support=NoThreadSupport;
720 #if defined(MAGICKCORE_JP2_DELEGATE)
721 entry->decoder=(DecodeImageHandler *) ReadJP2Image;
723 (void) RegisterMagickInfo(entry);
724 #if defined(MAGICKCORE_JP2_DELEGATE)
725 if (instantiate_jp2 == MagickFalse)
728 instantiate_jp2=MagickTrue;
731 return(MagickImageCoderSignature);
735 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
739 % U n r e g i s t e r J P 2 I m a g e %
743 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
745 % UnregisterJP2Image() removes format registrations made by the JP2 module
746 % from the list of supported formats.
748 % The format of the UnregisterJP2Image method is:
750 % UnregisterJP2Image(void)
753 ModuleExport void UnregisterJP2Image(void)
755 (void) UnregisterMagickInfo("PGX");
756 (void) UnregisterMagickInfo("J2C");
757 (void) UnregisterMagickInfo("JPC");
758 (void) UnregisterMagickInfo("JP2");
759 #if defined(MAGICKCORE_JP2_DELEGATE)
760 if (instantiate_jp2 != MagickFalse)
763 instantiate_jp2=MagickFalse;
768 #if defined(MAGICKCORE_JP2_DELEGATE)
770 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
774 % W r i t e J P 2 I m a g e %
778 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
780 % WriteJP2Image() writes an image in the JPEG 2000 image format.
782 % JP2 support originally written by Nathan Brown, nathanbrown@letu.edu
784 % The format of the WriteJP2Image method is:
786 % MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image)
788 % A description of each parameter follows.
790 % o image_info: the image info.
792 % o image: The image.
795 static MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image)
799 magick[MaxTextExtent],
827 register const PixelPacket
840 assert(image_info != (const ImageInfo *) NULL);
841 assert(image_info->signature == MagickSignature);
842 assert(image != (Image *) NULL);
843 assert(image->signature == MagickSignature);
844 if (image->debug != MagickFalse)
845 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
846 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
847 if (status == MagickFalse)
850 Intialize JPEG 2000 API.
852 if (image->colorspace != RGBColorspace)
853 (void) TransformImageColorspace(image,RGBColorspace);
854 jp2_stream=JP2StreamManager(image);
855 if (jp2_stream == (jas_stream_t *) NULL)
856 ThrowWriterException(DelegateError,"UnableToManageJP2Stream");
857 number_components=image->matte ? 4UL : 3UL;
858 if ((image_info->type != TrueColorType) &&
859 (IsGrayImage(image,&image->exception) != MagickFalse))
861 if ((image->columns != (unsigned int) image->columns) ||
862 (image->rows != (unsigned int) image->rows))
863 ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
864 (void) ResetMagickMemory(&component_info,0,sizeof(component_info));
865 for (i=0; i < (ssize_t) number_components; i++)
867 component_info[i].tlx=0;
868 component_info[i].tly=0;
869 component_info[i].hstep=1;
870 component_info[i].vstep=1;
871 component_info[i].width=(unsigned int) image->columns;
872 component_info[i].height=(unsigned int) image->rows;
873 component_info[i].prec=(int) MagickMax(MagickMin(image->depth,16),2);
874 component_info[i].sgnd=MagickFalse;
876 jp2_image=jas_image_create((int) number_components,component_info,
878 if (jp2_image == (jas_image_t *) NULL)
879 ThrowWriterException(DelegateError,"UnableToCreateImage");
880 if (number_components == 1)
885 jas_image_setclrspc(jp2_image,JAS_CLRSPC_SGRAY);
886 jas_image_setcmpttype(jp2_image,0,
887 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y));
894 jas_image_setclrspc(jp2_image,JAS_CLRSPC_SRGB);
895 jas_image_setcmpttype(jp2_image,0,
896 (jas_image_cmpttype_t) JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R));
897 jas_image_setcmpttype(jp2_image,1,
898 (jas_image_cmpttype_t) JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G));
899 jas_image_setcmpttype(jp2_image,2,
900 (jas_image_cmpttype_t) JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B));
901 if (number_components == 4)
902 jas_image_setcmpttype(jp2_image,3,JAS_IMAGE_CT_OPACITY);
905 Convert to JPEG 2000 pixels.
907 for (i=0; i < (ssize_t) number_components; i++)
909 pixels[i]=jas_matrix_create(1,(int) image->columns);
910 if (pixels[i] == (jas_matrix_t *) NULL)
912 for (x=0; x < i; x++)
913 jas_matrix_destroy(pixels[x]);
914 jas_image_destroy(jp2_image);
915 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
918 range=GetQuantumRange((size_t) component_info[0].prec);
919 for (y=0; y < (ssize_t) image->rows; y++)
921 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
922 if (p == (const PixelPacket *) NULL)
924 for (x=0; x < (ssize_t) image->columns; x++)
926 if (number_components == 1)
927 jas_matrix_setv(pixels[0],x,(jas_seqent_t) ScaleQuantumToAny(
928 PixelIntensityToQuantum(p),range));
931 jas_matrix_setv(pixels[0],x,(jas_seqent_t)
932 ScaleQuantumToAny(GetRedPixelComponent(p),range));
933 jas_matrix_setv(pixels[1],x,(jas_seqent_t)
934 ScaleQuantumToAny(GetGreenPixelComponent(p),range));
935 jas_matrix_setv(pixels[2],x,(jas_seqent_t)
936 ScaleQuantumToAny(GetBluePixelComponent(p),range));
937 if (number_components > 3)
938 jas_matrix_setv(pixels[3],x,(jas_seqent_t)
939 ScaleQuantumToAny((Quantum) (GetAlphaPixelComponent(p)),range));
943 for (i=0; i < (ssize_t) number_components; i++)
944 (void) jas_image_writecmpt(jp2_image,(short) i,0,(unsigned int) y,
945 (unsigned int) image->columns,1,pixels[i]);
946 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
948 if (status == MagickFalse)
951 (void) CopyMagickString(magick,image_info->magick,MaxTextExtent);
952 if (LocaleCompare(magick,"J2C") == 0)
953 (void) CopyMagickString(magick,"JPC",MaxTextExtent);
955 format=jas_image_strtofmt(magick);
956 options=(char *) NULL;
957 ResetImageOptionIterator(image_info);
958 key=GetNextImageOption(image_info);
959 for ( ; key != (char *) NULL; key=GetNextImageOption(image_info))
961 option=GetImageOption(image_info,key);
962 if (option == (const char *) NULL)
964 if (LocaleNCompare(key,"jp2:",4) == 0)
966 (void) ConcatenateString(&options,key+4);
969 (void) ConcatenateString(&options,"=");
970 (void) ConcatenateString(&options,option);
972 (void) ConcatenateString(&options," ");
975 option=GetImageOption(image_info,"jp2:rate");
976 if ((option == (const char *) NULL) &&
977 (image_info->compression != LosslessJPEGCompression) &&
978 (image->quality != UndefinedCompressionQuality) &&
979 ((double) image->quality <= 99.5) &&
980 ((image->rows*image->columns) > 2500))
983 option[MaxTextExtent];
992 alpha=115.0-image->quality;
993 rate=100.0/(alpha*alpha);
995 header_size+=(number_components-1)*142;
996 number_pixels=(double) image->rows*image->columns*number_components*
997 (GetImageQuantumDepth(image,MagickTrue)/8);
998 target_size=(number_pixels*rate)+header_size;
999 rate=target_size/number_pixels;
1000 (void) FormatMagickString(option,MaxTextExtent,"rate=%g",rate);
1001 (void) ConcatenateString(&options,option);
1003 status=jas_image_encode(jp2_image,jp2_stream,format,options) != 0 ?
1004 MagickTrue : MagickFalse;
1005 (void) jas_stream_close(jp2_stream);
1006 for (i=0; i < (ssize_t) number_components; i++)
1007 jas_matrix_destroy(pixels[i]);
1008 jas_image_destroy(jp2_image);
1009 if (status != MagickFalse)
1010 ThrowWriterException(DelegateError,"UnableToEncodeImageFile");