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 P i x e l C a c h e E p o c h %
4583 % %
4584 % %
4585 % %
4586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4587 %
4588 % ResetPixelCacheEpoch() resets the pixel cache epoch.
4589 %
4590 % The format of the ResetPixelCacheEpoch method is:
4591 %
4592 % void ResetPixelCacheEpoch(void)
4593 %
4594 */
4596 {
4597  cache_epoch=0;
4598 }
4599 
4600 /*
4601 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4602 % %
4603 % %
4604 % %
4605 + S e t P i x e l C a c h e M e t h o d s %
4606 % %
4607 % %
4608 % %
4609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4610 %
4611 % SetPixelCacheMethods() sets the image pixel methods to the specified ones.
4612 %
4613 % The format of the SetPixelCacheMethods() method is:
4614 %
4615 % SetPixelCacheMethods(Cache *,CacheMethods *cache_methods)
4616 %
4617 % A description of each parameter follows:
4618 %
4619 % o cache: the pixel cache.
4620 %
4621 % o cache_methods: Specifies a pointer to a CacheMethods structure.
4622 %
4623 */
4625 {
4626  CacheInfo
4627  *magick_restrict cache_info;
4628 
4630  get_one_authentic_pixel_from_handler;
4631 
4633  get_one_virtual_pixel_from_handler;
4634 
4635  /*
4636  Set cache pixel methods.
4637  */
4638  assert(cache != (Cache) NULL);
4639  assert(cache_methods != (CacheMethods *) NULL);
4640  cache_info=(CacheInfo *) cache;
4641  assert(cache_info->signature == MagickCoreSignature);
4642  if (cache_info->debug != MagickFalse)
4644  cache_info->filename);
4645  if (cache_methods->get_virtual_pixel_handler != (GetVirtualPixelHandler) NULL)
4646  cache_info->methods.get_virtual_pixel_handler=
4647  cache_methods->get_virtual_pixel_handler;
4648  if (cache_methods->destroy_pixel_handler != (DestroyPixelHandler) NULL)
4649  cache_info->methods.destroy_pixel_handler=
4650  cache_methods->destroy_pixel_handler;
4651  if (cache_methods->get_virtual_metacontent_from_handler !=
4653  cache_info->methods.get_virtual_metacontent_from_handler=
4654  cache_methods->get_virtual_metacontent_from_handler;
4655  if (cache_methods->get_authentic_pixels_handler !=
4657  cache_info->methods.get_authentic_pixels_handler=
4658  cache_methods->get_authentic_pixels_handler;
4659  if (cache_methods->queue_authentic_pixels_handler !=
4661  cache_info->methods.queue_authentic_pixels_handler=
4662  cache_methods->queue_authentic_pixels_handler;
4663  if (cache_methods->sync_authentic_pixels_handler !=
4665  cache_info->methods.sync_authentic_pixels_handler=
4666  cache_methods->sync_authentic_pixels_handler;
4667  if (cache_methods->get_authentic_pixels_from_handler !=
4669  cache_info->methods.get_authentic_pixels_from_handler=
4670  cache_methods->get_authentic_pixels_from_handler;
4671  if (cache_methods->get_authentic_metacontent_from_handler !=
4673  cache_info->methods.get_authentic_metacontent_from_handler=
4675  get_one_virtual_pixel_from_handler=
4676  cache_info->methods.get_one_virtual_pixel_from_handler;
4677  if (get_one_virtual_pixel_from_handler !=
4679  cache_info->methods.get_one_virtual_pixel_from_handler=
4680  cache_methods->get_one_virtual_pixel_from_handler;
4681  get_one_authentic_pixel_from_handler=
4682  cache_methods->get_one_authentic_pixel_from_handler;
4683  if (get_one_authentic_pixel_from_handler !=
4685  cache_info->methods.get_one_authentic_pixel_from_handler=
4686  cache_methods->get_one_authentic_pixel_from_handler;
4687 }
4688 
4689 /*
4690 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4691 % %
4692 % %
4693 % %
4694 + S e t P i x e l C a c h e N e x u s P i x e l s %
4695 % %
4696 % %
4697 % %
4698 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4699 %
4700 % SetPixelCacheNexusPixels() defines the region of the cache for the
4701 % specified cache nexus.
4702 %
4703 % The format of the SetPixelCacheNexusPixels() method is:
4704 %
4705 % Quantum SetPixelCacheNexusPixels(const CacheInfo *cache_info,
4706 % const MapMode mode,const RectangleInfo *region,NexusInfo *nexus_info,
4707 % ExceptionInfo *exception)
4708 %
4709 % A description of each parameter follows:
4710 %
4711 % o cache_info: the pixel cache.
4712 %
4713 % o mode: ReadMode, WriteMode, or IOMode.
4714 %
4715 % o region: A pointer to the RectangleInfo structure that defines the
4716 % region of this particular cache nexus.
4717 %
4718 % o nexus_info: the cache nexus to set.
4719 %
4720 % o exception: return any errors or warnings in this structure.
4721 %
4722 */
4723 
4725  const CacheInfo *magick_restrict cache_info,NexusInfo *nexus_info,
4726  ExceptionInfo *exception)
4727 {
4728  if (nexus_info->length != (MagickSizeType) ((size_t) nexus_info->length))
4729  return(MagickFalse);
4730  if (cache_anonymous_memory <= 0)
4731  {
4732  nexus_info->mapped=MagickFalse;
4734  (size_t) nexus_info->length));
4735  if (nexus_info->cache != (Quantum *) NULL)
4736  (void) ResetMagickMemory(nexus_info->cache,0,(size_t)
4737  nexus_info->length);
4738  }
4739  else
4740  {
4741  nexus_info->mapped=MagickTrue;
4742  nexus_info->cache=(Quantum *) MapBlob(-1,IOMode,0,(size_t)
4743  nexus_info->length);
4744  }
4745  if (nexus_info->cache == (Quantum *) NULL)
4746  {
4747  (void) ThrowMagickException(exception,GetMagickModule(),
4748  ResourceLimitError,"MemoryAllocationFailed","`%s'",
4749  cache_info->filename);
4750  return(MagickFalse);
4751  }
4752  return(MagickTrue);
4753 }
4754 
4756  const CacheInfo *magick_restrict cache_info,
4757  const NexusInfo *magick_restrict nexus_info)
4758 {
4760  status;
4761 
4763  offset;
4764 
4765  /*
4766  Does nexus pixels point directly to in-core cache pixels or is it buffered?
4767  */
4768  if (cache_info->type == PingCache)
4769  return(MagickTrue);
4770  offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4771  nexus_info->region.x;
4772  status=nexus_info->pixels == (cache_info->pixels+offset*
4773  cache_info->number_channels) ? MagickTrue : MagickFalse;
4774  return(status);
4775 }
4776 
4777 static inline void PrefetchPixelCacheNexusPixels(const NexusInfo *nexus_info,
4778  const MapMode mode)
4779 {
4780  if (mode == ReadMode)
4781  {
4782  MagickCachePrefetch((unsigned char *) nexus_info->pixels,0,1);
4783  return;
4784  }
4785  MagickCachePrefetch((unsigned char *) nexus_info->pixels,1,1);
4786 }
4787 
4788 static Quantum *SetPixelCacheNexusPixels(const CacheInfo *cache_info,
4789  const MapMode mode,const RectangleInfo *region,NexusInfo *nexus_info,
4790  ExceptionInfo *exception)
4791 {
4793  status;
4794 
4796  length,
4797  number_pixels;
4798 
4799  assert(cache_info != (const CacheInfo *) NULL);
4800  assert(cache_info->signature == MagickCoreSignature);
4801  if (cache_info->type == UndefinedCache)
4802  return((Quantum *) NULL);
4803  if ((region->width == 0) || (region->height == 0))
4804  return((Quantum *) NULL);
4805  nexus_info->region=(*region);
4806  number_pixels=(MagickSizeType) nexus_info->region.width*
4807  nexus_info->region.height;
4808  if (number_pixels == 0)
4809  return((Quantum *) NULL);
4810  if ((cache_info->type == MemoryCache) || (cache_info->type == MapCache))
4811  {
4812  ssize_t
4813  x,
4814  y;
4815 
4816  x=nexus_info->region.x+(ssize_t) nexus_info->region.width-1;
4817  y=nexus_info->region.y+(ssize_t) nexus_info->region.height-1;
4818  if (((nexus_info->region.x >= 0) && (x < (ssize_t) cache_info->columns) &&
4819  (nexus_info->region.y >= 0) && (y < (ssize_t) cache_info->rows)) &&
4820  ((nexus_info->region.height == 1UL) || ((nexus_info->region.x == 0) &&
4821  ((nexus_info->region.width == cache_info->columns) ||
4822  ((nexus_info->region.width % cache_info->columns) == 0)))))
4823  {
4825  offset;
4826 
4827  /*
4828  Pixels are accessed directly from memory.
4829  */
4830  offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
4831  nexus_info->region.x;
4832  nexus_info->pixels=cache_info->pixels+cache_info->number_channels*
4833  offset;
4834  nexus_info->metacontent=(void *) NULL;
4835  if (cache_info->metacontent_extent != 0)
4836  nexus_info->metacontent=(unsigned char *) cache_info->metacontent+
4837  offset*cache_info->metacontent_extent;
4838  PrefetchPixelCacheNexusPixels(nexus_info,mode);
4839  nexus_info->authentic_pixel_cache=IsPixelCacheAuthentic(cache_info,
4840  nexus_info);
4841  return(nexus_info->pixels);
4842  }
4843  }
4844  /*
4845  Pixels are stored in a staging region until they are synced to the cache.
4846  */
4847  length=number_pixels*cache_info->number_channels*sizeof(Quantum);
4848  if (cache_info->metacontent_extent != 0)
4849  length+=number_pixels*cache_info->metacontent_extent;
4850  if (nexus_info->cache == (Quantum *) NULL)
4851  {
4852  nexus_info->length=length;
4853  status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
4854  if (status == MagickFalse)
4855  {
4856  nexus_info->length=0;
4857  return((Quantum *) NULL);
4858  }
4859  }
4860  else
4861  if (nexus_info->length < length)
4862  {
4863  RelinquishCacheNexusPixels(nexus_info);
4864  nexus_info->length=length;
4865  status=AcquireCacheNexusPixels(cache_info,nexus_info,exception);
4866  if (status == MagickFalse)
4867  {
4868  nexus_info->length=0;
4869  return((Quantum *) NULL);
4870  }
4871  }
4872  nexus_info->pixels=nexus_info->cache;
4873  nexus_info->metacontent=(void *) NULL;
4874  if (cache_info->metacontent_extent != 0)
4875  nexus_info->metacontent=(void *) (nexus_info->pixels+number_pixels*
4876  cache_info->number_channels);
4877  PrefetchPixelCacheNexusPixels(nexus_info,mode);
4878  nexus_info->authentic_pixel_cache=IsPixelCacheAuthentic(cache_info,
4879  nexus_info);
4880  return(nexus_info->pixels);
4881 }
4882 
4883 /*
4884 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4885 % %
4886 % %
4887 % %
4888 % 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 %
4889 % %
4890 % %
4891 % %
4892 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4893 %
4894 % SetPixelCacheVirtualMethod() sets the "virtual pixels" method for the
4895 % pixel cache and returns the previous setting. A virtual pixel is any pixel
4896 % access that is outside the boundaries of the image cache.
4897 %
4898 % The format of the SetPixelCacheVirtualMethod() method is:
4899 %
4900 % VirtualPixelMethod SetPixelCacheVirtualMethod(Image *image,
4901 % const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
4902 %
4903 % A description of each parameter follows:
4904 %
4905 % o image: the image.
4906 %
4907 % o virtual_pixel_method: choose the type of virtual pixel.
4908 %
4909 % o exception: return any errors or warnings in this structure.
4910 %
4911 */
4912 
4914  ExceptionInfo *exception)
4915 {
4916  CacheInfo
4917  *magick_restrict cache_info;
4918 
4919  CacheView
4920  *magick_restrict image_view;
4921 
4923  status;
4924 
4925  ssize_t
4926  y;
4927 
4928  assert(image != (Image *) NULL);
4929  assert(image->signature == MagickCoreSignature);
4930  if (image->debug != MagickFalse)
4931  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4932  assert(image->cache != (Cache) NULL);
4933  cache_info=(CacheInfo *) image->cache;
4934  assert(cache_info->signature == MagickCoreSignature);
4936  status=MagickTrue;
4937  image_view=AcquireVirtualCacheView(image,exception); /* must be virtual */
4938 #if defined(MAGICKCORE_OPENMP_SUPPORT)
4939  #pragma omp parallel for schedule(static,4) shared(status) \
4940  magick_number_threads(image,image,image->rows,1)
4941 #endif
4942  for (y=0; y < (ssize_t) image->rows; y++)
4943  {
4944  register Quantum
4945  *magick_restrict q;
4946 
4947  register ssize_t
4948  x;
4949 
4950  if (status == MagickFalse)
4951  continue;
4952  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
4953  if (q == (Quantum *) NULL)
4954  {
4955  status=MagickFalse;
4956  continue;
4957  }
4958  for (x=0; x < (ssize_t) image->columns; x++)
4959  {
4960  SetPixelAlpha(image,alpha,q);
4961  q+=GetPixelChannels(image);
4962  }
4963  status=SyncCacheViewAuthenticPixels(image_view,exception);
4964  }
4965  image_view=DestroyCacheView(image_view);
4966  return(status);
4967 }
4968 
4970  const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
4971 {
4972  CacheInfo
4973  *magick_restrict cache_info;
4974 
4976  method;
4977 
4978  assert(image != (Image *) NULL);
4979  assert(image->signature == MagickCoreSignature);
4980  if (image->debug != MagickFalse)
4981  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4982  assert(image->cache != (Cache) NULL);
4983  cache_info=(CacheInfo *) image->cache;
4984  assert(cache_info->signature == MagickCoreSignature);
4985  method=cache_info->virtual_pixel_method;
4986  cache_info->virtual_pixel_method=virtual_pixel_method;
4987  if ((image->columns != 0) && (image->rows != 0))
4988  switch (virtual_pixel_method)
4989  {
4991  {
4993  (image->alpha_trait == UndefinedPixelTrait))
4994  (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
4995  if ((IsPixelInfoGray(&image->background_color) == MagickFalse) &&
4997  (void) SetImageColorspace(image,sRGBColorspace,exception);
4998  break;
4999  }
5001  {
5002  if (image->alpha_trait == UndefinedPixelTrait)
5003  (void) SetCacheAlphaChannel(image,OpaqueAlpha,exception);
5004  break;
5005  }
5006  default:
5007  break;
5008  }
5009  return(method);
5010 }
5011 
5012 #if defined(MAGICKCORE_OPENCL_SUPPORT)
5013 /*
5014 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5015 % %
5016 % %
5017 % %
5018 + 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 %
5019 % %
5020 % %
5021 % %
5022 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5023 %
5024 % SyncAuthenticOpenCLBuffer() makes sure that all the OpenCL operations have
5025 % been completed and updates the host memory.
5026 %
5027 % The format of the SyncAuthenticOpenCLBuffer() method is:
5028 %
5029 % void SyncAuthenticOpenCLBuffer(const Image *image)
5030 %
5031 % A description of each parameter follows:
5032 %
5033 % o image: the image.
5034 %
5035 */
5036 
5037 static void CopyOpenCLBuffer(CacheInfo *magick_restrict cache_info)
5038 {
5039  assert(cache_info != (CacheInfo *) NULL);
5040  assert(cache_info->signature == MagickCoreSignature);
5041  if ((cache_info->type != MemoryCache) ||
5042  (cache_info->opencl == (MagickCLCacheInfo) NULL))
5043  return;
5044  /*
5045  Ensure single threaded access to OpenCL environment.
5046  */
5047  LockSemaphoreInfo(cache_info->semaphore);
5048  cache_info->opencl=CopyMagickCLCacheInfo(cache_info->opencl);
5049  UnlockSemaphoreInfo(cache_info->semaphore);
5050 }
5051 
5052 MagickPrivate void SyncAuthenticOpenCLBuffer(const Image *image)
5053 {
5054  CacheInfo
5055  *magick_restrict cache_info;
5056 
5057  assert(image != (const Image *) NULL);
5058  cache_info=(CacheInfo *) image->cache;
5059  CopyOpenCLBuffer(cache_info);
5060 }
5061 #endif
5062 
5063 /*
5064 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5065 % %
5066 % %
5067 % %
5068 + 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 %
5069 % %
5070 % %
5071 % %
5072 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5073 %
5074 % SyncAuthenticPixelCacheNexus() saves the authentic image pixels to the
5075 % in-memory or disk cache. The method returns MagickTrue if the pixel region
5076 % is synced, otherwise MagickFalse.
5077 %
5078 % The format of the SyncAuthenticPixelCacheNexus() method is:
5079 %
5080 % MagickBooleanType SyncAuthenticPixelCacheNexus(Image *image,
5081 % NexusInfo *nexus_info,ExceptionInfo *exception)
5082 %
5083 % A description of each parameter follows:
5084 %
5085 % o image: the image.
5086 %
5087 % o nexus_info: the cache nexus to sync.
5088 %
5089 % o exception: return any errors or warnings in this structure.
5090 %
5091 */
5093  NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5094 {
5095  CacheInfo
5096  *magick_restrict cache_info;
5097 
5099  status;
5100 
5101  /*
5102  Transfer pixels to the cache.
5103  */
5104  assert(image != (Image *) NULL);
5105  assert(image->signature == MagickCoreSignature);
5106  if (image->cache == (Cache) NULL)
5107  ThrowBinaryException(CacheError,"PixelCacheIsNotOpen",image->filename);
5108  cache_info=(CacheInfo *) image->cache;
5109  assert(cache_info->signature == MagickCoreSignature);
5110  if (cache_info->type == UndefinedCache)
5111  return(MagickFalse);
5112  if (nexus_info->authentic_pixel_cache != MagickFalse)
5113  {
5114  image->taint=MagickTrue;
5115  return(MagickTrue);
5116  }
5117  assert(cache_info->signature == MagickCoreSignature);
5118  status=WritePixelCachePixels(cache_info,nexus_info,exception);
5119  if ((cache_info->metacontent_extent != 0) &&
5120  (WritePixelCacheMetacontent(cache_info,nexus_info,exception) == MagickFalse))
5121  return(MagickFalse);
5122  if (status != MagickFalse)
5123  image->taint=MagickTrue;
5124  return(status);
5125 }
5126 
5127 /*
5128 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5129 % %
5130 % %
5131 % %
5132 + S y n c A u t h e n t i c P i x e l C a c h e %
5133 % %
5134 % %
5135 % %
5136 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5137 %
5138 % SyncAuthenticPixelsCache() saves the authentic image pixels to the in-memory
5139 % or disk cache. The method returns MagickTrue if the pixel region is synced,
5140 % otherwise MagickFalse.
5141 %
5142 % The format of the SyncAuthenticPixelsCache() method is:
5143 %
5144 % MagickBooleanType SyncAuthenticPixelsCache(Image *image,
5145 % ExceptionInfo *exception)
5146 %
5147 % A description of each parameter follows:
5148 %
5149 % o image: the image.
5150 %
5151 % o exception: return any errors or warnings in this structure.
5152 %
5153 */
5155  ExceptionInfo *exception)
5156 {
5157  CacheInfo
5158  *magick_restrict cache_info;
5159 
5160  const int
5161  id = GetOpenMPThreadId();
5162 
5164  status;
5165 
5166  assert(image != (Image *) NULL);
5167  assert(image->signature == MagickCoreSignature);
5168  assert(image->cache != (Cache) NULL);
5169  cache_info=(CacheInfo *) image->cache;
5170  assert(cache_info->signature == MagickCoreSignature);
5171  assert(id < (int) cache_info->number_threads);
5172  status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5173  exception);
5174  return(status);
5175 }
5176 
5177 /*
5178 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5179 % %
5180 % %
5181 % %
5182 % S y n c A u t h e n t i c P i x e l s %
5183 % %
5184 % %
5185 % %
5186 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5187 %
5188 % SyncAuthenticPixels() saves the image pixels to the in-memory or disk cache.
5189 % The method returns MagickTrue if the pixel region is flushed, otherwise
5190 % MagickFalse.
5191 %
5192 % The format of the SyncAuthenticPixels() method is:
5193 %
5194 % MagickBooleanType SyncAuthenticPixels(Image *image,
5195 % ExceptionInfo *exception)
5196 %
5197 % A description of each parameter follows:
5198 %
5199 % o image: the image.
5200 %
5201 % o exception: return any errors or warnings in this structure.
5202 %
5203 */
5205  ExceptionInfo *exception)
5206 {
5207  CacheInfo
5208  *magick_restrict cache_info;
5209 
5210  const int
5211  id = GetOpenMPThreadId();
5212 
5214  status;
5215 
5216  assert(image != (Image *) NULL);
5217  assert(image->signature == MagickCoreSignature);
5218  assert(image->cache != (Cache) NULL);
5219  cache_info=(CacheInfo *) image->cache;
5220  assert(cache_info->signature == MagickCoreSignature);
5221  if (cache_info->methods.sync_authentic_pixels_handler !=
5223  {
5224  status=cache_info->methods.sync_authentic_pixels_handler(image,
5225  exception);
5226  return(status);
5227  }
5228  assert(id < (int) cache_info->number_threads);
5229  status=SyncAuthenticPixelCacheNexus(image,cache_info->nexus_info[id],
5230  exception);
5231  return(status);
5232 }
5233 
5234 /*
5235 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5236 % %
5237 % %
5238 % %
5239 + S y n c I m a g e P i x e l C a c h e %
5240 % %
5241 % %
5242 % %
5243 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5244 %
5245 % SyncImagePixelCache() saves the image pixels to the in-memory or disk cache.
5246 % The method returns MagickTrue if the pixel region is flushed, otherwise
5247 % MagickFalse.
5248 %
5249 % The format of the SyncImagePixelCache() method is:
5250 %
5251 % MagickBooleanType SyncImagePixelCache(Image *image,
5252 % ExceptionInfo *exception)
5253 %
5254 % A description of each parameter follows:
5255 %
5256 % o image: the image.
5257 %
5258 % o exception: return any errors or warnings in this structure.
5259 %
5260 */
5262  ExceptionInfo *exception)
5263 {
5264  CacheInfo
5265  *magick_restrict cache_info;
5266 
5267  assert(image != (Image *) NULL);
5268  assert(exception != (ExceptionInfo *) NULL);
5269  cache_info=(CacheInfo *) GetImagePixelCache(image,MagickTrue,exception);
5270  return(cache_info == (CacheInfo *) NULL ? MagickFalse : MagickTrue);
5271 }
5272 
5273 /*
5274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5275 % %
5276 % %
5277 % %
5278 + 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 %
5279 % %
5280 % %
5281 % %
5282 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5283 %
5284 % WritePixelCacheMetacontent() writes the meta-content to the specified region
5285 % of the pixel cache.
5286 %
5287 % The format of the WritePixelCacheMetacontent() method is:
5288 %
5289 % MagickBooleanType WritePixelCacheMetacontent(CacheInfo *cache_info,
5290 % NexusInfo *nexus_info,ExceptionInfo *exception)
5291 %
5292 % A description of each parameter follows:
5293 %
5294 % o cache_info: the pixel cache.
5295 %
5296 % o nexus_info: the cache nexus to write the meta-content.
5297 %
5298 % o exception: return any errors or warnings in this structure.
5299 %
5300 */
5302  NexusInfo *magick_restrict nexus_info,ExceptionInfo *exception)
5303 {
5305  count,
5306  offset;
5307 
5309  extent,
5310  length;
5311 
5312  register const unsigned char
5313  *magick_restrict p;
5314 
5315  register ssize_t
5316  y;
5317 
5318  size_t
5319  rows;
5320 
5321  if (cache_info->metacontent_extent == 0)
5322  return(MagickFalse);
5323  if (nexus_info->authentic_pixel_cache != MagickFalse)
5324  return(MagickTrue);
5325  offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5326  nexus_info->region.x;
5327  length=(MagickSizeType) nexus_info->region.width*
5328  cache_info->metacontent_extent;
5329  extent=(MagickSizeType) length*nexus_info->region.height;
5330  rows=nexus_info->region.height;
5331  y=0;
5332  p=(unsigned char *) nexus_info->metacontent;
5333  switch (cache_info->type)
5334  {
5335  case MemoryCache:
5336  case MapCache:
5337  {
5338  register unsigned char
5339  *magick_restrict q;
5340 
5341  /*
5342  Write associated pixels to memory.
5343  */
5344  if ((cache_info->columns == nexus_info->region.width) &&
5345  (extent == (MagickSizeType) ((size_t) extent)))
5346  {
5347  length=extent;
5348  rows=1UL;
5349  }
5350  q=(unsigned char *) cache_info->metacontent+offset*
5351  cache_info->metacontent_extent;
5352  for (y=0; y < (ssize_t) rows; y++)
5353  {
5354  (void) memcpy(q,p,(size_t) length);
5355  p+=nexus_info->region.width*cache_info->metacontent_extent;
5356  q+=cache_info->columns*cache_info->metacontent_extent;
5357  }
5358  break;
5359  }
5360  case DiskCache:
5361  {
5362  /*
5363  Write associated pixels to disk.
5364  */
5365  LockSemaphoreInfo(cache_info->file_semaphore);
5366  if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5367  {
5368  ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5369  cache_info->cache_filename);
5370  UnlockSemaphoreInfo(cache_info->file_semaphore);
5371  return(MagickFalse);
5372  }
5373  if ((cache_info->columns == nexus_info->region.width) &&
5374  (extent <= MagickMaxBufferExtent))
5375  {
5376  length=extent;
5377  rows=1UL;
5378  }
5379  extent=(MagickSizeType) cache_info->columns*cache_info->rows;
5380  for (y=0; y < (ssize_t) rows; y++)
5381  {
5382  count=WritePixelCacheRegion(cache_info,cache_info->offset+extent*
5383  cache_info->number_channels*sizeof(Quantum)+offset*
5384  cache_info->metacontent_extent,length,(const unsigned char *) p);
5385  if (count != (MagickOffsetType) length)
5386  break;
5387  p+=cache_info->metacontent_extent*nexus_info->region.width;
5388  offset+=cache_info->columns;
5389  }
5391  (void) ClosePixelCacheOnDisk(cache_info);
5392  UnlockSemaphoreInfo(cache_info->file_semaphore);
5393  break;
5394  }
5395  case DistributedCache:
5396  {
5398  region;
5399 
5400  /*
5401  Write metacontent to distributed cache.
5402  */
5403  LockSemaphoreInfo(cache_info->file_semaphore);
5404  region=nexus_info->region;
5405  if ((cache_info->columns != nexus_info->region.width) ||
5406  (extent > MagickMaxBufferExtent))
5407  region.height=1UL;
5408  else
5409  {
5410  length=extent;
5411  rows=1UL;
5412  }
5413  for (y=0; y < (ssize_t) rows; y++)
5414  {
5416  cache_info->server_info,&region,length,(const unsigned char *) p);
5417  if (count != (MagickOffsetType) length)
5418  break;
5419  p+=cache_info->metacontent_extent*nexus_info->region.width;
5420  region.y++;
5421  }
5422  UnlockSemaphoreInfo(cache_info->file_semaphore);
5423  break;
5424  }
5425  default:
5426  break;
5427  }
5428  if (y < (ssize_t) rows)
5429  {
5430  ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5431  cache_info->cache_filename);
5432  return(MagickFalse);
5433  }
5434  if ((cache_info->debug != MagickFalse) &&
5435  (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5437  "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5438  nexus_info->region.width,(double) nexus_info->region.height,(double)
5439  nexus_info->region.x,(double) nexus_info->region.y);
5440  return(MagickTrue);
5441 }
5442 
5443 /*
5444 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5445 % %
5446 % %
5447 % %
5448 + W r i t e C a c h e P i x e l s %
5449 % %
5450 % %
5451 % %
5452 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5453 %
5454 % WritePixelCachePixels() writes image pixels to the specified region of the
5455 % pixel cache.
5456 %
5457 % The format of the WritePixelCachePixels() method is:
5458 %
5459 % MagickBooleanType WritePixelCachePixels(CacheInfo *cache_info,
5460 % NexusInfo *nexus_info,ExceptionInfo *exception)
5461 %
5462 % A description of each parameter follows:
5463 %
5464 % o cache_info: the pixel cache.
5465 %
5466 % o nexus_info: the cache nexus to write the pixels.
5467 %
5468 % o exception: return any errors or warnings in this structure.
5469 %
5470 */
5472  CacheInfo *magick_restrict cache_info,NexusInfo *magick_restrict nexus_info,
5473  ExceptionInfo *exception)
5474 {
5476  count,
5477  offset;
5478 
5480  extent,
5481  length;
5482 
5483  register const Quantum
5484  *magick_restrict p;
5485 
5486  register ssize_t
5487  y;
5488 
5489  size_t
5490  rows;
5491 
5492  if (nexus_info->authentic_pixel_cache != MagickFalse)
5493  return(MagickTrue);
5494  offset=(MagickOffsetType) nexus_info->region.y*cache_info->columns+
5495  nexus_info->region.x;
5496  length=(MagickSizeType) cache_info->number_channels*nexus_info->region.width*
5497  sizeof(Quantum);
5498  extent=length*nexus_info->region.height;
5499  rows=nexus_info->region.height;
5500  y=0;
5501  p=nexus_info->pixels;
5502  switch (cache_info->type)
5503  {
5504  case MemoryCache:
5505  case MapCache:
5506  {
5507  register Quantum
5508  *magick_restrict q;
5509 
5510  /*
5511  Write pixels to memory.
5512  */
5513  if ((cache_info->columns == nexus_info->region.width) &&
5514  (extent == (MagickSizeType) ((size_t) extent)))
5515  {
5516  length=extent;
5517  rows=1UL;
5518  }
5519  q=cache_info->pixels+offset*cache_info->number_channels;
5520  for (y=0; y < (ssize_t) rows; y++)
5521  {
5522  (void) memcpy(q,p,(size_t) length);
5523  p+=cache_info->number_channels*nexus_info->region.width;
5524  q+=cache_info->number_channels*cache_info->columns;
5525  }
5526  break;
5527  }
5528  case DiskCache:
5529  {
5530  /*
5531  Write pixels to disk.
5532  */
5533  LockSemaphoreInfo(cache_info->file_semaphore);
5534  if (OpenPixelCacheOnDisk(cache_info,IOMode) == MagickFalse)
5535  {
5536  ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
5537  cache_info->cache_filename);
5538  UnlockSemaphoreInfo(cache_info->file_semaphore);
5539  return(MagickFalse);
5540  }
5541  if ((cache_info->columns == nexus_info->region.width) &&
5542  (extent <= MagickMaxBufferExtent))
5543  {
5544  length=extent;
5545  rows=1UL;
5546  }
5547  for (y=0; y < (ssize_t) rows; y++)
5548  {
5549  count=WritePixelCacheRegion(cache_info,cache_info->offset+offset*
5550  cache_info->number_channels*sizeof(*p),length,(const unsigned char *)
5551  p);
5552  if (count != (MagickOffsetType) length)
5553  break;
5554  p+=cache_info->number_channels*nexus_info->region.width;
5555  offset+=cache_info->columns;
5556  }
5558  (void) ClosePixelCacheOnDisk(cache_info);
5559  UnlockSemaphoreInfo(cache_info->file_semaphore);
5560  break;
5561  }
5562  case DistributedCache:
5563  {
5565  region;
5566 
5567  /*
5568  Write pixels to distributed cache.
5569  */
5570  LockSemaphoreInfo(cache_info->file_semaphore);
5571  region=nexus_info->region;
5572  if ((cache_info->columns != nexus_info->region.width) ||
5573  (extent > MagickMaxBufferExtent))
5574  region.height=1UL;
5575  else
5576  {
5577  length=extent;
5578  rows=1UL;
5579  }
5580  for (y=0; y < (ssize_t) rows; y++)
5581  {
5583  cache_info->server_info,&region,length,(const unsigned char *) p);
5584  if (count != (MagickOffsetType) length)
5585  break;
5586  p+=cache_info->number_channels*nexus_info->region.width;
5587  region.y++;
5588  }
5589  UnlockSemaphoreInfo(cache_info->file_semaphore);
5590  break;
5591  }
5592  default:
5593  break;
5594  }
5595  if (y < (ssize_t) rows)
5596  {
5597  ThrowFileException(exception,CacheError,"UnableToWritePixelCache",
5598  cache_info->cache_filename);
5599  return(MagickFalse);
5600  }
5601  if ((cache_info->debug != MagickFalse) &&
5602  (CacheTick(nexus_info->region.y,cache_info->rows) != MagickFalse))
5604  "%s[%.20gx%.20g%+.20g%+.20g]",cache_info->filename,(double)
5605  nexus_info->region.width,(double) nexus_info->region.height,(double)
5606  nexus_info->region.x,(double) nexus_info->region.y);
5607  return(MagickTrue);
5608 }
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
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:4595
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:5471
MagickBooleanType read_mask
Definition: image.h:276
static MagickOffsetType WritePixelCacheRegion(const CacheInfo *magick_restrict cache_info, const MagickOffsetType offset, const MagickSizeType length, const unsigned char *magick_restrict buffer)
Definition: cache.c:3347
static Quantum * QueueAuthenticPixelsCache(Image *image, const ssize_t x, const ssize_t y, const size_t columns, const size_t rows, ExceptionInfo *exception)
Definition: cache.c:4014
MagickExport MagickBooleanType GetOneVirtualPixel(const Image *image, const ssize_t x, const ssize_t y, Quantum *pixel, ExceptionInfo *exception)
Definition: cache.c:1880
MagickBooleanType authentic_pixel_cache
MagickBooleanType debug
MagickExport ssize_t FormatLocaleString(char *magick_restrict string, const size_t length, const char *magick_restrict format,...)
Definition: locale.c:473
static MagickBooleanType IsGrayColorspace(const ColorspaceType colorspace)
MagickPrivate void GetPixelCacheTileSize(const Image *image, size_t *width, size_t *height)
Definition: cache.c:2298
GetOneVirtualPixelFromHandler get_one_virtual_pixel_from_handler
Definition: cache-private.h:80
MagickCLCacheInfo opencl
static const Quantum * GetVirt