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=