MagickCore  7.0.8
Convert, Edit, Or Compose Bitmap Images
cache.c
Go to the documentation of this file.
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % CCCC AAA CCCC H H EEEEE %
7 % C A A C H H E %
8 % C AAAAA C HHHHH EEE %
9 % C A A C H H E %
10 % CCCC A A CCCC H H EEEEE %
11 % %
12 % %
13 % MagickCore Pixel Cache Methods %
14 % %
15 % Software Design %
16 % Cristy %
17 % July 1999 %
18 % %
19 % %
20 % Copyright 1999-2018 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
22 % %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
25 % %
26 % https://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 *) AcquireCriticalMemory(sizeof(*cache_info));
194  (void) memset(cache_info,0,sizeof(*cache_info));
195  cache_info->type=UndefinedCache;
196  cache_info->mode=IOMode;
197  cache_info->disk_mode=IOMode;
198  cache_info->colorspace=sRGBColorspace;
199  cache_info->file=(-1);
200  cache_info->id=GetMagickThreadId();
201  cache_info->number_threads=number_threads;
202  if (GetOpenMPMaximumThreads() > cache_info->number_threads)
203  cache_info->number_threads=GetOpenMPMaximumThreads();
204  if (GetMagickResourceLimit(ThreadResource) > cache_info->number_threads)
205  cache_info->number_threads=(size_t) GetMagickResourceLimit(ThreadResource);
206  if (cache_info->number_threads == 0)
207  cache_info->number_threads=1;
208  cache_info->nexus_info=AcquirePixelCacheNexus(cache_info->number_threads);
209  if (cache_info->nexus_info == (NexusInfo **) NULL)
210  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
211  value=GetEnvironmentValue("MAGICK_SYNCHRONIZE");
212  if (value != (const char *) NULL)
213  {
214  cache_info->synchronize=IsStringTrue(value);
215  value=DestroyString(value);
216  }
217  value=GetPolicyValue("cache:synchronize");
218  if (value != (const char *) NULL)
219  {
220  cache_info->synchronize=IsStringTrue(value);
221  value=DestroyString(value);
222  }
223  cache_info->semaphore=AcquireSemaphoreInfo();
224  cache_info->reference_count=1;
225  cache_info->file_semaphore=AcquireSemaphoreInfo();
226  cache_info->debug=IsEventLogging();
227  cache_info->signature=MagickCoreSignature;
228  return((Cache ) cache_info);
229 }
230 
231 /*
232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
233 % %
234 % %
235 % %
236 % A c q u i r e P i x e l C a c h e N e x u s %
237 % %
238 % %
239 % %
240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
241 %
242 % AcquirePixelCacheNexus() allocates the NexusInfo structure.
243 %
244 % The format of the AcquirePixelCacheNexus method is:
245 %
246 % NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
247 %
248 % A description of each parameter follows:
249 %
250 % o number_threads: the number of nexus threads.
251 %
252 */
253 MagickPrivate NexusInfo **AcquirePixelCacheNexus(const size_t number_threads)
254 {
255  NexusInfo
256  **magick_restrict nexus_info;
257 
258  register ssize_t
259  i;
260 
262  number_threads,sizeof(*nexus_info)));
263  if (nexus_info == (NexusInfo **) NULL)
264  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
265  nexus_info[0]=(NexusInfo *) AcquireQuantumMemory(number_threads,
266  sizeof(**nexus_info));
267  if (nexus_info[0] == (NexusInfo *) NULL)
268  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
269  (void) memset(nexus_info[0],0,number_threads*sizeof(**nexus_info));
270  for (i=0; i < (ssize_t) number_threads; i++)
271  {
272  nexus_info[i]=(&nexus_info[0][i]);
273  nexus_info[i]->signature=MagickCoreSignature;
274  }
275  return(nexus_info);
276 }
277 
278 /*
279 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
280 % %
281 % %
282 % %
283 % A c q u i r e P i x e l C a c h e P i x e l s %
284 % %
285 % %
286 % %
287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
288 %
289 % AcquirePixelCachePixels() returns the pixels associated with the specified
290 % image.
291 %
292 % The format of the AcquirePixelCachePixels() method is:
293 %
294 % void *AcquirePixelCachePixels(const Image *image,size_t *length,
295 % ExceptionInfo *exception)
296 %
297 % A description of each parameter follows:
298 %
299 % o image: the image.
300 %
301 % o length: the pixel cache length.
302 %
303 % o exception: return any errors or warnings in this structure.
304 %
305 */
306 MagickExport void *AcquirePixelCachePixels(const Image *image,size_t *length,
307  ExceptionInfo *exception)
308 {
309  CacheInfo
310  *magick_restrict cache_info;
311 
312  assert(image != (const Image *) NULL);
313  assert(image->signature == MagickCoreSignature);
314  assert(exception != (ExceptionInfo *) NULL);
315  assert(exception->signature == MagickCoreSignature);
316  assert(image->cache != (Cache) NULL);
317  cache_info=(CacheInfo *) image->cache;
318  assert(cache_info->signature == MagickCoreSignature);
319  *length=0;
320  if ((cache_info->type != MemoryCache) && (cache_info->type != MapCache))
321  return((void *) NULL);
322  *length=(size_t) cache_info->length;
323  return(cache_info->pixels);
324 }
325 
326 /*
327 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
328 % %
329 % %
330 % %
331 + C a c h e C o m p o n e n t G e n e s i s %
332 % %
333 % %
334 % %
335 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
336 %
337 % CacheComponentGenesis() instantiates the cache component.
338 %
339 % The format of the CacheComponentGenesis method is:
340 %
341 % MagickBooleanType CacheComponentGenesis(void)
342 %
343 */
345 {
346  if (cache_semaphore == (SemaphoreInfo *) NULL)
347  cache_semaphore=AcquireSemaphoreInfo();
348  return(MagickTrue);
349 }
350 
351 /*
352 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353 % %
354 % %
355 % %
356 + C a c h e C o m p o n e n t T e r m i n u s %
357 % %
358 % %
359 % %
360 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
361 %
362 % CacheComponentTerminus() destroys the cache component.
363 %
364 % The format of the CacheComponentTerminus() method is:
365 %
366 % CacheComponentTerminus(void)
367 %
368 */
370 {
371  if (cache_semaphore == (SemaphoreInfo *) NULL)
372  ActivateSemaphoreInfo(&cache_semaphore);
373  /* no op-- nothing to destroy */
374  RelinquishSemaphoreInfo(&cache_semaphore);
375 }
376 
377 /*
378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
379 % %
380 % %
381 % %
382 + C l i p P i x e l C a c h e N e x u s %
383 % %
384 % %
385 % %
386 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
387 %
388 % ClipPixelCacheNexus() clips the cache nexus as defined by the image clip
389 % mask. The method returns MagickTrue if the pixel region is clipped,
390 % otherwise MagickFalse.
391 %
392 % The format of the ClipPixelCacheNexus() method is:
393 %
394 % MagickBooleanType ClipPixelCacheNexus(Image *image,NexusInfo *nexus_info,
395 % ExceptionInfo *exception)
396 %
397 % A description of each parameter follows:
398 %
399 % o image: the image.
400 %
401 % o nexus_info: the cache nexus to clip.
402 %
403 % o exception: return any errors or warnings in this structure.
404 %
405 */
407  NexusInfo *nexus_info,ExceptionInfo *exception)
408 {
409  CacheInfo
410  *magick_restrict cache_info;
411 
413  number_pixels;
414 
415  NexusInfo
416  **magick_restrict image_nexus;
417 
418  register Quantum
419  *magick_restrict p,
420  *magick_restrict q;
421 
422  register ssize_t
423  n;
424 
425  /*
426  Apply clip mask.
427  */
428  if (image->debug != MagickFalse)
429  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
430  if ((image->channels & WriteMaskChannel) == 0)
431  return(MagickTrue);
432  cache_info=(CacheInfo *) image->cache;
433  if (cache_info == (Cache) NULL)
434  return(MagickFalse);
435  image_nexus=AcquirePixelCacheNexus(1);
436  p=GetAuthenticPixelCacheNexus(image,nexus_info->region.x,nexus_info->region.y,
437  nexus_info->region.width,nexus_info->region.height,image_nexus[0],
438  exception);
439  q=nexus_info->pixels;
440  number_pixels=(MagickSizeType) nexus_info->region.width*
441  nexus_info->region.height;
442  for (n=0; n < (ssize_t) number_pixels; n++)
443  {
444  double
445  mask_alpha;
446 
447  register ssize_t
448  i;
449 
450  if (p == (Quantum *) NULL)
451  break;
452  mask_alpha=QuantumScale*GetPixelWriteMask(image,p);
453  if (fabs(mask_alpha) >= MagickEpsilon)
454  {
455  for (i=0; i < (ssize_t) image->number_channels; i++)
456  {
457  PixelChannel channel = GetPixelChannelChannel(image,i);
458  PixelTrait traits = GetPixelChannelTraits(image,channel);
459  if ((traits & UpdatePixelTrait) == 0)
460  continue;
461  q[i]=ClampToQuantum(MagickOver_((double) p[i],mask_alpha*
462  GetPixelAlpha(image,p),(double) q[i],(double)
463  GetPixelAlpha(image,q)));
464  }
465  SetPixelAlpha(image,GetPixelAlpha(image,p),q);
466  }
467  p+=GetPixelChannels(image);
468  q+=GetPixelChannels(image);
469  }
470  image_nexus=DestroyPixelCacheNexus(image_nexus,1);
471  if (n < (ssize_t) number_pixels)
472  return(MagickFalse);
473  return(MagickTrue);
474 }
475 
476 /*
477 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
478 % %
479 % %
480 % %
481 + C l o n e P i x e l C a c h e %
482 % %
483 % %
484 % %
485 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
486 %
487 % ClonePixelCache() clones a pixel cache.
488 %
489 % The format of the ClonePixelCache() method is:
490 %
491 % Cache ClonePixelCache(const Cache cache)
492 %
493 % A description of each parameter follows:
494 %
495 % o cache: the pixel cache.
496 %
497 */
499 {
500  CacheInfo
501  *magick_restrict clone_info;
502 
503  const CacheInfo
504  *magick_restrict cache_info;
505 
506  assert(cache != NULL);
507  cache_info=(const CacheInfo *) cache;
508  assert(cache_info->signature == MagickCoreSignature);
509  if (cache_info->debug != MagickFalse)
511  cache_info->filename);
512  clone_info=(CacheInfo *) AcquirePixelCache(cache_info->number_threads);
513  clone_info->virtual_pixel_method=cache_info->virtual_pixel_method;
514  return((Cache ) clone_info);
515 }
516 
517 /*
518 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
519 % %
520 % %
521 % %
522 + C l o n e P i x e l C a c h e M e t h o d s %
523 % %
524 % %
525 % %
526 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
527 %
528 % ClonePixelCacheMethods() clones the pixel cache methods from one cache to
529 % another.
530 %
531 % The format of the ClonePixelCacheMethods() method is:
532 %
533 % void ClonePixelCacheMethods(Cache clone,const Cache cache)
534 %
535 % A description of each parameter follows:
536 %
537 % o clone: Specifies a pointer to a Cache structure.
538 %
539 % o cache: the pixel cache.
540 %
541 */
543 {
544  CacheInfo
545  *magick_restrict cache_info,
546  *magick_restrict source_info;
547 
548  assert(clone != (Cache) NULL);
549  source_info=(CacheInfo *) clone;
550  assert(source_info->signature == MagickCoreSignature);
551  if (source_info->debug != MagickFalse)
553  source_info->filename);
554  assert(cache != (Cache) NULL);
555  cache_info=(CacheInfo *) cache;
556  assert(cache_info->signature == MagickCoreSignature);
557  source_info->methods=cache_info->methods;
558 }
559 
560 /*
561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
562 % %
563 % %
564 % %
565 + C l o n e P i x e l C a c h e R e p o s i t o r y %
566 % %
567 % %
568 % %
569 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
570 %
571 % ClonePixelCacheRepository() clones the source pixel cache to the destination
572 % cache.
573 %
574 % The format of the ClonePixelCacheRepository() method is:
575 %
576 % MagickBooleanType ClonePixelCacheRepository(CacheInfo *cache_info,
577 % CacheInfo *source_info,ExceptionInfo *exception)
578 %
579 % A description of each parameter follows:
580 %
581 % o cache_info: the pixel cache.
582 %
583 % o source_info: the source pixel cache.
584 %
585 % o exception: return any errors or warnings in this structure.
586 %
587 */
588 
590  CacheInfo *magick_restrict cache_info,CacheInfo *magick_restrict clone_info)
591 {
593  extent;
594 
595  size_t
596  quantum;
597 
598  ssize_t
599  count;
600 
601  struct stat
602  file_stats;
603 
604  unsigned char
605  *buffer;
606 
607  /*
608  Clone pixel cache on disk with identical morphology.
609  */
610  if ((OpenPixelCacheOnDisk(cache_info,ReadMode) == MagickFalse) ||
611  (OpenPixelCacheOnDisk(clone_info,IOMode) == MagickFalse))
612  return(MagickFalse);
613  if ((lseek(cache_info->file,0,SEEK_SET) < 0) ||
614  (lseek(clone_info->file,0,SEEK_SET) < 0))
615  return(MagickFalse);
616  quantum=(size_t) MagickMaxBufferExtent;
617  if ((fstat(cache_info->file,&file_stats) == 0) && (file_stats.st_size > 0))
618  quantum=(size_t) MagickMin(file_stats.st_size,MagickMaxBufferExtent);
619  buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
620  if (buffer == (unsigned char *) NULL)
621  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
622  extent=0;
623  while ((count=read(cache_info->file,buffer,quantum)) > 0)
624  {
625  ssize_t
626  number_bytes;
627 
628  number_bytes=write(clone_info->file,buffer,(size_t) count);
629  if (number_bytes != count)
630  break;
631  extent+=number_bytes;
632  }
633  buffer=(unsigned char *) RelinquishMagickMemory(buffer);
634  if (extent != cache_info->length)
635  return(MagickFalse);
636  return(MagickTrue);
637 }
638 
640  CacheInfo *magick_restrict clone_info,CacheInfo *magick_restrict cache_info,
641  ExceptionInfo *exception)
642 {
643 #define MaxCacheThreads ((size_t) GetMagickResourceLimit(ThreadResource))
644 #define cache_number_threads(source,destination,chunk,multithreaded) \
645  num_threads((multithreaded) == 0 ? 1 : \
646  (((source)->type != MemoryCache) && ((source)->type != MapCache)) || \
647  (((destination)->type != MemoryCache) && ((destination)->type != MapCache)) ? \
648  MagickMax(MagickMin(GetMagickResourceLimit(ThreadResource),2),1) : \
649  MagickMax(MagickMin((ssize_t) GetMagickResourceLimit(ThreadResource),(ssize_t) (chunk)/256),1))
650 
652  optimize,
653  status;
654 
655  NexusInfo
656  **magick_restrict cache_nexus,
657  **magick_restrict clone_nexus;
658 
659  size_t
660  length;
661 
662  ssize_t
663  y;
664 
665  assert(cache_info != (CacheInfo *) NULL);
666  assert(clone_info != (CacheInfo *) NULL);
667  assert(exception != (ExceptionInfo *) NULL);
668  if (cache_info->type == PingCache)
669  return(MagickTrue);
670  length=cache_info->number_channels*sizeof(*cache_info->channel_map);
671  if ((cache_info->storage_class == clone_info->storage_class) &&
672  (cache_info->colorspace == clone_info->colorspace) &&
673  (cache_info->alpha_trait == clone_info->alpha_trait) &&
674  (cache_info->channels == clone_info->channels) &&
675  (cache_info->columns == clone_info->columns) &&
676  (cache_info->rows == clone_info->rows) &&
677  (cache_info->number_channels == clone_info->number_channels) &&
678  (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) &&
679  (cache_info->metacontent_extent == clone_info->metacontent_extent))
680  {
681  /*
682  Identical pixel cache morphology.
683  */
684  if (((cache_info->type == MemoryCache) ||
685  (cache_info->type == MapCache)) &&
686  ((clone_info->type == MemoryCache) ||
687  (clone_info->type == MapCache)))
688  {
689  (void) memcpy(clone_info->pixels,cache_info->pixels,
690  cache_info->number_channels*cache_info->columns*cache_info->rows*
691  sizeof(*cache_info->pixels));
692  if ((cache_info->metacontent_extent != 0) &&
693  (clone_info->metacontent_extent != 0))
694  (void) memcpy(clone_info->metacontent,cache_info->metacontent,
695  cache_info->columns*cache_info->rows*
696  clone_info->metacontent_extent*sizeof(unsigned char));
697  return(MagickTrue);
698  }
699  if ((cache_info->type == DiskCache) && (clone_info->type == DiskCache))
700  return(ClonePixelCacheOnDisk(cache_info,clone_info));
701  }
702  /*
703  Mismatched pixel cache morphology.
704  */
707  length=cache_info->number_channels*sizeof(*cache_info->channel_map);
708  optimize=(cache_info->number_channels == clone_info->number_channels) &&
709  (memcmp(cache_info->channel_map,clone_info->channel_map,length) == 0) ?
711  length=(size_t) MagickMin(cache_info->number_channels*cache_info->columns,
712  clone_info->number_channels*clone_info->columns);
713  status=MagickTrue;
714 #if defined(MAGICKCORE_OPENMP_SUPPORT)
715  #pragma omp parallel for schedule(static) shared(status) \
716  cache_number_threads(cache_info,clone_info,cache_info->rows,1)
717 #endif
718  for (y=0; y < (ssize_t) cache_info->rows; y++)
719  {
720  const int
721  id = GetOpenMPThreadId();
722 
723  Quantum
724  *pixels;
725 
727  region;
728 
729  register ssize_t
730  x;
731 
732  if (status == MagickFalse)
733  continue;
734  if (y >= (ssize_t) clone_info->rows)
735  continue;
736  region.width=cache_info->columns;
737  region.height=1;
738  region.x=0;
739  region.y=y;
740  pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,&region,MagickFalse,
741  cache_nexus[id],exception);
742  if (pixels == (Quantum *) NULL)
743  continue;
744  status=ReadPixelCachePixels(cache_info,cache_nexus[id],exception);
745  if (status == MagickFalse)
746  continue;
747  region.width=clone_info->columns;
748  pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,&region,MagickFalse,
749  clone_nexus[id],exception);
750  if (pixels == (Quantum *) NULL)
751  continue;
752  (void) memset(clone_nexus[id]->pixels,0,(size_t) clone_nexus[id]->length);
753  if (optimize != MagickFalse)
754  (void) memcpy(clone_nexus[id]->pixels,cache_nexus[id]->pixels,length*
755  sizeof(Quantum));
756  else
757  {
758  register const Quantum
759  *magick_restrict p;
760 
761  register Quantum
762  *magick_restrict q;
763 
764  /*
765  Mismatched pixel channel map.
766  */
767  p=cache_nexus[id]->pixels;
768  q=clone_nexus[id]->pixels;
769  for (x=0; x < (ssize_t) cache_info->columns; x++)
770  {
771  register ssize_t
772  i;
773 
774  if (x == (ssize_t) clone_info->columns)
775  break;
776  for (i=0; i < (ssize_t) clone_info->number_channels; i++)
777  {
779  channel;
780 
781  PixelTrait
782  traits;
783 
784  channel=clone_info->channel_map[i].channel;
785  traits=cache_info->channel_map[channel].traits;
786  if (traits != UndefinedPixelTrait)
787  *q=*(p+cache_info->channel_map[channel].offset);
788  q++;
789  }
790  p+=cache_info->number_channels;
791  }
792  }
793  status=WritePixelCachePixels(clone_info,clone_nexus[id],exception);
794  }
795  if ((cache_info->metacontent_extent != 0) &&
796  (clone_info->metacontent_extent != 0))
797  {
798  /*
799  Clone metacontent.
800  */
801  length=(size_t) MagickMin(cache_info->metacontent_extent,
802  clone_info->metacontent_extent);
803 #if defined(MAGICKCORE_OPENMP_SUPPORT)
804  #pragma omp parallel for schedule(static) shared(status) \
805  cache_number_threads(cache_info,clone_info,cache_info->rows,1)
806 #endif
807  for (y=0; y < (ssize_t) cache_info->rows; y++)
808  {
809  const int
810  id = GetOpenMPThreadId();
811 
812  Quantum
813  *pixels;
814 
816  region;
817 
818  if (status == MagickFalse)
819  continue;
820  if (y >= (ssize_t) clone_info->rows)
821  continue;
822  region.width=cache_info->columns;
823  region.height=1;
824  region.x=0;
825  region.y=y;
826  pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,&region,MagickFalse,
827  cache_nexus[id],exception);
828  if (pixels == (Quantum *) NULL)
829  continue;
830  status=ReadPixelCacheMetacontent(cache_info,cache_nexus[id],exception);
831  if (status == MagickFalse)
832  continue;
833  region.width=clone_info->columns;
834  pixels=SetPixelCacheNexusPixels(clone_info,WriteMode,&region,
835  MagickFalse,clone_nexus[id],exception);
836  if (pixels == (Quantum *) NULL)
837  continue;
838  if ((clone_nexus[id]->metacontent != (void *) NULL) &&
839  (cache_nexus[id]->metacontent != (void *) NULL))
840  (void) memcpy(clone_nexus[id]->metacontent,
841  cache_nexus[id]->metacontent,length*sizeof(unsigned char));
842  status=WritePixelCacheMetacontent(clone_info,clone_nexus[id],exception);
843  }
844  }
845  cache_nexus=DestroyPixelCacheNexus(cache_nexus,MaxCacheThreads);
846  clone_nexus=DestroyPixelCacheNexus(clone_nexus,MaxCacheThreads);
847  if (cache_info->debug != MagickFalse)
848  {
849  char
850  message[MagickPathExtent];
851 
852  (void) FormatLocaleString(message,MagickPathExtent,"%s => %s",
853  CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) cache_info->type),
854  CommandOptionToMnemonic(MagickCacheOptions,(ssize_t) clone_info->type));
855  (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
856  }
857  return(status);
858 }
859 
860 /*
861 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
862 % %
863 % %
864 % %
865 + D e s t r o y I m a g e P i x e l C a c h e %
866 % %
867 % %
868 % %
869 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
870 %
871 % DestroyImagePixelCache() deallocates memory associated with the pixel cache.
872 %
873 % The format of the DestroyImagePixelCache() method is:
874 %
875 % void DestroyImagePixelCache(Image *image)
876 %
877 % A description of each parameter follows:
878 %
879 % o image: the image.
880 %
881 */
882 static void DestroyImagePixelCache(Image *image)
883 {
884  assert(image != (Image *) NULL);
885  assert(image->signature == MagickCoreSignature);
886  if (image->debug != MagickFalse)
887  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
888  if (image->cache == (void *) NULL)
889  return;
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 *) RelinquishMagickMemory(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)
2710  modulo.quotient--;
2711  modulo.remainder=(ssize_t) (offset-(MagickOffsetType) modulo.quotient*
2712  (MagickOffsetType) extent);
2713  return(modulo);
2714 }
2715 
2717  const VirtualPixelMethod virtual_pixel_method,const ssize_t x,const ssize_t y,
2718  const size_t columns,const size_t rows,NexusInfo *nexus_info,
2719  ExceptionInfo *exception)
2720 {
2721  CacheInfo
2722  *magick_restrict cache_info;
2723 
2725  offset;
2726 
2728  length,
2729  number_pixels;
2730 
2731  NexusInfo
2732  **magick_restrict virtual_nexus;
2733 
2734  Quantum
2735  *magick_restrict pixels,
2736  virtual_pixel[MaxPixelChannels];
2737 
2739  region;
2740 
2741  register const Quantum
2742  *magick_restrict p;
2743 
2744  register const void
2745  *magick_restrict r;
2746 
2747  register Quantum
2748  *magick_restrict q;
2749 
2750  register ssize_t
2751  i,
2752  u;
2753 
2754  register unsigned char
2755  *magick_restrict s;
2756 
2757  ssize_t
2758  v;
2759 
2760  void
2761  *magick_restrict virtual_metacontent;
2762 
2763  /*
2764  Acquire pixels.
2765  */
2766  assert(image != (const Image *) NULL);
2767  assert(image->signature == MagickCoreSignature);
2768  assert(image->cache != (Cache) NULL);
2769  cache_info=(CacheInfo *) image->cache;
2770  assert(cache_info->signature == MagickCoreSignature);
2771  if (cache_info->type == UndefinedCache)
2772  return((const Quantum *) NULL);
2773 #if defined(MAGICKCORE_OPENCL_SUPPORT)
2774  CopyOpenCLBuffer(cache_info);
2775 #endif
2776  region.x=x;
2777  region.y=y;
2778  region.width=columns;
2779  region.height=rows;
2780  pixels=SetPixelCacheNexusPixels(cache_info,ReadMode,&region,
2781  ((image->channels & WriteMaskChannel) != 0) ||
2782  ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
2783  nexus_info,exception);
2784  if (pixels == (Quantum *) NULL)
2785  return((const Quantum *) NULL);
2786  q=pixels;
2787  offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
2788  nexus_info->region.x;
2789  length=(MagickSizeType) (nexus_info->region.height-1L)*cache_info->columns+
2790  nexus_info->region.width-1L;
2791  number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
2792  if ((offset >= 0) && (((MagickSizeType) offset+length) < number_pixels))
2793  if ((x >= 0) && ((ssize_t) (x+columns) <= (ssize_t) cache_info->columns) &&
2794  (y >= 0) && ((ssize_t) (y+rows) <= (ssize_t) cache_info->rows))
2795  {
2797  status;
2798 
2799  /*
2800  Pixel request is inside cache extents.
2801  */
2802  if (nexus_info->authentic_pixel_cache != MagickFalse)
2803  return(q);
2804  status=ReadPixelCachePixels(cache_info,nexus_info,exception);
2805  if (status == MagickFalse)
2806  return((const Quantum *) NULL);
2807  if (cache_info->metacontent_extent != 0)
2808  {
2809  status=ReadPixelCacheMetacontent(cache_info,nexus_info,exception);
2810  if (status == MagickFalse)
2811  return((const Quantum *) NULL);
2812  }
2813  return(q);
2814  }
2815  /*
2816  Pixel request is outside cache extents.
2817  */
2818  s=(unsigned char *) nexus_info->metacontent;
2819  virtual_nexus=AcquirePixelCacheNexus(1);
2820  (void) memset(virtual_pixel,0,cache_info->number_channels*
2821  sizeof(*virtual_pixel));
2822  virtual_metacontent=(void *) NULL;
2823  switch (virtual_pixel_method)
2824  {
2835  {
2836  if (cache_info->metacontent_extent != 0)
2837  {
2838  /*
2839  Acquire a metacontent buffer.
2840  */
2841  virtual_metacontent=(void *) AcquireQuantumMemory(1,
2842  cache_info->metacontent_extent);
2843  if (virtual_metacontent == (void *) NULL)
2844  {
2845  virtual_nexus=DestroyPixelCacheNexus(virtual_nexus,1);
2846  (void) ThrowMagickException(exception,GetMagickModule(),
2847  CacheError,"UnableToGetCacheNexus","`%s'",image->filename);
2848  return((const Quantum *) NULL);
2849  }
2850  (void) memset(virtual_metacontent,0,cache_info->metacontent_extent);
2851  }
2852  switch (virtual_pixel_method)
2853  {
2855  {
2856  for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2857  SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2858  SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2859  break;
2860  }
2862  {
2863  for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2865  virtual_pixel);
2866  SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2867  break;
2868  }
2870  {
2871  for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2872  SetPixelChannel(image,(PixelChannel) i,(Quantum) 0,virtual_pixel);
2873  SetPixelAlpha(image,TransparentAlpha,virtual_pixel);
2874  break;
2875  }
2878  {
2879  for (i=0; i < (ssize_t) cache_info->number_channels; i++)
2880  SetPixelChannel(image,(PixelChannel) i,QuantumRange,virtual_pixel);
2881  SetPixelAlpha(image,OpaqueAlpha,virtual_pixel);
2882  break;
2883  }
2884  default:
2885  {
2887  virtual_pixel);
2889  virtual_pixel);
2891  virtual_pixel);
2893  virtual_pixel);
2895  virtual_pixel);
2896  break;
2897  }
2898  }
2899  break;
2900  }
2901  default:
2902  break;
2903  }
2904  for (v=0; v < (ssize_t) rows; v++)
2905  {
2906  ssize_t
2907  y_offset;
2908 
2909  y_offset=y+v;
2910  if ((virtual_pixel_method == EdgeVirtualPixelMethod) ||
2911  (virtual_pixel_method == UndefinedVirtualPixelMethod))
2912  y_offset=EdgeY(y_offset,cache_info->rows);
2913  for (u=0; u < (ssize_t) columns; u+=length)
2914  {
2915  ssize_t
2916  x_offset;
2917 
2918  x_offset=x+u;
2919  length=(MagickSizeType) MagickMin(cache_info->columns-x_offset,columns-u);
2920  if (((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns)) ||
2921  ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows)) ||
2922  (length == 0))
2923  {
2924  MagickModulo
2925  x_modulo,
2926  y_modulo;
2927 
2928  /*
2929  Transfer a single pixel.
2930  */
2931  length=(MagickSizeType) 1;
2932  switch (virtual_pixel_method)
2933  {
2935  default:
2936  {
2937  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2938  EdgeX(x_offset,cache_info->columns),
2939  EdgeY(y_offset,cache_info->rows),1UL,1UL,*virtual_nexus,
2940  exception);
2941  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2942  break;
2943  }
2945  {
2946  if (cache_info->random_info == (RandomInfo *) NULL)
2947  cache_info->random_info=AcquireRandomInfo();
2948  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2949  RandomX(cache_info->random_info,cache_info->columns),
2950  RandomY(cache_info->random_info,cache_info->rows),1UL,1UL,
2951  *virtual_nexus,exception);
2952  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2953  break;
2954  }
2956  {
2957  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2958  DitherX(x_offset,cache_info->columns),
2959  DitherY(y_offset,cache_info->rows),1UL,1UL,*virtual_nexus,
2960  exception);
2961  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2962  break;
2963  }
2965  {
2966  x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
2967  y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
2968  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2969  x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
2970  exception);
2971  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2972  break;
2973  }
2975  {
2976  x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
2977  if ((x_modulo.quotient & 0x01) == 1L)
2978  x_modulo.remainder=(ssize_t) cache_info->columns-
2979  x_modulo.remainder-1L;
2980  y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
2981  if ((y_modulo.quotient & 0x01) == 1L)
2982  y_modulo.remainder=(ssize_t) cache_info->rows-
2983  y_modulo.remainder-1L;
2984  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2985  x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
2986  exception);
2987  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2988  break;
2989  }
2991  {
2992  x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
2993  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
2994  x_modulo.remainder,EdgeY(y_offset,cache_info->rows),1UL,1UL,
2995  *virtual_nexus,exception);
2996  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
2997  break;
2998  }
3000  {
3001  y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3002  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3003  EdgeX(x_offset,cache_info->columns),y_modulo.remainder,1UL,1UL,
3004  *virtual_nexus,exception);
3005  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3006  break;
3007  }
3014  {
3015  p=virtual_pixel;
3016  r=virtual_metacontent;
3017  break;
3018  }
3020  {
3021  x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3022  y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3023  if (((x_modulo.quotient ^ y_modulo.quotient) & 0x01) != 0L)
3024  {
3025  p=virtual_pixel;
3026  r=virtual_metacontent;
3027  break;
3028  }
3029  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3030  x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3031  exception);
3032  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3033  break;
3034  }
3036  {
3037  if ((y_offset < 0) || (y_offset >= (ssize_t) cache_info->rows))
3038  {
3039  p=virtual_pixel;
3040  r=virtual_metacontent;
3041  break;
3042  }
3043  x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3044  y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3045  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3046  x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3047  exception);
3048  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3049  break;
3050  }
3052  {
3053  if ((x_offset < 0) || (x_offset >= (ssize_t) cache_info->columns))
3054  {
3055  p=virtual_pixel;
3056  r=virtual_metacontent;
3057  break;
3058  }
3059  x_modulo=VirtualPixelModulo(x_offset,cache_info->columns);
3060  y_modulo=VirtualPixelModulo(y_offset,cache_info->rows);
3061  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,
3062  x_modulo.remainder,y_modulo.remainder,1UL,1UL,*virtual_nexus,
3063  exception);
3064  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3065  break;
3066  }
3067  }
3068  if (p == (const Quantum *) NULL)
3069  break;
3070  (void) memcpy(q,p,(size_t) length*cache_info->number_channels*
3071  sizeof(*p));
3072  q+=cache_info->number_channels;
3073  if ((s != (void *) NULL) && (r != (const void *) NULL))
3074  {
3075  (void) memcpy(s,r,(size_t) cache_info->metacontent_extent);
3076  s+=cache_info->metacontent_extent;
3077  }
3078  continue;
3079  }
3080  /*
3081  Transfer a run of pixels.
3082  */
3083  p=GetVirtualPixelCacheNexus(image,virtual_pixel_method,x_offset,y_offset,
3084  (size_t) length,1UL,*virtual_nexus,exception);
3085  if (p == (const Quantum *) NULL)
3086  break;
3087  r=GetVirtualMetacontentFromNexus(cache_info,*virtual_nexus);
3088  (void) memcpy(q,p,(size_t) length*cache_info->number_channels*sizeof(*p));
3089  q+=length*cache_info->number_channels;
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),(off_t) (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  cache_info->pixels=source_info.pixels;
3766  else
3767  {
3768  /*
3769  Create memory pixel cache.
3770  */
3771  cache_info->type=MemoryCache;
3772  cache_info->metacontent=(void *) NULL;
3773  if (cache_info->metacontent_extent != 0)
3774  cache_info->metacontent=(void *) (cache_info->pixels+
3775  number_pixels*cache_info->number_channels);
3776  if ((source_info.storage_class != UndefinedClass) &&
3777  (mode != ReadMode))
3778  {
3779  status=ClonePixelCacheRepository(cache_info,&source_info,
3780  exception);
3781  RelinquishPixelCachePixels(&source_info);
3782  }
3783  if (image->debug != MagickFalse)
3784  {
3785  (void) FormatMagickSize(cache_info->length,MagickTrue,"B",
3786  MagickPathExtent,format);
3788  cache_info->type);
3789  (void) FormatLocaleString(message,MagickPathExtent,
3790  "open %s (%s %s, %.20gx%.20gx%.20g %s)",
3791  cache_info->filename,cache_info->mapped != MagickFalse ?
3792  "Anonymous" : "Heap",type,(double) cache_info->columns,
3793  (double) cache_info->rows,(double)
3794  cache_info->number_channels,format);
3796  message);
3797  }
3798  return(status == 0 ? MagickFalse : MagickTrue);
3799  }
3800  }
3801  }
3802  status=AcquireMagickResource(DiskResource,cache_info->length);
3803  hosts=(const char *) GetImageRegistry(StringRegistryType,"cache:hosts",
3804  exception);
3805  if ((status == MagickFalse) && (hosts != (const char *) NULL))
3806  {
3808  *server_info;
3809 
3810  /*
3811  Distribute the pixel cache to a remote server.
3812  */
3813  server_info=AcquireDistributeCacheInfo(exception);
3814  if (server_info != (DistributeCacheInfo *) NULL)
3815  {
3816  status=OpenDistributePixelCache(server_info,image);
3817  if (status == MagickFalse)
3818  {
3819  ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
3820  GetDistributeCacheHostname(server_info));
3821  server_info=DestroyDistributeCacheInfo(server_info);
3822  }
3823  else
3824  {
3825  /*
3826  Create a distributed pixel cache.
3827  */
3828  status=MagickTrue;
3829  cache_info->type=DistributedCache;
3830  cache_info->server_info=server_info;
3831  (void) FormatLocaleString(cache_info->cache_filename,
3833  (DistributeCacheInfo *) cache_info->server_info),
3835  cache_info->server_info));
3836  if ((source_info.storage_class != UndefinedClass) &&
3837  (mode != ReadMode))
3838  {
3839  status=ClonePixelCacheRepository(cache_info,&source_info,
3840  exception);
3841  RelinquishPixelCachePixels(&source_info);
3842  }
3843  if (image->debug != MagickFalse)
3844  {
3845  (void) FormatMagickSize(cache_info->length,MagickFalse,"B",
3846  MagickPathExtent,format);
3848  cache_info->type);
3849  (void) FormatLocaleString(message,MagickPathExtent,
3850  "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3851  cache_info->filename,cache_info->cache_filename,
3853  cache_info->server_info),type,(double) cache_info->columns,
3854  (double) cache_info->rows,(double)
3855  cache_info->number_channels,format);
3857  message);
3858  }
3859  return(status == 0 ? MagickFalse : MagickTrue);
3860  }
3861  }
3862  cache_info->type=UndefinedCache;
3863  (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3864  "CacheResourcesExhausted","`%s'",image->filename);
3865  return(MagickFalse);
3866  }
3867  /*
3868  Create pixel cache on disk.
3869  */
3870  if (status == MagickFalse)
3871  {
3872  cache_info->type=UndefinedCache;
3873  (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
3874  "CacheResourcesExhausted","`%s'",image->filename);
3875  return(MagickFalse);
3876  }
3877  if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode) &&
3878  (cache_info->mode != PersistMode))
3879  {
3880  (void) ClosePixelCacheOnDisk(cache_info);
3881  *cache_info->cache_filename='\0';
3882  }
3883  if (OpenPixelCacheOnDisk(cache_info,mode) == MagickFalse)
3884  {
3885  ThrowFileException(exception,CacheError,"UnableToOpenPixelCache",
3886  image->filename);
3887  return(MagickFalse);
3888  }
3889  status=SetPixelCacheExtent(image,(MagickSizeType) cache_info->offset+
3890  cache_info->length);
3891  if (status == MagickFalse)
3892  {
3893  ThrowFileException(exception,CacheError,"UnableToExtendCache",
3894  image->filename);
3895  return(MagickFalse);
3896  }
3897  length=number_pixels*(cache_info->number_channels*sizeof(Quantum)+
3898  cache_info->metacontent_extent);
3899  if (length != (MagickSizeType) ((size_t) length))
3900  cache_info->type=DiskCache;
3901  else
3902  {
3903  status=AcquireMagickResource(MapResource,cache_info->length);
3904  if (status == MagickFalse)
3905  cache_info->type=DiskCache;
3906  else
3907  if ((cache_info->type != MapCache) && (cache_info->type != MemoryCache))
3908  {
3909  cache_info->type=DiskCache;
3910  RelinquishMagickResource(MapResource,cache_info->length);
3911  }
3912  else
3913  {
3914  cache_info->pixels=(Quantum *) MapBlob(cache_info->file,mode,
3915  cache_info->offset,(size_t) cache_info->length);
3916  if (cache_info->pixels == (Quantum *) NULL)
3917  {
3918  cache_info->type=DiskCache;
3919  cache_info->pixels=source_info.pixels;
3920  RelinquishMagickResource(MapResource,cache_info->length);
3921  }
3922  else
3923  {
3924  /*
3925  Create file-backed memory-mapped pixel cache.
3926  */
3927  (void) ClosePixelCacheOnDisk(cache_info);
3928  cache_info->type=MapCache;
3929  cache_info->mapped=MagickTrue;
3930  cache_info->metacontent=(void *) NULL;
3931  if (cache_info->metacontent_extent != 0)
3932  cache_info->metacontent=(void *) (cache_info->pixels+
3933  number_pixels*cache_info->number_channels);
3934  if ((source_info.storage_class != UndefinedClass) &&
3935  (mode != ReadMode))
3936  {
3937  status=ClonePixelCacheRepository(cache_info,&source_info,
3938  exception);
3939  RelinquishPixelCachePixels(&source_info);
3940  }
3941  if (image->debug != MagickFalse)
3942  {
3943  (void) FormatMagickSize(cache_info->length,MagickTrue,"B",
3944  MagickPathExtent,format);
3946  cache_info->type);
3947  (void) FormatLocaleString(message,MagickPathExtent,
3948  "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",
3949  cache_info->filename,cache_info->cache_filename,
3950  cache_info->file,type,(double) cache_info->columns,
3951  (double) cache_info->rows,(double)
3952  cache_info->number_channels,format);
3954  message);
3955  }
3956  return(status == 0 ? MagickFalse : MagickTrue);
3957  }
3958  }
3959  }
3960  status=MagickTrue;
3961  if ((source_info.storage_class != UndefinedClass) && (mode != ReadMode))
3962  {
3963  status=ClonePixelCacheRepository(cache_info,&source_info,exception);
3964  RelinquishPixelCachePixels(&source_info);
3965  }
3966  if (image->debug != MagickFalse)
3967  {
3968  (void) FormatMagickSize(cache_info->length,MagickFalse,"B",
3969  MagickPathExtent,format);
3971  cache_info->type);
3972  (void) FormatLocaleString(message,MagickPathExtent,
3973  "open %s (%s[%d], %s, %.20gx%.20gx%.20g %s)",cache_info->filename,
3974  cache_info->cache_filename,cache_info->file,type,(double)
3975  cache_info->columns,(double) cache_info->rows,(double)
3976  cache_info->number_channels,format);
3977  (void) LogMagickEvent(CacheEvent,GetMagickModule(),"%s",message);
3978  }
3979  return(status == 0 ? MagickFalse : MagickTrue);
3980 }
3981 
3982 /*
3983 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3984 % %
3985 % %
3986 % %
3987 + P e r s i s t P i x e l C a c h e %
3988 % %
3989 % %
3990 % %
3991 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3992 %
3993 % PersistPixelCache() attaches to or initializes a persistent pixel cache. A
3994 % persistent pixel cache is one that resides on disk and is not destroyed
3995 % when the program exits.
3996 %
3997 % The format of the PersistPixelCache() method is:
3998 %
3999 % MagickBooleanType PersistPixelCache(Image *image,const char *filename,
4000 % const MagickBooleanType attach,MagickOffsetType *offset,
4001 % ExceptionInfo *exception)
4002 %
4003 % A description of each parameter follows:
4004 %
4005 % o image: the image.
4006 %
4007 % o filename: the persistent pixel cache filename.
4008 %
4009 % o attach: A value other than zero initializes the persistent pixel cache.
4010 %
4011 % o initialize: A value other than zero initializes the persistent pixel
4012 % cache.
4013 %
4014 % o offset: the offset in the persistent cache to store pixels.
4015 %
4016 % o exception: return any errors or warnings in this structure.
4017 %
4018 */
4020  const char *filename,const MagickBooleanType attach,MagickOffsetType *offset,
4021  ExceptionInfo *exception)
4022 {
4023  CacheInfo
4024  *magick_restrict cache_info,
4025  *magick_restrict clone_info;
4026 
4028  status;
4029 
4030  ssize_t
4031  page_size;
4032 
4033  assert(image != (Image *) NULL);
4034  assert(image->signature == MagickCoreSignature);
4035  if (image->debug != MagickFalse)
4036  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4037  assert(image->cache != (void *) NULL);
4038  assert(filename != (const char *) NULL);
4039  assert(offset != (MagickOffsetType *) NULL);
4040  page_size=GetMagickPageSize();
4041  cache_info=(CacheInfo *) image->cache;
4042  assert(cache_info->signature == MagickCoreSignature);
4043 #if defined(MAGICKCORE_OPENCL_SUPPORT)
4044  CopyOpenCLBuffer(cache_info);
4045 #endif
4046  if (attach != MagickFalse)
4047  {
4048  /*
4049  Attach existing persistent pixel cache.
4050  */
4051  if (image->debug != MagickFalse)
4053  "attach persistent cache");
4054  (void) CopyMagickString(cache_info->cache_filename,filename,
4056  cache_info->type=DiskCache;
4057  cache_info->offset=(*offset);
4058  if (OpenPixelCache(image,ReadMode,exception) == MagickFalse)
4059  return(MagickFalse);
4060  *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4061  return(SyncImagePixelCache(image,exception));
4062  }
4063  /*
4064  Clone persistent pixel cache.
4065  */
4066  status=AcquireMagickResource(DiskResource,cache_info->length);
4067  if (status == MagickFalse)
4068  {
4069  (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4070  "CacheResourcesExhausted","`%s'",image->filename);
4071  return(MagickFalse);
4072  }
4073  clone_info=(CacheInfo *) ClonePixelCache(cache_info);
4074  clone_info->type=DiskCache;
4075  (void) CopyMagickString(clone_info->cache_filename,filename,MagickPathExtent);
4076  clone_info->file=(-1);
4077  clone_info->storage_class=cache_info->storage_class;
4078  clone_info->colorspace=cache_info->colorspace;
4079  clone_info->alpha_trait=cache_info->alpha_trait;
4080  clone_info->channels=cache_info->channels;
4081  clone_info->columns=cache_info->columns;
4082  clone_info->rows=cache_info->rows;
4083  clone_info->number_channels=cache_info->number_channels;
4084  clone_info->metacontent_extent=cache_info->metacontent_extent;
4085  clone_info->mode=PersistMode;
4086  clone_info->length=cache_info->length;
4087  (void) memcpy(clone_info->channel_map,cache_info->channel_map,
4088  MaxPixelChannels*sizeof(*cache_info->channel_map));
4089  clone_info->offset=(*offset);
4090  status=ClonePixelCacheRepository(clone_info,cache_info,exception);
4091  *offset+=cache_info->length+page_size-(cache_info->length % page_size);
4092  clone_info=(CacheInfo *) DestroyPixelCache(clone_info);
4093  return(status);
4094 }
4095 
4096 /*
4097 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4098 % %
4099 % %
4100 % %
4101 + 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 %
4102 % %
4103 % %
4104 % %
4105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4106 %
4107 % QueueAuthenticPixelCacheNexus() allocates an region to store image pixels as
4108 % defined by the region rectangle and returns a pointer to the region. This
4109 % region is subsequently transferred from the pixel cache with
4110 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4111 % pixels are transferred, otherwise a NULL is returned.
4112 %
4113 % The format of the QueueAuthenticPixelCacheNexus() method is:
4114 %
4115 % Quantum *QueueAuthenticPixelCacheNexus(Image *image,const ssize_t x,
4116 % const ssize_t y,const size_t columns,const size_t rows,
4117 % const MagickBooleanType clone,NexusInfo *nexus_info,
4118 % ExceptionInfo *exception)
4119 %
4120 % A description of each parameter follows:
4121 %
4122 % o image: the image.
4123 %
4124 % o x,y,columns,rows: These values define the perimeter of a region of
4125 % pixels.
4126 %
4127 % o nexus_info: the cache nexus to set.
4128 %
4129 % o clone: clone the pixel cache.
4130 %
4131 % o exception: return any errors or warnings in this structure.
4132 %
4133 */
4135  const ssize_t x,const ssize_t y,const size_t columns,const size_t rows,
4136  const MagickBooleanType clone,NexusInfo *nexus_info,ExceptionInfo *exception)
4137 {
4138  CacheInfo
4139  *magick_restrict cache_info;
4140 
4142  offset;
4143 
4145  number_pixels;
4146 
4147  Quantum
4148  *magick_restrict pixels;
4149 
4151  region;
4152 
4153  /*
4154  Validate pixel cache geometry.
4155  */
4156  assert(image != (const Image *) NULL);
4157  assert(image->signature == MagickCoreSignature);
4158  assert(image->cache != (Cache) NULL);
4159  cache_info=(CacheInfo *) GetImagePixelCache(image,clone,exception);
4160  if (cache_info == (Cache) NULL)
4161  return((Quantum *) NULL);
4162  assert(cache_info->signature == MagickCoreSignature);
4163  if ((cache_info->columns == 0) || (cache_info->rows == 0) || (x < 0) ||
4164  (y < 0) || (x >= (ssize_t) cache_info->columns) ||
4165  (y >= (ssize_t) cache_info->rows))
4166  {
4167  (void) ThrowMagickException(exception,GetMagickModule(),CacheError,
4168  "PixelsAreNotAuthentic","`%s'",image->filename);
4169  return((Quantum *) NULL);
4170  }
4171  offset=(MagickOffsetType) y*cache_info->columns+x;
4172  if (offset < 0)
4173  return((Quantum *) NULL);
4174  number_pixels=(MagickSizeType) cache_info->columns*cache_info->rows;
4175  offset+=(MagickOffsetType) (rows-1)*cache_info->columns+columns-1;
4176  if ((MagickSizeType) offset >= number_pixels)
4177  return((Quantum *) NULL);
4178  /*
4179  Return pixel cache.
4180  */
4181  region.x=x;
4182  region.y=y;
4183  region.width=columns;
4184  region.height=rows;
4185  pixels=SetPixelCacheNexusPixels(cache_info,WriteMode,&region,
4186  ((image->channels & WriteMaskChannel) != 0) ||
4187  ((image->channels & CompositeMaskChannel) != 0) ? MagickTrue : MagickFalse,
4188  nexus_info,exception);
4189  return(pixels);
4190 }
4191 
4192 /*
4193 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4194 % %
4195 % %
4196 % %
4197 + 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 %
4198 % %
4199 % %
4200 % %
4201 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4202 %
4203 % QueueAuthenticPixelsCache() allocates an region to store image pixels as
4204 % defined by the region rectangle and returns a pointer to the region. This
4205 % region is subsequently transferred from the pixel cache with
4206 % SyncAuthenticPixelsCache(). A pointer to the pixels is returned if the
4207 % pixels are transferred, otherwise a NULL is returned.
4208 %
4209 % The format of the QueueAuthenticPixelsCache() method is:
4210 %
4211 % Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4212 % const ssize_t y,const size_t columns,const size_t rows,
4213 % ExceptionInfo *exception)
4214 %
4215 % A description of each parameter follows:
4216 %
4217 % o image: the image.
4218 %
4219 % o x,y,columns,rows: These values define the perimeter of a region of
4220 % pixels.
4221 %
4222 % o exception: return any errors or warnings in this structure.
4223 %
4224 */
4225 static Quantum *QueueAuthenticPixelsCache(Image *image,const ssize_t x,
4226  const ssize_t y,const size_t columns,const size_t rows,
4227  ExceptionInfo *exception)
4228 {
4229  CacheInfo
4230  *magick_restrict cache_info;
4231 
4232  const int
4233  id = GetOpenMPThreadId();
4234 
4235  Quantum
4236  *magick_restrict pixels;
4237 
4238  assert(image != (const Image *) NULL);
4239  assert(image->signature == MagickCoreSignature);
4240  assert(image->cache != (Cache) NULL);
4241  cache_info=(CacheInfo *) image->cache;
4242  assert(cache_info->signature == MagickCoreSignature);
4243  assert(id < (int) cache_info->number_threads);
4244  pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4245  cache_info->nexus_info[id],exception);
4246  return(pixels);
4247 }
4248 
4249 /*
4250 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4251 % %
4252 % %
4253 % %
4254 % Q u e u e A u t h e n t i c P i x e l s %
4255 % %
4256 % %
4257 % %
4258 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4259 %
4260 % QueueAuthenticPixels() queues a mutable pixel region. If the region is
4261 % successfully initialized a pointer to a Quantum array representing the
4262 % region is returned, otherwise NULL is returned. The returned pointer may
4263 % point to a temporary working buffer for the pixels or it may point to the
4264 % final location of the pixels in memory.
4265 %
4266 % Write-only access means that any existing pixel values corresponding to
4267 % the region are ignored. This is useful if the initial image is being
4268 % created from scratch, or if the existing pixel values are to be
4269 % completely replaced without need to refer to their pre-existing values.
4270 % The application is free to read and write the pixel buffer returned by
4271 % QueueAuthenticPixels() any way it pleases. QueueAuthenticPixels() does not
4272 % initialize the pixel array values. Initializing pixel array values is the
4273 % application's responsibility.
4274 %
4275 % Performance is maximized if the selected region is part of one row, or
4276 % one or more full rows, since then there is opportunity to access the
4277 % pixels in-place (without a copy) if the image is in memory, or in a
4278 % memory-mapped file. The returned pointer must *never* be deallocated
4279 % by the user.
4280 %
4281 % Pixels accessed via the returned pointer represent a simple array of type
4282 % Quantum. If the image type is CMYK or the storage class is PseudoClass,
4283 % call GetAuthenticMetacontent() after invoking GetAuthenticPixels() to
4284 % obtain the meta-content (of type void) corresponding to the region.
4285 % Once the Quantum (and/or Quantum) array has been updated, the
4286 % changes must be saved back to the underlying image using
4287 % SyncAuthenticPixels() or they may be lost.
4288 %
4289 % The format of the QueueAuthenticPixels() method is:
4290 %
4291 % Quantum *QueueAuthenticPixels(Image *image,const ssize_t x,
4292 % const ssize_t y,const size_t columns,const size_t rows,
4293 % ExceptionInfo *exception)
4294 %
4295 % A description of each parameter follows:
4296 %
4297 % o image: the image.
4298 %
4299 % o x,y,columns,rows: These values define the perimeter of a region of
4300 % pixels.
4301 %
4302 % o exception: return any errors or warnings in this structure.
4303 %
4304 */
4306  const ssize_t y,const size_t columns,const size_t rows,
4307  ExceptionInfo *exception)
4308 {
4309  CacheInfo
4310  *magick_restrict cache_info;
4311 
4312  const int
4313  id = GetOpenMPThreadId();
4314 
4315  Quantum
4316  *magick_restrict pixels;
4317 
4318  assert(image != (Image *) NULL);
4319  assert(image->signature == MagickCoreSignature);
4320  assert(image->cache != (Cache) NULL);
4321  cache_info=(CacheInfo *) image->cache;
4322  assert(cache_info->signature == MagickCoreSignature);
4323  if (cache_info->methods.queue_authentic_pixels_handler !=
4325  {
4326  pixels=cache_info->methods.queue_authentic_pixels_handler(image,x,y,
4327  columns,rows,exception);
4328  return(pixels);
4329  }
4330  assert(id < (int) cache_info->number_threads);
4331  pixels=QueueAuthenticPixelCacheNexus(image,x,y,columns,rows,MagickFalse,
4332  cache_info->nexus_info[id],exception);
4333  return(pixels);
4334 }
4335 
4336 /*
4337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4338 % %
4339 % %
4340 % %
4341 + 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 %
4342 % %
4343 % %
4344 % %
4345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4346 %
4347 % ReadPixelCacheMetacontent() reads metacontent from the specified region of
4348 % the pixel cache.
4349 %
4350 % The format of the ReadPixelCacheMetacontent() method is:
4351 %
4352 % MagickBooleanType ReadPixelCacheMetacontent(CacheInfo *cache_info,
4353 % NexusInfo *nexus_info,ExceptionInfo *exception)
4354 %
4355 % A description of each parameter follows:
4356 %
4357 % o cache_info: the pixel cache.
4358 %
4359 % o nexus_info: the cache nexus to read the metacontent.
4360 %
4361 % o exception: return any errors or warnings in this structure.
4362 %
4363 */
4364 
4366  const CacheInfo *magick_restrict cache_info,const MagickOffsetType offset,
4367  const MagickSizeType length,unsigned char *magick_restrict buffer)
4368 {
4369  register MagickOffsetType
4370  i;
4371 
4372  ssize_t
4373  count;
4374 
4375 #if !defined(MAGICKCORE_HAVE_PREAD)
4376  if (lseek(cache_info->file,offset,SEEK_SET) < 0)
4377  return((MagickOffsetType) -1);
4378 #endif
4379  count=0;
4380  for (i=0; i < (MagickOffsetType) length; i+=count)
4381  {
4382 #if !defined(MAGICKCORE_HAVE_PREAD)
4383  count=read(cache_info->file,buffer+i,(size_t) MagickMin(length-i,(size_t)
4384  SSIZE_MAX));
4385 #else
4386  count=pread(cache_info->file,buffer+i,(size_t) MagickMin(length-i,(size_t)
4387  SSIZE_MAX),(off_t) (offset+i));
4388 #endif
4389  if (count <= 0)
4390  {
4391  count=0;
4392  if (errno != EINTR)
4393  break;
4394  }
4395  }
4396  return(i);
4397 }
4398 
4400  CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4401  ExceptionInfo *exception)
4402 {
4404  count,
4405  offset;
4406 
4408  extent,
4409  length;
4410 
4411  register ssize_t
4412  y;
4413 
4414  register unsigned char
4415  *magick_restrict q;
4416 
4417  size_t
4418  rows;
4419 
4420  if (cache_info->metacontent_extent == 0)
4421  return(MagickFalse);
4422  if (nexus_info->authentic_pixel_cache != MagickFalse)
4423  return(MagickTrue);
4424  offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4425  nexus_info->region.x;
4426  length=(MagickSizeType) nexus_info->region.width*
4427  cache_info->metacontent_extent;
4428  extent=length*nexus_info->region.height;
4429  rows=nexus_info->region.height;
4430  y=0;
4431  q=(unsigned char *) nexus_info->metacontent;
4432  switch (cache_info->type)
4433  {
4434  case MemoryCache:
4435  case MapCache:
4436  {
4437  register unsigned char
4438  *magick_restrict p;
4439 
4440  /*
4441  Read meta-content from memory.
4442  */
4443  if ((cache_info->columns == nexus_info->region.width) &&
4444  (extent == (MagickSizeType) ((size_t) extent)))
4445  {
4446  length=extent;
4447  rows=1UL;
4448  }
4449  p=(unsigned char *) cache_info->metacontent+offset*
4450  cache_info->metacontent_extent;
4451  for (y=0; y < (ssize_t) rows; y++)
4452  {
4453  (void) memcpy(q,p,(size_t) length);
4454  p+=cache_info->metacontent_extent*cache_info->columns;
4455  q+=cache_info->metacontent_extent*nexus_info->region.width;
4456  }
4457  break;
4458  }
4459  case DiskCache:
4460  {
4461  /*
4462  Read meta content from disk.
4463  */
4464  LockSemaphoreInfo(cache_info->file_semaphore);
4465  if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4466  {
4467  ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4468  cache_info->cache_filename);
4469  UnlockSemaphoreInfo(cache_info->file_semaphore);
4470  return(MagickFalse);
4471  }
4472  if ((cache_info->columns == nexus_info->region.width) &&
4473  (extent <= MagickMaxBufferExtent))
4474  {
4475  length=extent;
4476  rows=1UL;
4477  }
4478  extent=(MagickSizeType) cache_info->columns*cache_info->rows;
4479  for (y=0; y < (ssize_t) rows; y++)
4480  {
4481  count=ReadPixelCacheRegion(cache_info,cache_info->offset+extent*
4482  cache_info->number_channels*sizeof(Quantum)+offset*
4483  cache_info->metacontent_extent,length,(unsigned char *) q);
4484  if (count != (MagickOffsetType) length)
4485  break;
4486  offset+=cache_info->columns;
4487  q+=cache_info->metacontent_extent*nexus_info->region.width;
4488  }
4490  (void) ClosePixelCacheOnDisk(cache_info);
4491  UnlockSemaphoreInfo(cache_info->file_semaphore);
4492  break;
4493  }
4494  case DistributedCache:
4495  {
4497  region;
4498 
4499  /*
4500  Read metacontent from distributed cache.
4501  */
4502  LockSemaphoreInfo(cache_info->file_semaphore);
4503  region=nexus_info->region;
4504  if ((cache_info->columns != nexus_info->region.width) ||
4505  (extent > MagickMaxBufferExtent))
4506  region.height=1UL;
4507  else
4508  {
4509  length=extent;
4510  rows=1UL;
4511  }
4512  for (y=0; y < (ssize_t) rows; y++)
4513  {
4515  cache_info->server_info,&region,length,(unsigned char *) q);
4516  if (count != (MagickOffsetType) length)
4517  break;
4518  q+=cache_info->metacontent_extent*nexus_info->region.width;
4519  region.y++;
4520  }
4521  UnlockSemaphoreInfo(cache_info->file_semaphore);
4522  break;
4523  }
4524  default:
4525  break;
4526  }
4527  if (y < (ssize_t) rows)
4528  {
4529  ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4530  cache_info->cache_filename);
4531  return(MagickFalse);
4532  }
4533  if ((cache_info->debug != MagickFalse) &&
4534  (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4536  "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4537  nexus_info->region.width,(double) nexus_info->region.height,(double)
4538  nexus_info->region.x,(double) nexus_info->region.y);
4539  return(MagickTrue);
4540 }
4541 
4542 /*
4543 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4544 % %
4545 % %
4546 % %
4547 + R e a d P i x e l C a c h e P i x e l s %
4548 % %
4549 % %
4550 % %
4551 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4552 %
4553 % ReadPixelCachePixels() reads pixels from the specified region of the pixel
4554 % cache.
4555 %
4556 % The format of the ReadPixelCachePixels() method is:
4557 %
4558 % MagickBooleanType ReadPixelCachePixels(CacheInfo *cache_info,
4559 % NexusInfo *nexus_info,ExceptionInfo *exception)
4560 %
4561 % A description of each parameter follows:
4562 %
4563 % o cache_info: the pixel cache.
4564 %
4565 % o nexus_info: the cache nexus to read the pixels.
4566 %
4567 % o exception: return any errors or warnings in this structure.
4568 %
4569 */
4571  CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
4572  ExceptionInfo *exception)
4573 {
4575  count,
4576  offset;
4577 
4579  extent,
4580  length;
4581 
4582  register Quantum
4583  *magick_restrict q;
4584 
4585  register ssize_t
4586  y;
4587 
4588  size_t
4589  number_channels,
4590  rows;
4591 
4592  if (nexus_info->authentic_pixel_cache != MagickFalse)
4593  return(MagickTrue);
4594  offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns;
4595  if ((ssize_t) (offset/cache_info->columns) != nexus_info->region.y)
4596  return(MagickFalse);
4597  offset+=nexus_info->region.x;
4598  number_channels=cache_info->number_channels;
4599  length=(MagickSizeType) number_channels*nexus_info->region.width*
4600  sizeof(Quantum);
4601  if ((length/number_channels/sizeof(Quantum)) != nexus_info->region.width)
4602  return(MagickFalse);
4603  rows=nexus_info->region.height;
4604  extent=length*rows;
4605  if ((extent == 0) || ((extent/length) != rows))
4606  return(MagickFalse);
4607  y=0;
4608  q=nexus_info->pixels;
4609  switch (cache_info->type)
4610  {
4611  case MemoryCache:
4612  case MapCache:
4613  {
4614  register Quantum
4615  *magick_restrict p;
4616 
4617  /*
4618  Read pixels from memory.
4619  */
4620  if ((cache_info->columns == nexus_info->region.width) &&
4621  (extent == (MagickSizeType) ((size_t) extent)))
4622  {
4623  length=extent;
4624  rows=1UL;
4625  }
4626  p=cache_info->pixels+offset*cache_info->number_channels;
4627  for (y=0; y < (ssize_t) rows; y++)
4628  {
4629  (void) memcpy(q,p,(size_t) length);
4630  p+=cache_info->number_channels*cache_info->columns;
4631  q+=cache_info->number_channels*nexus_info->region.width;
4632  }
4633  break;
4634  }
4635  case DiskCache:
4636  {
4637  /*
4638  Read pixels from disk.
4639  */
4640  LockSemaphoreInfo(cache_info->file_semaphore);
4641  if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
4642  {
4643  ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
4644  cache_info->cache_filename);
4645  UnlockSemaphoreInfo(cache_info->file_semaphore);
4646  return(MagickFalse);
4647  }
4648  if ((cache_info->columns == nexus_info->region.width) &&
4649  (extent <= MagickMaxBufferExtent))
4650  {
4651  length=extent;
4652  rows=1UL;
4653  }
4654  for (y=0; y < (ssize_t) rows; y++)
4655  {
4656  count=ReadPixelCacheRegion(cache_info,cache_info->offset+offset*
4657  cache_info->number_channels*sizeof(*q),length,(unsigned char *) q);
4658  if (count != (MagickOffsetType) length)
4659  break;
4660  offset+=cache_info->columns;
4661  q+=cache_info->number_channels*nexus_info->region.width;
4662  }
4664  (void) ClosePixelCacheOnDisk(cache_info);
4665  UnlockSemaphoreInfo(cache_info->file_semaphore);
4666  break;
4667  }
4668  case DistributedCache:
4669  {
4671  region;
4672 
4673  /*
4674  Read pixels from distributed cache.
4675  */
4676  LockSemaphoreInfo(cache_info->file_semaphore);
4677  region=nexus_info->region;
4678  if ((cache_info->columns != nexus_info->region.width) ||
4679  (extent > MagickMaxBufferExtent))
4680  region.height=1UL;
4681  else
4682  {
4683  length=extent;
4684  rows=1UL;
4685  }
4686  for (y=0; y < (ssize_t) rows; y++)
4687  {
4689  cache_info->server_info,&region,length,(unsigned char *) q);
4690  if (count != (MagickOffsetType) length)
4691  break;
4692  q+=cache_info->number_channels*nexus_info->region.width;
4693  region.y++;
4694  }
4695  UnlockSemaphoreInfo(cache_info->file_semaphore);
4696  break;
4697  }
4698  default:
4699  break;
4700  }
4701  if (y < (ssize_t) rows)
4702  {
4703  ThrowFileException(exception,CacheError,"UnableToReadPixelCache",
4704  cache_info->cache_filename);
4705  return(MagickFalse);
4706  }
4707  if ((cache_info->debug != MagickFalse) &&
4708  (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
4710  "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
4711  nexus_info->region.width,(double) nexus_info->region.height,(double)
4712  nexus_info->region.x,(double) nexus_info->region.y);
4713  return(MagickTrue);
4714 }
4715 
4716 /*
4717 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4718 % %
4719 % %
4720 % %
4721 + R e f e r e n c e P i x e l C a c h e %
4722 % %
4723 % %
4724 % %
4725 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4726 %
4727 % ReferencePixelCache() increments the reference count associated with the
4728 % pixel cache returning a pointer to the cache.
4729 %
4730 % The format of the ReferencePixelCache method is:
4731 %
4732 % Cache ReferencePixelCache(Cache cache_info)
4733 %
4734 % A description of each parameter follows:
4735 %
4736 % o cache_info: the pixel cache.
4737 %
4738 */
4740 {
4741  CacheInfo
4742  *magick_restrict cache_info;
4743 
4744  assert(cache != (Cache *) NULL);
4745  cache_info=(CacheInfo *) cache;
4746  assert(cache_info->signature == MagickCoreSignature);
4747  LockSemaphoreInfo(cache_info->semaphore);
4748  cache_info->reference_count++;
4749  UnlockSemaphoreInfo(cache_info->semaphore);
4750  return(cache_info);
4751 }
4752 
4753 /*
4754 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4755 % %
4756 % %
4757 % %
4758 + R e s e t P i x e l C a c h e C h a n n e l s %
4759 % %
4760 % %
4761 % %
4762 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4763 %
4764 % ResetPixelCacheChannels() resets the pixel cache channels.
4765 %
4766 % The format of the ResetPixelCacheChannels method is:
4767 %
4768 % void ResetPixelCacheChannels(Image *)
4769 %
4770 % A description of each parameter follows:
4771 %
4772 % o image: the image.
4773 %
4774 */
4776 {
4777  CacheInfo
4778  *magick_restrict cache_info;
4779 
4780  assert(image != (const Image *) NULL);
4781  assert(image->signature == MagickCoreSignature);
4782  assert(image->cache != (Cache) NULL);
4783  cache_info=(CacheInfo *) image->cache;
4784  assert(cache_info->signature == MagickCoreSignature);
4785  cache_info->number_channels=GetPixelChannels(image);
4786 }
4787 
4788 /*
4789 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4790 % %
4791 % %
4792 % %
4793 + 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 %
4794 % %
4795 % %
4796 % %
4797 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4798 %
4799 % ResetCacheAnonymousMemory() resets the anonymous_memory value.
4800 %
4801 % The format of the ResetCacheAnonymousMemory method is:
4802 %
4803 % void ResetCacheAnonymousMemory(void)
4804 %
4805 */
4807 {
4809 }
4810 
4811 /*
4812 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4813 % %
4814 % %
4815 % %
4816 + R e s e t P i x e l C a c h e E p o c h %
4817 % %
4818 % %
4819 % %
4820 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4821 %
4822 % ResetPixelCacheEpoch() resets the pixel cache epoch.
4823 %
4824 % The format of the ResetPixelCacheEpoch method is:
4825 %
4826 % void ResetPixelCacheEpoch(void)
4827 %
4828 */
4830 {
4831  cache_epoch=0;
4832 }
4833 
4834 /*
4835 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4836 % %
4837 % %
4838 % %
4839 + S e t P i x e l C a c h e M e t h o d s %
4840 % %
4841 % %
4842 % %
4843 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4844 %
4845 % SetPixelCacheMethods() sets the image pixel methods to the specified ones.
4846 %
4847 % The format of the SetPixelCacheMethods() method is:
4848 %
4849 % SetPixelCacheMethods(Cache *,CacheMethods *cache_methods)
4850 %
4851 % A description of each parameter follows:
4852 %
4853 % o cache: the pixel cache.
4854 %
4855 % o cache_methods: Specifies a pointer to a CacheMethods structure.
4856 %
4857 */
4859 {
4860  CacheInfo
4861  *magick_restrict cache_info;
4862 
4864  get_one_authentic_pixel_from_handler;
4865 
4867  get_one_virtual_pixel_from_handler;
4868 
4869  /*
4870  Set cache pixel methods.
4871  */
4872  assert(cache != (Cache) NULL);
4873  assert(cache_methods != (CacheMethods *) NULL);
4874  cache_info=(CacheInfo *) cache;
4875  assert(cache_info->signature == MagickCoreSignature);
4876  if (cache_info->debug != MagickFalse)
4878  cache_info->filename);
4879  if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4880  cache_info->methods.get_virtual_pixel_handler=
4881  cache_methods->get_virtual_pixel_handler;
4882  if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4883  cache_info->methods.destroy_pixel_handler=
4884  cache_methods->destroy_pixel_handler;
4885  if (cache_methods->get_virtual_metacontent_from_handler !=
4887  cache_info->methods.get_virtual_metacontent_from_handler=
4888  cache_methods->get_virtual_metacontent_from_handler;
4889  if (cache_methods->get_authentic_pixels_handler !=
4891  cache_info->methods.get_authentic_pixels_handler=
4892  cache_methods->get_authentic_pixels_handler;
4893  if (cache_methods->queue_authentic_pixels_handler !=
4895  cache_info->methods.queue_authentic_pixels_handler=
4896  cache_methods->queue_authentic_pixels_handler;
4897  if (cache_methods->sync_authentic_pixels_handler !=
4899  cache_info->methods.sync_authentic_pixels_handler=
4900  cache_methods->sync_authentic_pixels_handler;
4901  if (cache_methods->get_authentic_pixels_from_handler !=
4903  cache_info->methods.get_authentic_pixels_from_handler=
4904  cache_methods->get_authentic_pixels_from_handler;
4905  if (cache_methods->get_authentic_metacontent_from_handler !=
4907  cache_info->methods.get_authentic_metacontent_from_handler=
4909  get_one_virtual_pixel_from_handler=
4910  cache_info->methods.get_one_virtual_pixel_from_handler;
4911  if (get_one_virtual_pixel_from_handler !=
4913  cache_info->methods.get_one_virtual_pixel_from_handler=
4914  cache_methods->get_one_virtual_pixel_from_handler;
4915  get_one_authentic_pixel_from_handler=
4916  cache_methods->get_one_authentic_pixel_from_handler;
4917  if (get_one_authentic_pixel_from_handler !=
4919  cache_info->methods.get_one_authentic_pixel_from_handler=
4920  cache_methods->get_one_authentic_pixel_from_handler;
4921 }
4922 
4923 /*
4924 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4925 % %
4926 % %
4927 % %
4928 + S e t P i x e l C a c h e N e x u s P i x e l s %
4929 % %
4930 % %
4931 % %
4932 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4933 %
4934 % SetPixelCacheNexusPixels() defines the region of the cache for the
4935 % specified cache nexus.
4936 %
4937 % The format of the SetPixelCacheNexusPixels() method is:
4938 %
4939 % Quantum SetPixelCacheNexusPixels(const CacheInfo *cache_info,
4940 % const MapMode mode,const RectangleInfo *region,
4941 % const MagickBooleanType buffered,NexusInfo *nexus_info,
4942 % ExceptionInfo *exception)
4943 %
4944 % A description of each parameter follows:
4945 %
4946 % o cache_info: the pixel cache.
4947 %
4948 % o mode: ReadMode, WriteMode, or IOMode.
4949 %
4950 % o region: A pointer to the RectangleInfo structure that defines the
4951 % region of this particular cache nexus.
4952 %
4953 % o buffered: if true, nexus pixels are buffered.
4954 %
4955 % o nexus_info: the cache nexus to set.
4956 %
4957 % o exception: return any errors or warnings in this structure.
4958 %
4959 */
4960 
4962  const CacheInfo *magick_restrict cache_info,NexusInfo *nexus_info,
4963  ExceptionInfo *exception)
4964 {
4965  if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
4966  return(MagickFalse);
4967  if (cache_anonymous_memory <= 0)
4968  {
4969  nexus_info->mapped=MagickFalse;
4971  (size_t) nexus_info->length));
4972  if (nexus_info->cache != (Quantum *) NULL)
4973  (void) memset(nexus_info->cache,0,(size_t) nexus_info->length);
4974  }
4975  else
4976  {
4977  nexus_info->mapped=MagickTrue;
4978  nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
4979  nexus_info->length);
4980  }
4981  if (nexus_info->cache == (Quantum *) NULL)
4982  {
4983  (void) ThrowMagickException(exception,GetMagickModule(),
4984  ResourceLimitError,"MemoryAllocationFailed","`%s'",
4985  cache_info->filename);
4986  return(MagickFalse);
4987  }
4988  return(MagickTrue);
4989 }
4990 
4992  const CacheInfo *magick_restrict cache_info,
4993  const NexusInfo *magick_restrict nexus_info)
4994 {
4996  status;
4997 
4999  offset;
5000 
5001  /*
5002  Does nexus pixels point directly to in-core cache pixels or is it buffered?
5003  */
5004  if (cache_info->type == PingCache)
5005  return(MagickTrue);
5006  offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5007  nexus_info->region.x;
5008  status=nexus_info->pixels == (cache_info->pixels+offset*
5009  cache_info->number_channels) ? MagickTrue : MagickFalse;
5010  return(status);
5011 }
5012 
5013 static inline void PrefetchPixelCacheNexusPixels(const NexusInfo *nexus_info,
5014  const MapMode mode)
5015 {
5016  if (mode == ReadMode)
5017  {
5018  MagickCachePrefetch((unsigned char *) nexus_info->pixels,0,1);
5019  return;
5020  }
5021  MagickCachePrefetch((unsigned char *) nexus_info->pixels,1,1);
5022 }
5023 
5024 static Quantum *SetPixelCacheNexusPixels(const CacheInfo *cache_info,
5025  const MapMode mode,const RectangleInfo *region,
5026  const MagickBooleanType buffered,NexusInfo *nexus_info,
5027  ExceptionInfo *exception)
5028 {
5030  status;
5031 
5033  length,
5034  number_pixels;
5035 
5036  assert(cache_info != (const CacheInfo *) NULL);
5037  assert(cache_info->signature == MagickCoreSignature);
5038  if (cache_info->type == UndefinedCache)
5039  return((Quantum *) NULL);
5040  if ((region->width == 0) || (region->height == 0))
5041  return((Quantum *) NULL);
5042  nexus_info->region=(*region);
5043  number_pixels=(MagickSizeType) nexus_info->region.width*
5044  nexus_info->region.height;
5045  if (number_pixels == 0)
5046  return((Quantum *) NULL);
5047  if (((cache_info->type == MemoryCache) || (cache_info->type == MapCache)) &&
5048  (buffered == MagickFalse))
5049  {
5050  ssize_t
5051  x,
5052  y;
5053 
5054  x=nexus_info->region.x+(ssize_t) nexus_info->region.width-1;
5055  y=nexus_info->region.y+(ssize_t) nexus_info->region.height-1;
5056  if (((nexus_info->region.x >= 0) && (nexus_info->region.y >= 0) &&
5057  (y < (ssize_t) cache_info->rows)) &&
5058  (((nexus_info->region.x == 0) &&
5059  (nexus_info->region.width == cache_info->columns)) ||
5060  ((nexus_info->region.height == 1) &&
5061  (x < (ssize_t) cache_info->columns))))
5062  {
5064  offset;
5065 
5066  /*
5067  Pixels are accessed directly from memory.
5068  */
5069  offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5070  nexus_info->region.x;
5071  nexus_info->pixels=cache_info->pixels+cache_info->number_channels*
5072  offset;
5073  nexus_info->metacontent=(void *) NULL;
5074  if (cache_info->metacontent_extent != 0)
5075  nexus_info->metacontent=(unsigned char *) cache_info->metacontent+
5076  offset*cache_info->metacontent_extent;
5077  PrefetchPixelCacheNexusPixels(nexus_info,mode);
5078  nexus_info->authentic_pixel_cache=IsPixelCacheAuthentic(cache_info,
5079  nexus_info);
5080  return(nexus_info->pixels);
5081  }
5082  }
5083  /*
5084  Pixels are stored in a staging region until they are synced to the cache.
5085  */
5086  length=number_pixels*cache_info->number_channels*sizeof(Quantum);
5087  if (cache_info->metacontent_extent != 0)
5088  length+=number_pixels*cache_info->metacontent_extent;
5089  if (nexus_info->cache == (Quantum *) NULL)
5090  {
5091  nexus_info->length=length;
5092  status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
5093  if (status == MagickFalse)
5094  {
5095  nexus_info->length=0;
5096  return((Quantum *) NULL);
5097  }
5098  }
5099  else
5100  if (nexus_info->length < length)
5101  {
5102  RelinquishCacheNexusPixels(nexus_info);
5103  nexus_info->length=length;
5104  status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
5105  if (status == MagickFalse)
5106  {
5107  nexus_info->length=0;
5108  return((Quantum *) NULL);
5109  }
5110  }
5111  nexus_info->pixels=nexus_info->cache;
5112  nexus_info->metacontent=(void *) NULL;
5113  if (cache_info->metacontent_extent != 0)
5114  nexus_info->metacontent=(void *) (nexus_info->pixels+number_pixels*
5115  cache_info->number_channels);
5116  PrefetchPixelCacheNexusPixels(nexus_info,mode);
5117  nexus_info->authentic_pixel_cache=IsPixelCacheAuthentic(cache_info,
5118  nexus_info);
5119  return(nexus_info->pixels);
5120 }
5121 
5122 /*
5123 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5124 % %
5125 % %
5126 % %
5127 % 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 %
5128 % %
5129 % %
5130 % %
5131 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5132 %
5133 % SetPixelCacheVirtualMethod() sets the "virtual pixels" method for the
5134 % pixel cache and returns the previous setting. A virtual pixel is any pixel
5135 % access that is outside the boundaries of the image cache.
5136 %
5137 % The format of the SetPixelCacheVirtualMethod() method is:
5138 %
5139 % VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
5140 % const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
5141 %
5142 % A description of each parameter follows:
5143 %
5144 % o image: the image.
5145 %
5146 % o virtual_pixel_method: choose the type of virtual pixel.
5147 %
5148 % o exception: return any errors or warnings in this structure.
5149 %
5150 */
5151 
5153  ExceptionInfo *exception)
5154 {
5155  CacheInfo
5156  *magick_restrict cache_info;
5157 
5158  CacheView
5159  *magick_restrict image_view;
5160 
5162  status;
5163 
5164  ssize_t
5165  y;
5166 
5167  assert(image != (Image *) NULL);
5168  assert(image->signature == MagickCoreSignature);
5169  if (image->debug != MagickFalse)
5170  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5171  assert(image->cache != (Cache) NULL);
5172  cache_info=(CacheInfo *) image->cache;
5173  assert(cache_info->signature == MagickCoreSignature);
5175  status=MagickTrue;
5176  image_view=AcquireVirtualCacheView(image,exception); /* must be virtual */
5177 #if defined(MAGICKCORE_OPENMP_SUPPORT)
5178  #pragma omp parallel for schedule(static) shared(status) \
5179  magick_number_threads(image,image,image->rows,1)
5180 #endif
5181  for (y=0; y < (ssize_t) image->rows; y++)
5182  {
5183  register Quantum
5184  *magick_restrict q;
5185 
5186  register ssize_t
5187  x;
5188 
5189  if (status == MagickFalse)
5190  continue;
5191  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
5192  if (q == (Quantum *) NULL)
5193  {
5194  status=MagickFalse;
5195  continue;
5196  }
5197  for (x=0; x < (ssize_t) image->columns; x++)
5198  {
5199  SetPixelAlpha(image,alpha,q);
5200  q+=GetPixelChannels(image);
5201  }
5202  status=SyncCacheViewAuthenticPixels(image_view,exception);
5203  }
5204  image_view=DestroyCacheView(image_view);
5205  return(status);
5206 }
5207 
5209  const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
5210 {
5211  CacheInfo
5212  *magick_restrict cache_info;
5213 
5215  method;
5216 
5217  assert(image != (Image *) NULL);
5218  assert(image->signature == MagickCoreSignature);
5219  if (image->debug != MagickFalse)
5220  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
5221  assert(image->cache != (Cache) NULL);
5222  cache_info=(CacheInfo *) image->cache;
5223  assert(cache_info->signature == MagickCoreSignature);
5224  method=cache_info->virtual_pixel_method;
5225  cache_info->virtual_pixel_method=virtual_pixel_method;
5226  if ((image->columns != 0) && (image->rows != 0))
5227  switch (virtual_pixel_method)
5228  {
5230  {
5232  (image->alpha_trait == UndefinedPixelTrait))
5233  (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5234  if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
5236  (void) SetImageColorspace(image,sRGBColorspace,exception);
5237  break;
5238  }
5240  {
5241  if (image->alpha_trait == UndefinedPixelTrait)
5242  (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5243  break;
5244  }
5245  default:
5246  break;
5247  }
5248  return(method);
5249 }
5250 
5251 #if defined(MAGICKCORE_OPENCL_SUPPORT)
5252 /*
5253 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5254 % %
5255 % %
5256 % %
5257 + 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 %
5258 % %
5259 % %
5260 % %
5261 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5262 %
5263 % SyncAuthenticOpenCLBuffer() makes sure that all the OpenCL operations have
5264 % been completed and updates the host memory.
5265 %
5266 % The format of the SyncAuthenticOpenCLBuffer() method is:
5267 %
5268 % void SyncAuthenticOpenCLBuffer(const Image *image)
5269 %
5270 % A description of each parameter follows:
5271 %
5272 % o image: the image.
5273 %
5274 */
5275 
5276 static void CopyOpenCLBuffer(CacheInfo *magick_restrict cache_info)
5277 {
5278  assert(cache_info != (CacheInfo *) NULL);
5279  assert(cache_info->signature == MagickCoreSignature);
5280  if ((cache_info->type != MemoryCache) ||
5281  (cache_info->opencl == (MagickCLCacheInfo) NULL))
5282  return;
5283  /*
5284  Ensure single threaded access to OpenCL environment.
5285  */
5286  LockSemaphoreInfo(cache_info->semaphore);
5287  cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5288  UnlockSemaphoreInfo(cache_info->semaphore);
5289 }
5290 
5291 MagickPrivate void SyncAuthenticOpenCLBuffer(const Image *image)
5292 {
5293  CacheInfo
5294  *magick_restrict cache_info;
5295 
5296  assert(image != (const Image *) NULL);
5297  cache_info=(CacheInfo *) image->cache;
5298  CopyOpenCLBuffer(cache_info);
5299 }
5300 #endif
5301 
5302 /*
5303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5304 % %
5305 % %
5306 % %
5307 + 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 %
5308 % %
5309 % %
5310 % %
5311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5312 %
5313 % SyncAuthenticPixelCacheNexus() saves the authentic image pixels to the
5314 % in-memory or disk cache. The method returns MagickTrue if the pixel region
5315 % is synced, otherwise MagickFalse.
5316 %
5317 % The format of the SyncAuthenticPixelCacheNexus() method is:
5318 %
5319 % MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5320 % NexusInfo *nexus_info,ExceptionInfo *exception)
5321 %
5322 % A description of each parameter follows:
5323 %
5324 % o image: the image.
5325 %
5326 % o nexus_info: the cache nexus to sync.
5327 %
5328 % o exception: return any errors or warnings in this structure.
5329 %
5330 */
5332  NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5333 {
5334  CacheInfo
5335  *magick_restrict cache_info;
5336 
5338  status;
5339 
5340  /*
5341  Transfer pixels to the cache.
5342  */
5343  assert(image != (Image *) NULL);
5344  assert(image->signature == MagickCoreSignature);
5345  if (image->cache == (Cache) NULL)
5346  ThrowBinaryException(CacheError,"PixelCacheIsNotOpen",image->filename);
5347  cache_info=(CacheInfo *) image->cache;
5348  assert(cache_info->signature == MagickCoreSignature);
5349  if (cache_info->type == UndefinedCache)
5350  return(MagickFalse);
5351  if (image->mask_trait != UpdatePixelTrait)
5352  {
5353  if (((image->channels & WriteMaskChannel) != 0) &&
5354  (ClipPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5355  return(MagickFalse);
5356  if (((image->channels & CompositeMaskChannel) != 0) &&
5357  (MaskPixelCacheNexus(image,nexus_info,exception) == MagickFalse))
5358  return(MagickFalse);
5359  }
5360  if (nexus_info->authentic_pixel_cache != MagickFalse)
5361  {
5362  image->taint=MagickTrue;
5363  return(MagickTrue);
5364  }
5365  assert(cache_info->signature == MagickCoreSignature);
5366  status=WritePixelCachePixels(cache_info,nexus_info,exception);
5367  if ((cache_info->metacontent_extent != 0) &&
5368  (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5369  return(MagickFalse);
5370  if (status != MagickFalse)
5371  image->taint=MagickTrue;
5372  return(status);
5373 }
5374 
5375 /*
5376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5377 % %
5378 % %
5379 % %
5380 + S y n c A u t h e n t i c P i x e l C a c h e %
5381 % %
5382 % %
5383 % %
5384 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5385 %
5386 % SyncAuthenticPixelsCache() saves the authentic image pixels to the in-memory
5387 % or disk cache. The method returns MagickTrue if the pixel region is synced,
5388 % otherwise MagickFalse.
5389 %
5390 % The format of the SyncAuthenticPixelsCache() method is:
5391 %
5392 % MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5393 % ExceptionInfo *exception)
5394 %
5395 % A description of each parameter follows:
5396 %
5397 % o image: the image.
5398 %
5399 % o exception: return any errors or warnings in this structure.
5400 %
5401 */
5403  ExceptionInfo *exception)
5404 {
5405  CacheInfo
5406  *magick_restrict cache_info;
5407 
5408  const int
5409  id = GetOpenMPThreadId();
5410 
5412  status;
5413 
5414  assert(image != (Image *) NULL);
5415  assert(image->signature == MagickCoreSignature);
5416  assert(image->cache != (Cache) NULL);
5417  cache_info=(CacheInfo *) image->cache;
5418  assert(cache_info->signature == MagickCoreSignature);
5419  assert(id < (int) cache_info->number_threads);
5420  status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5421  exception);
5422  return(status);
5423 }
5424 
5425 /*
5426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5427 % %
5428 % %
5429 % %
5430 % S y n c A u t h e n t i c P i x e l s %
5431 % %
5432 % %
5433 % %
5434 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5435 %
5436 % SyncAuthenticPixels() saves the image pixels to the in-memory or disk cache.
5437 % The method returns MagickTrue if the pixel region is flushed, otherwise
5438 % MagickFalse.
5439 %
5440 % The format of the SyncAuthenticPixels() method is:
5441 %
5442 % MagickBooleanType SyncAuthenticPixels(Image *image,
5443 % ExceptionInfo *exception)
5444 %
5445 % A description of each parameter follows:
5446 %
5447 % o image: the image.
5448 %
5449 % o exception: return any errors or warnings in this structure.
5450 %
5451 */
5453  ExceptionInfo *exception)
5454 {
5455  CacheInfo
5456  *magick_restrict cache_info;
5457 
5458  const int
5459  id = GetOpenMPThreadId();
5460 
5462  status;
5463 
5464  assert(image != (Image *) NULL);
5465  assert(image->signature == MagickCoreSignature);
5466  assert(image->cache != (Cache) NULL);
5467  cache_info=(CacheInfo *) image->cache;
5468  assert(cache_info->signature == MagickCoreSignature);
5469  if (cache_info->methods.sync_authentic_pixels_handler !=
5471  {
5472  status=cache_info->methods.sync_authentic_pixels_handler(image,
5473  exception);
5474  return(status);
5475  }
5476  assert(id < (int) cache_info->number_threads);
5477  status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5478  exception);
5479  return(status);
5480 }
5481 
5482 /*
5483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5484 % %
5485 % %
5486 % %
5487 + S y n c I m a g e P i x e l C a c h e %
5488 % %
5489 % %
5490 % %
5491 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5492 %
5493 % SyncImagePixelCache() saves the image pixels to the in-memory or disk cache.
5494 % The method returns MagickTrue if the pixel region is flushed, otherwise
5495 % MagickFalse.
5496 %
5497 % The format of the SyncImagePixelCache() method is:
5498 %
5499 % MagickBooleanType SyncImagePixelCache(Image *image,
5500 % ExceptionInfo *exception)
5501 %
5502 % A description of each parameter follows:
5503 %
5504 % o image: the image.
5505 %
5506 % o exception: return any errors or warnings in this structure.
5507 %
5508 */
5510  ExceptionInfo *exception)
5511 {
5512  CacheInfo
5513  *magick_restrict cache_info;
5514 
5515  assert(image != (Image *) NULL);
5516  assert(exception != (ExceptionInfo *) NULL);
5517  cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5518  return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5519 }
5520 
5521 /*
5522 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5523 % %
5524 % %
5525 % %
5526 + 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 %
5527 % %
5528 % %
5529 % %
5530 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5531 %
5532 % WritePixelCacheMetacontent() writes the meta-content to the specified region
5533 % of the pixel cache.
5534 %
5535 % The format of the WritePixelCacheMetacontent() method is:
5536 %
5537 % MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5538 % NexusInfo *nexus_info,ExceptionInfo *exception)
5539 %
5540 % A description of each parameter follows:
5541 %
5542 % o cache_info: the pixel cache.
5543 %
5544 % o nexus_info: the cache nexus to write the meta-content.
5545 %
5546 % o exception: return any errors or warnings in this structure.
5547 %
5548 */
5550  NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5551 {
5553  count,
5554  offset;
5555 
5557  extent,
5558  length;
5559 
5560  register const unsigned char
5561  *magick_restrict p;
5562 
5563  register ssize_t
5564  y;
5565 
5566  size_t
5567  rows;
5568 
5569  if (cache_info->metacontent_extent == 0)
5570  return(MagickFalse);
5571  if (nexus_info->authentic_pixel_cache != MagickFalse)
5572  return(MagickTrue);
5573  offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5574  nexus_info->region.x;
5575  length=(MagickSizeType) nexus_info->region.width*
5576  cache_info->metacontent_extent;
5577  extent=(MagickSizeType) length*nexus_info->region.height;
5578  rows=nexus_info->region.height;
5579  y=0;
5580  p=(unsigned char *) nexus_info->metacontent;
5581  switch (cache_info->type)
5582  {
5583  case MemoryCache:
5584  case MapCache:
5585  {
5586  register unsigned char
5587  *magick_restrict q;
5588 
5589  /*
5590  Write associated pixels to memory.
5591  */
5592  if ((cache_info->columns == nexus_info->region.width) &&
5593  (extent == (MagickSizeType) ((size_t) extent)))
5594  {
5595  length=extent;
5596  rows=1UL;
5597  }
5598  q=(unsigned char *) cache_info->metacontent+offset*
5599  cache_info->metacontent_extent;
5600  for (y=0; y < (ssize_t) rows; y++)
5601  {
5602  (void) memcpy(q,p,(size_t) length);
5603  p+=nexus_info->region.width*cache_info->metacontent_extent;
5604  q+=cache_info->columns*cache_info->metacontent_extent;
5605  }
5606  break;
5607  }
5608  case DiskCache:
5609  {
5610  /*
5611  Write associated pixels to disk.
5612  */
5613  LockSemaphoreInfo(cache_info->file_semaphore);
5614  if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5615  {
5616  ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5617  cache_info->cache_filename);
5618  UnlockSemaphoreInfo(cache_info->file_semaphore);
5619  return(MagickFalse);
5620  }
5621  if ((cache_info->columns == nexus_info->region.width) &&
5622  (extent <= MagickMaxBufferExtent))
5623  {
5624  length=extent;
5625  rows=1UL;
5626  }
5627  extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5628  for (y=0; y < (ssize_t) rows; y++)
5629  {
5630  count=WritePixelCacheRegion(cache_info,cache_info->offset+extent*
5631  cache_info->number_channels*sizeof(Quantum)+offset*
5632  cache_info->metacontent_extent,length,(const unsigned char *) p);
5633  if (count != (MagickOffsetType) length)
5634  break;
5635  p+=cache_info->metacontent_extent*nexus_info->region.width;
5636  offset+=cache_info->columns;
5637  }
5639  (void) ClosePixelCacheOnDisk(cache_info);
5640  UnlockSemaphoreInfo(cache_info->file_semaphore);
5641  break;
5642  }
5643  case DistributedCache:
5644  {
5646  region;
5647 
5648  /*
5649  Write metacontent to distributed cache.
5650  */
5651  LockSemaphoreInfo(cache_info->file_semaphore);
5652  region=nexus_info->region;
5653  if ((cache_info->columns != nexus_info->region.width) ||
5654  (extent > MagickMaxBufferExtent))
5655  region.height=1UL;
5656  else
5657  {
5658  length=extent;
5659  rows=1UL;
5660  }
5661  for (y=0; y < (ssize_t) rows; y++)
5662  {
5664  cache_info->server_info,&region,length,(const unsigned char *) p);
5665  if (count != (MagickOffsetType) length)
5666  break;
5667  p+=cache_info->metacontent_extent*nexus_info->region.width;
5668  region.y++;
5669  }
5670  UnlockSemaphoreInfo(cache_info->file_semaphore);
5671  break;
5672  }
5673  default:
5674  break;
5675  }
5676  if (y < (ssize_t) rows)
5677  {
5678  ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5679  cache_info->cache_filename);
5680  return(MagickFalse);
5681  }
5682  if ((cache_info->debug != MagickFalse) &&
5683  (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5685  "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5686  nexus_info->region.width,(double) nexus_info->region.height,(double)
5687  nexus_info->region.x,(double) nexus_info->region.y);
5688  return(MagickTrue);
5689 }
5690 
5691 /*
5692 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5693 % %
5694 % %
5695 % %
5696 + W r i t e C a c h e P i x e l s %
5697 % %
5698 % %
5699 % %
5700 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5701 %
5702 % WritePixelCachePixels() writes image pixels to the specified region of the
5703 % pixel cache.
5704 %
5705 % The format of the WritePixelCachePixels() method is:
5706 %
5707 % MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5708 % NexusInfo *nexus_info,ExceptionInfo *exception)
5709 %
5710 % A description of each parameter follows:
5711 %
5712 % o cache_info: the pixel cache.
5713 %
5714 % o nexus_info: the cache nexus to write the pixels.
5715 %
5716 % o exception: return any errors or warnings in this structure.
5717 %
5718 */
5720  CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
5721  ExceptionInfo *exception)
5722 {
5724  count,
5725  offset;
5726 
5728  extent,
5729  length;
5730 
5731  register const Quantum
5732  *magick_restrict p;
5733 
5734  register ssize_t
5735  y;
5736 
5737  size_t
5738  rows;
5739 
5740  if (nexus_info->authentic_pixel_cache != MagickFalse)
5741  return(MagickTrue);
5742  offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5743  nexus_info->region.x;
5744  length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5745  sizeof(Quantum);
5746  extent=length*nexus_info->region.height;
5747  rows=nexus_info->region.height;
5748  y=0;
5749  p=nexus_info->pixels;
5750  switch (cache_info->type)
5751  {
5752  case MemoryCache:
5753  case MapCache:
5754  {
5755  register Quantum
5756  *magick_restrict q;
5757 
5758  /*
5759  Write pixels to memory.
5760  */
5761  if ((cache_info->columns == nexus_info->region.width) &&
5762  (extent == (MagickSizeType) ((size_t) extent)))
5763  {
5764  length=extent;
5765  rows=1UL;
5766  }
5767  q=cache_info->pixels+offset*cache_info->number_channels;
5768  for (y=0; y < (ssize_t) rows; y++)
5769  {
5770  (void) memcpy(q,p,(size_t) length);
5771  p+=cache_info->number_channels*nexus_info->region.width;
5772  q+=cache_info->number_channels*cache_info->columns;
5773  }
5774  break;
5775  }
5776  case DiskCache:
5777  {
5778  /*
5779  Write pixels to disk.
5780  */
5781  LockSemaphoreInfo(cache_info->file_semaphore);
5782  if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5783  {
5784  ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5785  cache_info->cache_filename);
5786  UnlockSemaphoreInfo(cache_info->file_semaphore);
5787  return(MagickFalse);
5788  }
5789  if ((cache_info->columns == nexus_info->region.width) &&
5790  (extent <= MagickMaxBufferExtent))
5791  {
5792  length=extent;
5793  rows=1UL;
5794  }
5795  for (y=0; y < (ssize_t) rows; y++)
5796  {
5797  count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5798  cache_info->number_channels*sizeof(*p),length,(const unsigned char *)
5799  p);
5800  if (count != (MagickOffsetType) length)
5801  break;
5802  p+=cache_info->number_channels*nexus_info->region.width;
5803  offset+=cache_info->columns;
5804  }
5806  (void) ClosePixelCacheOnDisk(cache_info);
5807  Unloc