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