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