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