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/miff.c

Go to the documentation of this file.
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % M M IIIII FFFFF FFFFF % 00007 % MM MM I F F % 00008 % M M M I FFF FFF % 00009 % M M I F F % 00010 % M M IIIII F F % 00011 % % 00012 % % 00013 % Read/Write MIFF Image Format. % 00014 % % 00015 % Software Design % 00016 % John Cristy % 00017 % July 1992 % 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/attribute.h" 00044 #include "magick/blob.h" 00045 #include "magick/blob_private.h" 00046 #include "magick/color.h" 00047 #include "magick/color_private.h" 00048 #include "magick/colorspace.h" 00049 #include "magick/constitute.h" 00050 #include "magick/error.h" 00051 #include "magick/error_private.h" 00052 #include "magick/hashmap.h" 00053 #include "magick/geometry.h" 00054 #include "magick/image.h" 00055 #include "magick/image_private.h" 00056 #include "magick/list.h" 00057 #include "magick/magick.h" 00058 #include "magick/memory_.h" 00059 #include "magick/monitor.h" 00060 #include "magick/option.h" 00061 #include "magick/profile.h" 00062 #include "magick/static.h" 00063 #include "magick/string_.h" 00064 #if defined(HasZLIB) 00065 #include "zlib.h" 00066 #endif 00067 #if defined(HasBZLIB) 00068 #include "bzlib.h" 00069 #endif 00070 00071 /* 00072 Define declarations. 00073 */ 00074 #define PopCharPixel(q,pixel) \ 00075 { \ 00076 *(q)++=(unsigned char) (pixel); \ 00077 } 00078 #define PopLongPixel(q,pixel) \ 00079 { \ 00080 *(q)++=(unsigned char) ((pixel) >> 24); \ 00081 *(q)++=(unsigned char) ((pixel) >> 16); \ 00082 *(q)++=(unsigned char) ((pixel) >> 8); \ 00083 *(q)++=(unsigned char) (pixel); \ 00084 } 00085 #define PopShortPixel(q,pixel) \ 00086 { \ 00087 *(q)++=(unsigned char) ((pixel) >> 8); \ 00088 *(q)++=(unsigned char) (pixel); \ 00089 } 00090 #define PushCharPixel(pixel,p) \ 00091 { \ 00092 pixel=(unsigned long) (*(p)); \ 00093 (p)++; \ 00094 } 00095 #define PushLongPixel(pixel,p) \ 00096 { \ 00097 pixel=(unsigned long) \ 00098 ((*(p) << 24) | (*((p)+1) << 16) | (*((p)+2) << 8) | *((p)+3)); \ 00099 (p)+=4; \ 00100 } 00101 #define PushShortPixel(pixel,p) \ 00102 { \ 00103 pixel=(unsigned long) ((*(p) << 8) | *((p)+1)); \ 00104 (p)+=2; \ 00105 } 00106 00107 /* 00108 Forward declarations. 00109 */ 00110 static MagickBooleanType 00111 WriteMIFFImage(const ImageInfo *,Image *); 00112 00113 /* 00114 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00115 % % 00116 % % 00117 % % 00118 % I s M I F F % 00119 % % 00120 % % 00121 % % 00122 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00123 % 00124 % IsMIFF() returns MagickTrue if the image format type, identified by the magick 00125 % string, is MIFF. 00126 % 00127 % The format of the IsMIFF method is: 00128 % 00129 % MagickBooleanType IsMIFF(const unsigned char *magick,const size_t length) 00130 % 00131 % A description of each parameter follows: 00132 % 00133 % o magick: This string is generally the first few bytes of an image file 00134 % or blob. 00135 % 00136 % o length: Specifies the length of the magick string. 00137 % 00138 % 00139 */ 00140 static MagickBooleanType IsMIFF(const unsigned char *magick,const size_t length) 00141 { 00142 if (length < 14) 00143 return(MagickFalse); 00144 if (LocaleNCompare((char *) magick,"id=ImageMagick",14) == 0) 00145 return(MagickTrue); 00146 return(MagickFalse); 00147 } 00148 00149 /* 00150 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00151 % % 00152 % % 00153 % % 00154 % R e a d M I F F I m a g e % 00155 % % 00156 % % 00157 % % 00158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00159 % 00160 % ReadMIFFImage() reads a MIFF image file and returns it. It allocates the 00161 % memory necessary for the new Image structure and returns a pointer to the 00162 % new image. 00163 % 00164 % The format of the ReadMIFFImage method is: 00165 % 00166 % Image *ReadMIFFImage(const ImageInfo *image_info, 00167 % ExceptionInfo *exception) 00168 % 00169 % Decompression code contributed by Kyle Shorter. 00170 % 00171 % A description of each parameter follows: 00172 % 00173 % o image: Method ReadMIFFImage returns a pointer to the image after 00174 % reading. A null image is returned if there is a memory shortage or 00175 % if the image cannot be read. 00176 % 00177 % o image_info: The image info. 00178 % 00179 % o exception: return any errors or warnings in this structure. 00180 % 00181 % 00182 */ 00183 00184 #if defined(HasBZLIB) 00185 static void *AcquireBZIPMemory(void *context,int items,int size) 00186 { 00187 return((void *) AcquireMagickMemory((size_t) (items*size))); 00188 } 00189 #endif 00190 00191 #if defined(HasZLIB) 00192 static voidpf AcquireZIPMemory(voidpf context,unsigned int items, 00193 unsigned int size) 00194 { 00195 return((voidpf) AcquireMagickMemory((size_t) (items*size))); 00196 } 00197 #endif 00198 00199 static inline void PushRunlengthPacket(Image *image,const unsigned long depth, 00200 unsigned char *pixels,size_t *length,PixelPacket *pixel,IndexPacket *index) 00201 { 00202 register unsigned char 00203 *p; 00204 00205 unsigned long 00206 quantum; 00207 00208 p=pixels; 00209 if (image->storage_class == PseudoClass) 00210 { 00211 *index=0; 00212 switch (depth) 00213 { 00214 case 32: 00215 { 00216 *index=ConstrainColormapIndex(image, 00217 (*p << 24) | (*(p+1) << 16) | (*(p+2) << 8) | *(p+3)); 00218 p+=4; 00219 break; 00220 } 00221 case 16: 00222 { 00223 *index=ConstrainColormapIndex(image,(*p << 8) | *(p+1)); 00224 p+=2; 00225 break; 00226 } 00227 case 8: 00228 { 00229 *index=ConstrainColormapIndex(image,*p); 00230 p++; 00231 break; 00232 } 00233 default: 00234 (void) ThrowMagickException(&image->exception,GetMagickModule(), 00235 CorruptImageError,"ImageDepthNotSupported",image->filename); 00236 } 00237 *pixel=image->colormap[*index]; 00238 switch (depth) 00239 { 00240 case 32: 00241 { 00242 if (image->matte != MagickFalse) 00243 { 00244 PushLongPixel(quantum,p); 00245 pixel->opacity=(Quantum) (quantum >> (depth-QuantumDepth)); 00246 } 00247 break; 00248 } 00249 case 16: 00250 { 00251 if (image->matte != MagickFalse) 00252 { 00253 PushShortPixel(quantum,p); 00254 pixel->opacity=(Quantum) (quantum >> (depth-QuantumDepth)); 00255 } 00256 break; 00257 } 00258 case 8: 00259 { 00260 if (image->matte != MagickFalse) 00261 { 00262 PushCharPixel(quantum,p); 00263 pixel->opacity=ScaleCharToQuantum(quantum); 00264 } 00265 break; 00266 } 00267 default: 00268 (void) ThrowMagickException(&image->exception,GetMagickModule(), 00269 CorruptImageError,"ImageDepthNotSupported",image->filename); 00270 } 00271 *length=(size_t) (*p++)+1; 00272 return; 00273 } 00274 switch (depth) 00275 { 00276 case 32: 00277 { 00278 PushLongPixel(quantum,p); 00279 pixel->red=(Quantum) (quantum >> (depth-QuantumDepth)); 00280 PushLongPixel(quantum,p); 00281 pixel->green=(Quantum) (quantum >> (depth-QuantumDepth)); 00282 PushLongPixel(quantum,p); 00283 pixel->blue=(Quantum) (quantum >> (depth-QuantumDepth)); 00284 if (image->matte != MagickFalse) 00285 { 00286 PushLongPixel(quantum,p); 00287 pixel->opacity=(Quantum) (quantum >> (depth-QuantumDepth)); 00288 } 00289 if (image->colorspace == CMYKColorspace) 00290 { 00291 PushLongPixel(quantum,p); 00292 *index=(IndexPacket) (quantum >> (depth-QuantumDepth)); 00293 } 00294 break; 00295 } 00296 case 16: 00297 { 00298 PushShortPixel(quantum,p); 00299 pixel->red=(Quantum) (quantum >> (depth-QuantumDepth)); 00300 PushShortPixel(quantum,p); 00301 pixel->green=(Quantum) (quantum >> (depth-QuantumDepth)); 00302 PushShortPixel(quantum,p); 00303 pixel->blue=(Quantum) (quantum >> (depth-QuantumDepth)); 00304 if (image->matte != MagickFalse) 00305 { 00306 PushShortPixel(quantum,p); 00307 pixel->opacity=(Quantum) (quantum >> (depth-QuantumDepth)); 00308 } 00309 if (image->colorspace == CMYKColorspace) 00310 { 00311 PushShortPixel(quantum,p); 00312 *index=(IndexPacket) (quantum >> (depth-QuantumDepth)); 00313 } 00314 break; 00315 } 00316 case 8: 00317 { 00318 PushCharPixel(quantum,p); 00319 pixel->red=ScaleCharToQuantum(quantum); 00320 PushCharPixel(quantum,p); 00321 pixel->green=ScaleCharToQuantum(quantum); 00322 PushCharPixel(quantum,p); 00323 pixel->blue=ScaleCharToQuantum(quantum); 00324 if (image->matte != MagickFalse) 00325 { 00326 PushCharPixel(quantum,p); 00327 pixel->opacity=ScaleCharToQuantum(quantum); 00328 } 00329 if (image->colorspace == CMYKColorspace) 00330 { 00331 PushCharPixel(quantum,p); 00332 *index=ScaleCharToQuantum(quantum); 00333 } 00334 break; 00335 } 00336 default: 00337 (void) ThrowMagickException(&image->exception,GetMagickModule(), 00338 CorruptImageError,"ImageDepthNotSupported",image->filename); 00339 } 00340 *length=(size_t) (*p++)+1; 00341 } 00342 00343 #if defined(HasZLIB) 00344 static void RelinquishZIPMemory(voidpf context,voidpf memory) 00345 { 00346 memory=RelinquishMagickMemory(memory); 00347 } 00348 #endif 00349 00350 #if defined(HasBZLIB) 00351 static void RelinquishBZIPMemory(void *context,void *memory) 00352 { 00353 memory=RelinquishMagickMemory(memory); 00354 } 00355 #endif 00356 00357 static Image *ReadMIFFImage(const ImageInfo *image_info, 00358 ExceptionInfo *exception) 00359 { 00360 #define BZipMaxExtent(x) ((x)+((x)/100)+600) 00361 #define ZipMaxExtent(x) ((x)+(((x)+7) >> 3)+(((x)+63) >> 6)+11) 00362 00363 #if defined(HasBZLIB) 00364 bz_stream 00365 bzip_info; 00366 #endif 00367 00368 char 00369 id[MaxTextExtent], 00370 keyword[MaxTextExtent], 00371 *options; 00372 00373 double 00374 version; 00375 00376 GeometryInfo 00377 geometry_info; 00378 00379 Image 00380 *image; 00381 00382 IndexPacket 00383 index; 00384 00385 int 00386 c, 00387 code; 00388 00389 LinkedListInfo 00390 *profiles; 00391 00392 long 00393 y; 00394 00395 PixelPacket 00396 pixel; 00397 00398 QuantumType 00399 quantum_type; 00400 00401 MagickBooleanType 00402 status; 00403 00404 MagickStatusType 00405 flags; 00406 00407 register IndexPacket 00408 *indexes; 00409 00410 register long 00411 i, 00412 x; 00413 00414 register PixelPacket 00415 *q; 00416 00417 register unsigned char 00418 *p; 00419 00420 size_t 00421 length, 00422 packet_size; 00423 00424 StringInfo 00425 *profile; 00426 00427 unsigned char 00428 *compress_pixels, 00429 *pixels; 00430 00431 unsigned long 00432 colors, 00433 depth; 00434 00435 #if defined(HasZLIB) 00436 z_stream 00437 zip_info; 00438 #endif 00439 00440 /* 00441 Open image file. 00442 */ 00443 assert(image_info != (const ImageInfo *) NULL); 00444 assert(image_info->signature == MagickSignature); 00445 if (image_info->debug != MagickFalse) 00446 (void) LogMagickEvent(TraceEvent,GetMagickModule(),image_info->filename); 00447 assert(exception != (ExceptionInfo *) NULL); 00448 assert(exception->signature == MagickSignature); 00449 image=AllocateImage(image_info); 00450 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 00451 if (status == MagickFalse) 00452 { 00453 DestroyImageList(image); 00454 return((Image *) NULL); 00455 } 00456 /* 00457 Decode image header; header terminates one character beyond a ':'. 00458 */ 00459 c=ReadBlobByte(image); 00460 if (c == EOF) 00461 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 00462 code=0; 00463 *id='\0'; 00464 version=0.0; 00465 do 00466 { 00467 /* 00468 Decode image header; header terminates one character beyond a ':'. 00469 */ 00470 length=MaxTextExtent; 00471 options=AcquireString((char *) NULL); 00472 profiles=(LinkedListInfo *) NULL; 00473 colors=0; 00474 image->depth=8UL; 00475 image->compression=NoCompression; 00476 while ((isgraph(c) != MagickFalse) && (c != (int) ':')) 00477 { 00478 register char 00479 *p; 00480 00481 if (c == (int) '{') 00482 { 00483 char 00484 *comment; 00485 00486 /* 00487 Read comment-- any text between { }. 00488 */ 00489 length=MaxTextExtent; 00490 comment=AcquireString((char *) NULL); 00491 for (p=comment; comment != (char *) NULL; p++) 00492 { 00493 c=ReadBlobByte(image); 00494 if ((c == EOF) || (c == (int) '}')) 00495 break; 00496 if ((size_t) (p-comment+1) >= length) 00497 { 00498 *p='\0'; 00499 length<<=1; 00500 comment=(char *) ResizeMagickMemory(comment, 00501 (length+MaxTextExtent)*sizeof(*comment)); 00502 if (comment == (char *) NULL) 00503 break; 00504 p=comment+strlen(comment); 00505 } 00506 *p=(char) c; 00507 } 00508 if (comment == (char *) NULL) 00509 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 00510 *p='\0'; 00511 (void) SetImageAttribute(image,"Comment",comment); 00512 comment=(char *) RelinquishMagickMemory(comment); 00513 c=ReadBlobByte(image); 00514 } 00515 else 00516 if (isalnum(c) != MagickFalse) 00517 { 00518 /* 00519 Get the keyword. 00520 */ 00521 p=keyword; 00522 do 00523 { 00524 if (isspace((int) ((unsigned char) c)) != 0) 00525 break; 00526 if (c == (int) '=') 00527 break; 00528 if ((size_t) (p-keyword) < (MaxTextExtent-1)) 00529 *p++=(char) c; 00530 c=ReadBlobByte(image); 00531 } while (c != EOF); 00532 *p='\0'; 00533 p=options; 00534 while (isspace((int) ((unsigned char) c)) != 0) 00535 c=ReadBlobByte(image); 00536 if (c == (int) '=') 00537 { 00538 /* 00539 Get the keyword value. 00540 */ 00541 c=ReadBlobByte(image); 00542 while ((c != (int) '}') && (c != EOF)) 00543 { 00544 if ((size_t) (p-options+1) >= length) 00545 { 00546 *p='\0'; 00547 length<<=1; 00548 options=(char *) ResizeMagickMemory(options, 00549 (length+MaxTextExtent)*sizeof(*options)); 00550 if (options == (char *) NULL) 00551 break; 00552 p=options+strlen(options); 00553 } 00554 if (options == (char *) NULL) 00555 ThrowReaderException(ResourceLimitError, 00556 "MemoryAllocationFailed"); 00557 *p++=(char) c; 00558 c=ReadBlobByte(image); 00559 if (*options != '{') 00560 if (isspace((int) ((unsigned char) c)) != 0) 00561 break; 00562 } 00563 } 00564 *p='\0'; 00565 if (*options == '{') 00566 (void) CopyMagickString(options,options+1,MaxTextExtent); 00567 /* 00568 Assign a value to the specified keyword. 00569 */ 00570 switch (*keyword) 00571 { 00572 case 'b': 00573 case 'B': 00574 { 00575 if (LocaleCompare(keyword,"background-color") == 0) 00576 { 00577 (void) QueryColorDatabase(options,&image->background_color, 00578 exception); 00579 break; 00580 } 00581 if (LocaleCompare(keyword,"blue-primary") == 0) 00582 { 00583 flags=ParseGeometry(options,&geometry_info); 00584 image->chromaticity.blue_primary.x=geometry_info.rho; 00585 image->chromaticity.blue_primary.y=geometry_info.sigma; 00586 if ((flags & SigmaValue) == 0) 00587 image->chromaticity.blue_primary.y= 00588 image->chromaticity.blue_primary.x; 00589 break; 00590 } 00591 if (LocaleCompare(keyword,"border-color") == 0) 00592 { 00593 (void) QueryColorDatabase(options,&image->border_color, 00594 exception); 00595 break; 00596 } 00597 (void) SetImageAttribute(image,keyword,options); 00598 break; 00599 } 00600 case 'c': 00601 case 'C': 00602 { 00603 if (LocaleCompare(keyword,"class") == 0) 00604 { 00605 image->storage_class=(ClassType) 00606 ParseMagickOption(MagickClassOptions,MagickFalse,options); 00607 break; 00608 } 00609 if (LocaleCompare(keyword,"colors") == 0) 00610 { 00611 colors=(unsigned long) atol(options); 00612 break; 00613 } 00614 if (LocaleCompare(keyword,"colorspace") == 0) 00615 { 00616 image->colorspace=(ColorspaceType) ParseMagickOption( 00617 MagickColorspaceOptions,MagickFalse,options); 00618 break; 00619 } 00620 if (LocaleCompare(keyword,"compose") == 0) 00621 { 00622 image->compose=(CompositeOperator) ParseMagickOption( 00623 MagickCompositeOptions,MagickFalse,options); 00624 break; 00625 } 00626 if (LocaleCompare(keyword,"compression") == 0) 00627 { 00628 image->compression=(CompressionType) ParseMagickOption( 00629 MagickCompressionOptions,MagickFalse,options); 00630 break; 00631 } 00632 if (LocaleCompare(keyword,"columns") == 0) 00633 { 00634 image->columns=(unsigned long) atol(options); 00635 break; 00636 } 00637 (void) SetImageAttribute(image,keyword,options); 00638 break; 00639 } 00640 case 'd': 00641 case 'D': 00642 { 00643 if (LocaleCompare(keyword,"delay") == 0) 00644 { 00645 image->delay=(unsigned long) atol(options); 00646 break; 00647 } 00648 if (LocaleCompare(keyword,"depth") == 0) 00649 { 00650 image->depth=(unsigned long) atol(options); 00651 break; 00652 } 00653 if (LocaleCompare(keyword,"dispose") == 0) 00654 { 00655 image->dispose=(DisposeType) ParseMagickOption( 00656 MagickDisposeOptions,MagickFalse,options); 00657 break; 00658 } 00659 (void) SetImageAttribute(image,keyword,options); 00660 break; 00661 } 00662 case 'e': 00663 case 'E': 00664 { 00665 if (LocaleCompare(keyword,"endian") == 0) 00666 { 00667 image->endian=(EndianType) ParseMagickOption( 00668 MagickEndianOptions,MagickFalse,options); 00669 break; 00670 } 00671 (void) SetImageAttribute(image,keyword,options); 00672 break; 00673 } 00674 case 'g': 00675 case 'G': 00676 { 00677 if (LocaleCompare(keyword,"gamma") == 0) 00678 { 00679 image->gamma=atof(options); 00680 break; 00681 } 00682 if (LocaleCompare(keyword,"green-primary") == 0) 00683 { 00684 flags=ParseGeometry(options,&geometry_info); 00685 image->chromaticity.green_primary.x=geometry_info.rho; 00686 image->chromaticity.green_primary.y=geometry_info.sigma; 00687 if ((flags & SigmaValue) == 0) 00688 image->chromaticity.green_primary.y= 00689 image->chromaticity.green_primary.x; 00690 break; 00691 } 00692 (void) SetImageAttribute(image,keyword,options); 00693 break; 00694 } 00695 case 'i': 00696 case 'I': 00697 { 00698 if (LocaleCompare(keyword,"id") == 0) 00699 { 00700 (void) CopyMagickString(id,options,MaxTextExtent); 00701 break; 00702 } 00703 if (LocaleCompare(keyword,"iterations") == 0) 00704 { 00705 image->iterations=(unsigned long) atol(options); 00706 break; 00707 } 00708 (void) SetImageAttribute(image,keyword,options); 00709 break; 00710 } 00711 case 'm': 00712 case 'M': 00713 { 00714 if (LocaleCompare(keyword,"matte") == 0) 00715 { 00716 image->matte=(MagickBooleanType) ParseMagickOption( 00717 MagickBooleanOptions,MagickFalse,options); 00718 break; 00719 } 00720 if (LocaleCompare(keyword,"matte-color") == 0) 00721 { 00722 (void) QueryColorDatabase(options,&image->matte_color, 00723 exception); 00724 break; 00725 } 00726 if (LocaleCompare(keyword,"montage") == 0) 00727 { 00728 (void) CloneString(&image->montage,options); 00729 break; 00730 } 00731 (void) SetImageAttribute(image,keyword,options); 00732 break; 00733 } 00734 case 'o': 00735 case 'O': 00736 { 00737 if (LocaleCompare(keyword,"opaque") == 0) 00738 { 00739 image->matte=(MagickBooleanType) ParseMagickOption( 00740 MagickBooleanOptions,MagickFalse,options); 00741 break; 00742 } 00743 (void) SetImageAttribute(image,keyword,options); 00744 break; 00745 } 00746 case 'p': 00747 case 'P': 00748 { 00749 if (LocaleCompare(keyword,"page") == 0) 00750 { 00751 char 00752 *geometry; 00753 00754 geometry=GetPageGeometry(options); 00755 (void) ParseAbsoluteGeometry(geometry,&image->page); 00756 geometry=(char *) RelinquishMagickMemory(geometry); 00757 break; 00758 } 00759 if (LocaleNCompare(keyword,"profile-",8) == 0) 00760 { 00761 if (profiles == (LinkedListInfo *) NULL) 00762 profiles=NewLinkedList(0); 00763 (void) AppendElementToLinkedList(profiles, 00764 AcquireString(keyword+8)); 00765 profile=AcquireStringInfo((size_t) atol(options)); 00766 (void) SetImageProfile(image,keyword+8,profile); 00767 profile=DestroyStringInfo(profile); 00768 break; 00769 } 00770 (void) SetImageAttribute(image,keyword,options); 00771 break; 00772 } 00773 case 'r': 00774 case 'R': 00775 { 00776 if (LocaleCompare(keyword,"red-primary") == 0) 00777 { 00778 flags=ParseGeometry(options,&geometry_info); 00779 image->chromaticity.red_primary.x=geometry_info.rho; 00780 image->chromaticity.red_primary.y=geometry_info.sigma; 00781 if ((flags & SigmaValue) == 0) 00782 image->chromaticity.red_primary.y= 00783 image->chromaticity.red_primary.x; 00784 break; 00785 } 00786 if (LocaleCompare(keyword,"rendering-intent") == 0) 00787 { 00788 image->rendering_intent=(RenderingIntent) 00789 ParseMagickOption(MagickIntentOptions,MagickFalse,options); 00790 break; 00791 } 00792 if (LocaleCompare(keyword,"resolution") == 0) 00793 { 00794 flags=ParseGeometry(options,&geometry_info); 00795 image->x_resolution=geometry_info.rho; 00796 image->y_resolution=geometry_info.sigma; 00797 if ((flags & SigmaValue) == 0) 00798 image->y_resolution=image->x_resolution; 00799 break; 00800 } 00801 if (LocaleCompare(keyword,"rows") == 0) 00802 { 00803 image->rows=(unsigned long) atol(options); 00804 break; 00805 } 00806 (void) SetImageAttribute(image,keyword,options); 00807 break; 00808 } 00809 case 's': 00810 case 'S': 00811 { 00812 if (LocaleCompare(keyword,"scene") == 0) 00813 { 00814 image->scene=(unsigned long) atol(options); 00815 break; 00816 } 00817 (void) SetImageAttribute(image,keyword,options); 00818 break; 00819 } 00820 case 'u': 00821 case 'U': 00822 { 00823 if (LocaleCompare(keyword,"units") == 0) 00824 { 00825 image->units=(ResolutionType) ParseMagickOption( 00826 MagickResolutionOptions,MagickFalse,options); 00827 break; 00828 } 00829 (void) SetImageAttribute(image,keyword,options); 00830 break; 00831 } 00832 case 'v': 00833 case 'V': 00834 { 00835 if (LocaleCompare(keyword,"version") == 0) 00836 { 00837 version=atof(options); 00838 break; 00839 } 00840 (void) SetImageAttribute(image,keyword,options); 00841 break; 00842 } 00843 case 'w': 00844 case 'W': 00845 { 00846 if (LocaleCompare(keyword,"white-point") == 0) 00847 { 00848 flags=ParseGeometry(options,&geometry_info); 00849 image->chromaticity.white_point.x=geometry_info.rho; 00850 image->chromaticity.white_point.y=geometry_info.rho; 00851 if ((flags & SigmaValue) != 0) 00852 image->chromaticity.white_point.y= 00853 image->chromaticity.white_point.x; 00854 break; 00855 } 00856 (void) SetImageAttribute(image,keyword,options); 00857 break; 00858 } 00859 default: 00860 { 00861 (void) SetImageAttribute(image,keyword,options); 00862 break; 00863 } 00864 } 00865 } 00866 else 00867 c=ReadBlobByte(image); 00868 while (isspace((int) ((unsigned char) c)) != 0) 00869 c=ReadBlobByte(image); 00870 } 00871 options=(char *) RelinquishMagickMemory(options); 00872 (void) ReadBlobByte(image); 00873 /* 00874 Verify that required image information is defined. 00875 */ 00876 if ((LocaleCompare(id,"ImageMagick") != 0) || 00877 (image->storage_class == UndefinedClass) || 00878 (image->columns == 0) || (image->rows == 0)) 00879 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 00880 if (image->montage != (char *) NULL) 00881 { 00882 register char 00883 *p; 00884 00885 /* 00886 Image directory. 00887 */ 00888 length=MaxTextExtent; 00889 image->directory=AcquireString((char *) NULL); 00890 p=image->directory; 00891 do 00892 { 00893 *p='\0'; 00894 if ((strlen(image->directory)+MaxTextExtent) >= length) 00895 { 00896 /* 00897 Allocate more memory for the image directory. 00898 */ 00899 length<<=1; 00900 image->directory=(char *) ResizeMagickMemory(image->directory, 00901 (length+MaxTextExtent)*sizeof(*image->directory)); 00902 if (image->directory == (char *) NULL) 00903 ThrowReaderException(CorruptImageError,"UnableToReadImageData"); 00904 p=image->directory+strlen(image->directory); 00905 } 00906 c=ReadBlobByte(image); 00907 *p++=(char) c; 00908 } while (c != (int) '\0'); 00909 } 00910 if (profiles != (LinkedListInfo *) NULL) 00911 { 00912 const char 00913 *name; 00914 00915 /* 00916 Read image profiles. 00917 */ 00918 ResetLinkedListIterator(profiles); 00919 name=(const char *) GetNextElementInLinkedList(profiles); 00920 while (name != (const char *) NULL) 00921 { 00922 profile=GetImageProfile(image,name); 00923 (void) ReadBlob(image,profile->length,profile->datum); 00924 name=(const char *) GetNextElementInLinkedList(profiles); 00925 } 00926 profiles=DestroyLinkedList(profiles,RelinquishMagickMemory); 00927 } 00928 depth=GetImageQuantumDepth(image,MagickFalse); 00929 if (image->storage_class == PseudoClass) 00930 { 00931 /* 00932 Create image colormap. 00933 */ 00934 status=AllocateImageColormap(image,colors != 0 ? colors : 256); 00935 if (status == MagickFalse) 00936 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 00937 if (colors != 0) 00938 { 00939 size_t 00940 packet_size; 00941 00942 unsigned char 00943 *colormap; 00944 00945 unsigned long 00946 pixel; 00947 00948 /* 00949 Read image colormap from file. 00950 */ 00951 packet_size=(size_t) (3*depth/8); 00952 colormap=(unsigned char *) 00953 AcquireMagickMemory(packet_size*image->colors); 00954 if (colormap == (unsigned char *) NULL) 00955 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 00956 (void) ReadBlob(image,packet_size*image->colors,colormap); 00957 p=colormap; 00958 switch (depth) 00959 { 00960 default: 00961 ThrowReaderException(CorruptImageError, 00962 "ImageDepthNotSupported"); 00963 case 8: 00964 { 00965 for (i=0; i < (long) image->colors; i++) 00966 { 00967 PushCharPixel(pixel,p); 00968 image->colormap[i].red=ScaleCharToQuantum(pixel); 00969 PushCharPixel(pixel,p); 00970 image->colormap[i].green=ScaleCharToQuantum(pixel); 00971 PushCharPixel(pixel,p); 00972 image->colormap[i].blue=ScaleCharToQuantum(pixel); 00973 } 00974 break; 00975 } 00976 case 16: 00977 { 00978 for (i=0; i < (long) image->colors; i++) 00979 { 00980 PushShortPixel(pixel,p); 00981 image->colormap[i].red=ScaleShortToQuantum(pixel); 00982 PushShortPixel(pixel,p); 00983 image->colormap[i].green=ScaleShortToQuantum(pixel); 00984 PushShortPixel(pixel,p); 00985 image->colormap[i].blue=ScaleShortToQuantum(pixel); 00986 } 00987 break; 00988 } 00989 case 32: 00990 { 00991 for (i=0; i < (long) image->colors; i++) 00992 { 00993 PushLongPixel(pixel,p); 00994 image->colormap[i].red=ScaleLongToQuantum(pixel); 00995 PushLongPixel(pixel,p); 00996 image->colormap[i].green=ScaleLongToQuantum(pixel); 00997 PushLongPixel(pixel,p); 00998 image->colormap[i].blue=ScaleLongToQuantum(pixel); 00999 } 01000 break; 01001 } 01002 } 01003 colormap=(unsigned char *) RelinquishMagickMemory(colormap); 01004 } 01005 } 01006 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0)) 01007 if (image->scene >= (image_info->scene+image_info->number_scenes-1)) 01008 break; 01009 /* 01010 Allocate image pixels. 01011 */ 01012 packet_size=(size_t) (depth/8); 01013 if (image->storage_class == DirectClass) 01014 packet_size=(size_t) (3*depth/8); 01015 if (image->matte != MagickFalse) 01016 packet_size+=depth/8; 01017 if (image->colorspace == CMYKColorspace) 01018 packet_size+=depth/8; 01019 if (image->compression == RLECompression) 01020 packet_size++; 01021 length=packet_size*image->columns; 01022 pixels=(unsigned char *) AcquireMagickMemory(packet_size*image->columns); 01023 length=(size_t) Max(BZipMaxExtent(packet_size*image->columns), 01024 ZipMaxExtent(packet_size*image->columns)); 01025 compress_pixels=(unsigned char *) AcquireMagickMemory(length); 01026 if ((pixels == (unsigned char *) NULL) || 01027 (compress_pixels == (unsigned char *) NULL)) 01028 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 01029 /* 01030 Read image pixels. 01031 */ 01032 quantum_type=RGBQuantum; 01033 if (image->storage_class == PseudoClass) 01034 quantum_type=image->matte != MagickFalse ? IndexAlphaQuantum : 01035 IndexQuantum; 01036 else 01037 if (image->colorspace == CMYKColorspace) 01038 quantum_type=image->matte != MagickFalse ? CMYKAQuantum : CMYKQuantum; 01039 else 01040 quantum_type=image->matte != MagickFalse ? RGBAQuantum : RGBQuantum; 01041 index=0; 01042 length=0; 01043 for (y=0; y < (long) image->rows; y++) 01044 { 01045 q=SetImagePixels(image,0,y,image->columns,1); 01046 if (q == (PixelPacket *) NULL) 01047 break; 01048 indexes=GetIndexes(image); 01049 switch (image->compression) 01050 { 01051 #if defined(HasZLIB) 01052 case ZipCompression: 01053 { 01054 if (y == 0) 01055 { 01056 zip_info.zalloc=AcquireZIPMemory; 01057 zip_info.zfree=RelinquishZIPMemory; 01058 zip_info.opaque=(voidpf) NULL; 01059 code=inflateInit(&zip_info); 01060 if (code >= 0) 01061 status=MagickTrue; 01062 zip_info.avail_in=0; 01063 } 01064 zip_info.next_out=pixels; 01065 zip_info.avail_out=(uInt) (packet_size*image->columns); 01066 do 01067 { 01068 if (zip_info.avail_in == 0) 01069 { 01070 zip_info.next_in=compress_pixels; 01071 length=(size_t) ZipMaxExtent(packet_size*image->columns); 01072 if (version != 0) 01073 length=(size_t) ReadBlobMSBLong(image); 01074 zip_info.avail_in=(unsigned int) 01075 ReadBlob(image,length,zip_info.next_in); 01076 } 01077 if (inflate(&zip_info,Z_NO_FLUSH) == Z_STREAM_END) 01078 break; 01079 } while (zip_info.avail_out != 0); 01080 if (y == (long) (image->rows-1)) 01081 { 01082 if (version == 0) 01083 (void) SeekBlob(image,-((MagickOffsetType) zip_info.avail_in), 01084 SEEK_CUR); 01085 code=inflateEnd(&zip_info); 01086 if (code >= 0) 01087 status=MagickTrue; 01088 } 01089 (void) PushImagePixels(image,quantum_type,pixels); 01090 break; 01091 } 01092 #endif 01093 #if defined(HasBZLIB) 01094 case BZipCompression: 01095 { 01096 if (y == 0) 01097 { 01098 bzip_info.bzalloc=AcquireBZIPMemory; 01099 bzip_info.bzfree=RelinquishBZIPMemory; 01100 bzip_info.opaque=(void *) NULL; 01101 code=BZ2_bzDecompressInit(&bzip_info,(int) image_info->verbose, 01102 MagickFalse); 01103 if (code >= 0) 01104 status=MagickTrue; 01105 bzip_info.avail_in=0; 01106 } 01107 bzip_info.next_out=(char *) pixels; 01108 bzip_info.avail_out=(unsigned int) (packet_size*image->columns); 01109 do 01110 { 01111 if (bzip_info.avail_in == 0) 01112 { 01113 bzip_info.next_in=(char *) compress_pixels; 01114 length=(size_t) BZipMaxExtent(packet_size*image->columns); 01115 if (version != 0) 01116 length=(size_t) ReadBlobMSBLong(image); 01117 bzip_info.avail_in=(unsigned int) 01118 ReadBlob(image,length,(unsigned char *) bzip_info.next_in); 01119 } 01120 if (BZ2_bzDecompress(&bzip_info) == BZ_STREAM_END) 01121 break; 01122 } while (bzip_info.avail_out != 0); 01123 if (y == (long) (image->rows-1)) 01124 { 01125 if (version == 0) 01126 (void) SeekBlob(image,-((MagickOffsetType) bzip_info.avail_in), 01127 SEEK_CUR); 01128 code=BZ2_bzDecompressEnd(&bzip_info); 01129 if (code >= 0) 01130 status=MagickTrue; 01131 } 01132 (void) PushImagePixels(image,quantum_type,pixels); 01133 break; 01134 } 01135 #endif 01136 case RLECompression: 01137 { 01138 if (y == 0) 01139 { 01140 (void) ResetMagickMemory(&pixel,0,sizeof(pixel)); 01141 pixel.opacity=TransparentOpacity; 01142 index=0; 01143 } 01144 for (x=0; x < (long) image->columns; x++) 01145 { 01146 if (length == 0) 01147 { 01148 (void) ReadBlob(image,packet_size,pixels); 01149 PushRunlengthPacket(image,depth,pixels,&length,&pixel,&index); 01150 } 01151 length--; 01152 if ((image->storage_class == PseudoClass) || 01153 (image->colorspace == CMYKColorspace)) 01154 indexes[x]=index; 01155 *q++=pixel; 01156 } 01157 break; 01158 } 01159 default: 01160 { 01161 (void) ReadBlob(image,packet_size*image->columns,pixels); 01162 (void) PushImagePixels(image,quantum_type,pixels); 01163 break; 01164 } 01165 } 01166 if (SyncImagePixels(image) == MagickFalse) 01167 break; 01168 } 01169 pixels=(unsigned char *) RelinquishMagickMemory(pixels); 01170 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels); 01171 if (((y != (long) image->rows)) || (status == MagickFalse)) 01172 { 01173 DestroyImageList(image); 01174 return((Image *) NULL); 01175 } 01176 if (EOFBlob(image) != MagickFalse) 01177 { 01178 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", 01179 image->filename); 01180 break; 01181 } 01182 /* 01183 Proceed to next image. 01184 */ 01185 if (image_info->number_scenes != 0) 01186 if (image->scene >= (image_info->scene+image_info->number_scenes-1)) 01187 break; 01188 do 01189 { 01190 c=ReadBlobByte(image); 01191 } while ((isgraph(c) == MagickFalse) && (c != EOF)); 01192 if (c != EOF) 01193 { 01194 /* 01195 Allocate next image structure. 01196 */ 01197 AllocateNextImage(image_info,image); 01198 if (image->next == (Image *) NULL) 01199 { 01200 DestroyImageList(image); 01201 return((Image *) NULL); 01202 } 01203 image=SyncNextImageInList(image); 01204 if (image->progress_monitor != (MagickProgressMonitor) NULL) 01205 { 01206 status=image->progress_monitor(LoadImagesTag,TellBlob(image), 01207 GetBlobSize(image),image->client_data); 01208 if (status == MagickFalse) 01209 break; 01210 } 01211 } 01212 } while (c != EOF); 01213 CloseBlob(image); 01214 return(GetFirstImageInList(image)); 01215 } 01216 01217 /* 01218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01219 % % 01220 % % 01221 % % 01222 % R e g i s t e r M I F F I m a g e % 01223 % % 01224 % % 01225 % % 01226 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01227 % 01228 % RegisterMIFFImage() adds attributes for the MIFF image format to the list of 01229 % supported formats. The attributes include the image format tag, a method to 01230 % read and/or write the format, whether the format supports the saving of more 01231 % than one frame to the same file or blob, whether the format supports native 01232 % in-memory I/O, and a brief description of the format. 01233 % 01234 % The format of the RegisterMIFFImage method is: 01235 % 01236 % RegisterMIFFImage(void) 01237 % 01238 */ 01239 ModuleExport void RegisterMIFFImage(void) 01240 { 01241 char 01242 version[MaxTextExtent]; 01243 01244 MagickInfo 01245 *entry; 01246 01247 *version='\0'; 01248 #if defined(MagickLibVersionText) 01249 (void) CopyMagickString(version,MagickLibVersionText,MaxTextExtent); 01250 #if defined(ZLIB_VERSION) 01251 (void) ConcatenateMagickString(version," with Zlib ",MaxTextExtent); 01252 (void) ConcatenateMagickString(version,ZLIB_VERSION,MaxTextExtent); 01253 #endif 01254 #if defined(HasBZLIB) 01255 (void) ConcatenateMagickString(version," and BZlib",MaxTextExtent); 01256 #endif 01257 #endif 01258 entry=SetMagickInfo("MIFF"); 01259 entry->decoder=(DecoderHandler *) ReadMIFFImage; 01260 entry->encoder=(EncoderHandler *) WriteMIFFImage; 01261 entry->magick=(MagickHandler *) IsMIFF; 01262 entry->description=AcquireString("Magick Image File Format"); 01263 if (*version != '\0') 01264 entry->version=AcquireString(version); 01265 entry->module=AcquireString("MIFF"); 01266 (void) RegisterMagickInfo(entry); 01267 } 01268 01269 /* 01270 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01271 % % 01272 % % 01273 % % 01274 % U n r e g i s t e r M I F F I m a g e % 01275 % % 01276 % % 01277 % % 01278 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01279 % 01280 % UnregisterMIFFImage() removes format registrations made by the MIFF module 01281 % from the list of supported formats. 01282 % 01283 % The format of the UnregisterMIFFImage method is: 01284 % 01285 % UnregisterMIFFImage(void) 01286 % 01287 */ 01288 ModuleExport void UnregisterMIFFImage(void) 01289 { 01290 (void) UnregisterMagickInfo("MIFF"); 01291 } 01292 01293 /* 01294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01295 % % 01296 % % 01297 % % 01298 % W r i t e M I F F I m a g e % 01299 % % 01300 % % 01301 % % 01302 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01303 % 01304 % WriteMIFFImage() writes a MIFF image to a file. 01305 % 01306 % The format of the WriteMIFFImage method is: 01307 % 01308 % MagickBooleanType WriteMIFFImage(const ImageInfo *image_info,Image *image) 01309 % 01310 % Compression code contributed by Kyle Shorter. 01311 % 01312 % A description of each parameter follows: 01313 % 01314 % o image_info: The image info. 01315 % 01316 % o image: The image. 01317 % 01318 % 01319 */ 01320 01321 static inline size_t PopRunlengthPacket(Image *image,const unsigned long depth, 01322 unsigned char *pixels,size_t length,PixelPacket pixel,IndexPacket index) 01323 { 01324 register unsigned char 01325 *q; 01326 01327 unsigned long 01328 value; 01329 01330 q=pixels; 01331 if (image->storage_class != DirectClass) 01332 { 01333 switch (depth) 01334 { 01335 case 32: 01336 { 01337 *q++=(unsigned char) (index >> 24); 01338 *q++=(unsigned char) (index >> 16); 01339 } 01340 case 16: 01341 *q++=(unsigned char) (index >> 8); 01342 case 8: 01343 { 01344 *q++=(unsigned char) index; 01345 break; 01346 } 01347 default: 01348 (void) ThrowMagickException(&image->exception,GetMagickModule(), 01349 CorruptImageError,"ImageDepthNotSupported",image->filename); 01350 } 01351 switch (depth) 01352 { 01353 case 32: 01354 { 01355 if (image->matte != MagickFalse) 01356 { 01357 value=ScaleQuantumToLong(pixel.opacity); 01358 PopLongPixel(q,value); 01359 } 01360 break; 01361 } 01362 case 16: 01363 { 01364 if (image->matte != MagickFalse) 01365 { 01366 value=ScaleQuantumToShort(pixel.opacity); 01367 PopShortPixel(q,value); 01368 } 01369 break; 01370 } 01371 case 8: 01372 { 01373 if (image->matte != MagickFalse) 01374 { 01375 value=(unsigned long) ScaleQuantumToChar(pixel.opacity); 01376 PopCharPixel(q,value); 01377 } 01378 break; 01379 } 01380 default: 01381 (void) ThrowMagickException(&image->exception,GetMagickModule(), 01382 CorruptImageError,"ImageDepthNotSupported",image->filename); 01383 } 01384 *q++=(unsigned