|
MagickCore
6.7.5
|
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % CCCC AAA CCCC H H EEEEE % 00007 % C A A C H H E % 00008 % C AAAAA C HHHHH EEE % 00009 % C A A C H H E % 00010 % CCCC A A CCCC H H EEEEE % 00011 % % 00012 % % 00013 % MagickCore Pixel Cache Methods % 00014 % % 00015 % Software Design % 00016 % John Cristy % 00017 % July 1999 % 00018 % % 00019 % % 00020 % Copyright 1999-2012 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/script/license.php % 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 "MagickCore/studio.h" 00044 #include "MagickCore/blob.h" 00045 #include "MagickCore/blob-private.h" 00046 #include "MagickCore/cache.h" 00047 #include "MagickCore/cache-private.h" 00048 #include "MagickCore/color-private.h" 00049 #include "MagickCore/composite-private.h" 00050 #include "MagickCore/exception.h" 00051 #include "MagickCore/exception-private.h" 00052 #include "MagickCore/geometry.h" 00053 #include "MagickCore/list.h" 00054 #include "MagickCore/log.h" 00055 #include "MagickCore/magick.h" 00056 #include "MagickCore/memory_.h" 00057 #include "MagickCore/pixel.h" 00058 #include "MagickCore/pixel-accessor.h" 00059 #include "MagickCore/policy.h" 00060 #include "MagickCore/quantum.h" 00061 #include "MagickCore/random_.h" 00062 #include "MagickCore/resource_.h" 00063 #include "MagickCore/semaphore.h" 00064 #include "MagickCore/splay-tree.h" 00065 #include "MagickCore/string_.h" 00066 #include "MagickCore/string-private.h" 00067 #include "MagickCore/thread-private.h" 00068 #include "MagickCore/utility.h" 00069 #include "MagickCore/utility-private.h" 00070 #if defined(MAGICKCORE_ZLIB_DELEGATE) 00071 #include "zlib.h" 00072 #endif 00073 00074 /* 00075 Define declarations. 00076 */ 00077 #define CacheTick(offset,extent) QuantumTick((MagickOffsetType) offset,extent) 00078 #define IsFileDescriptorLimitExceeded() (GetMagickResource(FileResource) > \ 00079 GetMagickResourceLimit(FileResource) ? MagickTrue : MagickFalse) 00080 00081 /* 00082 Typedef declarations. 00083 */ 00084 typedef struct _MagickModulo 00085 { 00086 ssize_t 00087 quotient, 00088 remainder; 00089 } MagickModulo; 00090 00091 struct _NexusInfo 00092 { 00093 MagickBooleanType 00094 mapped; 00095 00096 RectangleInfo 00097 region; 00098 00099 MagickSizeType 00100 length; 00101 00102 Quantum 00103 *cache, 00104 *pixels; 00105 00106 void 00107 *metacontent; 00108 00109 size_t 00110 signature; 00111 }; 00112 00113 /* 00114 Forward declarations. 00115 */ 00116 #if defined(__cplusplus) || defined(c_plusplus) 00117 extern "C" { 00118 #endif 00119 00120 static const Quantum 00121 *GetVirtualPixelCache(const Image *,const VirtualPixelMethod,const ssize_t, 00122 const ssize_t,const size_t,const size_t,ExceptionInfo *), 00123 *GetVirtualPixelsCache(const Image *); 00124 00125 static const void 00126 *GetVirtualMetacontentFromCache(const Image *); 00127 00128 static MagickBooleanType 00129 GetOneAuthenticPixelFromCache(Image *,const ssize_t,const ssize_t, 00130 Quantum *,ExceptionInfo *), 00131 GetOneVirtualPixelFromCache(const Image *,const VirtualPixelMethod, 00132 const ssize_t,const ssize_t,Quantum *,ExceptionInfo *), 00133 OpenPixelCache(Image *,const MapMode,ExceptionInfo *), 00134 ReadPixelCacheMetacontent(CacheInfo *,NexusInfo *,ExceptionInfo *), 00135 ReadPixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *), 00136 SyncAuthenticPixelsCache(Image *,ExceptionInfo *), 00137 WritePixelCacheMetacontent(CacheInfo *,NexusInfo *,ExceptionInfo *), 00138 WritePixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *); 00139 00140 static Quantum 00141 *GetAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const size_t, 00142 const size_t,ExceptionInfo *), 00143 *QueueAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const size_t, 00144 const size_t,ExceptionInfo *), 00145 *SetPixelCacheNexusPixels(const Image *,const RectangleInfo *,NexusInfo *, 00146 ExceptionInfo *); 00147 00148 #if defined(__cplusplus) || defined(c_plusplus) 00149 } 00150 #endif 00151 00152 /* 00153 Global declarations. 00154 */ 00155 static volatile MagickBooleanType 00156 instantiate_cache = MagickFalse; 00157 00158 static SemaphoreInfo 00159 *cache_semaphore = (SemaphoreInfo *) NULL; 00160 00161 /* 00162 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00163 % % 00164 % % 00165 % % 00166 + A c q u i r e P i x e l C a c h e % 00167 % % 00168 % % 00169 % % 00170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00171 % 00172 % AcquirePixelCache() acquires a pixel cache. 00173 % 00174 % The format of the AcquirePixelCache() method is: 00175 % 00176 % Cache AcquirePixelCache(const size_t number_threads) 00177 % 00178 % A description of each parameter follows: 00179 % 00180 % o number_threads: the number of nexus threads. 00181 % 00182 */ 00183 MagickPrivate Cache AcquirePixelCache(const size_t number_threads) 00184 { 00185 CacheInfo 00186 *cache_info; 00187 00188 cache_info=(CacheInfo *) AcquireQuantumMemory(1,sizeof(*cache_info)); 00189 if (cache_info == (CacheInfo *) NULL) 00190 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 00191 (void) ResetMagickMemory(cache_info,0,sizeof(*cache_info)); 00192 cache_info->type=UndefinedCache; 00193 cache_info->mode=IOMode; 00194 cache_info->colorspace=RGBColorspace; 00195 cache_info->file=(-1); 00196 cache_info->id=GetMagickThreadId(); 00197 cache_info->number_threads=number_threads; 00198 if (number_threads == 0) 00199 cache_info->number_threads=GetOpenMPMaximumThreads(); 00200 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads); 00201 if (cache_info->nexus_info == (NexusInfo **) NULL) 00202 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 00203 cache_info->semaphore=AllocateSemaphoreInfo(); 00204 cache_info->reference_count=1; 00205 cache_info->disk_semaphore=AllocateSemaphoreInfo(); 00206 cache_info->debug=IsEventLogging(); 00207 cache_info->signature=MagickSignature; 00208 return((Cache ) cache_info); 00209 } 00210 00211 /* 00212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00213 % % 00214 % % 00215 % % 00216 % A c q u i r e P i x e l C a c h e N e x u s % 00217 % % 00218 % % 00219 % % 00220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00221 % 00222 % AcquirePixelCacheNexus() allocates the NexusInfo structure. 00223 % 00224 % The format of the AcquirePixelCacheNexus method is: 00225 % 00226 % NexusInfo **AcquirePixelCacheNexus(const size_t number_threads) 00227 % 00228 % A description of each parameter follows: 00229 % 00230 % o number_threads: the number of nexus threads. 00231 % 00232 */ 00233 MagickPrivate NexusInfo **AcquirePixelCacheNexus(const size_t number_threads) 00234 { 00235 NexusInfo 00236 **nexus_info; 00237 00238 register ssize_t 00239 i; 00240 00241 nexus_info=(NexusInfo **) AcquireQuantumMemory(number_threads, 00242 sizeof(*nexus_info)); 00243 if (nexus_info == (NexusInfo **) NULL) 00244 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 00245 for (i=0; i < (ssize_t) number_threads; i++) 00246 { 00247 nexus_info[i]=(NexusInfo *) AcquireQuantumMemory(1,sizeof(**nexus_info)); 00248 if (nexus_info[i] == (NexusInfo *) NULL) 00249 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 00250 (void) ResetMagickMemory(nexus_info[i],0,sizeof(*nexus_info[i])); 00251 nexus_info[i]->signature=MagickSignature; 00252 } 00253 return(nexus_info); 00254 } 00255 00256 /* 00257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00258 % % 00259 % % 00260 % % 00261 + A c q u i r e P i x e l C a c h e P i x e l s % 00262 % % 00263 % % 00264 % % 00265 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00266 % 00267 % AcquirePixelCachePixels() returns the pixels associated with the specified 00268 % image. 00269 % 00270 % The format of the AcquirePixelCachePixels() method is: 00271 % 00272 % const void *AcquirePixelCachePixels(const Image *image, 00273 % MagickSizeType *length,ExceptionInfo *exception) 00274 % 00275 % A description of each parameter follows: 00276 % 00277 % o image: the image. 00278 % 00279 % o length: the pixel cache length. 00280 % 00281 % o exception: return any errors or warnings in this structure. 00282 % 00283 */ 00284 MagickPrivate const void *AcquirePixelCachePixels(const Image *image, 00285 MagickSizeType *length,ExceptionInfo *exception) 00286 { 00287 CacheInfo 00288 *cache_info; 00289 00290 assert(image != (const Image *) NULL); 00291 assert(image->signature == MagickSignature); 00292 assert(exception != (ExceptionInfo *) NULL); 00293 assert(exception->signature == MagickSignature); 00294 assert(image->cache != (Cache) NULL); 00295 cache_info=(CacheInfo *) image->cache; 00296 assert(cache_info->signature == MagickSignature); 00297 *length=0; 00298 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache)) 00299 return((const void *) NULL); 00300 *length=cache_info->length; 00301 return((const void *) cache_info->pixels); 00302 } 00303 00304 /* 00305 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00306 % % 00307 % % 00308 % % 00309 + C a c h e C o m p o n e n t G e n e s i s % 00310 % % 00311 % % 00312 % % 00313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00314 % 00315 % CacheComponentGenesis() instantiates the cache component. 00316 % 00317 % The format of the CacheComponentGenesis method is: 00318 % 00319 % MagickBooleanType CacheComponentGenesis(void) 00320 % 00321 */ 00322 MagickPrivate MagickBooleanType CacheComponentGenesis(void) 00323 { 00324 AcquireSemaphoreInfo(&cache_semaphore); 00325 return(MagickTrue); 00326 } 00327 00328 /* 00329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00330 % % 00331 % % 00332 % % 00333 + C a c h e C o m p o n e n t T e r m i n u s % 00334 % % 00335 % % 00336 % % 00337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00338 % 00339 % CacheComponentTerminus() destroys the cache component. 00340 % 00341 % The format of the CacheComponentTerminus() method is: 00342 % 00343 % CacheComponentTerminus(void) 00344 % 00345 */ 00346 MagickPrivate void CacheComponentTerminus(void) 00347 { 00348 if (cache_semaphore == (SemaphoreInfo *) NULL) 00349 AcquireSemaphoreInfo(&cache_semaphore); 00350 LockSemaphoreInfo(cache_semaphore); 00351 instantiate_cache=MagickFalse; 00352 UnlockSemaphoreInfo(cache_semaphore); 00353 DestroySemaphoreInfo(&cache_semaphore); 00354 } 00355 00356 /* 00357 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00358 % % 00359 % % 00360 % % 00361 + C l o n e P i x e l C a c h e % 00362 % % 00363 % % 00364 % % 00365 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00366 % 00367 % ClonePixelCache() clones a pixel cache. 00368 % 00369 % The format of the ClonePixelCache() method is: 00370 % 00371 % Cache ClonePixelCache(const Cache cache) 00372 % 00373 % A description of each parameter follows: 00374 % 00375 % o cache: the pixel cache. 00376 % 00377 */ 00378 MagickPrivate Cache ClonePixelCache(const Cache cache) 00379 { 00380 CacheInfo 00381 *clone_info; 00382 00383 const CacheInfo 00384 *cache_info; 00385 00386 assert(cache != NULL); 00387 cache_info=(const CacheInfo *) cache; 00388 assert(cache_info->signature == MagickSignature); 00389 if (cache_info->debug != MagickFalse) 00390 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 00391 cache_info->filename); 00392 clone_info=(CacheInfo *) AcquirePixelCache(cache_info->number_threads); 00393 if (clone_info == (Cache) NULL) 00394 return((Cache) NULL); 00395 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method; 00396 return((Cache ) clone_info); 00397 } 00398 00399 /* 00400 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00401 % % 00402 % % 00403 % % 00404 + C l o n e P i x e l C a c h e P i x e l s % 00405 % % 00406 % % 00407 % % 00408 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % 00409 % ClonePixelCachePixels() clones the source pixel cache to the destination 00410 % cache. 00411 % 00412 % The format of the ClonePixelCachePixels() method is: 00413 % 00414 % MagickBooleanType ClonePixelCachePixels(CacheInfo *cache_info, 00415 % CacheInfo *source_info,ExceptionInfo *exception) 00416 % 00417 % A description of each parameter follows: 00418 % 00419 % o cache_info: the pixel cache. 00420 % 00421 % o source_info: the source pixel cache. 00422 % 00423 % o exception: return any errors or warnings in this structure. 00424 % 00425 */ 00426 00427 static MagickBooleanType ClosePixelCacheOnDisk(CacheInfo *cache_info) 00428 { 00429 int 00430 status; 00431 00432 status=(-1); 00433 LockSemaphoreInfo(cache_info->disk_semaphore); 00434 if (cache_info->file != -1) 00435 { 00436 status=close(cache_info->file); 00437 cache_info->file=(-1); 00438 RelinquishMagickResource(FileResource,1); 00439 } 00440 UnlockSemaphoreInfo(cache_info->disk_semaphore); 00441 return(status == -1 ? MagickFalse : MagickTrue); 00442 } 00443 00444 static inline MagickSizeType MagickMax(const MagickSizeType x, 00445 const MagickSizeType y) 00446 { 00447 if (x > y) 00448 return(x); 00449 return(y); 00450 } 00451 00452 static inline MagickSizeType MagickMin(const MagickSizeType x, 00453 const MagickSizeType y) 00454 { 00455 if (x < y) 00456 return(x); 00457 return(y); 00458 } 00459 00460 static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info, 00461 const MapMode mode) 00462 { 00463 int 00464 file; 00465 00466 /* 00467 Open pixel cache on disk. 00468 */ 00469 LockSemaphoreInfo(cache_info->disk_semaphore); 00470 if (cache_info->file != -1) 00471 { 00472 UnlockSemaphoreInfo(cache_info->disk_semaphore); 00473 return(MagickTrue); /* cache already open */ 00474 } 00475 if (*cache_info->cache_filename == '\0') 00476 file=AcquireUniqueFileResource(cache_info->cache_filename); 00477 else 00478 switch (mode) 00479 { 00480 case ReadMode: 00481 { 00482 file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0); 00483 break; 00484 } 00485 case WriteMode: 00486 { 00487 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT | 00488 O_BINARY | O_EXCL,S_MODE); 00489 if (file == -1) 00490 file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE); 00491 break; 00492 } 00493 case IOMode: 00494 default: 00495 { 00496 file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY | 00497 O_EXCL,S_MODE); 00498 if (file == -1) 00499 file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE); 00500 break; 00501 } 00502 } 00503 if (file == -1) 00504 { 00505 UnlockSemaphoreInfo(cache_info->disk_semaphore); 00506 return(MagickFalse); 00507 } 00508 (void) AcquireMagickResource(FileResource,1); 00509 cache_info->file=file; 00510 cache_info->mode=mode; 00511 cache_info->timestamp=time(0); 00512 UnlockSemaphoreInfo(cache_info->disk_semaphore); 00513 return(MagickTrue); 00514 } 00515 00516 static inline MagickOffsetType ReadPixelCacheRegion(CacheInfo *cache_info, 00517 const MagickOffsetType offset,const MagickSizeType length, 00518 unsigned char *restrict buffer) 00519 { 00520 register MagickOffsetType 00521 i; 00522 00523 ssize_t 00524 count; 00525 00526 cache_info->timestamp=time(0); 00527 #if !defined(MAGICKCORE_HAVE_PREAD) 00528 LockSemaphoreInfo(cache_info->disk_semaphore); 00529 if (lseek(cache_info->file,offset,SEEK_SET) < 0) 00530 { 00531 UnlockSemaphoreInfo(cache_info->disk_semaphore); 00532 return((MagickOffsetType) -1); 00533 } 00534 #endif 00535 count=0; 00536 for (i=0; i < (MagickOffsetType) length; i+=count) 00537 { 00538 #if !defined(MAGICKCORE_HAVE_PREAD) 00539 count=read(cache_info->file,buffer+i,(size_t) MagickMin(length-i, 00540 (MagickSizeType) SSIZE_MAX)); 00541 #else 00542 count=pread(cache_info->file,buffer+i,(size_t) MagickMin(length-i, 00543 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i)); 00544 #endif 00545 if (count > 0) 00546 continue; 00547 count=0; 00548 if (errno != EINTR) 00549 { 00550 i=(-1); 00551 break; 00552 } 00553 } 00554 #if !defined(MAGICKCORE_HAVE_PREAD) 00555 UnlockSemaphoreInfo(cache_info->disk_semaphore); 00556 #endif 00557 return(i); 00558 } 00559 00560 static inline MagickOffsetType WritePixelCacheRegion(CacheInfo *cache_info, 00561 const MagickOffsetType offset,const MagickSizeType length, 00562 const unsigned char *restrict buffer) 00563 { 00564 register MagickOffsetType 00565 i; 00566 00567 ssize_t 00568 count; 00569 00570 cache_info->timestamp=time(0); 00571 #if !defined(MAGICKCORE_HAVE_PWRITE) 00572 LockSemaphoreInfo(cache_info->disk_semaphore); 00573 if (lseek(cache_info->file,offset,SEEK_SET) < 0) 00574 { 00575 UnlockSemaphoreInfo(cache_info->disk_semaphore); 00576 return((MagickOffsetType) -1); 00577 } 00578 #endif 00579 count=0; 00580 for (i=0; i < (MagickOffsetType) length; i+=count) 00581 { 00582 #if !defined(MAGICKCORE_HAVE_PWRITE) 00583 count=write(cache_info->file,buffer+i,(size_t) MagickMin(length-i, 00584 (MagickSizeType) SSIZE_MAX)); 00585 #else 00586 count=pwrite(cache_info->file,buffer+i,(size_t) MagickMin(length-i, 00587 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i)); 00588 #endif 00589 if (count > 0) 00590 continue; 00591 count=0; 00592 if (errno != EINTR) 00593 { 00594 i=(-1); 00595 break; 00596 } 00597 } 00598 #if !defined(MAGICKCORE_HAVE_PWRITE) 00599 UnlockSemaphoreInfo(cache_info->disk_semaphore); 00600 #endif 00601 return(i); 00602 } 00603 00604 static MagickBooleanType DiskToDiskPixelCacheClone(CacheInfo *clone_info, 00605 CacheInfo *cache_info,ExceptionInfo *exception) 00606 { 00607 MagickOffsetType 00608 count; 00609 00610 register MagickOffsetType 00611 i; 00612 00613 size_t 00614 length; 00615 00616 unsigned char 00617 *blob; 00618 00619 /* 00620 Clone pixel cache (both caches on disk). 00621 */ 00622 if (cache_info->debug != MagickFalse) 00623 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => disk"); 00624 blob=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent, 00625 sizeof(*blob)); 00626 if (blob == (unsigned char *) NULL) 00627 { 00628 (void) ThrowMagickException(exception,GetMagickModule(), 00629 ResourceLimitError,"MemoryAllocationFailed","`%s'", 00630 cache_info->filename); 00631 return(MagickFalse); 00632 } 00633 if (OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) 00634 { 00635 blob=(unsigned char *) RelinquishMagickMemory(blob); 00636 ThrowFileException(exception,FileOpenError,"UnableToOpenFile", 00637 cache_info->cache_filename); 00638 return(MagickFalse); 00639 } 00640 if (OpenPixelCacheOnDisk(clone_info,WriteMode) == MagickFalse) 00641 { 00642 (void) ClosePixelCacheOnDisk(cache_info); 00643 blob=(unsigned char *) RelinquishMagickMemory(blob); 00644 ThrowFileException(exception,FileOpenError,"UnableToOpenFile", 00645 clone_info->cache_filename); 00646 return(MagickFalse); 00647 } 00648 count=0; 00649 for (i=0; i < (MagickOffsetType) cache_info->length; i+=count) 00650 { 00651 count=ReadPixelCacheRegion(cache_info,cache_info->offset+i, 00652 MagickMin(cache_info->length-i,(MagickSizeType) MagickMaxBufferExtent), 00653 blob); 00654 if (count <= 0) 00655 { 00656 ThrowFileException(exception,CacheError,"UnableToReadPixelCache", 00657 cache_info->cache_filename); 00658 break; 00659 } 00660 length=(size_t) count; 00661 count=WritePixelCacheRegion(clone_info,clone_info->offset+i,length,blob); 00662 if ((MagickSizeType) count != length) 00663 { 00664 ThrowFileException(exception,CacheError,"UnableToWritePixelCache", 00665 clone_info->cache_filename); 00666 break; 00667 } 00668 } 00669 (void) ClosePixelCacheOnDisk(clone_info); 00670 (void) ClosePixelCacheOnDisk(cache_info); 00671 blob=(unsigned char *) RelinquishMagickMemory(blob); 00672 if (i < (MagickOffsetType) cache_info->length) 00673 return(MagickFalse); 00674 return(MagickTrue); 00675 } 00676 00677 static MagickBooleanType PixelCacheCloneOptimized(CacheInfo *clone_info, 00678 CacheInfo *cache_info,ExceptionInfo *exception) 00679 { 00680 MagickOffsetType 00681 count; 00682 00683 if ((cache_info->type != DiskCache) && (clone_info->type != DiskCache)) 00684 { 00685 /* 00686 Clone pixel cache (both caches in memory). 00687 */ 00688 if (cache_info->debug != MagickFalse) 00689 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => memory"); 00690 (void) memcpy(clone_info->pixels,cache_info->pixels,(size_t) 00691 cache_info->length); 00692 return(MagickTrue); 00693 } 00694 if ((clone_info->type != DiskCache) && (cache_info->type == DiskCache)) 00695 { 00696 /* 00697 Clone pixel cache (one cache on disk, one in memory). 00698 */ 00699 if (cache_info->debug != MagickFalse) 00700 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => memory"); 00701 if (OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) 00702 { 00703 ThrowFileException(exception,FileOpenError,"UnableToOpenFile", 00704 cache_info->cache_filename); 00705 return(MagickFalse); 00706 } 00707 count=ReadPixelCacheRegion(cache_info,cache_info->offset, 00708 cache_info->length,(unsigned char *) clone_info->pixels); 00709 (void) ClosePixelCacheOnDisk(cache_info); 00710 if ((MagickSizeType) count != cache_info->length) 00711 { 00712 ThrowFileException(exception,CacheError,"UnableToReadPixelCache", 00713 cache_info->cache_filename); 00714 return(MagickFalse); 00715 } 00716 return(MagickTrue); 00717 } 00718 if ((clone_info->type == DiskCache) && (cache_info->type != DiskCache)) 00719 { 00720 /* 00721 Clone pixel cache (one cache on disk, one in memory). 00722 */ 00723 if (clone_info->debug != MagickFalse) 00724 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => disk"); 00725 if (OpenPixelCacheOnDisk(clone_info,WriteMode) == MagickFalse) 00726 { 00727 ThrowFileException(exception,FileOpenError,"UnableToOpenFile", 00728 clone_info->cache_filename); 00729 return(MagickFalse); 00730 } 00731 count=WritePixelCacheRegion(clone_info,clone_info->offset, 00732 clone_info->length,(unsigned char *) cache_info->pixels); 00733 (void) ClosePixelCacheOnDisk(clone_info); 00734 if ((MagickSizeType) count != clone_info->length) 00735 { 00736 ThrowFileException(exception,CacheError,"UnableToWritePixelCache", 00737 clone_info->cache_filename); 00738 return(MagickFalse); 00739 } 00740 return(MagickTrue); 00741 } 00742 /* 00743 Clone pixel cache (both caches on disk). 00744 */ 00745 return(DiskToDiskPixelCacheClone(clone_info,cache_info,exception)); 00746 } 00747 00748 static MagickBooleanType PixelCacheCloneUnoptimized(CacheInfo *clone_info, 00749 CacheInfo *cache_info,ExceptionInfo *exception) 00750 { 00751 MagickBooleanType 00752 status; 00753 00754 MagickOffsetType 00755 cache_offset, 00756 clone_offset, 00757 count; 00758 00759 register ssize_t 00760 x; 00761 00762 register unsigned char 00763 *p; 00764 00765 size_t 00766 length; 00767 00768 ssize_t 00769 y; 00770 00771 unsigned char 00772 *blob; 00773 00774 /* 00775 Clone pixel cache (unoptimized). 00776 */ 00777 if (cache_info->debug != MagickFalse) 00778 { 00779 if ((cache_info->type != DiskCache) && (clone_info->type != DiskCache)) 00780 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => memory"); 00781 else 00782 if ((clone_info->type != DiskCache) && (cache_info->type == DiskCache)) 00783 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => memory"); 00784 else 00785 if ((clone_info->type == DiskCache) && (cache_info->type != DiskCache)) 00786 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => disk"); 00787 else 00788 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => disk"); 00789 } 00790 length=(size_t) MagickMax(MagickMax(cache_info->number_channels, 00791 clone_info->number_channels)*sizeof(Quantum),MagickMax( 00792 cache_info->metacontent_extent,clone_info->metacontent_extent)); 00793 blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(*blob)); 00794 if (blob == (unsigned char *) NULL) 00795 { 00796 (void) ThrowMagickException(exception,GetMagickModule(), 00797 ResourceLimitError,"MemoryAllocationFailed","`%s'", 00798 cache_info->filename); 00799 return(MagickFalse); 00800 } 00801 (void) ResetMagickMemory(blob,0,length*sizeof(*blob)); 00802 cache_offset=0; 00803 clone_offset=0; 00804 if (cache_info->type == DiskCache) 00805 { 00806 if (OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) 00807 { 00808 blob=(unsigned char *) RelinquishMagickMemory(blob); 00809 ThrowFileException(exception,FileOpenError,"UnableToOpenFile", 00810 cache_info->cache_filename); 00811 return(MagickFalse); 00812 } 00813 cache_offset=cache_info->offset; 00814 } 00815 if (clone_info->type == DiskCache) 00816 { 00817 if (OpenPixelCacheOnDisk(clone_info,WriteMode) == MagickFalse) 00818 { 00819 blob=(unsigned char *) RelinquishMagickMemory(blob); 00820 ThrowFileException(exception,FileOpenError,"UnableToOpenFile", 00821 clone_info->cache_filename); 00822 return(MagickFalse); 00823 } 00824 clone_offset=clone_info->offset; 00825 } 00826 /* 00827 Clone pixel channels. 00828 */ 00829 status=MagickTrue; 00830 p=blob; 00831 for (y=0; y < (ssize_t) cache_info->rows; y++) 00832 { 00833 for (x=0; x < (ssize_t) cache_info->columns; x++) 00834 { 00835 register ssize_t 00836 i; 00837 00838 /* 00839 Read a set of pixel channels. 00840 */ 00841 length=cache_info->number_channels*sizeof(Quantum); 00842 if (cache_info->type != DiskCache) 00843 p=(unsigned char *) cache_info->pixels+cache_offset; 00844 else 00845 { 00846 count=ReadPixelCacheRegion(cache_info,cache_offset,length,p); 00847 if ((MagickSizeType) count != length) 00848 { 00849 status=MagickFalse; 00850 break; 00851 } 00852 } 00853 cache_offset+=length; 00854 if ((y < (ssize_t) clone_info->rows) && 00855 (x < (ssize_t) clone_info->columns)) 00856 for (i=0; i < (ssize_t) clone_info->number_channels; i++) 00857 { 00858 PixelChannel 00859 channel; 00860 00861 PixelTrait 00862 traits; 00863 00864 ssize_t 00865 offset; 00866 00867 /* 00868 Write a set of pixel channels. 00869 */ 00870 channel=clone_info->channel_map[i].channel; 00871 traits=cache_info->channel_map[channel].traits; 00872 if (traits == UndefinedPixelTrait) 00873 { 00874 clone_offset+=sizeof(Quantum); 00875 continue; 00876 } 00877 offset=cache_info->channel_map[channel].offset; 00878 if (clone_info->type != DiskCache) 00879 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,p+ 00880 offset*sizeof(Quantum),sizeof(Quantum)); 00881 else 00882 { 00883 count=WritePixelCacheRegion(clone_info,clone_offset, 00884 sizeof(Quantum),p+offset*sizeof(Quantum)); 00885 if ((MagickSizeType) count != sizeof(Quantum)) 00886 { 00887 status=MagickFalse; 00888 break; 00889 } 00890 } 00891 clone_offset+=sizeof(Quantum); 00892 } 00893 } 00894 length=clone_info->number_channels*sizeof(Quantum); 00895 (void) ResetMagickMemory(blob,0,length*sizeof(*blob)); 00896 for ( ; x < (ssize_t) clone_info->columns; x++) 00897 { 00898 /* 00899 Set remaining columns as undefined. 00900 */ 00901 if (clone_info->type != DiskCache) 00902 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,blob, 00903 length); 00904 else 00905 { 00906 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob); 00907 if ((MagickSizeType) count != length) 00908 { 00909 status=MagickFalse; 00910 break; 00911 } 00912 } 00913 clone_offset+=length; 00914 } 00915 } 00916 length=clone_info->number_channels*sizeof(Quantum); 00917 (void) ResetMagickMemory(blob,0,length*sizeof(*blob)); 00918 for ( ; y < (ssize_t) clone_info->rows; y++) 00919 { 00920 /* 00921 Set remaining rows as undefined. 00922 */ 00923 for (x=0; x < (ssize_t) clone_info->columns; x++) 00924 { 00925 if (clone_info->type != DiskCache) 00926 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset,blob, 00927 length); 00928 else 00929 { 00930 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob); 00931 if ((MagickSizeType) count != length) 00932 { 00933 status=MagickFalse; 00934 break; 00935 } 00936 } 00937 clone_offset+=length; 00938 } 00939 } 00940 if ((cache_info->metacontent_extent != 0) || 00941 (clone_info->metacontent_extent != 0)) 00942 { 00943 /* 00944 Clone metacontent. 00945 */ 00946 for (y=0; y < (ssize_t) cache_info->rows; y++) 00947 { 00948 for (x=0; x < (ssize_t) cache_info->columns; x++) 00949 { 00950 /* 00951 Read a set of metacontent. 00952 */ 00953 length=cache_info->metacontent_extent; 00954 if (cache_info->type != DiskCache) 00955 p=(unsigned char *) cache_info->pixels+cache_offset; 00956 else 00957 { 00958 count=ReadPixelCacheRegion(cache_info,cache_offset,length,p); 00959 if ((MagickSizeType) count != length) 00960 { 00961 status=MagickFalse; 00962 break; 00963 } 00964 } 00965 cache_offset+=length; 00966 if ((y < (ssize_t) clone_info->rows) && 00967 (x < (ssize_t) clone_info->columns)) 00968 { 00969 /* 00970 Write a set of metacontent. 00971 */ 00972 length=clone_info->metacontent_extent; 00973 if (clone_info->type != DiskCache) 00974 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset, 00975 p,length); 00976 else 00977 { 00978 count=WritePixelCacheRegion(clone_info,clone_offset,length,p); 00979 if ((MagickSizeType) count != length) 00980 { 00981 status=MagickFalse; 00982 break; 00983 } 00984 } 00985 clone_offset+=length; 00986 } 00987 } 00988 length=clone_info->metacontent_extent; 00989 (void) ResetMagickMemory(blob,0,length*sizeof(*blob)); 00990 for ( ; x < (ssize_t) clone_info->columns; x++) 00991 { 00992 /* 00993 Set remaining columns as undefined. 00994 */ 00995 if (clone_info->type != DiskCache) 00996 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset, 00997 blob,length); 00998 else 00999 { 01000 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob); 01001 if ((MagickSizeType) count != length) 01002 { 01003 status=MagickFalse; 01004 break; 01005 } 01006 } 01007 clone_offset+=length; 01008 } 01009 } 01010 length=clone_info->metacontent_extent; 01011 (void) ResetMagickMemory(blob,0,length*sizeof(*blob)); 01012 for ( ; y < (ssize_t) clone_info->rows; y++) 01013 { 01014 /* 01015 Set remaining rows as undefined. 01016 */ 01017 for (x=0; x < (ssize_t) clone_info->columns; x++) 01018 { 01019 if (clone_info->type != DiskCache) 01020 (void) memcpy((unsigned char *) clone_info->pixels+clone_offset, 01021 blob,length); 01022 else 01023 { 01024 count=WritePixelCacheRegion(clone_info,clone_offset,length,blob); 01025 if ((MagickSizeType) count != length) 01026 { 01027 status=MagickFalse; 01028 break; 01029 } 01030 } 01031 clone_offset+=length; 01032 } 01033 } 01034 } 01035 if (clone_info->type == DiskCache) 01036 (void) ClosePixelCacheOnDisk(clone_info); 01037 if (cache_info->type == DiskCache) 01038 (void) ClosePixelCacheOnDisk(cache_info); 01039 blob=(unsigned char *) RelinquishMagickMemory(blob); 01040 return(status); 01041 } 01042 01043 static MagickBooleanType ClonePixelCachePixels(CacheInfo *clone_info, 01044 CacheInfo *cache_info,ExceptionInfo *exception) 01045 { 01046 PixelChannelMap 01047 *p, 01048 *q; 01049 01050 if (cache_info->type == PingCache) 01051 return(MagickTrue); 01052 p=cache_info->channel_map; 01053 q=clone_info->channel_map; 01054 if ((cache_info->columns == clone_info->columns) && 01055 (cache_info->rows == clone_info->rows) && 01056 (cache_info->number_channels == clone_info->number_channels) && 01057 (memcmp(p,q,cache_info->number_channels*sizeof(*p)) == 0) && 01058 (cache_info->metacontent_extent == clone_info->metacontent_extent)) 01059 return(PixelCacheCloneOptimized(clone_info,cache_info,exception)); 01060 return(PixelCacheCloneUnoptimized(clone_info,cache_info,exception)); 01061 } 01062 01063 /* 01064 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01065 % % 01066 % % 01067 % % 01068 + C l o n e P i x e l C a c h e M e t h o d s % 01069 % % 01070 % % 01071 % % 01072 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01073 % 01074 % ClonePixelCacheMethods() clones the pixel cache methods from one cache to 01075 % another. 01076 % 01077 % The format of the ClonePixelCacheMethods() method is: 01078 % 01079 % void ClonePixelCacheMethods(Cache clone,const Cache cache) 01080 % 01081 % A description of each parameter follows: 01082 % 01083 % o clone: Specifies a pointer to a Cache structure. 01084 % 01085 % o cache: the pixel cache. 01086 % 01087 */ 01088 MagickPrivate void ClonePixelCacheMethods(Cache clone,const Cache cache) 01089 { 01090 CacheInfo 01091 *cache_info, 01092 *source_info; 01093 01094 assert(clone != (Cache) NULL); 01095 source_info=(CacheInfo *) clone; 01096 assert(source_info->signature == MagickSignature); 01097 if (source_info->debug != MagickFalse) 01098 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 01099 source_info->filename); 01100 assert(cache != (Cache) NULL); 01101 cache_info=(CacheInfo *) cache; 01102 assert(cache_info->signature == MagickSignature); 01103 source_info->methods=cache_info->methods; 01104 } 01105 01106 /* 01107 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01108 % % 01109 % % 01110 % % 01111 + D e s t r o y I m a g e P i x e l C a c h e % 01112 % % 01113 % % 01114 % % 01115 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01116 % 01117 % DestroyImagePixelCache() deallocates memory associated with the pixel cache. 01118 % 01119 % The format of the DestroyImagePixelCache() method is: 01120 % 01121 % void DestroyImagePixelCache(Image *image) 01122 % 01123 % A description of each parameter follows: 01124 % 01125 % o image: the image. 01126 % 01127 */ 01128 static void DestroyImagePixelCache(Image *image) 01129 { 01130 assert(image != (Image *) NULL); 01131 assert(image->signature == MagickSignature); 01132 if (image->debug != MagickFalse) 01133 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 01134 if (image->cache == (void *) NULL) 01135 return; 01136 image->cache=DestroyPixelCache(image->cache); 01137 } 01138 01139 /* 01140 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01141 % % 01142 % % 01143 % % 01144 + D e s t r o y I m a g e P i x e l s % 01145 % % 01146 % % 01147 % % 01148 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01149 % 01150 % DestroyImagePixels() deallocates memory associated with the pixel cache. 01151 % 01152 % The format of the DestroyImagePixels() method is: 01153 % 01154 % void DestroyImagePixels(Image *image) 01155 % 01156 % A description of each parameter follows: 01157 % 01158 % o image: the image. 01159 % 01160 */ 01161 MagickExport void DestroyImagePixels(Image *image) 01162 { 01163 CacheInfo 01164 *cache_info; 01165 01166 assert(image != (const Image *) NULL); 01167 assert(image->signature == MagickSignature); 01168 if (image->debug != MagickFalse) 01169 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 01170 assert(image->cache != (Cache) NULL); 01171 cache_info=(CacheInfo *) image->cache; 01172 assert(cache_info->signature == MagickSignature); 01173 if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL) 01174 { 01175 cache_info->methods.destroy_pixel_handler(image); 01176 return; 01177 } 01178 image->cache=DestroyPixelCache(image->cache); 01179 } 01180 01181 /* 01182 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01183 % % 01184 % % 01185 % % 01186 + D e s t r o y P i x e l C a c h e % 01187 % % 01188 % % 01189 % % 01190 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01191 % 01192 % DestroyPixelCache() deallocates memory associated with the pixel cache. 01193 % 01194 % The format of the DestroyPixelCache() method is: 01195 % 01196 % Cache DestroyPixelCache(Cache cache) 01197 % 01198 % A description of each parameter follows: 01199 % 01200 % o cache: the pixel cache. 01201 % 01202 */ 01203 01204 static inline void RelinquishPixelCachePixels(CacheInfo *cache_info) 01205 { 01206 switch (cache_info->type) 01207 { 01208 case MemoryCache: 01209 { 01210 if (cache_info->mapped == MagickFalse) 01211 cache_info->pixels=(Quantum *) RelinquishMagickMemory( 01212 cache_info->pixels); 01213 else 01214 cache_info->pixels=(Quantum *) UnmapBlob(cache_info->pixels, 01215 (size_t) cache_info->length); 01216 RelinquishMagickResource(MemoryResource,cache_info->length); 01217 break; 01218 } 01219 case MapCache: 01220 { 01221 cache_info->pixels=(Quantum *) UnmapBlob(cache_info->pixels,(size_t) 01222 cache_info->length); 01223 RelinquishMagickResource(MapResource,cache_info->length); 01224 } 01225 case DiskCache: 01226 { 01227 if (cache_info->file != -1) 01228 (void) ClosePixelCacheOnDisk(cache_info); 01229 RelinquishMagickResource(DiskResource,cache_info->length); 01230 break; 01231 } 01232 default: 01233 break; 01234 } 01235 cache_info->type=UndefinedCache; 01236 cache_info->mapped=MagickFalse; 01237 cache_info->metacontent=(void *) NULL; 01238 } 01239 01240 MagickPrivate Cache DestroyPixelCache(Cache cache) 01241 { 01242 CacheInfo 01243 *cache_info; 01244 01245 assert(cache != (Cache) NULL); 01246 cache_info=(CacheInfo *) cache; 01247 assert(cache_info->signature == MagickSignature); 01248 if (cache_info->debug != MagickFalse) 01249 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 01250 cache_info->filename); 01251 LockSemaphoreInfo(cache_info->semaphore); 01252 cache_info->reference_count--; 01253 if (cache_info->reference_count != 0) 01254 { 01255 UnlockSemaphoreInfo(cache_info->semaphore); 01256 return((Cache) NULL); 01257 } 01258 UnlockSemaphoreInfo(cache_info->semaphore); 01259 if (cache_info->debug != MagickFalse) 01260 { 01261 char 01262 message[MaxTextExtent]; 01263 01264 (void) FormatLocaleString(message,MaxTextExtent,"destroy %s", 01265 cache_info->filename); 01266 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message); 01267 } 01268 if ((cache_info->mode == ReadMode) || ((cache_info->type != MapCache) && 01269 (cache_info->type != DiskCache))) 01270 RelinquishPixelCachePixels(cache_info); 01271 else 01272 { 01273 RelinquishPixelCachePixels(cache_info); 01274 (void) RelinquishUniqueFileResource(cache_info->cache_filename); 01275 } 01276 *cache_info->cache_filename='\0'; 01277 if (cache_info->nexus_info != (NexusInfo **) NULL) 01278 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info, 01279 cache_info->number_threads); 01280 if (cache_info->random_info != (RandomInfo *) NULL) 01281 cache_info->random_info=DestroyRandomInfo(cache_info->random_info); 01282 if (cache_info->disk_semaphore != (SemaphoreInfo *) NULL) 01283 DestroySemaphoreInfo(&cache_info->disk_semaphore); 01284 if (cache_info->semaphore != (SemaphoreInfo *) NULL) 01285 DestroySemaphoreInfo(&cache_info->semaphore); 01286 cache_info->signature=(~MagickSignature); 01287 cache_info=(CacheInfo *) RelinquishMagickMemory(cache_info); 01288 cache=(Cache) NULL; 01289 return(cache); 01290 } 01291 01292 /* 01293 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01294 % % 01295 % % 01296 % % 01297 + D e s t r o y P i x e l C a c h e N e x u s % 01298 % % 01299 % % 01300 % % 01301 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01302 % 01303 % DestroyPixelCacheNexus() destroys a pixel cache nexus. 01304 % 01305 % The format of the DestroyPixelCacheNexus() method is: 01306 % 01307 % NexusInfo **DestroyPixelCacheNexus(NexusInfo *nexus_info, 01308 % const size_t number_threads) 01309 % 01310 % A description of each parameter follows: 01311 % 01312 % o nexus_info: the nexus to destroy. 01313 % 01314 % o number_threads: the number of nexus threads. 01315 % 01316 */ 01317 01318 static inline void RelinquishCacheNexusPixels(NexusInfo *nexus_info) 01319 { 01320 if (nexus_info->mapped == MagickFalse) 01321 (void) RelinquishAlignedMemory(nexus_info->cache); 01322 else 01323 (void) UnmapBlob(nexus_info->cache,(size_t) nexus_info->length); 01324 nexus_info->cache=(Quantum *) NULL; 01325 nexus_info->pixels=(Quantum *) NULL; 01326 nexus_info->metacontent=(void *) NULL; 01327 nexus_info->length=0; 01328 nexus_info->mapped=MagickFalse; 01329 } 01330 01331 MagickPrivate NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info, 01332 const size_t number_threads) 01333 { 01334 register ssize_t 01335 i; 01336 01337 assert(nexus_info != (NexusInfo **) NULL); 01338 for (i=0; i < (ssize_t) number_threads; i++) 01339 { 01340 if (nexus_info[i]->cache != (Quantum *) NULL) 01341 RelinquishCacheNexusPixels(nexus_info[i]); 01342 nexus_info[i]->signature=(~MagickSignature); 01343 nexus_info[i]=(NexusInfo *) RelinquishMagickMemory(nexus_info[i]); 01344 } 01345 nexus_info=(NexusInfo **) RelinquishMagickMemory(nexus_info); 01346 return(nexus_info); 01347 } 01348 01349 /* 01350 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01351 % % 01352 % % 01353 % % 01354 % G e t A u t h e n t i c M e t a c o n t e n t % 01355 % % 01356 % % 01357 % % 01358 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01359 % 01360 % GetAuthenticMetacontent() returns the authentic metacontent corresponding 01361 % with the last call to QueueAuthenticPixels() or GetVirtualPixels(). NULL is 01362 % returned if the associated pixels are not available. 01363 % 01364 % The format of the GetAuthenticMetacontent() method is: 01365 % 01366 % void *GetAuthenticMetacontent(const Image *image) 01367 % 01368 % A description of each parameter follows: 01369 % 01370 % o image: the image. 01371 % 01372 */ 01373 MagickExport void *GetAuthenticMetacontent(const Image *image) 01374 { 01375 CacheInfo 01376 *cache_info; 01377 01378 const int 01379 id = GetOpenMPThreadId(); 01380 01381 void 01382 *metacontent; 01383 01384 assert(image != (const Image *) NULL); 01385 assert(image->signature == MagickSignature); 01386 assert(image->cache != (Cache) NULL); 01387 cache_info=(CacheInfo *) image->cache; 01388 assert(cache_info->signature == MagickSignature); 01389 if (cache_info->methods.get_authentic_metacontent_from_handler != 01390 (GetAuthenticMetacontentFromHandler) NULL) 01391 { 01392 metacontent=cache_info->methods. 01393 get_authentic_metacontent_from_handler(image); 01394 return(metacontent); 01395 } 01396 assert(id < (int) cache_info->number_threads); 01397 metacontent=GetPixelCacheNexusMetacontent(cache_info, 01398 cache_info->nexus_info[id]); 01399 return(metacontent); 01400 } 01401 01402 /* 01403 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01404 % % 01405 % % 01406 % % 01407 + G e t A u t h e n t i c M e t a c o n t e n t F r o m C a c h e % 01408 % % 01409 % % 01410 % % 01411 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01412 % 01413 % GetAuthenticMetacontentFromCache() returns the meta-content corresponding 01414 % with the last call to QueueAuthenticPixelsCache() or 01415 % GetAuthenticPixelsCache(). 01416 % 01417 % The format of the GetAuthenticMetacontentFromCache() method is: 01418 % 01419 % void *GetAuthenticMetacontentFromCache(const Image *image) 01420 % 01421 % A description of each parameter follows: 01422 % 01423 % o image: the image. 01424 % 01425 */ 01426 static void *GetAuthenticMetacontentFromCache(const Image *image) 01427 { 01428 CacheInfo 01429 *cache_info; 01430 01431 const int 01432 id = GetOpenMPThreadId(); 01433 01434 void 01435 *metacontent; 01436 01437 assert(image != (const Image *) NULL); 01438 assert(image->signature == MagickSignature); 01439 assert(image->cache != (Cache) NULL); 01440 cache_info=(CacheInfo *) image->cache; 01441 assert(cache_info->signature == MagickSignature); 01442 assert(id < (int) cache_info->number_threads); 01443 metacontent=GetPixelCacheNexusMetacontent(image->cache, 01444 cache_info->nexus_info[id]); 01445 return(metacontent); 01446 } 01447 01448 /* 01449 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01450 % % 01451 % % 01452 % % 01453 + G e t A u t h e n t i c P i x e l C a c h e N e x u s % 01454 % % 01455 % % 01456 % % 01457 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01458 % 01459 % GetAuthenticPixelCacheNexus() gets authentic pixels from the in-memory or 01460 % disk pixel cache as defined by the geometry parameters. A pointer to the 01461 % pixels is returned if the pixels are transferred, otherwise a NULL is 01462 % returned. 01463 % 01464 % The format of the GetAuthenticPixelCacheNexus() method is: 01465 % 01466 % Quantum *GetAuthenticPixelCacheNexus(Image *image,const ssize_t x, 01467 % const ssize_t y,const size_t columns,const size_t rows, 01468 % NexusInfo *nexus_info,ExceptionInfo *exception) 01469 % 01470 % A description of each parameter follows: 01471 % 01472 % o image: the image. 01473 % 01474 % o x,y,columns,rows: These values define the perimeter of a region of 01475 % pixels. 01476 % 01477 % o nexus_info: the cache nexus to return. 01478 % 01479 % o exception: return any errors or warnings in this structure. 01480 % 01481 */ 01482 01483 static inline MagickBooleanType IsPixelAuthentic(const CacheInfo *cache_info, 01484 NexusInfo *nexus_info) 01485 { 01486 MagickBooleanType 01487 status; 01488 01489 MagickOffsetType 01490 offset; 01491 01492 if (cache_info->type == PingCache) 01493 return(MagickTrue); 01494 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+ 01495 nexus_info->region.x; 01496 status=nexus_info->pixels == (cache_info->pixels+offset* 01497 cache_info->number_channels) ? MagickTrue : MagickFalse; 01498 return(status); 01499 } 01500 01501 MagickPrivate Quantum *GetAuthenticPixelCacheNexus(Image *image, 01502 const ssize_t x,const ssize_t y,const size_t columns,const size_t rows, 01503 NexusInfo *nexus_info,ExceptionInfo *exception) 01504 { 01505 CacheInfo 01506 *cache_info; 01507 01508 Quantum 01509 *q; 01510 01511 /* 01512 Transfer pixels from the cache. 01513 */ 01514 assert(image != (Image *) NULL); 01515 assert(image->signature == MagickSignature); 01516 q=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,nexus_info, 01517 exception); 01518 if (q == (Quantum *) NULL) 01519 return((Quantum *) NULL); 01520 cache_info=(CacheInfo *) image->cache; 01521 assert(cache_info->signature == MagickSignature); 01522 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse) 01523 return(q); 01524 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse) 01525 return((Quantum *) NULL); 01526 if (cache_info->metacontent_extent != 0) 01527 if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse) 01528 return((Quantum *) NULL); 01529 return(q); 01530 } 01531 01532 /* 01533 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01534 % % 01535 % % 01536 % % 01537 + G e t A u t h e n t i c P i x e l s F r o m C a c h e % 01538 % % 01539 % % 01540 % % 01541 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01542 % 01543 % GetAuthenticPixelsFromCache() returns the pixels associated with the last 01544 % call to the QueueAuthenticPixelsCache() or GetAuthenticPixelsCache() methods. 01545 % 01546 % The format of the GetAuthenticPixelsFromCache() method is: 01547 % 01548 % Quantum *GetAuthenticPixelsFromCache(const Image image) 01549 % 01550 % A description of each parameter follows: 01551 % 01552 % o image: the image. 01553 % 01554 */ 01555 static Quantum *GetAuthenticPixelsFromCache(const Image *image) 01556 { 01557 CacheInfo 01558 *cache_info; 01559 01560 const int 01561 id = GetOpenMPThreadId(); 01562 01563 assert(image != (const Image *) NULL); 01564 assert(image->signature == MagickSignature); 01565 assert(image->cache != (Cache) NULL); 01566 cache_info=(CacheInfo *) image->cache; 01567 assert(cache_info->signature == MagickSignature); 01568 assert(id < (int) cache_info->number_threads); 01569 return(GetPixelCacheNexusPixels(image->cache,cache_info->nexus_info[id])); 01570 } 01571 01572 /* 01573 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01574 % % 01575 % % 01576 % % 01577 % G e t A u t h e n t i c P i x e l Q u e u e % 01578 % % 01579 % % 01580 % % 01581 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01582 % 01583 % GetAuthenticPixelQueue() returns the authentic pixels associated 01584 % corresponding with the last call to QueueAuthenticPixels() or 01585 % GetAuthenticPixels(). 01586 % 01587 % The format of the GetAuthenticPixelQueue() method is: 01588 % 01589 % Quantum *GetAuthenticPixelQueue(const Image image) 01590 % 01591 % A description of each parameter follows: 01592 % 01593 % o image: the image. 01594 % 01595 */ 01596 MagickExport Quantum *GetAuthenticPixelQueue(const Image *image) 01597 { 01598 CacheInfo 01599 *cache_info; 01600 01601 const int 01602 id = GetOpenMPThreadId(); 01603 01604 assert(image != (const Image *) NULL); 01605 assert(image->signature == MagickSignature); 01606 assert(image->cache != (Cache) NULL); 01607 cache_info=(CacheInfo *) image->cache; 01608 assert(cache_info->signature == MagickSignature); 01609 if (cache_info->methods.get_authentic_pixels_from_handler != 01610 (GetAuthenticPixelsFromHandler) NULL) 01611 return(cache_info->methods.get_authentic_pixels_from_handler(image)); 01612 assert(id < (int) cache_info->number_threads); 01613 return(GetPixelCacheNexusPixels(cache_info,cache_info->nexus_info[id])); 01614 } 01615 01616 /* 01617 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01618 % % 01619 % % 01620 % % 01621 % G e t A u t h e n t i c P i x e l s % 01622 % % 01623 % % 01624 % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01625 % 01626 % GetAuthenticPixels() obtains a pixel region for read/write access. If the 01627 % region is successfully accessed, a pointer to a Quantum array 01628 % representing the region is returned, otherwise NULL is returned. 01629 % 01630 % The returned pointer may point to a temporary working copy of the pixels 01631 % or it may point to the original pixels in memory. Performance is maximized 01632 % if the selected region is part of one row, or one or more full rows, since 01633 % then there is opportunity to access the pixels in-place (without a copy) 01634 % if the image is in memory, or in a memory-mapped file. The returned pointer 01635 % must *never* be deallocated by the user. 01636 % 01637 % Pixels accessed via the returned pointer represent a simple array of type 01638 % Quantum. If the image has corresponding metacontent,call 01639 % GetAuthenticMetacontent() after invoking GetAuthenticPixels() to obtain the 01640 % meta-content corresponding to the region. Once the Quantum array has 01641 % been updated, the changes must be saved back to the underlying image using 01642 % SyncAuthenticPixels() or they may be lost. 01643 % 01644 % The format of the GetAuthenticPixels() method is: 01645 % 01646 % Quantum *GetAuthenticPixels(Image *image,const ssize_t x, 01647 % const ssize_t y,const size_t columns,const size_t rows, 01648 % ExceptionInfo *exception) 01649 % 01650 % A description of each parameter follows: 01651 % 01652 % o image: the image. 01653 % 01654 % o x,y,columns,rows: These values define the perimeter of a region of 01655 % pixels. 01656 % 01657 % o exception: return any errors or warnings in this structure. 01658 % 01659 */ 01660 MagickExport Quantum *GetAuthenticPixels(Image *image,const ssize_t x, 01661 const ssize_t y,const size_t columns,const size_t rows, 01662 ExceptionInfo *exception) 01663 { 01664 CacheInfo 01665 *cache_info; 01666 01667 const int 01668 id = GetOpenMPThreadId(); 01669 01670 Quantum 01671 *q; 01672 01673 assert(image != (Image *) NULL); 01674 assert(image->signature == MagickSignature); 01675 assert(image->cache != (Cache) NULL); 01676 cache_info=(CacheInfo *) image->cache; 01677 assert(cache_info->signature == MagickSignature); 01678 if (cache_info->methods.get_authentic_pixels_handler != 01679 (GetAuthenticPixelsHandler) NULL) 01680 { 01681 q=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,rows, 01682 exception); 01683 return(q); 01684 } 01685 assert(id < (int) cache_info->number_threads); 01686 q=GetAuthenticPixelCacheNexus(image,x,y,columns,rows, 01687 cache_info->nexus_info[id],exception); 01688 return(q); 01689 } 01690 01691 /* 01692 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01693 % % 01694 % % 01695 % % 01696 + G e t A u t h e n t i c P i x e l s C a c h e % 01697 % % 01698 % % 01699 % % 01700 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01701 % 01702 % GetAuthenticPixelsCache() gets pixels from the in-memory or disk pixel cache 01703 % as defined by the geometry parameters. A pointer to the pixels is returned 01704 % if the pixels are transferred, otherwise a NULL is returned. 01705 % 01706 % The format of the GetAuthenticPixelsCache() method is: 01707 % 01708 % Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x, 01709 % const ssize_t y,const size_t columns,const size_t rows, 01710 % ExceptionInfo *exception) 01711 % 01712 % A description of each parameter follows: 01713 % 01714 % o image: the image. 01715 % 01716 % o x,y,columns,rows: These values define the perimeter of a region of 01717 % pixels. 01718 % 01719 % o exception: return any errors or warnings in this structure. 01720 % 01721 */ 01722 static Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x, 01723 const ssize_t y,const size_t columns,const size_t rows, 01724 ExceptionInfo *exception) 01725 { 01726 CacheInfo 01727 *cache_info; 01728 01729 const int 01730 id = GetOpenMPThreadId(); 01731 01732 Quantum 01733 *q; 01734 01735 assert(image != (const Image *) NULL); 01736 assert(image->signature == MagickSignature); 01737 assert(image->cache != (Cache) NULL); 01738 cache_info=(CacheInfo *) image->cache; 01739 if (cache_info == (Cache) NULL) 01740 return((Quantum *) NULL); 01741 assert(cache_info->signature == MagickSignature); 01742 assert(id < (int) cache_info->number_threads); 01743 q=GetAuthenticPixelCacheNexus(image,x,y,columns,rows, 01744 cache_info->nexus_info[id],exception); 01745 return(q); 01746 } 01747 01748 /* 01749 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01750 % % 01751 % % 01752 % % 01753 + G e t I m a g e E x t e n t % 01754 % % 01755 % % 01756 % % 01757 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01758 % 01759 % GetImageExtent() returns the extent of the pixels associated corresponding 01760 % with the last call to QueueAuthenticPixels() or GetAuthenticPixels(). 01761 % 01762 % The format of the GetImageExtent() method is: 01763 % 01764 % MagickSizeType GetImageExtent(const Image *image) 01765 % 01766 % A description of each parameter follows: 01767 % 01768 % o image: the image. 01769 % 01770 */ 01771 MagickExport MagickSizeType GetImageExtent(const Image *image) 01772 { 01773 CacheInfo 01774 *cache_info; 01775 01776 const int 01777 id = GetOpenMPThreadId(); 01778 01779 assert(image != (Image *) NULL); 01780 assert(image->signature == MagickSignature); 01781 if (image->debug != MagickFalse) 01782 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 01783 assert(image->cache != (Cache) NULL); 01784 cache_info=(CacheInfo *) image->cache; 01785 assert(cache_info->signature == MagickSignature); 01786 assert(id < (int) cache_info->number_threads); 01787 return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[id])); 01788 } 01789 01790 /* 01791 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01792 % % 01793 % % 01794 % % 01795 + G e t I m a g e P i x e l C a c h e % 01796 % % 01797 % % 01798 % % 01799 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01800 % 01801 % GetImagePixelCache() ensures that there is only a single reference to the 01802 % pixel cache to be modified, updating the provided cache pointer to point to 01803 % a clone of the original pixel cache if necessary. 01804 % 01805 % The format of the GetImagePixelCache method is: 01806 % 01807 % Cache GetImagePixelCache(Image *image,const MagickBooleanType clone, 01808 % ExceptionInfo *exception) 01809 % 01810 % A description of each parameter follows: 01811 % 01812 % o image: the image. 01813 % 01814 % o clone: any value other than MagickFalse clones the cache pixels. 01815 % 01816 % o exception: return any errors or warnings in this structure. 01817 % 01818 */ 01819 01820 static inline MagickBooleanType ValidatePixelCacheMorphology(const Image *image) 01821 { 01822 CacheInfo 01823 *cache_info; 01824 01825 PixelChannelMap 01826 *p, 01827 *q; 01828 01829 /* 01830 Does the image match the pixel cache morphology? 01831 */ 01832 cache_info=(CacheInfo *) image->cache; 01833 p=image->channel_map; 01834 q=cache_info->channel_map; 01835 if ((image->storage_class != cache_info->storage_class) || 01836 (image->colorspace != cache_info->colorspace) || 01837 (image->matte != cache_info->matte) || 01838 (image->mask != cache_info->mask) || 01839 (image->columns != cache_info->columns) || 01840 (image->rows != cache_info->rows) || 01841 (image->number_channels != cache_info->number_channels) || 01842 (memcmp(p,q,image->number_channels*sizeof(*p)) != 0) || 01843 (image->metacontent_extent != cache_info->metacontent_extent) || 01844 (cache_info->nexus_info == (NexusInfo **) NULL) || 01845 (cache_info->number_threads < GetOpenMPMaximumThreads())) 01846 return(MagickFalse); 01847 return(MagickTrue); 01848 } 01849 01850 static Cache GetImagePixelCache(Image *image,const MagickBooleanType clone, 01851 ExceptionInfo *exception) 01852 { 01853 CacheInfo 01854 *cache_info; 01855 01856 MagickBooleanType 01857 destroy, 01858 status; 01859 01860 static MagickSizeType 01861 cpu_throttle = 0, 01862 cycles = 0, 01863 time_limit = 0; 01864 01865 static time_t 01866 cache_timestamp = 0; 01867 01868 status=MagickTrue; 01869 LockSemaphoreInfo(image->semaphore); 01870 if (cpu_throttle == 0) 01871 { 01872 char 01873 *limit; 01874 01875 /* 01876 Set CPU throttle in milleseconds. 01877 */ 01878 cpu_throttle=MagickResourceInfinity; 01879 limit=GetEnvironmentValue("MAGICK_THROTTLE"); 01880 if (limit == (char *) NULL) 01881 limit=GetPolicyValue("throttle"); 01882 if (limit != (char *) NULL) 01883 { 01884 cpu_throttle=(MagickSizeType) StringToInteger(limit); 01885 limit=DestroyString(limit); 01886 } 01887 } 01888 if ((cpu_throttle != MagickResourceInfinity) && ((cycles++ % 32) == 0)) 01889 MagickDelay(cpu_throttle); 01890 if (time_limit == 0) 01891 { 01892 /* 01893 Set the exire time in seconds. 01894 */ 01895 time_limit=GetMagickResourceLimit(TimeResource); 01896 cache_timestamp=time((time_t *) NULL); 01897 } 01898 if ((time_limit != MagickResourceInfinity) && 01899 ((MagickSizeType) (time((time_t *) NULL)-cache_timestamp) >= time_limit)) 01900 ThrowFatalException(ResourceLimitFatalError,"TimeLimitExceeded"); 01901 assert(image->cache != (Cache) NULL); 01902 cache_info=(CacheInfo *) image->cache; 01903 destroy=MagickFalse; 01904 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode)) 01905 { 01906 LockSemaphoreInfo(cache_info->semaphore); 01907 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode)) 01908 { 01909 Image 01910 clone_image; 01911 01912 CacheInfo 01913 *clone_info; 01914 01915 /* 01916 Clone pixel cache. 01917 */ 01918 clone_image=(*image); 01919 clone_image.semaphore=AllocateSemaphoreInfo(); 01920 clone_image.reference_count=1; 01921 clone_image.cache=ClonePixelCache(cache_info); 01922 clone_info=(CacheInfo *) clone_image.cache; 01923 status=OpenPixelCache(&clone_image,IOMode,exception); 01924 if (status != MagickFalse) 01925 { 01926 if (clone != MagickFalse) 01927 status=ClonePixelCachePixels(clone_info,cache_info,exception); 01928 if (status != MagickFalse) 01929 { 01930 if (cache_info->mode == ReadMode) 01931 cache_info->nexus_info=(NexusInfo **) NULL; 01932 destroy=MagickTrue; 01933 image->cache=clone_image.cache; 01934 } 01935 } 01936 DestroySemaphoreInfo(&clone_image.semaphore); 01937 } 01938 UnlockSemaphoreInfo(cache_info->semaphore); 01939 } 01940 if (destroy != MagickFalse) 01941 cache_info=(CacheInfo *) DestroyPixelCache(cache_info); 01942 if (status != MagickFalse) 01943 { 01944 /* 01945 Ensure the image matches the pixel cache morphology. 01946 */ 01947 image->taint=MagickTrue; 01948 image->type=UndefinedType; 01949 if (ValidatePixelCacheMorphology(image) == MagickFalse) 01950 { 01951 status=OpenPixelCache(image,IOMode,exception); 01952 cache_info=(CacheInfo *) image->cache; 01953 if (cache_info->type == DiskCache) 01954 (void) ClosePixelCacheOnDisk(cache_info); 01955 } 01956 } 01957 UnlockSemaphoreInfo(image->semaphore); 01958 if (status == MagickFalse) 01959 return((Cache) NULL); 01960 return(image->cache); 01961 } 01962 01963 /* 01964 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01965 % % 01966 % % 01967 % % 01968 % G e t O n e A u t h e n t i c P i x e l % 01969 % % 01970 % % 01971 % % 01972 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01973 % 01974 % GetOneAuthenticPixel() returns a single pixel at the specified (x,y) 01975 % location. The image background color is returned if an error occurs. 01976 % 01977 % The format of the GetOneAuthenticPixel() method is: 01978 % 01979 % MagickBooleanType GetOneAuthenticPixel(const Image image,const ssize_t x, 01980 % const ssize_t y,Quantum *pixel,ExceptionInfo *exception) 01981 % 01982 % A description of each parameter follows: 01983 % 01984 % o image: the image. 01985 % 01986 % o x,y: These values define the location of the pixel to return. 01987 % 01988 % o pixel: return a pixel at the specified (x,y) location. 01989 % 01990 % o exception: return any errors or warnings in this structure. 01991 % 01992 */ 01993 MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image, 01994 const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception) 01995 { 01996 CacheInfo 01997 *cache_info; 01998 01999 register Quantum 02000 *q; 02001 02002 register ssize_t 02003 i; 02004 02005 assert(image != (Image *) NULL); 02006 assert(image->signature == MagickSignature); 02007 assert(image->cache != (Cache) NULL); 02008 cache_info=(CacheInfo *) image->cache; 02009 assert(cache_info->signature == MagickSignature); 02010 (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel)); 02011 if (cache_info->methods.get_one_authentic_pixel_from_handler != 02012 (GetOneAuthenticPixelFromHandler) NULL) 02013 return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y, 02014 pixel,exception)); 02015 q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception); 02016 if (q == (Quantum *) NULL) 02017 { 02018 pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red); 02019 pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green); 02020 pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue); 02021 pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black); 02022 pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha); 02023 return(MagickFalse); 02024 } 02025 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 02026 { 02027 PixelChannel 02028 channel; 02029 02030 channel=GetPixelChannelMapChannel(image,i); 02031 pixel[channel]=q[i]; 02032 } 02033 return(MagickTrue); 02034 } 02035 02036 /* 02037 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02038 % % 02039 % % 02040 % % 02041 + G e t O n e A u t h e n t i c P i x e l F r o m C a c h e % 02042 % % 02043 % % 02044 % % 02045 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02046 % 02047 % GetOneAuthenticPixelFromCache() returns a single pixel at the specified (x,y) 02048 % location. The image background color is returned if an error occurs. 02049 % 02050 % The format of the GetOneAuthenticPixelFromCache() method is: 02051 % 02052 % MagickBooleanType GetOneAuthenticPixelFromCache(const Image image, 02053 % const ssize_t x,const ssize_t y,Quantum *pixel, 02054 % ExceptionInfo *exception) 02055 % 02056 % A description of each parameter follows: 02057 % 02058 % o image: the image. 02059 % 02060 % o x,y: These values define the location of the pixel to return. 02061 % 02062 % o pixel: return a pixel at the specified (x,y) location. 02063 % 02064 % o exception: return any errors or warnings in this structure. 02065 % 02066 */ 02067 static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image, 02068 const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception) 02069 { 02070 CacheInfo 02071 *cache_info; 02072 02073 const int 02074 id = GetOpenMPThreadId(); 02075 02076 register Quantum 02077 *q; 02078 02079 register ssize_t 02080 i; 02081 02082 assert(image != (const Image *) NULL); 02083 assert(image->signature == MagickSignature); 02084 assert(image->cache != (Cache) NULL); 02085 cache_info=(CacheInfo *) image->cache; 02086 assert(cache_info->signature == MagickSignature); 02087 assert(id < (int) cache_info->number_threads); 02088 (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel)); 02089 q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[id], 02090 exception); 02091 if (q == (Quantum *) NULL) 02092 { 02093 pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red); 02094 pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green); 02095 pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue); 02096 pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black); 02097 pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha); 02098 return(MagickFalse); 02099 } 02100 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 02101 { 02102 PixelChannel 02103 channel; 02104 02105 channel=GetPixelChannelMapChannel(image,i); 02106 pixel[channel]=q[i]; 02107 } 02108 return(MagickTrue); 02109 } 02110 02111 /* 02112 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02113 % % 02114 % % 02115 % % 02116 % G e t O n e V i r t u a l P i x e l % 02117 % % 02118 % % 02119 % % 02120 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02121 % 02122 % GetOneVirtualPixel() returns a single virtual pixel at the specified 02123 % (x,y) location. The image background color is returned if an error occurs. 02124 % If you plan to modify the pixel, use GetOneAuthenticPixel() instead. 02125 % 02126 % The format of the GetOneVirtualPixel() method is: 02127 % 02128 % MagickBooleanType GetOneVirtualPixel(const Image image,const ssize_t x, 02129 % const ssize_t y,Quantum *pixel,ExceptionInfo exception) 02130 % 02131 % A description of each parameter follows: 02132 % 02133 % o image: the image. 02134 % 02135 % o x,y: These values define the location of the pixel to return. 02136 % 02137 % o pixel: return a pixel at the specified (x,y) location. 02138 % 02139 % o exception: return any errors or warnings in this structure. 02140 % 02141 */ 02142 MagickExport MagickBooleanType GetOneVirtualPixel(const Image *image, 02143 const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception) 02144 { 02145 CacheInfo 02146 *cache_info; 02147 02148 const int 02149 id = GetOpenMPThreadId(); 02150 02151 const Quantum 02152 *p; 02153 02154 register ssize_t 02155 i; 02156 02157 assert(image != (const Image *) NULL); 02158 assert(image->signature == MagickSignature); 02159 assert(image->cache != (Cache) NULL); 02160 cache_info=(CacheInfo *) image->cache; 02161 assert(cache_info->signature == MagickSignature); 02162 (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel)); 02163 if (cache_info->methods.get_one_virtual_pixel_from_handler != 02164 (GetOneVirtualPixelFromHandler) NULL) 02165 return(cache_info->methods.get_one_virtual_pixel_from_handler(image, 02166 GetPixelCacheVirtualMethod(image),x,y,pixel,exception)); 02167 assert(id < (int) cache_info->number_threads); 02168 p=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y, 02169 1UL,1UL,cache_info->nexus_info[id],exception); 02170 if (p == (const Quantum *) NULL) 02171 { 02172 pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red); 02173 pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green); 02174 pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue); 02175 pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black); 02176 pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha); 02177 return(MagickFalse); 02178 } 02179 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 02180 { 02181 PixelChannel 02182 channel; 02183 02184 channel=GetPixelChannelMapChannel(image,i); 02185 pixel[channel]=p[i]; 02186 } 02187 return(MagickTrue); 02188 } 02189 02190 /* 02191 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02192 % % 02193 % % 02194 % % 02195 + G e t O n e V i r t u a l P i x e l F r o m C a c h e % 02196 % % 02197 % % 02198 % % 02199 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02200 % 02201 % GetOneVirtualPixelFromCache() returns a single virtual pixel at the 02202 % specified (x,y) location. The image background color is returned if an 02203 % error occurs. 02204 % 02205 % The format of the GetOneVirtualPixelFromCache() method is: 02206 % 02207 % MagickBooleanType GetOneVirtualPixelFromCache(const Image image, 02208 % const VirtualPixelMethod method,const ssize_t x,const ssize_t y, 02209 % Quantum *pixel,ExceptionInfo *exception) 02210 % 02211 % A description of each parameter follows: 02212 % 02213 % o image: the image. 02214 % 02215 % o virtual_pixel_method: the virtual pixel method. 02216 % 02217 % o x,y: These values define the location of the pixel to return. 02218 % 02219 % o pixel: return a pixel at the specified (x,y) location. 02220 % 02221 % o exception: return any errors or warnings in this structure. 02222 % 02223 */ 02224 static MagickBooleanType GetOneVirtualPixelFromCache(const Image *image, 02225 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y, 02226 Quantum *pixel,ExceptionInfo *exception) 02227 { 02228 CacheInfo 02229 *cache_info; 02230 02231 const int 02232 id = GetOpenMPThreadId(); 02233 02234 const Quantum 02235 *p; 02236 02237 register ssize_t 02238 i; 02239 02240 assert(image != (const Image *) NULL); 02241 assert(image->signature == MagickSignature); 02242 assert(image->cache != (Cache) NULL); 02243 cache_info=(CacheInfo *) image->cache; 02244 assert(cache_info->signature == MagickSignature); 02245 assert(id < (int) cache_info->number_threads); 02246 (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel)); 02247 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL, 02248 cache_info->nexus_info[id],exception); 02249 if (p == (const Quantum *) NULL) 02250 { 02251 pixel[RedPixelChannel]=ClampToQuantum(image->background_color.red); 02252 pixel[GreenPixelChannel]=ClampToQuantum(image->background_color.green); 02253 pixel[BluePixelChannel]=ClampToQuantum(image->background_color.blue); 02254 pixel[BlackPixelChannel]=ClampToQuantum(image->background_color.black); 02255 pixel[AlphaPixelChannel]=ClampToQuantum(image->background_color.alpha); 02256 return(MagickFalse); 02257 } 02258 for (i=0; i < (ssize_t) GetPixelChannels(image); i++) 02259 { 02260 PixelChannel 02261 channel; 02262 02263 channel=GetPixelChannelMapChannel(image,i); 02264 pixel[channel]=p[i]; 02265 } 02266 return(MagickTrue); 02267 } 02268 02269 /* 02270 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02271 % % 02272 % % 02273 % % 02274 % G e t O n e V i r t u a l P i x e l I n f o % 02275 % % 02276 % % 02277 % % 02278 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02279 % 02280 % GetOneVirtualPixelInfo() returns a single pixel at the specified (x,y) 02281 % location. The image background color is returned if an error occurs. If 02282 % you plan to modify the pixel, use GetOneAuthenticPixel() instead. 02283 % 02284 % The format of the GetOneVirtualPixelInfo() method is: 02285 % 02286 % MagickBooleanType GetOneVirtualPixelInfo(const Image image, 02287 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x, 02288 % const ssize_t y,PixelInfo *pixel,ExceptionInfo exception) 02289 % 02290 % A description of each parameter follows: 02291 % 02292 % o image: the image. 02293 % 02294 % o virtual_pixel_method: the virtual pixel method. 02295 % 02296 % o x,y: these values define the location of the pixel to return. 02297 % 02298 % o pixel: return a pixel at the specified (x,y) location. 02299 % 02300 % o exception: return any errors or warnings in this structure. 02301 % 02302 */ 02303 MagickExport MagickBooleanType GetOneVirtualPixelInfo(const Image *image, 02304 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y, 02305 PixelInfo *pixel,ExceptionInfo *exception) 02306 { 02307 CacheInfo 02308 *cache_info; 02309 02310 const int 02311 id = GetOpenMPThreadId(); 02312 02313 register const Quantum 02314 *p; 02315 02316 assert(image != (const Image *) NULL); 02317 assert(image->signature == MagickSignature); 02318 assert(image->cache != (Cache) NULL); 02319 cache_info=(CacheInfo *) image->cache; 02320 assert(cache_info->signature == MagickSignature); 02321 assert(id < (int) cache_info->number_threads); 02322 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,1UL,1UL, 02323 cache_info->nexus_info[id],exception); 02324 GetPixelInfo(image,pixel); 02325 if (p == (const Quantum *) NULL) 02326 return(MagickFalse); 02327 GetPixelInfoPixel(image,p,pixel); 02328 return(MagickTrue); 02329 } 02330 02331 /* 02332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02333 % % 02334 % % 02335 % % 02336 + G e t P i x e l C a c h e C o l o r s p a c e % 02337 % % 02338 % % 02339 % % 02340 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02341 % 02342 % GetPixelCacheColorspace() returns the class type of the pixel cache. 02343 % 02344 % The format of the GetPixelCacheColorspace() method is: 02345 % 02346 % Colorspace GetPixelCacheColorspace(Cache cache) 02347 % 02348 % A description of each parameter follows: 02349 % 02350 % o cache: the pixel cache. 02351 % 02352 */ 02353 MagickPrivate ColorspaceType GetPixelCacheColorspace(const Cache cache) 02354 { 02355 CacheInfo 02356 *cache_info; 02357 02358 assert(cache != (Cache) NULL); 02359 cache_info=(CacheInfo *) cache; 02360 assert(cache_info->signature == MagickSignature); 02361 if (cache_info->debug != MagickFalse) 02362 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 02363 cache_info->filename); 02364 return(cache_info->colorspace); 02365 } 02366 02367 /* 02368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02369 % % 02370 % % 02371 % % 02372 + G e t P i x e l C a c h e M e t h o d s % 02373 % % 02374 % % 02375 % % 02376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02377 % 02378 % GetPixelCacheMethods() initializes the CacheMethods structure. 02379 % 02380 % The format of the GetPixelCacheMethods() method is: 02381 % 02382 % void GetPixelCacheMethods(CacheMethods *cache_methods) 02383 % 02384 % A description of each parameter follows: 02385 % 02386 % o cache_methods: Specifies a pointer to a CacheMethods structure. 02387 % 02388 */ 02389 MagickPrivate void GetPixelCacheMethods(CacheMethods *cache_methods) 02390 { 02391 assert(cache_methods != (CacheMethods *) NULL); 02392 (void) ResetMagickMemory(cache_methods,0,sizeof(*cache_methods)); 02393 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache; 02394 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache; 02395 cache_methods->get_virtual_metacontent_from_handler= 02396 GetVirtualMetacontentFromCache; 02397 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache; 02398 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache; 02399 cache_methods->get_authentic_metacontent_from_handler= 02400 GetAuthenticMetacontentFromCache; 02401 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache; 02402 cache_methods->get_one_authentic_pixel_from_handler= 02403 GetOneAuthenticPixelFromCache; 02404 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache; 02405 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache; 02406 cache_methods->destroy_pixel_handler=DestroyImagePixelCache; 02407 } 02408 02409 /* 02410 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02411 % % 02412 % % 02413 % % 02414 + G e t P i x e l C a c h e N e x u s E x t e n t % 02415 % % 02416 % % 02417 % % 02418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02419 % 02420 % GetPixelCacheNexusExtent() returns the extent of the pixels associated 02421 % corresponding with the last call to SetPixelCacheNexusPixels() or 02422 % GetPixelCacheNexusPixels(). 02423 % 02424 % The format of the GetPixelCacheNexusExtent() method is: 02425 % 02426 % MagickSizeType GetPixelCacheNexusExtent(const Cache cache, 02427 % NexusInfo *nexus_info) 02428 % 02429 % A description of each parameter follows: 02430 % 02431 % o nexus_info: the nexus info. 02432 % 02433 */ 02434 MagickPrivate MagickSizeType GetPixelCacheNexusExtent(const Cache cache, 02435 NexusInfo *nexus_info) 02436 { 02437 CacheInfo 02438 *cache_info; 02439 02440 MagickSizeType 02441 extent; 02442 02443 assert(cache != NULL); 02444 cache_info=(CacheInfo *) cache; 02445 assert(cache_info->signature == MagickSignature); 02446 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height; 02447 if (extent == 0) 02448 return((MagickSizeType) cache_info->columns*cache_info->rows); 02449 return(extent); 02450 } 02451 02452 /* 02453 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02454 % % 02455 % % 02456 % % 02457 + G e t P i x e l C a c h e N e x u s M e t a c o n t e n t % 02458 % % 02459 % % 02460 % % 02461 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02462 % 02463 % GetPixelCacheNexusMetacontent() returns the meta-content for the specified 02464 % cache nexus. 02465 % 02466 % The format of the GetPixelCacheNexusMetacontent() method is: 02467 % 02468 % void *GetPixelCacheNexusMetacontent(const Cache cache, 02469 % NexusInfo *nexus_info) 02470 % 02471 % A description of each parameter follows: 02472 % 02473 % o cache: the pixel cache. 02474 % 02475 % o nexus_info: the cache nexus to return the meta-content. 02476 % 02477 */ 02478 MagickPrivate void *GetPixelCacheNexusMetacontent(const Cache cache, 02479 NexusInfo *nexus_info) 02480 { 02481 CacheInfo 02482 *cache_info; 02483 02484 assert(cache != NULL); 02485 cache_info=(CacheInfo *) cache; 02486 assert(cache_info->signature == MagickSignature); 02487 if (cache_info->storage_class == UndefinedClass) 02488 return((void *) NULL); 02489 return(nexus_info->metacontent); 02490 } 02491 02492 /* 02493 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02494 % % 02495 % % 02496 % % 02497 + G e t P i x e l C a c h e N e x u s P i x e l s % 02498 % % 02499 % % 02500 % % 02501 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02502 % 02503 % GetPixelCacheNexusPixels() returns the pixels associated with the specified 02504 % cache nexus. 02505 % 02506 % The format of the GetPixelCacheNexusPixels() method is: 02507 % 02508 % Quantum *GetPixelCacheNexusPixels(const Cache cache, 02509 % NexusInfo *nexus_info) 02510 % 02511 % A description of each parameter follows: 02512 % 02513 % o cache: the pixel cache. 02514 % 02515 % o nexus_info: the cache nexus to return the pixels. 02516 % 02517 */ 02518 MagickPrivate Quantum *GetPixelCacheNexusPixels(const Cache cache, 02519 NexusInfo *nexus_info) 02520 { 02521 CacheInfo 02522 *cache_info; 02523 02524 assert(cache != NULL); 02525 cache_info=(CacheInfo *) cache; 02526 assert(cache_info->signature == MagickSignature); 02527 if (cache_info->storage_class == UndefinedClass) 02528 return((Quantum *) NULL); 02529 return(nexus_info->pixels); 02530 } 02531 02532 /* 02533 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02534 % % 02535 % % 02536 % % 02537 + G e t P i x e l C a c h e P i x e l s % 02538 % % 02539 % % 02540 % % 02541 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02542 % 02543 % GetPixelCachePixels() returns the pixels associated with the specified image. 02544 % 02545 % The format of the GetPixelCachePixels() method is: 02546 % 02547 % void *GetPixelCachePixels(Image *image,MagickSizeType *length, 02548 % ExceptionInfo *exception) 02549 % 02550 % A description of each parameter follows: 02551 % 02552 % o image: the image. 02553 % 02554 % o length: the pixel cache length. 02555 % 02556 % o exception: return any errors or warnings in this structure. 02557 % 02558 */ 02559 MagickPrivate void *GetPixelCachePixels(Image *image,MagickSizeType *length, 02560 ExceptionInfo *exception) 02561 { 02562 CacheInfo 02563 *cache_info; 02564 02565 assert(image != (const Image *) NULL); 02566 assert(image->signature == MagickSignature); 02567 assert(image->cache != (Cache) NULL); 02568 assert(length != (MagickSizeType *) NULL); 02569 assert(exception != (ExceptionInfo *) NULL); 02570 assert(exception->signature == MagickSignature); 02571 cache_info=(CacheInfo *) image->cache; 02572 assert(cache_info->signature == MagickSignature); 02573 *length=0; 02574 if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache)) 02575 return((void *) NULL); 02576 *length=cache_info->length; 02577 return((void *) cache_info->pixels); 02578 } 02579 02580 /* 02581 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02582 % % 02583 % % 02584 % % 02585 + G e t P i x e l C a c h e S t o r a g e C l a s s % 02586 % % 02587 % % 02588 % % 02589 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02590 % 02591 % GetPixelCacheStorageClass() returns the class type of the pixel cache. 02592 % 02593 % The format of the GetPixelCacheStorageClass() method is: 02594 % 02595 % ClassType GetPixelCacheStorageClass(Cache cache) 02596 % 02597 % A description of each parameter follows: 02598 % 02599 % o type: GetPixelCacheStorageClass returns DirectClass or PseudoClass. 02600 % 02601 % o cache: the pixel cache. 02602 % 02603 */ 02604 MagickPrivate ClassType GetPixelCacheStorageClass(const Cache cache) 02605 { 02606 CacheInfo 02607 *cache_info; 02608 02609 assert(cache != (Cache) NULL); 02610 cache_info=(CacheInfo *) cache; 02611 assert(cache_info->signature == MagickSignature); 02612 if (cache_info->debug != MagickFalse) 02613 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 02614 cache_info->filename); 02615 return(cache_info->storage_class); 02616 } 02617 02618 /* 02619 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02620 % % 02621 % % 02622 % % 02623 + G e t P i x e l C a c h e T i l e S i z e % 02624 % % 02625 % % 02626 % % 02627 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02628 % 02629 % GetPixelCacheTileSize() returns the pixel cache tile size. 02630 % 02631 % The format of the GetPixelCacheTileSize() method is: 02632 % 02633 % void GetPixelCacheTileSize(const Image *image,size_t *width, 02634 % size_t *height) 02635 % 02636 % A description of each parameter follows: 02637 % 02638 % o image: the image. 02639 % 02640 % o width: the optimize cache tile width in pixels. 02641 % 02642 % o height: the optimize cache tile height in pixels. 02643 % 02644 */ 02645 MagickPrivate void GetPixelCacheTileSize(const Image *image,size_t *width, 02646 size_t *height) 02647 { 02648 CacheInfo 02649 *cache_info; 02650 02651 assert(image != (Image *) NULL); 02652 assert(image->signature == MagickSignature); 02653 if (image->debug != MagickFalse) 02654 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 02655 cache_info=(CacheInfo *) image->cache; 02656 assert(cache_info->signature == MagickSignature); 02657 *width=2048UL/(cache_info->number_channels*sizeof(Quantum)); 02658 if (GetPixelCacheType(image) == DiskCache) 02659 *width=8192UL/(cache_info->number_channels*sizeof(Quantum)); 02660 *height=(*width); 02661 } 02662 02663 /* 02664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02665 % % 02666 % % 02667 % % 02668 + G e t P i x e l C a c h e T y p e % 02669 % % 02670 % % 02671 % % 02672 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02673 % 02674 % GetPixelCacheType() returns the pixel cache type (e.g. memory, disk, etc.). 02675 % 02676 % The format of the GetPixelCacheType() method is: 02677 % 02678 % CacheType GetPixelCacheType(const Image *image) 02679 % 02680 % A description of each parameter follows: 02681 % 02682 % o image: the image. 02683 % 02684 */ 02685 MagickPrivate CacheType GetPixelCacheType(const Image *image) 02686 { 02687 CacheInfo 02688 *cache_info; 02689 02690 assert(image != (Image *) NULL); 02691 assert(image->signature == MagickSignature); 02692 assert(image->cache != (Cache) NULL); 02693 cache_info=(CacheInfo *) image->cache; 02694 assert(cache_info->signature == MagickSignature); 02695 return(cache_info->type); 02696 } 02697 02698 /* 02699 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02700 % % 02701 % % 02702 % % 02703 + G e t P i x e l C a c h e V i r t u a l M e t h o d % 02704 % % 02705 % % 02706 % % 02707 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02708 % 02709 % GetPixelCacheVirtualMethod() gets the "virtual pixels" method for the 02710 % pixel cache. A virtual pixel is any pixel access that is outside the 02711 % boundaries of the image cache. 02712 % 02713 % The format of the GetPixelCacheVirtualMethod() method is: 02714 % 02715 % VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image) 02716 % 02717 % A description of each parameter follows: 02718 % 02719 % o image: the image. 02720 % 02721 */ 02722 MagickPrivate VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image) 02723 { 02724 CacheInfo 02725 *cache_info; 02726 02727 assert(image != (Image *) NULL); 02728 assert(image->signature == MagickSignature); 02729 assert(image->cache != (Cache) NULL); 02730 cache_info=(CacheInfo *) image->cache; 02731 assert(cache_info->signature == MagickSignature); 02732 return(cache_info->virtual_pixel_method); 02733 } 02734 02735 /* 02736 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02737 % % 02738 % % 02739 % % 02740 + G e t V i r t u a l M e t a c o n t e n t F r o m C a c h e % 02741 % % 02742 % % 02743 % % 02744 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02745 % 02746 % GetVirtualMetacontentFromCache() returns the meta-content corresponding with 02747 % the last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache(). 02748 % 02749 % The format of the GetVirtualMetacontentFromCache() method is: 02750 % 02751 % void *GetVirtualMetacontentFromCache(const Image *image) 02752 % 02753 % A description of each parameter follows: 02754 % 02755 % o image: the image. 02756 % 02757 */ 02758 static const void *GetVirtualMetacontentFromCache(const Image *image) 02759 { 02760 CacheInfo 02761 *cache_info; 02762 02763 const int 02764 id = GetOpenMPThreadId(); 02765 02766 const void 02767 *metacontent; 02768 02769 assert(image != (const Image *) NULL); 02770 assert(image->signature == MagickSignature); 02771 assert(image->cache != (Cache) NULL); 02772 cache_info=(CacheInfo *) image->cache; 02773 assert(cache_info->signature == MagickSignature); 02774 assert(id < (int) cache_info->number_threads); 02775 metacontent=GetVirtualMetacontentFromNexus(cache_info, 02776 cache_info->nexus_info[id]); 02777 return(metacontent); 02778 } 02779 02780 /* 02781 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02782 % % 02783 % % 02784 % % 02785 + G e t V i r t u a l M e t a c o n t e n t F r o m N e x u s % 02786 % % 02787 % % 02788 % % 02789 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02790 % 02791 % GetVirtualMetacontentFromNexus() returns the meta-content for the specified 02792 % cache nexus. 02793 % 02794 % The format of the GetVirtualMetacontentFromNexus() method is: 02795 % 02796 % const void *GetVirtualMetacontentFromNexus(const Cache cache, 02797 % NexusInfo *nexus_info) 02798 % 02799 % A description of each parameter follows: 02800 % 02801 % o cache: the pixel cache. 02802 % 02803 % o nexus_info: the cache nexus to return the meta-content. 02804 % 02805 */ 02806 MagickPrivate const void *GetVirtualMetacontentFromNexus(const Cache cache, 02807 NexusInfo *nexus_info) 02808 { 02809 CacheInfo 02810 *cache_info; 02811 02812 assert(cache != (Cache) NULL); 02813 cache_info=(CacheInfo *) cache; 02814 assert(cache_info->signature == MagickSignature); 02815 if (cache_info->storage_class == UndefinedClass) 02816 return((void *) NULL); 02817 return(nexus_info->metacontent); 02818 } 02819 02820 /* 02821 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02822 % % 02823 % % 02824 % % 02825 % G e t V i r t u a l M e t a c o n t e n t % 02826 % % 02827 % % 02828 % % 02829 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02830 % 02831 % GetVirtualMetacontent() returns the virtual metacontent corresponding with 02832 % the last call to QueueAuthenticPixels() or GetVirtualPixels(). NULL is 02833 % returned if the meta-content are not available. 02834 % 02835 % The format of the GetVirtualMetacontent() method is: 02836 % 02837 % const void *GetVirtualMetacontent(const Image *image) 02838 % 02839 % A description of each parameter follows: 02840 % 02841 % o image: the image. 02842 % 02843 */ 02844 MagickExport const void *GetVirtualMetacontent(const Image *image) 02845 { 02846 CacheInfo 02847 *cache_info; 02848 02849 const int 02850 id = GetOpenMPThreadId(); 02851 02852 const void 02853 *metacontent; 02854 02855 assert(image != (const Image *) NULL); 02856 assert(image->signature == MagickSignature); 02857 assert(image->cache != (Cache) NULL); 02858 cache_info=(CacheInfo *) image->cache; 02859 assert(cache_info->signature == MagickSignature); 02860 if (cache_info->methods.get_virtual_metacontent_from_handler != 02861 (GetVirtualMetacontentFromHandler) NULL) 02862 { 02863 metacontent=cache_info->methods. 02864 get_virtual_metacontent_from_handler(image); 02865 return(metacontent); 02866 } 02867 assert(id < (int) cache_info->number_threads); 02868 metacontent=GetVirtualMetacontentFromNexus(cache_info, 02869 cache_info->nexus_info[id]); 02870 return(metacontent); 02871 } 02872 02873 /* 02874 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02875 % % 02876 % % 02877 % % 02878 + G e t V i r t u a l P i x e l s F r o m N e x u s % 02879 % % 02880 % % 02881 % % 02882 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 02883 % 02884 % GetVirtualPixelsFromNexus() gets virtual pixels from the in-memory or disk 02885 % pixel cache as defined by the geometry parameters. A pointer to the pixels 02886 % is returned if the pixels are transferred, otherwise a NULL is returned. 02887 % 02888 % The format of the GetVirtualPixelsFromNexus() method is: 02889 % 02890 % Quantum *GetVirtualPixelsFromNexus(const Image *image, 02891 % const VirtualPixelMethod method,const ssize_t x,const ssize_t y, 02892 % const size_t columns,const size_t rows,NexusInfo *nexus_info, 02893 % ExceptionInfo *exception) 02894 % 02895 % A description of each parameter follows: 02896 % 02897 % o image: the image. 02898 % 02899 % o virtual_pixel_method: the virtual pixel method. 02900 % 02901 % o x,y,columns,rows: These values define the perimeter of a region of 02902 % pixels. 02903 % 02904 % o nexus_info: the cache nexus to acquire. 02905 % 02906 % o exception: return any errors or warnings in this structure. 02907 % 02908 */ 02909 02910 static ssize_t 02911 DitherMatrix[64] = 02912 { 02913 0, 48, 12, 60, 3, 51, 15, 63, 02914 32, 16, 44, 28, 35, 19, 47, 31, 02915 8, 56, 4, 52, 11, 59, 7, 55, 02916 40, 24, 36, 20, 43, 27, 39, 23, 02917 2, 50, 14, 62, 1, 49, 13, 61, 02918 34, 18, 46, 30, 33, 17, 45, 29, 02919 10, 58, 6, 54, 9, 57, 5, 53, 02920 42, 26, 38, 22, 41, 25, 37, 21 02921 }; 02922 02923 static inline ssize_t DitherX(const ssize_t x,const size_t columns) 02924 { 02925 ssize_t 02926 index; 02927 02928 index=x+DitherMatrix[x & 0x07]-32L; 02929 if (index < 0L) 02930 return(0L); 02931 if (index >= (ssize_t) columns) 02932 return((ssize_t) columns-1L); 02933 return(index); 02934 } 02935 02936 static inline ssize_t DitherY(const ssize_t y,const size_t rows) 02937 { 02938 ssize_t 02939 index; 02940 02941 index=y+DitherMatrix[y & 0x07]-32L; 02942 if (index < 0L) 02943 return(0L); 02944 if (index >= (ssize_t) rows) 02945 return((ssize_t) rows-1L); 02946 return(index); 02947 } 02948 02949 static inline ssize_t EdgeX(const ssize_t x,const size_t columns) 02950 { 02951 if (x < 0L) 02952 return(0L); 02953 if (x >= (ssize_t) columns) 02954 return((ssize_t) (columns-1)); 02955 return(x); 02956 } 02957 02958 static inline ssize_t EdgeY(const ssize_t y,const size_t rows) 02959 { 02960 if (y < 0L) 02961 return(0L); 02962 if (y >= (ssize_t) rows) 02963 return((ssize_t) (rows-1)); 02964 return(y); 02965 } 02966 02967 static inline ssize_t RandomX(RandomInfo *random_info,const size_t columns) 02968 { 02969 return((ssize_t) (columns*GetPseudoRandomValue(random_info))); 02970 } 02971 02972 static inline ssize_t RandomY(RandomInfo *random_info,const size_t rows) 02973 { 02974 return((ssize_t) (rows*GetPseudoRandomValue(random_info))); 02975 } 02976 02977 static inline MagickModulo VirtualPixelModulo(const ssize_t offset, 02978 const size_t extent) 02979 { 02980 MagickModulo 02981 modulo; 02982 02983 /* 02984 Compute the remainder of dividing offset by extent. It returns not only 02985 the quotient (tile the offset falls in) but also the positive remainer 02986 within that tile such that 0 <= remainder < extent. This method is 02987 essentially a ldiv() using a floored modulo division rather than the 02988 normal default truncated modulo division. 02989 */ 02990 modulo.quotient=offset/(ssize_t) extent; 02991 if (offset < 0L) 02992 modulo.quotient--; 02993 modulo.remainder=offset-modulo.quotient*(ssize_t) extent; 02994 return(modulo); 02995 } 02996 02997 MagickPrivate const Quantum *GetVirtualPixelsFromNexus(const Image *image, 02998 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y, 02999 const size_t columns,const size_t rows,NexusInfo *nexus_info, 03000 ExceptionInfo *exception) 03001 { 03002 CacheInfo 03003 *cache_info; 03004 03005 MagickOffsetType 03006 offset; 03007 03008 MagickSizeType 03009 length, 03010 number_pixels; 03011 03012 NexusInfo 03013 **virtual_nexus; 03014 03015 Quantum 03016 *pixels, 03017 virtual_pixel[CompositePixelChannel]; 03018 03019 RectangleInfo 03020 region; 03021 03022 register const Quantum 03023 *restrict p; 03024 03025 register const void 03026 *restrict r; 03027 03028 register Quantum 03029 *restrict q; 03030 03031 register ssize_t 03032 i, 03033 u; 03034 03035 register unsigned char 03036 *restrict s; 03037 03038 ssize_t 03039 v; 03040 03041 void 03042 *virtual_metacontent; 03043 03044 /* 03045 Acquire pixels. 03046 */ 03047 assert(image != (const Image *) NULL); 03048 assert(image->signature == MagickSignature); 03049 assert(image->cache != (Cache) NULL); 03050 cache_info=(CacheInfo *) image->cache; 03051 assert(cache_info->signature == MagickSignature); 03052 if (cache_info->type == UndefinedCache) 03053 return((const Quantum *) NULL); 03054 region.x=x; 03055 region.y=y; 03056 region.width=columns; 03057 region.height=rows; 03058 pixels=SetPixelCacheNexusPixels(image,®ion,nexus_info,exception); 03059 if (pixels == (Quantum *) NULL) 03060 return((const Quantum *) NULL); 03061 q=pixels; 03062 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+ 03063 nexus_info->region.x; 03064 length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+ 03065 nexus_info->region.width-1L; 03066 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows; 03067 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels)) 03068 if ((x >= 0) && ((ssize_t) (x+columns) <= (ssize_t) cache_info->columns) && 03069 (y >= 0) && ((ssize_t) (y+rows) <= (ssize_t) cache_info->rows)) 03070 { 03071 MagickBooleanType 03072 status; 03073 03074 /* 03075 Pixel request is inside cache extents. 03076 */ 03077 if (IsPixelAuthentic(cache_info,nexus_info) != MagickFalse) 03078 return(q); 03079 status=ReadPixelCachePixels(cache_info,nexus_info,exception); 03080 if (status == MagickFalse) 03081 return((const Quantum *) NULL); 03082 if (cache_info->metacontent_extent != 0) 03083 { 03084 status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception); 03085 if (status == MagickFalse) 03086 return((const Quantum *) NULL); 03087 } 03088 return(q); 03089 } 03090 /* 03091 Pixel request is outside cache extents. 03092 */ 03093 s=(unsigned char *) GetPixelCacheNexusMetacontent(cache_info,nexus_info); 03094 virtual_nexus=AcquirePixelCacheNexus(1); 03095 if (virtual_nexus == (NexusInfo **) NULL) 03096 { 03097 if (virtual_nexus != (NexusInfo **) NULL) 03098 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1); 03099 (void) ThrowMagickException(exception,GetMagickModule(),CacheError, 03100 "UnableToGetCacheNexus","`%s'",image->filename); 03101 return((const Quantum *) NULL); 03102 } 03103 (void) ResetMagickMemory(virtual_pixel,0,cache_info->number_channels* 03104 sizeof(*virtual_pixel)); 03105 virtual_metacontent=(void *) NULL; 03106 switch (virtual_pixel_method) 03107 { 03108 case BackgroundVirtualPixelMethod: 03109 case BlackVirtualPixelMethod: 03110 case GrayVirtualPixelMethod: 03111 case TransparentVirtualPixelMethod: 03112 case MaskVirtualPixelMethod: 03113 case WhiteVirtualPixelMethod: 03114 case EdgeVirtualPixelMethod: 03115 case CheckerTileVirtualPixelMethod: 03116 case HorizontalTileVirtualPixelMethod: 03117 case VerticalTileVirtualPixelMethod: 03118 { 03119 if (cache_info->metacontent_extent != 0) 03120 { 03121 /* 03122 Acquire a metacontent buffer. 03123 */ 03124 virtual_metacontent=(void *) AcquireQuantumMemory(1, 03125 cache_info->metacontent_extent); 03126 if (virtual_metacontent == (void *) NULL) 03127 { 03128 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1); 03129 (void) ThrowMagickException(exception,GetMagickModule(), 03130 CacheError,"UnableToGetCacheNexus","`%s'",image->filename); 03131 return((const Quantum *) NULL); 03132 } 03133 (void) ResetMagickMemory(virtual_metacontent,0, 03134 cache_info->metacontent_extent); 03135 } 03136 switch (virtual_pixel_method) 03137 { 03138 case BlackVirtualPixelMethod: 03139 { 03140 for (i=0; i < (ssize_t) cache_info->number_channels; i++) 03141 SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel); 03142 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel); 03143 break; 03144 } 03145 case GrayVirtualPixelMethod: 03146 { 03147 for (i=0; i < (ssize_t) cache_info->number_channels; i++) 03148 SetPixelChannel(image,(PixelChannel) i,QuantumRange/2, 03149 virtual_pixel); 03150 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel); 03151 break; 03152 } 03153 case TransparentVirtualPixelMethod: 03154 { 03155 for (i=0; i < (ssize_t) cache_info->number_channels; i++) 03156 SetPixelChannel(image,(PixelChannel) i,0,virtual_pixel); 03157 SetPixelAlpha(image,TransparentAlpha,virtual_pixel); 03158 break; 03159 } 03160 case MaskVirtualPixelMethod: 03161 case WhiteVirtualPixelMethod: 03162 { 03163 for (i=0; i < (ssize_t) cache_info->number_channels; i++) 03164 SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel); 03165 SetPixelAlpha(image,OpaqueAlpha,virtual_pixel); 03166 break; 03167 } 03168 default: 03169 { 03170 SetPixelRed(image,ClampToQuantum(image->background_color.red), 03171 virtual_pixel); 03172 SetPixelGreen(image,ClampToQuantum(image->background_color.green), 03173 virtual_pixel); 03174 SetPixelBlue(image,ClampToQuantum(image->background_color.blue), 03175 virtual_pixel); 03176 SetPixelBlack(image,ClampToQuantum(image->background_color.black), 03177 virtual_pixel); 03178 SetPixelAlpha(image,ClampToQuantum(image->background_color.alpha), 03179 virtual_pixel); 03180 break; 03181 } 03182 } 03183 break; 03184 } 03185 default: 03186 break; 03187 } 03188 for (v=0; v < (ssize_t) rows; v++) 03189 { 03190 for (u=0; u < (ssize_t) columns; u+=length) 03191 { 03192 length=(MagickSizeType) MagickMin(cache_info->columns-(x+u),columns-u); 03193 if ((((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns)) || 03194 (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows)) || 03195 (length == 0)) 03196 { 03197 MagickModulo 03198 x_modulo, 03199 y_modulo; 03200 03201 /* 03202 Transfer a single pixel. 03203 */ 03204 length=(MagickSizeType) 1; 03205 switch (virtual_pixel_method) 03206 { 03207 default: 03208 { 03209 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method, 03210 EdgeX(x+u,cache_info->columns),EdgeY(y+v,cache_info->rows), 03211 1UL,1UL,*virtual_nexus,exception); 03212 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus); 03213 break; 03214 } 03215 case RandomVirtualPixelMethod: 03216 { 03217 if (cache_info->random_info == (RandomInfo *) NULL) 03218 cache_info->random_info=AcquireRandomInfo(); 03219 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method, 03220 RandomX(cache_info->random_info,cache_info->columns), 03221 RandomY(cache_info->random_info,cache_info->rows),1UL,1UL, 03222 *virtual_nexus,exception); 03223 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus); 03224 break; 03225 } 03226 case DitherVirtualPixelMethod: 03227 { 03228 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method, 03229 DitherX(x+u,cache_info->columns),DitherY(y+v,cache_info->rows), 03230 1UL,1UL,*virtual_nexus,exception); 03231 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus); 03232 break; 03233 } 03234 case TileVirtualPixelMethod: 03235 { 03236 x_modulo=VirtualPixelModulo(x+u,cache_info->columns); 03237 y_modulo=VirtualPixelModulo(y+v,cache_info->rows); 03238 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method, 03239 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus, 03240 exception); 03241 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus); 03242 break; 03243 } 03244 case MirrorVirtualPixelMethod: 03245 { 03246 x_modulo=VirtualPixelModulo(x+u,cache_info->columns); 03247 if ((x_modulo.quotient & 0x01) == 1L) 03248 x_modulo.remainder=(ssize_t) cache_info->columns- 03249 x_modulo.remainder-1L; 03250 y_modulo=VirtualPixelModulo(y+v,cache_info->rows); 03251 if ((y_modulo.quotient & 0x01) == 1L) 03252 y_modulo.remainder=(ssize_t) cache_info->rows- 03253 y_modulo.remainder-1L; 03254 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method, 03255 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus, 03256 exception); 03257 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus); 03258 break; 03259 } 03260 case HorizontalTileEdgeVirtualPixelMethod: 03261 { 03262 x_modulo=VirtualPixelModulo(x+u,cache_info->columns); 03263 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method, 03264 x_modulo.remainder,EdgeY(y+v,cache_info->rows),1UL,1UL, 03265 *virtual_nexus,exception); 03266 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus); 03267 break; 03268 } 03269 case VerticalTileEdgeVirtualPixelMethod: 03270 { 03271 y_modulo=VirtualPixelModulo(y+v,cache_info->rows); 03272 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method, 03273 EdgeX(x+u,cache_info->columns),y_modulo.remainder,1UL,1UL, 03274 *virtual_nexus,exception); 03275 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus); 03276 break; 03277 } 03278 case BackgroundVirtualPixelMethod: 03279 case BlackVirtualPixelMethod: 03280 case GrayVirtualPixelMethod: 03281 case TransparentVirtualPixelMethod: 03282 case MaskVirtualPixelMethod: 03283 case WhiteVirtualPixelMethod: 03284 { 03285 p=virtual_pixel; 03286 r=virtual_metacontent; 03287 break; 03288 } 03289 case EdgeVirtualPixelMethod: 03290 case CheckerTileVirtualPixelMethod: 03291 { 03292 x_modulo=VirtualPixelModulo(x+u,cache_info->columns); 03293 y_modulo=VirtualPixelModulo(y+v,cache_info->rows); 03294 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L) 03295 { 03296 p=virtual_pixel; 03297 r=virtual_metacontent; 03298 break; 03299 } 03300 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method, 03301 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus, 03302 exception); 03303 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus); 03304 break; 03305 } 03306 case HorizontalTileVirtualPixelMethod: 03307 { 03308 if (((y+v) < 0) || ((y+v) >= (ssize_t) cache_info->rows)) 03309 { 03310 p=virtual_pixel; 03311 r=virtual_metacontent; 03312 break; 03313 } 03314 x_modulo=VirtualPixelModulo(x+u,cache_info->columns); 03315 y_modulo=VirtualPixelModulo(y+v,cache_info->rows); 03316 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method, 03317 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus, 03318 exception); 03319 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus); 03320 break; 03321 } 03322 case VerticalTileVirtualPixelMethod: 03323 { 03324 if (((x+u) < 0) || ((x+u) >= (ssize_t) cache_info->columns)) 03325 { 03326 p=virtual_pixel; 03327 r=virtual_metacontent; 03328 break; 03329 } 03330 x_modulo=VirtualPixelModulo(x+u,cache_info->columns); 03331 y_modulo=VirtualPixelModulo(y+v,cache_info->rows); 03332 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method, 03333 x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus, 03334 exception); 03335 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus); 03336 break; 03337 } 03338 } 03339 if (p == (const Quantum *) NULL) 03340 break; 03341 (void) memcpy(q,p,(size_t) length*cache_info->number_channels* 03342 sizeof(*p)); 03343 q+=cache_info->number_channels; 03344 if ((s != (void *) NULL) && (r != (const void *) NULL)) 03345 { 03346 (void) memcpy(s,r,(size_t) cache_info->metacontent_extent); 03347 s+=cache_info->metacontent_extent; 03348 } 03349 continue; 03350 } 03351 /* 03352 Transfer a run of pixels. 03353 */ 03354 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x+u,y+v,(size_t) 03355 length,1UL,*virtual_nexus,exception); 03356 if (p == (const Quantum *) NULL) 03357 break; 03358 r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus); 03359 (void) memcpy(q,p,(size_t) length*cache_info->number_channels*sizeof(*p)); 03360 q+=length*cache_info->number_channels; 03361 if ((r != (void *) NULL) && (s != (const void *) NULL)) 03362 { 03363 (void) memcpy(s,r,(size_t) length); 03364 s+=length*cache_info->metacontent_extent; 03365 } 03366 } 03367 } 03368 /* 03369 Free resources. 03370 */ 03371 if (virtual_metacontent != (void *) NULL) 03372 virtual_metacontent=(void *) RelinquishMagickMemory(virtual_metacontent); 03373 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1); 03374 return(pixels); 03375 } 03376 03377 /* 03378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03379 % % 03380 % % 03381 % % 03382 + G e t V i r t u a l P i x e l C a c h e % 03383 % % 03384 % % 03385 % % 03386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03387 % 03388 % GetVirtualPixelCache() get virtual pixels from the in-memory or disk pixel 03389 % cache as defined by the geometry parameters. A pointer to the pixels 03390 % is returned if the pixels are transferred, otherwise a NULL is returned. 03391 % 03392 % The format of the GetVirtualPixelCache() method is: 03393 % 03394 % const Quantum *GetVirtualPixelCache(const Image *image, 03395 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x, 03396 % const ssize_t y,const size_t columns,const size_t rows, 03397 % ExceptionInfo *exception) 03398 % 03399 % A description of each parameter follows: 03400 % 03401 % o image: the image. 03402 % 03403 % o virtual_pixel_method: the virtual pixel method. 03404 % 03405 % o x,y,columns,rows: These values define the perimeter of a region of 03406 % pixels. 03407 % 03408 % o exception: return any errors or warnings in this structure. 03409 % 03410 */ 03411 static const Quantum *GetVirtualPixelCache(const Image *image, 03412 const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y, 03413 const size_t columns,const size_t rows,ExceptionInfo *exception) 03414 { 03415 CacheInfo 03416 *cache_info; 03417 03418 const int 03419 id = GetOpenMPThreadId(); 03420 03421 const Quantum 03422 *p; 03423 03424 assert(image != (const Image *) NULL); 03425 assert(image->signature == MagickSignature); 03426 assert(image->cache != (Cache) NULL); 03427 cache_info=(CacheInfo *) image->cache; 03428 assert(cache_info->signature == MagickSignature); 03429 assert(id < (int) cache_info->number_threads); 03430 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,columns,rows, 03431 cache_info->nexus_info[id],exception); 03432 return(p); 03433 } 03434 03435 /* 03436 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03437 % % 03438 % % 03439 % % 03440 % G e t V i r t u a l P i x e l Q u e u e % 03441 % % 03442 % % 03443 % % 03444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03445 % 03446 % GetVirtualPixelQueue() returns the virtual pixels associated corresponding 03447 % with the last call to QueueAuthenticPixels() or GetVirtualPixels(). 03448 % 03449 % The format of the GetVirtualPixelQueue() method is: 03450 % 03451 % const Quantum *GetVirtualPixelQueue(const Image image) 03452 % 03453 % A description of each parameter follows: 03454 % 03455 % o image: the image. 03456 % 03457 */ 03458 MagickExport const Quantum *GetVirtualPixelQueue(const Image *image) 03459 { 03460 CacheInfo 03461 *cache_info; 03462 03463 const int 03464 id = GetOpenMPThreadId(); 03465 03466 assert(image != (const Image *) NULL); 03467 assert(image->signature == MagickSignature); 03468 assert(image->cache != (Cache) NULL); 03469 cache_info=(CacheInfo *) image->cache; 03470 assert(cache_info->signature == MagickSignature); 03471 if (cache_info->methods.get_virtual_pixels_handler != 03472 (GetVirtualPixelsHandler) NULL) 03473 return(cache_info->methods.get_virtual_pixels_handler(image)); 03474 assert(id < (int) cache_info->number_threads); 03475 return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[id])); 03476 } 03477 03478 /* 03479 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03480 % % 03481 % % 03482 % % 03483 % G e t V i r t u a l P i x e l s % 03484 % % 03485 % % 03486 % % 03487 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03488 % 03489 % GetVirtualPixels() returns an immutable pixel region. If the 03490 % region is successfully accessed, a pointer to it is returned, otherwise 03491 % NULL is returned. The returned pointer may point to a temporary working 03492 % copy of the pixels or it may point to the original pixels in memory. 03493 % Performance is maximized if the selected region is part of one row, or one 03494 % or more full rows, since there is opportunity to access the pixels in-place 03495 % (without a copy) if the image is in memory, or in a memory-mapped file. The 03496 % returned pointer must *never* be deallocated by the user. 03497 % 03498 % Pixels accessed via the returned pointer represent a simple array of type 03499 % Quantum. If the image type is CMYK or the storage class is PseudoClass, 03500 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to 03501 % access the meta-content (of type void) corresponding to the the 03502 % region. 03503 % 03504 % If you plan to modify the pixels, use GetAuthenticPixels() instead. 03505 % 03506 % Note, the GetVirtualPixels() and GetAuthenticPixels() methods are not thread- 03507 % safe. In a threaded environment, use GetCacheViewVirtualPixels() or 03508 % GetCacheViewAuthenticPixels() instead. 03509 % 03510 % The format of the GetVirtualPixels() method is: 03511 % 03512 % const Quantum *GetVirtualPixels(const Image *image,const ssize_t x, 03513 % const ssize_t y,const size_t columns,const size_t rows, 03514 % ExceptionInfo *exception) 03515 % 03516 % A description of each parameter follows: 03517 % 03518 % o image: the image. 03519 % 03520 % o x,y,columns,rows: These values define the perimeter of a region of 03521 % pixels. 03522 % 03523 % o exception: return any errors or warnings in this structure. 03524 % 03525 */ 03526 MagickExport const Quantum *GetVirtualPixels(const Image *image, 03527 const ssize_t x,const ssize_t y,const size_t columns,const size_t rows, 03528 ExceptionInfo *exception) 03529 { 03530 CacheInfo 03531 *cache_info; 03532 03533 const int 03534 id = GetOpenMPThreadId(); 03535 03536 const Quantum 03537 *p; 03538 03539 assert(image != (const Image *) NULL); 03540 assert(image->signature == MagickSignature); 03541 assert(image->cache != (Cache) NULL); 03542 cache_info=(CacheInfo *) image->cache; 03543 assert(cache_info->signature == MagickSignature); 03544 if (cache_info->methods.get_virtual_pixel_handler != 03545 (GetVirtualPixelHandler) NULL) 03546 return(cache_info->methods.get_virtual_pixel_handler(image, 03547 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception)); 03548 assert(id < (int) cache_info->number_threads); 03549 p=GetVirtualPixelsFromNexus(image,GetPixelCacheVirtualMethod(image),x,y, 03550 columns,rows,cache_info->nexus_info[id],exception); 03551 return(p); 03552 } 03553 03554 /* 03555 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03556 % % 03557 % % 03558 % % 03559 + G e t V i r t u a l P i x e l s F r o m C a c h e % 03560 % % 03561 % % 03562 % % 03563 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03564 % 03565 % GetVirtualPixelsCache() returns the pixels associated corresponding with the 03566 % last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache(). 03567 % 03568 % The format of the GetVirtualPixelsCache() method is: 03569 % 03570 % Quantum *GetVirtualPixelsCache(const Image *image) 03571 % 03572 % A description of each parameter follows: 03573 % 03574 % o image: the image. 03575 % 03576 */ 03577 static const Quantum *GetVirtualPixelsCache(const Image *image) 03578 { 03579 CacheInfo 03580 *cache_info; 03581 03582 const int 03583 id = GetOpenMPThreadId(); 03584 03585 assert(image != (const Image *) NULL); 03586 assert(image->signature == MagickSignature); 03587 assert(image->cache != (Cache) NULL); 03588 cache_info=(CacheInfo *) image->cache; 03589 assert(cache_info->signature == MagickSignature); 03590 assert(id < (int) cache_info->number_threads); 03591 return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[id])); 03592 } 03593 03594 /* 03595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03596 % % 03597 % % 03598 % % 03599 + G e t V i r t u a l P i x e l s N e x u s % 03600 % % 03601 % % 03602 % % 03603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03604 % 03605 % GetVirtualPixelsNexus() returns the pixels associated with the specified 03606 % cache nexus. 03607 % 03608 % The format of the GetVirtualPixelsNexus() method is: 03609 % 03610 % const Quantum *GetVirtualPixelsNexus(const Cache cache, 03611 % NexusInfo *nexus_info) 03612 % 03613 % A description of each parameter follows: 03614 % 03615 % o cache: the pixel cache. 03616 % 03617 % o nexus_info: the cache nexus to return the colormap pixels. 03618 % 03619 */ 03620 MagickPrivate const Quantum *GetVirtualPixelsNexus(const Cache cache, 03621 NexusInfo *nexus_info) 03622 { 03623 CacheInfo 03624 *cache_info; 03625 03626 assert(cache != (Cache) NULL); 03627 cache_info=(CacheInfo *) cache; 03628 assert(cache_info->signature == MagickSignature); 03629 if (cache_info->storage_class == UndefinedClass) 03630 return((Quantum *) NULL); 03631 return((const Quantum *) nexus_info->pixels); 03632 } 03633 03634 /* 03635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03636 % % 03637 % % 03638 % % 03639 + O p e n P i x e l C a c h e % 03640 % % 03641 % % 03642 % % 03643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 03644 % 03645 % OpenPixelCache() allocates the pixel cache. This includes defining the cache 03646 % dimensions, allocating space for the image pixels and optionally the 03647 % metacontent, and memory mapping the cache if it is disk based. The cache 03648 % nexus array is initialized as well. 03649 % 03650 % The format of the OpenPixelCache() method is: 03651 % 03652 % MagickBooleanType OpenPixelCache(Image *image,const MapMode mode, 03653 % ExceptionInfo *exception) 03654 % 03655 % A description of each parameter follows: 03656 % 03657 % o image: the image. 03658 % 03659 % o mode: ReadMode, WriteMode, or IOMode. 03660 % 03661 % o exception: return any errors or warnings in this structure. 03662 % 03663 */ 03664 03665 static inline void AllocatePixelCachePixels(CacheInfo *cache_info) 03666 { 03667 cache_info->mapped=MagickFalse; 03668 cache_info->pixels=(Quantum *) AcquireQuantumMemory(1,(size_t) 03669 cache_info->length); 03670 if (cache_info->pixels == (Quantum *) NULL) 03671 { 03672 cache_info->mapped=MagickTrue; 03673 cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(size_t) 03674 cache_info->length); 03675 } 03676 } 03677 03678 static MagickBooleanType ExtendCache(Image *image,MagickSizeType length) 03679 { 03680 CacheInfo 03681 *cache_info; 03682 03683 MagickOffsetType 03684 count, 03685 extent, 03686 offset; 03687 03688 cache_info=(CacheInfo *) image->cache; 03689 if (image->debug != MagickFalse) 03690 { 03691 char 03692 format[MaxTextExtent], 03693 message[MaxTextExtent]; 03694 03695 (void) FormatMagickSize(length,MagickFalse,format); 03696 (void) FormatLocaleString(message,MaxTextExtent, 03697 "extend %s (%s[%d], disk, %s)",cache_info->filename, 03698 cache_info->cache_filename,cache_info->file,format); 03699 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message); 03700 } 03701 if (length != (MagickSizeType) ((MagickOffsetType) length)) 03702 return(MagickFalse); 03703 extent=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END); 03704 if (extent < 0) 03705 return(MagickFalse); 03706 if ((MagickSizeType) extent >= length) 03707 return(MagickTrue); 03708 offset=(MagickOffsetType) length-1; 03709 count=WritePixelCacheRegion(cache_info,offset,1,(const unsigned char *) ""); 03710 return(count == (MagickOffsetType) 1 ? MagickTrue : MagickFalse); 03711 } 03712 03713 static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode, 03714 ExceptionInfo *exception) 03715 { 03716 CacheInfo 03717 *cache_info, 03718 source_info; 03719 03720 char 03721 format[MaxTextExtent], 03722 message[MaxTextExtent]; 03723 03724 MagickBooleanType 03725 status; 03726 03727 MagickSizeType 03728 length, 03729 number_pixels; 03730 03731 PixelChannelMap 03732 *p, 03733 *q; 03734 03735 size_t 03736 columns, 03737 packet_size; 03738 03739 assert(image != (const Image *) NULL); 03740 assert(image->signature == MagickSignature); 03741 assert(image->cache != (Cache) NULL); 03742 if (image->debug != MagickFalse) 03743 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 03744 if ((image->columns == 0) || (image->rows == 0)) 03745 ThrowBinaryException(CacheError,"NoPixelsDefinedInCache",image->filename); 03746 cache_info=(CacheInfo *) image->cache; 03747 assert(cache_info->signature == MagickSignature); 03748 source_info=(*cache_info); 03749 source_info.file=(-1); 03750 (void) FormatLocaleString(cache_info->filename,MaxTextExtent,"%s[%.20g]", 03751 image->filename,(double) GetImageIndexInList(image)); 03752 cache_info->storage_class=image->storage_class; 03753 cache_info->colorspace=image->colorspace; 03754 cache_info->matte=image->matte; 03755 cache_info->mask=image->mask; 03756 cache_info->rows=image->rows; 03757 cache_info->columns=image->columns; 03758 InitializePixelChannelMap(image); 03759 cache_info->number_channels=GetPixelChannels(image); 03760 (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels* 03761 sizeof(*image->channel_map)); 03762 cache_info->metacontent_extent=image->metacontent_extent; 03763 cache_info->mode=mode; 03764 if (image->ping != MagickFalse) 03765 { 03766 cache_info->type=PingCache; 03767 cache_info->pixels=(Quantum *) NULL; 03768 cache_info->metacontent=(void *) NULL; 03769 cache_info->length=0; 03770 return(MagickTrue); 03771 } 03772 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows; 03773 packet_size=cache_info->number_channels*sizeof(Quantum); 03774 if (image->metacontent_extent != 0) 03775 packet_size+=cache_info->metacontent_extent; 03776 length=number_pixels*packet_size; 03777 columns=(size_t) (length/cache_info->rows/packet_size); 03778 if (cache_info->columns != columns) 03779 ThrowBinaryException(ResourceLimitError,"PixelCacheAllocationFailed", 03780 image->filename); 03781 cache_info->length=length; 03782 p=cache_info->channel_map; 03783 q=source_info.channel_map; 03784 if ((cache_info->type != UndefinedCache) && 03785 (cache_info->columns <= source_info.columns) && 03786 (cache_info->rows <= source_info.rows) && 03787 (cache_info->number_channels <= source_info.number_channels) && 03788 (memcmp(p,q,cache_info->number_channels*sizeof(*p)) == 0) && 03789 (cache_info->metacontent_extent <= source_info.metacontent_extent)) 03790 { 03791 /* 03792 Inline pixel cache clone optimization. 03793 */ 03794 if ((cache_info->columns == source_info.columns) && 03795 (cache_info->rows == source_info.rows) && 03796 (cache_info->number_channels == source_info.number_channels) && 03797 (memcmp(p,q,cache_info->number_channels*sizeof(*p)) == 0) && 03798 (cache_info->metacontent_extent == source_info.metacontent_extent)) 03799 return(MagickTrue); 03800 return(ClonePixelCachePixels(cache_info,&source_info,exception)); 03801 } 03802 status=AcquireMagickResource(AreaResource,cache_info->length); 03803 length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+ 03804 cache_info->metacontent_extent); 03805 if ((status != MagickFalse) && (length == (MagickSizeType) ((size_t) length))) 03806 { 03807 status=AcquireMagickResource(MemoryResource,cache_info->length); 03808 if (((cache_info->type == UndefinedCache) && (status != MagickFalse)) || 03809 (cache_info->type == MemoryCache)) 03810 { 03811 AllocatePixelCachePixels(cache_info); 03812 if (cache_info->pixels == (Quantum *) NULL) 03813 cache_info->pixels=source_info.pixels; 03814 else 03815 { 03816 /* 03817 Create memory pixel cache. 03818 */ 03819 status=MagickTrue; 03820 if (image->debug != MagickFalse) 03821 { 03822 (void) FormatMagickSize(cache_info->length,MagickTrue,format); 03823 (void) FormatLocaleString(message,MaxTextExtent, 03824 "open %s (%s memory, %.20gx%.20gx%.20g %s)", 03825 cache_info->filename,cache_info->mapped != MagickFalse ? 03826 "anonymous" : "heap",(double) cache_info->columns,(double) 03827 cache_info->rows,(double) cache_info->number_channels, 03828 format); 03829 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s", 03830 message); 03831 } 03832 cache_info->type=MemoryCache; 03833 cache_info->metacontent=(void *) NULL; 03834 if (cache_info->metacontent_extent != 0) 03835 cache_info->metacontent=(void *) (cache_info->pixels+ 03836 number_pixels*cache_info->number_channels); 03837 if ((source_info.storage_class != UndefinedClass) && 03838 (mode != ReadMode)) 03839 { 03840 status=ClonePixelCachePixels(cache_info,&source_info, 03841 exception); 03842 RelinquishPixelCachePixels(&source_info); 03843 } 03844 return(status); 03845 } 03846 } 03847 RelinquishMagickResource(MemoryResource,cache_info->length); 03848 } 03849 /* 03850 Create pixel cache on disk. 03851 */ 03852 status=AcquireMagickResource(DiskResource,cache_info->length); 03853 if (status == MagickFalse) 03854 { 03855 (void) ThrowMagickException(exception,GetMagickModule(),CacheError, 03856 "CacheResourcesExhausted","`%s'",image->filename); 03857 return(MagickFalse); 03858 } 03859 if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode)) 03860 { 03861 (void) ClosePixelCacheOnDisk(cache_info); 03862 *cache_info->cache_filename='\0'; 03863 } 03864 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse) 03865 { 03866 RelinquishMagickResource(DiskResource,cache_info->length); 03867 ThrowFileException(exception,CacheError,"UnableToOpenPixelCache", 03868 image->filename); 03869 return(MagickFalse); 03870 } 03871 status=ExtendCache(image,(MagickSizeType) cache_info->offset+ 03872 cache_info->length); 03873 if (status == MagickFalse) 03874 { 03875 ThrowFileException(exception,CacheError,"UnableToExtendCache", 03876 image->filename); 03877 return(MagickFalse); 03878 } 03879 length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+ 03880 cache_info->metacontent_extent); 03881 if (length != (MagickSizeType) ((size_t) length)) 03882 cache_info->type=DiskCache; 03883 else 03884 { 03885 status=AcquireMagickResource(MapResource,cache_info->length); 03886 if ((status == MagickFalse) && (cache_info->type != MapCache) && 03887 (cache_info->type != MemoryCache)) 03888 cache_info->type=DiskCache; 03889 else 03890 { 03891 cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode, 03892 cache_info->offset,(size_t) cache_info->length); 03893 if (cache_info->pixels == (Quantum *) NULL) 03894 { 03895 cache_info->type=DiskCache; 03896 cache_info->pixels=source_info.pixels; 03897 } 03898 else 03899 { 03900 /* 03901 Create file-backed memory-mapped pixel cache. 03902 */ 03903 status=MagickTrue; 03904 (void) ClosePixelCacheOnDisk(cache_info); 03905 cache_info->type=MapCache; 03906 cache_info->mapped=MagickTrue; 03907 cache_info->metacontent=(void *) NULL; 03908 if (cache_info->metacontent_extent != 0) 03909 cache_info->metacontent=(void *) (cache_info->pixels+ 03910 number_pixels*cache_info->number_channels); 03911 if ((source_info.storage_class != UndefinedClass) && 03912 (mode != ReadMode)) 03913 { 03914 status=ClonePixelCachePixels(cache_info,&source_info, 03915 exception); 03916 RelinquishPixelCachePixels(&source_info); 03917 } 03918 if (image->debug != MagickFalse) 03919 { 03920 (void) FormatMagickSize(cache_info->length,<