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