Powered by Pair ImageMagick logo
Image Magick
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | File List | Namespace Members | Data Fields | Globals | Related Pages

ImageMagick-6.1.1/coders/jp2.c

Go to the documentation of this file.
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % JJJ PPPP 222 % 00007 % J P P 2 2 % 00008 % J PPPP 22 % 00009 % J J P 2 % 00010 % JJ P 22222 % 00011 % % 00012 % % 00013 % Read/Write JPEG-2000 Image Format. % 00014 % % 00015 % John Cristy % 00016 % Nathan Brown % 00017 % June 2001 % 00018 % % 00019 % % 00020 % Copyright 1999-2004 ImageMagick Studio LLC, a non-profit organization % 00021 % dedicated to making software imaging solutions freely available. % 00022 % % 00023 % You may not use this file except in compliance with the License. You may % 00024 % obtain a copy of the License at % 00025 % % 00026 % http://www.imagemagick.org/www/Copyright.html % 00027 % % 00028 % Unless required by applicable law or agreed to in writing, software % 00029 % distributed under the License is distributed on an "AS IS" BASIS, % 00030 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 00031 % See the License for the specific language governing permissions and % 00032 % limitations under the License. % 00033 % % 00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00035 % 00036 % 00037 */ 00038 00039 /* 00040 Include declarations. 00041 */ 00042 #include "magick/studio.h" 00043 #include "magick/blob.h" 00044 #include "magick/blob_private.h" 00045 #include "magick/colorspace.h" 00046 #include "magick/color.h" 00047 #include "magick/color_private.h" 00048 #include "magick/error.h" 00049 #include "magick/error_private.h" 00050 #include "magick/image.h" 00051 #include "magick/image_private.h" 00052 #include "magick/list.h" 00053 #include "magick/magick.h" 00054 #include "magick/memory_.h" 00055 #include "magick/monitor.h" 00056 #include "magick/option.h" 00057 #include "magick/static.h" 00058 #include "magick/string_.h" 00059 #if defined(HasJP2) 00060 #if !defined(uchar) 00061 #define uchar unsigned char 00062 #endif 00063 #if !defined(ushort) 00064 #define ushort unsigned short 00065 #endif 00066 #if !defined(uint) 00067 #define uint unsigned int 00068 #endif 00069 #if !defined(longlong) 00070 #define longlong long long 00071 #endif 00072 #if !defined(ulonglong) 00073 #define ulonglong unsigned long long 00074 #endif 00075 00076 #include "jasper/jasper.h" 00077 #endif 00078 00079 /* 00080 Forward declarations. 00081 */ 00082 #if defined(HasJP2) 00083 static MagickBooleanType 00084 WriteJP2Image(const ImageInfo *,Image *); 00085 #endif 00086 00087 /* 00088 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00089 % % 00090 % % 00091 % % 00092 % I s J P 2 % 00093 % % 00094 % % 00095 % % 00096 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00097 % 00098 % IsJP2() returns MagickTrue if the image format type, identified by the 00099 % magick string, is JP2. 00100 % 00101 % The format of the IsJP2 method is: 00102 % 00103 % MagickBooleanType IsJP2(const unsigned char *magick,const size_t length) 00104 % 00105 % A description of each parameter follows: 00106 % 00107 % o magick: This string is generally the first few bytes of an image file 00108 % or blob. 00109 % 00110 % o length: Specifies the length of the magick string. 00111 % 00112 % 00113 */ 00114 static MagickBooleanType IsJP2(const unsigned char *magick,const size_t length) 00115 { 00116 if (length < 9) 00117 return(MagickFalse); 00118 if (memcmp(magick+4,"\152\120\040\040\015",5) == 0) 00119 return(MagickTrue); 00120 return(MagickFalse); 00121 } 00122 00123 /* 00124 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00125 % % 00126 % % 00127 % % 00128 % I s J P C % 00129 % % 00130 % % 00131 % % 00132 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00133 % 00134 % IsJPC()() returns MagickTrue if the image format type, identified by the magick 00135 % string, is JPC. 00136 % 00137 % The format of the IsJPC method is: 00138 % 00139 % MagickBooleanType IsJPC(const unsigned char *magick,const size_t length) 00140 % 00141 % A description of each parameter follows: 00142 % 00143 % o magick: This string is generally the first few bytes of an image file 00144 % or blob. 00145 % 00146 % o length: Specifies the length of the magick string. 00147 % 00148 % 00149 */ 00150 static MagickBooleanType IsJPC(const unsigned char *magick,const size_t length) 00151 { 00152 if (length < 2) 00153 return(MagickFalse); 00154 if (memcmp(magick,"\377\117",2) == 0) 00155 return(MagickTrue); 00156 return(MagickFalse); 00157 } 00158 00159 /* 00160 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00161 % % 00162 % % 00163 % % 00164 % R e a d J P 2 I m a g e % 00165 % % 00166 % % 00167 % % 00168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00169 % 00170 % ReadJP2Image() reads a JPEG 2000 Image file (JP2) or JPEG 2000 00171 % codestream (JPC) image file and returns it. It allocates the memory 00172 % necessary for the new Image structure and returns a pointer to the new 00173 % image or set of images. 00174 % 00175 % JP2 support is originally written by Nathan Brown, nathanbrown@letu.edu. 00176 % 00177 % The format of the ReadJP2Image method is: 00178 % 00179 % Image *ReadJP2Image(const ImageInfo *image_info, 00180 % ExceptionInfo *exception) 00181 % 00182 % A description of each parameter follows: 00183 % 00184 % o image_info: The image info. 00185 % 00186 % o exception: return any errors or warnings in this structure. 00187 % 00188 */ 00189 #if defined(HasJP2) 00190 00191 typedef struct _StreamManager 00192 { 00193 jas_stream_t 00194 *stream; 00195 00196 Image 00197 *image; 00198 } StreamManager; 00199 00200 static int BlobRead(jas_stream_obj_t *object,char *buffer,const int length) 00201 { 00202 ssize_t 00203 count; 00204 00205 count=ReadBlob(((StreamManager *) object)->image,(size_t) length, 00206 (void *) buffer); 00207 return((int) count); 00208 } 00209 00210 static int BlobWrite(jas_stream_obj_t *object,char *buffer,const int length) 00211 { 00212 size_t 00213 count; 00214 00215 count=WriteBlob(((StreamManager *) object)->image,(size_t) length, 00216 (void *) buffer); 00217 return((int) count); 00218 } 00219 00220 static long BlobSeek(jas_stream_obj_t *object,long offset,int origin) 00221 { 00222 return(SeekBlob(((StreamManager *) object)->image,offset,origin)); 00223 } 00224 00225 static int BlobClose(jas_stream_obj_t *object) 00226 { 00227 CloseBlob(((StreamManager *) object)->image); 00228 return(0); 00229 } 00230 00231 static jas_stream_ops_t 00232 StreamOperators = 00233 { 00234 BlobRead, 00235 BlobWrite, 00236 BlobSeek, 00237 BlobClose 00238 }; 00239 00240 static jas_stream_t *JP2StreamManager(Image *image) 00241 { 00242 jas_stream_t 00243 *stream; 00244 00245 StreamManager 00246 *source; 00247 00248 stream=(jas_stream_t *) AcquireMagickMemory(sizeof(*stream)); 00249 if (stream == (jas_stream_t *) NULL) 00250 return((jas_stream_t *) NULL); 00251 (void) ResetMagickMemory(stream,0,sizeof(*stream)); 00252 stream->rwlimit_=(-1); 00253 stream->obj_=(jas_stream_obj_t *) AcquireMagickMemory(sizeof(StreamManager)); 00254 if (stream->obj_ == (jas_stream_obj_t *) NULL) 00255 return((jas_stream_t *) NULL); 00256 (void) ResetMagickMemory(stream->obj_,0,sizeof(StreamManager)); 00257 stream->ops_=(&StreamOperators); 00258 stream->openmode_=JAS_STREAM_READ | JAS_STREAM_WRITE | JAS_STREAM_BINARY; 00259 stream->bufbase_=stream->tinybuf_; 00260 stream->bufsize_=1; 00261 stream->bufstart_=(&stream->bufbase_[JAS_STREAM_MAXPUTBACK]); 00262 stream->ptr_=stream->bufstart_; 00263 stream->bufmode_|=JAS_STREAM_UNBUF & JAS_STREAM_BUFMODEMASK; 00264 source=(StreamManager *) stream->obj_; 00265 source->image=image; 00266 return(stream); 00267 } 00268 00269 static Image *ReadJP2Image(const ImageInfo *image_info,ExceptionInfo *exception) 00270 { 00271 Image 00272 *image; 00273 00274 long 00275 y; 00276 00277 jas_image_t 00278 *jp2_image; 00279 00280 jas_matrix_t 00281 *pixels[4]; 00282 00283 jas_stream_t 00284 *jp2_stream; 00285 00286 MagickBooleanType 00287 status; 00288 00289 register long 00290 i, 00291 x; 00292 00293 register PixelPacket 00294 *q; 00295 00296 int 00297 components[4]; 00298 00299 unsigned int 00300 channel_scale[4], 00301 maximum_component_depth; 00302 00303 unsigned long 00304 number_components; 00305 00306 /* 00307 Open image file. 00308 */ 00309 assert(image_info != (const ImageInfo *) NULL); 00310 assert(image_info->signature == MagickSignature); 00311 if (image_info->debug != MagickFalse) 00312 (void) LogMagickEvent(TraceEvent,GetMagickModule(),image_info->filename); 00313 assert(exception != (ExceptionInfo *) NULL); 00314 assert(exception->signature == MagickSignature); 00315 image=AllocateImage(image_info); 00316 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 00317 if (status == MagickFalse) 00318 { 00319 DestroyImageList(image); 00320 return((Image *) NULL); 00321 } 00322 /* 00323 Initialize JPEG 2000 API. 00324 */ 00325 jas_init(); 00326 jp2_stream=JP2StreamManager(image); 00327 if (jp2_stream == (jas_stream_t *) NULL) 00328 ThrowReaderException(DelegateError,"UnableToManageJP2Stream"); 00329 jp2_image=jas_image_decode(jp2_stream,-1,0); 00330 if (jp2_image == (jas_image_t *) NULL) 00331 { 00332 (void) jas_stream_close(jp2_stream); 00333 ThrowReaderException(DelegateError,"UnableToDecodeImageFile"); 00334 } 00335 switch (jas_clrspc_fam(jas_image_clrspc(jp2_image))) 00336 { 00337 case JAS_CLRSPC_FAM_RGB: 00338 { 00339 components[0]=jas_image_getcmptbytype(jp2_image, 00340 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R)); 00341 components[1]=jas_image_getcmptbytype(jp2_image, 00342 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G)); 00343 components[2]=jas_image_getcmptbytype(jp2_image, 00344 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B)); 00345 if ((components[0] < 0) || (components[1] < 0) || (components[2] < 0)) 00346 { 00347 (void) jas_stream_close(jp2_stream); 00348 jas_image_destroy(jp2_image); 00349 ThrowReaderException(CorruptImageError,"MissingImageChannel"); 00350 } 00351 number_components=3; 00352 components[3]=jas_image_getcmptbytype(jp2_image, 00353 JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_OPACITY)); 00354 if (components[3] > 0) 00355 { 00356 image->matte=MagickTrue; 00357 number_components++; 00358 } 00359 break; 00360 } 00361 case JAS_CLRSPC_FAM_GRAY: 00362 { 00363 components[0]=jas_image_getcmptbytype(jp2_image, 00364 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y)); 00365 if (components[0] < 0) 00366 { 00367 (void) jas_stream_close(jp2_stream); 00368 jas_image_destroy(jp2_image); 00369 ThrowReaderException(CorruptImageError,"MissingImageChannel"); 00370 } 00371 number_components=1; 00372 break; 00373 } 00374 case JAS_CLRSPC_FAM_YCBCR: 00375 default: 00376 { 00377 (void) jas_stream_close(jp2_stream); 00378 jas_image_destroy(jp2_image); 00379 ThrowReaderException(CoderError,"ColorspaceModelIsNotSupported"); 00380 } 00381 } 00382 image->columns=jas_image_width(jp2_image); 00383 image->rows=jas_image_height(jp2_image); 00384 for (i=0; i < (long) number_components; i++) 00385 { 00386 if ((jas_image_cmptwidth(jp2_image,components[i]) != image->columns) || 00387 (jas_image_cmptheight(jp2_image,components[i]) != image->rows) || 00388 (jas_image_cmpttlx(jp2_image,components[i]) != 0) || 00389 (jas_image_cmpttly(jp2_image,components[i]) != 0) || 00390 (jas_image_cmpthstep(jp2_image,components[i]) != 1) || 00391 (jas_image_cmptvstep(jp2_image,components[i]) != 1) || 00392 (jas_image_cmptsgnd(jp2_image,components[i]) != MagickFalse)) 00393 { 00394 (void) jas_stream_close(jp2_stream); 00395 jas_image_destroy(jp2_image); 00396 ThrowReaderException(CoderError,"IrregularChannelGeometryNotSupported"); 00397 } 00398 } 00399 /* 00400 Convert JPEG 2000 pixels. 00401 */ 00402 if (image_info->ping != MagickFalse) 00403 { 00404 (void) jas_stream_close(jp2_stream); 00405 jas_image_destroy(jp2_image); 00406 return(GetFirstImageInList(image)); 00407 } 00408 image->matte=number_components > 3; 00409 maximum_component_depth=0; 00410 for (i=0; i < (long) number_components; i++) 00411 { 00412 maximum_component_depth=Max(jas_image_cmptprec(jp2_image,components[i]), 00413 maximum_component_depth); 00414 pixels[i]=jas_matrix_create(1,(unsigned int) image->columns); 00415 if (pixels[i] == (jas_matrix_t *) NULL) 00416 { 00417 jas_image_destroy(jp2_image); 00418 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 00419 } 00420 } 00421 if (maximum_component_depth <= 8) 00422 image->depth=Min(QuantumDepth,8); 00423 else 00424 image->depth=Min(QuantumDepth,16); 00425 for (i=0; i < (long) number_components; i++) 00426 { 00427 channel_scale[i]=1; 00428 if (jas_image_cmptprec(jp2_image,components[i]) < 16) 00429 channel_scale[i]= 00430 (1 << (16-jas_image_cmptprec(jp2_image,components[i])))+1; 00431 } 00432 if (number_components == 1) 00433 { 00434 image->storage_class=PseudoClass; 00435 image->colors=(image->depth == 8 ? 256 : MaxColormapSize); 00436 if (AllocateImageColormap(image,image->colors) == MagickFalse) 00437 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 00438 } 00439 for (y=0; y < (long) image->rows; y++) 00440 { 00441 q=GetImagePixels(image,0,y,image->columns,1); 00442 if (q == (PixelPacket *) NULL) 00443 break; 00444 for (i=0; i < (long) number_components; i++) 00445 (void) jas_image_readcmpt(jp2_image,(short) components[i],0, 00446 (unsigned int) y,(unsigned int) image->columns,1,pixels[i]); 00447 switch (number_components) 00448 { 00449 case 1: 00450 { 00451 register IndexPacket 00452 *indexes; 00453 00454 IndexPacket 00455 index; 00456 00457 /* 00458 Grayscale. 00459 */ 00460 indexes=GetIndexes(image); 00461 if (image->depth == 8) 00462 for (x=0; x < (long) image->columns; x++) 00463 { 00464 index=ScaleQuantumToChar(ScaleShortToQuantum((unsigned short) 00465 jas_matrix_getv(pixels[0],x)*channel_scale[0])); 00466 index=ConstrainColormapIndex(image,index); 00467 *indexes++=index; 00468 *q++=image->colormap[index]; 00469 } 00470 else 00471 for (x=0; x < (long) image->columns; x++) 00472 { 00473 index=(unsigned short) jas_matrix_getv(pixels[0],x)* 00474 channel_scale[0]; 00475 index=ConstrainColormapIndex(image,index); 00476 *indexes++=index; 00477 *q++=image->colormap[index]; 00478 } 00479 break; 00480 } 00481 case 3: 00482 { 00483 /* 00484 RGB. 00485 */ 00486 for (x=0; x < (long) image->columns; x++) 00487 { 00488 q->red=ScaleShortToQuantum((unsigned short) 00489 jas_matrix_getv(pixels[0],x)*channel_scale[0]); 00490 q->green=ScaleShortToQuantum((unsigned short) 00491 jas_matrix_getv(pixels[1],x)*channel_scale[1]); 00492 q->blue=ScaleShortToQuantum((unsigned short) 00493 jas_matrix_getv(pixels[2],x)*channel_scale[2]); 00494 q++; 00495 } 00496 break; 00497 } 00498 case 4: 00499 { 00500 /* 00501 RGBA. 00502 */ 00503 for (x=0; x < (long) image->columns; x++) 00504 { 00505 q->red=ScaleShortToQuantum((unsigned short) 00506 jas_matrix_getv(pixels[0],x)*channel_scale[0]); 00507 q->green=ScaleShortToQuantum((unsigned short) 00508 jas_matrix_getv(pixels[1],x)*channel_scale[1]); 00509 q->blue=ScaleShortToQuantum((unsigned short) 00510 jas_matrix_getv(pixels[2],x)*channel_scale[2]); 00511 q->opacity=MaxRGB-ScaleShortToQuantum((unsigned short) 00512 jas_matrix_getv(pixels[3],x)*channel_scale[3]); 00513 q++; 00514 } 00515 break; 00516 } 00517 } 00518 if (SyncImagePixels(image) == MagickFalse) 00519 break; 00520 if (image->previous == (Image *) NULL) 00521 if ((image->progress_monitor != (MagickProgressMonitor) NULL) && 00522 (QuantumTick(y,image->rows) != MagickFalse)) 00523 { 00524 status=image->progress_monitor(LoadImagesTag,y,image->rows, 00525 image->client_data); 00526 if (status == MagickFalse) 00527 break; 00528 } 00529 } 00530 (void) jas_stream_close(jp2_stream); 00531 jas_image_destroy(jp2_image); 00532 for (i=0; i < (long) number_components; i++) 00533 jas_matrix_destroy(pixels[i]); 00534 return(GetFirstImageInList(image)); 00535 } 00536 #endif 00537 00538 /* 00539 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00540 % % 00541 % % 00542 % % 00543 % R e g i s t e r J P 2 I m a g e % 00544 % % 00545 % % 00546 % % 00547 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00548 % 00549 % RegisterJP2Image() adds attributes for the JP2 image format to the list of 00550 % supported formats. The attributes include the image format tag, a method 00551 % method to read and/or write the format, whether the format supports the 00552 % saving of more than one frame to the same file or blob, whether the format 00553 % supports native in-memory I/O, and a brief description of the format. 00554 % 00555 % The format of the RegisterJP2Image method is: 00556 % 00557 % RegisterJP2Image(void) 00558 % 00559 */ 00560 ModuleExport void RegisterJP2Image(void) 00561 { 00562 MagickInfo 00563 *entry; 00564 00565 entry=SetMagickInfo("JP2"); 00566 entry->description=AcquireString("JPEG-2000 JP2 File Format Syntax"); 00567 entry->module=AcquireString("JP2"); 00568 entry->magick=(MagickHandler *) IsJP2; 00569 entry->adjoin=MagickFalse; 00570 entry->seekable_stream=MagickTrue; 00571 entry->thread_support=MagickFalse; 00572 #if defined(HasJP2) 00573 entry->decoder=(DecoderHandler *) ReadJP2Image; 00574 entry->encoder=(EncoderHandler *) WriteJP2Image; 00575 #endif 00576 (void) RegisterMagickInfo(entry); 00577 entry=SetMagickInfo("JPC"); 00578 entry->description=AcquireString("JPEG-2000 Code Stream Syntax"); 00579 entry->module=AcquireString("JPC"); 00580 entry->magick=(MagickHandler *) IsJPC; 00581 entry->adjoin=MagickFalse; 00582 entry->seekable_stream=MagickTrue; 00583 entry->thread_support=MagickFalse; 00584 #if defined(HasJP2) 00585 entry->decoder=(DecoderHandler *) ReadJP2Image; 00586 entry->encoder=(EncoderHandler *) WriteJP2Image; 00587 #endif 00588 (void) RegisterMagickInfo(entry); 00589 entry=SetMagickInfo("PGX"); 00590 entry->description=AcquireString("JPEG-2000 VM Format"); 00591 entry->module=AcquireString("PGX"); 00592 entry->magick=(MagickHandler *) IsJPC; 00593 entry->adjoin=MagickFalse; 00594 entry->seekable_stream=MagickTrue; 00595 entry->thread_support=MagickFalse; 00596 #if defined(HasJP2) 00597 entry->decoder=(DecoderHandler *) ReadJP2Image; 00598 #endif 00599 (void) RegisterMagickInfo(entry); 00600 } 00601 00602 /* 00603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00604 % % 00605 % % 00606 % % 00607 % U n r e g i s t e r J P 2 I m a g e % 00608 % % 00609 % % 00610 % % 00611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00612 % 00613 % UnregisterJP2Image() removes format registrations made by the JP2 module 00614 % from the list of supported formats. 00615 % 00616 % The format of the UnregisterJP2Image method is: 00617 % 00618 % UnregisterJP2Image(void) 00619 % 00620 */ 00621 ModuleExport void UnregisterJP2Image(void) 00622 { 00623 (void) UnregisterMagickInfo("JP2"); 00624 (void) UnregisterMagickInfo("JPC"); 00625 (void) UnregisterMagickInfo("PGX"); 00626 } 00627 00628 #if defined(HasJP2) 00629 /* 00630 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00631 % % 00632 % % 00633 % % 00634 % W r i t e J P 2 I m a g e % 00635 % % 00636 % % 00637 % % 00638 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00639 % 00640 % WriteJP2Image() writes an image in the JPEG 2000 image format. 00641 % 00642 % JP2 support originally written by Nathan Brown, nathanbrown@letu.edu 00643 % 00644 % The format of the WriteJP2Image method is: 00645 % 00646 % MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image) 00647 % 00648 % A description of each parameter follows. 00649 % 00650 % o image_info: The image info. 00651 % 00652 % o image: The image. 00653 % 00654 % 00655 */ 00656 static MagickBooleanType WriteJP2Image(const ImageInfo *image_info,Image *image) 00657 { 00658 char 00659 *key, 00660 magick[MaxTextExtent], 00661 *options; 00662 00663 const char 00664 *option; 00665 00666 int 00667 format; 00668 00669 long 00670 y; 00671 00672 jas_image_cmptparm_t 00673 component_info; 00674 00675 jas_image_t 00676 *jp2_image; 00677 00678 jas_matrix_t 00679 *pixels[4]; 00680 00681 jas_stream_t 00682 *jp2_stream; 00683 00684 MagickBooleanType 00685 status; 00686 00687 register const PixelPacket 00688 *p; 00689 00690 register long 00691 i, 00692 x; 00693 00694 unsigned long 00695 number_components; 00696 00697 /* 00698 Open image file. 00699 */ 00700 assert(image_info != (const ImageInfo *) NULL); 00701 assert(image_info->signature == MagickSignature); 00702 assert(image != (Image *) NULL); 00703 assert(image->signature == MagickSignature); 00704 if (image->debug != MagickFalse) 00705 (void) LogMagickEvent(TraceEvent,GetMagickModule(),image->filename); 00706 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); 00707 if (status == MagickFalse) 00708 return(status); 00709 /* 00710 Intialize JPEG 2000 API. 00711 */ 00712 (void) SetImageColorspace(image,RGBColorspace); 00713 jas_init(); 00714 jp2_stream=JP2StreamManager(image); 00715 if (jp2_stream == (jas_stream_t *) NULL) 00716 ThrowWriterException(DelegateError,"UnableToManageJP2Stream"); 00717 number_components=image->matte ? 4 : 3; 00718 if ((image_info->type != TrueColorType) && 00719 IsGrayImage(image,&image->exception)) 00720 number_components=1; 00721 jp2_image=jas_image_create0(); 00722 if (jp2_image == (jas_image_t *) NULL) 00723 ThrowWriterException(DelegateError,"UnableToCreateImage"); 00724 for (i=0; i < (long) number_components; i++) 00725 { 00726 (void) ResetMagickMemory((void *) &component_info,0,sizeof(component_info)); 00727 component_info.tlx=0; 00728 component_info.tly=0; 00729 component_info.hstep=1; 00730 component_info.vstep=1; 00731 component_info.width=(unsigned int) image->columns; 00732 component_info.height=(unsigned int) image->rows; 00733 component_info.prec=(unsigned int) image->depth <= 8 ? 8 : 16; 00734 component_info.sgnd=MagickFalse; 00735 if (jas_image_addcmpt(jp2_image,i,&component_info)) 00736 { 00737 jas_image_destroy(jp2_image); 00738 ThrowWriterException(DelegateError,"UnableToCreateImageComponent"); 00739 } 00740 } 00741 if (number_components == 1) 00742 { 00743 /* 00744 sRGB Grayscale. 00745 */ 00746 jas_image_setclrspc(jp2_image,JAS_CLRSPC_SGRAY); 00747 jas_image_setcmpttype(jp2_image,0, 00748 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y)); 00749 } 00750 else 00751 { 00752 /* 00753 sRGB. 00754 */ 00755 jas_image_setclrspc(jp2_image,JAS_CLRSPC_SRGB); 00756 jas_image_setcmpttype(jp2_image,0, 00757 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_R)); 00758 jas_image_setcmpttype(jp2_image,1, 00759 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_G)); 00760 jas_image_setcmpttype(jp2_image,2, 00761 JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_RGB_B)); 00762 if (number_components == 4 ) 00763 jas_image_setcmpttype(jp2_image,3, 00764 JAS_IMAGE_CT_COLOR(JAS_IMAGE_CT_OPACITY)); 00765 } 00766 /* 00767 Convert to JPEG 2000 pixels. 00768 */ 00769 for (i=0; i < (long) number_components; i++) 00770 { 00771 pixels[i]=jas_matrix_create(1,(unsigned int) image->columns); 00772 if (pixels[i] == (jas_matrix_t *) NULL) 00773 { 00774 for (x=0; x < i; x++) 00775 jas_matrix_destroy(pixels[x]); 00776 jas_image_destroy(jp2_image); 00777 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 00778 } 00779 } 00780 for (y=0; y < (long) image->rows; y++) 00781 { 00782 p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception); 00783 if (p == (const PixelPacket *) NULL) 00784 break; 00785 if (image->depth <= 8) 00786 for (x=0; x < (long) image->columns; x++) 00787 { 00788 if (number_components == 1) 00789 jas_matrix_setv(pixels[0],x, 00790 ScaleQuantumToChar(PixelIntensityToQuantum(p))); 00791 else 00792 { 00793 jas_matrix_setv(pixels[0],x,ScaleQuantumToChar(p->red)); 00794 jas_matrix_setv(pixels[1],x,ScaleQuantumToChar(p->green)); 00795 jas_matrix_setv(pixels[2],x,ScaleQuantumToChar(p->blue)); 00796 if (number_components > 3) 00797 jas_matrix_setv(pixels[3],x, 00798 ScaleQuantumToChar(MaxRGB-p->opacity)); 00799 } 00800 p++; 00801 } 00802 else 00803 for (x=0; x < (long) image->columns; x++) 00804 { 00805 if (number_components == 1) 00806 jas_matrix_setv(pixels[0],x, 00807 ScaleQuantumToShort(PixelIntensityToQuantum(p))); 00808 else 00809 { 00810 jas_matrix_setv(pixels[0],x,ScaleQuantumToShort(p->red)); 00811 jas_matrix_setv(pixels[1],x,ScaleQuantumToShort(p->green)); 00812 jas_matrix_setv(pixels[2],x,ScaleQuantumToShort(p->blue)); 00813 if (number_components > 3) 00814 jas_matrix_setv(pixels[3],x, 00815 ScaleQuantumToShort(MaxRGB-p->opacity)); 00816 } 00817 p++; 00818 } 00819 for (i=0; i < (long) number_components; i++) 00820 (void) jas_image_writecmpt(jp2_image,(short) i,0,(unsigned int) y, 00821 (unsigned int) image->columns,1,pixels[i]); 00822 if (image->previous == (Image *) NULL) 00823 if ((image->progress_monitor != (MagickProgressMonitor) NULL) && 00824 (QuantumTick(y,image->rows) != MagickFalse)) 00825 { 00826 status=image->progress_monitor(SaveImageTag,y,image->rows, 00827 image->client_data); 00828 if (status == MagickFalse) 00829 break; 00830 } 00831 } 00832 (void) CopyMagickString(magick,image_info->magick,MaxTextExtent); 00833 LocaleLower(magick); 00834 format=jas_image_strtofmt(magick); 00835 options=(char *) NULL; 00836 ResetImageOptionIterator(image_info); 00837 key=GetNextImageOption(image_info); 00838 while (key != (char *) NULL) 00839 { 00840 option=GetImageOption(image_info,key); 00841 if (option != (const char *) NULL) 00842 { 00843 if (LocaleNCompare(key,"jp2:",4) == 0) 00844 { 00845 ConcatenateString(&options,key+4); 00846 ConcatenateString(&options,"="); 00847 ConcatenateString(&options,option); 00848 ConcatenateString(&options," "); 00849 } 00850 } 00851 key=GetNextImageOption(image_info); 00852 } 00853 option=GetImageOption(image_info,"jp2:rate"); 00854 if ((option == (const char *) NULL) && 00855 (image->compression != LosslessJPEGCompression) && 00856 (image->quality != UndefinedCompressionQuality) && 00857 (image->quality < 99.5) && ((image->rows*image->columns) > 2500)) 00858 { 00859 char 00860 option[MaxTextExtent]; 00861 00862 double 00863 alpha, 00864 header_size, 00865 number_pixels, 00866 rate, 00867 target_size; 00868 00869 alpha=115-image->quality; 00870 rate=100.0/(alpha*alpha); 00871 header_size=550.0; 00872 header_size+=(number_components-1)*142; 00873 number_pixels=(double) image->rows*image->columns*number_components* 00874 (GetImageQuantumDepth(image,MagickTrue)/8); 00875 target_size=(number_pixels*rate)+header_size; 00876 rate=target_size/number_pixels; 00877 FormatMagickString(option,MaxTextExtent,"rate=%g",rate); 00878 ConcatenateString(&options,option); 00879 } 00880 status=jas_image_encode(jp2_image,jp2_stream,format,options); 00881 if (status != MagickFalse) 00882 ThrowWriterException(DelegateError,"UnableToEncodeImageFile"); 00883 (void) jas_stream_close(jp2_stream); 00884 for (i=0; i < (long) number_components; i++) 00885 jas_matrix_destroy(pixels[i]); 00886 jas_image_destroy(jp2_image); 00887 return(MagickTrue); 00888 } 00889 #endif

Generated on Mon Oct 25 13:40:37 2004 for ImageMagick by doxygen 1.3.7
ImageMagick Copyright © 2004, ImageMagick Studio LLC