MagickCore  7.0.3
cache.c
Go to the documentation of this file.
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % CCCC AAA CCCC H H EEEEE %
7 % C A A C H H E %
8 % C AAAAA C HHHHH EEE %
9 % C A A C H H E %
10 % CCCC A A CCCC H H EEEEE %
11 % %
12 % %
13 % MagickCore Pixel Cache Methods %
14 % %
15 % Software Design %
16 % Cristy %
17 % July 1999 %
18 % %
19 % %
20 % Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % https://imagemagick.org/script/license.php %
27 % %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 %
38 */
39 
40 /*
41  Include declarations.
42 */
43 #include "MagickCore/studio.h"
44 #include "MagickCore/blob.h"
46 #include "MagickCore/cache.h"
52 #include "MagickCore/exception.h"
54 #include "MagickCore/geometry.h"
55 #include "MagickCore/list.h"
56 #include "MagickCore/log.h"
57 #include "MagickCore/magick.h"
58 #include "MagickCore/memory_.h"
61 #include "MagickCore/option.h"
62 #include "MagickCore/pixel.h"
64 #include "MagickCore/policy.h"
65 #include "MagickCore/quantum.h"
66 #include "MagickCore/random_.h"
67 #include "MagickCore/registry.h"
68 #include "MagickCore/resource_.h"
69 #include "MagickCore/semaphore.h"
70 #include "MagickCore/splay-tree.h"
71 #include "MagickCore/string_.h"
74 #include "MagickCore/utility.h"
76 #if defined(MAGICKCORE_ZLIB_DELEGATE)
77 #include "zlib.h"
78 #endif
79 
80 /*
81  Define declarations.
82 */
83 #define CacheTick(offset,extent) QuantumTick((MagickOffsetType) offset,extent)
84 #define IsFileDescriptorLimitExceeded() (GetMagickResource(FileResource) > \
85  GetMagickResourceLimit(FileResource) ? MagickTrue : MagickFalse)
86 
87 /*
88  Typedef declarations.
89 */
90 typedef struct _MagickModulo
91 {
92  ssize_t
94  remainder;
95 } MagickModulo;
96 
97 /*
98  Forward declarations.
99 */
100 #if defined(__cplusplus) || defined(c_plusplus)
101 extern "C" {
102 #endif
103 
104 static Cache
107 
108 static const Quantum
109  *GetVirtualPixelCache(const Image *,const VirtualPixelMethod,const ssize_t,
110  const ssize_t,const size_t,const size_t,ExceptionInfo *),
111  *GetVirtualPixelsCache(const Image *);
112 
113 static const void
114  *GetVirtualMetacontentFromCache(const Image *);
115 
116 static MagickBooleanType
117  GetOneAuthenticPixelFromCache(Image *,const ssize_t,const ssize_t,Quantum *,
118  ExceptionInfo *),
119  GetOneVirtualPixelFromCache(const Image *,const VirtualPixelMethod,
120  const ssize_t,const ssize_t,Quantum *,ExceptionInfo *),
121  OpenPixelCache(Image *,const MapMode,ExceptionInfo *),
122  OpenPixelCacheOnDisk(CacheInfo *,const MapMode),
123  ReadPixelCachePixels(CacheInfo *magick_restrict,NexusInfo *magick_restrict,
124  ExceptionInfo *),
125  ReadPixelCacheMetacontent(CacheInfo *magick_restrict,
126  NexusInfo *magick_restrict,ExceptionInfo *),
127  SyncAuthenticPixelsCache(Image *,ExceptionInfo *),
128  WritePixelCachePixels(CacheInfo *magick_restrict,NexusInfo *magick_restrict,
129  ExceptionInfo *),
130  WritePixelCacheMetacontent(CacheInfo *,NexusInfo *magick_restrict,
131  ExceptionInfo *);
132 
133 static Quantum
134  *GetAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const size_t,
135  const size_t,ExceptionInfo *),
136  *QueueAuthenticPixelsCache(Image *,const ssize_t,const ssize_t,const size_t,
137  const size_t,ExceptionInfo *),
138  *SetPixelCacheNexusPixels(const CacheInfo *,const MapMode,const ssize_t,
139  const ssize_t,const size_t,const size_t,const MagickBooleanType,
140  NexusInfo *,ExceptionInfo *) magick_hot_spot;
141 
142 #if defined(MAGICKCORE_OPENCL_SUPPORT)
143 static void
144  CopyOpenCLBuffer(CacheInfo *magick_restrict);
145 #endif
146 
147 #if defined(__cplusplus) || defined(c_plusplus)
148 }
149 #endif
150 
151 /*
152  Global declarations.
153 */
154 static SemaphoreInfo
155  *cache_semaphore = (SemaphoreInfo *) NULL;
156 
157 static ssize_t
158  cache_anonymous_memory = (-1);
159 
160 static time_t
161  cache_epoch = 0;
162 
163 /*
164 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
165 % %
166 % %
167 % %
168 + A c q u i r e P i x e l C a c h e %
169 % %
170 % %
171 % %
172 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
173 %
174 % AcquirePixelCache() acquires a pixel cache.
175 %
176 % The format of the AcquirePixelCache() method is:
177 %
178 % Cache AcquirePixelCache(const size_t number_threads)
179 %
180 % A description of each parameter follows:
181 %
182 % o number_threads: the number of nexus threads.
183 %
184 */
185 MagickPrivate Cache AcquirePixelCache(const size_t number_threads)
186 {
187  CacheInfo
188  *magick_restrict cache_info;
189 
190  char
191  *value;
192 
193  cache_info=(CacheInfo *) AcquireAlignedMemory(1,sizeof(*cache_info));
194  if (cache_info == (CacheInfo *) NULL)
195  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
196  (void) memset(cache_info,0,sizeof(*cache_info));
197  cache_info->type=UndefinedCache;
198  cache_info->mode=IOMode;
199  cache_info->disk_mode=IOMode;
200  cache_info->colorspace=sRGBColorspace;
201  cache_info->file=(-1);
202  cache_info->id=GetMagickThreadId();
203  cache_info->number_threads=number_threads;
204  if (GetOpenMPMaximumThreads() > cache_info->number_threads)
205  cache_info->number_threads=GetOpenMPMaximumThreads();
206  if (GetMagickResourceLimit(ThreadResource) > cache_info->number_threads)
207  cache_info->number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
208  if (cache_info->number_threads == 0)
209  cache_info->number_threads=1;
210  cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
211  if (cache_info->nexus_info == (NexusInfo **) NULL)
212  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
213  value=GetEnvironmentValue("MAGICK_SYNCHRONIZE");
214  if (value != (const char *) NULL)
215  {
216  cache_info->synchronize=IsStringTrue(value);
217  value=DestroyString(value);
218  }
219  value=GetPolicyValue("cache:synchronize");
220  if (value != (const char *) NULL)
221  {
222  cache_info->synchronize=IsStringTrue(value);
223  value=DestroyString(value);
224  }
225  cache_info->width_limit=GetMagickResourceLimit(WidthResource);
226  cache_info->height_limit=GetMagickResourceLimit(HeightResource);
227  cache_info->semaphore=AcquireSemaphoreInfo();
228  cache_info->reference_count=1;
229  cache_info->file_semaphore=AcquireSemaphoreInfo();
230  cache_info->debug=IsEventLogging();
231  cache_info->signature=MagickCoreSignature;
232  return((Cache ) cache_info);
233 }
234 
235 /*
236 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
237 % %
238 % %
239 % %
240 % A c q u i r e P i x e l C a c h e N e x u s %
241 % %
242 % %
243 % %
244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
245 %
246 % AcquirePixelCacheNexus() allocates the NexusInfo structure.
247 %
248 % The format of the AcquirePixelCacheNexus method is:
249 %
250 % NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
251 %
252 % A description of each parameter follows:
253 %
254 % o number_threads: the number of nexus threads.
255 %
256 */
257 MagickPrivate NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
258 {
259  NexusInfo
260  **magick_restrict nexus_info;
261 
262  register ssize_t
263  i;
264 
266  number_threads,sizeof(*nexus_info)));
267  if (nexus_info == (NexusInfo **) NULL)
268  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
269  nexus_info[0]=(NexusInfo *) AcquireQuantumMemory(number_threads,
270  sizeof(**nexus_info));
271  if (nexus_info[0] == (NexusInfo *) NULL)
272  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
273  (void) memset(nexus_info[0],0,number_threads*sizeof(**nexus_info));
274  for (i=0; i < (ssize_t) number_threads; i++)
275  {
276  nexus_info[i]=(&nexus_info[0][i]);
277  nexus_info[i]->signature=MagickCoreSignature;
278  }
279  return(nexus_info);
280 }
281 
282 /*
283 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
284 % %
285 % %
286 % %
287 % A c q u i r e P i x e l C a c h e P i x e l s %
288 % %
289 % %
290 % %
291 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
292 %
293 % AcquirePixelCachePixels() returns the pixels associated with the specified
294 % image.
295 %
296 % The format of the AcquirePixelCachePixels() method is:
297 %
298 % void *AcquirePixelCachePixels(const Image *image,size_t *length,
299 % ExceptionInfo *exception)
300 %
301 % A description of each parameter follows:
302 %
303 % o image: the image.
304 %
305 % o length: the pixel cache length.
306 %
307 % o exception: return any errors or warnings in this structure.
308 %
309 */
310 MagickExport void *AcquirePixelCachePixels(const Image *image,size_t *length,
311  ExceptionInfo *exception)
312 {
313  CacheInfo
314  *magick_restrict cache_info;
315 
316  assert(image != (const Image *) NULL);
317  assert(image->signature == MagickCoreSignature);
318  assert(exception != (ExceptionInfo *) NULL);
319  assert(exception->signature == MagickCoreSignature);
320  assert(image->cache != (Cache) NULL);
321  cache_info=(CacheInfo *) image->cache;
322  assert(cache_info->signature == MagickCoreSignature);
323  *length=0;
324  if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
325  return((void *) NULL);
326  *length=(size_t) cache_info->length;
327  return(cache_info->pixels);
328 }
329 
330 /*
331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
332 % %
333 % %
334 % %
335 + C a c h e C o m p o n e n t G e n e s i s %
336 % %
337 % %
338 % %
339 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
340 %
341 % CacheComponentGenesis() instantiates the cache component.
342 %
343 % The format of the CacheComponentGenesis method is:
344 %
345 % MagickBooleanType CacheComponentGenesis(void)
346 %
347 */
349 {
350  if (cache_semaphore == (SemaphoreInfo *) NULL)
351  cache_semaphore=AcquireSemaphoreInfo();
352  return(MagickTrue);
353 }
354 
355 /*
356 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
357 % %
358 % %
359 % %
360 + C a c h e C o m p o n e n t T e r m i n u s %
361 % %
362 % %
363 % %
364 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
365 %
366 % CacheComponentTerminus() destroys the cache component.
367 %
368 % The format of the CacheComponentTerminus() method is:
369 %
370 % CacheComponentTerminus(void)
371 %
372 */
374 {
375  if (cache_semaphore == (SemaphoreInfo *) NULL)
376  ActivateSemaphoreInfo(&cache_semaphore);
377  /* no op-- nothing to destroy */
378  RelinquishSemaphoreInfo(&cache_semaphore);
379 }
380 
381 /*
382 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
383 % %
384 % %
385 % %
386 + C l i p P i x e l C a c h e N e x u s %
387 % %
388 % %
389 % %
390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
391 %
392 % ClipPixelCacheNexus() clips the cache nexus as defined by the image clip
393 % mask. The method returns MagickTrue if the pixel region is clipped,
394 % otherwise MagickFalse.
395 %
396 % The format of the ClipPixelCacheNexus() method is:
397 %
398 % MagickBooleanType ClipPixelCacheNexus(Image *image,NexusInfo *nexus_info,
399 % ExceptionInfo *exception)
400 %
401 % A description of each parameter follows:
402 %
403 % o image: the image.
404 %
405 % o nexus_info: the cache nexus to clip.
406 %
407 % o exception: return any errors or warnings in this structure.
408 %
409 */
411  NexusInfo *nexus_info,ExceptionInfo *exception)
412 {
413  CacheInfo
414  *magick_restrict cache_info;
415 
417  number_pixels;
418 
419  NexusInfo
420  **magick_restrict image_nexus;
421 
422  register Quantum
423  *magick_restrict p,
424  *magick_restrict q;
425 
426  register ssize_t
427  n;
428 
429  /*
430  Apply clip mask.
431  */
432  if (image->debug != MagickFalse)
433  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
434  if ((image->channels & WriteMaskChannel) == 0)
435  return(MagickTrue);
436  cache_info=(CacheInfo *) image->cache;
437  if (cache_info == (Cache) NULL)
438  return(MagickFalse);
439  image_nexus=AcquirePixelCacheNexus(1);
440  p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
441  nexus_info->region.width,nexus_info->region.height,image_nexus[0],
442  exception);
443  q=nexus_info->pixels;
444  number_pixels=(MagickSizeType) nexus_info->region.width*
445  nexus_info->region.height;
446  for (n=0; n < (ssize_t) number_pixels; n++)
447  {
448  double
449  mask_alpha;
450 
451  register ssize_t
452  i;
453 
454  if (p == (Quantum *) NULL)
455  break;
456  mask_alpha=QuantumScale*GetPixelWriteMask(image,p);
457  if (fabs(mask_alpha) >= MagickEpsilon)
458  {
459  for (i=0; i < (ssize_t) image->number_channels; i++)
460  {
461  PixelChannel channel = GetPixelChannelChannel(image,i);
462  PixelTrait traits = GetPixelChannelTraits(image,channel);
463  if ((traits & UpdatePixelTrait) == 0)
464  continue;
465  q[i]=ClampToQuantum(MagickOver_((double) p[i],mask_alpha*
466  GetPixelAlpha(image,p),(double) q[i],(double)
467  GetPixelAlpha(image,q)));
468  }
469  SetPixelAlpha(image,GetPixelAlpha(image,p),q);
470  }
471  p+=GetPixelChannels(image);
472  q+=GetPixelChannels(image);
473  }
474  image_nexus=DestroyPixelCacheNexus(image_nexus,1);
475  if (n < (ssize_t) number_pixels)
476  return(MagickFalse);
477  return(MagickTrue);
478 }
479 
480 /*
481 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
482 % %
483 % %
484 % %
485 + C l o n e P i x e l C a c h e %
486 % %
487 % %
488 % %
489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
490 %
491 % ClonePixelCache() clones a pixel cache.
492 %
493 % The format of the ClonePixelCache() method is:
494 %
495 % Cache ClonePixelCache(const Cache cache)
496 %
497 % A description of each parameter follows:
498 %
499 % o cache: the pixel cache.
500 %
501 */
503 {
504  CacheInfo
505  *magick_restrict clone_info;
506 
507  const CacheInfo
508  *magick_restrict cache_info;
509 
510  assert(cache != NULL);
511  cache_info=(const CacheInfo *) cache;
512  assert(cache_info->signature == MagickCoreSignature);
513  if (cache_info->debug != MagickFalse)
515  cache_info->filename);
516  clone_info=(CacheInfo *) AcquirePixelCache(cache_info->number_threads);
517  clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
518  return((Cache ) clone_info);
519 }
520 
521 /*
522 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
523 % %
524 % %
525 % %
526 + C l o n e P i x e l C a c h e M e t h o d s %
527 % %
528 % %
529 % %
530 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
531 %
532 % ClonePixelCacheMethods() clones the pixel cache methods from one cache to
533 % another.
534 %
535 % The format of the ClonePixelCacheMethods() method is:
536 %
537 % void ClonePixelCacheMethods(Cache clone,const Cache cache)
538 %
539 % A description of each parameter follows:
540 %
541 % o clone: Specifies a pointer to a Cache structure.
542 %
543 % o cache: the pixel cache.
544 %
545 */
547 {
548  CacheInfo
549  *magick_restrict cache_info,
550  *magick_restrict source_info;
551 
552  assert(clone != (Cache) NULL);
553  source_info=(CacheInfo *) clone;
554  assert(source_info->signature == MagickCoreSignature);
555  if (source_info->debug != MagickFalse)
557  source_info->filename);
558  assert(cache != (Cache) NULL);
559  cache_info=(CacheInfo *) cache;
560  assert(cache_info->signature == MagickCoreSignature);
561  source_info->methods=cache_info->methods;
562 }
563 
564 /*
565 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
566 % %
567 % %
568 % %
569 + C l o n e P i x e l C a c h e R e p o s i t o r y %
570 % %
571 % %
572 % %
573 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
574 %
575 % ClonePixelCacheRepository() clones the source pixel cache to the destination
576 % cache.
577 %
578 % The format of the ClonePixelCacheRepository() method is:
579 %
580 % MagickBooleanType ClonePixelCacheRepository(CacheInfo *cache_info,
581 % CacheInfo *source_info,ExceptionInfo *exception)
582 %
583 % A description of each parameter follows:
584 %
585 % o cache_info: the pixel cache.
586 %
587 % o source_info: the source pixel cache.
588 %
589 % o exception: return any errors or warnings in this structure.
590 %
591 */
592 
594  CacheInfo *magick_restrict cache_info,CacheInfo *magick_restrict clone_info)
595 {
597  extent;
598 
599  size_t
600  quantum;
601 
602  ssize_t
603  count;
604 
605  struct stat
606  file_stats;
607 
608  unsigned char
609  *buffer;
610 
611  /*
612  Clone pixel cache on disk with identical morphology.
613  */
614  if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
615  (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
616  return(MagickFalse);
617  if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
618  (lseek(clone_info->file,0,SEEK_SET) < 0))
619  return(MagickFalse);
620  quantum=(size_t) MagickMaxBufferExtent;
621  if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
622  quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
623  buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
624  if (buffer == (unsigned char *) NULL)
625  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
626  extent=0;
627  while ((count=read(cache_info->file,buffer,quantum)) > 0)
628  {
629  ssize_t
630  number_bytes;
631 
632  number_bytes=write(clone_info->file,buffer,(size_t) count);
633  if (number_bytes != count)
634  break;
635  extent+=number_bytes;
636  }
637  buffer=(unsigned char *) RelinquishMagickMemory(buffer);
638  if (extent != cache_info->length)
639  return(MagickFalse);
640  return(MagickTrue);
641 }
642 
644  CacheInfo *magick_restrict clone_info,CacheInfo *magick_restrict cache_info,
645  ExceptionInfo *exception)
646 {
647 #define MaxCacheThreads ((size_t) GetMagickResourceLimit(ThreadResource))
648 #define cache_number_threads(source,destination,chunk,multithreaded) \
649  num_threads((multithreaded) == 0 ? 1 : \
650  (((source)->type != MemoryCache) && ((source)->type != MapCache)) || \
651  (((destination)->type != MemoryCache) && ((destination)->type != MapCache)) ? \
652  MagickMax(MagickMin(GetMagickResourceLimit(ThreadResource),2),1) : \
653  MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(ThreadResource),(ssize_t) (chunk)/256),1))
654 
656  optimize,
657  status;
658 
659  NexusInfo
660  **magick_restrict cache_nexus,
661  **magick_restrict clone_nexus;
662 
663  size_t
664  length;
665 
666  ssize_t
667  y;
668 
669  assert(cache_info != (CacheInfo *) NULL);
670  assert(clone_info != (CacheInfo *) NULL);
671  assert(exception != (ExceptionInfo *) NULL);
672  if (cache_info->type == PingCache)
673  return(MagickTrue);
674  length=cache_info->number_channels*sizeof(*cache_info->channel_map);
675  if ((cache_info->storage_class == clone_info->storage_class) &&
676  (cache_info->colorspace == clone_info->colorspace) &&
677  (cache_info->alpha_trait == clone_info->alpha_trait) &&
678  (cache_info->channels == clone_info->channels) &&
679  (cache_info->columns == clone_info->columns) &&
680  (cache_info->rows == clone_info->rows) &&
681  (cache_info->number_channels == clone_info->number_channels) &&
682  (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) &&
683  (cache_info->metacontent_extent == clone_info->metacontent_extent))
684  {
685  /*
686  Identical pixel cache morphology.
687  */
688  if (((cache_info->type == MemoryCache) ||
689  (cache_info->type == MapCache)) &&
690  ((clone_info->type == MemoryCache) || (clone_info->type == MapCache)))
691  {
692  (void) memcpy(clone_info->pixels,cache_info->pixels,
693  cache_info->number_channels*cache_info->columns*cache_info->rows*
694  sizeof(*cache_info->pixels));
695  if ((cache_info->metacontent_extent != 0) &&
696  (clone_info->metacontent_extent != 0))
697  (void) memcpy(clone_info->metacontent,cache_info->metacontent,
698  cache_info->columns*cache_info->rows*
699  clone_info->metacontent_extent*sizeof(unsigned char));
700  return(MagickTrue);
701  }
702  if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
703  return(ClonePixelCacheOnDisk(cache_info,clone_info));
704  }
705  /*
706  Mismatched pixel cache morphology.
707  */
710  length=cache_info->number_channels*sizeof(*cache_info->channel_map);
711  optimize=(cache_info->number_channels == clone_info->number_channels) &&
712  (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) ?
714  length=(size_t) MagickMin(cache_info->number_channels*cache_info->columns,
715  clone_info->number_channels*clone_info->columns);
716  status=MagickTrue;
717 #if defined(MAGICKCORE_OPENMP_SUPPORT)
718  #pragma omp parallel for schedule(static) shared(status) \
719  cache_number_threads(cache_info,clone_info,cache_info->rows,1)
720 #endif
721  for (y=0; y < (ssize_t) cache_info->rows; y++)
722  {
723  const int
724  id = GetOpenMPThreadId();
725 
726  Quantum
727  *pixels;
728 
729  register ssize_t
730  x;
731 
732  if (status == MagickFalse)
733  continue;
734  if (y >= (ssize_t) clone_info->rows)
735  continue;
736  pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
737  cache_info->columns,1,MagickFalse,cache_nexus[id],exception);
738  if (pixels == (Quantum *) NULL)
739  continue;
740  status=ReadPixelCachePixels(cache_info,cache_nexus[id],exception);
741  if (status == MagickFalse)
742  continue;
743  pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
744  clone_info->columns,1,MagickFalse,clone_nexus[id],exception);
745  if (pixels == (Quantum *) NULL)
746  continue;
747  (void) memset(clone_nexus[id]->pixels,0,(size_t) clone_nexus[id]->length);
748  if (optimize != MagickFalse)
749  (void) memcpy(clone_nexus[id]->pixels,cache_nexus[id]->pixels,length*
750  sizeof(Quantum));
751  else
752  {
753  register const Quantum
754  *magick_restrict p;
755 
756  register Quantum
757  *magick_restrict q;
758 
759  /*
760  Mismatched pixel channel map.
761  */
762  p=cache_nexus[id]->pixels;
763  q=clone_nexus[id]->pixels;
764  for (x=0; x < (ssize_t) cache_info->columns; x++)
765  {
766  register ssize_t
767  i;
768 
769  if (x == (ssize_t) clone_info->columns)
770  break;
771  for (i=0; i < (ssize_t) clone_info->number_channels; i++)
772  {
774  channel;
775 
776  PixelTrait
777  traits;
778 
779  channel=clone_info->channel_map[i].channel;
780  traits=cache_info->channel_map[channel].traits;
781  if (traits != UndefinedPixelTrait)
782  *q=*(p+cache_info->channel_map[channel].offset);
783  q++;
784  }
785  p+=cache_info->number_channels;
786  }
787  }
788  status=WritePixelCachePixels(clone_info,clone_nexus[id],exception);
789  }
790  if ((cache_info->metacontent_extent != 0) &&
791  (clone_info->metacontent_extent != 0))
792  {
793  /*
794  Clone metacontent.
795  */
796  length=(size_t) MagickMin(cache_info->metacontent_extent,
797  clone_info->metacontent_extent);
798 #if defined(MAGICKCORE_OPENMP_SUPPORT)
799  #pragma omp parallel for schedule(static) shared(status) \
800  cache_number_threads(cache_info,clone_info,cache_info->rows,1)
801 #endif
802  for (y=0; y < (ssize_t) cache_info->rows; y++)
803  {
804  const int
805  id = GetOpenMPThreadId();
806 
807  Quantum
808  *pixels;
809 
810  if (status == MagickFalse)
811  continue;
812  if (y >= (ssize_t) clone_info->rows)
813  continue;
814  pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,0,y,
815  cache_info->columns,1,MagickFalse,cache_nexus[id],exception);
816  if (pixels == (Quantum *) NULL)
817  continue;
818  status=ReadPixelCacheMetacontent(cache_info,cache_nexus[id],exception);
819  if (status == MagickFalse)
820  continue;
821  pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,0,y,
822  clone_info->columns,1,MagickFalse,clone_nexus[id],exception);
823  if (pixels == (Quantum *) NULL)
824  continue;
825  if ((clone_nexus[id]->metacontent != (void *) NULL) &&
826  (cache_nexus[id]->metacontent != (void *) NULL))
827  (void) memcpy(clone_nexus[id]->metacontent,
828  cache_nexus[id]->metacontent,length*sizeof(unsigned char));
829  status=WritePixelCacheMetacontent(clone_info,clone_nexus[id],exception);
830  }
831  }
832  cache_nexus=DestroyPixelCacheNexus(cache_nexus,MaxCacheThreads);
833  clone_nexus=DestroyPixelCacheNexus(clone_nexus,MaxCacheThreads);
834  if (cache_info->debug != MagickFalse)
835  {
836  char
837  message[MagickPathExtent];
838 
839  (void) FormatLocaleString(message,MagickPathExtent,"%s => %s",
840  CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
841  CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
842  (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
843  }
844  return(status);
845 }
846 
847 /*
848 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
849 % %
850 % %
851 % %
852 + D e s t r o y I m a g e P i x e l C a c h e %
853 % %
854 % %
855 % %
856 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
857 %
858 % DestroyImagePixelCache() deallocates memory associated with the pixel cache.
859 %
860 % The format of the DestroyImagePixelCache() method is:
861 %
862 % void DestroyImagePixelCache(Image *image)
863 %
864 % A description of each parameter follows:
865 %
866 % o image: the image.
867 %
868 */
869 static void DestroyImagePixelCache(Image *image)
870 {
871  assert(image != (Image *) NULL);
872  assert(image->signature == MagickCoreSignature);
873  if (image->debug != MagickFalse)
874  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
875  if (image->cache != (void *) NULL)
876  image->cache=DestroyPixelCache(image->cache);
877 }
878 
879 /*
880 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
881 % %
882 % %
883 % %
884 + D e s t r o y I m a g e P i x e l s %
885 % %
886 % %
887 % %
888 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
889 %
890 % DestroyImagePixels() deallocates memory associated with the pixel cache.
891 %
892 % The format of the DestroyImagePixels() method is:
893 %
894 % void DestroyImagePixels(Image *image)
895 %
896 % A description of each parameter follows:
897 %
898 % o image: the image.
899 %
900 */
902 {
903  CacheInfo
904  *magick_restrict cache_info;
905 
906  assert(image != (const Image *) NULL);
907  assert(image->signature == MagickCoreSignature);
908  if (image->debug != MagickFalse)
909  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
910  assert(image->cache != (Cache) NULL);
911  cache_info=(CacheInfo *) image->cache;
912  assert(cache_info->signature == MagickCoreSignature);
913  if (cache_info->methods.destroy_pixel_handler != (DestroyPixelHandler) NULL)
914  {
915  cache_info->methods.destroy_pixel_handler(image);
916  return;
917  }
918  image->cache=DestroyPixelCache(image->cache);
919 }
920 
921 /*
922 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
923 % %
924 % %
925 % %
926 + D e s t r o y P i x e l C a c h e %
927 % %
928 % %
929 % %
930 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
931 %
932 % DestroyPixelCache() deallocates memory associated with the pixel cache.
933 %
934 % The format of the DestroyPixelCache() method is:
935 %
936 % Cache DestroyPixelCache(Cache cache)
937 %
938 % A description of each parameter follows:
939 %
940 % o cache: the pixel cache.
941 %
942 */
943 
945 {
946  int
947  status;
948 
949  status=(-1);
950  if (cache_info->file != -1)
951  {
952  status=close(cache_info->file);
953  cache_info->file=(-1);
955  }
956  return(status == -1 ? MagickFalse : MagickTrue);
957 }
958 
959 static inline void RelinquishPixelCachePixels(CacheInfo *cache_info)
960 {
961  switch (cache_info->type)
962  {
963  case MemoryCache:
964  {
965 #if defined(MAGICKCORE_OPENCL_SUPPORT)
966  if (cache_info->opencl != (MagickCLCacheInfo) NULL)
967  {
968  cache_info->opencl=RelinquishMagickCLCacheInfo(cache_info->opencl,
969  MagickTrue);
970  cache_info->pixels=(Quantum *) NULL;
971  break;
972  }
973 #endif
974  if (cache_info->mapped == MagickFalse)
975  cache_info->pixels=(Quantum *) RelinquishAlignedMemory(
976  cache_info->pixels);
977  else
978  (void) UnmapBlob(cache_info->pixels,(size_t) cache_info->length);
980  break;
981  }
982  case MapCache:
983  {
984  (void) UnmapBlob(cache_info->pixels,(size_t) cache_info->length);
985  cache_info->pixels=(Quantum *) NULL;
986  if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
987  (void) RelinquishUniqueFileResource(cache_info->cache_filename);
988  *cache_info->cache_filename='\0';
990  }
991  case DiskCache:
992  {
993  if (cache_info->file != -1)
994  (void) ClosePixelCacheOnDisk(cache_info);
995  if ((cache_info->mode != ReadMode) && (cache_info->mode != PersistMode))
996  (void) RelinquishUniqueFileResource(cache_info->cache_filename);
997  *cache_info->cache_filename='\0';
999  break;
1000  }
1001  case DistributedCache:
1002  {
1003  *cache_info->cache_filename='\0';
1005  cache_info->server_info);
1006  break;
1007  }
1008  default:
1009  break;
1010  }
1011  cache_info->type=UndefinedCache;
1012  cache_info->mapped=MagickFalse;
1013  cache_info->metacontent=(void *) NULL;
1014 }
1015 
1017 {
1018  CacheInfo
1019  *magick_restrict cache_info;
1020 
1021  assert(cache != (Cache) NULL);
1022  cache_info=(CacheInfo *) cache;
1023  assert(cache_info->signature == MagickCoreSignature);
1024  if (cache_info->debug != MagickFalse)
1026  cache_info->filename);
1027  LockSemaphoreInfo(cache_info->semaphore);
1028  cache_info->reference_count--;
1029  if (cache_info->reference_count != 0)
1030  {
1031  UnlockSemaphoreInfo(cache_info->semaphore);
1032  return((Cache) NULL);
1033  }
1034  UnlockSemaphoreInfo(cache_info->semaphore);
1035  if (cache_info->debug != MagickFalse)
1036  {
1037  char
1038  message[MagickPathExtent];
1039 
1040  (void) FormatLocaleString(message,MagickPathExtent,"destroy %s",
1041  cache_info->filename);
1042  (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
1043  }
1044  RelinquishPixelCachePixels(cache_info);
1045  if (cache_info->server_info != (DistributeCacheInfo *) NULL)
1046  cache_info->server_info=DestroyDistributeCacheInfo((DistributeCacheInfo *)
1047  cache_info->server_info);
1048  if (cache_info->nexus_info != (NexusInfo **) NULL)
1049  cache_info->nexus_info=DestroyPixelCacheNexus(cache_info->nexus_info,
1050  cache_info->number_threads);
1051  if (cache_info->random_info != (RandomInfo *) NULL)
1052  cache_info->random_info=DestroyRandomInfo(cache_info->random_info);
1053  if (cache_info->file_semaphore != (SemaphoreInfo *) NULL)
1054  RelinquishSemaphoreInfo(&cache_info->file_semaphore);
1055  if (cache_info->semaphore != (SemaphoreInfo *) NULL)
1056  RelinquishSemaphoreInfo(&cache_info->semaphore);
1057  cache_info->signature=(~MagickCoreSignature);
1058  cache_info=(CacheInfo *) RelinquishAlignedMemory(cache_info);
1059  cache=(Cache) NULL;
1060  return(cache);
1061 }
1062 
1063 /*
1064 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1065 % %
1066 % %
1067 % %
1068 + D e s t r o y P i x e l C a c h e N e x u s %
1069 % %
1070 % %
1071 % %
1072 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1073 %
1074 % DestroyPixelCacheNexus() destroys a pixel cache nexus.
1075 %
1076 % The format of the DestroyPixelCacheNexus() method is:
1077 %
1078 % NexusInfo **DestroyPixelCacheNexus(NexusInfo *nexus_info,
1079 % const size_t number_threads)
1080 %
1081 % A description of each parameter follows:
1082 %
1083 % o nexus_info: the nexus to destroy.
1084 %
1085 % o number_threads: the number of nexus threads.
1086 %
1087 */
1088 
1089 static inline void RelinquishCacheNexusPixels(NexusInfo *nexus_info)
1090 {
1091  if (nexus_info->mapped == MagickFalse)
1092  (void) RelinquishAlignedMemory(nexus_info->cache);
1093  else
1094  (void) UnmapBlob(nexus_info->cache,(size_t) nexus_info->length);
1095  nexus_info->cache=(Quantum *) NULL;
1096  nexus_info->pixels=(Quantum *) NULL;
1097  nexus_info->metacontent=(void *) NULL;
1098  nexus_info->length=0;
1099  nexus_info->mapped=MagickFalse;
1100 }
1101 
1103  const size_t number_threads)
1104 {
1105  register ssize_t
1106  i;
1107 
1108  assert(nexus_info != (NexusInfo **) NULL);
1109  for (i=0; i < (ssize_t) number_threads; i++)
1110  {
1111  if (nexus_info[i]->cache != (Quantum *) NULL)
1112  RelinquishCacheNexusPixels(nexus_info[i]);
1113  nexus_info[i]->signature=(~MagickCoreSignature);
1114  }
1115  nexus_info[0]=(NexusInfo *) RelinquishMagickMemory(nexus_info[0]);
1116  nexus_info=(NexusInfo **) RelinquishAlignedMemory(nexus_info);
1117  return(nexus_info);
1118 }
1119 
1120 /*
1121 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1122 % %
1123 % %
1124 % %
1125 % G e t A u t h e n t i c M e t a c o n t e n t %
1126 % %
1127 % %
1128 % %
1129 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1130 %
1131 % GetAuthenticMetacontent() returns the authentic metacontent corresponding
1132 % with the last call to QueueAuthenticPixels() or GetVirtualPixels(). NULL is
1133 % returned if the associated pixels are not available.
1134 %
1135 % The format of the GetAuthenticMetacontent() method is:
1136 %
1137 % void *GetAuthenticMetacontent(const Image *image)
1138 %
1139 % A description of each parameter follows:
1140 %
1141 % o image: the image.
1142 %
1143 */
1145 {
1146  CacheInfo
1147  *magick_restrict cache_info;
1148 
1149  const int
1150  id = GetOpenMPThreadId();
1151 
1152  assert(image != (const Image *) NULL);
1153  assert(image->signature == MagickCoreSignature);
1154  assert(image->cache != (Cache) NULL);
1155  cache_info=(CacheInfo *) image->cache;
1156  assert(cache_info->signature == MagickCoreSignature);
1157  if (cache_info->methods.get_authentic_metacontent_from_handler !=
1159  {
1160  void
1161  *metacontent;
1162 
1163  metacontent=cache_info->methods.
1164  get_authentic_metacontent_from_handler(image);
1165  return(metacontent);
1166  }
1167  assert(id < (int) cache_info->number_threads);
1168  return(cache_info->nexus_info[id]->metacontent);
1169 }
1170 
1171 /*
1172 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1173 % %
1174 % %
1175 % %
1176 + G e t A u t h e n t i c M e t a c o n t e n t F r o m C a c h e %
1177 % %
1178 % %
1179 % %
1180 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1181 %
1182 % GetAuthenticMetacontentFromCache() returns the meta-content corresponding
1183 % with the last call to QueueAuthenticPixelsCache() or
1184 % GetAuthenticPixelsCache().
1185 %
1186 % The format of the GetAuthenticMetacontentFromCache() method is:
1187 %
1188 % void *GetAuthenticMetacontentFromCache(const Image *image)
1189 %
1190 % A description of each parameter follows:
1191 %
1192 % o image: the image.
1193 %
1194 */
1195 static void *GetAuthenticMetacontentFromCache(const Image *image)
1196 {
1197  CacheInfo
1198  *magick_restrict cache_info;
1199 
1200  const int
1201  id = GetOpenMPThreadId();
1202 
1203  assert(image != (const Image *) NULL);
1204  assert(image->signature == MagickCoreSignature);
1205  assert(image->cache != (Cache) NULL);
1206  cache_info=(CacheInfo *) image->cache;
1207  assert(cache_info->signature == MagickCoreSignature);
1208  assert(id < (int) cache_info->number_threads);
1209  return(cache_info->nexus_info[id]->metacontent);
1210 }
1211 
1212 #if defined(MAGICKCORE_OPENCL_SUPPORT)
1213 /*
1214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1215 % %
1216 % %
1217 % %
1218 + G e t A u t h e n t i c O p e n C L B u f f e r %
1219 % %
1220 % %
1221 % %
1222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1223 %
1224 % GetAuthenticOpenCLBuffer() returns an OpenCL buffer used to execute OpenCL
1225 % operations.
1226 %
1227 % The format of the GetAuthenticOpenCLBuffer() method is:
1228 %
1229 % cl_mem GetAuthenticOpenCLBuffer(const Image *image,
1230 % MagickCLDevice device,ExceptionInfo *exception)
1231 %
1232 % A description of each parameter follows:
1233 %
1234 % o image: the image.
1235 %
1236 % o device: the device to use.
1237 %
1238 % o exception: return any errors or warnings in this structure.
1239 %
1240 */
1241 MagickPrivate cl_mem GetAuthenticOpenCLBuffer(const Image *image,
1242  MagickCLDevice device,ExceptionInfo *exception)
1243 {
1244  CacheInfo
1245  *magick_restrict cache_info;
1246 
1247  assert(image != (const Image *) NULL);
1248  assert(device != (const MagickCLDevice) NULL);
1249  cache_info=(CacheInfo *) image->cache;
1250  if ((cache_info->type == UndefinedCache) || (cache_info->reference_count > 1))
1251  {
1252  SyncImagePixelCache((Image *) image,exception);
1253  cache_info=(CacheInfo *) image->cache;
1254  }
1255  if ((cache_info->type != MemoryCache) || (cache_info->mapped != MagickFalse))
1256  return((cl_mem) NULL);
1257  LockSemaphoreInfo(cache_info->semaphore);
1258  if ((cache_info->opencl != (MagickCLCacheInfo) NULL) &&
1259  (cache_info->opencl->device->context != device->context))
1260  cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
1261  if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1262  {
1263  assert(cache_info->pixels != (Quantum *) NULL);
1264  cache_info->opencl=AcquireMagickCLCacheInfo(device,cache_info->pixels,
1265  cache_info->length);
1266  }
1267  if (cache_info->opencl != (MagickCLCacheInfo) NULL)
1268  RetainOpenCLMemObject(cache_info->opencl->buffer);
1269  UnlockSemaphoreInfo(cache_info->semaphore);
1270  if (cache_info->opencl == (MagickCLCacheInfo) NULL)
1271  return((cl_mem) NULL);
1272  assert(cache_info->opencl->pixels == cache_info->pixels);
1273  return(cache_info->opencl->buffer);
1274 }
1275 #endif
1276 
1277 /*
1278 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1279 % %
1280 % %
1281 % %
1282 + G e t A u t h e n t i c P i x e l C a c h e N e x u s %
1283 % %
1284 % %
1285 % %
1286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1287 %
1288 % GetAuthenticPixelCacheNexus() gets authentic pixels from the in-memory or
1289 % disk pixel cache as defined by the geometry parameters. A pointer to the
1290 % pixels is returned if the pixels are transferred, otherwise a NULL is
1291 % returned.
1292 %
1293 % The format of the GetAuthenticPixelCacheNexus() method is:
1294 %
1295 % Quantum *GetAuthenticPixelCacheNexus(Image *image,const ssize_t x,
1296 % const ssize_t y,const size_t columns,const size_t rows,
1297 % NexusInfo *nexus_info,ExceptionInfo *exception)
1298 %
1299 % A description of each parameter follows:
1300 %
1301 % o image: the image.
1302 %
1303 % o x,y,columns,rows: These values define the perimeter of a region of
1304 % pixels.
1305 %
1306 % o nexus_info: the cache nexus to return.
1307 %
1308 % o exception: return any errors or warnings in this structure.
1309 %
1310 */
1311 
1313  const ssize_t y,const size_t columns,const size_t rows,NexusInfo *nexus_info,
1314  ExceptionInfo *exception)
1315 {
1316  CacheInfo
1317  *magick_restrict cache_info;
1318 
1319  Quantum
1320  *magick_restrict pixels;
1321 
1322  /*
1323  Transfer pixels from the cache.
1324  */
1325  assert(image != (Image *) NULL);
1326  assert(image->signature == MagickCoreSignature);
1327  pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickTrue,
1328  nexus_info,exception);
1329  if (pixels == (Quantum *) NULL)
1330  return((Quantum *) NULL);
1331  cache_info=(CacheInfo *) image->cache;
1332  assert(cache_info->signature == MagickCoreSignature);
1333  if (nexus_info->authentic_pixel_cache != MagickFalse)
1334  return(pixels);
1335  if (ReadPixelCachePixels(cache_info,nexus_info,exception) == MagickFalse)
1336  return((Quantum *) NULL);
1337  if (cache_info->metacontent_extent != 0)
1338  if (ReadPixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse)
1339  return((Quantum *) NULL);
1340  return(pixels);
1341 }
1342 
1343 /*
1344 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1345 % %
1346 % %
1347 % %
1348 + G e t A u t h e n t i c P i x e l s F r o m C a c h e %
1349 % %
1350 % %
1351 % %
1352 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1353 %
1354 % GetAuthenticPixelsFromCache() returns the pixels associated with the last
1355 % call to the QueueAuthenticPixelsCache() or GetAuthenticPixelsCache() methods.
1356 %
1357 % The format of the GetAuthenticPixelsFromCache() method is:
1358 %
1359 % Quantum *GetAuthenticPixelsFromCache(const Image image)
1360 %
1361 % A description of each parameter follows:
1362 %
1363 % o image: the image.
1364 %
1365 */
1367 {
1368  CacheInfo
1369  *magick_restrict cache_info;
1370 
1371  const int
1372  id = GetOpenMPThreadId();
1373 
1374  assert(image != (const Image *) NULL);
1375  assert(image->signature == MagickCoreSignature);
1376  assert(image->cache != (Cache) NULL);
1377  cache_info=(CacheInfo *) image->cache;
1378  assert(cache_info->signature == MagickCoreSignature);
1379  assert(id < (int) cache_info->number_threads);
1380  return(cache_info->nexus_info[id]->pixels);
1381 }
1382 
1383 /*
1384 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1385 % %
1386 % %
1387 % %
1388 % G e t A u t h e n t i c P i x e l Q u e u e %
1389 % %
1390 % %
1391 % %
1392 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1393 %
1394 % GetAuthenticPixelQueue() returns the authentic pixels associated
1395 % corresponding with the last call to QueueAuthenticPixels() or
1396 % GetAuthenticPixels().
1397 %
1398 % The format of the GetAuthenticPixelQueue() method is:
1399 %
1400 % Quantum *GetAuthenticPixelQueue(const Image image)
1401 %
1402 % A description of each parameter follows:
1403 %
1404 % o image: the image.
1405 %
1406 */
1408 {
1409  CacheInfo
1410  *magick_restrict cache_info;
1411 
1412  const int
1413  id = GetOpenMPThreadId();
1414 
1415  assert(image != (const Image *) NULL);
1416  assert(image->signature == MagickCoreSignature);
1417  assert(image->cache != (Cache) NULL);
1418  cache_info=(CacheInfo *) image->cache;
1419  assert(cache_info->signature == MagickCoreSignature);
1420  if (cache_info->methods.get_authentic_pixels_from_handler !=
1422  return(cache_info->methods.get_authentic_pixels_from_handler(image));
1423  assert(id < (int) cache_info->number_threads);
1424  return(cache_info->nexus_info[id]->pixels);
1425 }
1426 
1427 /*
1428 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1429 % %
1430 % %
1431 % %
1432 % G e t A u t h e n t i c P i x e l s %
1433 % %
1434 % %
1435 % %
1436 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1437 %
1438 % GetAuthenticPixels() obtains a pixel region for read/write access. If the
1439 % region is successfully accessed, a pointer to a Quantum array
1440 % representing the region is returned, otherwise NULL is returned.
1441 %
1442 % The returned pointer may point to a temporary working copy of the pixels
1443 % or it may point to the original pixels in memory. Performance is maximized
1444 % if the selected region is part of one row, or one or more full rows, since
1445 % then there is opportunity to access the pixels in-place (without a copy)
1446 % if the image is in memory, or in a memory-mapped file. The returned pointer
1447 % must *never* be deallocated by the user.
1448 %
1449 % Pixels accessed via the returned pointer represent a simple array of type
1450 % Quantum. If the image has corresponding metacontent,call
1451 % GetAuthenticMetacontent() after invoking GetAuthenticPixels() to obtain the
1452 % meta-content corresponding to the region. Once the Quantum array has
1453 % been updated, the changes must be saved back to the underlying image using
1454 % SyncAuthenticPixels() or they may be lost.
1455 %
1456 % The format of the GetAuthenticPixels() method is:
1457 %
1458 % Quantum *GetAuthenticPixels(Image *image,const ssize_t x,
1459 % const ssize_t y,const size_t columns,const size_t rows,
1460 % ExceptionInfo *exception)
1461 %
1462 % A description of each parameter follows:
1463 %
1464 % o image: the image.
1465 %
1466 % o x,y,columns,rows: These values define the perimeter of a region of
1467 % pixels.
1468 %
1469 % o exception: return any errors or warnings in this structure.
1470 %
1471 */
1473  const ssize_t y,const size_t columns,const size_t rows,
1474  ExceptionInfo *exception)
1475 {
1476  CacheInfo
1477  *magick_restrict cache_info;
1478 
1479  const int
1480  id = GetOpenMPThreadId();
1481 
1482  Quantum
1483  *pixels;
1484 
1485  assert(image != (Image *) NULL);
1486  assert(image->signature == MagickCoreSignature);
1487  assert(image->cache != (Cache) NULL);
1488  cache_info=(CacheInfo *) image->cache;
1489  assert(cache_info->signature == MagickCoreSignature);
1490  if (cache_info->methods.get_authentic_pixels_handler !=
1492  {
1493  pixels=cache_info->methods.get_authentic_pixels_handler(image,x,y,columns,
1494  rows,exception);
1495  return(pixels);
1496  }
1497  assert(id < (int) cache_info->number_threads);
1498  pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1499  cache_info->nexus_info[id],exception);
1500  return(pixels);
1501 }
1502 
1503 /*
1504 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1505 % %
1506 % %
1507 % %
1508 + G e t A u t h e n t i c P i x e l s C a c h e %
1509 % %
1510 % %
1511 % %
1512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1513 %
1514 % GetAuthenticPixelsCache() gets pixels from the in-memory or disk pixel cache
1515 % as defined by the geometry parameters. A pointer to the pixels is returned
1516 % if the pixels are transferred, otherwise a NULL is returned.
1517 %
1518 % The format of the GetAuthenticPixelsCache() method is:
1519 %
1520 % Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
1521 % const ssize_t y,const size_t columns,const size_t rows,
1522 % ExceptionInfo *exception)
1523 %
1524 % A description of each parameter follows:
1525 %
1526 % o image: the image.
1527 %
1528 % o x,y,columns,rows: These values define the perimeter of a region of
1529 % pixels.
1530 %
1531 % o exception: return any errors or warnings in this structure.
1532 %
1533 */
1534 static Quantum *GetAuthenticPixelsCache(Image *image,const ssize_t x,
1535  const ssize_t y,const size_t columns,const size_t rows,
1536  ExceptionInfo *exception)
1537 {
1538  CacheInfo
1539  *magick_restrict cache_info;
1540 
1541  const int
1542  id = GetOpenMPThreadId();
1543 
1544  Quantum
1545  *magick_restrict pixels;
1546 
1547  assert(image != (const Image *) NULL);
1548  assert(image->signature == MagickCoreSignature);
1549  assert(image->cache != (Cache) NULL);
1550  cache_info=(CacheInfo *) image->cache;
1551  if (cache_info == (Cache) NULL)
1552  return((Quantum *) NULL);
1553  assert(cache_info->signature == MagickCoreSignature);
1554  assert(id < (int) cache_info->number_threads);
1555  pixels=GetAuthenticPixelCacheNexus(image,x,y,columns,rows,
1556  cache_info->nexus_info[id],exception);
1557  return(pixels);
1558 }
1559 
1560 /*
1561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1562 % %
1563 % %
1564 % %
1565 + G e t I m a g e E x t e n t %
1566 % %
1567 % %
1568 % %
1569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1570 %
1571 % GetImageExtent() returns the extent of the pixels associated corresponding
1572 % with the last call to QueueAuthenticPixels() or GetAuthenticPixels().
1573 %
1574 % The format of the GetImageExtent() method is:
1575 %
1576 % MagickSizeType GetImageExtent(const Image *image)
1577 %
1578 % A description of each parameter follows:
1579 %
1580 % o image: the image.
1581 %
1582 */
1584 {
1585  CacheInfo
1586  *magick_restrict cache_info;
1587 
1588  const int
1589  id = GetOpenMPThreadId();
1590 
1591  assert(image != (Image *) NULL);
1592  assert(image->signature == MagickCoreSignature);
1593  if (image->debug != MagickFalse)
1594  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1595  assert(image->cache != (Cache) NULL);
1596  cache_info=(CacheInfo *) image->cache;
1597  assert(cache_info->signature == MagickCoreSignature);
1598  assert(id < (int) cache_info->number_threads);
1599  return(GetPixelCacheNexusExtent(cache_info,cache_info->nexus_info[id]));
1600 }
1601 
1602 /*
1603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1604 % %
1605 % %
1606 % %
1607 + G e t I m a g e P i x e l C a c h e %
1608 % %
1609 % %
1610 % %
1611 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1612 %
1613 % GetImagePixelCache() ensures that there is only a single reference to the
1614 % pixel cache to be modified, updating the provided cache pointer to point to
1615 % a clone of the original pixel cache if necessary.
1616 %
1617 % The format of the GetImagePixelCache method is:
1618 %
1619 % Cache GetImagePixelCache(Image *image,const MagickBooleanType clone,
1620 % ExceptionInfo *exception)
1621 %
1622 % A description of each parameter follows:
1623 %
1624 % o image: the image.
1625 %
1626 % o clone: any value other than MagickFalse clones the cache pixels.
1627 %
1628 % o exception: return any errors or warnings in this structure.
1629 %
1630 */
1631 
1633  const Image *magick_restrict image)
1634 {
1635  const CacheInfo
1636  *magick_restrict cache_info;
1637 
1638  const PixelChannelMap
1639  *magick_restrict p,
1640  *magick_restrict q;
1641 
1642  /*
1643  Does the image match the pixel cache morphology?
1644  */
1645  cache_info=(CacheInfo *) image->cache;
1646  p=image->channel_map;
1647  q=cache_info->channel_map;
1648  if ((image->storage_class != cache_info->storage_class) ||
1649  (image->colorspace != cache_info->colorspace) ||
1650  (image->alpha_trait != cache_info->alpha_trait) ||
1651  (image->channels != cache_info->channels) ||
1652  (image->columns != cache_info->columns) ||
1653  (image->rows != cache_info->rows) ||
1654  (image->number_channels != cache_info->number_channels) ||
1655  (memcmp(p,q,image->number_channels*sizeof(*p)) != 0) ||
1656  (image->metacontent_extent != cache_info->metacontent_extent) ||
1657  (cache_info->nexus_info == (NexusInfo **) NULL))
1658  return(MagickFalse);
1659  return(MagickTrue);
1660 }
1661 
1663  ExceptionInfo *exception)
1664 {
1665  CacheInfo
1666  *magick_restrict cache_info;
1667 
1669  destroy,
1670  status;
1671 
1672  static MagickSizeType
1673  cache_timelimit = MagickResourceInfinity,
1674  cpu_throttle = MagickResourceInfinity,
1675  cycles = 0;
1676 
1677  status=MagickTrue;
1678  if (cpu_throttle == MagickResourceInfinity)
1680  if ((cpu_throttle != 0) && ((cycles++ % 32) == 0))
1681  MagickDelay(cpu_throttle);
1682  if (cache_epoch == 0)
1683  {
1684  /*
1685  Set the expire time in seconds.
1686  */
1687  cache_timelimit=GetMagickResourceLimit(TimeResource);
1688  cache_epoch=time((time_t *) NULL);
1689  }
1690  if ((cache_timelimit != MagickResourceInfinity) &&
1691  ((MagickSizeType) (time((time_t *) NULL)-cache_epoch) >= cache_timelimit))
1692  {
1693 #if defined(ECANCELED)
1694  errno=ECANCELED;
1695 #endif
1696  cache_info=(CacheInfo *) image->cache;
1697  if (cache_info->file != -1)
1698  (void) ClosePixelCacheOnDisk(cache_info);
1699  ThrowFatalException(ResourceLimitFatalError,"TimeLimitExceeded");
1700  }
1701  LockSemaphoreInfo(image->semaphore);
1702  assert(image->cache != (Cache) NULL);
1703  cache_info=(CacheInfo *) image->cache;
1704 #if defined(MAGICKCORE_OPENCL_SUPPORT)
1705  CopyOpenCLBuffer(cache_info);
1706 #endif
1707  destroy=MagickFalse;
1708  if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1709  {
1710  LockSemaphoreInfo(cache_info->semaphore);
1711  if ((cache_info->reference_count > 1) || (cache_info->mode == ReadMode))
1712  {
1713  CacheInfo
1714  *clone_info;
1715 
1716  Image
1717  clone_image;
1718 
1719  /*
1720  Clone pixel cache.
1721  */
1722  clone_image=(*image);
1723  clone_image.semaphore=AcquireSemaphoreInfo();
1724  clone_image.reference_count=1;
1725  clone_image.cache=ClonePixelCache(cache_info);
1726  clone_info=(CacheInfo *) clone_image.cache;
1727  status=OpenPixelCache(&clone_image,IOMode,exception);
1728  if (status == MagickFalse)
1729  clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
1730  else
1731  {
1732  if (clone != MagickFalse)
1733  status=ClonePixelCacheRepository(clone_info,cache_info,
1734  exception);
1735  if (status == MagickFalse)
1736  clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
1737  else
1738  {
1739  destroy=MagickTrue;
1740  image->cache=clone_info;
1741  }
1742  }
1743  RelinquishSemaphoreInfo(&clone_image.semaphore);
1744  }
1745  UnlockSemaphoreInfo(cache_info->semaphore);
1746  }
1747  if (destroy != MagickFalse)
1748  cache_info=(CacheInfo *) DestroyPixelCache(cache_info);
1749  if (status != MagickFalse)
1750  {
1751  /*
1752  Ensure the image matches the pixel cache morphology.
1753  */
1754  image->type=UndefinedType;
1756  {
1757  status=OpenPixelCache(image,IOMode,exception);
1758  cache_info=(CacheInfo *) image->cache;
1759  if (cache_info->file != -1)
1760  (void) ClosePixelCacheOnDisk(cache_info);
1761  }
1762  }
1764  if (status == MagickFalse)
1765  return((Cache) NULL);
1766  return(image->cache);
1767 }
1768 
1769 /*
1770 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1771 % %
1772 % %
1773 % %
1774 + G e t I m a g e P i x e l C a c h e T y p e %
1775 % %
1776 % %
1777 % %
1778 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1779 %
1780 % GetImagePixelCacheType() returns the pixel cache type: UndefinedCache,
1781 % DiskCache, MemoryCache, MapCache, or PingCache.
1782 %
1783 % The format of the GetImagePixelCacheType() method is:
1784 %
1785 % CacheType GetImagePixelCacheType(const Image *image)
1786 %
1787 % A description of each parameter follows:
1788 %
1789 % o image: the image.
1790 %
1791 */
1793 {
1794  CacheInfo
1795  *magick_restrict cache_info;
1796 
1797  assert(image != (Image *) NULL);
1798  assert(image->signature == MagickCoreSignature);
1799  assert(image->cache != (Cache) NULL);
1800  cache_info=(CacheInfo *) image->cache;
1801  assert(cache_info->signature == MagickCoreSignature);
1802  return(cache_info->type);
1803 }
1804 
1805 /*
1806 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1807 % %
1808 % %
1809 % %
1810 % G e t O n e A u t h e n t i c P i x e l %
1811 % %
1812 % %
1813 % %
1814 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1815 %
1816 % GetOneAuthenticPixel() returns a single pixel at the specified (x,y)
1817 % location. The image background color is returned if an error occurs.
1818 %
1819 % The format of the GetOneAuthenticPixel() method is:
1820 %
1821 % MagickBooleanType GetOneAuthenticPixel(const Image image,const ssize_t x,
1822 % const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
1823 %
1824 % A description of each parameter follows:
1825 %
1826 % o image: the image.
1827 %
1828 % o x,y: These values define the location of the pixel to return.
1829 %
1830 % o pixel: return a pixel at the specified (x,y) location.
1831 %
1832 % o exception: return any errors or warnings in this structure.
1833 %
1834 */
1835 
1836 static inline MagickBooleanType CopyPixel(const Image *image,
1837  const Quantum *source,Quantum *destination)
1838 {
1839  register ssize_t
1840  i;
1841 
1842  if (source == (const Quantum *) NULL)
1843  {
1844  destination[RedPixelChannel]=ClampToQuantum(image->background_color.red);
1845  destination[GreenPixelChannel]=ClampToQuantum(
1846  image->background_color.green);
1847  destination[BluePixelChannel]=ClampToQuantum(
1848  image->background_color.blue);
1849  destination[BlackPixelChannel]=ClampToQuantum(
1850  image->background_color.black);
1851  destination[AlphaPixelChannel]=ClampToQuantum(
1852  image->background_color.alpha);
1853  return(MagickFalse);
1854  }
1855  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1856  {
1857  PixelChannel channel = GetPixelChannelChannel(image,i);
1858  destination[channel]=source[i];
1859  }
1860  return(MagickTrue);
1861 }
1862 
1864  const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
1865 {
1866  CacheInfo
1867  *magick_restrict cache_info;
1868 
1869  register Quantum
1870  *magick_restrict q;
1871 
1872  assert(image != (Image *) NULL);
1873  assert(image->signature == MagickCoreSignature);
1874  assert(image->cache != (Cache) NULL);
1875  cache_info=(CacheInfo *) image->cache;
1876  assert(cache_info->signature == MagickCoreSignature);
1877  (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
1878  if (cache_info->methods.get_one_authentic_pixel_from_handler != (GetOneAuthenticPixelFromHandler) NULL)
1879  return(cache_info->methods.get_one_authentic_pixel_from_handler(image,x,y,pixel,exception));
1880  q=GetAuthenticPixelsCache(image,x,y,1UL,1UL,exception);
1881  return(CopyPixel(image,q,pixel));
1882 }
1883 
1884 /*
1885 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1886 % %
1887 % %
1888 % %
1889 + G e t O n e A u t h e n t i c P i x e l F r o m C a c h e %
1890 % %
1891 % %
1892 % %
1893 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1894 %
1895 % GetOneAuthenticPixelFromCache() returns a single pixel at the specified (x,y)
1896 % location. The image background color is returned if an error occurs.
1897 %
1898 % The format of the GetOneAuthenticPixelFromCache() method is:
1899 %
1900 % MagickBooleanType GetOneAuthenticPixelFromCache(const Image image,
1901 % const ssize_t x,const ssize_t y,Quantum *pixel,
1902 % ExceptionInfo *exception)
1903 %
1904 % A description of each parameter follows:
1905 %
1906 % o image: the image.
1907 %
1908 % o x,y: These values define the location of the pixel to return.
1909 %
1910 % o pixel: return a pixel at the specified (x,y) location.
1911 %
1912 % o exception: return any errors or warnings in this structure.
1913 %
1914 */
1916  const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
1917 {
1918  CacheInfo
1919  *magick_restrict cache_info;
1920 
1921  const int
1922  id = GetOpenMPThreadId();
1923 
1924  register Quantum
1925  *magick_restrict q;
1926 
1927  assert(image != (const Image *) NULL);
1928  assert(image->signature == MagickCoreSignature);
1929  assert(image->cache != (Cache) NULL);
1930  cache_info=(CacheInfo *) image->cache;
1931  assert(cache_info->signature == MagickCoreSignature);
1932  assert(id < (int) cache_info->number_threads);
1933  (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
1934  q=GetAuthenticPixelCacheNexus(image,x,y,1UL,1UL,cache_info->nexus_info[id],
1935  exception);
1936  return(CopyPixel(image,q,pixel));
1937 }
1938 
1939 /*
1940 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1941 % %
1942 % %
1943 % %
1944 % G e t O n e V i r t u a l P i x e l %
1945 % %
1946 % %
1947 % %
1948 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1949 %
1950 % GetOneVirtualPixel() returns a single virtual pixel at the specified
1951 % (x,y) location. The image background color is returned if an error occurs.
1952 % If you plan to modify the pixel, use GetOneAuthenticPixel() instead.
1953 %
1954 % The format of the GetOneVirtualPixel() method is:
1955 %
1956 % MagickBooleanType GetOneVirtualPixel(const Image image,const ssize_t x,
1957 % const ssize_t y,Quantum *pixel,ExceptionInfo exception)
1958 %
1959 % A description of each parameter follows:
1960 %
1961 % o image: the image.
1962 %
1963 % o x,y: These values define the location of the pixel to return.
1964 %
1965 % o pixel: return a pixel at the specified (x,y) location.
1966 %
1967 % o exception: return any errors or warnings in this structure.
1968 %
1969 */
1971  const ssize_t x,const ssize_t y,Quantum *pixel,ExceptionInfo *exception)
1972 {
1973  CacheInfo
1974  *magick_restrict cache_info;
1975 
1976  const int
1977  id = GetOpenMPThreadId();
1978 
1979  const Quantum
1980  *p;
1981 
1982  assert(image != (const Image *) NULL);
1983  assert(image->signature == MagickCoreSignature);
1984  assert(image->cache != (Cache) NULL);
1985  cache_info=(CacheInfo *) image->cache;
1986  assert(cache_info->signature == MagickCoreSignature);
1987  (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
1988  if (cache_info->methods.get_one_virtual_pixel_from_handler !=
1990  return(cache_info->methods.get_one_virtual_pixel_from_handler(image,
1991  GetPixelCacheVirtualMethod(image),x,y,pixel,exception));
1992  assert(id < (int) cache_info->number_threads);
1994  1UL,1UL,cache_info->nexus_info[id],exception);
1995  return(CopyPixel(image,p,pixel));
1996 }
1997 
1998 /*
1999 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2000 % %
2001 % %
2002 % %
2003 + G e t O n e V i r t u a l P i x e l F r o m C a c h e %
2004 % %
2005 % %
2006 % %
2007 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2008 %
2009 % GetOneVirtualPixelFromCache() returns a single virtual pixel at the
2010 % specified (x,y) location. The image background color is returned if an
2011 % error occurs.
2012 %
2013 % The format of the GetOneVirtualPixelFromCache() method is:
2014 %
2015 % MagickBooleanType GetOneVirtualPixelFromCache(const Image image,
2016 % const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
2017 % Quantum *pixel,ExceptionInfo *exception)
2018 %
2019 % A description of each parameter follows:
2020 %
2021 % o image: the image.
2022 %
2023 % o virtual_pixel_method: the virtual pixel method.
2024 %
2025 % o x,y: These values define the location of the pixel to return.
2026 %
2027 % o pixel: return a pixel at the specified (x,y) location.
2028 %
2029 % o exception: return any errors or warnings in this structure.
2030 %
2031 */
2033  const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
2034  Quantum *pixel,ExceptionInfo *exception)
2035 {
2036  CacheInfo
2037  *magick_restrict cache_info;
2038 
2039  const int
2040  id = GetOpenMPThreadId();
2041 
2042  const Quantum
2043  *p;
2044 
2045  assert(image != (const Image *) NULL);
2046  assert(image->signature == MagickCoreSignature);
2047  assert(image->cache != (Cache) NULL);
2048  cache_info=(CacheInfo *) image->cache;
2049  assert(cache_info->signature == MagickCoreSignature);
2050  assert(id < (int) cache_info->number_threads);
2051  (void) memset(pixel,0,MaxPixelChannels*sizeof(*pixel));
2052  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2053  cache_info->nexus_info[id],exception);
2054  return(CopyPixel(image,p,pixel));
2055 }
2056 
2057 /*
2058 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2059 % %
2060 % %
2061 % %
2062 % G e t O n e V i r t u a l P i x e l I n f o %
2063 % %
2064 % %
2065 % %
2066 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2067 %
2068 % GetOneVirtualPixelInfo() returns a single pixel at the specified (x,y)
2069 % location. The image background color is returned if an error occurs. If
2070 % you plan to modify the pixel, use GetOneAuthenticPixel() instead.
2071 %
2072 % The format of the GetOneVirtualPixelInfo() method is:
2073 %
2074 % MagickBooleanType GetOneVirtualPixelInfo(const Image image,
2075 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
2076 % const ssize_t y,PixelInfo *pixel,ExceptionInfo exception)
2077 %
2078 % A description of each parameter follows:
2079 %
2080 % o image: the image.
2081 %
2082 % o virtual_pixel_method: the virtual pixel method.
2083 %
2084 % o x,y: these values define the location of the pixel to return.
2085 %
2086 % o pixel: return a pixel at the specified (x,y) location.
2087 %
2088 % o exception: return any errors or warnings in this structure.
2089 %
2090 */
2092  const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
2093  PixelInfo *pixel,ExceptionInfo *exception)
2094 {
2095  CacheInfo
2096  *magick_restrict cache_info;
2097 
2098  const int
2099  id = GetOpenMPThreadId();
2100 
2101  register const Quantum
2102  *magick_restrict p;
2103 
2104  assert(image != (const Image *) NULL);
2105  assert(image->signature == MagickCoreSignature);
2106  assert(image->cache != (Cache) NULL);
2107  cache_info=(CacheInfo *) image->cache;
2108  assert(cache_info->signature == MagickCoreSignature);
2109  assert(id < (int) cache_info->number_threads);
2110  GetPixelInfo(image,pixel);
2111  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,1UL,1UL,
2112  cache_info->nexus_info[id],exception);
2113  if (p == (const Quantum *) NULL)
2114  return(MagickFalse);
2115  GetPixelInfoPixel(image,p,pixel);
2116  return(MagickTrue);
2117 }
2118 
2119 /*
2120 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2121 % %
2122 % %
2123 % %
2124 + G e t P i x e l C a c h e C o l o r s p a c e %
2125 % %
2126 % %
2127 % %
2128 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2129 %
2130 % GetPixelCacheColorspace() returns the class type of the pixel cache.
2131 %
2132 % The format of the GetPixelCacheColorspace() method is:
2133 %
2134 % Colorspace GetPixelCacheColorspace(Cache cache)
2135 %
2136 % A description of each parameter follows:
2137 %
2138 % o cache: the pixel cache.
2139 %
2140 */
2142 {
2143  CacheInfo
2144  *magick_restrict cache_info;
2145 
2146  assert(cache != (Cache) NULL);
2147  cache_info=(CacheInfo *) cache;
2148  assert(cache_info->signature == MagickCoreSignature);
2149  if (cache_info->debug != MagickFalse)
2151  cache_info->filename);
2152  return(cache_info->colorspace);
2153 }
2154 
2155 /*
2156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2157 % %
2158 % %
2159 % %
2160 + G e t P i x e l C a c h e F i l e n a m e %
2161 % %
2162 % %
2163 % %
2164 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2165 %
2166 % GetPixelCacheFilename() returns the filename associated with the pixel
2167 % cache.
2168 %
2169 % The format of the GetPixelCacheFilename() method is:
2170 %
2171 % const char *GetPixelCacheFilename(const Image *image)
2172 %
2173 % A description of each parameter follows:
2174 %
2175 % o image: the image.
2176 %
2177 */
2178 MagickExport const char *GetPixelCacheFilename(const Image *image)
2179 {
2180  CacheInfo
2181  *magick_restrict cache_info;
2182 
2183  assert(image != (const Image *) NULL);
2184  assert(image->signature == MagickCoreSignature);
2185  assert(image->cache != (Cache) NULL);
2186  cache_info=(CacheInfo *) image->cache;
2187  assert(cache_info->signature == MagickCoreSignature);
2188  return(cache_info->cache_filename);
2189 }
2190 
2191 /*
2192 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2193 % %
2194 % %
2195 % %
2196 + G e t P i x e l C a c h e M e t h o d s %
2197 % %
2198 % %
2199 % %
2200 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2201 %
2202 % GetPixelCacheMethods() initializes the CacheMethods structure.
2203 %
2204 % The format of the GetPixelCacheMethods() method is:
2205 %
2206 % void GetPixelCacheMethods(CacheMethods *cache_methods)
2207 %
2208 % A description of each parameter follows:
2209 %
2210 % o cache_methods: Specifies a pointer to a CacheMethods structure.
2211 %
2212 */
2214 {
2215  assert(cache_methods != (CacheMethods *) NULL);
2216  (void) memset(cache_methods,0,sizeof(*cache_methods));
2219  cache_methods->get_virtual_metacontent_from_handler=
2226  cache_methods->get_one_authentic_pixel_from_handler=
2231 }
2232 
2233 /*
2234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2235 % %
2236 % %
2237 % %
2238 + G e t P i x e l C a c h e N e x u s E x t e n t %
2239 % %
2240 % %
2241 % %
2242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2243 %
2244 % GetPixelCacheNexusExtent() returns the extent of the pixels associated
2245 % corresponding with the last call to SetPixelCacheNexusPixels() or
2246 % GetPixelCacheNexusPixels().
2247 %
2248 % The format of the GetPixelCacheNexusExtent() method is:
2249 %
2250 % MagickSizeType GetPixelCacheNexusExtent(const Cache cache,
2251 % NexusInfo *nexus_info)
2252 %
2253 % A description of each parameter follows:
2254 %
2255 % o nexus_info: the nexus info.
2256 %
2257 */
2259  NexusInfo *magick_restrict nexus_info)
2260 {
2261  CacheInfo
2262  *magick_restrict cache_info;
2263 
2265  extent;
2266 
2267  assert(cache != NULL);
2268  cache_info=(CacheInfo *) cache;
2269  assert(cache_info->signature == MagickCoreSignature);
2270  extent=(MagickSizeType) nexus_info->region.width*nexus_info->region.height;
2271  if (extent == 0)
2272  return((MagickSizeType) cache_info->columns*cache_info->rows);
2273  return(extent);
2274 }
2275 
2276 /*
2277 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2278 % %
2279 % %
2280 % %
2281 + G e t P i x e l C a c h e P i x e l s %
2282 % %
2283 % %
2284 % %
2285 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2286 %
2287 % GetPixelCachePixels() returns the pixels associated with the specified image.
2288 %
2289 % The format of the GetPixelCachePixels() method is:
2290 %
2291 % void *GetPixelCachePixels(Image *image,MagickSizeType *length,
2292 % ExceptionInfo *exception)
2293 %
2294 % A description of each parameter follows:
2295 %
2296 % o image: the image.
2297 %
2298 % o length: the pixel cache length.
2299 %
2300 % o exception: return any errors or warnings in this structure.
2301 %
2302 */
2304  ExceptionInfo *exception)
2305 {
2306  CacheInfo
2307  *magick_restrict cache_info;
2308 
2309  assert(image != (const Image *) NULL);
2310  assert(image->signature == MagickCoreSignature);
2311  assert(image->cache != (Cache) NULL);
2312  assert(length != (MagickSizeType *) NULL);
2313  assert(exception != (ExceptionInfo *) NULL);
2314  assert(exception->signature == MagickCoreSignature);
2315  cache_info=(CacheInfo *) image->cache;
2316  assert(cache_info->signature == MagickCoreSignature);
2317  *length=cache_info->length;
2318  if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
2319  return((void *) NULL);
2320  return((void *) cache_info->pixels);
2321 }
2322 
2323 /*
2324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2325 % %
2326 % %
2327 % %
2328 + G e t P i x e l C a c h e S t o r a g e C l a s s %
2329 % %
2330 % %
2331 % %
2332 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2333 %
2334 % GetPixelCacheStorageClass() returns the class type of the pixel cache.
2335 %
2336 % The format of the GetPixelCacheStorageClass() method is:
2337 %
2338 % ClassType GetPixelCacheStorageClass(Cache cache)
2339 %
2340 % A description of each parameter follows:
2341 %
2342 % o type: GetPixelCacheStorageClass returns DirectClass or PseudoClass.
2343 %
2344 % o cache: the pixel cache.
2345 %
2346 */
2348 {
2349  CacheInfo
2350  *magick_restrict cache_info;
2351 
2352  assert(cache != (Cache) NULL);
2353  cache_info=(CacheInfo *) cache;
2354  assert(cache_info->signature == MagickCoreSignature);
2355  if (cache_info->debug != MagickFalse)
2357  cache_info->filename);
2358  return(cache_info->storage_class);
2359 }
2360 
2361 /*
2362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2363 % %
2364 % %
2365 % %
2366 + G e t P i x e l C a c h e T i l e S i z e %
2367 % %
2368 % %
2369 % %
2370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2371 %
2372 % GetPixelCacheTileSize() returns the pixel cache tile size.
2373 %
2374 % The format of the GetPixelCacheTileSize() method is:
2375 %
2376 % void GetPixelCacheTileSize(const Image *image,size_t *width,
2377 % size_t *height)
2378 %
2379 % A description of each parameter follows:
2380 %
2381 % o image: the image.
2382 %
2383 % o width: the optimized cache tile width in pixels.
2384 %
2385 % o height: the optimized cache tile height in pixels.
2386 %
2387 */
2388 MagickPrivate void GetPixelCacheTileSize(const Image *image,size_t *width,
2389  size_t *height)
2390 {
2391  CacheInfo
2392  *magick_restrict cache_info;
2393 
2394  assert(image != (Image *) NULL);
2395  assert(image->signature == MagickCoreSignature);
2396  if (image->debug != MagickFalse)
2397  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2398  cache_info=(CacheInfo *) image->cache;
2399  assert(cache_info->signature == MagickCoreSignature);
2400  *width=2048UL/(cache_info->number_channels*sizeof(Quantum));
2401  if (GetImagePixelCacheType(image) == DiskCache)
2402  *width=8192UL/(cache_info->number_channels*sizeof(Quantum));
2403  *height=(*width);
2404 }
2405 
2406 /*
2407 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2408 % %
2409 % %
2410 % %
2411 + G e t P i x e l C a c h e V i r t u a l M e t h o d %
2412 % %
2413 % %
2414 % %
2415 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2416 %
2417 % GetPixelCacheVirtualMethod() gets the "virtual pixels" method for the
2418 % pixel cache. A virtual pixel is any pixel access that is outside the
2419 % boundaries of the image cache.
2420 %
2421 % The format of the GetPixelCacheVirtualMethod() method is:
2422 %
2423 % VirtualPixelMethod GetPixelCacheVirtualMethod(const Image *image)
2424 %
2425 % A description of each parameter follows:
2426 %
2427 % o image: the image.
2428 %
2429 */
2431 {
2432  CacheInfo
2433  *magick_restrict cache_info;
2434 
2435  assert(image != (Image *) NULL);
2436  assert(image->signature == MagickCoreSignature);
2437  assert(image->cache != (Cache) NULL);
2438  cache_info=(CacheInfo *) image->cache;
2439  assert(cache_info->signature == MagickCoreSignature);
2440  return(cache_info->virtual_pixel_method);
2441 }
2442 
2443 /*
2444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2445 % %
2446 % %
2447 % %
2448 + G e t V i r t u a l M e t a c o n t e n t F r o m C a c h e %
2449 % %
2450 % %
2451 % %
2452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2453 %
2454 % GetVirtualMetacontentFromCache() returns the meta-content corresponding with
2455 % the last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
2456 %
2457 % The format of the GetVirtualMetacontentFromCache() method is:
2458 %
2459 % void *GetVirtualMetacontentFromCache(const Image *image)
2460 %
2461 % A description of each parameter follows:
2462 %
2463 % o image: the image.
2464 %
2465 */
2466 static const void *GetVirtualMetacontentFromCache(const Image *image)
2467 {
2468  CacheInfo
2469  *magick_restrict cache_info;
2470 
2471  const int
2472  id = GetOpenMPThreadId();
2473 
2474  const void
2475  *magick_restrict metacontent;
2476 
2477  assert(image != (const Image *) NULL);
2478  assert(image->signature == MagickCoreSignature);
2479  assert(image->cache != (Cache) NULL);
2480  cache_info=(CacheInfo *) image->cache;
2481  assert(cache_info->signature == MagickCoreSignature);
2482  assert(id < (int) cache_info->number_threads);
2483  metacontent=GetVirtualMetacontentFromNexus(cache_info,
2484  cache_info->nexus_info[id]);
2485  return(metacontent);
2486 }
2487 
2488 /*
2489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2490 % %
2491 % %
2492 % %
2493 + G e t V i r t u a l M e t a c o n t e n t F r o m N e x u s %
2494 % %
2495 % %
2496 % %
2497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2498 %
2499 % GetVirtualMetacontentFromNexus() returns the meta-content for the specified
2500 % cache nexus.
2501 %
2502 % The format of the GetVirtualMetacontentFromNexus() method is:
2503 %
2504 % const void *GetVirtualMetacontentFromNexus(const Cache cache,
2505 % NexusInfo *nexus_info)
2506 %
2507 % A description of each parameter follows:
2508 %
2509 % o cache: the pixel cache.
2510 %
2511 % o nexus_info: the cache nexus to return the meta-content.
2512 %
2513 */
2515  NexusInfo *magick_restrict nexus_info)
2516 {
2517  CacheInfo
2518  *magick_restrict cache_info;
2519 
2520  assert(cache != (Cache) NULL);
2521  cache_info=(CacheInfo *) cache;
2522  assert(cache_info->signature == MagickCoreSignature);
2523  if (cache_info->storage_class == UndefinedClass)
2524  return((void *) NULL);
2525  return(nexus_info->metacontent);
2526 }
2527 
2528 /*
2529 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2530 % %
2531 % %
2532 % %
2533 % G e t V i r t u a l M e t a c o n t e n t %
2534 % %
2535 % %
2536 % %
2537 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2538 %
2539 % GetVirtualMetacontent() returns the virtual metacontent corresponding with
2540 % the last call to QueueAuthenticPixels() or GetVirtualPixels(). NULL is
2541 % returned if the meta-content are not available.
2542 %
2543 % The format of the GetVirtualMetacontent() method is:
2544 %
2545 % const void *GetVirtualMetacontent(const Image *image)
2546 %
2547 % A description of each parameter follows:
2548 %
2549 % o image: the image.
2550 %
2551 */
2552 MagickExport const void *GetVirtualMetacontent(const Image *image)
2553 {
2554  CacheInfo
2555  *magick_restrict cache_info;
2556 
2557  const int
2558  id = GetOpenMPThreadId();
2559 
2560  const void
2561  *magick_restrict metacontent;
2562 
2563  assert(image != (const Image *) NULL);
2564  assert(image->signature == MagickCoreSignature);
2565  assert(image->cache != (Cache) NULL);
2566  cache_info=(CacheInfo *) image->cache;
2567  assert(cache_info->signature == MagickCoreSignature);
2568  metacontent=cache_info->methods.get_virtual_metacontent_from_handler(image);
2569  if (metacontent != (void *) NULL)
2570  return(metacontent);
2571  assert(id < (int) cache_info->number_threads);
2572  metacontent=GetVirtualMetacontentFromNexus(cache_info,
2573  cache_info->nexus_info[id]);
2574  return(metacontent);
2575 }
2576 
2577 /*
2578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2579 % %
2580 % %
2581 % %
2582 + G e t V i r t u a l P i x e l C a c h e N e x u s %
2583 % %
2584 % %
2585 % %
2586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2587 %
2588 % GetVirtualPixelCacheNexus() gets virtual pixels from the in-memory or disk
2589 % pixel cache as defined by the geometry parameters. A pointer to the pixels
2590 % is returned if the pixels are transferred, otherwise a NULL is returned.
2591 %
2592 % The format of the GetVirtualPixelCacheNexus() method is:
2593 %
2594 % Quantum *GetVirtualPixelCacheNexus(const Image *image,
2595 % const VirtualPixelMethod method,const ssize_t x,const ssize_t y,
2596 % const size_t columns,const size_t rows,NexusInfo *nexus_info,
2597 % ExceptionInfo *exception)
2598 %
2599 % A description of each parameter follows:
2600 %
2601 % o image: the image.
2602 %
2603 % o virtual_pixel_method: the virtual pixel method.
2604 %
2605 % o x,y,columns,rows: These values define the perimeter of a region of
2606 % pixels.
2607 %
2608 % o nexus_info: the cache nexus to acquire.
2609 %
2610 % o exception: return any errors or warnings in this structure.
2611 %
2612 */
2613 
2614 static ssize_t
2616  {
2617  0, 48, 12, 60, 3, 51, 15, 63,
2618  32, 16, 44, 28, 35, 19, 47, 31,
2619  8, 56, 4, 52, 11, 59, 7, 55,
2620  40, 24, 36, 20, 43, 27, 39, 23,
2621  2, 50, 14, 62, 1, 49, 13, 61,
2622  34, 18, 46, 30, 33, 17, 45, 29,
2623  10, 58, 6, 54, 9, 57, 5, 53,
2624  42, 26, 38, 22, 41, 25, 37, 21
2625  };
2626 
2627 static inline ssize_t DitherX(const ssize_t x,const size_t columns)
2628 {
2629  ssize_t
2630  index;
2631 
2632  index=x+DitherMatrix[x & 0x07]-32L;
2633  if (index < 0L)
2634  return(0L);
2635  if (index >= (ssize_t) columns)
2636  return((ssize_t) columns-1L);
2637  return(index);
2638 }
2639 
2640 static inline ssize_t DitherY(const ssize_t y,const size_t rows)
2641 {
2642  ssize_t
2643  index;
2644 
2645  index=y+DitherMatrix[y & 0x07]-32L;
2646  if (index < 0L)
2647  return(0L);
2648  if (index >= (ssize_t) rows)
2649  return((ssize_t) rows-1L);
2650  return(index);
2651 }
2652 
2653 static inline ssize_t EdgeX(const ssize_t x,const size_t columns)
2654 {
2655  if (x < 0L)
2656  return(0L);
2657  if (x >= (ssize_t) columns)
2658  return((ssize_t) (columns-1));
2659  return(x);
2660 }
2661 
2662 static inline ssize_t EdgeY(const ssize_t y,const size_t rows)
2663 {
2664  if (y < 0L)
2665  return(0L);
2666  if (y >= (ssize_t) rows)
2667  return((ssize_t) (rows-1));
2668  return(y);
2669 }
2670 
2671 static inline ssize_t RandomX(RandomInfo *random_info,const size_t columns)
2672 {
2673  return((ssize_t) (columns*GetPseudoRandomValue(random_info)));
2674 }
2675 
2676 static inline ssize_t RandomY(RandomInfo *random_info,const size_t rows)
2677 {
2678  return((ssize_t) (rows*GetPseudoRandomValue(random_info)));
2679 }
2680 
2681 static inline MagickModulo VirtualPixelModulo(const ssize_t offset,
2682  const size_t extent)
2683 {
2684  MagickModulo
2685  modulo;
2686 
2687  /*
2688  Compute the remainder of dividing offset by extent. It returns not only
2689  the quotient (tile the offset falls in) but also the positive remainer
2690  within that tile such that 0 <= remainder < extent. This method is
2691  essentially a ldiv() using a floored modulo division rather than the
2692  normal default truncated modulo division.
2693  */
2694  modulo.quotient=offset/(ssize_t) extent;
2695  if ((offset < 0L) && (modulo.quotient > (ssize_t) (-SSIZE_MAX)))
2696  modulo.quotient--;
2697  modulo.remainder=(ssize_t) (offset-(double) modulo.quotient*extent);
2698  return(modulo);
2699 }
2700 
2702  const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
2703  const size_t columns,const size_t rows,NexusInfo *nexus_info,
2704  ExceptionInfo *exception)
2705 {
2706  CacheInfo
2707  *magick_restrict cache_info;
2708 
2710  offset;
2711 
2713  length,
2714  number_pixels;
2715 
2716  NexusInfo
2717  **magick_restrict virtual_nexus;
2718 
2719  Quantum
2720  *magick_restrict pixels,
2721  virtual_pixel[MaxPixelChannels];
2722 
2723  register const Quantum
2724  *magick_restrict p;
2725 
2726  register const void
2727  *magick_restrict r;
2728 
2729  register Quantum
2730  *magick_restrict q;
2731 
2732  register ssize_t
2733  i,
2734  u;
2735 
2736  register unsigned char
2737  *magick_restrict s;
2738 
2739  ssize_t
2740  v;
2741 
2742  void
2743  *magick_restrict virtual_metacontent;
2744 
2745  /*
2746  Acquire pixels.
2747  */
2748  assert(image != (const Image *) NULL);
2749  assert(image->signature == MagickCoreSignature);
2750  assert(image->cache != (Cache) NULL);
2751  cache_info=(CacheInfo *) image->cache;
2752  assert(cache_info->signature == MagickCoreSignature);
2753  if (cache_info->type == UndefinedCache)
2754  return((const Quantum *) NULL);
2755 #if defined(MAGICKCORE_OPENCL_SUPPORT)
2756  CopyOpenCLBuffer(cache_info);
2757 #endif
2758  pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,x,y,columns,rows,
2759  ((image->channels & WriteMaskChannel) != 0) ||
2760  ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
2761  nexus_info,exception);
2762  if (pixels == (Quantum *) NULL)
2763  return((const Quantum *) NULL);
2764  q=pixels;
2765  offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
2766  nexus_info->region.x;
2767  length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
2768  nexus_info->region.width-1L;
2769  number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
2770  if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
2771  if ((x >= 0) && ((ssize_t) (x+columns) <= (ssize_t) cache_info->columns) &&
2772  (y >= 0) && ((ssize_t) (y+rows) <= (ssize_t) cache_info->rows))
2773  {
2775  status;
2776 
2777  /*
2778  Pixel request is inside cache extents.
2779  */
2780  if (nexus_info->authentic_pixel_cache != MagickFalse)
2781  return(q);
2782  status=ReadPixelCachePixels(cache_info,nexus_info,exception);
2783  if (status == MagickFalse)
2784  return((const Quantum *) NULL);
2785  if (cache_info->metacontent_extent != 0)
2786  {
2787  status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
2788  if (status == MagickFalse)
2789  return((const Quantum *) NULL);
2790  }
2791  return(q);
2792  }
2793  /*
2794  Pixel request is outside cache extents.
2795  */
2796  s=(unsigned char *) nexus_info->metacontent;
2797  virtual_nexus=AcquirePixelCacheNexus(1);
2798  (void) memset(virtual_pixel,0,cache_info->number_channels*
2799  sizeof(*virtual_pixel));
2800  virtual_metacontent=(void *) NULL;
2801  switch (virtual_pixel_method)
2802  {
2813  {
2814  if (cache_info->metacontent_extent != 0)
2815  {
2816  /*
2817  Acquire a metacontent buffer.
2818  */
2819  virtual_metacontent=(void *) AcquireQuantumMemory(1,
2820  cache_info->metacontent_extent);
2821  if (virtual_metacontent == (void *) NULL)
2822  {
2823  virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
2824  (void) ThrowMagickException(exception,GetMagickModule(),
2825  CacheError,"UnableToGetCacheNexus","`%s'",image->filename);
2826  return((const Quantum *) NULL);
2827  }
2828  (void) memset(virtual_metacontent,0,cache_info->metacontent_extent);
2829  }
2830  switch (virtual_pixel_method)
2831  {
2833  {
2834  for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2835  SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2836  SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2837  break;
2838  }
2840  {
2841  for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2843  virtual_pixel);
2844  SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2845  break;
2846  }
2848  {
2849  for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2850  SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2851  SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
2852  break;
2853  }
2856  {
2857  for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2858  SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
2859  SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2860  break;
2861  }
2862  default:
2863  {
2865  virtual_pixel);
2867  virtual_pixel);
2869  virtual_pixel);
2871  virtual_pixel);
2873  virtual_pixel);
2874  break;
2875  }
2876  }
2877  break;
2878  }
2879  default:
2880  break;
2881  }
2882  for (v=0; v < (ssize_t) rows; v++)
2883  {
2884  ssize_t
2885  y_offset;
2886 
2887  y_offset=y+v;
2888  if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
2889  (virtual_pixel_method == UndefinedVirtualPixelMethod))
2890  y_offset=EdgeY(y_offset,cache_info->rows);
2891  for (u=0; u < (ssize_t) columns; u+=length)
2892  {
2893  ssize_t
2894  x_offset;
2895 
2896  x_offset=x+u;
2897  length=(MagickSizeType) MagickMin(cache_info->columns-x_offset,columns-u);
2898  if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
2899  ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
2900  (length == 0))
2901  {
2902  MagickModulo
2903  x_modulo,
2904  y_modulo;
2905 
2906  /*
2907  Transfer a single pixel.
2908  */
2909  length=(MagickSizeType) 1;
2910  switch (virtual_pixel_method)
2911  {
2913  default:
2914  {
2915  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2916  EdgeX(x_offset,cache_info->columns),
2917  EdgeY(y_offset,cache_info->rows),1UL,1UL,*virtual_nexus,
2918  exception);
2919  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2920  break;
2921  }
2923  {
2924  if (cache_info->random_info == (RandomInfo *) NULL)
2925  cache_info->random_info=AcquireRandomInfo();
2926  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2927  RandomX(cache_info->random_info,cache_info->columns),
2928  RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
2929  *virtual_nexus,exception);
2930  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2931  break;
2932  }
2934  {
2935  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2936  DitherX(x_offset,cache_info->columns),
2937  DitherY(y_offset,cache_info->rows),1UL,1UL,*virtual_nexus,
2938  exception);
2939  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2940  break;
2941  }
2943  {
2944  x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
2945  y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
2946  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2947  x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
2948  exception);
2949  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2950  break;
2951  }
2953  {
2954  x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
2955  if ((x_modulo.quotient & 0x01) == 1L)
2956  x_modulo.remainder=(ssize_t) cache_info->columns-
2957  x_modulo.remainder-1L;
2958  y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
2959  if ((y_modulo.quotient & 0x01) == 1L)
2960  y_modulo.remainder=(ssize_t) cache_info->rows-
2961  y_modulo.remainder-1L;
2962  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2963  x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
2964  exception);
2965  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2966  break;
2967  }
2969  {
2970  x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
2971  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2972  x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
2973  *virtual_nexus,exception);
2974  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2975  break;
2976  }
2978  {
2979  y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
2980  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2981  EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
2982  *virtual_nexus,exception);
2983  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2984  break;
2985  }
2992  {
2993  p=virtual_pixel;
2994  r=virtual_metacontent;
2995  break;
2996  }
2998  {
2999  x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3000  y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3001  if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3002  {
3003  p=virtual_pixel;
3004  r=virtual_metacontent;
3005  break;
3006  }
3007  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3008  x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3009  exception);
3010  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3011  break;
3012  }
3014  {
3015  if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3016  {
3017  p=virtual_pixel;
3018  r=virtual_metacontent;
3019  break;
3020  }
3021  x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3022  y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3023  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3024  x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3025  exception);
3026  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3027  break;
3028  }
3030  {
3031  if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3032  {
3033  p=virtual_pixel;
3034  r=virtual_metacontent;
3035  break;
3036  }
3037  x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3038  y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3039  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3040  x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3041  exception);
3042  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3043  break;
3044  }
3045  }
3046  if (p == (const Quantum *) NULL)
3047  break;
3048  (void) memcpy(q,p,(size_t) (cache_info->number_channels*length*
3049  sizeof(*p)));
3050  q+=cache_info->number_channels;
3051  if ((s != (void *) NULL) && (r != (const void *) NULL))
3052  {
3053  (void) memcpy(s,r,(size_t) cache_info->metacontent_extent);
3054  s+=cache_info->metacontent_extent;
3055  }
3056  continue;
3057  }
3058  /*
3059  Transfer a run of pixels.
3060  */
3061  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3062  (size_t) length,1UL,*virtual_nexus,exception);
3063  if (p == (const Quantum *) NULL)
3064  break;
3065  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3066  (void) memcpy(q,p,(size_t) (cache_info->number_channels*length*
3067  sizeof(*p)));
3068  q+=cache_info->number_channels*length;
3069  if ((r != (void *) NULL) && (s != (const void *) NULL))
3070  {
3071  (void) memcpy(s,r,(size_t) length);
3072  s+=length*cache_info->metacontent_extent;
3073  }
3074  }
3075  if (u < (ssize_t) columns)
3076  break;
3077  }
3078  /*
3079  Free resources.
3080  */
3081  if (virtual_metacontent != (void *) NULL)
3082  virtual_metacontent=(void *) RelinquishMagickMemory(virtual_metacontent);
3083  virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
3084  if (v < (ssize_t) rows)
3085  return((const Quantum *) NULL);
3086  return(pixels);
3087 }
3088 
3089 /*
3090 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3091 % %
3092 % %
3093 % %
3094 + G e t V i r t u a l P i x e l C a c h e %
3095 % %
3096 % %
3097 % %
3098 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3099 %
3100 % GetVirtualPixelCache() get virtual pixels from the in-memory or disk pixel
3101 % cache as defined by the geometry parameters. A pointer to the pixels
3102 % is returned if the pixels are transferred, otherwise a NULL is returned.
3103 %
3104 % The format of the GetVirtualPixelCache() method is:
3105 %
3106 % const Quantum *GetVirtualPixelCache(const Image *image,
3107 % const VirtualPixelMethod virtual_pixel_method,const ssize_t x,
3108 % const ssize_t y,const size_t columns,const size_t rows,
3109 % ExceptionInfo *exception)
3110 %
3111 % A description of each parameter follows:
3112 %
3113 % o image: the image.
3114 %
3115 % o virtual_pixel_method: the virtual pixel method.
3116 %
3117 % o x,y,columns,rows: These values define the perimeter of a region of
3118 % pixels.
3119 %
3120 % o exception: return any errors or warnings in this structure.
3121 %
3122 */
3123 static const Quantum *GetVirtualPixelCache(const Image *image,
3124  const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
3125  const size_t columns,const size_t rows,ExceptionInfo *exception)
3126 {
3127  CacheInfo
3128  *magick_restrict cache_info;
3129 
3130  const int
3131  id = GetOpenMPThreadId();
3132 
3133  const Quantum
3134  *magick_restrict p;
3135 
3136  assert(image != (const Image *) NULL);
3137  assert(image->signature == MagickCoreSignature);
3138  assert(image->cache != (Cache) NULL);
3139  cache_info=(CacheInfo *) image->cache;
3140  assert(cache_info->signature == MagickCoreSignature);
3141  assert(id < (int) cache_info->number_threads);
3142  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x,y,columns,rows,
3143  cache_info->nexus_info[id],exception);
3144  return(p);
3145 }
3146 
3147 /*
3148 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3149 % %
3150 % %
3151 % %
3152 % G e t V i r t u a l P i x e l Q u e u e %
3153 % %
3154 % %
3155 % %
3156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3157 %
3158 % GetVirtualPixelQueue() returns the virtual pixels associated corresponding
3159 % with the last call to QueueAuthenticPixels() or GetVirtualPixels().
3160 %
3161 % The format of the GetVirtualPixelQueue() method is:
3162 %
3163 % const Quantum *GetVirtualPixelQueue(const Image image)
3164 %
3165 % A description of each parameter follows:
3166 %
3167 % o image: the image.
3168 %
3169 */
3171 {
3172  CacheInfo
3173  *magick_restrict cache_info;
3174 
3175  const int
3176  id = GetOpenMPThreadId();
3177 
3178  assert(image != (const Image *) NULL);
3179  assert(image->signature == MagickCoreSignature);
3180  assert(image->cache != (Cache) NULL);
3181  cache_info=(CacheInfo *) image->cache;
3182  assert(cache_info->signature == MagickCoreSignature);
3183  if (cache_info->methods.get_virtual_pixels_handler !=
3184  (GetVirtualPixelsHandler) NULL)
3185  return(cache_info->methods.get_virtual_pixels_handler(image));
3186  assert(id < (int) cache_info->number_threads);
3187  return(GetVirtualPixelsNexus(cache_info,cache_info->nexus_info[id]));
3188 }
3189 
3190 /*
3191 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3192 % %
3193 % %
3194 % %
3195 % G e t V i r t u a l P i x e l s %
3196 % %
3197 % %
3198 % %
3199 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3200 %
3201 % GetVirtualPixels() returns an immutable pixel region. If the
3202 % region is successfully accessed, a pointer to it is returned, otherwise
3203 % NULL is returned. The returned pointer may point to a temporary working
3204 % copy of the pixels or it may point to the original pixels in memory.
3205 % Performance is maximized if the selected region is part of one row, or one
3206 % or more full rows, since there is opportunity to access the pixels in-place
3207 % (without a copy) if the image is in memory, or in a memory-mapped file. The
3208 % returned pointer must *never* be deallocated by the user.
3209 %
3210 % Pixels accessed via the returned pointer represent a simple array of type
3211 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
3212 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
3213 % access the meta-content (of type void) corresponding to the the
3214 % region.
3215 %
3216 % If you plan to modify the pixels, use GetAuthenticPixels() instead.
3217 %
3218 % Note, the GetVirtualPixels() and GetAuthenticPixels() methods are not thread-
3219 % safe. In a threaded environment, use GetCacheViewVirtualPixels() or
3220 % GetCacheViewAuthenticPixels() instead.
3221 %
3222 % The format of the GetVirtualPixels() method is:
3223 %
3224 % const Quantum *GetVirtualPixels(const Image *image,const ssize_t x,
3225 % const ssize_t y,const size_t columns,const size_t rows,
3226 % ExceptionInfo *exception)
3227 %
3228 % A description of each parameter follows:
3229 %
3230 % o image: the image.
3231 %
3232 % o x,y,columns,rows: These values define the perimeter of a region of
3233 % pixels.
3234 %
3235 % o exception: return any errors or warnings in this structure.
3236 %
3237 */
3239  const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
3240  ExceptionInfo *exception)
3241 {
3242  CacheInfo
3243  *magick_restrict cache_info;
3244 
3245  const int
3246  id = GetOpenMPThreadId();
3247 
3248  const Quantum
3249  *magick_restrict p;
3250 
3251  assert(image != (const Image *) NULL);
3252  assert(image->signature == MagickCoreSignature);
3253  assert(image->cache != (Cache) NULL);
3254  cache_info=(CacheInfo *) image->cache;
3255  assert(cache_info->signature == MagickCoreSignature);
3256  if (cache_info->methods.get_virtual_pixel_handler !=
3257  (GetVirtualPixelHandler) NULL)
3258  return(cache_info->methods.get_virtual_pixel_handler(image,
3259  GetPixelCacheVirtualMethod(image),x,y,columns,rows,exception));
3260  assert(id < (int) cache_info->number_threads);
3262  columns,rows,cache_info->nexus_info[id],exception);
3263  return(p);
3264 }
3265 
3266 /*
3267 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3268 % %
3269 % %
3270 % %
3271 + G e t V i r t u a l P i x e l s F r o m C a c h e %
3272 % %
3273 % %
3274 % %
3275 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3276 %
3277 % GetVirtualPixelsCache() returns the pixels associated corresponding with the
3278 % last call to QueueAuthenticPixelsCache() or GetVirtualPixelCache().
3279 %
3280 % The format of the GetVirtualPixelsCache() method is:
3281 %
3282 % Quantum *GetVirtualPixelsCache(const Image *image)
3283 %
3284 % A description of each parameter follows:
3285 %
3286 % o image: the image.
3287 %
3288 */
3289 static const Quantum *GetVirtualPixelsCache(const Image *image)
3290 {
3291  CacheInfo
3292  *magick_restrict cache_info;
3293 
3294  const int
3295  id = GetOpenMPThreadId();
3296 
3297  assert(image != (const Image *) NULL);
3298  assert(image->signature == MagickCoreSignature);
3299  assert(image->cache != (Cache) NULL);
3300  cache_info=(CacheInfo *) image->cache;
3301  assert(cache_info->signature == MagickCoreSignature);
3302  assert(id < (int) cache_info->number_threads);
3303  return(GetVirtualPixelsNexus(image->cache,cache_info->nexus_info[id]));
3304 }
3305 
3306 /*
3307 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3308 % %
3309 % %
3310 % %
3311 + G e t V i r t u a l P i x e l s N e x u s %
3312 % %
3313 % %
3314 % %
3315 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3316 %
3317 % GetVirtualPixelsNexus() returns the pixels associated with the specified
3318 % cache nexus.
3319 %
3320 % The format of the GetVirtualPixelsNexus() method is:
3321 %
3322 % const Quantum *GetVirtualPixelsNexus(const Cache cache,
3323 % NexusInfo *nexus_info)
3324 %
3325 % A description of each parameter follows:
3326 %
3327 % o cache: the pixel cache.
3328 %
3329 % o nexus_info: the cache nexus to return the colormap pixels.
3330 %
3331 */
3333  NexusInfo *magick_restrict nexus_info)
3334 {
3335  CacheInfo
3336  *magick_restrict cache_info;
3337 
3338  assert(cache != (Cache) NULL);
3339  cache_info=(CacheInfo *) cache;
3340  assert(cache_info->signature == MagickCoreSignature);
3341  if (cache_info->storage_class == UndefinedClass)
3342  return((Quantum *) NULL);
3343  return((const Quantum *) nexus_info->pixels);
3344 }
3345 
3346 /*
3347 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3348 % %
3349 % %
3350 % %
3351 + M a s k P i x e l C a c h e N e x u s %
3352 % %
3353 % %
3354 % %
3355 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3356 %
3357 % MaskPixelCacheNexus() masks the cache nexus as defined by the image mask.
3358 % The method returns MagickTrue if the pixel region is masked, otherwise
3359 % MagickFalse.
3360 %
3361 % The format of the MaskPixelCacheNexus() method is:
3362 %
3363 % MagickBooleanType MaskPixelCacheNexus(Image *image,
3364 % NexusInfo *nexus_info,ExceptionInfo *exception)
3365 %
3366 % A description of each parameter follows:
3367 %
3368 % o image: the image.
3369 %
3370 % o nexus_info: the cache nexus to clip.
3371 %
3372 % o exception: return any errors or warnings in this structure.
3373 %
3374 */
3375 
3377  const MagickRealType alpha,const Quantum q,const MagickRealType beta)
3378 {
3379  double
3380  mask_alpha;
3381 
3382  if (fabs(alpha-OpaqueAlpha) < MagickEpsilon)
3383  return(p);
3384  mask_alpha=1.0-QuantumScale*QuantumScale*alpha*beta;
3385  mask_alpha=PerceptibleReciprocal(mask_alpha);
3386  return(ClampToQuantum(mask_alpha*MagickOver_((double) p,alpha,(double) q,beta)));
3387 }
3388 
3390  ExceptionInfo *exception)
3391 {
3392  CacheInfo
3393  *magick_restrict cache_info;
3394 
3396  number_pixels;
3397 
3398  NexusInfo
3399  **magick_restrict image_nexus;
3400 
3401  register Quantum
3402  *magick_restrict p,
3403  *magick_restrict q;
3404 
3405  register ssize_t
3406  n;
3407 
3408  /*
3409  Apply clip mask.
3410  */
3411  if (image->debug != MagickFalse)
3412  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3413  if ((image->channels & CompositeMaskChannel) == 0)
3414  return(MagickTrue);
3415  cache_info=(CacheInfo *) image->cache;
3416  if (cache_info == (Cache) NULL)
3417  return(MagickFalse);
3418  image_nexus=AcquirePixelCacheNexus(1);
3419  p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
3420  nexus_info->region.width,nexus_info->region.height,image_nexus[0],
3421  exception);
3422  q=nexus_info->pixels;
3423  number_pixels=(MagickSizeType) nexus_info->region.width*
3424  nexus_info->region.height;
3425  for (n=0; n < (ssize_t) number_pixels; n++)
3426  {
3427  double
3428  mask_alpha;
3429 
3430  register ssize_t
3431  i;
3432 
3433  if (p == (Quantum *) NULL)
3434  break;
3435  mask_alpha=(double) GetPixelCompositeMask(image,p);
3436  for (i=0; i < (ssize_t) image->number_channels; i++)
3437  {
3438  PixelChannel channel = GetPixelChannelChannel(image,i);
3439  PixelTrait traits = GetPixelChannelTraits(image,channel);
3440  if ((traits & UpdatePixelTrait) == 0)
3441  continue;
3442  q[i]=ApplyPixelCompositeMask(p[i],mask_alpha,q[i],
3443  (MagickRealType) GetPixelAlpha(image,q));
3444  }
3445  p+=GetPixelChannels(image);
3446  q+=GetPixelChannels(image);
3447  }
3448  image_nexus=DestroyPixelCacheNexus(image_nexus,1);
3449  if (n < (ssize_t) number_pixels)
3450  return(MagickFalse);
3451  return(MagickTrue);
3452 }
3453 
3454 /*
3455 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3456 % %
3457 % %
3458 % %
3459 + O p e n P i x e l C a c h e %
3460 % %
3461 % %
3462 % %
3463 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3464 %
3465 % OpenPixelCache() allocates the pixel cache. This includes defining the cache
3466 % dimensions, allocating space for the image pixels and optionally the
3467 % metacontent, and memory mapping the cache if it is disk based. The cache
3468 % nexus array is initialized as well.
3469 %
3470 % The format of the OpenPixelCache() method is:
3471 %
3472 % MagickBooleanType OpenPixelCache(Image *image,const MapMode mode,
3473 % ExceptionInfo *exception)
3474 %
3475 % A description of each parameter follows:
3476 %
3477 % o image: the image.
3478 %
3479 % o mode: ReadMode, WriteMode, or IOMode.
3480 %
3481 % o exception: return any errors or warnings in this structure.
3482 %
3483 */
3484 
3486  const MapMode mode)
3487 {
3488  int
3489  file;
3490 
3491  /*
3492  Open pixel cache on disk.
3493  */
3494  if ((cache_info->file != -1) && (cache_info->disk_mode == mode))
3495  return(MagickTrue); /* cache already open and in the proper mode */
3496  if (*cache_info->cache_filename == '\0')
3497  file=AcquireUniqueFileResource(cache_info->cache_filename);
3498  else
3499  switch (mode)
3500  {
3501  case ReadMode:
3502  {
3503  file=open_utf8(cache_info->cache_filename,O_RDONLY | O_BINARY,0);
3504  break;
3505  }
3506  case WriteMode:
3507  {
3508  file=open_utf8(cache_info->cache_filename,O_WRONLY | O_CREAT |
3509  O_BINARY | O_EXCL,S_MODE);
3510  if (file == -1)
3511  file=open_utf8(cache_info->cache_filename,O_WRONLY | O_BINARY,S_MODE);
3512  break;
3513  }
3514  case IOMode:
3515  default:
3516  {
3517  file=open_utf8(cache_info->cache_filename,O_RDWR | O_CREAT | O_BINARY |
3518  O_EXCL,S_MODE);
3519  if (file == -1)
3520  file=open_utf8(cache_info->cache_filename,O_RDWR | O_BINARY,S_MODE);
3521  break;
3522  }
3523  }
3524  if (file == -1)
3525  return(MagickFalse);
3527  if (cache_info->file != -1)
3528  (void) ClosePixelCacheOnDisk(cache_info);
3529  cache_info->file=file;
3530  cache_info->disk_mode=mode;
3531  return(MagickTrue);
3532 }
3533 
3535  const CacheInfo *magick_restrict cache_info,const MagickOffsetType offset,
3536  const MagickSizeType length,const unsigned char *magick_restrict buffer)
3537 {
3538  register MagickOffsetType
3539  i;
3540 
3541  ssize_t
3542  count;
3543 
3544 #if !defined(MAGICKCORE_HAVE_PWRITE)
3545  if (lseek(cache_info->file,offset,SEEK_SET) < 0)
3546  return((MagickOffsetType) -1);
3547 #endif
3548  count=0;
3549  for (i=0; i < (MagickOffsetType) length; i+=count)
3550  {
3551 #if !defined(MAGICKCORE_HAVE_PWRITE)
3552  count=write(cache_info->file,buffer+i,(size_t) MagickMin(length-i,(size_t)
3553  SSIZE_MAX));
3554 #else
3555  count=pwrite(cache_info->file,buffer+i,(size_t) MagickMin(length-i,(size_t)
3556  SSIZE_MAX),offset+i);
3557 #endif
3558  if (count <= 0)
3559  {
3560  count=0;
3561  if (errno != EINTR)
3562  break;
3563  }
3564  }
3565  return(i);
3566 }
3567 
3569 {
3570  CacheInfo
3571  *magick_restrict cache_info;
3572 
3574  count,
3575  extent,
3576  offset;
3577 
3578  cache_info=(CacheInfo *) image->cache;
3579  if (image->debug != MagickFalse)
3580  {
3581  char
3582  format[MagickPathExtent],
3583  message[MagickPathExtent];
3584 
3585  (void) FormatMagickSize(length,MagickFalse,"B",MagickPathExtent,format);
3586  (void) FormatLocaleString(message,MagickPathExtent,
3587  "extend %s (%s[%d], disk, %s)",cache_info->filename,
3588  cache_info->cache_filename,cache_info->file,format);
3589  (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
3590  }
3591  if (length != (MagickSizeType) ((MagickOffsetType) length))
3592  return(MagickFalse);
3593  offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_END);
3594  if (offset < 0)
3595  return(MagickFalse);
3596  if ((MagickSizeType) offset >= length)
3597  count=(MagickOffsetType) 1;
3598  else
3599  {
3600  extent=(MagickOffsetType) length-1;
3601  count=WritePixelCacheRegion(cache_info,extent,1,(const unsigned char *)
3602  "");
3603  if (count != 1)
3604  return(MagickFalse);
3605 #if defined(MAGICKCORE_HAVE_POSIX_FALLOCATE)
3606  if (cache_info->synchronize != MagickFalse)
3607  if (posix_fallocate(cache_info->file,offset+1,extent-offset) != 0)
3608  return(MagickFalse);
3609 #endif
3610  }
3611  offset=(MagickOffsetType) lseek(cache_info->file,0,SEEK_SET);
3612  if (offset < 0)
3613  return(MagickFalse);
3614  return(MagickTrue);
3615 }
3616 
3618  ExceptionInfo *exception)
3619 {
3620  CacheInfo
3621  *magick_restrict cache_info,
3622  source_info;
3623 
3624  char
3625  format[MagickPathExtent],
3626  message[MagickPathExtent];
3627 
3628  const char
3629  *hosts,
3630  *type;
3631 
3633  status;
3634 
3636  length,
3637  number_pixels;
3638 
3639  size_t
3640  columns,
3641  packet_size;
3642 
3643  assert(image != (const Image *) NULL);
3644  assert(image->signature == MagickCoreSignature);
3645  assert(image->cache != (Cache) NULL);
3646  if (image->debug != MagickFalse)
3647  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3648  if (cache_anonymous_memory < 0)
3649  {
3650  char
3651  *value;
3652 
3653  /*
3654  Does the security policy require anonymous mapping for pixel cache?
3655  */
3657  value=GetPolicyValue("pixel-cache-memory");
3658  if (value == (char *) NULL)
3659  value=GetPolicyValue("cache:memory-map");
3660  if (LocaleCompare(value,"anonymous") == 0)
3661  {
3662 #if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
3664 #else
3665  (void) ThrowMagickException(exception,GetMagickModule(),
3666  MissingDelegateError,"DelegateLibrarySupportNotBuiltIn",
3667  "'%s' (policy requires anonymous memory mapping)",image->filename);
3668 #endif
3669  }
3670  value=DestroyString(value);
3671  }
3672  if ((image->columns == 0) || (image->rows == 0))
3673  ThrowBinaryException(CacheError,"NoPixelsDefinedInCache",image->filename);
3674  cache_info=(CacheInfo *) image->cache;
3675  assert(cache_info->signature == MagickCoreSignature);
3676  if (((MagickSizeType) image->columns > cache_info->width_limit) ||
3677  ((MagickSizeType) image->rows > cache_info->height_limit))
3678  ThrowBinaryException(ImageError,"WidthOrHeightExceedsLimit",
3679  image->filename);
3680  length=GetImageListLength(image);
3682  ThrowBinaryException(ResourceLimitError,"ListLengthExceedsLimit",
3683  image->filename);
3684  source_info=(*cache_info);
3685  source_info.file=(-1);
3686  (void) FormatLocaleString(cache_info->filename,MagickPathExtent,"%s[%.20g]",
3687  image->filename,(double) image->scene);
3688  cache_info->storage_class=image->storage_class;
3689  cache_info->colorspace=image->colorspace;
3690  cache_info->alpha_trait=image->alpha_trait;
3691  cache_info->channels=image->channels;
3692  cache_info->rows=image->rows;
3693  cache_info->columns=image->columns;
3695  cache_info->number_channels=GetPixelChannels(image);
3696  (void) memcpy(cache_info->channel_map,image->channel_map,MaxPixelChannels*
3697  sizeof(*image->channel_map));
3698  cache_info->metacontent_extent=image->metacontent_extent;
3699  cache_info->mode=mode;
3700  number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
3701  packet_size=cache_info->number_channels*sizeof(Quantum);
3702  if (image->metacontent_extent != 0)
3703  packet_size+=cache_info->metacontent_extent;
3704  length=number_pixels*packet_size;
3705  columns=(size_t) (length/cache_info->rows/packet_size);
3706  if ((cache_info->columns != columns) || ((ssize_t) cache_info->columns < 0) ||
3707  ((ssize_t) cache_info->rows < 0))
3708  ThrowBinaryException(ResourceLimitError,"PixelCacheAllocationFailed",
3709  image->filename);
3710  cache_info->length=length;
3711  if (image->ping != MagickFalse)
3712  {
3713  cache_info->storage_class=image->storage_class;
3714  cache_info->colorspace=image->colorspace;
3715  cache_info->type=PingCache;
3716  return(MagickTrue);
3717  }
3719  cache_info->columns*cache_info->rows);
3720  if (cache_info->mode == PersistMode)
3721  status=MagickFalse;
3722  length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
3723  cache_info->metacontent_extent);
3724  if ((status != MagickFalse) &&
3725  (length == (MagickSizeType) ((size_t) length)) &&
3726  ((cache_info->type == UndefinedCache) || (cache_info->type == MemoryCache)))
3727  {
3728  status=AcquireMagickResource(MemoryResource,cache_info->length);
3729  if (status != MagickFalse)
3730  {
3731  status=MagickTrue;
3732  if (cache_anonymous_memory <= 0)
3733  {
3734  cache_info->mapped=MagickFalse;
3735  cache_info->pixels=(Quantum *) MagickAssumeAligned(
3736  AcquireAlignedMemory(1,(size_t) cache_info->length));
3737  }
3738  else
3739  {
3740  cache_info->mapped=MagickTrue;
3741  cache_info->pixels=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
3742  cache_info->length);
3743  }
3744  if (cache_info->pixels == (Quantum *) NULL)
3745  {
3746  cache_info->mapped=source_info.mapped;
3747  cache_info->pixels=source_info.pixels;
3748  }
3749  else
3750  {
3751  /*
3752  Create memory pixel cache.
3753  */
3754  cache_info->type=MemoryCache;
3755  cache_info->metacontent=(void *) NULL;
3756  if (cache_info->metacontent_extent != 0)
3757  cache_info->metacontent=(void *) (cache_info->pixels+
3758  cache_info->number_channels*number_pixels);
3759  if ((source_info.storage_class != UndefinedClass) &&
3760  (mode != ReadMode))
3761  {
3762  status=ClonePixelCacheRepository(cache_info,&source_info,
3763  exception);
3764  RelinquishPixelCachePixels(&source_info);
3765  }
3766  if (image->debug != MagickFalse)
3767  {
3768  (void) FormatMagickSize(cache_info->length,MagickTrue,"B",
3769  MagickPathExtent,format);
3771  cache_info->type);
3772  (void) FormatLocaleString(message,MagickPathExtent,
3773  "open %s (%s %s, %.20gx%.20gx%.20g %s)",
3774  cache_info->filename,cache_info->mapped != MagickFalse ?
3775  "Anonymous" : "Heap",type,(double) cache_info->columns,
3776  (double) cache_info->rows,(double)
3777  cache_info->number_channels,format);
3779  message);
3780  }
3781  return(status == 0 ? MagickFalse : MagickTrue);
3782  }
3783  }
3784  }
3785  status=AcquireMagickResource(DiskResource,cache_info->length);
3786  hosts=(const char *) GetImageRegistry(StringRegistryType,"cache:hosts",
3787  exception);
3788  if ((status == MagickFalse) && (hosts != (const char *) NULL))
3789  {
3791  *server_info;
3792 
3793  /*
3794  Distribute the pixel cache to a remote server.
3795  */
3796  server_info=AcquireDistributeCacheInfo(exception);
3797  if (server_info != (DistributeCacheInfo *) NULL)
3798  {
3799  status=OpenDistributePixelCache(server_info,image);
3800  if (status == MagickFalse)
3801  {
3802  ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
3803  GetDistributeCacheHostname(server_info));
3804  server_info=DestroyDistributeCacheInfo(server_info);
3805  }
3806  else
3807  {
3808  /*
3809  Create a distributed pixel cache.
3810  */
3811  status=MagickTrue;
3812  cache_info->type=DistributedCache;
3813  cache_info->server_info=server_info;
3814  (void) FormatLocaleString(cache_info->cache_filename,
3816  (DistributeCacheInfo *) cache_info->server_info),
3818  cache_info->server_info));
3819  if ((source_info.storage_class != UndefinedClass) &&
3820  (mode != ReadMode))
3821  {
3822  status=ClonePixelCacheRepository(cache_info,&source_info,
3823  exception);
3824  RelinquishPixelCachePixels(&source_info);
3825  }
3826  if (image->debug != MagickFalse)
3827  {
3828  (void) FormatMagickSize(cache_info->length,MagickFalse,"B",
3829  MagickPathExtent,format);
3831  cache_info->type);
3832  (void) FormatLocaleString(message,MagickPathExtent,
3833  "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3834  cache_info->filename,cache_info->cache_filename,
3836  cache_info->server_info),type,(double) cache_info->columns,
3837  (double) cache_info->rows,(double)
3838  cache_info->number_channels,format);
3840  message);
3841  }
3842  return(status == 0 ? MagickFalse : MagickTrue);
3843  }
3844  }
3845  cache_info->type=UndefinedCache;
3846  (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3847  "CacheResourcesExhausted","`%s'",image->filename);
3848  return(MagickFalse);
3849  }
3850  /*
3851  Create pixel cache on disk.
3852  */
3853  if (status == MagickFalse)
3854  {
3855  cache_info->type=UndefinedCache;
3856  (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3857  "CacheResourcesExhausted","`%s'",image->filename);
3858  return(MagickFalse);
3859  }
3860  if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
3861  (cache_info->mode != PersistMode))
3862  {
3863  (void) ClosePixelCacheOnDisk(cache_info);
3864  *cache_info->cache_filename='\0';
3865  }
3866  if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
3867  {
3868  ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
3869  image->filename);
3870  return(MagickFalse);
3871  }
3872  status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
3873  cache_info->length);
3874  if (status == MagickFalse)
3875  {
3876  ThrowFileException(exception,CacheError,"UnableToExtendCache",
3877  image->filename);
3878  return(MagickFalse);
3879  }
3880  length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
3881  cache_info->metacontent_extent);
3882  if (length != (MagickSizeType) ((size_t) length))
3883  cache_info->type=DiskCache;
3884  else
3885  {
3886  status=AcquireMagickResource(MapResource,cache_info->length);
3887  if (status == MagickFalse)
3888  cache_info->type=DiskCache;
3889  else
3890  if ((cache_info->type != MapCache) && (cache_info->type != MemoryCache))
3891  {
3892  cache_info->type=DiskCache;
3893  RelinquishMagickResource(MapResource,cache_info->length);
3894  }
3895  else
3896  {
3897  cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
3898  cache_info->offset,(size_t) cache_info->length);
3899  if (cache_info->pixels == (Quantum *) NULL)
3900  {
3901  cache_info->type=DiskCache;
3902  cache_info->mapped=source_info.mapped;
3903  cache_info->pixels=source_info.pixels;
3904  RelinquishMagickResource(MapResource,cache_info->length);
3905  }
3906  else
3907  {
3908  /*
3909  Create file-backed memory-mapped pixel cache.
3910  */
3911  (void) ClosePixelCacheOnDisk(cache_info);
3912  cache_info->type=MapCache;
3913  cache_info->mapped=MagickTrue;
3914  cache_info->metacontent=(void *) NULL;
3915  if (cache_info->metacontent_extent != 0)
3916  cache_info->metacontent=(void *) (cache_info->pixels+
3917  cache_info->number_channels*number_pixels);
3918  if ((source_info.storage_class != UndefinedClass) &&
3919  (mode != ReadMode))
3920  {
3921  status=ClonePixelCacheRepository(cache_info,&source_info,
3922  exception);
3923  RelinquishPixelCachePixels(&source_info);
3924  }
3925  if (image->debug != MagickFalse)
3926  {
3927  (void) FormatMagickSize(cache_info->length,MagickTrue,"B",
3928  MagickPathExtent,format);
3930  cache_info->type);
3931  (void) FormatLocaleString(message,MagickPathExtent,
3932  "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3933  cache_info->filename,cache_info->cache_filename,
3934  cache_info->file,type,(double) cache_info->columns,
3935  (double) cache_info->rows,(double)
3936  cache_info->number_channels,format);
3938  message);
3939  }
3940  return(status == 0 ? MagickFalse : MagickTrue);
3941  }
3942  }
3943  }
3944  status=MagickTrue;
3945  if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3946  {
3947  status=ClonePixelCacheRepository(cache_info,&source_info,exception);
3948  RelinquishPixelCachePixels(&source_info);
3949  }
3950  if (image->debug != MagickFalse)
3951  {
3952  (void) FormatMagickSize(cache_info->length,MagickFalse,"B",
3953  MagickPathExtent,format);
3955  cache_info->type);
3956  (void) FormatLocaleString(message,MagickPathExtent,
3957  "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",cache_info->filename,
3958  cache_info->cache_filename,cache_info->file,type,(double)
3959  cache_info->columns,(double) cache_info->rows,(double)
3960  cache_info->number_channels,format);
3961  (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
3962  }
3963  return(status == 0 ? MagickFalse : MagickTrue);
3964 }
3965 
3966 /*
3967 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3968 % %
3969 % %
3970 % %
3971 + P e r s i s t P i x e l C a c h e %
3972 % %
3973 % %
3974 % %
3975 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3976 %
3977 % PersistPixelCache() attaches to or initializes a persistent pixel cache. A
3978 % persistent pixel cache is one that resides on disk and is not destroyed
3979 % when the program exits.
3980 %
3981 % The format of the PersistPixelCache() method is:
3982 %
3983 % MagickBooleanType PersistPixelCache(Image *image,const char *filename,
3984 % const MagickBooleanType attach,MagickOffsetType *offset,
3985 % ExceptionInfo *exception)
3986 %
3987 % A description of each parameter follows:
3988 %
3989 % o image: the image.
3990 %
3991 % o filename: the persistent pixel cache filename.
3992 %
3993 % o attach: A value other than zero initializes the persistent pixel cache.
3994 %
3995 % o initialize: A value other than zero initializes the persistent pixel
3996 % cache.
3997 %
3998 % o offset: the offset in the persistent cache to store pixels.
3999 %
4000 % o exception: return any errors or warnings in this structure.
4001 %
4002 */
4004  const char *filename,const MagickBooleanType attach,MagickOffsetType *offset,
4005  ExceptionInfo *exception)
4006 {
4007  CacheInfo
4008  *magick_restrict cache_info,
4009  *magick_restrict clone_info;
4010 
4012  status;
4013 
4014  ssize_t
4015  page_size;
4016 
4017  assert(image != (Image *) NULL);
4018  assert(image->signature == MagickCoreSignature);
4019  if (image->debug != MagickFalse)
4020  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4021  assert(image->cache != (void *) NULL);
4022  assert(filename != (const char *) NULL);
4023  assert(offset != (MagickOffsetType *) NULL);
4024  page_size=GetMagickPageSize();
4025  cache_info=(CacheInfo *) image->cache;
4026  assert(cache_info->signature == MagickCoreSignature);
4027 #if defined(MAGICKCORE_OPENCL_SUPPORT)
4028  CopyOpenCLBuffer(cache_info);
4029 #endif
4030  if (attach != MagickFalse)
4031  {
4032  /*
4033  Attach existing persistent pixel cache.
4034  */
4035  if (image->debug != MagickFalse)
4037  "attach persistent cache");
4038  (void) CopyMagickString(cache_info->cache_filename,filename,
4040  cache_info->type=DiskCache;
4041  cache_info->offset=(*offset);
4042  if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4043  return(MagickFalse);
4044  *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4045  return(SyncImagePixelCache(image,exception));
4046  }
4047  /*
4048  Clone persistent pixel cache.
4049  */
4050  status=AcquireMagickResource(DiskResource,cache_info->length);
4051  if (status == MagickFalse)
4052  {
4053  (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4054  "CacheResourcesExhausted","`%s'",image->filename);
4055  return(MagickFalse);
4056  }
4057  clone_info=(CacheInfo *) ClonePixelCache(cache_info);
4058  clone_info->type=DiskCache;
4059  (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
4060  clone_info->file=(-1);
4061  clone_info->storage_class=cache_info->storage_class;
4062  clone_info->colorspace=cache_info->colorspace;
4063  clone_info->alpha_trait=cache_info->alpha_trait;
4064  clone_info->channels=cache_info->channels;
4065  clone_info->columns=cache_info->columns;
4066  clone_info->rows=cache_info->rows;
4067  clone_info->number_channels=cache_info->number_channels;
4068  clone_info->metacontent_extent=cache_info->metacontent_extent;
4069  clone_info->mode=PersistMode;
4070  clone_info->length=cache_info->length;
4071  (void) memcpy(clone_info->channel_map,cache_info->channel_map,
4072  MaxPixelChannels*sizeof(*cache_info->channel_map));
4073  clone_info->offset=(*offset);
4074  status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4075  *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4076  clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4077  return(status);
4078 }
4079 
4080 /*
4081 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4082 % %
4083 % %
4084 % %
4085 + Q u e u e A u t h e n t i c P i x e l C a c h e N e x u s %
4086 % %
4087 % %
4088 % %
4089 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4090 %
4091 % QueueAuthenticPixelCacheNexus() allocates an region to store image pixels as
4092 % defined by the region rectangle and returns a pointer to the region. This
4093 % region is subsequently transferred from the pixel cache with
4094 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4095 % pixels are transferred, otherwise a NULL is returned.
4096 %
4097 % The format of the QueueAuthenticPixelCacheNexus() method is:
4098 %
4099 % Quantum *QueueAuthenticPixelCacheNexus(Image *image,const ssize_t x,
4100 % const ssize_t y,const size_t columns,const size_t rows,
4101 % const MagickBooleanType clone,NexusInfo *nexus_info,
4102 % ExceptionInfo *exception)
4103 %
4104 % A description of each parameter follows:
4105 %
4106 % o image: the image.
4107 %
4108 % o x,y,columns,rows: These values define the perimeter of a region of
4109 % pixels.
4110 %
4111 % o nexus_info: the cache nexus to set.
4112 %
4113 % o clone: clone the pixel cache.
4114 %
4115 % o exception: return any errors or warnings in this structure.
4116 %
4117 */
4119  const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
4120  const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
4121 {
4122  CacheInfo
4123  *magick_restrict cache_info;
4124 
4126  offset;
4127 
4129  number_pixels;
4130 
4131  Quantum
4132  *magick_restrict pixels;
4133 
4134  /*
4135  Validate pixel cache geometry.
4136  */
4137  assert(image != (const Image *) NULL);
4138  assert(image->signature == MagickCoreSignature);
4139  assert(image->cache != (Cache) NULL);
4140  cache_info=(CacheInfo *) GetImagePixelCache(image,clone,exception);
4141  if (cache_info == (Cache) NULL)
4142  return((Quantum *) NULL);
4143  assert(cache_info->signature == MagickCoreSignature);
4144  if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4145  (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4146  (y >= (ssize_t) cache_info->rows))
4147  {
4148  (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4149  "PixelsAreNotAuthentic","`%s'",image->filename);
4150  return((Quantum *) NULL);
4151  }
4152  offset=(MagickOffsetType) y*cache_info->columns+x;
4153  if (offset < 0)
4154  return((Quantum *) NULL);
4155  number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4156  offset+=(MagickOffsetType) (rows-1)*cache_info->columns+columns-1;
4157  if ((MagickSizeType) offset >= number_pixels)
4158  return((Quantum *) NULL);
4159  /*
4160  Return pixel cache.
4161  */
4162  pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,x,y,columns,rows,
4163  ((image->channels & WriteMaskChannel) != 0) ||
4164  ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
4165  nexus_info,exception);
4166  return(pixels);
4167 }
4168 
4169 /*
4170 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4171 % %
4172 % %
4173 % %
4174 + Q u e u e A u t h e n t i c P i x e l s C a c h e %
4175 % %
4176 % %
4177 % %
4178 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4179 %
4180 % QueueAuthenticPixelsCache() allocates an region to store image pixels as
4181 % defined by the region rectangle and returns a pointer to the region. This
4182 % region is subsequently transferred from the pixel cache with
4183 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4184 % pixels are transferred, otherwise a NULL is returned.
4185 %
4186 % The format of the QueueAuthenticPixelsCache() method is:
4187 %
4188 % Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4189 % const ssize_t y,const size_t columns,const size_t rows,
4190 % ExceptionInfo *exception)
4191 %
4192 % A description of each parameter follows:
4193 %
4194 % o image: the image.
4195 %
4196 % o x,y,columns,rows: These values define the perimeter of a region of
4197 % pixels.
4198 %
4199 % o exception: return any errors or warnings in this structure.
4200 %
4201 */
4202 static Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4203  const ssize_t y,const size_t columns,const size_t rows,
4204  ExceptionInfo *exception)
4205 {
4206  CacheInfo
4207  *magick_restrict cache_info;
4208 
4209  const int
4210  id = GetOpenMPThreadId();
4211 
4212  Quantum
4213  *magick_restrict pixels;
4214 
4215  assert(image != (const Image *) NULL);
4216  assert(image->signature == MagickCoreSignature);
4217  assert(image->cache != (Cache) NULL);
4218  cache_info=(CacheInfo *) image->cache;
4219  assert(cache_info->signature == MagickCoreSignature);
4220  assert(id < (int) cache_info->number_threads);
4221  pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4222  cache_info->nexus_info[id],exception);
4223  return(pixels);
4224 }
4225 
4226 /*
4227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4228 % %
4229 % %
4230 % %
4231 % Q u e u e A u t h e n t i c P i x e l s %
4232 % %
4233 % %
4234 % %
4235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4236 %
4237 % QueueAuthenticPixels() queues a mutable pixel region. If the region is
4238 % successfully initialized a pointer to a Quantum array representing the
4239 % region is returned, otherwise NULL is returned. The returned pointer may
4240 % point to a temporary working buffer for the pixels or it may point to the
4241 % final location of the pixels in memory.
4242 %
4243 % Write-only access means that any existing pixel values corresponding to
4244 % the region are ignored. This is useful if the initial image is being
4245 % created from scratch, or if the existing pixel values are to be
4246 % completely replaced without need to refer to their pre-existing values.
4247 % The application is free to read and write the pixel buffer returned by
4248 % QueueAuthenticPixels() any way it pleases. QueueAuthenticPixels() does not
4249 % initialize the pixel array values. Initializing pixel array values is the
4250 % application's responsibility.
4251 %
4252 % Performance is maximized if the selected region is part of one row, or
4253 % one or more full rows, since then there is opportunity to access the
4254 % pixels in-place (without a copy) if the image is in memory, or in a
4255 % memory-mapped file. The returned pointer must *never* be deallocated
4256 % by the user.
4257 %
4258 % Pixels accessed via the returned pointer represent a simple array of type
4259 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
4260 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
4261 % obtain the meta-content (of type void) corresponding to the region.
4262 % Once the Quantum (and/or Quantum) array has been updated, the
4263 % changes must be saved back to the underlying image using
4264 % SyncAuthenticPixels() or they may be lost.
4265 %
4266 % The format of the QueueAuthenticPixels() method is:
4267 %
4268 % Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4269 % const ssize_t y,const size_t columns,const size_t rows,
4270 % ExceptionInfo *exception)
4271 %
4272 % A description of each parameter follows:
4273 %
4274 % o image: the image.
4275 %
4276 % o x,y,columns,rows: These values define the perimeter of a region of
4277 % pixels.
4278 %
4279 % o exception: return any errors or warnings in this structure.
4280 %
4281 */
4283  const ssize_t y,const size_t columns,const size_t rows,
4284  ExceptionInfo *exception)
4285 {
4286  CacheInfo
4287  *magick_restrict cache_info;
4288 
4289  const int
4290  id = GetOpenMPThreadId();
4291 
4292  Quantum
4293  *magick_restrict pixels;
4294 
4295  assert(image != (Image *) NULL);
4296  assert(image->signature == MagickCoreSignature);
4297  assert(image->cache != (Cache) NULL);
4298  cache_info=(CacheInfo *) image->cache;
4299  assert(cache_info->signature == MagickCoreSignature);
4300  if (cache_info->methods.queue_authentic_pixels_handler !=
4302  {
4303  pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4304  columns,rows,exception);
4305  return(pixels);
4306  }
4307  assert(id < (int) cache_info->number_threads);
4308  pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4309  cache_info->nexus_info[id],exception);
4310  return(pixels);
4311 }
4312 
4313 /*
4314 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4315 % %
4316 % %
4317 % %
4318 + R e a d P i x e l C a c h e M e t a c o n t e n t %
4319 % %
4320 % %
4321 % %
4322 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4323 %
4324 % ReadPixelCacheMetacontent() reads metacontent from the specified region of
4325 % the pixel cache.
4326 %
4327 % The format of the ReadPixelCacheMetacontent() method is:
4328 %
4329 % MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4330 % NexusInfo *nexus_info,ExceptionInfo *exception)
4331 %
4332 % A description of each parameter follows:
4333 %
4334 % o cache_info: the pixel cache.
4335 %
4336 % o nexus_info: the cache nexus to read the metacontent.
4337 %
4338 % o exception: return any errors or warnings in this structure.
4339 %
4340 */
4341 
4343  const CacheInfo *magick_restrict cache_info,const MagickOffsetType offset,
4344  const MagickSizeType length,unsigned char *magick_restrict buffer)
4345 {
4346  register MagickOffsetType
4347  i;
4348 
4349  ssize_t
4350  count;
4351 
4352 #if !defined(MAGICKCORE_HAVE_PREAD)
4353  if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4354  return((MagickOffsetType) -1);
4355 #endif
4356  count=0;
4357  for (i=0; i < (MagickOffsetType) length; i+=count)
4358  {
4359 #if !defined(MAGICKCORE_HAVE_PREAD)
4360  count=read(cache_info->file,buffer+i,(size_t) MagickMin(length-i,(size_t)
4361  SSIZE_MAX));
4362 #else
4363  count=pread(cache_info->file,buffer+i,(size_t) MagickMin(length-i,(size_t)
4364  SSIZE_MAX),offset+i);
4365 #endif
4366  if (count <= 0)
4367  {
4368  count=0;
4369  if (errno != EINTR)
4370  break;
4371  }
4372  }
4373  return(i);
4374 }
4375 
4377  CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4378  ExceptionInfo *exception)
4379 {
4381  count,
4382  offset;
4383 
4385  extent,
4386  length;
4387 
4388  register ssize_t
4389  y;
4390 
4391  register unsigned char
4392  *magick_restrict q;
4393 
4394  size_t
4395  rows;
4396 
4397  if (cache_info->metacontent_extent == 0)
4398  return(MagickFalse);
4399  if (nexus_info->authentic_pixel_cache != MagickFalse)
4400  return(MagickTrue);
4401  offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4402  nexus_info->region.x;
4403  length=(MagickSizeType) nexus_info->region.width*
4404  cache_info->metacontent_extent;
4405  extent=length*nexus_info->region.height;
4406  rows=nexus_info->region.height;
4407  y=0;
4408  q=(unsigned char *) nexus_info->metacontent;
4409  switch (cache_info->type)
4410  {
4411  case MemoryCache:
4412  case MapCache:
4413  {
4414  register unsigned char
4415  *magick_restrict p;
4416 
4417  /*
4418  Read meta-content from memory.
4419  */
4420  if ((cache_info->columns == nexus_info->region.width) &&
4421  (extent == (MagickSizeType) ((size_t) extent)))
4422  {
4423  length=extent;
4424  rows=1UL;
4425  }
4426  p=(unsigned char *) cache_info->metacontent+offset*
4427  cache_info->metacontent_extent;
4428  for (y=0; y < (ssize_t) rows; y++)
4429  {
4430  (void) memcpy(q,p,(size_t) length);
4431  p+=cache_info->metacontent_extent*cache_info->columns;
4432  q+=cache_info->metacontent_extent*nexus_info->region.width;
4433  }
4434  break;
4435  }
4436  case DiskCache:
4437  {
4438  /*
4439  Read meta content from disk.
4440  */
4441  LockSemaphoreInfo(cache_info->file_semaphore);
4442  if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4443  {
4444  ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4445  cache_info->cache_filename);
4446  UnlockSemaphoreInfo(cache_info->file_semaphore);
4447  return(MagickFalse);
4448  }
4449  if ((cache_info->columns == nexus_info->region.width) &&
4450  (extent <= MagickMaxBufferExtent))
4451  {
4452  length=extent;
4453  rows=1UL;
4454  }
4455  extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4456  for (y=0; y < (ssize_t) rows; y++)
4457  {
4458  count=ReadPixelCacheRegion(cache_info,cache_info->offset+extent*
4459  cache_info->number_channels*sizeof(Quantum)+offset*
4460  cache_info->metacontent_extent,length,(unsigned char *) q);
4461  if (count != (MagickOffsetType) length)
4462  break;
4463  offset+=cache_info->columns;
4464  q+=cache_info->metacontent_extent*nexus_info->region.width;
4465  }
4467  (void) ClosePixelCacheOnDisk(cache_info);
4468  UnlockSemaphoreInfo(cache_info->file_semaphore);
4469  break;
4470  }
4471  case DistributedCache:
4472  {
4474  region;
4475 
4476  /*
4477  Read metacontent from distributed cache.
4478  */
4479  LockSemaphoreInfo(cache_info->file_semaphore);
4480  region=nexus_info->region;
4481  if ((cache_info->columns != nexus_info->region.width) ||
4482  (extent > MagickMaxBufferExtent))
4483  region.height=1UL;
4484  else
4485  {
4486  length=extent;
4487  rows=1UL;
4488  }
4489  for (y=0; y < (ssize_t) rows; y++)
4490  {
4492  cache_info->server_info,&region,length,(unsigned char *) q);
4493  if (count != (MagickOffsetType) length)
4494  break;
4495  q+=cache_info->metacontent_extent*nexus_info->region.width;
4496  region.y++;
4497  }
4498  UnlockSemaphoreInfo(cache_info->file_semaphore);
4499  break;
4500  }
4501  default:
4502  break;
4503  }
4504  if (y < (ssize_t) rows)
4505  {
4506  ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4507  cache_info->cache_filename);
4508  return(MagickFalse);
4509  }
4510  if ((cache_info->debug != MagickFalse) &&
4511  (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4513  "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4514  nexus_info->region.width,(double) nexus_info->region.height,(double)
4515  nexus_info->region.x,(double) nexus_info->region.y);
4516  return(MagickTrue);
4517 }
4518 
4519 /*
4520 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4521 % %
4522 % %
4523 % %
4524 + R e a d P i x e l C a c h e P i x e l s %
4525 % %
4526 % %
4527 % %
4528 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4529 %
4530 % ReadPixelCachePixels() reads pixels from the specified region of the pixel
4531 % cache.
4532 %
4533 % The format of the ReadPixelCachePixels() method is:
4534 %
4535 % MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4536 % NexusInfo *nexus_info,ExceptionInfo *exception)
4537 %
4538 % A description of each parameter follows:
4539 %
4540 % o cache_info: the pixel cache.
4541 %
4542 % o nexus_info: the cache nexus to read the pixels.
4543 %
4544 % o exception: return any errors or warnings in this structure.
4545 %
4546 */
4548  CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4549  ExceptionInfo *exception)
4550 {
4552  count,
4553  offset;
4554 
4556  extent,
4557  length;
4558 
4559  register Quantum
4560  *magick_restrict q;
4561 
4562  register ssize_t
4563  y;
4564 
4565  size_t
4566  number_channels,
4567  rows;
4568 
4569  if (nexus_info->authentic_pixel_cache != MagickFalse)
4570  return(MagickTrue);
4571  offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns;
4572  if ((ssize_t) (offset/cache_info->columns) != nexus_info->region.y)
4573  return(MagickFalse);
4574  offset+=nexus_info->region.x;
4575  number_channels=cache_info->number_channels;
4576  length=(MagickSizeType) number_channels*nexus_info->region.width*
4577  sizeof(Quantum);
4578  if ((length/number_channels/sizeof(Quantum)) != nexus_info->region.width)
4579  return(MagickFalse);
4580  rows=nexus_info->region.height;
4581  extent=length*rows;
4582  if ((extent == 0) || ((extent/length) != rows))
4583  return(MagickFalse);
4584  y=0;
4585  q=nexus_info->pixels;
4586  switch (cache_info->type)
4587  {
4588  case MemoryCache:
4589  case MapCache:
4590  {
4591  register Quantum
4592  *magick_restrict p;
4593 
4594  /*
4595  Read pixels from memory.
4596  */
4597  if ((cache_info->columns == nexus_info->region.width) &&
4598  (extent == (MagickSizeType) ((size_t) extent)))
4599  {
4600  length=extent;
4601  rows=1UL;
4602  }
4603  p=cache_info->pixels+cache_info->number_channels*offset;
4604  for (y=0; y < (ssize_t) rows; y++)
4605  {
4606  (void) memcpy(q,p,(size_t) length);
4607  p+=cache_info->number_channels*cache_info->columns;
4608  q+=cache_info->number_channels*nexus_info->region.width;
4609  }
4610  break;
4611  }
4612  case DiskCache:
4613  {
4614  /*
4615  Read pixels from disk.
4616  */
4617  LockSemaphoreInfo(cache_info->file_semaphore);
4618  if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4619  {
4620  ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4621  cache_info->cache_filename);
4622  UnlockSemaphoreInfo(cache_info->file_semaphore);
4623  return(MagickFalse);
4624  }
4625  if ((cache_info->columns == nexus_info->region.width) &&
4626  (extent <= MagickMaxBufferExtent))
4627  {
4628  length=extent;
4629  rows=1UL;
4630  }
4631  for (y=0; y < (ssize_t) rows; y++)
4632  {
4633  count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4634  cache_info->number_channels*sizeof(*q),length,(unsigned char *) q);
4635  if (count != (MagickOffsetType) length)
4636  break;
4637  offset+=cache_info->columns;
4638  q+=cache_info->number_channels*nexus_info->region.width;
4639  }
4641  (void) ClosePixelCacheOnDisk(cache_info);
4642  UnlockSemaphoreInfo(cache_info->file_semaphore);
4643  break;
4644  }
4645  case DistributedCache:
4646  {
4648  region;
4649 
4650  /*
4651  Read pixels from distributed cache.
4652  */
4653  LockSemaphoreInfo(cache_info->file_semaphore);
4654  region=nexus_info->region;
4655  if ((cache_info->columns != nexus_info->region.width) ||
4656  (extent > MagickMaxBufferExtent))
4657  region.height=1UL;
4658  else
4659  {
4660  length=extent;
4661  rows=1UL;
4662  }
4663  for (y=0; y < (ssize_t) rows; y++)
4664  {
4666  cache_info->server_info,&region,length,(unsigned char *) q);
4667  if (count != (MagickOffsetType) length)
4668  break;
4669  q+=cache_info->number_channels*nexus_info->region.width;
4670  region.y++;
4671  }
4672  UnlockSemaphoreInfo(cache_info->file_semaphore);
4673  break;
4674  }
4675  default:
4676  break;
4677  }
4678  if (y < (ssize_t) rows)
4679  {
4680  ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4681  cache_info->cache_filename);
4682  return(MagickFalse);
4683  }
4684  if ((cache_info->debug != MagickFalse) &&
4685  (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4687  "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4688  nexus_info->region.width,(double) nexus_info->region.height,(double)
4689  nexus_info->region.x,(double) nexus_info->region.y);
4690  return(MagickTrue);
4691 }
4692 
4693 /*
4694 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4695 % %
4696 % %
4697 % %
4698 + R e f e r e n c e P i x e l C a c h e %
4699 % %
4700 % %
4701 % %
4702 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4703 %
4704 % ReferencePixelCache() increments the reference count associated with the
4705 % pixel cache returning a pointer to the cache.
4706 %
4707 % The format of the ReferencePixelCache method is:
4708 %
4709 % Cache ReferencePixelCache(Cache cache_info)
4710 %
4711 % A description of each parameter follows:
4712 %
4713 % o cache_info: the pixel cache.
4714 %
4715 */
4717 {
4718  CacheInfo
4719  *magick_restrict cache_info;
4720 
4721  assert(cache != (Cache *) NULL);
4722  cache_info=(CacheInfo *) cache;
4723  assert(cache_info->signature == MagickCoreSignature);
4724  LockSemaphoreInfo(cache_info->semaphore);
4725  cache_info->reference_count++;
4726  UnlockSemaphoreInfo(cache_info->semaphore);
4727  return(cache_info);
4728 }
4729 
4730 /*
4731 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4732 % %
4733 % %
4734 % %
4735 + R e s e t P i x e l C a c h e C h a n n e l s %
4736 % %
4737 % %
4738 % %
4739 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4740 %
4741 % ResetPixelCacheChannels() resets the pixel cache channels.
4742 %
4743 % The format of the ResetPixelCacheChannels method is:
4744 %
4745 % void ResetPixelCacheChannels(Image *)
4746 %
4747 % A description of each parameter follows:
4748 %
4749 % o image: the image.
4750 %
4751 */
4753 {
4754  CacheInfo
4755  *magick_restrict cache_info;
4756 
4757  assert(image != (const Image *) NULL);
4758  assert(image->signature == MagickCoreSignature);
4759  assert(image->cache != (Cache) NULL);
4760  cache_info=(CacheInfo *) image->cache;
4761  assert(cache_info->signature == MagickCoreSignature);
4762  cache_info->number_channels=GetPixelChannels(image);
4763 }
4764 
4765 /*
4766 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4767 % %
4768 % %
4769 % %
4770 + R e s e t C a c h e A n o n y m o u s M e m o r y %
4771 % %
4772 % %
4773 % %
4774 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4775 %
4776 % ResetCacheAnonymousMemory() resets the anonymous_memory value.
4777 %
4778 % The format of the ResetCacheAnonymousMemory method is:
4779 %
4780 % void ResetCacheAnonymousMemory(void)
4781 %
4782 */
4784 {
4786 }
4787 
4788 /*
4789 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4790 % %
4791 % %
4792 % %
4793 + R e s e t P i x e l C a c h e E p o c h %
4794 % %
4795 % %
4796 % %
4797 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4798 %
4799 % ResetPixelCacheEpoch() resets the pixel cache epoch.
4800 %
4801 % The format of the ResetPixelCacheEpoch method is:
4802 %
4803 % void ResetPixelCacheEpoch(void)
4804 %
4805 */
4807 {
4808  cache_epoch=0;
4809 }
4810 
4811 /*
4812 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4813 % %
4814 % %
4815 % %
4816 + S e t P i x e l C a c h e M e t h o d s %
4817 % %
4818 % %
4819 % %
4820 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4821 %
4822 % SetPixelCacheMethods() sets the image pixel methods to the specified ones.
4823 %
4824 % The format of the SetPixelCacheMethods() method is:
4825 %
4826 % SetPixelCacheMethods(Cache *,CacheMethods *cache_methods)
4827 %
4828 % A description of each parameter follows:
4829 %
4830 % o cache: the pixel cache.
4831 %
4832 % o cache_methods: Specifies a pointer to a CacheMethods structure.
4833 %
4834 */
4836 {
4837  CacheInfo
4838  *magick_restrict cache_info;
4839 
4841  get_one_authentic_pixel_from_handler;
4842 
4844  get_one_virtual_pixel_from_handler;
4845 
4846  /*
4847  Set cache pixel methods.
4848  */
4849  assert(cache != (Cache) NULL);
4850  assert(cache_methods != (CacheMethods *) NULL);
4851  cache_info=(CacheInfo *) cache;
4852  assert(cache_info->signature == MagickCoreSignature);
4853  if (cache_info->debug != MagickFalse)
4855  cache_info->filename);
4856  if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4857  cache_info->methods.get_virtual_pixel_handler=
4858  cache_methods->get_virtual_pixel_handler;
4859  if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4860  cache_info->methods.destroy_pixel_handler=
4861  cache_methods->destroy_pixel_handler;
4862  if (cache_methods->get_virtual_metacontent_from_handler !=
4864  cache_info->methods.get_virtual_metacontent_from_handler=
4865  cache_methods->get_virtual_metacontent_from_handler;
4866  if (cache_methods->get_authentic_pixels_handler !=
4868  cache_info->methods.get_authentic_pixels_handler=
4869  cache_methods->get_authentic_pixels_handler;
4870  if (cache_methods->queue_authentic_pixels_handler !=
4872  cache_info->methods.queue_authentic_pixels_handler=
4873  cache_methods->queue_authentic_pixels_handler;
4874  if (cache_methods->sync_authentic_pixels_handler !=
4876  cache_info->methods.sync_authentic_pixels_handler=
4877  cache_methods->sync_authentic_pixels_handler;
4878  if (cache_methods->get_authentic_pixels_from_handler !=
4880  cache_info->methods.get_authentic_pixels_from_handler=
4881  cache_methods->get_authentic_pixels_from_handler;
4882  if (cache_methods->get_authentic_metacontent_from_handler !=
4884  cache_info->methods.get_authentic_metacontent_from_handler=
4886  get_one_virtual_pixel_from_handler=
4887  cache_info->methods.get_one_virtual_pixel_from_handler;
4888  if (get_one_virtual_pixel_from_handler !=
4890  cache_info->methods.get_one_virtual_pixel_from_handler=
4891  cache_methods->get_one_virtual_pixel_from_handler;
4892  get_one_authentic_pixel_from_handler=
4893  cache_methods->get_one_authentic_pixel_from_handler;
4894  if (get_one_authentic_pixel_from_handler !=
4896  cache_info->methods.get_one_authentic_pixel_from_handler=
4897  cache_methods->get_one_authentic_pixel_from_handler;
4898 }
4899 
4900 /*
4901 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4902 % %
4903 % %
4904 % %
4905 + S e t P i x e l C a c h e N e x u s P i x e l s %
4906 % %
4907 % %
4908 % %
4909 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4910 %
4911 % SetPixelCacheNexusPixels() defines the region of the cache for the
4912 % specified cache nexus.
4913 %
4914 % The format of the SetPixelCacheNexusPixels() method is:
4915 %
4916 % Quantum SetPixelCacheNexusPixels(const CacheInfo *cache_info,
4917 % const MapMode mode,const ssize_t x,const ssize_t y,const size_t width,
4918 % const size_t height,const MagickBooleanType buffered,
4919 % NexusInfo *nexus_info,ExceptionInfo *exception)
4920 %
4921 % A description of each parameter follows:
4922 %
4923 % o cache_info: the pixel cache.
4924 %
4925 % o mode: ReadMode, WriteMode, or IOMode.
4926 %
4927 % o x,y,width,height: define the region of this particular cache nexus.
4928 %
4929 % o buffered: if true, nexus pixels are buffered.
4930 %
4931 % o nexus_info: the cache nexus to set.
4932 %
4933 % o exception: return any errors or warnings in this structure.
4934 %
4935 */
4936 
4938  const CacheInfo *magick_restrict cache_info,const MagickSizeType length,
4939  NexusInfo *nexus_info,ExceptionInfo *exception)
4940 {
4941  if (length != (MagickSizeType) ((size_t) length))
4942  {
4943  (void) ThrowMagickException(exception,GetMagickModule(),
4944  ResourceLimitError,"PixelCacheAllocationFailed","`%s'",
4945  cache_info->filename);
4946  return(MagickFalse);
4947  }
4948  nexus_info->length=0;
4949  nexus_info->mapped=MagickFalse;
4950  if (cache_anonymous_memory <= 0)
4951  {
4953  (size_t) length));
4954  if (nexus_info->cache != (Quantum *) NULL)
4955  (void) memset(nexus_info->cache,0,(size_t) length);
4956  }
4957  else
4958  {
4959  nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(size_t) length);
4960  if (nexus_info->cache != (Quantum *) NULL)
4961  nexus_info->mapped=MagickTrue;
4962  }
4963  if (nexus_info->cache == (Quantum *) NULL)
4964  {
4965  (void) ThrowMagickException(exception,GetMagickModule(),
4966  ResourceLimitError,"PixelCacheAllocationFailed","`%s'",
4967  cache_info->filename);
4968  return(MagickFalse);
4969  }
4970  nexus_info->length=length;
4971  return(MagickTrue);
4972 }
4973 
4974 static inline void PrefetchPixelCacheNexusPixels(const NexusInfo *nexus_info,
4975  const MapMode mode)
4976 {
4977  if (nexus_info->length < CACHE_LINE_SIZE)
4978  return;
4979  if (mode == ReadMode)
4980  {
4981  MagickCachePrefetch((unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,
4982  0,1);
4983  return;
4984  }
4985  MagickCachePrefetch((unsigned char *) nexus_info->pixels+CACHE_LINE_SIZE,1,1);
4986 }
4987 
4988 static Quantum *SetPixelCacheNexusPixels(const CacheInfo *cache_info,
4989  const MapMode mode,const ssize_t x,const ssize_t y,const size_t width,
4990  const size_t height,const MagickBooleanType buffered,NexusInfo *nexus_info,
4991  ExceptionInfo *exception)
4992 {
4994  status;
4995 
4997  length,
4998  number_pixels;
4999 
5000  assert(cache_info != (const CacheInfo *) NULL);
5001  assert(cache_info->signature == MagickCoreSignature);
5002  if (cache_info->type == UndefinedCache)
5003  return((Quantum *) NULL);
5004  (void) memset(&nexus_info->region,0,sizeof(nexus_info->region));
5005  if ((width == 0) || (height == 0))
5006  {
5007  (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
5008  "NoPixelsDefinedInCache","`%s'",cache_info->filename);
5009  return((Quantum *) NULL);
5010  }
5011  assert(nexus_info->signature == MagickCoreSignature);
5012  if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5013  (buffered == MagickFalse))
5014  {
5015  if (((x >= 0) && (y >= 0) &&
5016  (((ssize_t) height+y-1) < (ssize_t) cache_info->rows)) &&
5017  (((x == 0) && (width == cache_info->columns)) || ((height == 1) &&
5018  (((ssize_t) width+x-1) < (ssize_t) cache_info->columns))))
5019  {
5021  offset;
5022 
5023  /*
5024  Pixels are accessed directly from memory.
5025  */
5026  offset=(MagickOffsetType) y*cache_info->columns+x;
5027  nexus_info->pixels=cache_info->pixels+cache_info->number_channels*
5028  offset;
5029  nexus_info->metacontent=(void *) NULL;
5030  if (cache_info->metacontent_extent != 0)
5031  nexus_info->metacontent=(unsigned char *) cache_info->metacontent+
5032  offset*cache_info->metacontent_extent;
5033  nexus_info->region.width=width;
5034  nexus_info->region.height=height;
5035  nexus_info->region.x=x;
5036  nexus_info->region.y=y;
5037  nexus_info->authentic_pixel_cache=MagickTrue;
5038  PrefetchPixelCacheNexusPixels(nexus_info,mode);
5039  return(nexus_info->pixels);
5040  }
5041  }
5042  /*
5043  Pixels are stored in a staging region until they are synced to the cache.
5044  */
5045  if (((MagickSizeType) width > cache_info->width_limit) ||
5046  ((MagickSizeType) height > cache_info->height_limit))
5047  {
5048  (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
5049  "WidthOrHeightExceedsLimit","`%s'",cache_info->filename);
5050  return((Quantum *) NULL);
5051  }
5052  number_pixels=(MagickSizeType) width*height;
5053  length=MagickMax(number_pixels,cache_info->columns)*
5054  cache_info->number_channels*sizeof(*nexus_info->pixels);
5055  if (cache_info->metacontent_extent != 0)
5056  length+=number_pixels*cache_info->metacontent_extent;
5057  status=MagickTrue;
5058  if (nexus_info->cache == (Quantum *) NULL)
5059  status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5060  else
5061  if (nexus_info->length < length)
5062  {
5063  RelinquishCacheNexusPixels(nexus_info);
5064  status=AcquireCacheNexusPixels(cache_info,length,nexus_info,exception);
5065  }
5066  if (status == MagickFalse)
5067  return((Quantum *) NULL);
5068  nexus_info->pixels=nexus_info->cache;
5069  nexus_info->metacontent=(void *) NULL;
5070  if (cache_info->metacontent_extent != 0)
5071  nexus_info->metacontent=(void *) (nexus_info->pixels+
5072  cache_info->number_channels*number_pixels);
5073  nexus_info->region.width=width;
5074  nexus_info->region.height=height;
5075  nexus_info->region.x=x;
5076  nexus_info->region.y=y;
5077  nexus_info->authentic_pixel_cache=cache_info->type == PingCache ?
5079  PrefetchPixelCacheNexusPixels(nexus_info,mode);
5080  return(nexus_info->pixels);
5081 }
5082 
5083 /*
5084 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5085 % %
5086 % %
5087 % %
5088 % S e t P i x e l C a c h e V i r t u a l M e t h o d %
5089 % %
5090 % %
5091 % %
5092 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5093 %
5094 % SetPixelCacheVirtualMethod() sets the "virtual pixels" method for the
5095 % pixel cache and returns the previous setting. A virtual pixel is any pixel
5096 % access that is outside the boundaries of the image cache.
5097 %
5098 % The format of the SetPixelCacheVirtualMethod() method is:
5099 %
5100 % VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
5101 % const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
5102 %
5103 % A description of each parameter follows:
5104 %
5105 % o image: the image.
5106 %
5107 % o virtual_pixel_method: choose the type of virtual pixel.
5108 %
5109 % o exception: return any errors or warnings in this structure.
5110 %
5111 */
5112 
5114  ExceptionInfo *exception)
5115 {
5116  CacheInfo
5117  *magick_restrict cache_info;
5118 
5119  CacheView
5120  *magick_restrict image_view;
5121 
5123  status;
5124 
5125  ssize_t
5126  y;
5127 
5128  assert(image != (Image *) NULL);
5129  assert(image->signature == MagickCoreSignature);
5130  if (image->debug != MagickFalse)
5131  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5132  assert(image->cache != (Cache) NULL);
5133  cache_info=(CacheInfo *) image->cache;
5134  assert(cache_info->signature == MagickCoreSignature);
5136  status=MagickTrue;
5137  image_view=AcquireVirtualCacheView(image,exception); /* must be virtual */
5138 #if defined(MAGICKCORE_OPENMP_SUPPORT)
5139  #pragma omp parallel for schedule(static) shared(status) \
5140  magick_number_threads(image,image,image->rows,1)
5141 #endif
5142  for (y=0; y < (ssize_t) image->rows; y++)
5143  {
5144  register Quantum
5145  *magick_restrict q;
5146 
5147  register ssize_t
5148  x;
5149 
5150  if (status == MagickFalse)
5151  continue;
5152  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5153  if (q == (Quantum *) NULL)
5154  {
5155  status=MagickFalse;
5156  continue;
5157  }
5158  for (x=0; x < (ssize_t) image->columns; x++)
5159  {
5160  SetPixelAlpha(image,alpha,q);
5161  q+=GetPixelChannels(image);
5162  }
5163  status=SyncCacheViewAuthenticPixels(image_view,exception);
5164  }
5165  image_view=DestroyCacheView(image_view);
5166  return(status);
5167 }
5168 
5170  const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
5171 {
5172  CacheInfo
5173  *magick_restrict cache_info;
5174 
5176  method;
5177 
5178  assert(image != (Image *) NULL);
5179  assert(image->signature == MagickCoreSignature);
5180  if (image->debug != MagickFalse)
5181  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5182  assert(image->cache != (Cache) NULL);
5183  cache_info=(CacheInfo *) image->cache;
5184  assert(cache_info->signature == MagickCoreSignature);
5185  method=cache_info->virtual_pixel_method;
5186  cache_info->virtual_pixel_method=virtual_pixel_method;
5187  if ((image->columns != 0) && (image->rows != 0))
5188  switch (virtual_pixel_method)
5189  {
5191  {
5193  (image->alpha_trait == UndefinedPixelTrait))
5194  (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5195  if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5197  (void) SetImageColorspace(image,sRGBColorspace,exception);
5198  break;
5199  }
5201  {
5202  if (image->alpha_trait == UndefinedPixelTrait)
5203  (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5204  break;
5205  }
5206  default:
5207  break;
5208  }
5209  return(method);
5210 }
5211 
5212 #if defined(MAGICKCORE_OPENCL_SUPPORT)
5213 /*
5214 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5215 % %
5216 % %
5217 % %
5218 + S y n c A u t h e n t i c O p e n C L B u f f e r %
5219 % %
5220 % %
5221 % %
5222 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5223 %
5224 % SyncAuthenticOpenCLBuffer() makes sure that all the OpenCL operations have
5225 % been completed and updates the host memory.
5226 %
5227 % The format of the SyncAuthenticOpenCLBuffer() method is:
5228 %
5229 % void SyncAuthenticOpenCLBuffer(const Image *image)
5230 %
5231 % A description of each parameter follows:
5232 %
5233 % o image: the image.
5234 %
5235 */
5236 
5237 static void CopyOpenCLBuffer(CacheInfo *magick_restrict cache_info)
5238 {
5239  assert(cache_info != (CacheInfo *) NULL);
5240  assert(cache_info->signature == MagickCoreSignature);
5241  if ((cache_info->type != MemoryCache) ||
5242  (cache_info->opencl == (MagickCLCacheInfo) NULL))
5243  return;
5244  /*
5245  Ensure single threaded access to OpenCL environment.
5246  */
5247  LockSemaphoreInfo(cache_info->semaphore);
5248  cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5249  UnlockSemaphoreInfo(cache_info->semaphore);
5250 }
5251 
5252 MagickPrivate void SyncAuthenticOpenCLBuffer(const Image *image)
5253 {
5254  CacheInfo
5255  *magick_restrict cache_info;
5256 
5257  assert(image != (const Image *) NULL);
5258  cache_info=(CacheInfo *) image->cache;
5259  CopyOpenCLBuffer(cache_info);
5260 }
5261 #endif
5262 
5263 /*
5264 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5265 % %
5266 % %
5267 % %
5268 + S y n c A u t h e n t i c P i x e l C a c h e N e x u s %
5269 % %
5270 % %
5271 % %
5272 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5273 %
5274 % SyncAuthenticPixelCacheNexus() saves the authentic image pixels to the
5275 % in-memory or disk cache. The method returns MagickTrue if the pixel region
5276 % is synced, otherwise MagickFalse.
5277 %
5278 % The format of the SyncAuthenticPixelCacheNexus() method is:
5279 %
5280 % MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5281 % NexusInfo *nexus_info,ExceptionInfo *exception)
5282 %
5283 % A description of each parameter follows:
5284 %
5285 % o image: the image.
5286 %
5287 % o nexus_info: the cache nexus to sync.
5288 %
5289 % o exception: return any errors or warnings in this structure.
5290 %
5291 */
5293  NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5294 {
5295  CacheInfo
5296  *magick_restrict cache_info;
5297 
5299  status;
5300 
5301  /*
5302  Transfer pixels to the cache.
5303  */
5304  assert(image != (Image *) NULL);
5305  assert(image->signature == MagickCoreSignature);
5306  if (image->cache == (Cache) NULL)
5307  ThrowBinaryException(CacheError,"PixelCacheIsNotOpen",image->filename);
5308  cache_info=(CacheInfo *) image->cache;
5309  assert(cache_info->signature == MagickCoreSignature);
5310  if (cache_info->type == UndefinedCache)
5311  return(MagickFalse);
5312  if (image->mask_trait != UpdatePixelTrait)
5313  {
5314  if (((image->channels & WriteMaskChannel) != 0) &&
5315  (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5316  return(MagickFalse);
5317  if (((image->channels & CompositeMaskChannel) != 0) &&
5318  (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5319  return(MagickFalse);
5320  }
5321  if (nexus_info->authentic_pixel_cache != MagickFalse)
5322  {
5323  image->taint=MagickTrue;
5324  return(MagickTrue);
5325  }
5326  assert(cache_info->signature == MagickCoreSignature);
5327  status=WritePixelCachePixels(cache_info,nexus_info,exception);
5328  if ((cache_info->metacontent_extent != 0) &&
5329  (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5330  return(MagickFalse);
5331  if (status != MagickFalse)
5332  image->taint=MagickTrue;
5333  return(status);
5334 }
5335 
5336 /*
5337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5338 % %
5339 % %
5340 % %
5341 + S y n c A u t h e n t i c P i x e l C a c h e %
5342 % %
5343 % %
5344 % %
5345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5346 %
5347 % SyncAuthenticPixelsCache() saves the authentic image pixels to the in-memory
5348 % or disk cache. The method returns MagickTrue if the pixel region is synced,
5349 % otherwise MagickFalse.
5350 %
5351 % The format of the SyncAuthenticPixelsCache() method is:
5352 %
5353 % MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5354 % ExceptionInfo *exception)
5355 %
5356 % A description of each parameter follows:
5357 %
5358 % o image: the image.
5359 %
5360 % o exception: return any errors or warnings in this structure.
5361 %
5362 */
5364  ExceptionInfo *exception)
5365 {
5366  CacheInfo
5367  *magick_restrict cache_info;
5368 
5369  const int
5370  id = GetOpenMPThreadId();
5371 
5373  status;
5374 
5375  assert(image != (Image *) NULL);
5376  assert(image->signature == MagickCoreSignature);
5377  assert(image->cache != (Cache) NULL);
5378  cache_info=(CacheInfo *) image->cache;
5379  assert(cache_info->signature == MagickCoreSignature);
5380  assert(id < (int) cache_info->number_threads);
5381  status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5382  exception);
5383  return(status);
5384 }
5385 
5386 /*
5387 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5388 % %
5389 % %
5390 % %
5391 % S y n c A u t h e n t i c P i x e l s %
5392 % %
5393 % %
5394 % %
5395 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5396 %
5397 % SyncAuthenticPixels() saves the image pixels to the in-memory or disk cache.
5398 % The method returns MagickTrue if the pixel region is flushed, otherwise
5399 % MagickFalse.
5400 %
5401 % The format of the SyncAuthenticPixels() method is:
5402 %
5403 % MagickBooleanType SyncAuthenticPixels(Image *image,
5404 % ExceptionInfo *exception)
5405 %
5406 % A description of each parameter follows:
5407 %
5408 % o image: the image.
5409 %
5410 % o exception: return any errors or warnings in this structure.
5411 %
5412 */
5414  ExceptionInfo *exception)
5415 {
5416  CacheInfo
5417  *magick_restrict cache_info;
5418 
5419  const int
5420  id = GetOpenMPThreadId();
5421 
5423  status;
5424 
5425  assert(image != (Image *) NULL);
5426  assert(image->signature == MagickCoreSignature);
5427  assert(image->cache != (Cache) NULL);
5428  cache_info=(CacheInfo *) image->cache;
5429  assert(cache_info->signature == MagickCoreSignature);
5430  if (cache_info->methods.sync_authentic_pixels_handler != (SyncAuthenticPixelsHandler) NULL)
5431  {
5432  status=cache_info->methods.sync_authentic_pixels_handler(image,
5433  exception);
5434  return(status);
5435  }
5436  assert(id < (int) cache_info->number_threads);
5437  status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5438  exception);
5439  return(status);
5440 }
5441 
5442 /*
5443 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5444 % %
5445 % %
5446 % %
5447 + S y n c I m a g e P i x e l C a c h e %
5448 % %
5449 % %
5450 % %
5451 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5452 %
5453 % SyncImagePixelCache() saves the image pixels to the in-memory or disk cache.
5454 % The method returns MagickTrue if the pixel region is flushed, otherwise
5455 % MagickFalse.
5456 %
5457 % The format of the SyncImagePixelCache() method is:
5458 %
5459 % MagickBooleanType SyncImagePixelCache(Image *image,
5460 % ExceptionInfo *exception)
5461 %
5462 % A description of each parameter follows:
5463 %
5464 % o image: the image.
5465 %
5466 % o exception: return any errors or warnings in this structure.
5467 %
5468 */
5470  ExceptionInfo *exception)
5471 {
5472  CacheInfo
5473  *magick_restrict cache_info;
5474 
5475  assert(image != (Image *) NULL);
5476  assert(exception != (ExceptionInfo *) NULL);
5477  cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5478  return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5479 }
5480 
5481 /*
5482 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5483 % %
5484 % %
5485 % %
5486 + W r i t e P i x e l C a c h e M e t a c o n t e n t %
5487 % %
5488 % %
5489 % %
5490 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5491 %
5492 % WritePixelCacheMetacontent() writes the meta-content to the specified region
5493 % of the pixel cache.
5494 %
5495 % The format of the WritePixelCacheMetacontent() method is:
5496 %
5497 % MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5498 % NexusInfo *nexus_info,ExceptionInfo *exception)
5499 %
5500 % A description of each parameter follows:
5501 %
5502 % o cache_info: the pixel cache.
5503 %
5504 % o nexus_info: the cache nexus to write the meta-content.
5505 %
5506 % o exception: return any errors or warnings in this structure.
5507 %
5508 */
5510  NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5511 {
5513  count,
5514  offset;
5515 
5517  extent,
5518  length;
5519 
5520  register const unsigned char
5521  *magick_restrict p;
5522 
5523  register ssize_t
5524  y;
5525 
5526  size_t
5527  rows;
5528 
5529  if (cache_info->metacontent_extent == 0)
5530  return(MagickFalse);
5531  if (nexus_info->authentic_pixel_cache != MagickFalse)
5532  return(MagickTrue);
5533  offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5534  nexus_info->region.x;
5535  length=(MagickSizeType) nexus_info->region.width*
5536  cache_info->metacontent_extent;
5537  extent=(MagickSizeType) length*nexus_info->region.height;
5538  rows=nexus_info->region.height;
5539  y=0;
5540  p=(unsigned char *) nexus_info->metacontent;
5541  switch (cache_info->type)
5542  {
5543  case MemoryCache:
5544  case MapCache:
5545  {
5546  register unsigned char
5547  *magick_restrict q;
5548 
5549  /*
5550  Write associated pixels to memory.
5551  */
5552  if ((cache_info->columns == nexus_info->region.width) &&
5553  (extent == (MagickSizeType) ((size_t) extent)))
5554  {
5555  length=extent;
5556  rows=1UL;
5557  }
5558  q=(unsigned char *) cache_info->metacontent+offset*
5559  cache_info->metacontent_extent;
5560  for (y=0; y < (ssize_t) rows; y++)
5561  {
5562  (void) memcpy(q,p,(size_t) length);
5563  p+=nexus_info->region.width*cache_info->metacontent_extent;
5564  q+=cache_info->columns*cache_info->metacontent_extent;
5565  }
5566  break;
5567  }
5568  case DiskCache:
5569  {
5570  /*
5571  Write associated pixels to disk.
5572  */
5573  LockSemaphoreInfo(cache_info->file_semaphore);
5574  if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5575  {
5576  ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5577  cache_info->cache_filename);
5578  UnlockSemaphoreInfo(cache_info->file_semaphore);
5579  return(MagickFalse);
5580  }
5581  if ((cache_info->columns == nexus_info->region.width) &&
5582  (extent <= MagickMaxBufferExtent))
5583  {
5584  length=extent;
5585  rows=1UL;
5586  }
5587  extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5588  for (y=0; y < (ssize_t) rows; y++)
5589  {
5590  count=WritePixelCacheRegion(cache_info,cache_info->offset+extent*
5591  cache_info->number_channels*sizeof(Quantum)+offset*
5592  cache_info->metacontent_extent,length,(const unsigned char *) p);
5593  if (count != (MagickOffsetType) length)
5594  break;
5595  p+=cache_info->metacontent_extent*nexus_info->region.width;
5596  offset+=cache_info->columns;
5597  }
5599  (void) ClosePixelCacheOnDisk(cache_info);
5600  UnlockSemaphoreInfo(cache_info->file_semaphore);
5601  break;
5602  }
5603  case DistributedCache:
5604  {
5606  region;
5607 
5608  /*
5609  Write metacontent to distributed cache.
5610  */
5611  LockSemaphoreInfo(cache_info->file_semaphore);
5612  region=nexus_info->region;
5613  if ((cache_info->columns != nexus_info->region.width) ||
5614  (extent > MagickMaxBufferExtent))
5615  region.height=1UL;
5616  else
5617  {
5618  length=extent;
5619  rows=1UL;
5620  }
5621  for (y=0; y < (ssize_t) rows; y++)
5622  {
5624  cache_info->server_info,&region,length,(const unsigned char *) p);
5625  if (count != (MagickOffsetType) length)
5626  break;
5627  p+=cache_info->metacontent_extent*nexus_info->region.width;
5628  region.y++;
5629  }
5630  UnlockSemaphoreInfo(cache_info->file_semaphore);
5631  break;
5632  }
5633  default:
5634  break;
5635  }
5636  if (y < (ssize_t) rows)
5637  {
5638  ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5639  cache_info->cache_filename);
5640  return(MagickFalse);
5641  }
5642  if ((cache_info->debug != MagickFalse) &&
5643  (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5645  "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5646  nexus_info->region.width,(double) nexus_info->region.height,(double)
5647  nexus_info->region.x,(double) nexus_info->region.y);
5648  return(MagickTrue);
5649 }
5650 
5651 /*
5652 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5653 % %
5654 % %
5655 % %
5656 + W r i t e C a c h e P i x e l s %
5657 % %
5658 % %
5659 % %
5660 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5661 %
5662 % WritePixelCachePixels() writes image pixels to the specified region of the
5663 % pixel cache.
5664 %
5665 % The format of the WritePixelCachePixels() method is:
5666 %
5667 % MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5668 % NexusInfo *nexus_info,ExceptionInfo *exception)
5669 %
5670 % A description of each parameter follows:
5671 %
5672 % o cache_info: the pixel cache.
5673 %
5674 % o nexus_info: the cache nexus to write the pixels.
5675 %
5676 % o exception: return any errors or warnings in this structure.
5677 %
5678 */
5680  CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
5681  ExceptionInfo *exception)
5682 {
5684  count,
5685  offset;
5686 
5688  extent,
5689  length;
5690 
5691  register const Quantum
5692  *magick_restrict p;
5693 
5694  register ssize_t
5695  y;
5696 
5697  size_t
5698  rows;
5699 
5700  if (nexus_info->authentic_pixel_cache != MagickFalse)
5701  return(MagickTrue);
5702  offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5703  nexus_info->region.x;
5704  length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5705  sizeof(Quantum);
5706  extent=length*nexus_info->region.height;
5707  rows=nexus_info->region.height;
5708  y=0;
5709  p=nexus_info->pixels;
5710  switch (cache_info->type)
5711  {
5712  case MemoryCache:
5713  case MapCache:
5714  {
5715  register Quantum
5716  *magick_restrict q;
5717 
5718  /*
5719  Write pixels to memory.
5720  */
5721  if ((cache_info->columns == nexus_info->region.width) &&
5722  (extent == (MagickSizeType) ((size_t) extent)))
5723  {
5724  length=extent;
5725  rows=1UL;
5726  }
5727  q=cache_info->pixels+cache_info->number_channels*offset;
5728  for (y=0; y < (ssize_t) rows; y++)
5729  {
5730  (void) memcpy(q,p,(size_t) length);
5731  p+=cache_info->number_channels*nexus_info->region.width;
5732  q+=cache_info->number_channels*cache_info->columns;
5733  }
5734  break;
5735  }
5736  case DiskCache:
5737  {
5738  /*
5739  Write pixels to disk.
5740  */
5741  LockSemaphoreInfo(cache_info->file_semaphore);
5742  if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5743  {
5744  ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5745  cache_info->cache_filename);
5746  UnlockSemaphoreInfo(cache_info->file_semaphore);
5747  return(MagickFalse);
5748  }
5749  if ((cache_info->columns == nexus_info->region.width) &&
5750  (extent <= MagickMaxBufferExtent))
5751  {
5752  length=extent;
5753  rows=1UL;
5754  }
5755  for (y=0; y < (ssize_t) rows; y++)
5756  {
5757  count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5758  cache_info->number_channels*sizeof(*p),length,(const unsigned char *)
5759  p);
5760  if (count != (MagickOffsetType) length)
5761  break;
5762  p+=cache_info->number_channels*nexus_info->region.width;
5763  offset+=cache_info->columns;
5764  }
5766  (void) ClosePixelCacheOnDisk(cache_info);
5767  UnlockSemaphoreInfo(cache_info->file_semaphore);
5768  break;
5769  }
5770  case DistributedCache:
5771  {