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 AcquirePixelCache(const unsigned long number_threads)
00178 {
00179 CacheInfo
00180 *cache_info;
00181
00182 cache_info=(CacheInfo *) AcquireAlignedMemory(1,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->mode=IOMode;
00188 cache_info->colorspace=RGBColorspace;
00189 cache_info->file=(-1);
00190 cache_info->id=GetMagickThreadId();
00191 cache_info->number_threads=number_threads;
00192 if (number_threads == 0)
00193 cache_info->number_threads=GetOpenMPMaximumThreads();
00194 cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
00195 if (cache_info->nexus_info == (NexusInfo **) NULL)
00196 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00197 GetPixelCacheMethods(&cache_info->methods);
00198 cache_info->reference_count=1;
00199 cache_info->semaphore=AllocateSemaphoreInfo();
00200 cache_info->disk_semaphore=AllocateSemaphoreInfo();
00201 cache_info->debug=IsEventLogging();
00202 cache_info->signature=MagickSignature;
00203 if ((cache_resources == (SplayTreeInfo *) NULL) &&
00204 (instantiate_cache == MagickFalse))
00205 {
00206 if (cache_semaphore == (SemaphoreInfo *) NULL)
00207 AcquireSemaphoreInfo(&cache_semaphore);
00208 (void) LockSemaphoreInfo(cache_semaphore);
00209 if ((cache_resources == (SplayTreeInfo *) NULL) &&
00210 (instantiate_cache == MagickFalse))
00211 {
00212 cache_resources=NewSplayTree((int (*)(const void *,const void *))
00213 NULL,(void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
00214 instantiate_cache=MagickTrue;
00215 }
00216 (void) UnlockSemaphoreInfo(cache_semaphore);
00217 }
00218 (void) AddValueToSplayTree(cache_resources,cache_info,cache_info);
00219 return((Cache ) cache_info);
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 MagickExport NexusInfo **AcquirePixelCacheNexus(
00245 const unsigned long number_threads)
00246 {
00247 register long
00248 i;
00249
00250 NexusInfo
00251 **nexus_info;
00252
00253 nexus_info=(NexusInfo **) AcquireAlignedMemory(number_threads,
00254 sizeof(*nexus_info));
00255 if (nexus_info == (NexusInfo **) NULL)
00256 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00257 for (i=0; i < (long) number_threads; i++)
00258 {
00259 nexus_info[i]=(NexusInfo *) AcquireAlignedMemory(1,sizeof(**nexus_info));
00260 if (nexus_info[i] == (NexusInfo *) NULL)
00261 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00262 (void) ResetMagickMemory(nexus_info[i],0,sizeof(*nexus_info[i]));
00263 nexus_info[i]->signature=MagickSignature;
00264 }
00265 return(nexus_info);
00266 }
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286 MagickExport MagickBooleanType CacheComponentGenesis(void)
00287 {
00288 AcquireSemaphoreInfo(&cache_semaphore);
00289 return(MagickTrue);
00290 }
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310 MagickExport void CacheComponentTerminus(void)
00311 {
00312 if (cache_semaphore == (SemaphoreInfo *) NULL)
00313 AcquireSemaphoreInfo(&cache_semaphore);
00314 (void) LockSemaphoreInfo(cache_semaphore);
00315 if (cache_resources != (SplayTreeInfo *) NULL)
00316 cache_resources=DestroySplayTree(cache_resources);
00317 instantiate_cache=MagickFalse;
00318 (void) UnlockSemaphoreInfo(cache_semaphore);
00319 DestroySemaphoreInfo(&cache_semaphore);
00320 }
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 static MagickBooleanType ClipPixelCacheNexus(Image *image,
00352 NexusInfo *nexus_info,ExceptionInfo *exception)
00353 {
00354 CacheInfo
00355 *cache_info;
00356
00357 MagickSizeType
00358 number_pixels;
00359
00360 NexusInfo
00361 **clip_nexus,
00362 **image_nexus;
00363
00364 register const PixelPacket
00365 *__restrict r;
00366
00367 register IndexPacket
00368 *__restrict nexus_indexes,
00369 *__restrict indexes;
00370
00371 register long
00372 i;
00373
00374 register PixelPacket
00375 *__restrict p,
00376 *__restrict q;
00377
00378
00379
00380
00381 if (image->debug != MagickFalse)
00382 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
00383 if (image->clip_mask == (Image *) NULL)
00384 return(MagickFalse);
00385 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
00386 if (cache_info == (Cache) NULL)
00387 return(MagickFalse);
00388 image_nexus=AcquirePixelCacheNexus(1);
00389 clip_nexus=AcquirePixelCacheNexus(1);
00390 if ((image_nexus == (NexusInfo **) NULL) ||
00391 (clip_nexus == (NexusInfo **) NULL))
00392 ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
00393 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
00394 nexus_info->region.width,nexus_info->region.height,image_nexus[0],
00395 exception);
00396 indexes=GetPixelCacheNexusIndexes(image->cache,image_nexus[0]);
00397 q=nexus_info->pixels;
00398 nexus_indexes=nexus_info->indexes;
00399 r=GetVirtualPixelsFromNexus(image->clip_mask,MaskVirtualPixelMethod,
00400 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
00401 nexus_info->region.height,clip_nexus[0],exception);
00402 number_pixels=(MagickSizeType) nexus_info->region.width*
00403 nexus_info->region.height;
00404 for (i=0; i < (long) number_pixels; i++)
00405 {
00406 if ((p == (PixelPacket *) NULL) || (r == (const PixelPacket *) NULL))
00407 break;
00408 if (PixelIntensityToQuantum(r) > ((Quantum) QuantumRange/2))
00409 {
00410 q->red=p->red;
00411 q->green=p->green;
00412 q->blue=p->blue;
00413 q->opacity=p->opacity;
00414 if (cache_info->active_index_channel != MagickFalse)
00415 nexus_indexes[i]=indexes[i];
00416 }
00417 p++;
00418 q++;
00419 r++;
00420 }
00421 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
00422 image_nexus=DestroyPixelCacheNexus(image_nexus,1);
00423 if (i < (long) number_pixels)
00424 return(MagickFalse);
00425 return(MagickTrue);
00426 }
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450 MagickExport Cache ClonePixelCache(const Cache cache)
00451 {
00452 CacheInfo
00453 *clone_info;
00454
00455 const CacheInfo
00456 *cache_info;
00457
00458 assert(cache != (const Cache) NULL);
00459 cache_info=(const CacheInfo *) cache;
00460 assert(cache_info->signature == MagickSignature);
00461 if (cache_info->debug != MagickFalse)
00462 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
00463 cache_info->filename);
00464 clone_info=(CacheInfo *) AcquirePixelCache(cache_info->number_threads);
00465 if (clone_info == (Cache) NULL)
00466 return((Cache) NULL);
00467 clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
00468 return((Cache ) clone_info);
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
00498
00499
00500 static inline MagickBooleanType AcquireCacheNexusPixels(CacheInfo *cache_info,
00501 NexusInfo *nexus_info,ExceptionInfo *exception)
00502 {
00503 if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
00504 return(MagickFalse);
00505 nexus_info->mapped=MagickFalse;
00506 nexus_info->cache=(PixelPacket *) AcquireMagickMemory((size_t)
00507 nexus_info->length);
00508 if (nexus_info->cache == (PixelPacket *) NULL)
00509 {
00510 nexus_info->mapped=MagickTrue;
00511 nexus_info->cache=(PixelPacket *) MapBlob(-1,IOMode,0,(size_t)
00512 nexus_info->length);
00513 }
00514 if (nexus_info->cache == (PixelPacket *) NULL)
00515 {
00516 (void) ThrowMagickException(exception,GetMagickModule(),
00517 ResourceLimitError,"MemoryAllocationFailed","`%s'",
00518 cache_info->filename);
00519 return(MagickFalse);
00520 }
00521 return(MagickTrue);
00522 }
00523
00524 static MagickBooleanType ClonePixelCacheNexus(CacheInfo *destination,
00525 CacheInfo *source,ExceptionInfo *exception)
00526 {
00527 MagickBooleanType
00528 status;
00529
00530 MagickSizeType
00531 number_pixels;
00532
00533 register long
00534 i;
00535
00536 register const NexusInfo
00537 *p;
00538
00539 register NexusInfo
00540 *q;
00541
00542 status=MagickTrue;
00543 for (i=0; i < (long) source->number_threads; i++)
00544 {
00545 p=source->nexus_info[i];
00546 q=destination->nexus_info[i];
00547 q->mapped=p->mapped;
00548 q->region=p->region;
00549 q->length=p->length;
00550 q->cache=p->cache;
00551 q->pixels=p->pixels;
00552 q->indexes=p->indexes;
00553 if (p->cache != (PixelPacket *) NULL)
00554 {
00555 status=AcquireCacheNexusPixels(source,q,exception);
00556 if (status != MagickFalse)
00557 {
00558 (void) CopyMagickMemory(q->cache,p->cache,(size_t) p->length);
00559 q->pixels=q->cache;
00560 q->indexes=(IndexPacket *) NULL;
00561 number_pixels=(MagickSizeType) q->region.width*q->region.height;
00562 if (p->indexes != (IndexPacket *) NULL)
00563 q->indexes=(IndexPacket *) (q->pixels+number_pixels);
00564 }
00565 }
00566 }
00567 return(status);
00568 }
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598 static MagickBooleanType ClosePixelCacheOnDisk(CacheInfo *cache_info)
00599 {
00600 int
00601 status;
00602
00603 (void) LockSemaphoreInfo(cache_info->disk_semaphore);
00604 status=close(cache_info->file);
00605 cache_info->file=(-1);
00606 RelinquishMagickResource(FileResource,1);
00607 (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
00608 return(status == -1 ? MagickFalse : MagickTrue);
00609 }
00610
00611 static void LimitPixelCacheDescriptors(void)
00612 {
00613 register CacheInfo
00614 *p,
00615 *q;
00616
00617
00618
00619
00620 if (GetMagickResource(FileResource) < GetMagickResourceLimit(FileResource))
00621 return;
00622 (void) LockSemaphoreInfo(cache_semaphore);
00623 if (cache_resources == (SplayTreeInfo *) NULL)
00624 {
00625 (void) UnlockSemaphoreInfo(cache_semaphore);
00626 return;
00627 }
00628 ResetSplayTreeIterator(cache_resources);
00629 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
00630 while (p != (CacheInfo *) NULL)
00631 {
00632 if ((p->type == DiskCache) && (p->file != -1))
00633 {
00634 if (IsMagickThreadEqual(p->id) != MagickFalse)
00635 break;
00636 }
00637 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
00638 }
00639 for (q=p; p != (CacheInfo *) NULL; )
00640 {
00641 if ((p->type == DiskCache) && (p->file != -1) &&
00642 (p->timestamp < q->timestamp))
00643 {
00644 if (IsMagickThreadEqual(p->id) != MagickFalse)
00645 q=p;
00646 }
00647 p=(CacheInfo *) GetNextKeyInSplayTree(cache_resources);
00648 }
00649 if (q != (CacheInfo *) NULL)
00650 (void) ClosePixelCacheOnDisk(q);
00651 (void) UnlockSemaphoreInfo(cache_semaphore);
00652 }
00653
00654 static inline MagickSizeType MagickMax(const MagickSizeType x,
00655 const MagickSizeType y)
00656 {
00657 if (x > y)
00658 return(x);
00659 return(y);
00660 }
00661
00662 static inline MagickSizeType MagickMin(const MagickSizeType x,
00663 const MagickSizeType y)
00664 {
00665 if (x < y)
00666 return(x);
00667 return(y);
00668 }
00669
00670 static MagickBooleanType OpenPixelCacheOnDisk(CacheInfo *cache_info,
00671 const MapMode mode)
00672 {
00673 int
00674 file;
00675
00676
00677
00678
00679 (void) LockSemaphoreInfo(cache_info->disk_semaphore);
00680 if (cache_info->file != -1)
00681 {
00682 (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
00683 return(MagickTrue);
00684 }
00685 LimitPixelCacheDescriptors();
00686 if (*cache_info->cache_filename == '\0')
00687 file=AcquireUniqueFileResource(cache_info->cache_filename);
00688 else
00689 switch (mode)
00690 {
00691 case ReadMode:
00692 {
00693 file=open(cache_info->cache_filename,O_RDONLY | O_BINARY);
00694 break;
00695 }
00696 case WriteMode:
00697 {
00698 file=open(cache_info->cache_filename,O_WRONLY | O_CREAT | O_BINARY |
00699 O_EXCL,S_MODE);
00700 if (file == -1)
00701 file=open(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
00702 break;
00703 }
00704 case IOMode:
00705 default:
00706 {
00707 file=open(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
00708 O_EXCL,S_MODE);
00709 if (file == -1)
00710 file=open(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
00711 break;
00712 }
00713 }
00714 if (file == -1)
00715 {
00716 (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
00717 return(MagickFalse);
00718 }
00719 (void) AcquireMagickResource(FileResource,1);
00720 cache_info->file=file;
00721 cache_info->timestamp=time(0);
00722 (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
00723 return(MagickTrue);
00724 }
00725
00726 static inline MagickOffsetType ReadPixelCacheRegion(CacheInfo *cache_info,
00727 const MagickOffsetType offset,const MagickSizeType length,
00728 unsigned char *__restrict buffer)
00729 {
00730 register MagickOffsetType
00731 i;
00732
00733 ssize_t
00734 count;
00735
00736 #if !defined(MAGICKCORE_HAVE_PREAD)
00737 (void) LockSemaphoreInfo(cache_info->disk_semaphore);
00738 cache_info->timestamp=time(0);
00739 if (MagickSeek(cache_info->file,offset,SEEK_SET) < 0)
00740 {
00741 (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
00742 return((MagickOffsetType) -1);
00743 }
00744 #endif
00745 count=0;
00746 for (i=0; i < (MagickOffsetType) length; i+=count)
00747 {
00748 #if !defined(MAGICKCORE_HAVE_PREAD)
00749 count=read(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
00750 (MagickSizeType) SSIZE_MAX));
00751 #else
00752 count=pread(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
00753 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
00754 #endif
00755 if (count > 0)
00756 continue;
00757 count=0;
00758 if (errno != EINTR)
00759 {
00760 i=(-1);
00761 break;
00762 }
00763 }
00764 #if !defined(MAGICKCORE_HAVE_PREAD)
00765 (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
00766 #endif
00767 return(i);
00768 }
00769
00770 static inline MagickOffsetType WritePixelCacheRegion(CacheInfo *cache_info,
00771 const MagickOffsetType offset,const MagickSizeType length,
00772 const unsigned char *__restrict buffer)
00773 {
00774 register MagickOffsetType
00775 i;
00776
00777 ssize_t
00778 count;
00779
00780 #if !defined(MAGICKCORE_HAVE_PWRITE)
00781 (void) LockSemaphoreInfo(cache_info->disk_semaphore);
00782 cache_info->timestamp=time(0);
00783 if (MagickSeek(cache_info->file,offset,SEEK_SET) < 0)
00784 {
00785 (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
00786 return((MagickOffsetType) -1);
00787 }
00788 #endif
00789 count=0;
00790 for (i=0; i < (MagickOffsetType) length; i+=count)
00791 {
00792 #if !defined(MAGICKCORE_HAVE_PWRITE)
00793 count=write(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
00794 (MagickSizeType) SSIZE_MAX));
00795 #else
00796 count=pwrite(cache_info->file,buffer+i,(size_t) MagickMin(length-i,
00797 (MagickSizeType) SSIZE_MAX),(off_t) (offset+i));
00798 #endif
00799 if (count > 0)
00800 continue;
00801 count=0;
00802 if (errno != EINTR)
00803 {
00804 i=(-1);
00805 break;
00806 }
00807 }
00808 #if !defined(MAGICKCORE_HAVE_PWRITE)
00809 (void) UnlockSemaphoreInfo(cache_info->disk_semaphore);
00810 #endif
00811 return(i);
00812 }
00813
00814 static MagickBooleanType CloneDiskToDiskPixelCache(CacheInfo *clone_info,
00815 CacheInfo *cache_info,ExceptionInfo *exception)
00816 {
00817 MagickOffsetType
00818 count,
00819 offset,
00820 source_offset;
00821
00822 MagickSizeType
00823 length;
00824
00825 register long
00826 y;
00827
00828 register PixelPacket
00829 *__restrict pixels;
00830
00831 unsigned long
00832 columns,
00833 rows;
00834
00835 if (cache_info->debug != MagickFalse)
00836 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => disk");
00837 if (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse)
00838 {
00839 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
00840 clone_info->cache_filename);
00841 return(MagickFalse);
00842 }
00843 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
00844 {
00845 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
00846 cache_info->cache_filename);
00847 return(MagickFalse);
00848 }
00849 columns=(unsigned long) MagickMin(clone_info->columns,cache_info->columns);
00850 rows=(unsigned long) MagickMin(clone_info->rows,cache_info->rows);
00851 if ((clone_info->active_index_channel != MagickFalse) &&
00852 (cache_info->active_index_channel != MagickFalse))
00853 {
00854 register IndexPacket
00855 *indexes;
00856
00857
00858
00859
00860 length=MagickMax(clone_info->columns,cache_info->columns)*
00861 sizeof(*indexes);
00862 indexes=(IndexPacket *) AcquireMagickMemory((size_t) length);
00863 if (indexes == (IndexPacket *) NULL)
00864 {
00865 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
00866 "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
00867 return(MagickFalse);
00868 }
00869 (void) ResetMagickMemory(indexes,0,(size_t) length);
00870 length=columns*sizeof(*indexes);
00871 source_offset=(MagickOffsetType) cache_info->columns*cache_info->rows*
00872 sizeof(*pixels)+cache_info->columns*rows*sizeof(*indexes);
00873 offset=(MagickOffsetType) clone_info->columns*clone_info->rows*
00874 sizeof(*pixels)+clone_info->columns*rows*sizeof(*indexes);
00875 for (y=0; y < (long) rows; y++)
00876 {
00877 source_offset-=cache_info->columns*sizeof(*indexes);
00878 count=ReadPixelCacheRegion(cache_info,cache_info->offset+source_offset,
00879 length,(unsigned char *) indexes);
00880 if ((MagickSizeType) count != length)
00881 break;
00882 offset-=clone_info->columns*sizeof(*indexes);
00883 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
00884 (unsigned char *) indexes);
00885 if ((MagickSizeType) count != length)
00886 break;
00887 }
00888 if (y < (long) rows)
00889 {
00890 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
00891 ThrowFileException(exception,CacheError,"UnableToCloneCache",
00892 cache_info->cache_filename);
00893 return(MagickFalse);
00894 }
00895 if (clone_info->columns > cache_info->columns)
00896 {
00897 length=(clone_info->columns-cache_info->columns)*sizeof(*indexes);
00898 (void) ResetMagickMemory(indexes,0,(size_t) length);
00899 offset=(MagickOffsetType) clone_info->columns*clone_info->rows*
00900 sizeof(*pixels)+(clone_info->columns*rows+columns)*sizeof(*indexes);
00901 for (y=0; y < (long) rows; y++)
00902 {
00903 offset-=clone_info->columns*sizeof(*indexes);
00904 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,
00905 length,(unsigned char *) indexes);
00906 if ((MagickSizeType) count != length)
00907 break;
00908 }
00909 if (y < (long) rows)
00910 {
00911 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
00912 ThrowFileException(exception,CacheError,"UnableToCloneCache",
00913 cache_info->cache_filename);
00914 return(MagickFalse);
00915 }
00916 }
00917 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
00918 }
00919
00920
00921
00922 length=MagickMax(clone_info->columns,cache_info->columns)*sizeof(*pixels);
00923 pixels=(PixelPacket *) AcquireMagickMemory((size_t) length);
00924 if (pixels == (PixelPacket *) NULL)
00925 {
00926 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
00927 "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
00928 return(MagickFalse);
00929 }
00930 (void) ResetMagickMemory(pixels,0,(size_t) length);
00931 length=columns*sizeof(*pixels);
00932 source_offset=(MagickOffsetType) cache_info->columns*rows*sizeof(*pixels);
00933 offset=(MagickOffsetType) clone_info->columns*rows*sizeof(*pixels);
00934 for (y=0; y < (long) rows; y++)
00935 {
00936 source_offset-=cache_info->columns*sizeof(*pixels);
00937 count=ReadPixelCacheRegion(cache_info,cache_info->offset+source_offset,
00938 length,(unsigned char *) pixels);
00939 if ((MagickSizeType) count != length)
00940 break;
00941 offset-=clone_info->columns*sizeof(*pixels);
00942 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
00943 (unsigned char *) pixels);
00944 if ((MagickSizeType) count != length)
00945 break;
00946 }
00947 if (y < (long) rows)
00948 {
00949 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
00950 ThrowFileException(exception,CacheError,"UnableToCloneCache",
00951 cache_info->cache_filename);
00952 return(MagickFalse);
00953 }
00954 if (clone_info->columns > cache_info->columns)
00955 {
00956 offset=(MagickOffsetType) (clone_info->columns*rows+columns)*
00957 sizeof(*pixels);
00958 length=(clone_info->columns-cache_info->columns)*sizeof(*pixels);
00959 (void) ResetMagickMemory(pixels,0,(size_t) length);
00960 for (y=0; y < (long) rows; y++)
00961 {
00962 offset-=clone_info->columns*sizeof(*pixels);
00963 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
00964 (unsigned char *) pixels);
00965 if ((MagickSizeType) count != length)
00966 break;
00967 }
00968 if (y < (long) rows)
00969 {
00970 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
00971 ThrowFileException(exception,CacheError,"UnableToCloneCache",
00972 cache_info->cache_filename);
00973 return(MagickFalse);
00974 }
00975 }
00976 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
00977 return(MagickTrue);
00978 }
00979
00980 static MagickBooleanType CloneDiskToMemoryPixelCache(CacheInfo *clone_info,
00981 CacheInfo *cache_info,ExceptionInfo *exception)
00982 {
00983 MagickOffsetType
00984 count,
00985 offset;
00986
00987 MagickSizeType
00988 length;
00989
00990 register long
00991 y;
00992
00993 register PixelPacket
00994 *__restrict pixels,
00995 *__restrict q;
00996
00997 unsigned long
00998 columns,
00999 rows;
01000
01001 if (cache_info->debug != MagickFalse)
01002 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"disk => memory");
01003 if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
01004 {
01005 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
01006 cache_info->cache_filename);
01007 return(MagickFalse);
01008 }
01009 columns=(unsigned long) MagickMin(clone_info->columns,cache_info->columns);
01010 rows=(unsigned long) MagickMin(clone_info->rows,cache_info->rows);
01011 if ((clone_info->active_index_channel != MagickFalse) &&
01012 (cache_info->active_index_channel != MagickFalse))
01013 {
01014 register IndexPacket
01015 *indexes,
01016 *q;
01017
01018
01019
01020
01021 length=MagickMax(clone_info->columns,cache_info->columns)*
01022 sizeof(*indexes);
01023 indexes=(IndexPacket *) AcquireMagickMemory((size_t) length);
01024 if (indexes == (IndexPacket *) NULL)
01025 {
01026 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
01027 "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
01028 return(MagickFalse);
01029 }
01030 (void) ResetMagickMemory(indexes,0,(size_t) length);
01031 length=columns*sizeof(IndexPacket);
01032 offset=(MagickOffsetType) cache_info->columns*cache_info->rows*
01033 sizeof(*pixels)+cache_info->columns*rows*sizeof(*indexes);
01034 q=clone_info->indexes+clone_info->columns*rows;
01035 for (y=0; y < (long) rows; y++)
01036 {
01037 offset-=cache_info->columns*sizeof(IndexPacket);
01038 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset,
01039 length,(unsigned char *) indexes);
01040 if ((MagickSizeType) count != length)
01041 break;
01042 q-=clone_info->columns;
01043 (void) CopyMagickMemory(q,indexes,(size_t) length);
01044 if ((MagickSizeType) count != length)
01045 break;
01046 }
01047 if (y < (long) rows)
01048 {
01049 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
01050 ThrowFileException(exception,CacheError,"UnableToCloneCache",
01051 cache_info->cache_filename);
01052 return(MagickFalse);
01053 }
01054 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
01055 }
01056
01057
01058
01059 length=MagickMax(clone_info->columns,cache_info->columns)*sizeof(*pixels);
01060 pixels=(PixelPacket *) AcquireMagickMemory((size_t) length);
01061 if (pixels == (PixelPacket *) NULL)
01062 {
01063 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
01064 "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
01065 return(MagickFalse);
01066 }
01067 (void) ResetMagickMemory(pixels,0,(size_t) length);
01068 length=columns*sizeof(*pixels);
01069 offset=(MagickOffsetType) cache_info->columns*rows*sizeof(*pixels);
01070 q=clone_info->pixels+clone_info->columns*rows;
01071 for (y=0; y < (long) rows; y++)
01072 {
01073 offset-=cache_info->columns*sizeof(*pixels);
01074 count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset,length,
01075 (unsigned char *) pixels);
01076 if ((MagickSizeType) count != length)
01077 break;
01078 q-=clone_info->columns;
01079 (void) CopyMagickMemory(q,pixels,(size_t) length);
01080 }
01081 if (y < (long) rows)
01082 {
01083 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
01084 ThrowFileException(exception,CacheError,"UnableToCloneCache",
01085 cache_info->cache_filename);
01086 return(MagickFalse);
01087 }
01088 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
01089 return(MagickTrue);
01090 }
01091
01092 static MagickBooleanType CloneMemoryToDiskPixelCache(CacheInfo *clone_info,
01093 CacheInfo *cache_info,ExceptionInfo *exception)
01094 {
01095 MagickOffsetType
01096 count,
01097 offset;
01098
01099 MagickSizeType
01100 length;
01101
01102 register long
01103 y;
01104
01105 register PixelPacket
01106 *__restrict p,
01107 *__restrict pixels;
01108
01109 unsigned long
01110 columns,
01111 rows;
01112
01113 if (cache_info->debug != MagickFalse)
01114 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => disk");
01115 if (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse)
01116 {
01117 ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
01118 clone_info->cache_filename);
01119 return(MagickFalse);
01120 }
01121 columns=(unsigned long) MagickMin(clone_info->columns,cache_info->columns);
01122 rows=(unsigned long) MagickMin(clone_info->rows,cache_info->rows);
01123 if ((clone_info->active_index_channel != MagickFalse) &&
01124 (cache_info->active_index_channel != MagickFalse))
01125 {
01126 register IndexPacket
01127 *p,
01128 *indexes;
01129
01130
01131
01132
01133 length=MagickMax(clone_info->columns,cache_info->columns)*
01134 sizeof(*indexes);
01135 indexes=(IndexPacket *) AcquireMagickMemory((size_t) length);
01136 if (indexes == (IndexPacket *) NULL)
01137 {
01138 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
01139 "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
01140 return(MagickFalse);
01141 }
01142 (void) ResetMagickMemory(indexes,0,(size_t) length);
01143 length=columns*sizeof(*indexes);
01144 p=cache_info->indexes+cache_info->columns*rows;
01145 offset=(MagickOffsetType) clone_info->columns*clone_info->rows*
01146 sizeof(*pixels)+clone_info->columns*rows*sizeof(*indexes);
01147 for (y=0; y < (long) rows; y++)
01148 {
01149 p-=cache_info->columns;
01150 (void) CopyMagickMemory(indexes,p,(size_t) length);
01151 offset-=clone_info->columns*sizeof(*indexes);
01152 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
01153 (unsigned char *) indexes);
01154 if ((MagickSizeType) count != length)
01155 break;
01156 }
01157 if (y < (long) rows)
01158 {
01159 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
01160 ThrowFileException(exception,CacheError,"UnableToCloneCache",
01161 cache_info->cache_filename);
01162 return(MagickFalse);
01163 }
01164 if (clone_info->columns > cache_info->columns)
01165 {
01166 length=(clone_info->columns-cache_info->columns)*sizeof(*indexes);
01167 (void) ResetMagickMemory(indexes,0,(size_t) length);
01168 offset=(MagickOffsetType) clone_info->columns*clone_info->rows*
01169 sizeof(*pixels)+(clone_info->columns*rows+columns)*sizeof(*indexes);
01170 for (y=0; y < (long) rows; y++)
01171 {
01172 offset-=clone_info->columns*sizeof(*indexes);
01173 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,
01174 length,(unsigned char *) indexes);
01175 if ((MagickSizeType) count != length)
01176 break;
01177 }
01178 if (y < (long) rows)
01179 {
01180 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
01181 ThrowFileException(exception,CacheError,"UnableToCloneCache",
01182 cache_info->cache_filename);
01183 return(MagickFalse);
01184 }
01185 }
01186 indexes=(IndexPacket *) RelinquishMagickMemory(indexes);
01187 }
01188
01189
01190
01191 length=MagickMax(clone_info->columns,cache_info->columns)*sizeof(*pixels);
01192 pixels=(PixelPacket *) AcquireMagickMemory((size_t) length);
01193 if (pixels == (PixelPacket *) NULL)
01194 {
01195 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
01196 "MemoryAllocationFailed","`%s'",cache_info->cache_filename);
01197 return(MagickFalse);
01198 }
01199 (void) ResetMagickMemory(pixels,0,(size_t) length);
01200 length=columns*sizeof(*pixels);
01201 p=cache_info->pixels+cache_info->columns*rows;
01202 offset=(MagickOffsetType) clone_info->columns*rows*sizeof(*pixels);
01203 for (y=0; y < (long) rows; y++)
01204 {
01205 p-=cache_info->columns;
01206 (void) CopyMagickMemory(pixels,p,(size_t) length);
01207 offset-=clone_info->columns*sizeof(*pixels);
01208 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
01209 (unsigned char *) pixels);
01210 if ((MagickSizeType) count != length)
01211 break;
01212 }
01213 if (y < (long) rows)
01214 {
01215 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
01216 ThrowFileException(exception,CacheError,"UnableToCloneCache",
01217 cache_info->cache_filename);
01218 return(MagickFalse);
01219 }
01220 if (clone_info->columns > cache_info->columns)
01221 {
01222 offset=(MagickOffsetType) (clone_info->columns*rows+columns)*
01223 sizeof(*pixels);
01224 length=(clone_info->columns-cache_info->columns)*sizeof(*pixels);
01225 (void) ResetMagickMemory(pixels,0,(size_t) length);
01226 for (y=0; y < (long) rows; y++)
01227 {
01228 offset-=clone_info->columns*sizeof(*pixels);
01229 count=WritePixelCacheRegion(clone_info,clone_info->offset+offset,length,
01230 (unsigned char *) pixels);
01231 if ((MagickSizeType) count != length)
01232 break;
01233 }
01234 if (y < (long) rows)
01235 {
01236 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
01237 ThrowFileException(exception,CacheError,"UnableToCloneCache",
01238 cache_info->cache_filename);
01239 return(MagickFalse);
01240 }
01241 }
01242 pixels=(PixelPacket *) RelinquishMagickMemory(pixels);
01243 return(MagickTrue);
01244 }
01245
01246 static MagickBooleanType CloneMemoryToMemoryPixelCache(CacheInfo *clone_info,
01247 CacheInfo *cache_info,ExceptionInfo *magick_unused(exception))
01248 {
01249 register long
01250 y;
01251
01252 register PixelPacket
01253 *__restrict pixels,
01254 *__restrict source_pixels;
01255
01256 size_t
01257 length;
01258
01259 unsigned long
01260 columns,
01261 rows;
01262
01263 if (cache_info->debug != MagickFalse)
01264 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"memory => memory");
01265 columns=(unsigned long) MagickMin(clone_info->columns,cache_info->columns);
01266 rows=(unsigned long) MagickMin(clone_info->rows,cache_info->rows);
01267 if ((clone_info->active_index_channel != MagickFalse) &&
01268 (cache_info->active_index_channel != MagickFalse))
01269 {
01270 register IndexPacket
01271 *indexes,
01272 *source_indexes;
01273
01274
01275
01276
01277 length=columns*sizeof(*indexes);
01278 if (clone_info->columns == cache_info->columns)
01279 (void) CopyMagickMemory(clone_info->indexes,cache_info->indexes,
01280 length*rows);
01281 else
01282 {
01283 source_indexes=cache_info->indexes+cache_info->columns*rows;
01284 indexes=clone_info->indexes+clone_info->columns*rows;
01285 for (y=0; y < (long) rows; y++)
01286 {
01287 source_indexes-=cache_info->columns;
01288 indexes-=clone_info->columns;
01289 (void) CopyMagickMemory(indexes,source_indexes,length);
01290 }
01291 if (clone_info->columns > cache_info->columns)
01292 {
01293 length=(clone_info->columns-cache_info->columns)*
01294 sizeof(*indexes);
01295 indexes=clone_info->indexes+clone_info->columns*rows+
01296 cache_info->columns;
01297 for (y=0; y < (long) rows; y++)
01298 {
01299 indexes-=clone_info->columns;
01300 (void) ResetMagickMemory(indexes,0,length);
01301 }
01302 }
01303 }
01304 }
01305
01306
01307
01308 length=columns*sizeof(*pixels);
01309 if (clone_info->columns == cache_info->columns)
01310 (void) CopyMagickMemory(clone_info->pixels,cache_info->pixels,length*rows);
01311 else
01312 {
01313 source_pixels=cache_info->pixels+cache_info->columns*rows;
01314 pixels=clone_info->pixels+clone_info->columns*rows;
01315 for (y=0; y < (long) rows; y++)
01316 {
01317 source_pixels-=cache_info->columns;
01318 pixels-=clone_info->columns;
01319 (void) CopyMagickMemory(pixels,source_pixels,length);
01320 }
01321 if (clone_info->columns > cache_info->columns)
01322 {
01323 length=(clone_info->columns-cache_info->columns)*sizeof(*pixels);
01324 pixels=clone_info->pixels+clone_info->columns*rows+
01325 cache_info->columns;
01326 for (y=0; y < (long) rows; y++)
01327 {
01328 pixels-=clone_info->columns;
01329 (void) ResetMagickMemory(pixels,0,length);
01330 }
01331 }
01332 }
01333 return(MagickTrue);
01334 }
01335
01336 static MagickBooleanType ClonePixelCachePixels(CacheInfo *clone_info,
01337 CacheInfo *cache_info,ExceptionInfo *exception)
01338 {
01339 if ((clone_info->type != DiskCache) && (cache_info->type != DiskCache))
01340 return(CloneMemoryToMemoryPixelCache(clone_info,cache_info,exception));
01341 if ((clone_info->type == DiskCache) && (cache_info->type == DiskCache))
01342 return(CloneDiskToDiskPixelCache(clone_info,cache_info,exception));
01343 if (cache_info->type == DiskCache)
01344 return(CloneDiskToMemoryPixelCache(clone_info,cache_info,exception));
01345 return(CloneMemoryToDiskPixelCache(clone_info,cache_info,exception));
01346 }
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373 MagickExport void ClonePixelCacheMethods(Cache clone,const Cache cache)
01374 {
01375 CacheInfo
01376 *cache_info,
01377 *source_info;
01378
01379 assert(clone != (Cache) NULL);
01380 source_info=(CacheInfo *) clone;
01381 assert(source_info->signature == MagickSignature);
01382 if (source_info->debug != MagickFalse)
01383 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
01384 source_info->filename);
01385 assert(cache != (Cache) NULL);
01386 cache_info=(CacheInfo *) cache;
01387 assert(cache_info->signature == MagickSignature);
01388 source_info->methods=cache_info->methods;
01389 }
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413 static void DestroyImagePixelCache(Image *image)
01414 {
01415 assert(image != (Image *) NULL);
01416 assert(image->signature == MagickSignature);
01417 if (image->debug != MagickFalse)
01418 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01419 if (image->cache == (void *) NULL)
01420 return;
01421 image->cache=DestroyPixelCache(image->cache);
01422 }
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446 MagickExport void DestroyImagePixels(Image *image)
01447 {
01448 CacheInfo
01449 *cache_info;
01450
01451 assert(image != (const Image *) NULL);
01452 assert(image->signature == MagickSignature);
01453 if (image->debug != MagickFalse)
01454 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01455 assert(image->cache != (Cache) NULL);
01456 cache_info=(CacheInfo *) image->cache;
01457 assert(cache_info->signature == MagickSignature);
01458 if (cache_info->methods.destroy_pixel_handler == (DestroyPixelHandler) NULL)
01459 return;
01460 cache_info->methods.destroy_pixel_handler(image);
01461 }
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486 static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
01487 {
01488 switch (cache_info->type)
01489 {
01490 case MemoryCache:
01491 {
01492 if (cache_info->mapped == MagickFalse)
01493 cache_info->pixels=(PixelPacket *) RelinquishMagickMemory(
01494 cache_info->pixels);
01495 else
01496 cache_info->pixels=(PixelPacket *) UnmapBlob(cache_info->pixels,
01497 (size_t) cache_info->length);
01498 RelinquishMagickResource(MemoryResource,cache_info->length);
01499 break;
01500 }
01501 case MapCache:
01502 {
01503 cache_info->pixels=(PixelPacket *) UnmapBlob(cache_info->pixels,(size_t)
01504 cache_info->length);
01505 RelinquishMagickResource(MapResource,cache_info->length);
01506 }
01507 case DiskCache:
01508 {
01509 if (cache_info->file != -1)
01510 (void) ClosePixelCacheOnDisk(cache_info);
01511 RelinquishMagickResource(DiskResource,cache_info->length);
01512 break;
01513 }
01514 default:
01515 break;
01516 }
01517 cache_info->type=UndefinedCache;
01518 cache_info->mapped=MagickFalse;
01519 cache_info->indexes=(IndexPacket *) NULL;
01520 }
01521
01522 MagickExport Cache DestroyPixelCache(Cache cache)
01523 {
01524 CacheInfo
01525 *cache_info;
01526
01527 assert(cache != (Cache) NULL);
01528 cache_info=(CacheInfo *) cache;
01529 assert(cache_info->signature == MagickSignature);
01530 if (cache_info->debug != MagickFalse)
01531 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
01532 cache_info->filename);
01533 (void) LockSemaphoreInfo(cache_info->semaphore);
01534 cache_info->reference_count--;
01535 if (cache_info->reference_count != 0)
01536 {
01537 (void) UnlockSemaphoreInfo(cache_info->semaphore);
01538 return((Cache) NULL);
01539 }
01540 (void) UnlockSemaphoreInfo(cache_info->semaphore);
01541 if (cache_resources != (SplayTreeInfo *) NULL)
01542 (void) DeleteNodeByValueFromSplayTree(cache_resources,cache_info);
01543 if (cache_info->debug != MagickFalse)
01544 {
01545 char
01546 message[MaxTextExtent];
01547
01548 (void) FormatMagickString(message,MaxTextExtent,"destroy %s",
01549 cache_info->filename);
01550 (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
01551 }
01552 if ((cache_info->mode == ReadMode) || ((cache_info->type != MapCache) &&
01553 (cache_info->type != DiskCache)))
01554 RelinquishPixelCachePixels(cache_info);
01555 else
01556 {
01557 RelinquishPixelCachePixels(cache_info);
01558 (void) RelinquishUniqueFileResource(cache_info->cache_filename);
01559 }
01560 *cache_info->cache_filename='\0';
01561 if (cache_info->nexus_info != (NexusInfo **) NULL)
01562 cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
01563 cache_info->number_threads);
01564 if (cache_info->random_info != (RandomInfo *) NULL)
01565 cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
01566 cache_info->signature=(~MagickSignature);
01567 if (cache_info->disk_semaphore != (SemaphoreInfo *) NULL)
01568 DestroySemaphoreInfo(&cache_info->disk_semaphore);
01569 if (cache_info->semaphore != (SemaphoreInfo *) NULL)
01570 DestroySemaphoreInfo(&cache_info->semaphore);
01571 cache_info=(CacheInfo *) RelinquishAlignedMemory(cache_info);
01572 cache=(Cache) NULL;
01573 return(cache);
01574 }
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602 static inline void RelinquishCacheNexusPixels(NexusInfo *nexus_info)
01603 {
01604 if (nexus_info->mapped == MagickFalse)
01605 (void) RelinquishMagickMemory(nexus_info->cache);
01606 else
01607 (void) UnmapBlob(nexus_info->cache,(size_t) nexus_info->length);
01608 nexus_info->cache=(PixelPacket *) NULL;
01609 nexus_info->pixels=(PixelPacket *) NULL;
01610 nexus_info->indexes=(IndexPacket *) NULL;
01611 nexus_info->length=0;
01612 nexus_info->mapped=MagickFalse;
01613 }
01614
01615 MagickExport NexusInfo **DestroyPixelCacheNexus(NexusInfo **nexus_info,
01616 const unsigned long number_threads)
01617 {
01618 register long
01619 i;
01620
01621 assert(nexus_info != (NexusInfo **) NULL);
01622 for (i=0; i < (long) number_threads; i++)
01623 {
01624 if (nexus_info[i]->cache != (PixelPacket *) NULL)
01625 RelinquishCacheNexusPixels(nexus_info[i]);
01626 nexus_info[i]->signature=(~MagickSignature);
01627 nexus_info[i]=(NexusInfo *) RelinquishAlignedMemory(nexus_info[i]);
01628 }
01629 nexus_info=(NexusInfo **) RelinquishAlignedMemory(nexus_info);
01630 return(nexus_info);
01631 }
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656 static IndexPacket *GetAuthenticIndexesFromCache(const Image *image)
01657 {
01658 CacheInfo
01659 *cache_info;
01660
01661 IndexPacket
01662 *indexes;
01663
01664 long
01665 id;
01666
01667 if (image->debug != MagickFalse)
01668 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01669 cache_info=(CacheInfo *) image->cache;
01670 id=GetOpenMPThreadId();
01671 assert(id < (long) cache_info->number_threads);
01672 indexes=GetPixelCacheNexusIndexes(image->cache,cache_info->nexus_info[id]);
01673 return(indexes);
01674 }
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701 MagickExport IndexPacket *GetAuthenticIndexQueue(const Image *image)
01702 {
01703 CacheInfo
01704 *cache_info;
01705
01706 assert(image != (const Image *) NULL);
01707 assert(image->signature == MagickSignature);
01708 if (image->debug != MagickFalse)
01709 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01710 assert(image->cache != (Cache) NULL);
01711 cache_info=(CacheInfo *) image->cache;
01712 assert(cache_info->signature == MagickSignature);
01713 if (cache_info->methods.get_authentic_indexes_from_handler ==
01714 (GetAuthenticIndexesFromHandler) NULL)
01715 return((IndexPacket *) NULL);
01716 return(cache_info->methods.get_authentic_indexes_from_handler(image));
01717 }
01718
01719
01720
01721
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
01748
01749
01750
01751
01752
01753
01754 static inline MagickBooleanType IsNexusInCore(const CacheInfo *cache_info,
01755 NexusInfo *nexus_info)
01756 {
01757 MagickOffsetType
01758 offset;
01759
01760 offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
01761 nexus_info->region.x;
01762 if (nexus_info->pixels != (cache_info->pixels+offset))
01763 return(MagickFalse);
01764 return(MagickTrue);
01765 }
01766
01767 MagickExport PixelPacket *GetAuthenticPixelCacheNexus(Image *image,const long x,
01768 const long y,const unsigned long columns,const unsigned long rows,
01769 NexusInfo *nexus_info,ExceptionInfo *exception)
01770 {
01771 CacheInfo
01772 *cache_info;
01773
01774 PixelPacket
01775 *pixels;
01776
01777
01778
01779
01780 assert(image != (Image *) NULL);
01781 assert(image->signature == MagickSignature);
01782 if (image->debug != MagickFalse)
01783 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01784 pixels=QueueAuthenticNexus(image,x,y,columns,rows,nexus_info,exception);
01785 if (pixels == (PixelPacket *) NULL)
01786 return((PixelPacket *) NULL);
01787 cache_info=(CacheInfo *) image->cache;
01788 assert(cache_info->signature == MagickSignature);
01789 if (IsNexusInCore(cache_info,nexus_info) != MagickFalse)
01790 return(pixels);
01791 if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
01792 return((PixelPacket *) NULL);
01793 if (cache_info->active_index_channel != MagickFalse)
01794 if (ReadPixelCacheIndexes(cache_info,nexus_info,exception) == MagickFalse)
01795 return((PixelPacket *) NULL);
01796 return(pixels);
01797 }
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822 static PixelPacket *GetAuthenticPixelsFromCache(const Image *image)
01823 {
01824 CacheInfo
01825 *cache_info;
01826
01827 long
01828 id;
01829
01830 PixelPacket
01831 *pixels;
01832
01833 if (image->debug != MagickFalse)
01834 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01835 cache_info=(CacheInfo *) image->cache;
01836 id=GetOpenMPThreadId();
01837 assert(id < (long) cache_info->number_threads);
01838 pixels=GetPixelCacheNexusPixels(image->cache,cache_info->nexus_info[id]);
01839 return(pixels);
01840 }
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865 MagickExport PixelPacket *GetAuthenticPixelQueue(const Image *image)
01866 {
01867 CacheInfo
01868 *cache_info;
01869
01870 assert(image != (const Image *) NULL);
01871 assert(image->signature == MagickSignature);
01872 if (image->debug != MagickFalse)
01873 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01874 assert(image->cache != (Cache) NULL);
01875 cache_info=(CacheInfo *) image->cache;
01876 assert(cache_info->signature == MagickSignature);
01877 if (cache_info->methods.get_authentic_pixels_from_handler ==
01878 (GetAuthenticPixelsFromHandler) NULL)
01879 return((PixelPacket *) NULL);
01880 return(cache_info->methods.get_authentic_pixels_from_handler(image));
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
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929 MagickExport PixelPacket *GetAuthenticPixels(Image *image,const long x,
01930 const long y,const unsigned long columns,const unsigned long rows,
01931 ExceptionInfo *exception)
01932 {
01933 CacheInfo
01934 *cache_info;
01935
01936 PixelPacket
01937 *pixels;
01938
01939 assert(image != (Image *) NULL);
01940 assert(image->signature == MagickSignature);
01941 if (image->debug != MagickFalse)
01942 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
01943 assert(image->cache != (Cache) NULL);
01944 cache_info=(CacheInfo *) image->cache;
01945 assert(cache_info->signature == MagickSignature);
01946 if (cache_info->methods.get_authentic_pixels_handler ==
01947 (GetAuthenticPixelsHandler) NULL)
01948 return((PixelPacket *) NULL);
01949 pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
01950 rows,exception);
01951 return(pixels);
01952 }
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985 static PixelPacket *GetAuthenticPixelsCache(Image *image,const long x,
01986 const long y,const unsigned long columns,const unsigned long rows,
01987 ExceptionInfo *exception)
01988 {
01989 CacheInfo
01990 *cache_info;
01991
01992 long
01993 id;
01994
01995 PixelPacket
01996 *pixels;
01997
01998 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
01999 if (cache_info == (Cache) NULL)
02000 return((PixelPacket *) NULL);
02001 id=GetOpenMPThreadId();
02002 assert(id < (long) cache_info->number_threads);
02003 pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
02004 cache_info->nexus_info[id],exception);
02005 return(pixels);
02006 }
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031 MagickExport MagickSizeType GetImageExtent(const Image *image)
02032 {
02033 CacheInfo
02034 *cache_info;
02035
02036 long
02037 id;
02038
02039 MagickSizeType
02040 extent;
02041
02042 assert(image != (Image *) NULL);
02043 assert(image->signature == MagickSignature);
02044 if (image->debug != MagickFalse)
02045 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02046 assert(image->cache != (Cache) NULL);
02047 cache_info=(CacheInfo *) image->cache;
02048 assert(cache_info->signature == MagickSignature);
02049 id=GetOpenMPThreadId();
02050 assert(id < (long) cache_info->number_threads);
02051 extent=GetPixelCacheNexusExtent(image->cache,cache_info->nexus_info[id]);
02052 return(extent);
02053 }
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085 static inline MagickBooleanType ValidatePixelCacheMorphology(const Image *image)
02086 {
02087 CacheInfo
02088 *cache_info;
02089
02090
02091
02092
02093 cache_info=(CacheInfo *) image->cache;
02094 if ((image->storage_class != cache_info->storage_class) ||
02095 (image->colorspace != cache_info->colorspace) ||
02096 (image->columns != cache_info->columns) ||
02097 (image->rows != cache_info->rows) ||
02098 (cache_info->nexus_info == (NexusInfo **) NULL) ||
02099 (cache_info->number_threads < GetOpenMPMaximumThreads()))
02100 return(MagickFalse);
02101 return(MagickTrue);
02102 }
02103
02104 MagickExport Cache GetImagePixelCache(Image *image,
02105 const MagickBooleanType clone,ExceptionInfo *exception)
02106 {
02107 CacheInfo
02108 *cache_info;
02109
02110 MagickSizeType
02111 time_limit;
02112
02113 MagickBooleanType
02114 destroy,
02115 status;
02116
02117 if (image->debug != MagickFalse)
02118 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02119 status=MagickTrue;
02120 (void) LockSemaphoreInfo(image->semaphore);
02121 time_limit=GetMagickResourceLimit(TimeResource);
02122 if (cache_timer == 0)
02123 cache_timer=time((time_t *) NULL);
02124 if ((time_limit != MagickResourceInfinity) &&
02125 ((MagickSizeType) (time((time_t *) NULL)-cache_timer) >= time_limit))
02126 ThrowFatalException(ResourceLimitFatalError,"TimeLimitExceeded");
02127 assert(image->cache != (Cache) NULL);
02128 cache_info=(CacheInfo *) image->cache;
02129 destroy=MagickFalse;
02130 (void) LockSemaphoreInfo(cache_info->semaphore);
02131 if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
02132 {
02133 Image
02134 clone_image;
02135
02136 CacheInfo
02137 *clone_info;
02138
02139
02140
02141
02142 clone_image=(*image);
02143 clone_image.cache=ClonePixelCache(cache_info);
02144 clone_info=(CacheInfo *) clone_image.cache;
02145 status=ClonePixelCacheNexus(cache_info,clone_info,exception);
02146 if (status != MagickFalse)
02147 {
02148 status=OpenPixelCache(&clone_image,IOMode,exception);
02149 if (status != MagickFalse)
02150 {
02151 if (clone != MagickFalse)
02152 status=ClonePixelCachePixels(clone_info,cache_info,exception);
02153 if (status != MagickFalse)
02154 {
02155 destroy=MagickTrue;
02156 image->cache=clone_image.cache;
02157 }
02158 }
02159 }
02160 }
02161 (void) UnlockSemaphoreInfo(cache_info->semaphore);
02162 if (destroy != MagickFalse)
02163 cache_info=(CacheInfo *) DestroyPixelCache(cache_info);
02164 if (status != MagickFalse)
02165 {
02166
02167
02168
02169 image->taint=MagickTrue;
02170 image->type=UndefinedType;
02171 if (image->colorspace == GRAYColorspace)
02172 image->colorspace=RGBColorspace;
02173 if (ValidatePixelCacheMorphology(image) == MagickFalse)
02174 status=OpenPixelCache(image,IOMode,exception);
02175 }
02176 (void) UnlockSemaphoreInfo(image->semaphore);
02177 if (status == MagickFalse)
02178 return((Cache) NULL);
02179 return(image->cache);
02180 }
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206
02207
02208
02209
02210
02211
02212 MagickExport MagickBooleanType GetOneAuthenticPixel(Image *image,const long x,
02213 const long y,PixelPacket *pixel,ExceptionInfo *exception)
02214 {
02215 CacheInfo
02216 *cache_info;
02217
02218 GetOneAuthenticPixelFromHandler
02219 get_one_authentic_pixel_from_handler;
02220
02221 MagickBooleanType
02222 status;
02223
02224 assert(image != (Image *) NULL);
02225 assert(image->signature == MagickSignature);
02226 if (image->debug != MagickFalse)
02227 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02228 assert(image->cache != (Cache) NULL);
02229 cache_info=(CacheInfo *) image->cache;
02230 assert(cache_info->signature == MagickSignature);
02231 *pixel=image->background_color;
02232 get_one_authentic_pixel_from_handler=
02233 cache_info->methods.get_one_authentic_pixel_from_handler;
02234 if (get_one_authentic_pixel_from_handler ==
02235 (GetOneAuthenticPixelFromHandler) NULL)
02236 return(MagickFalse);
02237 status=cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,
02238 pixel,exception);
02239 return(status);
02240 }
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272 static MagickBooleanType GetOneAuthenticPixelFromCache(Image *image,
02273 const long x,const long y,PixelPacket *pixel,ExceptionInfo *exception)
02274 {
02275 PixelPacket
02276 *pixels;
02277
02278 if (image->debug != MagickFalse)
02279 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02280 *pixel=image->background_color;
02281 pixels=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
02282 if (pixels == (PixelPacket *) NULL)
02283 return(MagickFalse);
02284 *pixel=(*pixels);
02285 return(MagickTrue);
02286 }
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320 MagickExport MagickBooleanType GetOneVirtualMagickPixel(const Image *image,
02321 const long x,const long y,MagickPixelPacket *pixel,ExceptionInfo *exception)
02322 {
02323 CacheInfo
02324 *cache_info;
02325
02326 register const IndexPacket
02327 *indexes;
02328
02329 register const PixelPacket
02330 *p;
02331
02332 assert(image != (const Image *) NULL);
02333 assert(image->signature == MagickSignature);
02334 assert(image->cache != (Cache) NULL);
02335 cache_info=(CacheInfo *) image->cache;
02336 assert(cache_info->signature == MagickSignature);
02337 GetMagickPixelPacket(image,pixel);
02338 p=GetVirtualPixelCache(image,GetPixelCacheVirtualMethod(image),x,y,1,1,
02339 exception);
02340 if (p == (const PixelPacket *) NULL)
02341 return(MagickFalse);
02342 indexes=GetVirtualIndexQueue(image);
02343 SetMagickPixelPacket(image,p,indexes,pixel);
02344 return(MagickTrue);
02345 }
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382 MagickExport MagickBooleanType GetOneVirtualMethodPixel(const Image *image,
02383 const VirtualPixelMethod virtual_pixel_method,const long x,const long y,
02384 PixelPacket *pixel,ExceptionInfo *exception)
02385 {
02386 GetOneVirtualPixelFromHandler
02387 get_one_virtual_pixel_from_handler;
02388
02389 CacheInfo
02390 *cache_info;
02391
02392 MagickBooleanType
02393 status;
02394
02395 assert(image != (const Image *) NULL);
02396 assert(image->signature == MagickSignature);
02397 assert(image->cache != (Cache) NULL);
02398 cache_info=(CacheInfo *) image->cache;
02399 assert(cache_info->signature == MagickSignature);
02400 *pixel=image->background_color;
02401 get_one_virtual_pixel_from_handler=
02402 cache_info->methods.get_one_virtual_pixel_from_handler;
02403 if (get_one_virtual_pixel_from_handler ==
02404 (GetOneVirtualPixelFromHandler) NULL)
02405 return(MagickFalse);
02406 status=get_one_virtual_pixel_from_handler(image,virtual_pixel_method,x,y,
02407 pixel,exception);
02408 return(status);
02409 }
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442 MagickExport MagickBooleanType GetOneVirtualPixel(const Image *image,
02443 const long x,const long y,PixelPacket *pixel,ExceptionInfo *exception)
02444 {
02445 GetOneVirtualPixelFromHandler
02446 get_one_virtual_pixel_from_handler;
02447
02448 CacheInfo
02449 *cache_info;
02450
02451 MagickBooleanType
02452 status;
02453
02454 assert(image != (const Image *) NULL);
02455 assert(image->signature == MagickSignature);
02456 assert(image->cache != (Cache) NULL);
02457 cache_info=(CacheInfo *) image->cache;
02458 assert(cache_info->signature == MagickSignature);
02459 *pixel=image->background_color;
02460 get_one_virtual_pixel_from_handler=
02461 cache_info->methods.get_one_virtual_pixel_from_handler;
02462 if (get_one_virtual_pixel_from_handler ==
02463 (GetOneVirtualPixelFromHandler) NULL)
02464 return(MagickFalse);
02465 status=get_one_virtual_pixel_from_handler(image,GetPixelCacheVirtualMethod(
02466 image),x,y,pixel,exception);
02467 return(status);
02468 }
02469
02470
02471
02472
02473
02474
02475
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
02501
02502
02503
02504 static MagickBooleanType GetOneVirtualPixelFromCache(const Image *image,
02505 const VirtualPixelMethod virtual_pixel_method,const long x,const long y,
02506 PixelPacket *pixel,ExceptionInfo *exception)
02507 {
02508 const PixelPacket
02509 *pixels;
02510
02511 *pixel=image->background_color;
02512 pixels=GetVirtualPixelCache(image,virtual_pixel_method,x,y,1UL,1UL,exception);
02513 if (pixels == (const PixelPacket *) NULL)
02514 return(MagickFalse);
02515 *pixel=(*pixels);
02516 return(MagickTrue);
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 MagickExport ColorspaceType GetPixelCacheColorspace(const Cache cache)
02542 {
02543 CacheInfo
02544 *cache_info;
02545
02546 assert(cache != (Cache) NULL);
02547 cache_info=(CacheInfo *) cache;
02548 assert(cache_info->signature == MagickSignature);
02549 if (cache_info->debug != MagickFalse)
02550 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
02551 cache_info->filename);
02552 return(cache_info->colorspace);
02553 }
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577 MagickExport void GetPixelCacheMethods(CacheMethods *cache_methods)
02578 {
02579 assert(cache_methods != (CacheMethods *) NULL);
02580 (void) ResetMagickMemory(cache_methods,0,sizeof(*cache_methods));
02581 cache_methods->get_virtual_pixel_handler=GetVirtualPixelCache;
02582 cache_methods->get_virtual_pixels_handler=GetVirtualPixelsCache;
02583 cache_methods->get_virtual_indexes_from_handler=GetVirtualIndexesFromCache;
02584 cache_methods->get_one_virtual_pixel_from_handler=GetOneVirtualPixelFromCache;
02585 cache_methods->get_authentic_pixels_handler=GetAuthenticPixelsCache;
02586 cache_methods->get_authentic_indexes_from_handler=
02587 GetAuthenticIndexesFromCache;
02588 cache_methods->get_authentic_pixels_from_handler=GetAuthenticPixelsFromCache;
02589 cache_methods->get_one_authentic_pixel_from_handler=
02590 GetOneAuthenticPixelFromCache;
02591 cache_methods->queue_authentic_pixels_handler=QueueAuthenticPixelsCache;
02592 cache_methods->sync_authentic_pixels_handler=SyncAuthenticPixelsCache;
02593 cache_methods->destroy_pixel_handler=DestroyImagePixelCache;
02594 }
02595
02596
02597
02598
02599
02600
02601
02602
02603
02604
02605
02606
02607
02608
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618
02619
02620 MagickExport MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
02621 NexusInfo *nexus_info)
02622 {
02623 CacheInfo
02624 *cache_info;
02625
02626 MagickSizeType
02627 extent;
02628
02629 if (cache == (Cache) NULL)
02630 return(0);
02631 cache_info=(CacheInfo *) cache;
02632 assert(cache_info->signature == MagickSignature);
02633 extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
02634 if (extent == 0)
02635 return((MagickSizeType) cache_info->columns*cache_info->rows);
02636 return(extent);
02637 }
02638
02639
02640
02641
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665 MagickExport IndexPacket *GetPixelCacheNexusIndexes(const Cache cache,
02666 NexusInfo *nexus_info)
02667 {
02668 CacheInfo
02669 *cache_info;
02670
02671 if (cache == (Cache) NULL)
02672 return((IndexPacket *) NULL);
02673 cache_info=(CacheInfo *) cache;
02674 assert(cache_info->signature == MagickSignature);
02675 if (cache_info->storage_class == UndefinedClass)
02676 return((IndexPacket *) NULL);
02677 return(nexus_info->indexes);
02678 }
02679
02680
02681
02682
02683
02684
02685
02686
02687
02688
02689
02690
02691
02692
02693
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703
02704
02705
02706 MagickExport PixelPacket *GetPixelCacheNexusPixels(const Cache cache,
02707 NexusInfo *nexus_info)
02708 {
02709 CacheInfo
02710 *cache_info;
02711
02712 if (cache == (Cache) NULL)
02713 return((PixelPacket *) NULL);
02714 cache_info=(CacheInfo *) cache;
02715 assert(cache_info->signature == MagickSignature);
02716 if (cache_info->debug != MagickFalse)
02717 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
02718 cache_info->filename);
02719 if (cache_info->storage_class == UndefinedClass)
02720 return((PixelPacket *) NULL);
02721 return(nexus_info->pixels);
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
02748 MagickExport ClassType GetPixelCacheStorageClass(const Cache cache)
02749 {
02750 CacheInfo
02751 *cache_info;
02752
02753 assert(cache != (Cache) NULL);
02754 cache_info=(CacheInfo *) cache;
02755 assert(cache_info->signature == MagickSignature);
02756 if (cache_info->debug != MagickFalse)
02757 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
02758 cache_info->filename);
02759 return(cache_info->storage_class);
02760 }
02761
02762
02763
02764
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 MagickExport void GetPixelCacheTileSize(const Image *image,unsigned long *width,
02790 unsigned long *height)
02791 {
02792 CacheInfo
02793 *cache_info;
02794
02795 assert(image != (Image *) NULL);
02796 assert(image->signature == MagickSignature);
02797 if (image->debug != MagickFalse)
02798 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02799 assert(image->cache != (Cache) NULL);
02800 cache_info=(CacheInfo *) image->cache;
02801 assert(cache_info->signature == MagickSignature);
02802 *width=2048UL/sizeof(PixelPacket);
02803 if (GetPixelCacheType(image) == DiskCache)
02804 *width=8192UL/sizeof(PixelPacket);
02805 *height=(*width);
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 MagickExport CacheType GetPixelCacheType(const Image *image)
02831 {
02832 CacheInfo
02833 *cache_info;
02834
02835 assert(image != (Image *) NULL);
02836 assert(image->signature == MagickSignature);
02837 if (image->debug != MagickFalse)
02838 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02839 assert(image->cache != (Cache) NULL);
02840 cache_info=(CacheInfo *) image->cache;
02841 assert(cache_info->signature == MagickSignature);
02842 return(cache_info->type);
02843 }
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869 MagickExport VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
02870 {
02871 CacheInfo
02872 *cache_info;
02873
02874 assert(image != (Image *) NULL);
02875 assert(image->signature == MagickSignature);
02876 if (image->debug != MagickFalse)
02877 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02878 assert(image->cache != (Cache) NULL);
02879 cache_info=(CacheInfo *) image->cache;
02880 assert(cache_info->signature == MagickSignature);
02881 return(cache_info->virtual_pixel_method);
02882 }
02883
02884
02885
02886
02887
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902
02903
02904
02905
02906
02907 static const IndexPacket *GetVirtualIndexesFromCache(const Image *image)
02908 {
02909 CacheInfo
02910 *cache_info;
02911
02912 const IndexPacket
02913 *indexes;
02914
02915 long
02916 id;
02917
02918 if (image->debug != MagickFalse)
02919 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
02920 cache_info=(CacheInfo *) image->cache;
02921 id=GetOpenMPThreadId();
02922 assert(id < (long) cache_info->number_threads);
02923 indexes=GetVirtualIndexesFromNexus(image->cache,cache_info->nexus_info[id]);
02924 return(indexes);
02925 }
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942
02943
02944
02945
02946
02947
02948
02949
02950
02951
02952
02953 MagickExport const IndexPacket *GetVirtualIndexesFromNexus(const Cache cache,
02954 NexusInfo *nexus_info)
02955 {
02956 CacheInfo
02957 *cache_info;
02958
02959 if (cache == (Cache) NULL)
02960 return((IndexPacket *) NULL);
02961 cache_info=(CacheInfo *) cache;
02962 assert(cache_info->signature == MagickSignature);
02963 if (cache_info->storage_class == UndefinedClass)
02964 return((IndexPacket *) NULL);
02965 return(nexus_info->indexes);
02966 }
02967
02968
02969
02970
02971
02972
02973
02974
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993 MagickExport const IndexPacket *GetVirtualIndexQueue(const Image *image)
02994 {
02995 CacheInfo
02996 *cache_info;
02997
02998 assert(image != (const Image *) NULL);
02999 assert(image->signature == MagickSignature);
03000 if (image->debug != MagickFalse)
03001 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03002 assert(image->cache != (Cache) NULL);
03003 cache_info=(CacheInfo *) image->cache;
03004 assert(cache_info->signature == MagickSignature);
03005 if (cache_info->methods.get_virtual_indexes_from_handler ==
03006 (GetVirtualIndexesFromHandler) NULL)
03007 return((IndexPacket *) NULL);
03008 return(cache_info->methods.get_virtual_indexes_from_handler(image));
03009 }
03010
03011
03012
03013
03014
03015
03016
03017
03018
03019
03020
03021
03022
03023
03024
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034
03035
03036
03037
03038
03039
03040
03041
03042
03043
03044
03045
03046
03047
03048 static long
03049 DitherMatrix[64] =
03050 {
03051 0, 48, 12, 60, 3, 51, 15, 63,
03052 32, 16, 44, 28, 35, 19, 47, 31,
03053 8, 56, 4, 52, 11, 59, 7, 55,
03054 40, 24, 36, 20, 43, 27, 39, 23,
03055 2, 50, 14, 62, 1, 49, 13, 61,
03056 34, 18, 46, 30, 33, 17, 45, 29,
03057 10, 58, 6, 54, 9, 57, 5, 53,
03058 42, 26, 38, 22, 41, 25, 37, 21
03059 };
03060
03061 static inline long DitherX(const unsigned long columns,const long x)
03062 {
03063 long
03064 index;
03065
03066 index=x+DitherMatrix[x & 0x07]-32L;
03067 if (index < 0L)
03068 return(0L);
03069 if (index >= (long) columns)
03070 return((long) columns-1L);
03071 return(index);
03072 }
03073
03074 static inline long DitherY(const unsigned long rows,const long y)
03075 {
03076 long
03077 index;
03078
03079 index=y+DitherMatrix[y & 0x07]-32L;
03080 if (index < 0L)
03081 return(0L);
03082 if (index >= (long) rows)
03083 return((long) rows-1L);
03084 return(index);
03085 }
03086
03087 static inline long EdgeX(const unsigned long columns,const long x)
03088 {
03089 if (x < 0L)
03090 return(0L);
03091 if (x >= (long) columns)
03092 return((long) columns-1L);
03093 return(x);
03094 }
03095
03096 static inline long EdgeY(const unsigned long rows,const long y)
03097 {
03098 if (y < 0L)
03099 return(0L);
03100 if (y >= (long) rows)
03101 return((long) rows-1L);
03102 return(y);
03103 }
03104
03105 static inline long RandomX(const unsigned long columns,RandomInfo *random_info)
03106 {
03107 return((long) (columns*GetPseudoRandomValue(random_info)));
03108 }
03109
03110 static inline long RandomY(const unsigned long rows,RandomInfo *random_info)
03111 {
03112 return((long) (rows*GetPseudoRandomValue(random_info)));
03113 }
03114
03115
03116
03117
03118
03119
03120
03121
03122 static inline MagickModulo VirtualPixelModulo(const long offset,
03123 const unsigned long extent)
03124 {
03125 MagickModulo
03126 modulo;
03127
03128 modulo.quotient=offset/(long) extent;
03129 if (offset < 0L)
03130 modulo.quotient--;
03131 modulo.remainder=offset-modulo.quotient*(long) extent;
03132 return(modulo);
03133 }
03134
03135 MagickExport const PixelPacket *GetVirtualPixelsFromNexus(const Image *image,
03136 const VirtualPixelMethod virtual_pixel_method,const long x,const long y,
03137 const unsigned long columns,const unsigned long rows,NexusInfo *nexus_info,
03138 ExceptionInfo *exception)
03139 {
03140 CacheInfo
03141 *cache_info;
03142
03143 MagickOffsetType
03144 offset;
03145
03146 MagickSizeType
03147 length,
03148 number_pixels;
03149
03150 NexusInfo
03151 **virtual_nexus;
03152
03153 PixelPacket
03154 *pixels,
03155 virtual_pixel;
03156
03157 RectangleInfo
03158 region;
03159
03160 register const IndexPacket
03161 *__restrict nexus_indexes;
03162
03163 register const PixelPacket
03164 *__restrict p;
03165
03166 register IndexPacket
03167 *__restrict indexes;
03168
03169 register long
03170 u,
03171 v;
03172
03173 register PixelPacket
03174 *__restrict q;
03175
03176
03177
03178
03179 if (image->debug != MagickFalse)
03180 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03181 cache_info=(CacheInfo *) image->cache;
03182 if (cache_info->type == UndefinedCache)
03183 return((const PixelPacket *) NULL);
03184 region.x=x;
03185 region.y=y;
03186 region.width=columns;
03187 region.height=rows;
03188 pixels=SetPixelCacheNexusPixels(image,®ion,nexus_info,exception);
03189 if (pixels == (PixelPacket *) NULL)
03190 return((const PixelPacket *) NULL);
03191 offset=(MagickOffsetType) region.y*cache_info->columns+region.x;
03192 length=(MagickSizeType) (region.height-1)*cache_info->columns+region.width-1;
03193 number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
03194 if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
03195 if ((x >= 0) && ((long) (x+columns) <= (long) cache_info->columns) &&
03196 (y >= 0) && ((long) (y+rows) <= (long) cache_info->rows))
03197 {
03198 MagickBooleanType
03199 status;
03200
03201
03202
03203
03204 if (IsNexusInCore(cache_info,nexus_info) != MagickFalse)
03205 return(pixels);
03206 status=ReadPixelCachePixels(cache_info,nexus_info,exception);
03207 if (status == MagickFalse)
03208 return((const PixelPacket *) NULL);
03209 if ((cache_info->storage_class == PseudoClass) ||
03210 (cache_info->colorspace == CMYKColorspace))
03211 {
03212 status=ReadPixelCacheIndexes(cache_info,nexus_info,exception);
03213 if (status == MagickFalse)
03214 return((const PixelPacket *) NULL);
03215 }
03216 return(pixels);
03217 }
03218
03219
03220
03221 q=pixels;
03222 indexes=GetPixelCacheNexusIndexes(cache_info,nexus_info);
03223 virtual_nexus=AcquirePixelCacheNexus(1);
03224 if (virtual_nexus == (NexusInfo **) NULL)
03225 {
03226 (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
03227 "UnableToGetCacheNexus","`%s'",image->filename);
03228 return((const PixelPacket *) NULL);
03229 }
03230 switch (virtual_pixel_method)
03231 {
03232 case BlackVirtualPixelMethod:
03233 {
03234 virtual_pixel.red=0;
03235 virtual_pixel.green=0;
03236 virtual_pixel.blue=0;
03237 virtual_pixel.opacity=OpaqueOpacity;
03238 break;
03239 }
03240 case GrayVirtualPixelMethod:
03241 {
03242 virtual_pixel.red=(Quantum) QuantumRange/2;
03243 virtual_pixel.green=(Quantum) QuantumRange/2;
03244 virtual_pixel.blue=(Quantum) QuantumRange/2;
03245 virtual_pixel.opacity=(Quantum) OpaqueOpacity;
03246 break;
03247 }
03248 case TransparentVirtualPixelMethod:
03249 {
03250 virtual_pixel.red=(Quantum) 0;
03251 virtual_pixel.green=(Quantum) 0;
03252 virtual_pixel.blue=(Quantum) 0;
03253 virtual_pixel.opacity=(Quantum) TransparentOpacity;
03254 break;
03255 }
03256 case MaskVirtualPixelMethod:
03257 case WhiteVirtualPixelMethod:
03258 {
03259 virtual_pixel.red=(Quantum) QuantumRange;
03260 virtual_pixel.green=(Quantum) QuantumRange;
03261 virtual_pixel.blue=(Quantum) QuantumRange;
03262 virtual_pixel.opacity=OpaqueOpacity;
03263 break;
03264 }
03265 default:
03266 {
03267 virtual_pixel=image->background_color;
03268 break;
03269 }
03270 }
03271 for (v=0; v < (long) rows; v++)
03272 {
03273 for (u=0; u < (long) columns; u+=length)
03274 {
03275 length=(MagickSizeType) MagickMin(cache_info->columns-(x+u),columns-u);
03276 if ((((x+u) < 0) || ((x+u) >= (long) cache_info->columns)) ||
03277 (((y+v) < 0) || ((y+v) >= (long) cache_info->rows)) || (length == 0))
03278 {
03279 MagickModulo
03280 x_modulo,
03281 y_modulo;
03282
03283
03284
03285
03286 length=(MagickSizeType) 1;
03287 switch (virtual_pixel_method)
03288 {
03289 case BackgroundVirtualPixelMethod:
03290 case ConstantVirtualPixelMethod:
03291 case BlackVirtualPixelMethod:
03292 case GrayVirtualPixelMethod:
03293 case TransparentVirtualPixelMethod:
03294 case MaskVirtualPixelMethod:
03295 case WhiteVirtualPixelMethod:
03296 {
03297 p=(&virtual_pixel);
03298 break;
03299 }
03300 case EdgeVirtualPixelMethod:
03301 default:
03302 {
03303 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
03304 EdgeX(cache_info->columns,x+u),EdgeY(cache_info->rows,y+v),
03305 1UL,1UL,virtual_nexus[0],exception);
03306 break;
03307 }
03308 case RandomVirtualPixelMethod:
03309 {
03310 if (cache_info->random_info == (RandomInfo *) NULL)
03311 cache_info->random_info=AcquireRandomInfo();
03312 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
03313 RandomX(cache_info->columns,cache_info->random_info),
03314 RandomY(cache_info->rows,cache_info->random_info),1UL,1UL,
03315 virtual_nexus[0],exception);
03316 break;
03317 }
03318 case DitherVirtualPixelMethod:
03319 {
03320 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
03321 DitherX(cache_info->columns,x+u),DitherY(cache_info->rows,y+v),
03322 1UL,1UL,virtual_nexus[0],exception);
03323 break;
03324 }
03325 case TileVirtualPixelMethod:
03326 {
03327 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
03328 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
03329 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
03330 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus[0],
03331 exception);
03332 break;
03333 }
03334 case MirrorVirtualPixelMethod:
03335 {
03336 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
03337 if ((x_modulo.quotient & 0x01) == 1L)
03338 x_modulo.remainder=(long) cache_info->columns-
03339 x_modulo.remainder-1L;
03340 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
03341 if ((y_modulo.quotient & 0x01) == 1L)
03342 y_modulo.remainder=(long) cache_info->rows-
03343 y_modulo.remainder-1L;
03344 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
03345 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus[0],
03346 exception);
03347 break;
03348 }
03349 case CheckerTileVirtualPixelMethod:
03350 {
03351 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
03352 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
03353 if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
03354 {
03355 p=(&virtual_pixel);
03356 break;
03357 }
03358 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
03359 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus[0],
03360 exception);
03361 break;
03362 }
03363 case HorizontalTileVirtualPixelMethod:
03364 {
03365 if (((y+v) < 0) || ((y+v) >= (long) cache_info->rows))
03366 {
03367 p=(&virtual_pixel);
03368 break;
03369 }
03370 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
03371 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
03372 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
03373 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus[0],
03374 exception);
03375 break;
03376 }
03377 case VerticalTileVirtualPixelMethod:
03378 {
03379 if (((x+u) < 0) || ((x+u) >= (long) cache_info->columns))
03380 {
03381 p=(&virtual_pixel);
03382 break;
03383 }
03384 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
03385 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
03386 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
03387 x_modulo.remainder,y_modulo.remainder,1UL,1UL,virtual_nexus[0],
03388 exception);
03389 break;
03390 }
03391 case HorizontalTileEdgeVirtualPixelMethod:
03392 {
03393 x_modulo=VirtualPixelModulo(x+u,cache_info->columns);
03394 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
03395 x_modulo.remainder,EdgeY(cache_info->rows,y+v),1UL,1UL,
03396 virtual_nexus[0],exception);
03397 break;
03398 }
03399 case VerticalTileEdgeVirtualPixelMethod:
03400 {
03401 y_modulo=VirtualPixelModulo(y+v,cache_info->rows);
03402 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,
03403 EdgeX(cache_info->columns,x+u),y_modulo.remainder,1UL,1UL,
03404 virtual_nexus[0],exception);
03405 break;
03406 }
03407 }
03408 if (p == (const PixelPacket *) NULL)
03409 break;
03410 *q++=(*p);
03411 if (indexes != (IndexPacket *) NULL)
03412 {
03413 nexus_indexes=GetVirtualIndexesFromNexus(cache_info,
03414 virtual_nexus[0]);
03415 if (nexus_indexes != (const IndexPacket *) NULL)
03416 *indexes++=(*nexus_indexes);
03417 }
03418 continue;
03419 }
03420
03421
03422
03423 p=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x+u,y+v,
03424 (unsigned long) length,1UL,virtual_nexus[0],exception);
03425 if (p == (const PixelPacket *) NULL)
03426 break;
03427 (void) CopyMagickMemory(q,p,(size_t) length*sizeof(*p));
03428 q+=length;
03429 if (indexes != (IndexPacket *) NULL)
03430 {
03431 nexus_indexes=GetVirtualIndexesFromNexus(cache_info,virtual_nexus[0]);
03432 if (nexus_indexes != (const IndexPacket *) NULL)
03433 {
03434 (void) CopyMagickMemory(indexes,nexus_indexes,(size_t) length*
03435 sizeof(*nexus_indexes));
03436 indexes+=length;
03437 }
03438 }
03439 }
03440 }
03441 virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
03442 return(pixels);
03443 }
03444
03445
03446
03447
03448
03449
03450
03451
03452
03453
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 *GetVirtualPixelCache(const Image *image,
03480 const VirtualPixelMethod virtual_pixel_method,const long x,const long y,
03481 const unsigned long columns,const unsigned long rows,ExceptionInfo *exception)
03482 {
03483 CacheInfo
03484 *cache_info;
03485
03486 const PixelPacket
03487 *pixels;
03488
03489 long
03490 id;
03491
03492 if (image->debug != MagickFalse)
03493 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03494 cache_info=(CacheInfo *) image->cache;
03495 id=GetOpenMPThreadId();
03496 assert(id < (long) cache_info->number_threads);
03497 pixels=GetVirtualPixelsFromNexus(image,virtual_pixel_method,x,y,columns,rows,
03498 cache_info->nexus_info[id],exception);
03499 return(pixels);
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 *GetVirtualPixelQueue(const Image *image)
03526 {
03527 CacheInfo
03528 *cache_info;
03529
03530 assert(image != (const Image *) NULL);
03531 assert(image->signature == MagickSignature);
03532 if (image->debug != MagickFalse)
03533 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03534 assert(image->cache != (Cache) NULL);
03535 cache_info=(CacheInfo *) image->cache;
03536 assert(cache_info->signature == MagickSignature);
03537 if (cache_info->methods.get_virtual_pixels_handler ==
03538 (GetVirtualPixelsHandler) NULL)
03539 return((PixelPacket *) NULL);
03540 return(cache_info->methods.get_virtual_pixels_handler(image));
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
03571
03572
03573
03574
03575
03576
03577
03578
03579
03580
03581
03582
03583
03584
03585
03586
03587
03588
03589
03590
03591 MagickExport const PixelPacket *GetVirtualPixels(const Image *image,
03592 const long x,const long y,const unsigned long columns,
03593 const unsigned long rows,ExceptionInfo *exception)
03594 {
03595 CacheInfo
03596 *cache_info;
03597
03598 const PixelPacket
03599 *pixels;
03600
03601 assert(image != (const Image *) NULL);
03602 assert(image->signature == MagickSignature);
03603 if (image->debug != MagickFalse)
03604 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03605 assert(image->cache != (Cache) NULL);
03606 cache_info=(CacheInfo *) image->cache;
03607 assert(cache_info->signature == MagickSignature);
03608 if (cache_info->methods.get_virtual_pixel_handler ==
03609 (GetVirtualPixelHandler) NULL)
03610 return((const PixelPacket *) NULL);
03611 pixels=cache_info->methods.get_virtual_pixel_handler(image,
03612 GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception);
03613 return(pixels);
03614 }
03615
03616
03617
03618
03619
03620
03621
03622
03623
03624
03625
03626
03627
03628
03629
03630
03631
03632
03633
03634
03635
03636
03637
03638
03639 static const PixelPacket *GetVirtualPixelsCache(const Image *image)
03640 {
03641 CacheInfo
03642 *cache_info;
03643
03644 const PixelPacket
03645 *pixels;
03646
03647 long
03648 id;
03649
03650 if (image->debug != MagickFalse)
03651 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03652 cache_info=(CacheInfo *) image->cache;
03653 id=GetOpenMPThreadId();
03654 assert(id < (long) cache_info->number_threads);
03655 pixels=GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[id]);
03656 return(pixels);
03657 }
03658
03659
03660
03661
03662
03663
03664
03665
03666
03667
03668
03669
03670
03671
03672
03673
03674
03675
03676
03677
03678
03679
03680
03681
03682
03683
03684
03685 MagickExport const PixelPacket *GetVirtualPixelsNexus(const Cache cache,
03686 NexusInfo *nexus_info)
03687 {
03688 CacheInfo
03689 *cache_info;
03690
03691 if (cache == (Cache) NULL)
03692 return((PixelPacket *) NULL);
03693 cache_info=(CacheInfo *) cache;
03694 assert(cache_info->signature == MagickSignature);
03695 if (cache_info->storage_class == UndefinedClass)
03696 return((PixelPacket *) NULL);
03697 return((const PixelPacket *) nexus_info->pixels);
03698 }
03699
03700
03701
03702
03703
03704
03705
03706
03707
03708
03709
03710
03711
03712
03713
03714
03715
03716
03717
03718
03719
03720
03721
03722
03723
03724
03725
03726
03727
03728
03729
03730 static inline void MagickPixelCompositeMask(const MagickPixelPacket *p,
03731 const MagickRealType alpha,const MagickPixelPacket *q,
03732 const MagickRealType beta,MagickPixelPacket *composite)
03733 {
03734 MagickRealType
03735 gamma;
03736
03737 if (alpha == TransparentOpacity)
03738 {
03739 *composite=(*q);
03740 return;
03741 }
03742 gamma=1.0-QuantumScale*QuantumScale*alpha*beta;
03743 gamma=1.0/(gamma <= MagickEpsilon ? 1.0 : gamma);
03744 composite->red=gamma*MagickOver_(p->red,alpha,q->red,beta);
03745 composite->green=gamma*MagickOver_(p->green,alpha,q->green,beta);
03746 composite->blue=gamma*MagickOver_(p->blue,alpha,q->blue,beta);
03747 if ((p->colorspace == CMYKColorspace) && (q->colorspace == CMYKColorspace))
03748 composite->index=gamma*MagickOver_(p->index,alpha,q->index,beta);
03749 }
03750
03751 static MagickBooleanType MaskPixelCacheNexus(Image *image,NexusInfo *nexus_info,
03752 ExceptionInfo *exception)
03753 {
03754 CacheInfo
03755 *cache_info;
03756
03757 MagickPixelPacket
03758 alpha,
03759 beta;
03760
03761 MagickSizeType
03762 number_pixels;
03763
03764 NexusInfo
03765 **clip_nexus,
03766 **image_nexus;
03767
03768 register const PixelPacket
03769 *__restrict r;
03770
03771 register IndexPacket
03772 *__restrict nexus_indexes,
03773 *__restrict indexes;
03774
03775 register long
03776 i;
03777
03778 register PixelPacket
03779 *__restrict p,
03780 *__restrict q;
03781
03782
03783
03784
03785 if (image->debug != MagickFalse)
03786 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
03787 if (image->mask == (Image *) NULL)
03788 return(MagickFalse);
03789 cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
03790 if (cache_info == (Cache) NULL)
03791 return(MagickFalse);
03792 image_nexus=AcquirePixelCacheNexus(1);
03793 clip_nexus=AcquirePixelCacheNexus(1);
03794 if ((image_nexus == (NexusInfo **) NULL) ||
03795 (clip_nexus == (NexusInfo **) NULL))
03796 ThrowBinaryException(CacheError,"UnableToGetCacheNexus",image->filename);
03797 p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
03798 nexus_info->region.width,nexus_info->region.height,image_nexus[0],
03799 exception);
03800 indexes=GetPixelCacheNexusIndexes(image->cache,image_nexus[0]);
03801 q=nexus_info->pixels;
03802 nexus_indexes=nexus_info->indexes;
03803 r=GetVirtualPixelsFromNexus(image->mask,MaskVirtualPixelMethod,
03804 nexus_info->region.x,nexus_info->region.y,nexus_info->region.width,
03805 nexus_info->region.height,clip_nexus[0],&image->exception);
03806 GetMagickPixelPacket(image,&alpha);
03807 GetMagickPixelPacket(image,&beta);
03808 number_pixels=(MagickSizeType) nexus_info->region.width*
03809 nexus_info->region.height;
03810 for (i=0; i < (long) number_pixels; i++)
03811 {
03812 if ((p == (PixelPacket *) NULL) || (r == (const PixelPacket *) NULL))
03813 break;
03814 SetMagickPixelPacket(image,p,indexes+i,&alpha);
03815 SetMagickPixelPacket(image,q,nexus_indexes+i,&beta);
03816 MagickPixelCompositeMask(&beta,(MagickRealType) PixelIntensityToQuantum(r),
03817 &alpha,alpha.opacity,&beta);
03818 q->red=RoundToQuantum(beta.red);
03819 q->green=RoundToQuantum(beta.green);
03820 q->blue=RoundToQuantum(beta.blue);
03821 q->opacity=RoundToQuantum(beta.opacity);
03822 if (cache_info->active_index_channel != MagickFalse)
03823 nexus_indexes[i]=indexes[i];
03824 p++;
03825 q++;
03826 r++;
03827 }
03828 clip_nexus=DestroyPixelCacheNexus(clip_nexus,1);
03829 image_nexus=DestroyPixelCacheNexus(image_nexus,1);
03830 if (i < (long) number_pixels)
03831 return(MagickFalse);
03832 return(MagickTrue);
03833 }
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845
03846
03847
03848
03849
03850
03851
03852
03853
03854
03855
03856
03857
03858
03859
03860