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