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