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

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