00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include "magick/studio.h"
00044 #include "magick/blob.h"
00045 #include "magick/blob-private.h"
00046 #include "magick/cache.h"
00047 #include "magick/cache-private.h"
00048 #include "magick/color-private.h"
00049 #include "magick/composite-private.h"
00050 #include "magick/exception.h"
00051 #include "magick/exception-private.h"
00052 #include "magick/list.h"
00053 #include "magick/log.h"
00054 #include "magick/magick.h"
00055 #include "magick/memory_.h"
00056 #include "magick/pixel-private.h"
00057 #include "magick/quantum.h"
00058 #include "magick/random_.h"
00059 #include "magick/resource_.h"
00060 #include "magick/semaphore.h"
00061 #include "magick/splay-tree.h"
00062 #include "magick/string_.h"
00063 #include "magick/thread-private.h"
00064 #include "magick/utility.h"
00065 #if defined(MAGICKCORE_ZLIB_DELEGATE)
00066 #include "zlib.h"
00067 #endif
00068
00069
00070
00071
00072 typedef struct _MagickModulo
00073 {
00074 long
00075 quotient,
00076 remainder;
00077 } MagickModulo;
00078
00079 struct _NexusInfo
00080 {
00081 MagickBooleanType
00082 mapped;
00083
00084 RectangleInfo
00085 region;
00086
00087 MagickSizeType
00088 length;
00089
00090 PixelPacket
00091 *cache,
00092 *pixels;
00093
00094 IndexPacket
00095 *indexes;
00096
00097 unsigned long
00098 signature;
00099 };
00100
00101
00102
00103
00104 #if defined(__cplusplus) || defined(c_plusplus)
00105 extern "C" {
00106 #endif
00107
00108 static const IndexPacket
00109 *GetVirtualIndexesFromCache(const Image *);
00110
00111 static const PixelPacket
00112 *GetVirtualPixelCache(const Image *,const VirtualPixelMethod,const long,
00113 const long,const unsigned long,const unsigned long,ExceptionInfo *),
00114 *GetVirtualPixelsCache(const Image *);
00115
00116 static MagickBooleanType
00117 GetOneAuthenticPixelFromCache(Image *,const long,const long,PixelPacket *,
00118 ExceptionInfo *),
00119 GetOneVirtualPixelFromCache(const Image *,const VirtualPixelMethod,
00120 const long,const long,PixelPacket *,ExceptionInfo *),
00121 OpenPixelCache(Image *,const MapMode,ExceptionInfo *),
00122 ReadPixelCacheIndexes(CacheInfo *,NexusInfo *,ExceptionInfo *),
00123 ReadPixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *),
00124 SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
00125 WritePixelCacheIndexes(CacheInfo *,NexusInfo *,ExceptionInfo *),
00126 WritePixelCachePixels(CacheInfo *,NexusInfo *,ExceptionInfo *);
00127
00128 static PixelPacket
00129 *GetAuthenticPixelsCache(Image *,const long,const long,const unsigned long,
00130 const unsigned long,ExceptionInfo *),
00131 *QueueAuthenticPixelsCache(Image *,const long,const long,const unsigned long,
00132 const unsigned long,ExceptionInfo *),
00133 *SetPixelCacheNexusPixels(const Image *,const RectangleInfo *,NexusInfo *,
00134 ExceptionInfo *);
00135
00136 #if defined(__cplusplus) || defined(c_plusplus)
00137 }
00138 #endif
00139
00140
00141
00142
00143 static volatile MagickBooleanType
00144 instantiate_cache = MagickFalse;
00145
00146 static SemaphoreInfo
00147 *cache_semaphore = (SemaphoreInfo *) NULL;
00148
00149 static SplayTreeInfo
00150 *cache_resources = (SplayTreeInfo *) NULL;
00151
00152 static time_t
00153 cache_timer = 0;
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 MagickExport Cache AcquirePixelCacheInfo(const unsigned long number_threads)
00178 {
00179 CacheInfo
00180 *cache_info;
00181
00182 cache_info=(CacheInfo *) AcquireCachelineMemory(sizeof(*cache_info));
00183 if (cache_info == (CacheInfo *) NULL)
00184 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00185 (void) ResetMagickMemory(cache_info,0,sizeof(*cache_info));
00186 cache_info->type=UndefinedCache;
00187 cache_info->colorspace=RGBColorspace;
00188 cache_info->file=(-1);
00189 cache_info->id=GetMagickThreadId();
00190 cache_info->number_threads=number_threads;
00191 if (number_threads == 0)
00192 cache_info->number_threads=GetOpenMPMaximumThreads();
00193 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
00194 if (cache_info->nexus_info == (NexusInfo **) NULL)
00195 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00196 GetPixelCacheMethods(&cache_info->methods);
00197 cache_info->reference_count=1;
00198 cache_info->semaphore=AllocateSemaphoreInfo();
00199 cache_info->disk_semaphore=AllocateSemaphoreInfo();
00200 cache_info->debug=IsEventLogging();
00201 cache_info->signature=MagickSignature;
00202 if ((cache_resources == (SplayTreeInfo *) NULL) &&
00203 (instantiate_cache == MagickFalse))
00204 {
00205 AcquireSemaphoreInfo(&cache_semaphore);
00206 if ((cache_resources == (SplayTreeInfo *) NULL) &&
00207 (instantiate_cache == MagickFalse))
00208 {
00209 cache_resources=NewSplayTree((int (*)(const void *,const void *))
00210 NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
00211 instantiate_cache=MagickTrue;
00212 }
00213 RelinquishSemaphoreInfo(cache_semaphore);
00214 }
00215 (void) AddValueToSplayTree(cache_resources,cache_info,cache_info);
00216 return((Cache ) cache_info);
00217 }
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 MagickExport NexusInfo **AcquirePixelCacheNexus(
00242 const unsigned long number_threads)
00243 {
00244 register long
00245 i;
00246
00247 NexusInfo
00248 **nexus_info;
00249
00250 nexus_info=(NexusInfo **) AcquireCachelineMemory(number_threads*
00251 sizeof(*nexus_info));
00252 if (nexus_info == (NexusInfo **) NULL)
00253 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00254 for (i=0; i < (long) number_threads; i++)
00255 {
00256 nexus_info[i]=(NexusInfo *) AcquireCachelineMemory(sizeof(**nexus_info));
00257 if (nexus_info[i] == (NexusInfo *) NULL)
00258 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00259 (void) ResetMagickMemory(nexus_info[i],0,sizeof(*nexus_info[i]));
00260 nexus_info[i]->signature=MagickSignature;
00261 }
00262 return(nexus_info);
00263 }
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 static MagickBooleanType ClipPixelCacheNexus(Image *image,
00295 NexusInfo *nexus_info,ExceptionInfo *exception)
00296 {
00297 CacheInfo
00298 *cache_info;
00299
00300 MagickSizeType
00301 number_pixels;
00302
00303 NexusInfo
00304 **clip_nexus,
00305 **image_nexus;
00306
00307 register const PixelPacket
00308 *__restrict r;
00309
00310 register IndexPacket
00311 *__restrict nexus_indexes,
00312 *__restrict indexes;
00313
00314 register long
00315 i;
00316
00317 register PixelPacket
00318 *__restrict p,
00319 *__restrict q;
00320
00321
00322
00323
00324 if (image->debug != MagickFalse)
00325 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00326 if (image->clip_mask == (Image *) NULL)
00327 return(MagickFalse);
00328 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
00329 if (cache_info == (Cache) NULL)
00330 return(MagickFalse);
00331 image_nexus=AcquirePixelCacheNexus(1);
00332 clip_nexus=AcquirePixelCacheNexus(1);
00333 if ((image_nexus == (NexusInfo **) NULL) ||
00334 (clip_nexus == (NexusInfo **) NULL))
00335 ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
00336 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
00337 nexus_info->region.width,nexus_info->region.height,image_nexus[0],
00338 exception);
00339 indexes=GetPixelCacheNexusIndexes(image->cache,image_nexus[0]);
00340 q=nexus_info->pixels;
00341 nexus_indexes=nexus_info->indexes;
00342 r=GetVirtualPixelsFromNexus(image->clip_mask,MaskVirtualPixelMethod,
00343 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
00344 nexus_info->region.height,clip_nexus[0],exception);
00345 number_pixels=(MagickSizeType) nexus_info->region.width*
00346 nexus_info->region.height;
00347 for (i=0; i < (long) number_pixels; i++)
00348 {
00349 if ((p == (PixelPacket *) NULL) || (r == (const PixelPacket *) NULL))
00350 break;
00351 if (PixelIntensityToQuantum(r) > ((Quantum) QuantumRange/2))
00352 {
00353 q->red=p->red;
00354 q->green=p->green;
00355 q->blue=p->blue;
00356 q->opacity=p->opacity;
00357 if (cache_info->active_index_channel != MagickFalse)
00358 nexus_indexes[i]=indexes[i];
00359 }
00360 p++;
00361 q++;
00362 r++;
00363 }
00364 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
00365 image_nexus=DestroyPixelCacheNexus(image_nexus,1);
00366 if (i < (long) number_pixels)
00367 return(MagickFalse);
00368 return(MagickTrue);
00369 }
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 static inline MagickBooleanType AcquireCacheNexusPixels(CacheInfo *cache_info,
00401 NexusInfo *nexus_info,ExceptionInfo *exception)
00402 {
00403 if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
00404 return(MagickFalse);
00405 nexus_info->mapped=MagickFalse;
00406 nexus_info->cache=(PixelPacket *) AcquireMagickMemory((size_t)
00407 nexus_info->length);
00408 if (nexus_info->cache == (PixelPacket *) NULL)
00409 {
00410 nexus_info->mapped=MagickTrue;
00411 nexus_info->cache=(PixelPacket *) MapBlob(-1,IOMode,0,(size_t)
00412 nexus_info->length);
00413 }
00414 if (nexus_info->cache == (PixelPacket *) NULL)
00415 {
00416 (void) ThrowMagickException(exception,GetMagickModule(),
00417 ResourceLimitError,"MemoryAllocationFailed","`%s'",
00418 cache_info->filename);
00419 return(MagickFalse);
00420 }
00421 return(MagickTrue);
00422 }
00423
00424 static MagickBooleanType ClonePixelCacheNexus(CacheInfo *destination,
00425 CacheInfo *source,ExceptionInfo *exception)
00426 {
00427 MagickBooleanType
00428 status;
00429
00430 MagickSizeType
00431 number_pixels;
00432
00433 register long
00434 i;
00435
00436 register const NexusInfo
00437 *p;
00438
00439 register NexusInfo
00440 *q;
00441
00442 status=MagickTrue;
00443 for (i=0; i < (long) source->number_threads; i++)
00444 {
00445 p=source->nexus_info[i];
00446 q=destination->nexus_info[i];
00447 q->mapped=p->mapped;
00448 q->region=p->region;
00449 q->length=p->length;
00450 q->cache=p->cache;
00451 q->pixels=p->pixels;
00452 q->indexes=p->indexes;
00453 if (p->cache != (PixelPacket *) NULL)
00454 {
00455 status=AcquireCacheNexusPixels(source,q,exception);
00456 if (status != MagickFalse)
00457 {
00458 (void) CopyMagickMemory(q->cache,p->cache,(size_t) p->length);
00459 q->pixels=q->cache;
00460 q->indexes=(IndexPacket *) NULL;
00461 number_pixels=(MagickSizeType) q->region.width*q->region.height;
00462 if (p->indexes != (IndexPacket *) NULL)
00463 q->indexes=(IndexPacket *) (q->pixels+number_pixels);
00464 }
00465 }
00466 }
00467 return(status);
00468 }
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497 static MagickBooleanType ClosePixelCacheOnDisk(CacheInfo *cache_info)
00498 {
00499 int
00500 status;
00501
00502 AcquireSemaphoreInfo(&cache_info->disk_semaphore);
00503 status=close(cache_info->file);
00504 cache_info->file=(-1);
00505 RelinquishMagickResource(FileResource,1);
00506 RelinquishSemaphoreInfo(cache_info->disk_semaphore);
00507 return(status == -1 ? MagickFalse : MagickTrue);
00508 }
00509
00510 static void LimitPixelCacheDescriptors(void)
00511 {
00512 register CacheInfo
00513 *p,
00514 *q;
00515
00516
00517
00518
00519 if (GetMagickResource(FileResource) < GetMagickResourceLimit(FileResource))
00520 return;
00521 AcquireSemaphoreInfo(&cache_semaphore);
00522 if (cache_resources == (SplayTreeInfo *) NULL)
00523 {
00524 RelinquishSemaphoreInfo(cache_semaphore);
00525 return;
00526 }
00527 ResetSplayTreeIterator(cache_resources);
00528 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
00529 while (p != (CacheInfo *) NULL)
00530 {
00531 if ((p->type == DiskCache) && (p->file != -1))
00532 {
00533 if (IsMagickThreadEqual(p->id) != MagickFalse)
00534 break;
00535 }
00536 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
00537 }
00538 for (q=p; p != (CacheInfo *) NULL; )
00539 {
00540 if ((p->type == DiskCache) && (p->file != -1) &&
00541 (p->timestamp < q->timestamp))
00542 {
00543 if (IsMagickThreadEqual(p->id) != MagickFalse)
00544 q=p;
00545 }
00546 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
00547 }
00548 if (q != (CacheInfo *) NULL)
00549 (void) ClosePixelCacheOnDisk(q);
00550 RelinquishSemaphoreInfo(cache_semaphore);
00551 }
00552
00553 static inline MagickSizeType MagickMax(const MagickSizeType x,
00554 const MagickSizeType y)
00555 {
00556 if (x > y)
00557 return(x);
00558 return(y);
00559 }
00560
00561 static inline MagickSizeType MagickMin(const MagickSizeType x,
00562 const MagickSizeType y)
00563 {
00564 if (x < y)
00565 return(x);
00566 return(y);
00567 }
00568
00569 static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
00570 const MapMode mode)
00571 {
00572 int
00573 file;
00574
00575
00576
00577
00578 AcquireSemaphoreInfo(&cache_info->disk_semaphore);
00579 if (cache_info->file != -1)
00580 {
00581 RelinquishSemaphoreInfo(cache_info->disk_semaphore);
00582 return(MagickTrue);
00583 }
00584 LimitPixelCacheDescriptors();
00585 if (*cache_info->cache_filename == '\0')
00586 file=AcquireUniqueFileResource(cache_info->cache_filename);
00587 else
00588 switch (mode)
00589 {
00590 case ReadMode:
00591 {
00592 file=open(cache_info->cache_filename,O_RDONLY | O_BINARY);
00593 break;
00594 }
00595 case WriteMode:
00596 {
00597 file=open(cache_info->cache_filename,O_WRONLY | O_CREAT | O_BINARY |
00598 O_EXCL,S_MODE);
00599 if (file == -1)
00600 file=open(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
00601 break;
00602 }
00603 case IOMode:
00604 default:
00605 {
00606 file=open(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
00607 O_EXCL,S_MODE);
00608 if (file == -1)
00609 file=open(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
00610 break;
00611 }
00612 }
00613 if (file == -1)
00614 {
00615 RelinquishSemaphoreInfo(cache_info->disk_semaphore);
00616 return(MagickFalse);
00617 }
00618 (void) AcquireMagickResource(FileResource,1);
00619 cache_info->file=file;
00620 cache_info->timestamp=time(0);
00621 RelinquishSemaphoreInfo(cache_info->disk_semaphore);
00622 return(MagickTrue);
00623 }
00624
00625 static inline MagickOffsetType ReadPixelCacheRegion(CacheInfo *cache_info,
00626 const MagickOffsetType offset,const MagickSizeType length,
00627 unsigned char *__restrict buffer)
00628 {
00629 register MagickOffsetType
00630 i;
00631
00632 ssize_t
00633 count;
00634
00635 #if !defined(MAGICKCORE_HAVE_PREAD)
00636 (void) LockSemaphoreInfo(cache_info->disk_semaphore);
00637 cache_info->timestamp=time(0);
00638 if (MagickSeek(cache_info->file,offset,SEEK_SET) < 0)
00639 {
00640 (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
00641 return((MagickOffsetType) -1);
00642 }
00643 #endif
00644 count=0;
00645 for (i=0; i < (MagickOffsetType) length; i+=count)
00646 {
00647 #if !defined(MAGICKCORE_HAVE_PREAD)
00648 count=read(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
00649 (MagickSizeType) SSIZE_MAX));
00650 #else
00651 count=pread(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
00652 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
00653 #endif
00654 if (count > 0)
00655 continue;
00656 count=0;
00657 if (errno != EINTR)
00658 {
00659 i=(-1);
00660 break;
00661 }
00662 }
00663 #if !defined(MAGICKCORE_HAVE_PREAD)
00664 (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
00665 #endif
00666 return(i);
00667 }
00668
00669 static inline MagickOffsetType WritePixelCacheRegion(CacheInfo *cache_info,
00670 const MagickOffsetType offset,const MagickSizeType length,
00671 const unsigned char *__restrict buffer)
00672 {
00673 register MagickOffsetType
00674 i;
00675
00676 ssize_t
00677 count;
00678
00679 #if !defined(MAGICKCORE_HAVE_PWRITE)
00680 (void) LockSemaphoreInfo(cache_info->disk_semaphore);
00681 cache_info->timestamp=time(0);
00682 if (MagickSeek(cache_info->file,offset,SEEK_SET) < 0)
00683 {
00684 (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
00685 return((MagickOffsetType) -1);
00686 }
00687 #endif
00688 count=0;
00689 for (i=0; i < (MagickOffsetType) length; i+=count)
00690 {
00691 #if !defined(MAGICKCORE_HAVE_PWRITE)
00692 count=write(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
00693 (MagickSizeType) SSIZE_MAX));
00694 #else
00695 count=pwrite(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
00696 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
00697 #endif
00698 if (count > 0)
00699 continue;
00700 count=0;
00701 if (errno != EINTR)
00702 {
00703 i=(-1);
00704 break;
00705 }
00706 }
00707 #if !defined(MAGICKCORE_HAVE_PWRITE)
00708 (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
00709 #endif
00710 return(i);
00711 }
00712
00713 static MagickBooleanType CloneDiskToDiskPixelCache(CacheInfo *clone_info,
00714 CacheInfo *cache_info,ExceptionInfo *exception)
00715 {
00716 MagickOffsetType
00717 count,
00718 offset,
00719 source_offset;
00720
00721 MagickSizeType
00722 length;
00723
00724 register long
00725 y;
00726
00727 register PixelPacket
00728 *__restrict pixels;
00729
00730 unsigned long
00731 columns,
00732 rows;
00733
00734 if (cache_info->debug != MagickFalse)
00735 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => disk");
00736 if (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse)
00737 {
00738 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
00739 clone_info->cache_filename);
00740 return(MagickFalse);
00741 }
00742 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
00743 {
00744 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
00745 cache_info->cache_filename);
00746 return(MagickFalse);
00747 }
00748 columns=(unsigned long) MagickMin(clone_info->columns,cache_info->columns);
00749 rows=(unsigned long) MagickMin(clone_info->rows,cache_info->rows);
00750 if ((clone_info->active_index_channel != MagickFalse) &&
00751 (cache_info->active_index_channel != MagickFalse))
00752 {
00753 register IndexPacket
00754 *indexes;
00755
00756
00757
00758
00759 length=MagickMax(clone_info->columns,cache_info->columns)*
00760 sizeof(*indexes);
00761 indexes=(IndexPacket *) AcquireMagickMemory((size_t) length);
00762 if (indexes == (IndexPacket *) NULL)
00763 {
00764 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
00765 "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
00766 return(MagickFalse);
00767 }
00768 (void) ResetMagickMemory(indexes,0,(size_t) length);
00769 length=columns*sizeof(*indexes);
00770 source_offset=(MagickOffsetType) cache_info->columns*cache_info->rows*
00771 sizeof(*pixels)+cache_info->columns*rows*sizeof(*indexes);
00772 offset=(MagickOffsetType) clone_info->columns*clone_info->rows*
00773 sizeof(*pixels)+clone_info->columns*rows*sizeof(*indexes);
00774 for (y=0; y < (long) rows; y++)
00775 {
00776 source_offset-=cache_info->columns*sizeof(*indexes);
00777 count=ReadPixelCacheRegion(cache_info,cache_info->offset+source_offset,
00778 length,(unsigned char *) indexes);
00779 if ((MagickSizeType) count != length)
00780 break;
00781 offset-=clone_info->columns*sizeof(*indexes);
00782 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
00783 (unsigned char *) indexes);
00784 if ((MagickSizeType) count != length)
00785 break;
00786 }
00787 if (y < (long) rows)
00788 {
00789 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
00790 ThrowFileException(exception,CacheError,"UnableToCloneCache",
00791 cache_info->cache_filename);
00792 return(MagickFalse);
00793 }
00794 if (clone_info->columns > cache_info->columns)
00795 {
00796 length=(clone_info->columns-cache_info->columns)*sizeof(*indexes);
00797 (void) ResetMagickMemory(indexes,0,(size_t) length);
00798 offset=(MagickOffsetType) clone_info->columns*clone_info->rows*
00799 sizeof(*pixels)+(clone_info->columns*rows+columns)*sizeof(*indexes);
00800 for (y=0; y < (long) rows; y++)
00801 {
00802 offset-=clone_info->columns*sizeof(*indexes);
00803 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,
00804 length,(unsigned char *) indexes);
00805 if ((MagickSizeType) count != length)
00806 break;
00807 }
00808 if (y < (long) rows)
00809 {
00810 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
00811 ThrowFileException(exception,CacheError,"UnableToCloneCache",
00812 cache_info->cache_filename);
00813 return(MagickFalse);
00814 }
00815 }
00816 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
00817 }
00818
00819
00820
00821 length=MagickMax(clone_info->columns,cache_info->columns)*sizeof(*pixels);
00822 pixels=(PixelPacket *) AcquireMagickMemory((size_t) length);
00823 if (pixels == (PixelPacket *) NULL)
00824 {
00825 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
00826 "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
00827 return(MagickFalse);
00828 }
00829 (void) ResetMagickMemory(pixels,0,(size_t) length);
00830 length=columns*sizeof(*pixels);
00831 source_offset=(MagickOffsetType) cache_info->columns*rows*sizeof(*pixels);
00832 offset=(MagickOffsetType) clone_info->columns*rows*sizeof(*pixels);
00833 for (y=0; y < (long) rows; y++)
00834 {
00835 source_offset-=cache_info->columns*sizeof(*pixels);
00836 count=ReadPixelCacheRegion(cache_info,cache_info->offset+source_offset,
00837 length,(unsigned char *) pixels);
00838 if ((MagickSizeType) count != length)
00839 break;
00840 offset-=clone_info->columns*sizeof(*pixels);
00841 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
00842 (unsigned char *) pixels);
00843 if ((MagickSizeType) count != length)
00844 break;
00845 }
00846 if (y < (long) rows)
00847 {
00848 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
00849 ThrowFileException(exception,CacheError,"UnableToCloneCache",
00850 cache_info->cache_filename);
00851 return(MagickFalse);
00852 }
00853 if (clone_info->columns > cache_info->columns)
00854 {
00855 offset=(MagickOffsetType) (clone_info->columns*rows+columns)*
00856 sizeof(*pixels);
00857 length=(clone_info->columns-cache_info->columns)*sizeof(*pixels);
00858 (void) ResetMagickMemory(pixels,0,(size_t) length);
00859 for (y=0; y < (long) rows; y++)
00860 {
00861 offset-=clone_info->columns*sizeof(*pixels);
00862 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
00863 (unsigned char *) pixels);
00864 if ((MagickSizeType) count != length)
00865 break;
00866 }
00867 if (y < (long) rows)
00868 {
00869 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
00870 ThrowFileException(exception,CacheError,"UnableToCloneCache",
00871 cache_info->cache_filename);
00872 return(MagickFalse);
00873 }
00874 }
00875 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
00876 return(MagickTrue);
00877 }
00878
00879 static MagickBooleanType CloneDiskToMemoryPixelCache(CacheInfo *clone_info,
00880 CacheInfo *cache_info,ExceptionInfo *exception)
00881 {
00882 MagickOffsetType
00883 count,
00884 offset;
00885
00886 MagickSizeType
00887 length;
00888
00889 register long
00890 y;
00891
00892 register PixelPacket
00893 *__restrict pixels,
00894 *__restrict q;
00895
00896 unsigned long
00897 columns,
00898 rows;
00899
00900 if (cache_info->debug != MagickFalse)
00901 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => memory");
00902 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
00903 {
00904 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
00905 cache_info->cache_filename);
00906 return(MagickFalse);
00907 }
00908 columns=(unsigned long) MagickMin(clone_info->columns,cache_info->columns);
00909 rows=(unsigned long) MagickMin(clone_info->rows,cache_info->rows);
00910 if ((clone_info->active_index_channel != MagickFalse) &&
00911 (cache_info->active_index_channel != MagickFalse))
00912 {
00913 register IndexPacket
00914 *indexes,
00915 *q;
00916
00917
00918
00919
00920 length=MagickMax(clone_info->columns,cache_info->columns)*
00921 sizeof(*indexes);
00922 indexes=(IndexPacket *) AcquireMagickMemory((size_t) length);
00923 if (indexes == (IndexPacket *) NULL)
00924 {
00925 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
00926 "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
00927 return(MagickFalse);
00928 }
00929 (void) ResetMagickMemory(indexes,0,(size_t) length);
00930 length=columns*sizeof(IndexPacket);
00931 offset=(MagickOffsetType) cache_info->columns*cache_info->rows*
00932 sizeof(*pixels)+cache_info->columns*rows*sizeof(*indexes);
00933 q=clone_info->indexes+clone_info->columns*rows;
00934 for (y=0; y < (long) rows; y++)
00935 {
00936 offset-=cache_info->columns*sizeof(IndexPacket);
00937 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset,
00938 length,(unsigned char *) indexes);
00939 if ((MagickSizeType) count != length)
00940 break;
00941 q-=clone_info->columns;
00942 (void) CopyMagickMemory(q,indexes,(size_t) length);
00943 if ((MagickSizeType) count != length)
00944 break;
00945 }
00946 if (y < (long) rows)
00947 {
00948 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
00949 ThrowFileException(exception,CacheError,"UnableToCloneCache",
00950 cache_info->cache_filename);
00951 return(MagickFalse);
00952 }
00953 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
00954 }
00955
00956
00957
00958 length=MagickMax(clone_info->columns,cache_info->columns)*sizeof(*pixels);
00959 pixels=(PixelPacket *) AcquireMagickMemory((size_t) length);
00960 if (pixels == (PixelPacket *) NULL)
00961 {
00962 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
00963 "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
00964 return(MagickFalse);
00965 }
00966 (void) ResetMagickMemory(pixels,0,(size_t) length);
00967 length=columns*sizeof(*pixels);
00968 offset=(MagickOffsetType) cache_info->columns*rows*sizeof(*pixels);
00969 q=clone_info->pixels+clone_info->columns*rows;
00970 for (y=0; y < (long) rows; y++)
00971 {
00972 offset-=cache_info->columns*sizeof(*pixels);
00973 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset,length,
00974 (unsigned char *) pixels);
00975 if ((MagickSizeType) count != length)
00976 break;
00977 q-=clone_info->columns;
00978 (void) CopyMagickMemory(q,pixels,(size_t) length);
00979 }
00980 if (y < (long) rows)
00981 {
00982 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
00983 ThrowFileException(exception,CacheError,"UnableToCloneCache",
00984 cache_info->cache_filename);
00985 return(MagickFalse);
00986 }
00987 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
00988 return(MagickTrue);
00989 }
00990
00991 static MagickBooleanType CloneMemoryToDiskPixelCache(CacheInfo *clone_info,
00992 CacheInfo *cache_info,ExceptionInfo *exception)
00993 {
00994 MagickOffsetType
00995 count,
00996 offset;
00997
00998 MagickSizeType
00999 length;
01000
01001 register long
01002 y;
01003
01004 register PixelPacket
01005 *__restrict p,
01006 *__restrict pixels;
01007
01008 unsigned long
01009 columns,
01010 rows;
01011
01012 if (cache_info->debug != MagickFalse)
01013 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => disk");
01014 if (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse)
01015 {
01016 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
01017 clone_info->cache_filename);
01018 return(MagickFalse);
01019 }
01020 columns=(unsigned long) MagickMin(clone_info->columns,cache_info->columns);
01021 rows=(unsigned long) MagickMin(clone_info->rows,cache_info->rows);
01022 if ((clone_info->active_index_channel != MagickFalse) &&
01023 (cache_info->active_index_channel != MagickFalse))
01024 {
01025 register IndexPacket
01026 *p,
01027 *indexes;
01028
01029
01030
01031
01032 length=MagickMax(clone_info->columns,cache_info->columns)*
01033 sizeof(*indexes);
01034 indexes=(IndexPacket *) AcquireMagickMemory((size_t) length);
01035 if (indexes == (IndexPacket *) NULL)
01036 {
01037 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
01038 "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
01039 return(MagickFalse);
01040 }
01041 (void) ResetMagickMemory(indexes,0,(size_t) length);
01042 length=columns*sizeof(*indexes);
01043 p=cache_info->indexes+cache_info->columns*rows;
01044 offset=(MagickOffsetType) clone_info->columns*clone_info->rows*
01045 sizeof(*pixels)+clone_info->columns*rows*sizeof(*indexes);
01046 for (y=0; y < (long) rows; y++)
01047 {
01048 p-=cache_info->columns;
01049 (void) CopyMagickMemory(indexes,p,(size_t) length);
01050 offset-=clone_info->columns*sizeof(*indexes);
01051 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
01052 (unsigned char *) indexes);
01053 if ((MagickSizeType) count != length)
01054 break;
01055 }
01056 if (y < (long) rows)
01057 {
01058 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
01059 ThrowFileException(exception,CacheError,"UnableToCloneCache",
01060 cache_info->cache_filename);
01061 return(MagickFalse);
01062 }
01063 if (clone_info->columns > cache_info->columns)
01064 {
01065 length=(clone_info->columns-cache_info->columns)*sizeof(*indexes);
01066 (void) ResetMagickMemory(indexes,0,(size_t) length);
01067 offset=(MagickOffsetType) clone_info->columns*clone_info->rows*
01068 sizeof(*pixels)+(clone_info->columns*rows+columns)*sizeof(*indexes);
01069 for (y=0; y < (long) rows; y++)
01070 {
01071 offset-=clone_info->columns*sizeof(*indexes);
01072 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,
01073 length,(unsigned char *) indexes);
01074 if ((MagickSizeType) count != length)
01075 break;
01076 }
01077 if (y < (long) rows)
01078 {
01079 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
01080 ThrowFileException(exception,CacheError,"UnableToCloneCache",
01081 cache_info->cache_filename);
01082 return(MagickFalse);
01083 }
01084 }
01085 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
01086 }
01087
01088
01089
01090 length=MagickMax(clone_info->columns,cache_info->columns)*sizeof(*pixels);
01091 pixels=(PixelPacket *) AcquireMagickMemory((size_t) length);
01092 if (pixels == (PixelPacket *) NULL)
01093 {
01094 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
01095 "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
01096 return(MagickFalse);
01097 }
01098 (void) ResetMagickMemory(pixels,0,(size_t) length);
01099 length=columns*sizeof(*pixels);
01100 p=cache_info->pixels+cache_info->columns*rows;
01101 offset=(MagickOffsetType) clone_info->columns*rows*sizeof(*pixels);
01102 for (y=0; y < (long) rows; y++)
01103 {
01104 p-=cache_info->columns;
01105 (void) CopyMagickMemory(pixels,p,(size_t) length);
01106 offset-=clone_info->columns*sizeof(*pixels);
01107 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
01108 (unsigned char *) pixels);
01109 if ((MagickSizeType) count != length)
01110 break;
01111 }
01112 if (y < (long) rows)
01113 {
01114 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
01115 ThrowFileException(exception,CacheError,"UnableToCloneCache",
01116 cache_info->cache_filename);
01117 return(MagickFalse);
01118 }
01119 if (clone_info->columns > cache_info->columns)
01120 {
01121 offset=(MagickOffsetType) (clone_info->columns*rows+columns)*
01122 sizeof(*pixels);
01123 length=(clone_info->columns-cache_info->columns)*sizeof(*pixels);
01124 (void) ResetMagickMemory(pixels,0,(size_t) length);
01125 for (y=0; y < (long) rows; y++)
01126 {
01127 offset-=clone_info->columns*sizeof(*pixels);
01128 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
01129 (unsigned char *) pixels);
01130 if ((MagickSizeType) count != length)
01131 break;
01132 }
01133 if (y < (long) rows)
01134 {
01135 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
01136 ThrowFileException(exception,CacheError,"UnableToCloneCache",
01137 cache_info->cache_filename);
01138 return(MagickFalse);
01139 }
01140 }
01141 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
01142 return(MagickTrue);
01143 }
01144
01145 static MagickBooleanType CloneMemoryToMemoryPixelCache(CacheInfo *clone_info,
01146 CacheInfo *cache_info,ExceptionInfo *magick_unused(exception))
01147 {
01148 register long
01149 y;
01150
01151 register PixelPacket
01152 *__restrict pixels,
01153 *__restrict source_pixels;
01154
01155 size_t
01156 length;
01157
01158 unsigned long
01159 columns,
01160 rows;
01161
01162 if (cache_info->debug != MagickFalse)
01163 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => memory");
01164 columns=(unsigned long) MagickMin(clone_info->columns,cache_info->columns);
01165 rows=(unsigned long) MagickMin(clone_info->rows,cache_info->rows);
01166 if ((clone_info->active_index_channel != MagickFalse) &&
01167 (cache_info->active_index_channel != MagickFalse))
01168 {
01169 register IndexPacket
01170 *indexes,
01171 *source_indexes;
01172
01173
01174
01175
01176 length=columns*sizeof(*indexes);
01177 if (clone_info->columns == cache_info->columns)
01178 (void) CopyMagickMemory(clone_info->indexes,cache_info->indexes,
01179 length*rows);
01180 else
01181 {
01182 source_indexes=cache_info->indexes+cache_info->columns*rows;
01183 indexes=clone_info->indexes+clone_info->columns*rows;
01184 for (y=0; y < (long) rows; y++)
01185 {
01186 source_indexes-=cache_info->columns;
01187 indexes-=clone_info->columns;
01188 (void) CopyMagickMemory(indexes,source_indexes,length);
01189 }
01190 if (clone_info->columns > cache_info->columns)
01191 {
01192 length=(clone_info->columns-cache_info->columns)*
01193 sizeof(*indexes);
01194 indexes=clone_info->indexes+clone_info->columns*rows+
01195 cache_info->columns;
01196 for (y=0; y < (long) rows; y++)
01197 {
01198 indexes-=clone_info->columns;
01199 (void) ResetMagickMemory(indexes,0,length);
01200 }
01201 }
01202 }
01203 }
01204
01205
01206
01207 length=columns*sizeof(*pixels);
01208 if (clone_info->columns == cache_info->columns)
01209 (void) CopyMagickMemory(clone_info->pixels,cache_info->pixels,length*rows);
01210 else
01211 {
01212 source_pixels=cache_info->pixels+cache_info->columns*rows;
01213 pixels=clone_info->pixels+clone_info->columns*rows;
01214 for (y=0; y < (long) rows; y++)
01215 {
01216 source_pixels-=cache_info->columns;
01217 pixels-=clone_info->columns;
01218 (void) CopyMagickMemory(pixels,source_pixels,length);
01219 }
01220 if (clone_info->columns > cache_info->columns)
01221 {
01222 length=(clone_info->columns-cache_info->columns)*sizeof(*pixels);
01223 pixels=clone_info->pixels+clone_info->columns*rows+
01224 cache_info->columns;
01225 for (y=0; y < (long) rows; y++)
01226 {
01227 pixels-=clone_info->columns;
01228 (void) ResetMagickMemory(pixels,0,length);
01229 }
01230 }
01231 }
01232 return(MagickTrue);
01233 }
01234
01235 static MagickBooleanType ClonePixelCache(CacheInfo *clone_info,
01236 CacheInfo *cache_info,ExceptionInfo *exception)
01237 {
01238 if ((clone_info->type != DiskCache) && (cache_info->type != DiskCache))
01239 return(CloneMemoryToMemoryPixelCache(clone_info,cache_info,exception));
01240 if ((clone_info->type == DiskCache) && (cache_info->type == DiskCache))
01241 return(CloneDiskToDiskPixelCache(clone_info,cache_info,exception));
01242 if (cache_info->type == DiskCache)
01243 return(CloneDiskToMemoryPixelCache(clone_info,cache_info,exception));
01244 return(CloneMemoryToDiskPixelCache(clone_info,cache_info,exception));
01245 }
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272 MagickExport void ClonePixelCacheMethods(Cache clone,const Cache cache)
01273 {
01274 CacheInfo
01275 *cache_info,
01276 *source_info;
01277
01278 assert(clone != (Cache) NULL);
01279 source_info=(CacheInfo *) clone;
01280 assert(source_info->signature == MagickSignature);
01281 if (source_info->debug != MagickFalse)
01282 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
01283 source_info->filename);
01284 assert(cache != (Cache) NULL);
01285 cache_info=(CacheInfo *) cache;
01286 assert(cache_info->signature == MagickSignature);
01287 source_info->methods=cache_info->methods;
01288 }
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312 MagickExport void DestroyImagePixels(Image *image)
01313 {
01314 CacheInfo
01315 *cache_info;
01316
01317 assert(image != (const Image *) NULL);
01318 assert(image->signature == MagickSignature);
01319 if (image->debug != MagickFalse)
01320 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01321 assert(image->cache != (Cache) NULL);
01322 cache_info=(CacheInfo *) image->cache;
01323 assert(cache_info->signature == MagickSignature);
01324 if (cache_info->methods.destroy_pixel_handler == (DestroyPixelHandler) NULL)
01325 return;
01326 cache_info->methods.destroy_pixel_handler(image);
01327 }
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351 static void DestroyPixelCache(Image *image)
01352 {
01353 assert(image != (Image *) NULL);
01354 assert(image->signature == MagickSignature);
01355 if (image->debug != MagickFalse)
01356 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01357 if (image->cache == (void *) NULL)
01358 return;
01359 image->cache=DestroyPixelCacheInfo(image->cache);
01360 }
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385 static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
01386 {
01387 switch (cache_info->type)
01388 {
01389 case MemoryCache:
01390 {
01391 if (cache_info->mapped == MagickFalse)
01392 cache_info->pixels=(PixelPacket *) RelinquishMagickMemory(
01393 cache_info->pixels);
01394 else
01395 cache_info->pixels=(PixelPacket *) UnmapBlob(cache_info->pixels,
01396 (size_t) cache_info->length);
01397 RelinquishMagickResource(MemoryResource,cache_info->length);
01398 break;
01399 }
01400 case MapCache:
01401 {
01402 cache_info->pixels=(PixelPacket *) UnmapBlob(cache_info->pixels,(size_t)
01403 cache_info->length);
01404 RelinquishMagickResource(MapResource,cache_info->length);
01405 }
01406 case DiskCache:
01407 {
01408 if (cache_info->file != -1)
01409 (void) ClosePixelCacheOnDisk(cache_info);
01410 RelinquishMagickResource(DiskResource,cache_info->length);
01411 break;
01412 }
01413 default:
01414 break;
01415 }
01416 cache_info->type=UndefinedCache;
01417 cache_info->mapped=MagickFalse;
01418 cache_info->indexes=(IndexPacket *) NULL;
01419 }
01420
01421 MagickExport Cache DestroyPixelCacheInfo(Cache cache)
01422 {
01423 CacheInfo
01424 *cache_info;
01425
01426 CacheType
01427 type;
01428
01429 assert(cache != (Cache) NULL);
01430 cache_info=(CacheInfo *) cache;
01431 assert(cache_info->signature == MagickSignature);
01432 if (cache_info->debug != MagickFalse)
01433 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
01434 cache_info->filename);
01435 (void) LockSemaphoreInfo(cache_info->semaphore);
01436 cache_info->reference_count--;
01437 if (cache_info->reference_count != 0)
01438 {
01439 (void) UnlockSemaphoreInfo(cache_info->semaphore);
01440 return((Cache) NULL);
01441 }
01442 (void) UnlockSemaphoreInfo(cache_info->semaphore);
01443 if (cache_resources != (SplayTreeInfo *) NULL)
01444 (void) DeleteNodeByValueFromSplayTree(cache_resources,cache_info);
01445 type=cache_info->type;
01446 RelinquishPixelCachePixels(cache_info);
01447 if ((type == MapCache) || (type == DiskCache))
01448 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
01449 *cache_info->cache_filename='\0';
01450 if (cache_info->nexus_info != (NexusInfo **) NULL)
01451 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
01452 cache_info->number_threads);
01453 if (cache_info->debug != MagickFalse)
01454 {
01455 char
01456 message[MaxTextExtent];
01457
01458 (void) FormatMagickString(message,MaxTextExtent,"destroy %s",
01459 cache_info->filename);
01460 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
01461 }
01462 if (cache_info->random_info != (RandomInfo *) NULL)
01463 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
01464 cache_info->signature=(~MagickSignature);
01465 if (cache_info->disk_semaphore != (SemaphoreInfo *) NULL)
01466 DestroySemaphoreInfo(&cache_info->disk_semaphore);
01467 if (cache_info->semaphore != (SemaphoreInfo *) NULL)
01468 DestroySemaphoreInfo(&cache_info->semaphore);
01469 cache_info=(CacheInfo *) RelinquishMagickMemory(cache_info);
01470 cache=(Cache) NULL;
01471 return(cache);
01472 }
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500 static inline void RelinquishCacheNexusPixels(NexusInfo *nexus_info)
01501 {
01502 if (nexus_info->mapped == MagickFalse)
01503 (void) RelinquishMagickMemory(nexus_info->cache);
01504 else
01505 (void) UnmapBlob(nexus_info->cache,(size_t) nexus_info->length);
01506 nexus_info->cache=(PixelPacket *) NULL;
01507 nexus_info->pixels=(PixelPacket *) NULL;
01508 nexus_info->indexes=(IndexPacket *) NULL;
01509 nexus_info->length=0;
01510 nexus_info->mapped=MagickFalse;
01511 }
01512
01513 MagickExport NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
01514 const unsigned long number_threads)
01515 {
01516 register long
01517 i;
01518
01519 assert(nexus_info != (NexusInfo **) NULL);
01520 for (i=0; i < (long) number_threads; i++)
01521 {
01522 if (nexus_info[i]->cache != (PixelPacket *) NULL)
01523 RelinquishCacheNexusPixels(nexus_info[i]);
01524 nexus_info[i]->signature=(~MagickSignature);
01525 nexus_info[i]=(NexusInfo *) RelinquishMagickMemory(nexus_info[i]);
01526 }
01527 return((NexusInfo **) RelinquishMagickMemory(nexus_info));
01528 }
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548 MagickExport void DestroyPixelCacheResources(void)
01549 {
01550 AcquireSemaphoreInfo(&cache_semaphore);
01551 if (cache_resources != (SplayTreeInfo *) NULL)
01552 cache_resources=DestroySplayTree(cache_resources);
01553 instantiate_cache=MagickFalse;
01554 RelinquishSemaphoreInfo(cache_semaphore);
01555 DestroySemaphoreInfo(&cache_semaphore);
01556 }
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581 static IndexPacket *GetAuthenticIndexesFromCache(const Image *image)
01582 {
01583 CacheInfo
01584 *cache_info;
01585
01586 IndexPacket
01587 *indexes;
01588
01589 long
01590 id;
01591
01592 if (image->debug != MagickFalse)
01593 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01594 cache_info=(CacheInfo *) image->cache;
01595 id=GetOpenMPThreadId();
01596 assert(id < (long) cache_info->number_threads);
01597 indexes=GetPixelCacheNexusIndexes(image->cache,cache_info->nexus_info[id]);
01598 return(indexes);
01599 }
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626 MagickExport IndexPacket *GetAuthenticIndexQueue(const Image *image)
01627 {
01628 CacheInfo
01629 *cache_info;
01630
01631 assert(image != (const Image *) NULL);
01632 assert(image->signature == MagickSignature);
01633 if (image->debug != MagickFalse)
01634 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01635 assert(image->cache != (Cache) NULL);
01636 cache_info=(CacheInfo *) image->cache;
01637 assert(cache_info->signature == MagickSignature);
01638 if (cache_info->methods.get_authentic_indexes_from_handler ==
01639 (GetAuthenticIndexesFromHandler) NULL)
01640 return((IndexPacket *) NULL);
01641 return(cache_info->methods.get_authentic_indexes_from_handler(image));
01642 }
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679 static inline MagickBooleanType IsNexusInCore(const CacheInfo *cache_info,
01680 NexusInfo *nexus_info)
01681 {
01682 MagickOffsetType
01683 offset;
01684
01685 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
01686 nexus_info->region.x;
01687 if (nexus_info->pixels != (cache_info->pixels+offset))
01688 return(MagickFalse);
01689 return(MagickTrue);
01690 }
01691
01692 MagickExport PixelPacket *GetAuthenticPixelCacheNexus(Image *image,const long x,
01693 const long y,const unsigned long columns,const unsigned long rows,
01694 NexusInfo *nexus_info,ExceptionInfo *exception)
01695 {
01696 CacheInfo
01697 *cache_info;
01698
01699 PixelPacket
01700 *pixels;
01701
01702
01703
01704
01705 assert(image != (Image *) NULL);
01706 assert(image->signature == MagickSignature);
01707 if (image->debug != MagickFalse)
01708 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01709 pixels=QueueAuthenticNexus(image,x,y,columns,rows,nexus_info,exception);
01710 if (pixels == (PixelPacket *) NULL)
01711 return((PixelPacket *) NULL);
01712 cache_info=(CacheInfo *) image->cache;
01713 assert(cache_info->signature == MagickSignature);
01714 if (IsNexusInCore(cache_info,nexus_info) != MagickFalse)
01715 return(pixels);
01716 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
01717 return((PixelPacket *) NULL);
01718 if (cache_info->active_index_channel != MagickFalse)
01719 if (ReadPixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse)
01720 return((PixelPacket *) NULL);
01721 return(pixels);
01722 }
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747 static PixelPacket *GetAuthenticPixelsFromCache(const Image *image)
01748 {
01749 CacheInfo
01750 *cache_info;
01751
01752 long
01753 id;
01754
01755 PixelPacket
01756 *pixels;
01757
01758 if (image->debug != MagickFalse)
01759 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01760 cache_info=(CacheInfo *) image->cache;
01761 id=GetOpenMPThreadId();
01762 assert(id < (long) cache_info->number_threads);
01763 pixels=GetPixelCacheNexusPixels(image->cache,cache_info->nexus_info[id]);
01764 return(pixels);
01765 }
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790 MagickExport PixelPacket *GetAuthenticPixelQueue(const Image *image)
01791 {
01792 CacheInfo
01793 *cache_info;
01794
01795 assert(image != (const Image *) NULL);
01796 assert(image->signature == MagickSignature);
01797 if (image->debug != MagickFalse)
01798 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01799 assert(image->cache != (Cache) NULL);
01800 cache_info=(CacheInfo *) image->cache;
01801 assert(cache_info->signature == MagickSignature);
01802 if (cache_info->methods.get_authentic_pixels_from_handler ==
01803 (GetAuthenticPixelsFromHandler) NULL)
01804 return((PixelPacket *) NULL);
01805 return(cache_info->methods.get_authentic_pixels_from_handler(image));
01806 }
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854 MagickExport PixelPacket *GetAuthenticPixels(Image *image,const long x,
01855 const long y,const unsigned long columns,const unsigned long rows,
01856 ExceptionInfo *exception)
01857 {
01858 CacheInfo
01859 *cache_info;
01860
01861 PixelPacket
01862 *pixels;
01863
01864 assert(image != (Image *) NULL);
01865 assert(image->signature == MagickSignature);
01866 if (image->debug != MagickFalse)
01867 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01868 assert(image->cache != (Cache) NULL);
01869 cache_info=(CacheInfo *) image->cache;
01870 assert(cache_info->signature == MagickSignature);
01871 if (cache_info->methods.get_authentic_pixels_handler ==
01872 (GetAuthenticPixelsHandler) NULL)
01873 return((PixelPacket *) NULL);
01874 pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
01875 rows,exception);
01876 return(pixels);
01877 }
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910 static PixelPacket *GetAuthenticPixelsCache(Image *image,const long x,
01911 const long y,const unsigned long columns,const unsigned long rows,
01912 ExceptionInfo *exception)
01913 {
01914 CacheInfo
01915 *cache_info;
01916
01917 long
01918 id;
01919
01920 PixelPacket
01921 *pixels;
01922
01923 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
01924 if (cache_info == (Cache) NULL)
01925 return((PixelPacket *) NULL);
01926 id=GetOpenMPThreadId();
01927 assert(id < (long) cache_info->number_threads);
01928 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
01929 cache_info->nexus_info[id],exception);
01930 return(pixels);
01931 }
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956 MagickExport MagickSizeType GetImageExtent(const Image *image)
01957 {
01958 CacheInfo
01959 *cache_info;
01960
01961 long
01962 id;
01963
01964 MagickSizeType
01965 extent;
01966
01967 assert(image != (Image *) NULL);
01968 assert(image->signature == MagickSignature);
01969 if (image->debug != MagickFalse)
01970 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01971 assert(image->cache != (Cache) NULL);
01972 cache_info=(CacheInfo *) image->cache;
01973 assert(cache_info->signature == MagickSignature);
01974 id=GetOpenMPThreadId();
01975 assert(id < (long) cache_info->number_threads);
01976 extent=GetPixelCacheNexusExtent(image->cache,cache_info->nexus_info[id]);
01977 return(extent);
01978 }
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010 static inline MagickBooleanType ValidatePixelCacheMorphology(const Image *image)
02011 {
02012 CacheInfo
02013 *cache_info;
02014
02015
02016
02017
02018 cache_info=(CacheInfo *) image->cache;
02019 if ((image->storage_class != cache_info->storage_class) ||
02020 (image->colorspace != cache_info->colorspace) ||
02021 (image->columns != cache_info->columns) ||
02022 (image->rows != cache_info->rows) ||
02023 (cache_info->nexus_info == (NexusInfo **) NULL) ||
02024 (cache_info->number_threads < GetOpenMPMaximumThreads()))
02025 return(MagickFalse);
02026 return(MagickTrue);
02027 }
02028
02029 MagickExport Cache GetImagePixelCache(Image *image,
02030 const MagickBooleanType clone,ExceptionInfo *exception)
02031 {
02032 CacheInfo
02033 *cache_info;
02034
02035 MagickSizeType
02036 time_limit;
02037
02038 MagickBooleanType
02039 status;
02040
02041 if (image->debug != MagickFalse)
02042 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02043 status=MagickTrue;
02044 (void) LockSemaphoreInfo(image->semaphore);
02045 time_limit=GetMagickResourceLimit(TimeResource);
02046 if (cache_timer == 0)
02047 cache_timer=time((time_t *) NULL);
02048 if ((time_limit != MagickResourceInfinity) &&
02049 ((time((time_t *) NULL)-cache_timer) >= (MagickOffsetType) time_limit))
02050 ThrowFatalException(ResourceLimitFatalError,"TimeLimitExceeded");
02051 assert(image->cache != (Cache) NULL);
02052 cache_info=(CacheInfo *) image->cache;
02053 (void) LockSemaphoreInfo(cache_info->semaphore);
02054 if (cache_info->reference_count > 1)
02055 {
02056 Image
02057 clone_image;
02058
02059 CacheInfo
02060 *clone_info;
02061
02062
02063
02064
02065 clone_image=(*image);
02066 clone_image.cache=AcquirePixelCacheInfo(cache_info->number_threads);
02067 clone_info=(CacheInfo *) clone_image.cache;
02068 status=ClonePixelCacheNexus(cache_info,clone_info,exception);
02069 if (status != MagickFalse)
02070 {
02071 status=OpenPixelCache(&clone_image,IOMode,exception);
02072 if (status != MagickFalse)
02073 {
02074 if (clone != MagickFalse)
02075 status=ClonePixelCache(clone_info,cache_info,exception);
02076 if (status != MagickFalse)
02077 {
02078 cache_info->reference_count--;
02079 image->cache=clone_image.cache;
02080 (void) SetPixelCacheVirtualMethod(image,
02081 cache_info->virtual_pixel_method);
02082 }
02083 }
02084 }
02085 }
02086 (void) UnlockSemaphoreInfo(cache_info->semaphore);
02087 if (status != MagickFalse)
02088 {
02089
02090
02091
02092 image->taint=MagickTrue;
02093 image->type=UndefinedType;
02094 if (image->colorspace == GRAYColorspace)
02095 image->colorspace=RGBColorspace;
02096 if (ValidatePixelCacheMorphology(image) == MagickFalse)
02097 status=OpenPixelCache(image,IOMode,exception);
02098 }
02099 (void) UnlockSemaphoreInfo(image->semaphore);
02100 if (status == MagickFalse)
02101 return((Cache) NULL);
02102 return(image->cache);
02103 }
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135 MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,const long x,
02136 const long y,PixelPacket *pixel,ExceptionInfo *exception)
02137 {
02138 CacheInfo
02139 *cache_info;
02140
02141 GetOneAuthenticPixelFromHandler
02142 get_one_authentic_pixel_from_handler;
02143
02144 MagickBooleanType
02145 status;
02146
02147 assert(image != (Image *) NULL);
02148 assert(image->signature == MagickSignature);
02149 if (image->debug != MagickFalse)
02150 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02151 assert(image->cache != (Cache) NULL);
02152 cache_info=(CacheInfo *) image->cache;
02153 assert(cache_info->signature == MagickSignature);
02154 *pixel=image->background_color;
02155 get_one_authentic_pixel_from_handler=
02156 cache_info->methods.get_one_authentic_pixel_from_handler;
02157 if (get_one_authentic_pixel_from_handler ==
02158 (GetOneAuthenticPixelFromHandler) NULL)
02159 return(MagickFalse);
02160 status=cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,
02161 pixel,exception);
02162 return(status);
02163 }
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195 static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
02196 const long x,const long y,PixelPacket *pixel,ExceptionInfo *exception)
02197 {
02198 PixelPacket
02199 *pixels;
02200
02201 if (image->debug != MagickFalse)
02202 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02203 *pixel=image->background_color;
02204 pixels=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
02205 if (pixels == (PixelPacket *) NULL)
02206 return(MagickFalse);
02207 *pixel=(*pixels);
02208 return(MagickTrue);
02209 }
02210
02211
02212
02213
02214
02215
02216
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243 MagickExport MagickBooleanType GetOneVirtualMagickPixel(const Image *image,
02244 const long x,const long y,MagickPixelPacket *pixel,ExceptionInfo *exception)
02245 {
02246 CacheInfo
02247 *cache_info;
02248
02249 register const IndexPacket
02250 *indexes;
02251
02252 register const PixelPacket
02253 *p;
02254
02255 assert(image != (const Image *) NULL);
02256 assert(image->signature == MagickSignature);
02257 assert(image->cache != (Cache) NULL);
02258 cache_info=(CacheInfo *) image->cache;
02259 assert(cache_info->signature == MagickSignature);
02260 GetMagickPixelPacket(image,pixel);
02261 p=GetVirtualPixelCache(image,GetPixelCacheVirtualMethod(image),x,y,1,1,
02262 exception);
02263 if (p == (const PixelPacket *) NULL)
02264 return(MagickFalse);
02265 indexes=GetVirtualIndexQueue(image);
02266 SetMagickPixelPacket(image,p,indexes,pixel);
02267 return(MagickTrue);
02268 }
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305 MagickExport MagickBooleanType GetOneVirtualMethodPixel(const Image *image,
02306 const VirtualPixelMethod virtual_pixel_method,const long x,const long y,
02307 PixelPacket *pixel,ExceptionInfo *exception)
02308 {
02309 GetOneVirtualPixelFromHandler
02310 get_one_virtual_pixel_from_handler;
02311
02312 CacheInfo
02313 *cache_info;
02314
02315 MagickBooleanType
02316 status;
02317
02318 assert(image != (const Image *) NULL);
02319 assert(image->signature == MagickSignature);
02320 assert(image->cache != (Cache) NULL);
02321 cache_info=(CacheInfo *) image->cache;
02322 assert(cache_info->signature == MagickSignature);
02323 *pixel=image->background_color;
02324 get_one_virtual_pixel_from_handler=
02325 cache_info->methods.get_one_virtual_pixel_from_handler;
02326 if (get_one_virtual_pixel_from_handler ==
02327 (GetOneVirtualPixelFromHandler) NULL)
02328 return(MagickFalse);
02329 status=get_one_virtual_pixel_from_handler(image,virtual_pixel_method,x,y,
02330 pixel,exception);
02331 return(status);
02332 }
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365 MagickExport MagickBooleanType GetOneVirtualPixel(const Image *image,
02366 const long x,const long y,PixelPacket *pixel,ExceptionInfo *exception)
02367 {
02368 GetOneVirtualPixelFromHandler
02369 get_one_virtual_pixel_from_handler;
02370
02371 CacheInfo
02372 *cache_info;
02373
02374 MagickBooleanType
02375 status;
02376
02377 assert(image != (const Image *) NULL);
02378 assert(image->signature == MagickSignature);
02379 assert(image->cache != (Cache) NULL);
02380 cache_info=(CacheInfo *) image->cache;
02381 assert(cache_info->signature == MagickSignature);
02382 *pixel=image->background_color;
02383 get_one_virtual_pixel_from_handler=
02384 cache_info->methods.get_one_virtual_pixel_from_handler;
02385 if (get_one_virtual_pixel_from_handler ==
02386 (GetOneVirtualPixelFromHandler) NULL)
02387 return(MagickFalse);
02388 status=get_one_virtual_pixel_from_handler(image,GetPixelCacheVirtualMethod(
02389 image),x,y,pixel,exception);
02390 return(status);
02391 }
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427 static MagickBooleanType GetOneVirtualPixelFromCache(const Image *image,
02428 const VirtualPixelMethod virtual_pixel_method,const long x,const long y,
02429 PixelPacket *pixel,ExceptionInfo *exception)
02430 {
02431 const PixelPacket
02432 *pixels;
02433
02434 *pixel=image->background_color;
02435 pixels=GetVirtualPixelCache(image,virtual_pixel_method,x,y,1UL,1UL,exception);
02436 if (pixels == (const PixelPacket *) NULL)
02437 return(MagickFalse);
02438 *pixel=(*pixels);
02439 return(MagickTrue);
02440 }
02441
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464 MagickExport ColorspaceType GetPixelCacheColorspace(const Cache cache)
02465 {
02466 CacheInfo
02467 *cache_info;
02468
02469 assert(cache != (Cache) NULL);
02470 cache_info=(CacheInfo *) cache;
02471 assert(cache_info->signature == MagickSignature);
02472 if (cache_info->debug != MagickFalse)
02473 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
02474 cache_info->filename);
02475 return(cache_info->colorspace);
02476 }
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500 MagickExport void GetPixelCacheMethods(CacheMethods *cache_methods)
02501 {
02502 assert(cache_methods != (CacheMethods *) NULL);
02503 (void) ResetMagickMemory(cache_methods,0,sizeof(*cache_methods));
02504 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
02505 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
02506 cache_methods->get_virtual_indexes_from_handler=GetVirtualIndexesFromCache;
02507 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
02508 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
02509 cache_methods->get_authentic_indexes_from_handler=
02510 GetAuthenticIndexesFromCache;
02511 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
02512 cache_methods->get_one_authentic_pixel_from_handler=
02513 GetOneAuthenticPixelFromCache;
02514 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
02515 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
02516 cache_methods->destroy_pixel_handler=DestroyPixelCache;
02517 }
02518
02519
02520
02521
02522
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532
02533
02534
02535
02536
02537
02538
02539
02540
02541
02542
02543 MagickExport MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
02544 NexusInfo *nexus_info)
02545 {
02546 CacheInfo
02547 *cache_info;
02548
02549 MagickSizeType
02550 extent;
02551
02552 if (cache == (Cache) NULL)
02553 return(0);
02554 cache_info=(CacheInfo *) cache;
02555 assert(cache_info->signature == MagickSignature);
02556 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
02557 if (extent == 0)
02558 return((MagickSizeType) cache_info->columns*cache_info->rows);
02559 return(extent);
02560 }
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
02586
02587
02588 MagickExport IndexPacket *GetPixelCacheNexusIndexes(const Cache cache,
02589 NexusInfo *nexus_info)
02590 {
02591 CacheInfo
02592 *cache_info;
02593
02594 if (cache == (Cache) NULL)
02595 return((IndexPacket *) NULL);
02596 cache_info=(CacheInfo *) cache;
02597 assert(cache_info->signature == MagickSignature);
02598 if (cache_info->storage_class == UndefinedClass)
02599 return((IndexPacket *) NULL);
02600 return(nexus_info->indexes);
02601 }
02602
02603
02604
02605
02606
02607
02608
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629 MagickExport PixelPacket *GetPixelCacheNexusPixels(const Cache cache,
02630 NexusInfo *nexus_info)
02631 {
02632 CacheInfo
02633 *cache_info;
02634
02635 if (cache == (Cache) NULL)
02636 return((PixelPacket *) NULL);
02637 cache_info=(CacheInfo *) cache;
02638 assert(cache_info->signature == MagickSignature);
02639 if (cache_info->debug != MagickFalse)
02640 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
02641 cache_info->filename);
02642 if (cache_info->storage_class == UndefinedClass)
02643 return((PixelPacket *) NULL);
02644 return(nexus_info->pixels);
02645 }
02646
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665
02666
02667
02668
02669
02670
02671 MagickExport ClassType GetPixelCacheStorageClass(const Cache cache)
02672 {
02673 CacheInfo
02674 *cache_info;
02675
02676 assert(cache != (Cache) NULL);
02677 cache_info=(CacheInfo *) cache;
02678 assert(cache_info->signature == MagickSignature);
02679 if (cache_info->debug != MagickFalse)
02680 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
02681 cache_info->filename);
02682 return(cache_info->storage_class);
02683 }
02684
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703
02704
02705
02706
02707
02708
02709 MagickExport VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
02710 {
02711 CacheInfo
02712 *cache_info;
02713
02714 assert(image != (Image *) NULL);
02715 assert(image->signature == MagickSignature);
02716 if (image->debug != MagickFalse)
02717 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02718 assert(image->cache != (Cache) NULL);
02719 cache_info=(CacheInfo *) image->cache;
02720 assert(cache_info->signature == MagickSignature);
02721 return(cache_info->virtual_pixel_method);
02722 }
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747 static const IndexPacket *GetVirtualIndexesFromCache(const Image *image)
02748 {
02749 CacheInfo
02750 *cache_info;
02751
02752 const IndexPacket
02753 *indexes;
02754
02755 long
02756 id;
02757
02758 if (image->debug != MagickFalse)
02759 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02760 cache_info=(CacheInfo *) image->cache;
02761 id=GetOpenMPThreadId();
02762 assert(id < (long) cache_info->number_threads);
02763 indexes=GetVirtualIndexesFromNexus(image->cache,cache_info->nexus_info[id]);
02764 return(indexes);
02765 }
02766
02767
02768
02769
02770
02771
02772
02773
02774
02775
02776
02777
02778
02779
02780
02781
02782
02783
02784
02785
02786
02787
02788
02789
02790
02791
02792
02793 MagickExport const IndexPacket *GetVirtualIndexesFromNexus(const Cache cache,
02794 NexusInfo *nexus_info)
02795 {
02796 CacheInfo
02797 *cache_info;
02798
02799 if (cache == (Cache) NULL)
02800 return((IndexPacket *) NULL);
02801 cache_info=(CacheInfo *) cache;
02802 assert(cache_info->signature == MagickSignature);
02803 if (cache_info->storage_class == UndefinedClass)
02804 return((IndexPacket *) NULL);
02805 return(nexus_info->indexes);
02806 }
02807
02808
02809
02810
02811
02812
02813
02814
02815
02816
02817
02818
02819
02820
02821
02822
02823
02824
02825
02826
02827
02828
02829
02830
02831
02832
02833 MagickExport const IndexPacket *GetVirtualIndexQueue(const Image *image)
02834 {
02835 CacheInfo
02836 *cache_info;
02837
02838 assert(image != (const Image *) NULL);
02839 assert(image->signature == MagickSignature);
02840 if (image->debug != MagickFalse)
02841 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02842 assert(image->cache != (Cache) NULL);
02843 cache_info=(CacheInfo *) image->cache;
02844 assert(cache_info->signature == MagickSignature);
02845 if (cache_info->methods.get_virtual_indexes_from_handler ==
02846 (GetVirtualIndexesFromHandler) NULL)
02847 return((IndexPacket *) NULL);
02848 return(cache_info->methods.get_virtual_indexes_from_handler(image));
02849 }
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871
02872
02873
02874
02875
02876
02877
02878
02879
02880
02881
02882
02883
02884
02885
02886
02887
02888 static long
02889 DitherMatrix[64] =
02890 {
02891 0, 48, 12, 60, 3, 51, 15, 63,
02892 32, 16, 44, 28, 35, 19, 47, 31,
02893 8, 56, 4, 52, 11, 59, 7, 55,
02894 40, 24, 36, 20, 43, 27, 39, 23,
02895 2, 50, 14, 62, 1, 49, 13, 61,
02896 34, 18, 46, 30, 33, 17, 45, 29,
02897 10, 58, 6, 54, 9, 57, 5, 53,
02898 42, 26, 38, 22, 41, 25, 37, 21
02899 };
02900
02901 static inline long DitherX(const unsigned long columns,const long x)
02902 {
02903 long
02904 index;
02905
02906 index=x+DitherMatrix[x & 0x07]-32L;
02907 if (index < 0L)
02908 return(0L);
02909 if (index >= (long) columns)
02910 return((long) columns-1L);
02911 return(index);
02912 }
02913
02914 static inline long DitherY(const unsigned long rows,const long y)
02915 {
02916 long
02917 index;
02918
02919 index=y+DitherMatrix[y & 0x07]-32L;
02920 if (index < 0L)
02921 return(0L);
02922 if (index >= (long) rows)
02923 return((long) rows-1L);
02924 return(index);
02925 }
02926
02927 static inline long EdgeX(const unsigned long columns,const long x)
02928 {
02929 if (x < 0L)
02930 return(0L);
02931 if (x >= (long) columns)
02932 return((long) columns-1L);
02933 return(x);
02934 }
02935
02936 static inline long EdgeY(const unsigned long rows,const long y)
02937 {
02938 if (y < 0L)
02939 return(0L);
02940 if (y >= (long) rows)
02941 return((long) rows-1L);
02942 return(y);
02943 }
02944
02945 static inline long RandomX(const unsigned long columns,RandomInfo *random_info)
02946 {
02947 return((long) (columns*GetPseudoRandomValue(random_info)));
02948 }
02949
02950 static inline long RandomY(const unsigned long rows,RandomInfo *random_info)
02951 {
02952 return((long) (rows*GetPseudoRandomValue(random_info)));
02953 }
02954
02955
02956
02957
02958
02959
02960
02961
02962 static inline MagickModulo VirtualPixelModulo(const long offset,
02963 const unsigned long extent)
02964 {
02965 MagickModulo
02966 modulo;
02967
02968 modulo.quotient=offset/(long) extent;
02969 if (offset < 0L)
02970 modulo.quotient--;
02971 modulo.remainder=offset-modulo.quotient*(long) extent;
02972 return(modulo);
02973 }
02974
02975 MagickExport const PixelPacket *GetVirtualPixelsFromNexus(const Image *image,
02976 const VirtualPixelMethod virtual_pixel_method,const long x,const long y,
02977 const unsigned long columns,const unsigned long rows,NexusInfo *nexus_info,
02978 ExceptionInfo *exception)
02979 {
02980 CacheInfo
02981 *cache_info;
02982
02983 MagickOffsetType
02984 offset;
02985
02986 MagickSizeType
02987 length,
02988 number_pixels;
02989
02990 NexusInfo
02991 **virtual_nexus;
02992
02993 PixelPacket
02994 *pixels,
02995 virtual_pixel;
02996
02997 RectangleInfo
02998 region;
02999
03000 register const IndexPacket
03001 *__restrict nexus_indexes;
03002
03003 register const PixelPacket
03004 *__restrict p;
03005
03006 register IndexPacket
03007 *__restrict indexes;
03008
03009 register long
03010 u,
03011 v;
03012
03013 register PixelPacket
03014 *__restrict q;
03015
03016
03017
03018
03019 if (image->debug != MagickFalse)
03020 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03021 cache_info=(CacheInfo *) image->cache;
03022 if (cache_info->type == UndefinedCache)
03023 return((const PixelPacket *) NULL);
03024 region.x=x;
03025 region.y=y;
03026 region.width=columns;
03027 region.height=rows;
03028 pixels=SetPixelCacheNexusPixels(image,®ion,nexus_info,exception);
03029 if (pixels == (PixelPacket *) NULL)
03030 return((const PixelPacket *) NULL);
03031 offset=(MagickOffsetType) region.y*cache_info->columns+region.x;
03032 length=(MagickSizeType) (region.height-1)*cache_info->columns+region.width-1;
03033 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
03034 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
03035 if ((x >= 0) && ((long) (x+columns) <= (long) cache_info->columns) &&
03036 (y >= 0) && ((long) (y+rows) <= (long) cache_info->rows))
03037 {
03038 MagickBooleanType
03039 status;
03040
03041
03042
03043
03044 if (IsNexusInCore(cache_info,nexus_info) != MagickFalse)
03045 return(pixels);
03046 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
03047 if (status == MagickFalse)
03048 return((const PixelPacket *) NULL);
03049 if ((cache_info->storage_class == PseudoClass) ||
03050 (cache_info->colorspace == CMYKColorspace))
03051 {
03052 status=ReadPixelCacheIndexes(cache_info,nexus_info,exception);
03053 if (status == MagickFalse)
03054 return((const PixelPacket *) NULL);
03055 }
03056 return(pixels);
03057 }
03058
03059
03060
03061 q=pixels;
03062 indexes=GetPixelCacheNexusIndexes(cache_info,nexus_info);
03063 virtual_nexus=AcquirePixelCacheNexus(1);
03064 if (virtual_nexus == (NexusInfo **) NULL)
03065 {
03066 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
03067 "UnableToGetCacheNexus","`%s'",image->filename);
03068 return((const PixelPacket *) NULL);
03069 }
03070 switch (virtual_pixel_method)
03071 {
03072 case BlackVirtualPixelMethod:
03073 {
03074 virtual_pixel.red=0;
03075 virtual_pixel.green=0;
03076 virtual_pixel.blue=0;
03077 virtual_pixel.opacity=OpaqueOpacity;
03078 break;
03079 }
03080 case GrayVirtualPixelMethod:
03081 {
03082 virtual_pixel.red=(Quantum) QuantumRange/2;
03083 virtual_pixel.green=(Quantum) QuantumRange/2;
03084 virtual_pixel.blue=(Quantum) QuantumRange/2;
03085 virtual_pixel.opacity=(Quantum) OpaqueOpacity;
03086 break;
03087 }
03088 case TransparentVirtualPixelMethod:
03089 {
03090 virtual_pixel.red=(Quantum) 0;
03091 virtual_pixel.green=(Quantum) 0;
03092 virtual_pixel.blue=(Quantum) 0;
03093 virtual_pixel.opacity=(Quantum) TransparentOpacity;
03094 break;
03095 }
03096 case MaskVirtualPixelMethod:
03097 case WhiteVirtualPixelMethod:
03098 {
03099 virtual_pixel.red=(Quantum) QuantumRange;
03100 virtual_pixel.green=(Quantum) QuantumRange;
03101 virtual_pixel.blue=(Quantum) QuantumRange;
03102 virtual_pixel.opacity=OpaqueOpacity;
03103 break;
03104 }
03105 default:
03106 {
03107 virtual_pixel=image->background_color;
03108 break;
03109 }
03110 }
03111 for (v=0; v < (long) rows; v++)
03112 {
03113 for (u=0; u < (long) columns; u+=length)
03114 {
03115 length=(MagickSizeType) MagickMin(cache_info->columns-(x+u),columns-u);
03116 if ((((x+u) < 0) || ((x+u) >= (long) cache_info->columns)) ||
03117 (((y+v) < 0) || ((y+v) >= (long) cache_info->rows)) || (length == 0))
03118 {
03119 MagickModulo
03120 x_modulo,
03121 y_modulo;
03122
03123
03124
03125
03126 length=(MagickSizeType) 1;
03127 switch (virtual_pixel_method)
03128 {
03129 case BackgroundVirtualPixelMethod:
03130 case ConstantVirtualPixelMethod:
03131 case BlackVirtualPixelMethod:
03132 case GrayVirtualPixelMethod:
03133 case TransparentVirtualPixelMethod:
03134 case MaskVirtualPixelMethod:
03135 case WhiteVirtualPixelMethod:
03136 {
03137 p=(&virtual_pixel);
03138 break;
03139 }
03140 case EdgeVirtualPixelMethod:
03141 default:
03142 {
03143 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
03144 EdgeX(cache_info->columns,x+u),EdgeY(cache_info->rows,y+v),
03145 1UL,1UL,virtual_nexus[0],exception);
03146 break;
03147 }
03148 case RandomVirtualPixelMethod:
03149 {
03150 if (cache_info->random_info == (RandomInfo *) NULL)
03151 cache_info->random_info=AcquireRandomInfo();
03152 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
03153 RandomX(cache_info->columns,cache_info->random_info),
03154 RandomY(cache_info->rows,cache_info->random_info),1UL,1UL,
03155 virtual_nexus[0],exception);
03156 break;
03157 }
03158 case DitherVirtualPixelMethod:
03159 {
03160 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
03161 DitherX(cache_info->columns,x+u),DitherY(cache_info->rows,y+v),
03162 1UL,1UL,virtual_nexus[0],exception);
03163 break;
03164 }
03165 case TileVirtualPixelMethod:
03166 {
03167 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
03168 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
03169 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
03170 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus[0],
03171 exception);
03172 break;
03173 }
03174 case MirrorVirtualPixelMethod:
03175 {
03176 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
03177 if ((x_modulo.quotient & 0x01) == 1L)
03178 x_modulo.remainder=(long) cache_info->columns-
03179 x_modulo.remainder-1L;
03180 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
03181 if ((y_modulo.quotient & 0x01) == 1L)
03182 y_modulo.remainder=(long) cache_info->rows-
03183 y_modulo.remainder-1L;
03184 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
03185 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus[0],
03186 exception);
03187 break;
03188 }
03189 case CheckerTileVirtualPixelMethod:
03190 {
03191 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
03192 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
03193 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
03194 {
03195 p=(&virtual_pixel);
03196 break;
03197 }
03198 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
03199 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus[0],
03200 exception);
03201 break;
03202 }
03203 case HorizontalTileVirtualPixelMethod:
03204 {
03205 if (((y+v) < 0) || ((y+v) >= (long) cache_info->rows))
03206 {
03207 p=(&virtual_pixel);
03208 break;
03209 }
03210 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
03211 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
03212 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
03213 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus[0],
03214 exception);
03215 break;
03216 }
03217 case VerticalTileVirtualPixelMethod:
03218 {
03219 if (((x+u) < 0) || ((x+u) >= (long) cache_info->columns))
03220 {
03221 p=(&virtual_pixel);
03222 break;
03223 }
03224 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
03225 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
03226 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
03227 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus[0],
03228 exception);
03229 break;
03230 }
03231 case HorizontalTileEdgeVirtualPixelMethod:
03232 {
03233 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
03234 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
03235 x_modulo.remainder,EdgeY(cache_info->rows,y+v),1UL,1UL,
03236 virtual_nexus[0],exception);
03237 break;
03238 }
03239 case VerticalTileEdgeVirtualPixelMethod:
03240 {
03241 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
03242 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
03243 EdgeX(cache_info->columns,x+u),y_modulo.remainder,1UL,1UL,
03244 virtual_nexus[0],exception);
03245 break;
03246 }
03247 }
03248 if (p == (const PixelPacket *) NULL)
03249 break;
03250 *q++=(*p);
03251 if (indexes != (IndexPacket *) NULL)
03252 {
03253 nexus_indexes=GetVirtualIndexesFromNexus(cache_info,
03254 virtual_nexus[0]);
03255 if (nexus_indexes != (const IndexPacket *) NULL)
03256 *indexes++=(*nexus_indexes);
03257 }
03258 continue;
03259 }
03260
03261
03262
03263 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x+u,y+v,
03264 (unsigned long) length,1UL,virtual_nexus[0],exception);
03265 if (p == (const PixelPacket *) NULL)
03266 break;
03267 (void) CopyMagickMemory(q,p,(size_t) length*sizeof(*p));
03268 q+=length;
03269 if (indexes != (IndexPacket *) NULL)
03270 {
03271 nexus_indexes=GetVirtualIndexesFromNexus(cache_info,virtual_nexus[0]);
03272 if (nexus_indexes != (const IndexPacket *) NULL)
03273 {
03274 (void) CopyMagickMemory(indexes,nexus_indexes,(size_t) length*
03275 sizeof(*nexus_indexes));
03276 indexes+=length;
03277 }
03278 }
03279 }
03280 }
03281 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
03282 return(pixels);
03283 }
03284
03285
03286
03287
03288
03289
03290
03291
03292
03293
03294
03295
03296
03297
03298
03299
03300
03301
03302
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312
03313
03314
03315
03316
03317
03318
03319 static const PixelPacket *GetVirtualPixelCache(const Image *image,
03320 const VirtualPixelMethod virtual_pixel_method,const long x,const long y,
03321 const unsigned long columns,const unsigned long rows,ExceptionInfo *exception)
03322 {
03323 CacheInfo
03324 *cache_info;
03325
03326 const PixelPacket
03327 *pixels;
03328
03329 long
03330 id;
03331
03332 if (image->debug != MagickFalse)
03333 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03334 cache_info=(CacheInfo *) image->cache;
03335 id=GetOpenMPThreadId();
03336 assert(id < (long) cache_info->number_threads);
03337 pixels=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,columns,rows,
03338 cache_info->nexus_info[id],exception);
03339 return(pixels);
03340 }
03341
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364
03365 MagickExport const PixelPacket *GetVirtualPixelQueue(const Image *image)
03366 {
03367 CacheInfo
03368 *cache_info;
03369
03370 assert(image != (const Image *) NULL);
03371 assert(image->signature == MagickSignature);
03372 if (image->debug != MagickFalse)
03373 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03374 assert(image->cache != (Cache) NULL);
03375 cache_info=(CacheInfo *) image->cache;
03376 assert(cache_info->signature == MagickSignature);
03377 if (cache_info->methods.get_virtual_pixels_handler ==
03378 (GetVirtualPixelsHandler) NULL)
03379 return((PixelPacket *) NULL);
03380 return(cache_info->methods.get_virtual_pixels_handler(image));
03381 }
03382
03383
03384
03385
03386
03387
03388
03389
03390
03391
03392
03393
03394
03395
03396
03397
03398
03399
03400
03401
03402
03403
03404
03405
03406
03407
03408
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418
03419
03420
03421
03422
03423
03424
03425
03426
03427
03428
03429
03430
03431 MagickExport const PixelPacket *GetVirtualPixels(const Image *image,
03432 const long x,const long y,const unsigned long columns,
03433 const unsigned long rows,ExceptionInfo *exception)
03434 {
03435 CacheInfo
03436 *cache_info;
03437
03438 const PixelPacket
03439 *pixels;
03440
03441 assert(image != (const Image *) NULL);
03442 assert(image->signature == MagickSignature);
03443 if (image->debug != MagickFalse)
03444 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03445 assert(image->cache != (Cache) NULL);
03446 cache_info=(CacheInfo *) image->cache;
03447 assert(cache_info->signature == MagickSignature);
03448 if (cache_info->methods.get_virtual_pixel_handler ==
03449 (GetVirtualPixelHandler) NULL)
03450 return((const PixelPacket *) NULL);
03451 pixels=cache_info->methods.get_virtual_pixel_handler(image,
03452 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception);
03453 return(pixels);
03454 }
03455
03456
03457
03458
03459
03460
03461
03462
03463
03464
03465
03466
03467
03468
03469
03470
03471
03472
03473
03474
03475
03476
03477
03478
03479 static const PixelPacket *GetVirtualPixelsCache(const Image *image)
03480 {
03481 CacheInfo
03482 *cache_info;
03483
03484 const PixelPacket
03485 *pixels;
03486
03487 long
03488 id;
03489
03490 if (image->debug != MagickFalse)
03491 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03492 cache_info=(CacheInfo *) image->cache;
03493 id=GetOpenMPThreadId();
03494 assert(id < (long) cache_info->number_threads);
03495 pixels=GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[id]);
03496 return(pixels);
03497 }
03498
03499
03500
03501
03502
03503
03504
03505
03506
03507
03508
03509
03510
03511
03512
03513
03514
03515
03516
03517
03518
03519
03520
03521
03522
03523
03524
03525 MagickExport const PixelPacket *GetVirtualPixelsNexus(const Cache cache,
03526 NexusInfo *nexus_info)
03527 {
03528 CacheInfo
03529 *cache_info;
03530
03531 if (cache == (Cache) NULL)
03532 return((PixelPacket *) NULL);
03533 cache_info=(CacheInfo *) cache;
03534 assert(cache_info->signature == MagickSignature);
03535 if (cache_info->storage_class == UndefinedClass)
03536 return((PixelPacket *) NULL);
03537 return((const PixelPacket *) nexus_info->pixels);
03538 }
03539
03540
03541
03542
03543
03544
03545
03546
03547
03548
03549
03550
03551
03552
03553
03554
03555
03556
03557
03558
03559
03560
03561
03562
03563
03564
03565
03566
03567
03568
03569
03570 static inline void MagickPixelCompositeMask(const MagickPixelPacket *p,
03571 const MagickRealType alpha,const MagickPixelPacket *q,
03572 const MagickRealType beta,MagickPixelPacket *composite)
03573 {
03574 MagickRealType
03575 gamma;
03576
03577 if (alpha == TransparentOpacity)
03578 {
03579 *composite=(*q);
03580 return;
03581 }
03582 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
03583 gamma=1.0/(gamma <= MagickEpsilon ? 1.0 : gamma);
03584 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
03585 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
03586 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
03587 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
03588 composite->index=gamma*MagickOver_(p->index,alpha,q->index,beta);
03589 }
03590
03591 static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
03592 ExceptionInfo *exception)
03593 {
03594 CacheInfo
03595 *cache_info;
03596
03597 MagickPixelPacket
03598 alpha,
03599 beta;
03600
03601 MagickSizeType
03602 number_pixels;
03603
03604 NexusInfo
03605 **clip_nexus,
03606 **image_nexus;
03607
03608 register const PixelPacket
03609 *__restrict r;
03610
03611 register IndexPacket
03612 *__restrict nexus_indexes,
03613 *__restrict indexes;
03614
03615 register long
03616 i;
03617
03618 register PixelPacket
03619 *__restrict p,
03620 *__restrict q;
03621
03622
03623
03624
03625 if (image->debug != MagickFalse)
03626 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03627 if (image->mask == (Image *) NULL)
03628 return(MagickFalse);
03629 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
03630 if (cache_info == (Cache) NULL)
03631 return(MagickFalse);
03632 image_nexus=AcquirePixelCacheNexus(1);
03633 clip_nexus=AcquirePixelCacheNexus(1);
03634 if ((image_nexus == (NexusInfo **) NULL) ||
03635 (clip_nexus == (NexusInfo **) NULL))
03636 ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
03637 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
03638 nexus_info->region.width,nexus_info->region.height,image_nexus[0],
03639 exception);
03640 indexes=GetPixelCacheNexusIndexes(image->cache,image_nexus[0]);
03641 q=nexus_info->pixels;
03642 nexus_indexes=nexus_info->indexes;
03643 r=GetVirtualPixelsFromNexus(image->mask,MaskVirtualPixelMethod,
03644 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
03645 nexus_info->region.height,clip_nexus[0],&image->exception);
03646 GetMagickPixelPacket(image,&alpha);
03647 GetMagickPixelPacket(image,&beta);
03648 number_pixels=(MagickSizeType) nexus_info->region.width*
03649 nexus_info->region.height;
03650 for (i=0; i < (long) number_pixels; i++)
03651 {
03652 if ((p == (PixelPacket *) NULL) || (r == (const PixelPacket *) NULL))
03653 break;
03654 SetMagickPixelPacket(image,p,indexes+i,&alpha);
03655 SetMagickPixelPacket(image,q,nexus_indexes+i,&beta);
03656 MagickPixelCompositeMask(&beta,(MagickRealType) PixelIntensityToQuantum(r),
03657 &alpha,alpha.opacity,&beta);
03658 q->red=RoundToQuantum(beta.red);
03659 q->green=RoundToQuantum(beta.green);
03660 q->blue=RoundToQuantum(beta.blue);
03661 q->opacity=RoundToQuantum(beta.opacity);
03662 if (cache_info->active_index_channel != MagickFalse)
03663 nexus_indexes[i]=indexes[i];
03664 p++;
03665 q++;
03666 r++;
03667 }
03668 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
03669 image_nexus=DestroyPixelCacheNexus(image_nexus,1);
03670 if (i < (long) number_pixels)
03671 return(MagickFalse);
03672 return(MagickTrue);
03673 }
03674
03675
03676
03677
03678
03679
03680
03681
03682
03683
03684
03685
03686
03687
03688
03689
03690
03691
03692
03693
03694
03695
03696
03697
03698
03699
03700
03701
03702
03703
03704
03705
03706 static inline void AcquirePixelCachePixels(CacheInfo *cache_info)
03707 {
03708 cache_info->mapped=MagickFalse;
03709 cache_info->pixels=(PixelPacket *) AcquireMagickMemory((size_t)
03710 cache_info->length);
03711 if (cache_info->pixels == (PixelPacket *) NULL)
03712 {
03713 cache_info->mapped=MagickTrue;
03714 cache_info->pixels=(PixelPacket *) MapBlob(-1,IOMode,0,(size_t)
03715 cache_info->length);
03716 }
03717 }
03718
03719 static MagickBooleanType ExtendCache(Image *image,MagickSizeType length)
03720 {
03721 CacheInfo
03722 *cache_info;
03723
03724 MagickOffsetType
03725 count,
03726 extent,
03727 offset;
03728
03729 cache_info=(CacheInfo *) image->cache;
03730 if (image->debug != MagickFalse)
03731 {
03732 char
03733 format[MaxTextExtent],
03734 message[MaxTextExtent];
03735
03736 (void) FormatMagickSize(length,format);
03737 (void) FormatMagickString(message,MaxTextExtent,
03738 "extend %s (%s[%d], disk, %s)",cache_info->filename,
03739 cache_info->cache_filename,cache_info->file,format);
03740 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
03741 }
03742 if (length != (MagickSizeType) ((MagickOffsetType) length))
03743 return(MagickFalse);
03744 extent=(MagickOffsetType) MagickSeek(cache_info->file,0,SEEK_END);
03745 if (extent < 0)
03746 return(MagickFalse);
03747 if ((MagickSizeType) extent >= length)
03748 return(MagickTrue);
03749 offset=(MagickOffsetType) length-1;
03750 count=WritePixelCacheRegion(cache_info,offset,1,(const unsigned char *) "");
03751 return(count == (MagickOffsetType) 1 ? MagickTrue : MagickFalse);
03752 }
03753
03754 static MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
03755 ExceptionInfo *exception)
03756 {
03757 char
03758 format[MaxTextExtent],
03759 message[MaxTextExtent];
03760
03761 CacheInfo
03762 *cache_info,
03763 source_info;
03764
03765 MagickSizeType
03766 length,
03767 number_pixels;
03768
03769 MagickStatusType
03770 status;
03771
03772 size_t
03773 packet_size;
03774
03775 unsigned long
03776 columns;
03777
03778 if (image->debug != MagickFalse)
03779 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03780 if ((image->columns == 0) || (image->rows == 0))
03781 ThrowBinaryException(CacheError,"NoPixelsDefinedInCache",image->filename);
03782 cache_info=(CacheInfo *) image->cache;
03783 source_info=(*cache_info);
03784 source_info.file=(-1);
03785 (void) FormatMagickString(cache_info->filename,MaxTextExtent,"%s[%ld]",
03786 image->filename,GetImageIndexInList(image));
03787 cache_info->rows=image->rows;
03788 cache_info->columns=image->columns;
03789 cache_info->active_index_channel=((image->storage_class == PseudoClass) ||
03790 (image->colorspace == CMYKColorspace)) ? MagickTrue : MagickFalse;
03791 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
03792 packet_size=sizeof(PixelPacket);
03793 if (cache_info->active_index_channel != MagickFalse)
03794 packet_size+=sizeof(IndexPacket);
03795 length=number_pixels*packet_size;
03796 columns=(unsigned long) (length/cache_info->rows/packet_size);
03797 if (cache_info->columns != columns)
03798 ThrowBinaryException(ResourceLimitError,"PixelCacheAllocationFailed",
03799 image->filename);
03800 cache_info->length=length;
03801 status=AcquireMagickResource(AreaResource,cache_info->length);
03802 length=number_pixels*(sizeof(PixelPacket)+sizeof(IndexPacket));
03803 if ((status != MagickFalse) && (length == (MagickSizeType) ((size_t) length)))
03804 {
03805 status=AcquireMagickResource(MemoryResource,cache_info->length);
03806 if (((cache_info->type == UndefinedCache) && (status != MagickFalse)) ||
03807 (cache_info->type == MemoryCache))
03808 {
03809 AcquirePixelCachePixels(cache_info);
03810 if (cache_info->pixels == (PixelPacket *) NULL)
03811 cache_info->pixels=source_info.pixels;
03812 else
03813 {
03814
03815
03816
03817 if (image->debug != MagickFalse)
03818 {
03819 (void) FormatMagickSize(cache_info->length,format);
03820 (void) FormatMagickString(message,MaxTextExtent,
03821 "open %s (%s memory, %lux%lu %s)",cache_info->filename,
03822 cache_info->mapped != MagickFalse ? "anonymous" : "heap",
03823 cache_info->columns,cache_info->rows,format);
03824 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
03825 message);
03826 }
03827 cache_info->storage_class=image->storage_class;
03828 cache_info->colorspace=image->colorspace;
03829 cache_info->type=MemoryCache;
03830 cache_info->indexes=(IndexPacket *) NULL;
03831 if (cache_info->active_index_channel != MagickFalse)
03832 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
03833 number_pixels);
03834 if (source_info.storage_class != UndefinedClass)
03835 {
03836 status|=ClonePixelCache(cache_info,&source_info,exception);
03837 RelinquishPixelCachePixels(&source_info);
03838 }
03839 return(MagickTrue);
03840 }
03841 }
03842 RelinquishMagickResource(MemoryResource,cache_info->length);
03843 }
03844
03845
03846
03847 status=AcquireMagickResource(DiskResource,cache_info->length);
03848 if (status == MagickFalse)
03849 {
03850 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
03851 "CacheResourcesExhausted","`%s'",image->filename);
03852 return(MagickFalse);
03853 }
03854 if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
03855 {
03856 RelinquishMagickResource(DiskResource,cache_info->length);
03857 ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
03858 image->filename);
03859 return(MagickFalse);
03860 }
03861 status=ExtendCache(image,(MagickSizeType) cache_info->offset+
03862 cache_info->length);
03863 if (status == MagickFalse)
03864 {
03865 ThrowFileException(exception,CacheError,"UnableToExtendCache",
03866 image->filename);
03867 return(MagickFalse);
03868 }
03869 cache_info->storage_class=image->storage_class;
03870 cache_info->colorspace=image->colorspace;
03871 length=number_pixels*(sizeof(PixelPacket)+sizeof(IndexPacket));
03872 status=AcquireMagickResource(AreaResource,cache_info->length);
03873 if ((status == MagickFalse) || (length != (MagickSizeType) ((size_t) length)))
03874 cache_info->type=DiskCache;
03875 else
03876 {
03877 status=AcquireMagickResource(MapResource,cache_info->length);
03878 if ((status == MagickFalse) && (cache_info->type != MapCache) &&
03879 (cache_info->type != MemoryCache))
03880 cache_info->type=DiskCache;
03881 else
03882 {
03883 cache_info->pixels=(PixelPacket *) MapBlob(cache_info->file,mode,
03884 cache_info->offset,(size_t) cache_info->length);
03885 if (cache_info->pixels == (PixelPacket *) NULL)
03886 {
03887 cache_info->pixels=source_info.pixels;
03888 cache_info->type=DiskCache;
03889 }
03890 else
03891 {
03892
03893
03894
03895 (void) ClosePixelCacheOnDisk(cache_info);
03896 cache_info->type=MapCache;
03897 cache_info->mapped=MagickTrue;
03898 cache_info->indexes=(IndexPacket *) NULL;
03899 if (cache_info->active_index_channel != MagickFalse)
03900 cache_info->indexes=(IndexPacket *) (cache_info->pixels+
03901 number_pixels);
03902 if ((source_info.type != UndefinedCache) && (mode != ReadMode))
03903 {
03904 status=ClonePixelCache(cache_info,&source_info,exception);
03905 RelinquishPixelCachePixels(&source_info);
03906 }
03907 if (image->debug != MagickFalse)
03908 {
03909 (void) FormatMagickSize(cache_info->length,format);
03910 (void) FormatMagickString(message,MaxTextExtent,
03911 "open %s (%s[%d], memory-mapped, %lux%lu %s)",
03912 cache_info->filename,cache_info->cache_filename,
03913 cache_info->file,cache_info->columns,cache_info->rows,
03914 format);
03915 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",
03916 message);
03917 }
03918 return(MagickTrue);
03919 }
03920 }
03921 RelinquishMagickResource(MapResource,cache_info->length);
03922 }
03923 if ((source_info.type != UndefinedCache) && (mode != ReadMode))
03924 {
03925 status=ClonePixelCache(cache_info,&source_info,exception);
03926 RelinquishPixelCachePixels(&source_info);
03927 }
03928 if (image->debug != MagickFalse)
03929 {
03930 (void) FormatMagickSize(cache_info->length,format);
03931 (void) FormatMagickString(message,MaxTextExtent,
03932 "open %s (%s[%d], disk, %lux%lu %s)",cache_info->filename,
03933 cache_info->cache_filename,cache_info->file,cache_info->columns,
03934 cache_info->rows,format);
03935 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
03936 }
03937 return(MagickTrue);
03938 }
03939
03940
03941
03942
03943
03944
03945
03946
03947
03948
03949
03950
03951
03952
03953
03954
03955
03956
03957
03958
03959
03960
03961
03962
03963
03964
03965
03966
03967
03968
03969
03970
03971
03972
03973
03974
03975 MagickExport MagickBooleanType PersistPixelCache(Image *image,
03976 const char *filename,const MagickBooleanType attach,MagickOffsetType *offset,
03977 ExceptionInfo *exception)
03978 {
03979 CacheInfo
03980 *cache_info,
03981 *clone_info;
03982
03983 Image
03984 clone_image;
03985
03986 long
03987 pagesize;
03988
03989 MagickBooleanType
03990 status;
03991
03992 assert(image != (Image *) NULL);
03993 assert(image->signature == MagickSignature);
03994 if (image->debug != MagickFalse)
03995 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03996 assert(image->cache != (void *) NULL);
03997 assert(filename != (const char *) NULL);
03998 assert(offset != (MagickOffsetType *) NULL);
03999 pagesize=(-1);
04000 #if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PAGESIZE)
04001 pagesize=sysconf(_SC_PAGESIZE);
04002 #elif defined(MAGICKCORE_HAVE_GETPAGESIZE) && defined(MAGICKCORE_POSIX_SUPPORT)
04003 pagesize=getpagesize();
04004 #endif
04005 if (pagesize <= 0)
04006 pagesize=4096;
04007 cache_info=(CacheInfo *) image->cache;
04008 assert(cache_info->signature == MagickSignature);
04009 if (attach != MagickFalse)
04010 {
04011
04012
04013
04014 if (image->debug != MagickFalse)
04015 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
04016 "attach persistent cache");
04017 (void) CopyMagickString(cache_info->cache_filename,filename,
04018 MaxTextExtent);
04019 cache_info->type=DiskCache;
04020 cache_info->offset=(*offset);
04021 if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
04022 return(MagickFalse);
04023 cache_info=(CacheInfo *) ReferencePixelCache(cache_info);
04024 *offset+=cache_info->length+pagesize-(cache_info->length % pagesize);
04025 return(MagickTrue);
04026 }
04027 if ((cache_info->type != MemoryCache) && (cache_info->reference_count == 1))
04028 {
04029 (void) LockSemaphoreInfo(cache_info->semaphore);
04030 if ((cache_info->type != MemoryCache) &&
04031 (cache_info->reference_count == 1))
04032 {
04033 int
04034 status;
04035
04036
04037
04038
04039 status=rename(cache_info->cache_filename,filename);
04040 if (status == 0)
04041 {
04042 (void) CopyMagickString(cache_info->cache_filename,filename,
04043 MaxTextExtent);
04044 cache_info=(CacheInfo *) ReferencePixelCache(cache_info);
04045 *offset+=cache_info->length+pagesize-(cache_info->length %
04046 pagesize);
04047 if (image->debug != MagickFalse)
04048 (void) LogMagickEvent(CacheEvent,GetMagickModule(),
04049 "Usurp resident persistent cache");
04050 (void) UnlockSemaphoreInfo(cache_info->semaphore);
04051 return(MagickTrue);
04052 }
04053 }
04054 (void) UnlockSemaphoreInfo(cache_info->semaphore);
04055 }
04056
04057
04058
04059 clone_image=(*image);
04060 clone_info=(CacheInfo *) clone_image.cache;
04061 image->cache=AcquirePixelCacheInfo(cache_info->number_threads);
04062 cache_info=(CacheInfo *) ReferencePixelCache(image->cache);
04063 (void) CopyMagickString(cache_info->cache_filename,filename,MaxTextExtent);
04064 cache_info->type=DiskCache;
04065 cache_info->offset=(*offset);
04066 cache_info=(CacheInfo *) image->cache;
04067 status=ClonePixelCacheNexus(cache_info,clone_info,exception);
04068 if (status != MagickFalse)
04069 {
04070 status=OpenPixelCache(image,IOMode,exception);
04071 if (status != MagickFalse)
04072 status=ClonePixelCache(cache_info,clone_info,&image->exception);
04073 }
04074 *offset+=cache_info->length+pagesize-(cache_info->length % pagesize);
04075 clone_info=(CacheInfo *) DestroyPixelCacheInfo(clone_info);
04076 return(status);
04077 }
04078
04079
04080
04081
04082
04083
04084
04085
04086
04087
04088
04089
04090
04091
04092
04093
04094
04095
04096
04097
04098
04099
04100
04101
04102
04103
04104
04105
04106
04107
04108
04109
04110
04111
04112
04113
04114 MagickExport PixelPacket *QueueAuthenticNexus(Image *image,const long x,
04115 const long y,const unsigned long columns,const unsigned long rows,
04116 NexusInfo *nexus_info,ExceptionInfo *exception)
04117 {
04118 CacheInfo
04119 *cache_info;
04120
04121 MagickOffsetType
04122 offset;
04123
04124 MagickSizeType
04125 number_pixels;
04126
04127 RectangleInfo
04128 region;
04129
04130
04131
04132
04133 cache_info=(CacheInfo *) image->cache;
04134 if ((cache_info->columns == 0) && (cache_info->rows == 0))
04135 {
04136 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
04137 "NoPixelsDefinedInCache","`%s'",image->filename);
04138 return((PixelPacket *) NULL);
04139 }
04140 if ((x < 0) || (y < 0) || (x >= (long) cache_info->columns) ||
04141 (y >= (long) cache_info->rows))
04142 {
04143 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
04144 "PixelsAreNotAuthentic","`%s'",image->filename);
04145 return((PixelPacket *) NULL);
04146 }
04147 offset=(MagickOffsetType) y*cache_info->columns+x;
04148 if (offset < 0)
04149 return((PixelPacket *) NULL);
04150 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
04151 offset+=(MagickOffsetType) (rows-1)*cache_info->columns+columns-1;
04152 if ((MagickSizeType) offset >= number_pixels)
04153 return((PixelPacket *) NULL);
04154
04155
04156
04157 region.x=x;
04158 region.y=y;
04159 region.width=columns;
04160 region.height=rows;
04161 return(SetPixelCacheNexusPixels(image,®ion,nexus_info,exception));
04162 }
04163
04164
04165
04166
04167
04168
04169
04170
04171
04172
04173
04174
04175
04176
04177
04178
04179
04180
04181
04182
04183
04184
04185
04186
04187
04188
04189
04190
04191
04192
04193
04194
04195
04196
04197 static PixelPacket *QueueAuthenticPixelsCache(Image *image,const long x,
04198 const long y,const unsigned long columns,const unsigned long rows,
04199 ExceptionInfo *exception)
04200 {
04201 CacheInfo
04202 *cache_info;
04203
04204 long
04205 id;
04206
04207 PixelPacket
04208 *pixels;
04209
04210 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickFalse,exception);
04211 if (cache_info == (Cache) NULL)
04212 return((PixelPacket *) NULL);
04213 id=GetOpenMPThreadId();
04214 assert(id < (long) cache_info->number_threads);
04215 pixels=QueueAuthenticNexus(image,x,y,columns,rows,cache_info->nexus_info[id],
04216 exception);
04217 return(pixels);
04218 }
04219
04220
04221
04222
04223
04224
04225
04226
04227
04228
04229
04230
04231
04232
04233
04234
04235
04236
04237
04238
04239
04240
04241
04242
04243
04244
04245
04246
04247
04248
04249
04250
04251
04252
04253
04254
04255
04256
04257
04258
04259
04260
04261
04262
04263
04264
04265
04266
04267
04268
04269
04270
04271
04272
04273
04274
04275
04276 MagickExport PixelPacket *QueueAuthenticPixels(Image *image,const long x,
04277 const long y,const unsigned long columns,const unsigned long rows,
04278 ExceptionInfo *exception)
04279 {
04280 CacheInfo
04281 *cache_info;
04282
04283 PixelPacket
04284 *pixels;
04285
04286 assert(image != (Image *) NULL);
04287 assert(image->signature == MagickSignature);
04288 if (image->debug != MagickFalse)
04289 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
04290 assert(image->cache != (Cache) NULL);
04291 cache_info=(CacheInfo *) image->cache;
04292 assert(cache_info->signature == MagickSignature);
04293 if (cache_info->methods.queue_authentic_pixels_handler ==
04294 (QueueAuthenticPixelsHandler) NULL)
04295 return((PixelPacket *) NULL);
04296 pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,columns,
04297 rows,exception);
04298 return(pixels);
04299 }
04300
04301
04302
04303
04304
04305
04306
04307
04308
04309
04310
04311
04312
04313
04314
04315
04316
04317
04318
04319
04320
04321
04322
04323
04324
04325
04326
04327
04328
04329 static MagickBooleanType ReadPixelCacheIndexes(CacheInfo *cache_info,
04330 NexusInfo *nexus_info,ExceptionInfo *exception)
04331 {
04332 MagickOffsetType
04333 count,
04334 offset;
04335
04336 MagickSizeType
04337 length,
04338 number_pixels;
04339
04340 register IndexPacket
04341 *__restrict q;
04342
04343 register long
04344 y;
04345
04346 unsigned long
04347 rows;
04348
04349 if (cache_info->debug != MagickFalse)
04350 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
04351 cache_info->filename);
04352 if (cache_info->active_index_channel == MagickFalse)
04353 return(MagickFalse);
04354 if (IsNexusInCore(cache_info,nexus_info) != MagickFalse)
04355 return(MagickTrue);
04356 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
04357 nexus_info->region.x;
04358 length=(MagickSizeType) nexus_info->region.width*sizeof(IndexPacket);
04359 rows=nexus_info->region.height;
04360 number_pixels=length*rows;
04361 if ((cache_info->columns == nexus_info->region.width) &&
04362 (number_pixels == (MagickSizeType) ((size_t) number_pixels)))
04363 {
04364 length=number_pixels;
04365 rows=1UL;
04366 }
04367 q=nexus_info->indexes;
04368 switch (cache_info->type)
04369 {
04370 case MemoryCache:
04371 case MapCache:
04372 {
04373 register IndexPacket
04374 *__restrict p;
04375
04376
04377
04378
04379 p=cache_info->indexes+offset;
04380 for (y=0; y < (long) rows; y++)
04381 {
04382 (void) CopyMagickMemory(q,p,(size_t) length);
04383 p+=cache_info->columns;
04384 q+=nexus_info->region.width;
04385 }
04386 break;
04387 }
04388 case DiskCache:
04389 {
04390
04391
04392
04393 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
04394 {
04395 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
04396 cache_info->cache_filename);
04397 return(MagickFalse);
04398 }
04399 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
04400 for (y=0; y < (long) rows; y++)
04401 {
04402 count=ReadPixelCacheRegion(cache_info,cache_info->offset+number_pixels*
04403 sizeof(PixelPacket)+offset*sizeof(*q),length,(unsigned char *) q);
04404 if ((MagickSizeType) count < length)
04405 break;
04406 offset+=cache_info->columns;
04407 q+=nexus_info->region.width;
04408 }
04409 if (y < (long) rows)
04410 {
04411 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
04412 cache_info->cache_filename);
04413 return(MagickFalse);
04414 }
04415 break;
04416 }
04417 default:
04418 break;
04419 }
04420 if ((cache_info->debug != MagickFalse) &&
04421 (QuantumTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
04422 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s[%lux%lu%+ld%+ld]",
04423 cache_info->filename,nexus_info->region.width,nexus_info->region.height,
04424 nexus_info->region.x,nexus_info->region.y);
04425 return(MagickTrue);
04426 }
04427
04428
04429
04430
04431
04432
04433
04434
04435
04436
04437
04438
04439
04440
04441
04442
04443
04444
04445
04446
04447
04448
04449
04450
04451
04452
04453
04454
04455
04456 static MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
04457 NexusInfo *nexus_info,ExceptionInfo *exception)
04458 {
04459 MagickOffsetType
04460 count,
04461 offset;
04462
04463 MagickSizeType
04464 length,
04465 number_pixels;
04466
04467 register long
04468 y;
04469
04470 register PixelPacket
04471 *__restrict q;
04472
04473 unsigned long
04474 rows;
04475
04476 if (cache_info->debug != MagickFalse)
04477 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
04478 cache_info->filename);
04479 if (IsNexusInCore(cache_info,nexus_info) != MagickFalse)
04480 return(MagickTrue);
04481 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
04482 nexus_info->region.x;
04483 length=(MagickSizeType) nexus_info->region.width*sizeof(PixelPacket);
04484 rows=nexus_info->region.height;
04485 number_pixels=length*rows;
04486 if ((cache_info->columns == nexus_info->region.width) &&
04487 (number_pixels == (MagickSizeType) ((size_t) number_pixels)))
04488 {
04489 length=number_pixels;
04490 rows=1UL;
04491 }
04492 q=nexus_info->pixels;
04493 switch (cache_info->type)
04494 {
04495 case MemoryCache:
04496 case MapCache:
04497 {
04498 register PixelPacket
04499 *__restrict p;
04500
04501
04502
04503
04504 p=cache_info->pixels+offset;
04505 for (y=0; y < (long) rows; y++)
04506 {
04507 (void) CopyMagickMemory(q,p,(size_t) length);
04508 p+=cache_info->columns;
04509 q+=nexus_info->region.width;
04510 }
04511 break;
04512 }
04513 case DiskCache:
04514 {
04515
04516
04517
04518 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
04519 {
04520 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
04521 cache_info->cache_filename);
04522 return(MagickFalse);
04523 }
04524 for (y=0; y < (long) rows; y++)
04525 {
04526 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
04527 sizeof(*q),length,(unsigned char *) q);
04528 if ((MagickSizeType) count < length)
04529 break;
04530 offset+=cache_info->columns;
04531 q+=nexus_info->region.width;
04532 }
04533 if (y < (long) rows)
04534 {
04535 ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
04536 cache_info->cache_filename);
04537 return(MagickFalse);
04538 }
04539 break;
04540 }
04541 default:
04542 break;
04543 }
04544 if ((cache_info->debug != MagickFalse) &&
04545 (QuantumTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
04546 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s[%lux%lu%+ld%+ld]",
04547 cache_info->filename,nexus_info->region.width,nexus_info->region.height,
04548 nexus_info->region.x,nexus_info->region.y);
04549 return(MagickTrue);
04550 }
04551
04552
04553
04554
04555
04556
04557
04558
04559
04560
04561
04562
04563
04564
04565
04566
04567
04568
04569
04570
04571
04572
04573
04574
04575 MagickExport Cache ReferencePixelCache(Cache cache)
04576 {
04577 CacheInfo
04578 *cache_info;
04579
04580 assert(cache != (Cache *) NULL);
04581 cache_info=(CacheInfo *) cache;
04582 assert(cache_info->signature == MagickSignature);
04583 if (cache_info->debug != MagickFalse)
04584 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
04585 cache_info->filename);
04586 (void) LockSemaphoreInfo(cache_info->semaphore);
04587 cache_info->reference_count++;
04588 (void) UnlockSemaphoreInfo(cache_info->semaphore);
04589 return(cache_info);
04590 }
04591
04592
04593
04594
04595
04596
04597
04598
04599
04600
04601
04602
04603
04604
04605
04606
04607
04608
04609
04610
04611
04612
04613
04614
04615
04616 MagickExport void SetPixelCacheMethods(Cache cache,CacheMethods *cache_methods)
04617 {
04618 CacheInfo
04619 *cache_info;
04620
04621 GetOneAuthenticPixelFromHandler
04622 get_one_authentic_pixel_from_handler;
04623
04624 GetOneVirtualPixelFromHandler
04625 get_one_virtual_pixel_from_handler;
04626
04627
04628
04629
04630 assert(cache != (Cache) NULL);
04631 assert(cache_methods != (CacheMethods *) NULL);
04632 cache_info=(CacheInfo *) cache;
04633 assert(cache_info->signature == MagickSignature);
04634 if (cache_info->debug != MagickFalse)
04635 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
04636 cache_info->filename);
04637 if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
04638 cache_info->methods.get_virtual_pixel_handler=
04639 cache_methods->get_virtual_pixel_handler;
04640 if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
04641 cache_info->methods.destroy_pixel_handler=
04642 cache_methods->destroy_pixel_handler;
04643 if (cache_methods->get_virtual_indexes_from_handler !=
04644 (GetVirtualIndexesFromHandler) NULL)
04645 cache_info->methods.get_virtual_indexes_from_handler=
04646 cache_methods->get_virtual_indexes_from_handler;
04647 if (cache_methods->get_authentic_pixels_handler !=
04648 (GetAuthenticPixelsHandler) NULL)
04649 cache_info->methods.get_authentic_pixels_handler=
04650 cache_methods->get_authentic_pixels_handler;
04651 if (cache_methods->queue_authentic_pixels_handler !=
04652 (QueueAuthenticPixelsHandler) NULL)
04653 cache_info->methods.queue_authentic_pixels_handler=
04654 cache_methods->queue_authentic_pixels_handler;
04655 if (cache_methods->sync_authentic_pixels_handler !=
04656 (SyncAuthenticPixelsHandler) NULL)
04657 cache_info->methods.sync_authentic_pixels_handler=
04658 cache_methods->sync_authentic_pixels_handler;
04659 if (cache_methods->get_authentic_pixels_from_handler !=
04660 (GetAuthenticPixelsFromHandler) NULL)
04661 cache_info->methods.get_authentic_pixels_from_handler=
04662 cache_methods->get_authentic_pixels_from_handler;
04663 if (cache_methods->get_authentic_indexes_from_handler !=
04664 (GetAuthenticIndexesFromHandler) NULL)
04665 cache_info->methods.get_authentic_indexes_from_handler=
04666 cache_methods->get_authentic_indexes_from_handler;
04667 get_one_virtual_pixel_from_handler=
04668 cache_info->methods.get_one_virtual_pixel_from_handler;
04669 if (get_one_virtual_pixel_from_handler !=
04670 (GetOneVirtualPixelFromHandler) NULL)
04671 cache_info->methods.get_one_virtual_pixel_from_handler=
04672 cache_methods->get_one_virtual_pixel_from_handler;
04673 get_one_authentic_pixel_from_handler=
04674 cache_methods->get_one_authentic_pixel_from_handler;
04675 if (get_one_authentic_pixel_from_handler !=
04676 (GetOneAuthenticPixelFromHandler) NULL)
04677 cache_info->methods.get_one_authentic_pixel_from_handler=
04678 cache_methods->get_one_authentic_pixel_from_handler;
04679 }
04680
04681
04682
04683
04684
04685
04686
04687
04688
04689
04690
04691
04692
04693
04694
04695
04696
04697
04698
04699
04700
04701
04702
04703
04704
04705
04706
04707
04708
04709
04710
04711
04712
04713 static PixelPacket *SetPixelCacheNexusPixels(const Image *image,
04714 const RectangleInfo *region,NexusInfo *nexus_info,ExceptionInfo *exception)
04715 {
04716 CacheInfo
04717 *cache_info;
04718
04719 MagickBooleanType
04720 status;
04721
04722 MagickOffsetType
04723 offset;
04724
04725 MagickSizeType
04726 length,
04727 number_pixels;
04728
04729 if (image->debug != MagickFalse)
04730 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
04731 cache_info=(CacheInfo *) image->cache;
04732 assert(cache_info->signature == MagickSignature);
04733 if (cache_info->type == UndefinedCache)
04734 return((PixelPacket *) NULL);
04735 nexus_info->region.width=region->width == 0UL ? 1UL : region->width;
04736 nexus_info->region.height=region->height == 0UL ? 1UL : region->height;
04737 nexus_info->region.x=region->x;
04738 nexus_info->region.y=region->y;
04739 if ((cache_info->type != DiskCache) && (image->clip_mask == (Image *) NULL) &&
04740 (image->mask == (Image *) NULL))
04741 {
04742 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
04743 nexus_info->region.x;
04744 length=(MagickSizeType) (nexus_info->region.height-1)*cache_info->columns+
04745 nexus_info->region.width-1;
04746 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
04747 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
04748 {
04749 long
04750 x,
04751 y;
04752
04753 x=nexus_info->region.x+nexus_info->region.width;
04754 y=nexus_info->region.y+nexus_info->region.height;
04755 if ((nexus_info->region.x >= 0) &&
04756 (x <= (long) cache_info->columns) &&
04757 (nexus_info->region.y >= 0) && (y <= (long) cache_info->rows))
04758 if ((nexus_info->region.height == 1UL) ||
04759 ((nexus_info->region.x == 0) &&
04760 ((nexus_info->region.width % cache_info->columns) == 0)))
04761 {
04762
04763
04764
04765 nexus_info->pixels=cache_info->pixels+offset;
04766 nexus_info->indexes=(IndexPacket *) NULL;
04767 if (cache_info->active_index_channel != MagickFalse)
04768 nexus_info->indexes=cache_info->indexes+offset;
04769 return(nexus_info->pixels);
04770 }
04771 }
04772 }
04773
04774
04775
04776 number_pixels=(MagickSizeType) nexus_info->region.width*
04777 nexus_info->region.height;
04778 length=number_pixels*sizeof(PixelPacket);
04779 if (cache_info->active_index_channel != MagickFalse)
04780 length+=number_pixels*sizeof(IndexPacket);
04781 if (nexus_info->cache == (PixelPacket *) NULL)
04782 {
04783 nexus_info->length=length;
04784 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
04785 if (status == MagickFalse)
04786 return((PixelPacket *) NULL);
04787 }
04788 else
04789 if (nexus_info->length != length)
04790 {
04791 RelinquishCacheNexusPixels(nexus_info);
04792 nexus_info->length=length;
04793 status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
04794 if (status == MagickFalse)
04795 return((PixelPacket *) NULL);
04796 }
04797 nexus_info->pixels=nexus_info->cache;
04798 nexus_info->indexes=(IndexPacket *) NULL;
04799 if (cache_info->active_index_channel != MagickFalse)
04800 nexus_info->indexes=(IndexPacket *) (nexus_info->pixels+number_pixels);
04801 return(nexus_info->pixels);
04802 }
04803
04804
04805
04806
04807
04808
04809
04810
04811
04812
04813
04814
04815
04816
04817
04818
04819
04820
04821
04822
04823
04824
04825
04826
04827
04828
04829
04830
04831 MagickExport VirtualPixelMethod SetPixelCacheVirtualMethod(const Image *image,
04832 const VirtualPixelMethod virtual_pixel_method)
04833 {
04834 CacheInfo
04835 *cache_info;
04836
04837 VirtualPixelMethod
04838 method;
04839
04840 assert(image != (Image *) NULL);
04841 assert(image->signature == MagickSignature);
04842 if (image->debug != MagickFalse)
04843 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
04844 assert(image->cache != (Cache) NULL);
04845 cache_info=(CacheInfo *) image->cache;
04846 assert(cache_info->signature == MagickSignature);
04847 method=cache_info->virtual_pixel_method;
04848 cache_info->virtual_pixel_method=virtual_pixel_method;
04849 return(method);
04850 }
04851
04852
04853
04854
04855
04856
04857
04858
04859
04860
04861
04862
04863
04864
04865
04866
04867
04868
04869
04870
04871
04872
04873
04874
04875
04876
04877
04878
04879
04880
04881 MagickExport MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
04882 NexusInfo *nexus_info,ExceptionInfo *exception)
04883 {
04884 CacheInfo
04885 *cache_info;
04886
04887 MagickBooleanType
04888 status;
04889
04890
04891
04892
04893 assert(image != (Image *) NULL);
04894 assert(image->signature == MagickSignature);
04895 if (image->debug != MagickFalse)
04896 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
04897 if (image->cache == (Cache) NULL)
04898 ThrowBinaryException(CacheError,"PixelCacheIsNotOpen",image->filename);
04899 cache_info=(CacheInfo *) image->cache;
04900 if (cache_info->type == UndefinedCache)
04901 return(MagickFalse);
04902 if ((image->clip_mask != (Image *) NULL) &&
04903 (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
04904 return(MagickFalse);
04905 if ((image->mask != (Image *) NULL) &&
04906 (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
04907 return(MagickFalse);
04908 if (IsNexusInCore(cache_info,nexus_info) != MagickFalse)
04909 return(MagickTrue);
04910 assert(cache_info->signature == MagickSignature);
04911 status=WritePixelCachePixels(cache_info,nexus_info,exception);
04912 if ((cache_info->active_index_channel != MagickFalse) &&
04913 (WritePixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse))
04914 return(MagickFalse);
04915 return(status);
04916 }
04917
04918
04919
04920
04921
04922
04923
04924
04925
04926
04927
04928
04929
04930
04931
04932
04933
04934
04935
04936
04937
04938
04939
04940
04941
04942
04943
04944
04945 static MagickBooleanType SyncAuthenticPixelsCache(Image *image,
04946 ExceptionInfo *exception)
04947 {
04948 CacheInfo
04949 *cache_info;
04950
04951 long
04952 id;
04953
04954 MagickBooleanType
04955 status;
04956
04957 cache_info=(CacheInfo *) image->cache;
04958 id=GetOpenMPThreadId();
04959 assert(id < (long) cache_info->number_threads);
04960 status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
04961 exception);
04962 return(status);
04963 }
04964
04965
04966
04967
04968
04969
04970
04971
04972
04973
04974
04975
04976
04977
04978
04979
04980
04981
04982
04983
04984
04985
04986
04987
04988
04989
04990
04991
04992 MagickExport MagickBooleanType SyncAuthenticPixels(Image *image,
04993 ExceptionInfo *exception)
04994 {
04995 CacheInfo
04996 *cache_info;
04997
04998 assert(image != (Image *) NULL);
04999 assert(image->signature == MagickSignature);
05000 if (image->debug != MagickFalse)
05001 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
05002 assert(image->cache != (Cache) NULL);
05003 cache_info=(CacheInfo *) image->cache;
05004 assert(cache_info->signature == MagickSignature);
05005 if (cache_info->methods.sync_authentic_pixels_handler ==
05006 (SyncAuthenticPixelsHandler) NULL)
05007 return(MagickFalse);
05008 return(cache_info->methods.sync_authentic_pixels_handler(image,exception));
05009 }
05010
05011
05012
05013
05014
05015
05016
05017
05018
05019
05020
05021
05022
05023
05024
05025
05026
05027
05028
05029
05030
05031
05032
05033
05034
05035
05036
05037
05038
05039 static MagickBooleanType WritePixelCacheIndexes(CacheInfo *cache_info,
05040 NexusInfo *nexus_info,ExceptionInfo *exception)
05041 {
05042 MagickOffsetType
05043 count,
05044 offset;
05045
05046 MagickSizeType
05047 length,
05048 number_pixels;
05049
05050 register const IndexPacket
05051 *__restrict p;
05052
05053 register long
05054 y;
05055
05056 unsigned long
05057 rows;
05058
05059 if (cache_info->debug != MagickFalse)
05060 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
05061 cache_info->filename);
05062 if (cache_info->active_index_channel == MagickFalse)
05063 return(MagickFalse);
05064 if (IsNexusInCore(cache_info,nexus_info) != MagickFalse)
05065 return(MagickTrue);
05066 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
05067 nexus_info->region.x;
05068 length=(MagickSizeType) nexus_info->region.width*sizeof(IndexPacket);
05069 rows=nexus_info->region.height;
05070 number_pixels=(MagickSizeType) length*rows;
05071 if ((cache_info->columns == nexus_info->region.width) &&
05072 (number_pixels == (MagickSizeType) ((size_t) number_pixels)))
05073 {
05074 length=number_pixels;
05075 rows=1UL;
05076 }
05077 p=nexus_info->indexes;
05078 switch (cache_info->type)
05079 {
05080 case MemoryCache:
05081 case MapCache:
05082 {
05083 register IndexPacket
05084 *__restrict q;
05085
05086
05087
05088
05089 q=cache_info->indexes+offset;
05090 for (y=0; y < (long) rows; y++)
05091 {
05092 (void) CopyMagickMemory(q,p,(size_t) length);
05093 p+=nexus_info->region.width;
05094 q+=cache_info->columns;
05095 }
05096 break;
05097 }
05098 case DiskCache:
05099 {
05100
05101
05102
05103 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
05104 {
05105 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
05106 cache_info->cache_filename);
05107 return(MagickFalse);
05108 }
05109 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
05110 for (y=0; y < (long) rows; y++)
05111 {
05112 count=WritePixelCacheRegion(cache_info,cache_info->offset+number_pixels*
05113 sizeof(PixelPacket)+offset*sizeof(*p),length,
05114 (const unsigned char *) p);
05115 if ((MagickSizeType) count < length)
05116 break;
05117 p+=nexus_info->region.width;
05118 offset+=cache_info->columns;
05119 }
05120 if (y < (long) rows)
05121 {
05122 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
05123 cache_info->cache_filename);
05124 return(MagickFalse);
05125 }
05126 break;
05127 }
05128 default:
05129 break;
05130 }
05131 if ((cache_info->debug != MagickFalse) &&
05132 (QuantumTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
05133 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s[%lux%lu%+ld%+ld]",
05134 cache_info->filename,nexus_info->region.width,nexus_info->region.height,
05135 nexus_info->region.x,nexus_info->region.y);
05136 return(MagickTrue);
05137 }
05138
05139
05140
05141
05142
05143
05144
05145
05146
05147
05148
05149
05150
05151
05152
05153
05154
05155
05156
05157
05158
05159
05160
05161
05162
05163
05164
05165
05166
05167 static MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
05168 NexusInfo *nexus_info,ExceptionInfo *exception)
05169 {
05170 MagickOffsetType
05171 count,
05172 offset;
05173
05174 MagickSizeType
05175 length,
05176 number_pixels;
05177
05178 register long
05179 y;
05180
05181 register const PixelPacket
05182 *__restrict p;
05183
05184 unsigned long
05185 rows;
05186
05187 if (cache_info->debug != MagickFalse)
05188 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
05189 cache_info->filename);
05190 if (IsNexusInCore(cache_info,nexus_info) != MagickFalse)
05191 return(MagickTrue);
05192 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
05193 nexus_info->region.x;
05194 length=(MagickSizeType) nexus_info->region.width*sizeof(PixelPacket);
05195 rows=nexus_info->region.height;
05196 number_pixels=length*rows;
05197 if ((cache_info->columns == nexus_info->region.width) &&
05198 (number_pixels == (MagickSizeType) ((size_t) number_pixels)))
05199 {
05200 length=number_pixels;
05201 rows=1UL;
05202 }
05203 p=nexus_info->pixels;
05204 switch (cache_info->type)
05205 {
05206 case MemoryCache:
05207 case MapCache:
05208 {
05209 register PixelPacket
05210 *__restrict q;
05211
05212
05213
05214
05215 q=cache_info->pixels+offset;
05216 for (y=0; y < (long) rows; y++)
05217 {
05218 (void) CopyMagickMemory(q,p,(size_t) length);
05219 p+=nexus_info->region.width;
05220 q+=cache_info->columns;
05221 }
05222 break;
05223 }
05224 case DiskCache:
05225 {
05226
05227
05228
05229 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
05230 {
05231 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
05232 cache_info->cache_filename);
05233 return(MagickFalse);
05234 }
05235 for (y=0; y < (long) rows; y++)
05236 {
05237 count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
05238 sizeof(*p),length,(const unsigned char *) p);
05239 if ((MagickSizeType) count < length)
05240 break;
05241 p+=nexus_info->region.width;
05242 offset+=cache_info->columns;
05243 }
05244 if (y < (long) rows)
05245 {
05246 ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
05247 cache_info->cache_filename);
05248 return(MagickFalse);
05249 }
05250 break;
05251 }
05252 default:
05253 break;
05254 }
05255 if ((cache_info->debug != MagickFalse) &&
05256 (QuantumTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
05257 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s[%lux%lu%+ld%+ld]",
05258 cache_info->filename,nexus_info->region.width,nexus_info->region.height,
05259 nexus_info->region.x,nexus_info->region.y);
05260 return(MagickTrue);
05261 }