MagickCore  7.1.1-43
Convert, Edit, Or Compose Bitmap Images
image.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % IIIII M M AAA GGGG EEEEE %
7 % I MM MM A A G E %
8 % I M M M AAAAA G GG EEE %
9 % I M M A A G G E %
10 % IIIII M M A A GGGG EEEEE %
11 % %
12 % %
13 % MagickCore Image Methods %
14 % %
15 % Software Design %
16 % Cristy %
17 % July 1992 %
18 % %
19 % %
20 % Copyright @ 1999 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://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/animate.h"
45 #include "MagickCore/artifact.h"
46 #include "MagickCore/attribute.h"
47 #include "MagickCore/blob.h"
48 #include "MagickCore/blob-private.h"
49 #include "MagickCore/cache.h"
50 #include "MagickCore/cache-private.h"
51 #include "MagickCore/cache-view.h"
52 #include "MagickCore/channel.h"
53 #include "MagickCore/client.h"
54 #include "MagickCore/color.h"
55 #include "MagickCore/color-private.h"
56 #include "MagickCore/colormap.h"
57 #include "MagickCore/colorspace.h"
58 #include "MagickCore/colorspace-private.h"
59 #include "MagickCore/composite.h"
60 #include "MagickCore/composite-private.h"
61 #include "MagickCore/compress.h"
62 #include "MagickCore/constitute.h"
63 #include "MagickCore/delegate.h"
64 #include "MagickCore/display.h"
65 #include "MagickCore/draw.h"
66 #include "MagickCore/enhance.h"
67 #include "MagickCore/exception.h"
68 #include "MagickCore/exception-private.h"
69 #include "MagickCore/gem.h"
70 #include "MagickCore/geometry.h"
71 #include "MagickCore/histogram.h"
72 #include "MagickCore/image-private.h"
73 #include "MagickCore/list.h"
74 #include "MagickCore/magic.h"
75 #include "MagickCore/magick.h"
76 #include "MagickCore/magick-private.h"
77 #include "MagickCore/memory_.h"
78 #include "MagickCore/memory-private.h"
79 #include "MagickCore/module.h"
80 #include "MagickCore/monitor.h"
81 #include "MagickCore/monitor-private.h"
82 #include "MagickCore/option.h"
83 #include "MagickCore/paint.h"
84 #include "MagickCore/pixel-accessor.h"
85 #include "MagickCore/profile.h"
86 #include "MagickCore/property.h"
87 #include "MagickCore/quantize.h"
88 #include "MagickCore/random_.h"
89 #include "MagickCore/resource_.h"
90 #include "MagickCore/segment.h"
91 #include "MagickCore/semaphore.h"
92 #include "MagickCore/signature-private.h"
93 #include "MagickCore/statistic.h"
94 #include "MagickCore/string_.h"
95 #include "MagickCore/string-private.h"
96 #include "MagickCore/thread-private.h"
97 #include "MagickCore/threshold.h"
98 #include "MagickCore/timer.h"
99 #include "MagickCore/timer-private.h"
100 #include "MagickCore/token.h"
101 #include "MagickCore/token-private.h"
102 #include "MagickCore/utility.h"
103 #include "MagickCore/utility-private.h"
104 #include "MagickCore/version.h"
105 #include "MagickCore/xwindow-private.h"
106 
107 /*
108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
109 % %
110 % %
111 % %
112 % A c q u i r e I m a g e %
113 % %
114 % %
115 % %
116 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
117 %
118 % AcquireImage() returns a pointer to an image structure initialized to
119 % default values.
120 %
121 % The format of the AcquireImage method is:
122 %
123 % Image *AcquireImage(const ImageInfo *image_info,ExceptionInfo *exception)
124 %
125 % A description of each parameter follows:
126 %
127 % o image_info: Many of the image default values are set from this
128 % structure. For example, filename, compression, depth, background color,
129 % and others.
130 %
131 % o exception: return any errors or warnings in this structure.
132 %
133 */
134 MagickExport Image *AcquireImage(const ImageInfo *image_info,
135  ExceptionInfo *exception)
136 {
137  const char
138  *option;
139 
140  Image
141  *image;
142 
143  int
144  time_limit;
145 
146  MagickStatusType
147  flags;
148 
149  /*
150  Allocate image structure.
151  */
152  if (IsEventLogging() != MagickFalse)
153  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
154  image=(Image *) AcquireCriticalMemory(sizeof(*image));
155  (void) memset(image,0,sizeof(*image));
156  /*
157  Initialize Image structure.
158  */
159  (void) CopyMagickString(image->magick,"MIFF",MagickPathExtent);
160  image->storage_class=DirectClass;
161  image->depth=MAGICKCORE_QUANTUM_DEPTH;
162  image->colorspace=sRGBColorspace;
163  image->rendering_intent=PerceptualIntent;
164  image->gamma=1.000/2.200;
165  image->chromaticity.red_primary.x=0.6400;
166  image->chromaticity.red_primary.y=0.3300;
167  image->chromaticity.red_primary.z=0.0300;
168  image->chromaticity.green_primary.x=0.3000;
169  image->chromaticity.green_primary.y=0.6000;
170  image->chromaticity.green_primary.z=0.1000;
171  image->chromaticity.blue_primary.x=0.1500;
172  image->chromaticity.blue_primary.y=0.0600;
173  image->chromaticity.blue_primary.z=0.7900;
174  image->chromaticity.white_point.x=0.3127;
175  image->chromaticity.white_point.y=0.3290;
176  image->chromaticity.white_point.z=0.3583;
177  image->interlace=NoInterlace;
178  image->ticks_per_second=UndefinedTicksPerSecond;
179  image->compose=OverCompositeOp;
180  GetPixelInfoRGBA(BackgroundColorRGBA,&image->background_color);
181  GetPixelInfoRGBA(BorderColorRGBA,&image->border_color);
182  GetPixelInfoRGBA(MatteColorRGBA,&image->matte_color);
183  GetPixelInfoRGBA(TransparentColorRGBA,&image->transparent_color);
184  GetTimerInfo(&image->timer);
185  image->cache=AcquirePixelCache(0);
186  image->channel_mask=AllChannels;
187  image->channel_map=AcquirePixelChannelMap();
188  image->blob=CloneBlobInfo((BlobInfo *) NULL);
189  image->timestamp=GetMagickTime();
190  time_limit=(int) GetMagickResourceLimit(TimeResource);
191  if (time_limit > 0)
192  image->ttl=image->timestamp+time_limit;
193  image->debug=(GetLogEventMask() & (ImageEvent | TransformEvent | CoderEvent))
194  != 0 ? MagickTrue : MagickFalse;
195  image->reference_count=1;
196  image->semaphore=AcquireSemaphoreInfo();
197  image->signature=MagickCoreSignature;
198  if (image_info == (ImageInfo *) NULL)
199  return(image);
200  /*
201  Transfer image info.
202  */
203  SetBlobExempt(image,image_info->file != (FILE *) NULL ? MagickTrue :
204  MagickFalse);
205  (void) CopyMagickString(image->filename,image_info->filename,
206  MagickPathExtent);
207  (void) CopyMagickString(image->magick_filename,image_info->filename,
208  MagickPathExtent);
209  (void) CopyMagickString(image->magick,image_info->magick,MagickPathExtent);
210  if (image_info->size != (char *) NULL)
211  {
212  (void) ParseAbsoluteGeometry(image_info->size,&image->extract_info);
213  image->columns=image->extract_info.width;
214  image->rows=image->extract_info.height;
215  image->offset=image->extract_info.x;
216  image->extract_info.x=0;
217  image->extract_info.y=0;
218  }
219  if (image_info->extract != (char *) NULL)
220  {
222  geometry;
223 
224  (void) memset(&geometry,0,sizeof(geometry));
225  flags=ParseAbsoluteGeometry(image_info->extract,&geometry);
226  if (((flags & XValue) != 0) || ((flags & YValue) != 0))
227  {
228  image->extract_info=geometry;
229  Swap(image->columns,image->extract_info.width);
230  Swap(image->rows,image->extract_info.height);
231  }
232  }
233  image->compression=image_info->compression;
234  image->quality=image_info->quality;
235  image->endian=image_info->endian;
236  image->interlace=image_info->interlace;
237  image->units=image_info->units;
238  if (image_info->density != (char *) NULL)
239  {
241  geometry_info;
242 
243  flags=ParseGeometry(image_info->density,&geometry_info);
244  if ((flags & RhoValue) != 0)
245  image->resolution.x=geometry_info.rho;
246  image->resolution.y=image->resolution.x;
247  if ((flags & SigmaValue) != 0)
248  image->resolution.y=geometry_info.sigma;
249  }
250  if (image_info->page != (char *) NULL)
251  {
252  char
253  *geometry;
254 
255  image->page=image->extract_info;
256  geometry=GetPageGeometry(image_info->page);
257  (void) ParseAbsoluteGeometry(geometry,&image->page);
258  geometry=DestroyString(geometry);
259  }
260  if (image_info->depth != 0)
261  image->depth=image_info->depth;
262  image->dither=image_info->dither;
263  image->matte_color=image_info->matte_color;
264  image->background_color=image_info->background_color;
265  image->border_color=image_info->border_color;
266  image->transparent_color=image_info->transparent_color;
267  image->ping=image_info->ping;
268  image->progress_monitor=image_info->progress_monitor;
269  image->client_data=image_info->client_data;
270  if (image_info->cache != (void *) NULL)
271  ClonePixelCacheMethods(image->cache,image_info->cache);
272  /*
273  Set all global options that map to per-image settings.
274  */
275  (void) SyncImageSettings(image_info,image,exception);
276  /*
277  Global options that are only set for new images.
278  */
279  option=GetImageOption(image_info,"delay");
280  if (option != (const char *) NULL)
281  {
283  geometry_info;
284 
285  flags=ParseGeometry(option,&geometry_info);
286  if ((flags & GreaterValue) != 0)
287  {
288  if ((double) image->delay > floor(geometry_info.rho+0.5))
289  image->delay=(size_t) CastDoubleToLong(floor(
290  geometry_info.rho+0.5));
291  }
292  else
293  if ((flags & LessValue) != 0)
294  {
295  if ((double) image->delay < floor(geometry_info.rho+0.5))
296  image->ticks_per_second=CastDoubleToLong(floor(
297  geometry_info.sigma+0.5));
298  }
299  else
300  image->delay=(size_t) CastDoubleToLong(floor(geometry_info.rho+0.5));
301  if ((flags & SigmaValue) != 0)
302  image->ticks_per_second=CastDoubleToLong(floor(
303  geometry_info.sigma+0.5));
304  }
305  option=GetImageOption(image_info,"dispose");
306  if (option != (const char *) NULL)
307  image->dispose=(DisposeType) ParseCommandOption(MagickDisposeOptions,
308  MagickFalse,option);
309  return(image);
310 }
311 
312 /*
313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
314 % %
315 % %
316 % %
317 % A c q u i r e I m a g e I n f o %
318 % %
319 % %
320 % %
321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
322 %
323 % AcquireImageInfo() allocates the ImageInfo structure.
324 %
325 % The format of the AcquireImageInfo method is:
326 %
327 % ImageInfo *AcquireImageInfo(void)
328 %
329 */
330 MagickExport ImageInfo *AcquireImageInfo(void)
331 {
332  ImageInfo
333  *image_info;
334 
335  image_info=(ImageInfo *) AcquireCriticalMemory(sizeof(*image_info));
336  GetImageInfo(image_info);
337  return(image_info);
338 }
339 
340 /*
341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
342 % %
343 % %
344 % %
345 % A c q u i r e N e x t I m a g e %
346 % %
347 % %
348 % %
349 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
350 %
351 % AcquireNextImage() initializes the next image in a sequence to
352 % default values. The next member of image points to the newly allocated
353 % image. If there is a memory shortage, next is assigned NULL.
354 %
355 % The format of the AcquireNextImage method is:
356 %
357 % void AcquireNextImage(const ImageInfo *image_info,Image *image,
358 % ExceptionInfo *exception)
359 %
360 % A description of each parameter follows:
361 %
362 % o image_info: Many of the image default values are set from this
363 % structure. For example, filename, compression, depth, background color,
364 % and others.
365 %
366 % o image: the image.
367 %
368 % o exception: return any errors or warnings in this structure.
369 %
370 */
371 MagickExport void AcquireNextImage(const ImageInfo *image_info,Image *image,
372  ExceptionInfo *exception)
373 {
374  /*
375  Allocate image structure.
376  */
377  assert(image != (Image *) NULL);
378  assert(image->signature == MagickCoreSignature);
379  if (IsEventLogging() != MagickFalse)
380  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
381  image->next=AcquireImage(image_info,exception);
382  if (GetNextImageInList(image) == (Image *) NULL)
383  return;
384  (void) CopyMagickString(GetNextImageInList(image)->filename,image->filename,
385  MagickPathExtent);
386  if (image_info != (ImageInfo *) NULL)
387  (void) CopyMagickString(GetNextImageInList(image)->filename,
388  image_info->filename,MagickPathExtent);
389  DestroyBlob(GetNextImageInList(image));
390  image->next->blob=ReferenceBlob(image->blob);
391  image->next->endian=image->endian;
392  image->next->scene=image->scene+1;
393  image->next->previous=image;
394 }
395 
396 /*
397 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
398 % %
399 % %
400 % %
401 % A p p e n d I m a g e s %
402 % %
403 % %
404 % %
405 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
406 %
407 % AppendImages() takes all images from the current image pointer to the end
408 % of the image list and appends them to each other top-to-bottom if the
409 % stack parameter is true, otherwise left-to-right.
410 %
411 % The current gravity setting effects how the image is justified in the
412 % final image.
413 %
414 % The format of the AppendImages method is:
415 %
416 % Image *AppendImages(const Image *images,const MagickBooleanType stack,
417 % ExceptionInfo *exception)
418 %
419 % A description of each parameter follows:
420 %
421 % o images: the image sequence.
422 %
423 % o stack: A value other than 0 stacks the images top-to-bottom.
424 %
425 % o exception: return any errors or warnings in this structure.
426 %
427 */
428 MagickExport Image *AppendImages(const Image *images,
429  const MagickBooleanType stack,ExceptionInfo *exception)
430 {
431 #define AppendImageTag "Append/Image"
432 
433  CacheView
434  *append_view;
435 
436  Image
437  *append_image;
438 
439  ImageType
440  image_type;
441 
442  MagickBooleanType
443  homogeneous_colorspace,
444  status;
445 
446  MagickOffsetType
447  n;
448 
449  PixelTrait
450  alpha_trait;
451 
453  geometry;
454 
455  const Image
456  *next;
457 
458  size_t
459  depth,
460  height,
461  number_images,
462  width;
463 
464  ssize_t
465  x_offset,
466  y,
467  y_offset;
468 
469  /*
470  Compute maximum area of appended area.
471  */
472  assert(images != (Image *) NULL);
473  assert(images->signature == MagickCoreSignature);
474  assert(exception != (ExceptionInfo *) NULL);
475  assert(exception->signature == MagickCoreSignature);
476  if (IsEventLogging() != MagickFalse)
477  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
478  alpha_trait=images->alpha_trait;
479  number_images=1;
480  width=images->columns;
481  height=images->rows;
482  depth=images->depth;
483  image_type=images->type;
484  homogeneous_colorspace=MagickTrue;
485  next=GetNextImageInList(images);
486  for ( ; next != (Image *) NULL; next=GetNextImageInList(next))
487  {
488  if (next->depth > depth)
489  depth=next->depth;
490  if (next->type != images->type)
491  image_type=UndefinedType;
492  if (next->colorspace != images->colorspace)
493  homogeneous_colorspace=MagickFalse;
494  if (next->alpha_trait != UndefinedPixelTrait)
495  alpha_trait=BlendPixelTrait;
496  number_images++;
497  if (stack != MagickFalse)
498  {
499  if (next->columns > width)
500  width=next->columns;
501  height+=next->rows;
502  continue;
503  }
504  width+=next->columns;
505  if (next->rows > height)
506  height=next->rows;
507  }
508  /*
509  Append images.
510  */
511  append_image=CloneImage(images,width,height,MagickTrue,exception);
512  if (append_image == (Image *) NULL)
513  return((Image *) NULL);
514  if (image_type != BilevelType)
515  {
516  if (SetImageStorageClass(append_image,DirectClass,exception) == MagickFalse)
517  {
518  append_image=DestroyImage(append_image);
519  return((Image *) NULL);
520  }
521  if (homogeneous_colorspace == MagickFalse)
522  (void) SetImageColorspace(append_image,sRGBColorspace,exception);
523  }
524  append_image->depth=depth;
525  append_image->alpha_trait=alpha_trait;
526  append_image->page=images->page;
527  (void) SetImageBackgroundColor(append_image,exception);
528  status=MagickTrue;
529  x_offset=0;
530  y_offset=0;
531  next=images;
532  append_view=AcquireAuthenticCacheView(append_image,exception);
533  for (n=0; n < (MagickOffsetType) number_images; n++)
534  {
535  CacheView
536  *image_view;
537 
538  MagickBooleanType
539  proceed;
540 
541  SetGeometry(append_image,&geometry);
542  GravityAdjustGeometry(next->columns,next->rows,next->gravity,&geometry);
543  if (stack != MagickFalse)
544  x_offset-=geometry.x;
545  else
546  y_offset-=geometry.y;
547  image_view=AcquireVirtualCacheView(next,exception);
548 #if defined(MAGICKCORE_OPENMP_SUPPORT)
549  #pragma omp parallel for schedule(static) shared(status) \
550  magick_number_threads(next,next,next->rows,2)
551 #endif
552  for (y=0; y < (ssize_t) next->rows; y++)
553  {
554  MagickBooleanType
555  sync;
556 
557  PixelInfo
558  pixel;
559 
560  const Quantum
561  *magick_restrict p;
562 
563  Quantum
564  *magick_restrict q;
565 
566  ssize_t
567  x;
568 
569  if (status == MagickFalse)
570  continue;
571  p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
572  q=QueueCacheViewAuthenticPixels(append_view,x_offset,y+y_offset,
573  next->columns,1,exception);
574  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
575  {
576  status=MagickFalse;
577  continue;
578  }
579  GetPixelInfo(next,&pixel);
580  for (x=0; x < (ssize_t) next->columns; x++)
581  {
582  GetPixelInfoPixel(next,p,&pixel);
583  SetPixelViaPixelInfo(append_image,&pixel,q);
584  p+=(ptrdiff_t) GetPixelChannels(next);
585  q+=(ptrdiff_t) GetPixelChannels(append_image);
586  }
587  sync=SyncCacheViewAuthenticPixels(append_view,exception);
588  if (sync == MagickFalse)
589  status=MagickFalse;
590  }
591  image_view=DestroyCacheView(image_view);
592  if (stack == MagickFalse)
593  {
594  x_offset+=(ssize_t) next->columns;
595  y_offset=0;
596  }
597  else
598  {
599  x_offset=0;
600  y_offset+=(ssize_t) next->rows;
601  }
602  proceed=SetImageProgress(append_image,AppendImageTag,n,number_images);
603  if (proceed == MagickFalse)
604  break;
605  next=GetNextImageInList(next);
606  }
607  append_view=DestroyCacheView(append_view);
608  if (status == MagickFalse)
609  append_image=DestroyImage(append_image);
610  return(append_image);
611 }
612 
613 /*
614 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
615 % %
616 % %
617 % %
618 % C a t c h I m a g e E x c e p t i o n %
619 % %
620 % %
621 % %
622 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
623 %
624 % CatchImageException() returns if no exceptions are found in the image
625 % sequence, otherwise it determines the most severe exception and reports
626 % it as a warning or error depending on the severity.
627 %
628 % The format of the CatchImageException method is:
629 %
630 % ExceptionType CatchImageException(Image *image)
631 %
632 % A description of each parameter follows:
633 %
634 % o image: An image sequence.
635 %
636 */
637 MagickExport ExceptionType CatchImageException(Image *image)
638 {
640  *exception;
641 
642  ExceptionType
643  severity;
644 
645  assert(image != (const Image *) NULL);
646  assert(image->signature == MagickCoreSignature);
647  if (IsEventLogging() != MagickFalse)
648  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
649  exception=AcquireExceptionInfo();
650  CatchException(exception);
651  severity=exception->severity;
652  exception=DestroyExceptionInfo(exception);
653  return(severity);
654 }
655 
656 /*
657 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
658 % %
659 % %
660 % %
661 % C l i p I m a g e P a t h %
662 % %
663 % %
664 % %
665 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
666 %
667 % ClipImagePath() sets the image clip mask based any clipping path information
668 % if it exists.
669 %
670 % The format of the ClipImagePath method is:
671 %
672 % MagickBooleanType ClipImagePath(Image *image,const char *pathname,
673 % const MagickBooleanType inside,ExceptionInfo *exception)
674 %
675 % A description of each parameter follows:
676 %
677 % o image: the image.
678 %
679 % o pathname: name of clipping path resource. If name is preceded by #, use
680 % clipping path numbered by name.
681 %
682 % o inside: if non-zero, later operations take effect inside clipping path.
683 % Otherwise later operations take effect outside clipping path.
684 %
685 % o exception: return any errors or warnings in this structure.
686 %
687 */
688 
689 MagickExport MagickBooleanType ClipImage(Image *image,ExceptionInfo *exception)
690 {
691  return(ClipImagePath(image,"#1",MagickTrue,exception));
692 }
693 
694 MagickExport MagickBooleanType ClipImagePath(Image *image,const char *pathname,
695  const MagickBooleanType inside,ExceptionInfo *exception)
696 {
697 #define ClipImagePathTag "ClipPath/Image"
698 
699  char
700  *property;
701 
702  const char
703  *value;
704 
705  Image
706  *clip_mask;
707 
708  ImageInfo
709  *image_info;
710 
711  assert(image != (const Image *) NULL);
712  assert(image->signature == MagickCoreSignature);
713  assert(pathname != NULL);
714  if (IsEventLogging() != MagickFalse)
715  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
716  property=AcquireString(pathname);
717  (void) FormatLocaleString(property,MagickPathExtent,"8BIM:1999,2998:%s",
718  pathname);
719  value=GetImageProperty(image,property,exception);
720  property=DestroyString(property);
721  if (value == (const char *) NULL)
722  {
723  ThrowFileException(exception,OptionError,"NoClipPathDefined",
724  image->filename);
725  return(MagickFalse);
726  }
727  image_info=AcquireImageInfo();
728  (void) CopyMagickString(image_info->filename,image->filename,
729  MagickPathExtent);
730  (void) ConcatenateMagickString(image_info->filename,pathname,
731  MagickPathExtent);
732  clip_mask=BlobToImage(image_info,value,strlen(value),exception);
733  image_info=DestroyImageInfo(image_info);
734  if (clip_mask == (Image *) NULL)
735  return(MagickFalse);
736  if (clip_mask->storage_class == PseudoClass)
737  {
738  (void) SyncImage(clip_mask,exception);
739  if (SetImageStorageClass(clip_mask,DirectClass,exception) == MagickFalse)
740  return(MagickFalse);
741  }
742  if (inside != MagickFalse)
743  (void) NegateImage(clip_mask,MagickFalse,exception);
744  (void) FormatLocaleString(clip_mask->magick_filename,MagickPathExtent,
745  "8BIM:1999,2998:%s\nPS",pathname);
746  (void) SetImageMask(image,WritePixelMask,clip_mask,exception);
747  image->mask_trait=UpdatePixelTrait;
748  clip_mask=DestroyImage(clip_mask);
749  return(MagickTrue);
750 }
751 
752 /*
753 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
754 % %
755 % %
756 % %
757 % C l o n e I m a g e %
758 % %
759 % %
760 % %
761 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
762 %
763 % CloneImage() copies an image and returns the copy as a new image object.
764 %
765 % If the specified columns and rows is 0, an exact copy of the image is
766 % returned, otherwise the pixel data is undefined and must be initialized
767 % with the QueueAuthenticPixels() and SyncAuthenticPixels() methods. On
768 % failure, a NULL image is returned and exception describes the reason for the
769 % failure.
770 %
771 % The format of the CloneImage method is:
772 %
773 % Image *CloneImage(const Image *image,const size_t columns,
774 % const size_t rows,const MagickBooleanType orphan,
775 % ExceptionInfo *exception)
776 %
777 % A description of each parameter follows:
778 %
779 % o image: the image.
780 %
781 % o columns: the number of columns in the cloned image.
782 %
783 % o rows: the number of rows in the cloned image.
784 %
785 % o detach: With a value other than 0, the cloned image is detached from
786 % its parent I/O stream.
787 %
788 % o exception: return any errors or warnings in this structure.
789 %
790 */
791 MagickExport Image *CloneImage(const Image *image,const size_t columns,
792  const size_t rows,const MagickBooleanType detach,ExceptionInfo *exception)
793 {
794  double
795  scale_x,
796  scale_y;
797 
798  Image
799  *clone_image;
800 
801  size_t
802  length;
803 
804  /*
805  Clone the image.
806  */
807  assert(image != (const Image *) NULL);
808  assert(image->signature == MagickCoreSignature);
809  assert(exception != (ExceptionInfo *) NULL);
810  assert(exception->signature == MagickCoreSignature);
811  if (IsEventLogging() != MagickFalse)
812  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
813  if ((image->columns == 0) || (image->rows == 0))
814  {
815  (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
816  "NegativeOrZeroImageSize","`%s'",image->filename);
817  return((Image *) NULL);
818  }
819  clone_image=(Image *) AcquireCriticalMemory(sizeof(*clone_image));
820  (void) memset(clone_image,0,sizeof(*clone_image));
821  clone_image->signature=MagickCoreSignature;
822  clone_image->storage_class=image->storage_class;
823  clone_image->number_channels=image->number_channels;
824  clone_image->number_meta_channels=image->number_meta_channels;
825  clone_image->metacontent_extent=image->metacontent_extent;
826  clone_image->colorspace=image->colorspace;
827  clone_image->alpha_trait=image->alpha_trait;
828  clone_image->channels=image->channels;
829  clone_image->mask_trait=image->mask_trait;
830  clone_image->columns=image->columns;
831  clone_image->rows=image->rows;
832  clone_image->dither=image->dither;
833  clone_image->image_info=CloneImageInfo(image->image_info);
834  (void) CloneImageProfiles(clone_image,image);
835  (void) CloneImageProperties(clone_image,image);
836  (void) CloneImageArtifacts(clone_image,image);
837  GetTimerInfo(&clone_image->timer);
838  if (image->ascii85 != (void *) NULL)
839  Ascii85Initialize(clone_image);
840  clone_image->extent=image->extent;
841  clone_image->magick_columns=image->magick_columns;
842  clone_image->magick_rows=image->magick_rows;
843  clone_image->type=image->type;
844  clone_image->channel_mask=image->channel_mask;
845  clone_image->channel_map=ClonePixelChannelMap(image->channel_map);
846  (void) CopyMagickString(clone_image->magick_filename,image->magick_filename,
847  MagickPathExtent);
848  (void) CopyMagickString(clone_image->magick,image->magick,MagickPathExtent);
849  (void) CopyMagickString(clone_image->filename,image->filename,
850  MagickPathExtent);
851  clone_image->progress_monitor=image->progress_monitor;
852  clone_image->client_data=image->client_data;
853  clone_image->reference_count=1;
854  clone_image->next=image->next;
855  clone_image->previous=image->previous;
856  clone_image->list=NewImageList();
857  if (detach == MagickFalse)
858  clone_image->blob=ReferenceBlob(image->blob);
859  else
860  {
861  clone_image->next=NewImageList();
862  clone_image->previous=NewImageList();
863  clone_image->blob=CloneBlobInfo((BlobInfo *) NULL);
864  }
865  clone_image->ping=image->ping;
866  clone_image->timestamp=image->timestamp;
867  clone_image->ttl=image->ttl;
868  clone_image->debug=image->debug;
869  clone_image->semaphore=AcquireSemaphoreInfo();
870  if (image->colormap != (PixelInfo *) NULL)
871  {
872  /*
873  Allocate and copy the image colormap.
874  */
875  clone_image->colors=image->colors;
876  length=(size_t) image->colors;
877  clone_image->colormap=(PixelInfo *) AcquireQuantumMemory(length+1,
878  sizeof(*clone_image->colormap));
879  if (clone_image->colormap == (PixelInfo *) NULL)
880  {
881  clone_image=DestroyImage(clone_image);
882  ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
883  }
884  (void) memcpy(clone_image->colormap,image->colormap,length*
885  sizeof(*clone_image->colormap));
886  }
887  if ((columns == 0) || (rows == 0))
888  {
889  if (image->montage != (char *) NULL)
890  (void) CloneString(&clone_image->montage,image->montage);
891  if (image->directory != (char *) NULL)
892  (void) CloneString(&clone_image->directory,image->directory);
893  clone_image->cache=ReferencePixelCache(image->cache);
894  return(clone_image);
895  }
896  scale_x=1.0;
897  scale_y=1.0;
898  if (image->columns != 0)
899  scale_x=(double) columns/(double) image->columns;
900  if (image->rows != 0)
901  scale_y=(double) rows/(double) image->rows;
902  clone_image->page.width=(size_t) CastDoubleToLong(floor(scale_x*
903  image->page.width+0.5));
904  clone_image->page.height=(size_t) CastDoubleToLong(floor(scale_y*
905  image->page.height+0.5));
906  if (MagickAbsoluteValue(scale_x-scale_y) < 2.0)
907  scale_x=scale_y=MagickMin(scale_x,scale_y);
908  clone_image->page.x=CastDoubleToLong(ceil(scale_x*image->page.x-0.5));
909  clone_image->tile_offset.x=CastDoubleToLong(ceil(scale_x*
910  image->tile_offset.x-0.5));
911  clone_image->page.y=CastDoubleToLong(ceil(scale_y*image->page.y-0.5));
912  clone_image->tile_offset.y=CastDoubleToLong(ceil(scale_y*
913  image->tile_offset.y-0.5));
914  clone_image->cache=ClonePixelCache(image->cache);
915  if (SetImageExtent(clone_image,columns,rows,exception) == MagickFalse)
916  clone_image=DestroyImage(clone_image);
917  return(clone_image);
918 }
919 
920 /*
921 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
922 % %
923 % %
924 % %
925 % C l o n e I m a g e I n f o %
926 % %
927 % %
928 % %
929 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
930 %
931 % CloneImageInfo() makes a copy of the given image info structure. If
932 % NULL is specified, a new image info structure is created initialized to
933 % default values.
934 %
935 % The format of the CloneImageInfo method is:
936 %
937 % ImageInfo *CloneImageInfo(const ImageInfo *image_info)
938 %
939 % A description of each parameter follows:
940 %
941 % o image_info: the image info.
942 %
943 */
944 MagickExport ImageInfo *CloneImageInfo(const ImageInfo *image_info)
945 {
946  ImageInfo
947  *clone_info;
948 
949  clone_info=AcquireImageInfo();
950  if (image_info == (ImageInfo *) NULL)
951  return(clone_info);
952  clone_info->compression=image_info->compression;
953  clone_info->temporary=image_info->temporary;
954  clone_info->adjoin=image_info->adjoin;
955  clone_info->antialias=image_info->antialias;
956  clone_info->scene=image_info->scene;
957  clone_info->number_scenes=image_info->number_scenes;
958  clone_info->depth=image_info->depth;
959  if (image_info->size != (char *) NULL)
960  (void) CloneString(&clone_info->size,image_info->size);
961  if (image_info->extract != (char *) NULL)
962  (void) CloneString(&clone_info->extract,image_info->extract);
963  if (image_info->scenes != (char *) NULL)
964  (void) CloneString(&clone_info->scenes,image_info->scenes);
965  if (image_info->page != (char *) NULL)
966  (void) CloneString(&clone_info->page,image_info->page);
967  clone_info->interlace=image_info->interlace;
968  clone_info->endian=image_info->endian;
969  clone_info->units=image_info->units;
970  clone_info->quality=image_info->quality;
971  if (image_info->sampling_factor != (char *) NULL)
972  (void) CloneString(&clone_info->sampling_factor,
973  image_info->sampling_factor);
974  if (image_info->server_name != (char *) NULL)
975  (void) CloneString(&clone_info->server_name,image_info->server_name);
976  if (image_info->font != (char *) NULL)
977  (void) CloneString(&clone_info->font,image_info->font);
978  if (image_info->texture != (char *) NULL)
979  (void) CloneString(&clone_info->texture,image_info->texture);
980  if (image_info->density != (char *) NULL)
981  (void) CloneString(&clone_info->density,image_info->density);
982  clone_info->pointsize=image_info->pointsize;
983  clone_info->fuzz=image_info->fuzz;
984  clone_info->matte_color=image_info->matte_color;
985  clone_info->background_color=image_info->background_color;
986  clone_info->border_color=image_info->border_color;
987  clone_info->transparent_color=image_info->transparent_color;
988  clone_info->dither=image_info->dither;
989  clone_info->monochrome=image_info->monochrome;
990  clone_info->colorspace=image_info->colorspace;
991  clone_info->type=image_info->type;
992  clone_info->orientation=image_info->orientation;
993  clone_info->ping=image_info->ping;
994  clone_info->verbose=image_info->verbose;
995  clone_info->progress_monitor=image_info->progress_monitor;
996  clone_info->client_data=image_info->client_data;
997  clone_info->cache=image_info->cache;
998  if (image_info->cache != (void *) NULL)
999  clone_info->cache=ReferencePixelCache(image_info->cache);
1000  if (image_info->profile != (void *) NULL)
1001  clone_info->profile=(void *) CloneStringInfo((StringInfo *)
1002  image_info->profile);
1003  SetImageInfoFile(clone_info,image_info->file);
1004  SetImageInfoBlob(clone_info,image_info->blob,image_info->length);
1005  clone_info->stream=image_info->stream;
1006  clone_info->custom_stream=image_info->custom_stream;
1007  (void) CopyMagickString(clone_info->magick,image_info->magick,
1008  MagickPathExtent);
1009  (void) CopyMagickString(clone_info->unique,image_info->unique,
1010  MagickPathExtent);
1011  (void) CopyMagickString(clone_info->filename,image_info->filename,
1012  MagickPathExtent);
1013  clone_info->channel=image_info->channel;
1014  (void) CloneImageOptions(clone_info,image_info);
1015  clone_info->debug=image_info->debug;
1016  clone_info->signature=image_info->signature;
1017  return(clone_info);
1018 }
1019 
1020 /*
1021 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1022 % %
1023 % %
1024 % %
1025 % C o p y I m a g e P i x e l s %
1026 % %
1027 % %
1028 % %
1029 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1030 %
1031 % CopyImagePixels() copies pixels from the source image as defined by the
1032 % geometry the destination image at the specified offset.
1033 %
1034 % The format of the CopyImagePixels method is:
1035 %
1036 % MagickBooleanType CopyImagePixels(Image *image,const Image *source_image,
1037 % const RectangleInfo *geometry,const OffsetInfo *offset,
1038 % ExceptionInfo *exception);
1039 %
1040 % A description of each parameter follows:
1041 %
1042 % o image: the destination image.
1043 %
1044 % o source_image: the source image.
1045 %
1046 % o geometry: define the dimensions of the source pixel rectangle.
1047 %
1048 % o offset: define the offset in the destination image.
1049 %
1050 % o exception: return any errors or warnings in this structure.
1051 %
1052 */
1053 MagickExport MagickBooleanType CopyImagePixels(Image *image,
1054  const Image *source_image,const RectangleInfo *geometry,
1055  const OffsetInfo *offset,ExceptionInfo *exception)
1056 {
1057 #define CopyImageTag "Copy/Image"
1058 
1059  CacheView
1060  *image_view,
1061  *source_view;
1062 
1063  MagickBooleanType
1064  status;
1065 
1066  MagickOffsetType
1067  progress;
1068 
1069  ssize_t
1070  y;
1071 
1072  assert(image != (Image *) NULL);
1073  assert(source_image != (Image *) NULL);
1074  assert(geometry != (RectangleInfo *) NULL);
1075  assert(offset != (OffsetInfo *) NULL);
1076  if (IsEventLogging() != MagickFalse)
1077  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1078  if ((offset->x < 0) || (offset->y < 0) ||
1079  ((offset->x+(ssize_t) geometry->width) > (ssize_t) image->columns) ||
1080  ((offset->y+(ssize_t) geometry->height) > (ssize_t) image->rows))
1081  ThrowBinaryException(OptionError,"GeometryDoesNotContainImage",
1082  image->filename);
1083  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
1084  return(MagickFalse);
1085  /*
1086  Copy image pixels.
1087  */
1088  status=MagickTrue;
1089  progress=0;
1090  source_view=AcquireVirtualCacheView(source_image,exception);
1091  image_view=AcquireAuthenticCacheView(image,exception);
1092 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1093  #pragma omp parallel for schedule(static) shared(progress,status) \
1094  magick_number_threads(image,source_image,geometry->height,2)
1095 #endif
1096  for (y=0; y < (ssize_t) geometry->height; y++)
1097  {
1098  MagickBooleanType
1099  sync;
1100 
1101  const Quantum
1102  *magick_restrict p;
1103 
1104  ssize_t
1105  x;
1106 
1107  Quantum
1108  *magick_restrict q;
1109 
1110  if (status == MagickFalse)
1111  continue;
1112  p=GetCacheViewVirtualPixels(source_view,geometry->x,y+geometry->y,
1113  geometry->width,1,exception);
1114  q=QueueCacheViewAuthenticPixels(image_view,offset->x,y+offset->y,
1115  geometry->width,1,exception);
1116  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
1117  {
1118  status=MagickFalse;
1119  continue;
1120  }
1121  for (x=0; x < (ssize_t) geometry->width; x++)
1122  {
1123  ssize_t
1124  i;
1125 
1126  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1127  {
1128  PixelChannel channel = GetPixelChannelChannel(image,i);
1129  PixelTrait traits = GetPixelChannelTraits(image,channel);
1130  PixelTrait source_traits=GetPixelChannelTraits(source_image,channel);
1131  if ((traits == UndefinedPixelTrait) ||
1132  ((traits & UpdatePixelTrait) == 0) ||
1133  (source_traits == UndefinedPixelTrait))
1134  continue;
1135  SetPixelChannel(image,channel,p[i],q);
1136  }
1137  p+=(ptrdiff_t) GetPixelChannels(source_image);
1138  q+=(ptrdiff_t) GetPixelChannels(image);
1139  }
1140  sync=SyncCacheViewAuthenticPixels(image_view,exception);
1141  if (sync == MagickFalse)
1142  status=MagickFalse;
1143  if (image->progress_monitor != (MagickProgressMonitor) NULL)
1144  {
1145  MagickBooleanType
1146  proceed;
1147 
1148 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1149  #pragma omp atomic
1150 #endif
1151  progress++;
1152  proceed=SetImageProgress(image,CopyImageTag,progress,image->rows);
1153  if (proceed == MagickFalse)
1154  status=MagickFalse;
1155  }
1156  }
1157  source_view=DestroyCacheView(source_view);
1158  image_view=DestroyCacheView(image_view);
1159  return(status);
1160 }
1161 
1162 /*
1163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1164 % %
1165 % %
1166 % %
1167 % D e s t r o y I m a g e %
1168 % %
1169 % %
1170 % %
1171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1172 %
1173 % DestroyImage() dereferences an image, deallocating memory associated with
1174 % the image if the reference count becomes zero.
1175 %
1176 % The format of the DestroyImage method is:
1177 %
1178 % Image *DestroyImage(Image *image)
1179 %
1180 % A description of each parameter follows:
1181 %
1182 % o image: the image.
1183 %
1184 */
1185 MagickExport Image *DestroyImage(Image *image)
1186 {
1187  MagickBooleanType
1188  destroy;
1189 
1190  /*
1191  Dereference image.
1192  */
1193  assert(image != (Image *) NULL);
1194  assert(image->signature == MagickCoreSignature);
1195  if (IsEventLogging() != MagickFalse)
1196  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1197  destroy=MagickFalse;
1198  LockSemaphoreInfo(image->semaphore);
1199  image->reference_count--;
1200  if (image->reference_count == 0)
1201  destroy=MagickTrue;
1202  UnlockSemaphoreInfo(image->semaphore);
1203  if (destroy == MagickFalse)
1204  return((Image *) NULL);
1205  /*
1206  Destroy image.
1207  */
1208  DestroyImagePixels(image);
1209  image->channel_map=DestroyPixelChannelMap(image->channel_map);
1210  if (image->montage != (char *) NULL)
1211  image->montage=DestroyString(image->montage);
1212  if (image->directory != (char *) NULL)
1213  image->directory=DestroyString(image->directory);
1214  if (image->colormap != (PixelInfo *) NULL)
1215  image->colormap=(PixelInfo *) RelinquishMagickMemory(image->colormap);
1216  if (image->geometry != (char *) NULL)
1217  image->geometry=DestroyString(image->geometry);
1218  DestroyImageProfiles(image);
1219  DestroyImageProperties(image);
1220  DestroyImageArtifacts(image);
1221  if (image->ascii85 != (Ascii85Info *) NULL)
1222  image->ascii85=(Ascii85Info *) RelinquishMagickMemory(image->ascii85);
1223  if (image->image_info != (ImageInfo *) NULL)
1224  image->image_info=DestroyImageInfo(image->image_info);
1225  DestroyBlob(image);
1226  if (image->semaphore != (SemaphoreInfo *) NULL)
1227  RelinquishSemaphoreInfo(&image->semaphore);
1228  image->signature=(~MagickCoreSignature);
1229  image=(Image *) RelinquishMagickMemory(image);
1230  return(image);
1231 }
1232 
1233 /*
1234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1235 % %
1236 % %
1237 % %
1238 % D e s t r o y I m a g e I n f o %
1239 % %
1240 % %
1241 % %
1242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1243 %
1244 % DestroyImageInfo() deallocates memory associated with an ImageInfo
1245 % structure.
1246 %
1247 % The format of the DestroyImageInfo method is:
1248 %
1249 % ImageInfo *DestroyImageInfo(ImageInfo *image_info)
1250 %
1251 % A description of each parameter follows:
1252 %
1253 % o image_info: the image info.
1254 %
1255 */
1256 MagickExport ImageInfo *DestroyImageInfo(ImageInfo *image_info)
1257 {
1258  assert(image_info != (ImageInfo *) NULL);
1259  assert(image_info->signature == MagickCoreSignature);
1260  if (IsEventLogging() != MagickFalse)
1261  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1262  image_info->filename);
1263  if (image_info->size != (char *) NULL)
1264  image_info->size=DestroyString(image_info->size);
1265  if (image_info->extract != (char *) NULL)
1266  image_info->extract=DestroyString(image_info->extract);
1267  if (image_info->scenes != (char *) NULL)
1268  image_info->scenes=DestroyString(image_info->scenes);
1269  if (image_info->page != (char *) NULL)
1270  image_info->page=DestroyString(image_info->page);
1271  if (image_info->sampling_factor != (char *) NULL)
1272  image_info->sampling_factor=DestroyString(
1273  image_info->sampling_factor);
1274  if (image_info->server_name != (char *) NULL)
1275  image_info->server_name=DestroyString(
1276  image_info->server_name);
1277  if (image_info->font != (char *) NULL)
1278  image_info->font=DestroyString(image_info->font);
1279  if (image_info->texture != (char *) NULL)
1280  image_info->texture=DestroyString(image_info->texture);
1281  if (image_info->density != (char *) NULL)
1282  image_info->density=DestroyString(image_info->density);
1283  if (image_info->cache != (void *) NULL)
1284  image_info->cache=DestroyPixelCache(image_info->cache);
1285  if (image_info->profile != (StringInfo *) NULL)
1286  image_info->profile=(void *) DestroyStringInfo((StringInfo *)
1287  image_info->profile);
1288  DestroyImageOptions(image_info);
1289  image_info->signature=(~MagickCoreSignature);
1290  image_info=(ImageInfo *) RelinquishMagickMemory(image_info);
1291  return(image_info);
1292 }
1293 
1294 /*
1295 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1296 % %
1297 % %
1298 % %
1299 + D i s a s s o c i a t e I m a g e S t r e a m %
1300 % %
1301 % %
1302 % %
1303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1304 %
1305 % DisassociateImageStream() disassociates the image stream. It checks if the
1306 % blob of the specified image is referenced by other images. If the reference
1307 % count is higher then 1 a new blob is assigned to the specified image.
1308 %
1309 % The format of the DisassociateImageStream method is:
1310 %
1311 % void DisassociateImageStream(const Image *image)
1312 %
1313 % A description of each parameter follows:
1314 %
1315 % o image: the image.
1316 %
1317 */
1318 MagickExport void DisassociateImageStream(Image *image)
1319 {
1320  assert(image != (Image *) NULL);
1321  assert(image->signature == MagickCoreSignature);
1322  if (IsEventLogging() != MagickFalse)
1323  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1324  DisassociateBlob(image);
1325 }
1326 
1327 /*
1328 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1329 % %
1330 % %
1331 % %
1332 % G e t I m a g e I n f o %
1333 % %
1334 % %
1335 % %
1336 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1337 %
1338 % GetImageInfo() initializes image_info to default values.
1339 %
1340 % The format of the GetImageInfo method is:
1341 %
1342 % void GetImageInfo(ImageInfo *image_info)
1343 %
1344 % A description of each parameter follows:
1345 %
1346 % o image_info: the image info.
1347 %
1348 */
1349 MagickExport void GetImageInfo(ImageInfo *image_info)
1350 {
1351  char
1352  *synchronize;
1353 
1354  /*
1355  File and image dimension members.
1356  */
1357  assert(image_info != (ImageInfo *) NULL);
1358  if (IsEventLogging() != MagickFalse)
1359  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1360  (void) memset(image_info,0,sizeof(*image_info));
1361  image_info->adjoin=MagickTrue;
1362  image_info->interlace=NoInterlace;
1363  image_info->channel=AllChannels;
1364  image_info->quality=UndefinedCompressionQuality;
1365  image_info->antialias=MagickTrue;
1366  image_info->dither=MagickTrue;
1367  image_info->depth=0;
1368  synchronize=GetEnvironmentValue("MAGICK_SYNCHRONIZE");
1369  if (synchronize != (const char *) NULL)
1370  {
1371  image_info->synchronize=IsStringTrue(synchronize);
1372  synchronize=DestroyString(synchronize);
1373  }
1374  GetPixelInfoRGBA(BackgroundColorRGBA,&image_info->background_color);
1375  GetPixelInfoRGBA(BorderColorRGBA,&image_info->border_color);
1376  GetPixelInfoRGBA(MatteColorRGBA,&image_info->matte_color);
1377  GetPixelInfoRGBA(TransparentColorRGBA,&image_info->transparent_color);
1378  image_info->debug=(GetLogEventMask() & ImageEvent) != 0 ? MagickTrue :
1379  MagickFalse;
1380  image_info->signature=MagickCoreSignature;
1381 }
1382 
1383 /*
1384 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1385 % %
1386 % %
1387 % %
1388 % G e t I m a g e I n f o F i l e %
1389 % %
1390 % %
1391 % %
1392 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1393 %
1394 % GetImageInfoFile() returns the image info file member.
1395 %
1396 % The format of the GetImageInfoFile method is:
1397 %
1398 % FILE *GetImageInfoFile(const ImageInfo *image_info)
1399 %
1400 % A description of each parameter follows:
1401 %
1402 % o image_info: the image info.
1403 %
1404 */
1405 MagickExport FILE *GetImageInfoFile(const ImageInfo *image_info)
1406 {
1407  return(image_info->file);
1408 }
1409 
1410 /*
1411 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1412 % %
1413 % %
1414 % %
1415 % G e t I m a g e M a s k %
1416 % %
1417 % %
1418 % %
1419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1420 %
1421 % GetImageMask() returns the mask associated with the image.
1422 %
1423 % The format of the GetImageMask method is:
1424 %
1425 % Image *GetImageMask(const Image *image,const PixelMask type,
1426 % ExceptionInfo *exception)
1427 %
1428 % A description of each parameter follows:
1429 %
1430 % o image: the image.
1431 %
1432 % o type: the mask type, ReadPixelMask or WritePixelMask.
1433 %
1434 */
1435 MagickExport Image *GetImageMask(const Image *image,const PixelMask type,
1436  ExceptionInfo *exception)
1437 {
1438  CacheView
1439  *mask_view,
1440  *image_view;
1441 
1442  Image
1443  *mask_image;
1444 
1445  MagickBooleanType
1446  status;
1447 
1448  ssize_t
1449  y;
1450 
1451  /*
1452  Get image mask.
1453  */
1454  assert(image != (Image *) NULL);
1455  assert(image->signature == MagickCoreSignature);
1456  if (IsEventLogging() != MagickFalse)
1457  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1458  switch (type)
1459  {
1460  case ReadPixelMask:
1461  {
1462  if ((image->channels & ReadMaskChannel) == 0)
1463  return((Image *) NULL);
1464  break;
1465  }
1466  case WritePixelMask:
1467  {
1468  if ((image->channels & WriteMaskChannel) == 0)
1469  return((Image *) NULL);
1470  break;
1471  }
1472  default:
1473  {
1474  if ((image->channels & CompositeMaskChannel) == 0)
1475  return((Image *) NULL);
1476  break;
1477  }
1478  }
1479  mask_image=AcquireImage((ImageInfo *) NULL,exception);
1480  status=SetImageExtent(mask_image,image->columns,image->rows,exception);
1481  if (status == MagickFalse)
1482  return(DestroyImage(mask_image));
1483  status=MagickTrue;
1484  mask_image->alpha_trait=UndefinedPixelTrait;
1485  (void) SetImageColorspace(mask_image,GRAYColorspace,exception);
1486  image_view=AcquireVirtualCacheView(image,exception);
1487  mask_view=AcquireAuthenticCacheView(mask_image,exception);
1488 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1489  #pragma omp parallel for schedule(static) shared(status) \
1490  magick_number_threads(image,image,image->rows,2)
1491 #endif
1492  for (y=0; y < (ssize_t) image->rows; y++)
1493  {
1494  const Quantum
1495  *magick_restrict p;
1496 
1497  Quantum
1498  *magick_restrict q;
1499 
1500  ssize_t
1501  x;
1502 
1503  if (status == MagickFalse)
1504  continue;
1505  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1506  q=GetCacheViewAuthenticPixels(mask_view,0,y,mask_image->columns,1,
1507  exception);
1508  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
1509  {
1510  status=MagickFalse;
1511  continue;
1512  }
1513  for (x=0; x < (ssize_t) image->columns; x++)
1514  {
1515  switch (type)
1516  {
1517  case ReadPixelMask:
1518  {
1519  SetPixelGray(mask_image,GetPixelReadMask(image,p),q);
1520  break;
1521  }
1522  case WritePixelMask:
1523  {
1524  SetPixelGray(mask_image,GetPixelWriteMask(image,p),q);
1525  break;
1526  }
1527  default:
1528  {
1529  SetPixelGray(mask_image,GetPixelCompositeMask(image,p),q);
1530  break;
1531  }
1532  }
1533  p+=(ptrdiff_t) GetPixelChannels(image);
1534  q+=(ptrdiff_t) GetPixelChannels(mask_image);
1535  }
1536  if (SyncCacheViewAuthenticPixels(mask_view,exception) == MagickFalse)
1537  status=MagickFalse;
1538  }
1539  mask_view=DestroyCacheView(mask_view);
1540  image_view=DestroyCacheView(image_view);
1541  if (status == MagickFalse)
1542  mask_image=DestroyImage(mask_image);
1543  return(mask_image);
1544 }
1545 
1546 /*
1547 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1548 % %
1549 % %
1550 % %
1551 + G e t I m a g e R e f e r e n c e C o u n t %
1552 % %
1553 % %
1554 % %
1555 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1556 %
1557 % GetImageReferenceCount() returns the image reference count.
1558 %
1559 % The format of the GetReferenceCount method is:
1560 %
1561 % ssize_t GetImageReferenceCount(Image *image)
1562 %
1563 % A description of each parameter follows:
1564 %
1565 % o image: the image.
1566 %
1567 */
1568 MagickExport ssize_t GetImageReferenceCount(Image *image)
1569 {
1570  ssize_t
1571  reference_count;
1572 
1573  assert(image != (Image *) NULL);
1574  assert(image->signature == MagickCoreSignature);
1575  if (IsEventLogging() != MagickFalse)
1576  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1577  LockSemaphoreInfo(image->semaphore);
1578  reference_count=image->reference_count;
1579  UnlockSemaphoreInfo(image->semaphore);
1580  return(reference_count);
1581 }
1582 
1583 /*
1584 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1585 % %
1586 % %
1587 % %
1588 % G e t I m a g e V i r t u a l P i x e l M e t h o d %
1589 % %
1590 % %
1591 % %
1592 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1593 %
1594 % GetImageVirtualPixelMethod() gets the "virtual pixels" method for the
1595 % image. A virtual pixel is any pixel access that is outside the boundaries
1596 % of the image cache.
1597 %
1598 % The format of the GetImageVirtualPixelMethod() method is:
1599 %
1600 % VirtualPixelMethod GetImageVirtualPixelMethod(const Image *image)
1601 %
1602 % A description of each parameter follows:
1603 %
1604 % o image: the image.
1605 %
1606 */
1607 MagickExport VirtualPixelMethod GetImageVirtualPixelMethod(const Image *image)
1608 {
1609  assert(image != (Image *) NULL);
1610  assert(image->signature == MagickCoreSignature);
1611  if (IsEventLogging() != MagickFalse)
1612  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1613  return(GetPixelCacheVirtualMethod(image));
1614 }
1615 
1616 /*
1617 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1618 % %
1619 % %
1620 % %
1621 % I n t e r p r e t I m a g e F i l e n a m e %
1622 % %
1623 % %
1624 % %
1625 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1626 %
1627 % InterpretImageFilename() interprets embedded characters in an image filename.
1628 % The filename length is returned.
1629 %
1630 % The format of the InterpretImageFilename method is:
1631 %
1632 % size_t InterpretImageFilename(const ImageInfo *image_info,Image *image,
1633 % const char *format,int value,char *filename,ExceptionInfo *exception)
1634 %
1635 % A description of each parameter follows.
1636 %
1637 % o image_info: the image info..
1638 %
1639 % o image: the image.
1640 %
1641 % o format: A filename describing the format to use to write the numeric
1642 % argument. Only the first numeric format identifier is replaced.
1643 %
1644 % o value: Numeric value to substitute into format filename.
1645 %
1646 % o filename: return the formatted filename in this character buffer.
1647 %
1648 % o exception: return any errors or warnings in this structure.
1649 %
1650 */
1651 MagickExport size_t InterpretImageFilename(const ImageInfo *image_info,
1652  Image *image,const char *format,int value,char *filename,
1653  ExceptionInfo *exception)
1654 {
1655  char
1656  *q;
1657 
1658  const char
1659  *p;
1660 
1661  int
1662  c;
1663 
1664  MagickBooleanType
1665  canonical;
1666 
1667  ssize_t
1668  field_width,
1669  offset;
1670 
1671  canonical=MagickFalse;
1672  offset=0;
1673  (void) CopyMagickString(filename,format,MagickPathExtent);
1674  if (IsStringTrue(GetImageOption(image_info,"filename:literal")) != MagickFalse)
1675  return(strlen(filename));
1676  for (p=strchr(format,'%'); p != (char *) NULL; p=strchr(p+1,'%'))
1677  {
1678  q=(char *) p+1;
1679  if (*q == '%')
1680  {
1681  p=q+1;
1682  continue;
1683  }
1684  field_width=0;
1685  if (*q == '0')
1686  field_width=(ssize_t) strtol(q,&q,10);
1687  switch (*q)
1688  {
1689  case 'd':
1690  case 'o':
1691  case 'x':
1692  {
1693  q++;
1694  c=(*q);
1695  *q='\0';
1696  (void) FormatLocaleString(filename+(p-format-offset),(size_t)
1697  (MagickPathExtent-(p-format-offset)),p,value);
1698  offset+=(4-field_width);
1699  *q=c;
1700  (void) ConcatenateMagickString(filename,q,MagickPathExtent);
1701  canonical=MagickTrue;
1702  if (*(q-1) != '%')
1703  break;
1704  p++;
1705  break;
1706  }
1707  case '[':
1708  {
1709  char
1710  pattern[MagickPathExtent];
1711 
1712  const char
1713  *option;
1714 
1715  char
1716  *r;
1717 
1718  ssize_t
1719  i;
1720 
1721  ssize_t
1722  depth;
1723 
1724  /*
1725  Image option.
1726  */
1727  if (strchr(p,']') == (char *) NULL)
1728  break;
1729  depth=1;
1730  r=q+1;
1731  for (i=0; (i < (MagickPathExtent-1L)) && (*r != '\0'); i++)
1732  {
1733  if (*r == '[')
1734  depth++;
1735  if (*r == ']')
1736  depth--;
1737  if (depth <= 0)
1738  break;
1739  pattern[i]=(*r++);
1740  }
1741  pattern[i]='\0';
1742  if (LocaleNCompare(pattern,"filename:",9) != 0)
1743  break;
1744  option=(const char *) NULL;
1745  if (image != (Image *) NULL)
1746  option=GetImageProperty(image,pattern,exception);
1747  if ((option == (const char *) NULL) && (image != (Image *) NULL))
1748  option=GetImageArtifact(image,pattern);
1749  if ((option == (const char *) NULL) &&
1750  (image_info != (ImageInfo *) NULL))
1751  option=GetImageOption(image_info,pattern);
1752  if (option == (const char *) NULL)
1753  break;
1754  q--;
1755  c=(*q);
1756  *q='\0';
1757  (void) CopyMagickString(filename+(p-format-offset),option,(size_t)
1758  (MagickPathExtent-(p-format-offset)));
1759  offset+=(ssize_t) strlen(pattern)-(ssize_t) strlen(option)+3;
1760  *q=c;
1761  (void) ConcatenateMagickString(filename,r+1,MagickPathExtent);
1762  canonical=MagickTrue;
1763  if (*(q-1) != '%')
1764  break;
1765  p++;
1766  break;
1767  }
1768  default:
1769  break;
1770  }
1771  }
1772  if (canonical == MagickFalse)
1773  (void) CopyMagickString(filename,format,MagickPathExtent);
1774  else
1775  for (q=filename; *q != '\0'; q++)
1776  if ((*q == '%') && (*(q+1) == '%'))
1777  (void) CopyMagickString(q,q+1,(size_t) (MagickPathExtent-(q-filename)));
1778  return(strlen(filename));
1779 }
1780 
1781 /*
1782 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1783 % %
1784 % %
1785 % %
1786 % I s H i g h D y n a m i c R a n g e I m a g e %
1787 % %
1788 % %
1789 % %
1790 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1791 %
1792 % IsHighDynamicRangeImage() returns MagickTrue if any pixel component is
1793 % non-integer or exceeds the bounds of the quantum depth (e.g. for Q16
1794 % 0..65535.
1795 %
1796 % The format of the IsHighDynamicRangeImage method is:
1797 %
1798 % MagickBooleanType IsHighDynamicRangeImage(const Image *image,
1799 % ExceptionInfo *exception)
1800 %
1801 % A description of each parameter follows:
1802 %
1803 % o image: the image.
1804 %
1805 % o exception: return any errors or warnings in this structure.
1806 %
1807 */
1808 MagickExport MagickBooleanType IsHighDynamicRangeImage(const Image *image,
1809  ExceptionInfo *exception)
1810 {
1811 #if !defined(MAGICKCORE_HDRI_SUPPORT)
1812  (void) image;
1813  (void) exception;
1814  return(MagickFalse);
1815 #else
1816  CacheView
1817  *image_view;
1818 
1819  MagickBooleanType
1820  hdri = MagickFalse;
1821 
1822  ssize_t
1823  y;
1824 
1825  assert(image != (Image *) NULL);
1826  assert(image->signature == MagickCoreSignature);
1827  if (IsEventLogging() != MagickFalse)
1828  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1829  image_view=AcquireVirtualCacheView(image,exception);
1830 #if defined(MAGICKCORE_OPENMP_SUPPORT)
1831  #pragma omp parallel for schedule(static) shared(hdri) \
1832  magick_number_threads(image,image,image->rows,2)
1833 #endif
1834  for (y=0; y < (ssize_t) image->rows; y++)
1835  {
1836  const Quantum
1837  *p;
1838 
1839  ssize_t
1840  x;
1841 
1842  if (hdri != MagickFalse)
1843  continue;
1844  p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1845  if (p == (const Quantum *) NULL)
1846  continue;
1847  for (x=0; x < (ssize_t) image->columns; x++)
1848  {
1849  ssize_t
1850  i;
1851 
1852  for (i=0; i < (ssize_t) GetPixelChannels(image); i++)
1853  {
1854  double
1855  pixel;
1856 
1857  PixelTrait
1858  traits;
1859 
1860  traits=GetPixelChannelTraits(image,(PixelChannel) i);
1861  if (traits == UndefinedPixelTrait)
1862  continue;
1863  pixel=(double) p[i];
1864  if ((pixel < 0.0) || (pixel > (double) QuantumRange) ||
1865  (pixel != (double) ((QuantumAny) pixel)))
1866  {
1867  hdri=MagickTrue;
1868  break;
1869  }
1870  }
1871  if (hdri != MagickFalse)
1872  break;
1873  p+=(ptrdiff_t) GetPixelChannels(image);
1874  }
1875  }
1876  image_view=DestroyCacheView(image_view);
1877  return(hdri);
1878 #endif
1879 }
1880 
1881 /*
1882 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1883 % %
1884 % %
1885 % %
1886 % I s I m a g e O b j e c t %
1887 % %
1888 % %
1889 % %
1890 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1891 %
1892 % IsImageObject() returns MagickTrue if the image sequence contains a valid
1893 % set of image objects.
1894 %
1895 % The format of the IsImageObject method is:
1896 %
1897 % MagickBooleanType IsImageObject(const Image *image)
1898 %
1899 % A description of each parameter follows:
1900 %
1901 % o image: the image.
1902 %
1903 */
1904 MagickExport MagickBooleanType IsImageObject(const Image *image)
1905 {
1906  const Image
1907  *p;
1908 
1909  assert(image != (Image *) NULL);
1910  if (IsEventLogging() != MagickFalse)
1911  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1912  for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
1913  if (p->signature != MagickCoreSignature)
1914  return(MagickFalse);
1915  return(MagickTrue);
1916 }
1917 
1918 /*
1919 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1920 % %
1921 % %
1922 % %
1923 % I s T a i n t I m a g e %
1924 % %
1925 % %
1926 % %
1927 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1928 %
1929 % IsTaintImage() returns MagickTrue any pixel in the image has been altered
1930 % since it was first constituted.
1931 %
1932 % The format of the IsTaintImage method is:
1933 %
1934 % MagickBooleanType IsTaintImage(const Image *image)
1935 %
1936 % A description of each parameter follows:
1937 %
1938 % o image: the image.
1939 %
1940 */
1941 MagickExport MagickBooleanType IsTaintImage(const Image *image)
1942 {
1943  char
1944  magick[MagickPathExtent],
1945  filename[MagickPathExtent];
1946 
1947  const Image
1948  *p;
1949 
1950  assert(image != (Image *) NULL);
1951  assert(image->signature == MagickCoreSignature);
1952  if (IsEventLogging() != MagickFalse)
1953  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1954  (void) CopyMagickString(magick,image->magick,MagickPathExtent);
1955  (void) CopyMagickString(filename,image->filename,MagickPathExtent);
1956  for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
1957  {
1958  if (p->taint != MagickFalse)
1959  return(MagickTrue);
1960  if (LocaleCompare(p->magick,magick) != 0)
1961  return(MagickTrue);
1962  if (LocaleCompare(p->filename,filename) != 0)
1963  return(MagickTrue);
1964  }
1965  return(MagickFalse);
1966 }
1967 
1968 /*
1969 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1970 % %
1971 % %
1972 % %
1973 % M o d i f y I m a g e %
1974 % %
1975 % %
1976 % %
1977 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1978 %
1979 % ModifyImage() ensures that there is only a single reference to the image
1980 % to be modified, updating the provided image pointer to point to a clone of
1981 % the original image if necessary.
1982 %
1983 % The format of the ModifyImage method is:
1984 %
1985 % MagickBooleanType ModifyImage(Image *image,ExceptionInfo *exception)
1986 %
1987 % A description of each parameter follows:
1988 %
1989 % o image: the image.
1990 %
1991 % o exception: return any errors or warnings in this structure.
1992 %
1993 */
1994 MagickExport MagickBooleanType ModifyImage(Image **image,
1995  ExceptionInfo *exception)
1996 {
1997  Image
1998  *clone_image;
1999 
2000  assert(image != (Image **) NULL);
2001  assert(*image != (Image *) NULL);
2002  assert((*image)->signature == MagickCoreSignature);
2003  if (IsEventLogging() != MagickFalse)
2004  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
2005  if (GetImageReferenceCount(*image) <= 1)
2006  return(MagickTrue);
2007  clone_image=CloneImage(*image,0,0,MagickTrue,exception);
2008  LockSemaphoreInfo((*image)->semaphore);
2009  (*image)->reference_count--;
2010  UnlockSemaphoreInfo((*image)->semaphore);
2011  *image=clone_image;
2012  return(MagickTrue);
2013 }
2014 
2015 /*
2016 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2017 % %
2018 % %
2019 % %
2020 % N e w M a g i c k I m a g e %
2021 % %
2022 % %
2023 % %
2024 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2025 %
2026 % NewMagickImage() creates a blank image canvas of the specified size and
2027 % background color.
2028 %
2029 % The format of the NewMagickImage method is:
2030 %
2031 % Image *NewMagickImage(const ImageInfo *image_info,const size_t width,
2032 % const size_t height,const PixelInfo *background,
2033 % ExceptionInfo *exception)
2034 %
2035 % A description of each parameter follows:
2036 %
2037 % o image: the image.
2038 %
2039 % o width: the image width.
2040 %
2041 % o height: the image height.
2042 %
2043 % o background: the image color.
2044 %
2045 % o exception: return any errors or warnings in this structure.
2046 %
2047 */
2048 MagickExport Image *NewMagickImage(const ImageInfo *image_info,
2049  const size_t width,const size_t height,const PixelInfo *background,
2050  ExceptionInfo *exception)
2051 {
2052  CacheView
2053  *image_view;
2054 
2055  Image
2056  *image;
2057 
2058  MagickBooleanType
2059  status;
2060 
2061  ssize_t
2062  y;
2063 
2064  assert(image_info != (const ImageInfo *) NULL);
2065  assert(image_info->signature == MagickCoreSignature);
2066  assert(background != (const PixelInfo *) NULL);
2067  if (IsEventLogging() != MagickFalse)
2068  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2069  image=AcquireImage(image_info,exception);
2070  image->columns=width;
2071  image->rows=height;
2072  image->colorspace=background->colorspace;
2073  image->alpha_trait=background->alpha_trait;
2074  image->fuzz=background->fuzz;
2075  image->depth=background->depth;
2076  status=MagickTrue;
2077  image_view=AcquireAuthenticCacheView(image,exception);
2078 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2079  #pragma omp parallel for schedule(static) shared(status) \
2080  magick_number_threads(image,image,image->rows,2)
2081 #endif
2082  for (y=0; y < (ssize_t) image->rows; y++)
2083  {
2084  Quantum
2085  *magick_restrict q;
2086 
2087  ssize_t
2088  x;
2089 
2090  if (status == MagickFalse)
2091  continue;
2092  q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2093  if (q == (Quantum *) NULL)
2094  {
2095  status=MagickFalse;
2096  continue;
2097  }
2098  for (x=0; x < (ssize_t) image->columns; x++)
2099  {
2100  SetPixelViaPixelInfo(image,background,q);
2101  q+=(ptrdiff_t) GetPixelChannels(image);
2102  }
2103  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2104  status=MagickFalse;
2105  }
2106  image_view=DestroyCacheView(image_view);
2107  if (status == MagickFalse)
2108  image=DestroyImage(image);
2109  return(image);
2110 }
2111 
2112 /*
2113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2114 % %
2115 % %
2116 % %
2117 % R e f e r e n c e I m a g e %
2118 % %
2119 % %
2120 % %
2121 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2122 %
2123 % ReferenceImage() increments the reference count associated with an image
2124 % returning a pointer to the image.
2125 %
2126 % The format of the ReferenceImage method is:
2127 %
2128 % Image *ReferenceImage(Image *image)
2129 %
2130 % A description of each parameter follows:
2131 %
2132 % o image: the image.
2133 %
2134 */
2135 MagickExport Image *ReferenceImage(Image *image)
2136 {
2137  assert(image != (Image *) NULL);
2138  assert(image->signature == MagickCoreSignature);
2139  if (IsEventLogging() != MagickFalse)
2140  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2141  LockSemaphoreInfo(image->semaphore);
2142  image->reference_count++;
2143  UnlockSemaphoreInfo(image->semaphore);
2144  return(image);
2145 }
2146 
2147 /*
2148 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2149 % %
2150 % %
2151 % %
2152 % R e s e t I m a g e P a g e %
2153 % %
2154 % %
2155 % %
2156 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2157 %
2158 % ResetImagePage() resets the image page canvas and position.
2159 %
2160 % The format of the ResetImagePage method is:
2161 %
2162 % MagickBooleanType ResetImagePage(Image *image,const char *page)
2163 %
2164 % A description of each parameter follows:
2165 %
2166 % o image: the image.
2167 %
2168 % o page: the relative page specification.
2169 %
2170 */
2171 MagickExport MagickBooleanType ResetImagePage(Image *image,const char *page)
2172 {
2173  MagickStatusType
2174  flags;
2175 
2177  geometry;
2178 
2179  assert(image != (Image *) NULL);
2180  assert(image->signature == MagickCoreSignature);
2181  if (IsEventLogging() != MagickFalse)
2182  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2183  flags=ParseAbsoluteGeometry(page,&geometry);
2184  if ((flags & WidthValue) != 0)
2185  {
2186  if ((flags & HeightValue) == 0)
2187  geometry.height=geometry.width;
2188  image->page.width=geometry.width;
2189  image->page.height=geometry.height;
2190  }
2191  if ((flags & AspectValue) != 0)
2192  {
2193  if ((flags & XValue) != 0)
2194  image->page.x+=geometry.x;
2195  if ((flags & YValue) != 0)
2196  image->page.y+=geometry.y;
2197  }
2198  else
2199  {
2200  if ((flags & XValue) != 0)
2201  {
2202  image->page.x=geometry.x;
2203  if ((image->page.width == 0) && (geometry.x > 0))
2204  image->page.width=(size_t) ((ssize_t) image->columns+geometry.x);
2205  }
2206  if ((flags & YValue) != 0)
2207  {
2208  image->page.y=geometry.y;
2209  if ((image->page.height == 0) && (geometry.y > 0))
2210  image->page.height=(size_t) ((ssize_t) image->rows+geometry.y);
2211  }
2212  }
2213  return(MagickTrue);
2214 }
2215 
2216 /*
2217 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2218 % %
2219 % %
2220 % %
2221 % R e s e t I m a g e P i x e l s %
2222 % %
2223 % %
2224 % %
2225 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2226 %
2227 % ResetImagePixels() reset the image pixels, that is, all the pixel components
2228 % are zeroed.
2229 %
2230 % The format of the SetImage method is:
2231 %
2232 % MagickBooleanType ResetImagePixels(Image *image,
2233 % ExceptionInfo *exception)
2234 %
2235 % A description of each parameter follows:
2236 %
2237 % o image: the image.
2238 %
2239 % o exception: return any errors or warnings in this structure.
2240 %
2241 */
2242 MagickExport MagickBooleanType ResetImagePixels(Image *image,
2243  ExceptionInfo *exception)
2244 {
2245  CacheView
2246  *image_view;
2247 
2248  MagickBooleanType
2249  status;
2250 
2251  size_t
2252  length;
2253 
2254  ssize_t
2255  y;
2256 
2257  void
2258  *pixels;
2259 
2260  assert(image != (Image *) NULL);
2261  assert(image->signature == MagickCoreSignature);
2262  if (IsEventLogging() != MagickFalse)
2263  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2264  pixels=AcquirePixelCachePixels(image,&length,exception);
2265  if (pixels != (void *) NULL)
2266  {
2267  /*
2268  Reset in-core image pixels.
2269  */
2270  (void) memset(pixels,0,length);
2271  return(MagickTrue);
2272  }
2273  /*
2274  Reset image pixels.
2275  */
2276  status=MagickTrue;
2277  image_view=AcquireAuthenticCacheView(image,exception);
2278 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2279  #pragma omp parallel for schedule(static) shared(status) \
2280  magick_number_threads(image,image,image->rows,2)
2281 #endif
2282  for (y=0; y < (ssize_t) image->rows; y++)
2283  {
2284  Quantum
2285  *magick_restrict q;
2286 
2287  ssize_t
2288  x;
2289 
2290  if (status == MagickFalse)
2291  continue;
2292  q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2293  if (q == (Quantum *) NULL)
2294  {
2295  status=MagickFalse;
2296  continue;
2297  }
2298  for (x=0; x < (ssize_t) image->columns; x++)
2299  {
2300  (void) memset(q,0,GetPixelChannels(image)*sizeof(Quantum));
2301  q+=(ptrdiff_t) GetPixelChannels(image);
2302  }
2303  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2304  status=MagickFalse;
2305  }
2306  image_view=DestroyCacheView(image_view);
2307  return(status);
2308 }
2309 
2310 /*
2311 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2312 % %
2313 % %
2314 % %
2315 % S e t I m a g e A l p h a %
2316 % %
2317 % %
2318 % %
2319 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2320 %
2321 % SetImageAlpha() sets the alpha levels of the image.
2322 %
2323 % The format of the SetImageAlpha method is:
2324 %
2325 % MagickBooleanType SetImageAlpha(Image *image,const Quantum alpha,
2326 % ExceptionInfo *exception)
2327 %
2328 % A description of each parameter follows:
2329 %
2330 % o image: the image.
2331 %
2332 % o alpha: the level of transparency: 0 is fully transparent and QuantumRange
2333 % is fully opaque.
2334 %
2335 % o exception: return any errors or warnings in this structure.
2336 %
2337 */
2338 MagickExport MagickBooleanType SetImageAlpha(Image *image,const Quantum alpha,
2339  ExceptionInfo *exception)
2340 {
2341  CacheView
2342  *image_view;
2343 
2344  MagickBooleanType
2345  status;
2346 
2347  ssize_t
2348  y;
2349 
2350  assert(image != (Image *) NULL);
2351  assert(image->signature == MagickCoreSignature);
2352  if (IsEventLogging() != MagickFalse)
2353  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2354  image->alpha_trait=BlendPixelTrait;
2355  status=MagickTrue;
2356  image_view=AcquireAuthenticCacheView(image,exception);
2357 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2358  #pragma omp parallel for schedule(static) shared(status) \
2359  magick_number_threads(image,image,image->rows,2)
2360 #endif
2361  for (y=0; y < (ssize_t) image->rows; y++)
2362  {
2363  Quantum
2364  *magick_restrict q;
2365 
2366  ssize_t
2367  x;
2368 
2369  if (status == MagickFalse)
2370  continue;
2371  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2372  if (q == (Quantum *) NULL)
2373  {
2374  status=MagickFalse;
2375  continue;
2376  }
2377  for (x=0; x < (ssize_t) image->columns; x++)
2378  {
2379  if (GetPixelWriteMask(image,q) > (QuantumRange/2))
2380  SetPixelAlpha(image,alpha,q);
2381  q+=(ptrdiff_t) GetPixelChannels(image);
2382  }
2383  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2384  status=MagickFalse;
2385  }
2386  image_view=DestroyCacheView(image_view);
2387  return(status);
2388 }
2389 
2390 /*
2391 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2392 % %
2393 % %
2394 % %
2395 % S e t I m a g e B a c k g r o u n d C o l o r %
2396 % %
2397 % %
2398 % %
2399 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2400 %
2401 % SetImageBackgroundColor() initializes the image pixels to the image
2402 % background color. The background color is defined by the background_color
2403 % member of the image structure.
2404 %
2405 % The format of the SetImage method is:
2406 %
2407 % MagickBooleanType SetImageBackgroundColor(Image *image,
2408 % ExceptionInfo *exception)
2409 %
2410 % A description of each parameter follows:
2411 %
2412 % o image: the image.
2413 %
2414 % o exception: return any errors or warnings in this structure.
2415 %
2416 */
2417 MagickExport MagickBooleanType SetImageBackgroundColor(Image *image,
2418  ExceptionInfo *exception)
2419 {
2420  CacheView
2421  *image_view;
2422 
2423  MagickBooleanType
2424  status;
2425 
2426  PixelInfo
2427  background;
2428 
2429  ssize_t
2430  y;
2431 
2432  assert(image != (Image *) NULL);
2433  assert(image->signature == MagickCoreSignature);
2434  if (IsEventLogging() != MagickFalse)
2435  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2436  if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse)
2437  return(MagickFalse);
2438  if ((image->background_color.alpha_trait != UndefinedPixelTrait) &&
2439  ((image->alpha_trait & BlendPixelTrait) == 0))
2440  (void) SetImageAlphaChannel(image,ActivateAlphaChannel,exception);
2441  ConformPixelInfo(image,&image->background_color,&background,exception);
2442  /*
2443  Set image background color.
2444  */
2445  status=MagickTrue;
2446  image_view=AcquireAuthenticCacheView(image,exception);
2447 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2448  #pragma omp parallel for schedule(static) shared(status) \
2449  magick_number_threads(image,image,image->rows,2)
2450 #endif
2451  for (y=0; y < (ssize_t) image->rows; y++)
2452  {
2453  Quantum
2454  *magick_restrict q;
2455 
2456  ssize_t
2457  x;
2458 
2459  if (status == MagickFalse)
2460  continue;
2461  q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2462  if (q == (Quantum *) NULL)
2463  {
2464  status=MagickFalse;
2465  continue;
2466  }
2467  for (x=0; x < (ssize_t) image->columns; x++)
2468  {
2469  SetPixelViaPixelInfo(image,&background,q);
2470  q+=(ptrdiff_t) GetPixelChannels(image);
2471  }
2472  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2473  status=MagickFalse;
2474  }
2475  image_view=DestroyCacheView(image_view);
2476  return(status);
2477 }
2478 
2479 /*
2480 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2481 % %
2482 % %
2483 % %
2484 % S e t I m a g e C h a n n e l M a s k %
2485 % %
2486 % %
2487 % %
2488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2489 %
2490 % SetImageChannelMask() sets the image channel mask from the specified channel
2491 % mask.
2492 %
2493 % The format of the SetImageChannelMask method is:
2494 %
2495 % ChannelType SetImageChannelMask(Image *image,
2496 % const ChannelType channel_mask)
2497 %
2498 % A description of each parameter follows:
2499 %
2500 % o image: the image.
2501 %
2502 % o channel_mask: the channel mask.
2503 %
2504 */
2505 MagickExport ChannelType SetImageChannelMask(Image *image,
2506  const ChannelType channel_mask)
2507 {
2508  return(SetPixelChannelMask(image,channel_mask));
2509 }
2510 
2511 /*
2512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2513 % %
2514 % %
2515 % %
2516 % S e t I m a g e C o l o r %
2517 % %
2518 % %
2519 % %
2520 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2521 %
2522 % SetImageColor() set the entire image canvas to the specified color.
2523 %
2524 % The format of the SetImageColor method is:
2525 %
2526 % MagickBooleanType SetImageColor(Image *image,const PixelInfo *color,
2527 % ExceptionInfo *exception)
2528 %
2529 % A description of each parameter follows:
2530 %
2531 % o image: the image.
2532 %
2533 % o background: the image color.
2534 %
2535 % o exception: return any errors or warnings in this structure.
2536 %
2537 */
2538 MagickExport MagickBooleanType SetImageColor(Image *image,
2539  const PixelInfo *color,ExceptionInfo *exception)
2540 {
2541  CacheView
2542  *image_view;
2543 
2544  MagickBooleanType
2545  status;
2546 
2547  ssize_t
2548  y;
2549 
2550  assert(image != (Image *) NULL);
2551  assert(image->signature == MagickCoreSignature);
2552  assert(color != (const PixelInfo *) NULL);
2553  if (IsEventLogging() != MagickFalse)
2554  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2555  image->colorspace=color->colorspace;
2556  image->alpha_trait=color->alpha_trait;
2557  image->fuzz=color->fuzz;
2558  image->depth=color->depth;
2559  status=MagickTrue;
2560  image_view=AcquireAuthenticCacheView(image,exception);
2561 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2562  #pragma omp parallel for schedule(static) shared(status) \
2563  magick_number_threads(image,image,image->rows,2)
2564 #endif
2565  for (y=0; y < (ssize_t) image->rows; y++)
2566  {
2567  Quantum
2568  *magick_restrict q;
2569 
2570  ssize_t
2571  x;
2572 
2573  if (status == MagickFalse)
2574  continue;
2575  q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2576  if (q == (Quantum *) NULL)
2577  {
2578  status=MagickFalse;
2579  continue;
2580  }
2581  for (x=0; x < (ssize_t) image->columns; x++)
2582  {
2583  SetPixelViaPixelInfo(image,color,q);
2584  q+=(ptrdiff_t) GetPixelChannels(image);
2585  }
2586  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2587  status=MagickFalse;
2588  }
2589  image_view=DestroyCacheView(image_view);
2590  return(status);
2591 }
2592 
2593 /*
2594 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2595 % %
2596 % %
2597 % %
2598 % S e t I m a g e S t o r a g e C l a s s %
2599 % %
2600 % %
2601 % %
2602 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2603 %
2604 % SetImageStorageClass() sets the image class: DirectClass for true color
2605 % images or PseudoClass for colormapped images.
2606 %
2607 % The format of the SetImageStorageClass method is:
2608 %
2609 % MagickBooleanType SetImageStorageClass(Image *image,
2610 % const ClassType storage_class,ExceptionInfo *exception)
2611 %
2612 % A description of each parameter follows:
2613 %
2614 % o image: the image.
2615 %
2616 % o storage_class: The image class.
2617 %
2618 % o exception: return any errors or warnings in this structure.
2619 %
2620 */
2621 MagickExport MagickBooleanType SetImageStorageClass(Image *image,
2622  const ClassType storage_class,ExceptionInfo *exception)
2623 {
2624  assert(image != (Image *) NULL);
2625  assert(image->signature == MagickCoreSignature);
2626  assert(exception != (ExceptionInfo *) NULL);
2627  assert(exception->signature == MagickCoreSignature);
2628  if (IsEventLogging() != MagickFalse)
2629  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2630  image->storage_class=storage_class;
2631  return(SyncImagePixelCache(image,exception));
2632 }
2633 
2634 /*
2635 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2636 % %
2637 % %
2638 % %
2639 % S e t I m a g e E x t e n t %
2640 % %
2641 % %
2642 % %
2643 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2644 %
2645 % SetImageExtent() sets the image size (i.e. columns & rows).
2646 %
2647 % The format of the SetImageExtent method is:
2648 %
2649 % MagickBooleanType SetImageExtent(Image *image,const size_t columns,
2650 % const size_t rows,ExceptionInfo *exception)
2651 %
2652 % A description of each parameter follows:
2653 %
2654 % o image: the image.
2655 %
2656 % o columns: The image width in pixels.
2657 %
2658 % o rows: The image height in pixels.
2659 %
2660 % o exception: return any errors or warnings in this structure.
2661 %
2662 */
2663 MagickExport MagickBooleanType SetImageExtent(Image *image,const size_t columns,
2664  const size_t rows,ExceptionInfo *exception)
2665 {
2666  if ((columns == 0) || (rows == 0))
2667  ThrowBinaryException(ImageError,"NegativeOrZeroImageSize",image->filename);
2668  image->columns=columns;
2669  image->rows=rows;
2670  if (image->depth == 0)
2671  {
2672  image->depth=8;
2673  (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
2674  "ImageDepthNotSupported","`%s'",image->filename);
2675  }
2676  if (image->depth > (8*sizeof(MagickSizeType)))
2677  {
2678  image->depth=8*sizeof(MagickSizeType);
2679  (void) ThrowMagickException(exception,GetMagickModule(),ImageError,
2680  "ImageDepthNotSupported","`%s'",image->filename);
2681  }
2682  return(SyncImagePixelCache(image,exception));
2683 }
2684 
2685 /*
2686 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2687 % %
2688 % %
2689 % %
2690 + S e t I m a g e I n f o %
2691 % %
2692 % %
2693 % %
2694 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2695 %
2696 % SetImageInfo() initializes the 'magick' field of the ImageInfo structure.
2697 % It is set to a type of image format based on the prefix or suffix of the
2698 % filename. For example, 'ps:image' returns PS indicating a Postscript image.
2699 % JPEG is returned for this filename: 'image.jpg'. The filename prefix has
2700 % precedence over the suffix. Use an optional index enclosed in brackets
2701 % after a file name to specify a desired scene of a multi-resolution image
2702 % format like Photo CD (e.g. img0001.pcd[4]). A True (non-zero) return value
2703 % indicates success.
2704 %
2705 % The format of the SetImageInfo method is:
2706 %
2707 % MagickBooleanType SetImageInfo(ImageInfo *image_info,
2708 % const unsigned int frames,ExceptionInfo *exception)
2709 %
2710 % A description of each parameter follows:
2711 %
2712 % o image_info: the image info.
2713 %
2714 % o frames: the number of images you intend to write.
2715 %
2716 % o exception: return any errors or warnings in this structure.
2717 %
2718 */
2719 
2720 static const MagickInfo *SetImageInfoFromExtension(ImageInfo *image_info,
2721  const char *component,char *magic,ExceptionInfo *exception)
2722 {
2723  const MagickInfo
2724  *magick_info;
2725 
2726  MagickFormatType
2727  format_type;
2728 
2729  ssize_t
2730  i;
2731 
2732  static const char
2733  *format_type_formats[] =
2734  {
2735  "AUTOTRACE",
2736  "BROWSE",
2737  "DCRAW",
2738  "EDIT",
2739  "LAUNCH",
2740  "MPEG:DECODE",
2741  "MPEG:ENCODE",
2742  "PRINT",
2743  "PS:ALPHA",
2744  "PS:CMYK",
2745  "PS:COLOR",
2746  "PS:GRAY",
2747  "PS:MONO",
2748  "SCAN",
2749  "SHOW",
2750  "WIN",
2751  (char *) NULL
2752  };
2753 
2754  /*
2755  User specified image format.
2756  */
2757  (void) CopyMagickString(magic,component,MagickPathExtent);
2758  LocaleUpper(magic);
2759  /*
2760  Look for explicit image formats.
2761  */
2762  format_type=UndefinedFormatType;
2763  magick_info=GetMagickInfo(magic,exception);
2764  if ((magick_info != (const MagickInfo *) NULL) &&
2765  (magick_info->format_type != UndefinedFormatType))
2766  format_type=magick_info->format_type;
2767  i=0;
2768  while ((format_type == UndefinedFormatType) &&
2769  (format_type_formats[i] != (char *) NULL))
2770  {
2771  if ((*magic == *format_type_formats[i]) &&
2772  (LocaleCompare(magic,format_type_formats[i]) == 0))
2773  format_type=ExplicitFormatType;
2774  i++;
2775  }
2776  if (format_type == UndefinedFormatType)
2777  (void) CopyMagickString(image_info->magick,magic,MagickPathExtent);
2778  else
2779  if (format_type == ExplicitFormatType)
2780  {
2781  image_info->affirm=MagickTrue;
2782  (void) CopyMagickString(image_info->magick,magic,MagickPathExtent);
2783  }
2784  if (LocaleCompare(magic,"RGB") == 0)
2785  image_info->affirm=MagickFalse; /* maybe SGI disguised as RGB */
2786  return(magick_info);
2787 }
2788 
2789 MagickExport MagickBooleanType SetImageInfo(ImageInfo *image_info,
2790  const unsigned int frames,ExceptionInfo *exception)
2791 {
2792  char
2793  component[MagickPathExtent],
2794  magic[MagickPathExtent],
2795  path[MagickPathExtent],
2796  *q;
2797 
2798  const MagicInfo
2799  *magic_info;
2800 
2801  const MagickInfo
2802  *magick_info;
2803 
2805  *sans_exception;
2806 
2807  Image
2808  *image;
2809 
2810  MagickBooleanType
2811  status;
2812 
2813  const char
2814  *p;
2815 
2816  ssize_t
2817  count;
2818 
2819  /*
2820  Look for 'image.format' in filename.
2821  */
2822  assert(image_info != (ImageInfo *) NULL);
2823  assert(image_info->signature == MagickCoreSignature);
2824  if (IsEventLogging() != MagickFalse)
2825  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
2826  image_info->filename);
2827  *component='\0';
2828  GetPathComponent(image_info->filename,SubimagePath,component);
2829  if (*component != '\0')
2830  {
2831  /*
2832  Look for scene specification (e.g. img0001.pcd[4]).
2833  */
2834  if (IsSceneGeometry(component,MagickFalse) == MagickFalse)
2835  {
2836  if (IsGeometry(component) != MagickFalse)
2837  (void) CloneString(&image_info->extract,component);
2838  }
2839  else
2840  {
2841  size_t
2842  first,
2843  last;
2844 
2845  (void) CloneString(&image_info->scenes,component);
2846  image_info->scene=StringToUnsignedLong(image_info->scenes);
2847  image_info->number_scenes=image_info->scene;
2848  p=image_info->scenes;
2849  for (q=(char *) image_info->scenes; *q != '\0'; p++)
2850  {
2851  while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ','))
2852  p++;
2853  first=(size_t) strtol(p,&q,10);
2854  last=first;
2855  while (isspace((int) ((unsigned char) *q)) != 0)
2856  q++;
2857  if (*q == '-')
2858  last=(size_t) strtol(q+1,&q,10);
2859  if (first > last)
2860  Swap(first,last);
2861  if (first < image_info->scene)
2862  image_info->scene=first;
2863  if (last > image_info->number_scenes)
2864  image_info->number_scenes=last;
2865  p=q;
2866  }
2867  image_info->number_scenes-=image_info->scene-1;
2868  }
2869  }
2870  *component='\0';
2871  if (*image_info->magick == '\0')
2872  GetPathComponent(image_info->filename,ExtensionPath,component);
2873  if (*component != '\0')
2874  {
2875  /*
2876  Base path sans any compression extension.
2877  */
2878  GetPathComponent(image_info->filename,BasePathSansCompressExtension,path);
2879  GetPathComponent(path,ExtensionPath,component);
2880  }
2881  image_info->affirm=MagickFalse;
2882  sans_exception=AcquireExceptionInfo();
2883  if ((*component != '\0') && (IsGlob(component) == MagickFalse))
2884  magick_info=SetImageInfoFromExtension(image_info,component,magic,
2885  sans_exception);
2886  /*
2887  Look for explicit 'format:image' in filename.
2888  */
2889  *magic='\0';
2890  GetPathComponent(image_info->filename,MagickPath,magic);
2891  if (*magic == '\0')
2892  {
2893  (void) CopyMagickString(magic,image_info->magick,MagickPathExtent);
2894  magick_info=GetMagickInfo(magic,sans_exception);
2895  if ((magick_info != (const MagickInfo *) NULL) &&
2896  (magick_info->format_type == ExplicitFormatType))
2897  image_info->affirm=MagickTrue;
2898  if (frames == 0)
2899  GetPathComponent(image_info->filename,CanonicalPath,component);
2900  else
2901  GetPathComponent(image_info->filename,SubcanonicalPath,component);
2902  (void) CopyMagickString(image_info->filename,component,MagickPathExtent);
2903  }
2904  else
2905  {
2906  const DelegateInfo
2907  *delegate_info;
2908 
2909  /*
2910  User specified image format.
2911  */
2912  LocaleUpper(magic);
2913  magick_info=GetMagickInfo(magic,sans_exception);
2914  delegate_info=(const DelegateInfo *) NULL;
2915  if (magick_info == (const MagickInfo *) NULL)
2916  {
2917  delegate_info=GetDelegateInfo(magic,"*",sans_exception);
2918  if (delegate_info == (const DelegateInfo *) NULL)
2919  delegate_info=GetDelegateInfo("*",magic,sans_exception);
2920  if ((delegate_info == (const DelegateInfo *) NULL) &&
2921  ((*component != '\0') && (IsGlob(component) == MagickFalse)))
2922  {
2923  /*
2924  Retry in case GetMagickInfo loaded a custom module.
2925  */
2926  magick_info=SetImageInfoFromExtension(image_info,component,magic,
2927  sans_exception);
2928  }
2929  }
2930  if (((magick_info != (const MagickInfo *) NULL) ||
2931  (delegate_info != (const DelegateInfo *) NULL)) &&
2932  (IsMagickConflict(magic) == MagickFalse))
2933  {
2934  image_info->affirm=MagickTrue;
2935  (void) CopyMagickString(image_info->magick,magic,MagickPathExtent);
2936  GetPathComponent(image_info->filename,CanonicalPath,component);
2937  (void) CopyMagickString(image_info->filename,component,
2938  MagickPathExtent);
2939  }
2940  }
2941  sans_exception=DestroyExceptionInfo(sans_exception);
2942  if ((magick_info == (const MagickInfo *) NULL) ||
2943  (GetMagickEndianSupport(magick_info) == MagickFalse))
2944  image_info->endian=UndefinedEndian;
2945  if ((image_info->adjoin != MagickFalse) && (frames > 1))
2946  {
2947  /*
2948  Test for multiple image support (e.g. image%02d.png).
2949  */
2950  (void) InterpretImageFilename(image_info,(Image *) NULL,
2951  image_info->filename,(int) image_info->scene,component,exception);
2952  if ((LocaleCompare(component,image_info->filename) != 0) &&
2953  (strchr(component,'%') == (char *) NULL))
2954  image_info->adjoin=MagickFalse;
2955  }
2956  if ((image_info->adjoin != MagickFalse) && (frames > 0))
2957  {
2958  /*
2959  Some image formats do not support multiple frames per file.
2960  */
2961  magick_info=GetMagickInfo(magic,exception);
2962  if (magick_info != (const MagickInfo *) NULL)
2963  if (GetMagickAdjoin(magick_info) == MagickFalse)
2964  image_info->adjoin=MagickFalse;
2965  }
2966  if (image_info->affirm != MagickFalse)
2967  return(MagickTrue);
2968  if (frames == 0)
2969  {
2970  unsigned char
2971  *magick;
2972 
2973  size_t
2974  magick_size;
2975 
2976  /*
2977  Determine the image format from the first few bytes of the file.
2978  */
2979  magick_size=GetMagicPatternExtent(exception);
2980  if (magick_size == 0)
2981  return(MagickFalse);
2982  image=AcquireImage(image_info,exception);
2983  (void) CopyMagickString(image->filename,image_info->filename,
2984  MagickPathExtent);
2985  sans_exception=AcquireExceptionInfo();
2986  status=OpenBlob(image_info,image,ReadBinaryBlobMode,sans_exception);
2987  sans_exception=DestroyExceptionInfo(sans_exception);
2988  if (status == MagickFalse)
2989  {
2990  image=DestroyImage(image);
2991  return(MagickFalse);
2992  }
2993  if ((IsBlobSeekable(image) == MagickFalse) ||
2994  (IsBlobExempt(image) != MagickFalse))
2995  {
2996  /*
2997  Copy image to seekable temporary file.
2998  */
2999  *component='\0';
3000  status=ImageToFile(image,component,exception);
3001  if (CloseBlob(image) == MagickFalse)
3002  status=MagickFalse;
3003  if (status == MagickFalse)
3004  {
3005  (void) RelinquishUniqueFileResource(component);
3006  image=DestroyImage(image);
3007  return(MagickFalse);
3008  }
3009  SetImageInfoFile(image_info,(FILE *) NULL);
3010  (void) CopyMagickString(image->filename,component,MagickPathExtent);
3011  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
3012  if (status == MagickFalse)
3013  {
3014  (void) RelinquishUniqueFileResource(component);
3015  image=DestroyImage(image);
3016  return(MagickFalse);
3017  }
3018  (void) CopyMagickString(image_info->filename,component,
3019  MagickPathExtent);
3020  image_info->temporary=MagickTrue;
3021  }
3022  magick=(unsigned char *) AcquireQuantumMemory(1,magick_size);
3023  if (magick == (unsigned char *) NULL)
3024  {
3025  (void) CloseBlob(image);
3026  image=DestroyImage(image);
3027  return(MagickFalse);
3028  }
3029  (void) memset(magick,0,magick_size);
3030  count=ReadBlob(image,magick_size,magick);
3031  (void) SeekBlob(image,-((MagickOffsetType) count),SEEK_CUR);
3032  (void) CloseBlob(image);
3033  image=DestroyImage(image);
3034  /*
3035  Check magic cache.
3036  */
3037  sans_exception=AcquireExceptionInfo();
3038  magic_info=GetMagicInfo(magick,(size_t) count,sans_exception);
3039  magick=(unsigned char *) RelinquishMagickMemory(magick);
3040  if ((magic_info != (const MagicInfo *) NULL) &&
3041  (GetMagicName(magic_info) != (char *) NULL))
3042  {
3043  /*
3044  Try to use magick_info that was determined earlier by the extension
3045  */
3046  if ((magick_info != (const MagickInfo *) NULL) &&
3047  (GetMagickUseExtension(magick_info) != MagickFalse) &&
3048  (LocaleCompare(magick_info->magick_module,GetMagicName(
3049  magic_info)) == 0))
3050  (void) CopyMagickString(image_info->magick,magick_info->name,
3051  MagickPathExtent);
3052  else
3053  {
3054  (void) CopyMagickString(image_info->magick,GetMagicName(
3055  magic_info),MagickPathExtent);
3056  magick_info=GetMagickInfo(image_info->magick,sans_exception);
3057  }
3058  if ((magick_info == (const MagickInfo *) NULL) ||
3059  (GetMagickEndianSupport(magick_info) == MagickFalse))
3060  image_info->endian=UndefinedEndian;
3061  sans_exception=DestroyExceptionInfo(sans_exception);
3062  return(MagickTrue);
3063  }
3064  magick_info=GetMagickInfo(image_info->magick,sans_exception);
3065  if ((magick_info == (const MagickInfo *) NULL) ||
3066  (GetMagickEndianSupport(magick_info) == MagickFalse))
3067  image_info->endian=UndefinedEndian;
3068  sans_exception=DestroyExceptionInfo(sans_exception);
3069  }
3070  return(MagickTrue);
3071 }
3072 
3073 /*
3074 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3075 % %
3076 % %
3077 % %
3078 % S e t I m a g e I n f o B l o b %
3079 % %
3080 % %
3081 % %
3082 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3083 %
3084 % SetImageInfoBlob() sets the image info blob member.
3085 %
3086 % The format of the SetImageInfoBlob method is:
3087 %
3088 % void SetImageInfoBlob(ImageInfo *image_info,const void *blob,
3089 % const size_t length)
3090 %
3091 % A description of each parameter follows:
3092 %
3093 % o image_info: the image info.
3094 %
3095 % o blob: the blob.
3096 %
3097 % o length: the blob length.
3098 %
3099 */
3100 MagickExport void SetImageInfoBlob(ImageInfo *image_info,const void *blob,
3101  const size_t length)
3102 {
3103  assert(image_info != (ImageInfo *) NULL);
3104  assert(image_info->signature == MagickCoreSignature);
3105  if (IsEventLogging() != MagickFalse)
3106  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3107  image_info->filename);
3108  image_info->blob=(void *) blob;
3109  image_info->length=length;
3110 }
3111 
3112 /*
3113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3114 % %
3115 % %
3116 % %
3117 % S e t I m a g e I n f o C u s t o m S t r e a m %
3118 % %
3119 % %
3120 % %
3121 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3122 %
3123 % SetImageInfoCustomStream() sets the image info custom stream handlers.
3124 %
3125 % The format of the SetImageInfoCustomStream method is:
3126 %
3127 % void SetImageInfoCustomStream(ImageInfo *image_info,
3128 % CustomStreamInfo *custom_stream)
3129 %
3130 % A description of each parameter follows:
3131 %
3132 % o image_info: the image info.
3133 %
3134 % o custom_stream: your custom stream methods.
3135 %
3136 */
3137 MagickExport void SetImageInfoCustomStream(ImageInfo *image_info,
3138  CustomStreamInfo *custom_stream)
3139 {
3140  assert(image_info != (ImageInfo *) NULL);
3141  assert(image_info->signature == MagickCoreSignature);
3142  if (IsEventLogging() != MagickFalse)
3143  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3144  image_info->filename);
3145  image_info->custom_stream=(CustomStreamInfo *) custom_stream;
3146 }
3147 
3148 /*
3149 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3150 % %
3151 % %
3152 % %
3153 % S e t I m a g e I n f o F i l e %
3154 % %
3155 % %
3156 % %
3157 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3158 %
3159 % SetImageInfoFile() sets the image info file member.
3160 %
3161 % The format of the SetImageInfoFile method is:
3162 %
3163 % void SetImageInfoFile(ImageInfo *image_info,FILE *file)
3164 %
3165 % A description of each parameter follows:
3166 %
3167 % o image_info: the image info.
3168 %
3169 % o file: the file.
3170 %
3171 */
3172 MagickExport void SetImageInfoFile(ImageInfo *image_info,FILE *file)
3173 {
3174  assert(image_info != (ImageInfo *) NULL);
3175  assert(image_info->signature == MagickCoreSignature);
3176  if (IsEventLogging() != MagickFalse)
3177  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3178  image_info->filename);
3179  image_info->file=file;
3180 }
3181 
3182 /*
3183 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3184 % %
3185 % %
3186 % %
3187 % S e t I m a g e M a s k %
3188 % %
3189 % %
3190 % %
3191 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3192 %
3193 % SetImageMask() associates a mask with the image. The mask must be the same
3194 % dimensions as the image.
3195 %
3196 % The format of the SetImageMask method is:
3197 %
3198 % MagickBooleanType SetImageMask(Image *image,const PixelMask type,
3199 % const Image *mask,ExceptionInfo *exception)
3200 %
3201 % A description of each parameter follows:
3202 %
3203 % o image: the image.
3204 %
3205 % o type: the mask type, ReadPixelMask or WritePixelMask.
3206 %
3207 % o mask: the image mask.
3208 %
3209 % o exception: return any errors or warnings in this structure.
3210 %
3211 */
3212 MagickExport MagickBooleanType SetImageMask(Image *image,const PixelMask type,
3213  const Image *mask,ExceptionInfo *exception)
3214 {
3215  CacheView
3216  *mask_view,
3217  *image_view;
3218 
3219  MagickBooleanType
3220  status;
3221 
3222  ssize_t
3223  y;
3224 
3225  /*
3226  Set image mask.
3227  */
3228  assert(image != (Image *) NULL);
3229  if (IsEventLogging() != MagickFalse)
3230  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3231  assert(image->signature == MagickCoreSignature);
3232  if (mask == (const Image *) NULL)
3233  {
3234  switch (type)
3235  {
3236  case ReadPixelMask:
3237  {
3238  image->channels=(ChannelType) ((unsigned int) image->channels &
3239  (unsigned int) ~ReadMaskChannel);
3240  break;
3241  }
3242  case WritePixelMask:
3243  {
3244  image->channels=(ChannelType) ((unsigned int) image->channels &
3245  (unsigned int) ~WriteMaskChannel);
3246  magick_fallthrough;
3247  }
3248  default:
3249  {
3250  image->channels=(ChannelType) ((unsigned int) image->channels &
3251  (unsigned int) ~CompositeMaskChannel);
3252  break;
3253  }
3254  }
3255  return(SyncImagePixelCache(image,exception));
3256  }
3257  switch (type)
3258  {
3259  case ReadPixelMask:
3260  {
3261  image->channels=(ChannelType) (image->channels | ReadMaskChannel);
3262  break;
3263  }
3264  case WritePixelMask:
3265  {
3266  image->channels=(ChannelType) (image->channels | WriteMaskChannel);
3267  break;
3268  }
3269  default:
3270  {
3271  image->channels=(ChannelType) (image->channels | CompositeMaskChannel);
3272  break;
3273  }
3274  }
3275  if (SyncImagePixelCache(image,exception) == MagickFalse)
3276  return(MagickFalse);
3277  status=MagickTrue;
3278  image->mask_trait=UpdatePixelTrait;
3279  mask_view=AcquireVirtualCacheView(mask,exception);
3280  image_view=AcquireAuthenticCacheView(image,exception);
3281 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3282  #pragma omp parallel for schedule(static) shared(status) \
3283  magick_number_threads(mask,image,image->rows,2)
3284 #endif
3285  for (y=0; y < (ssize_t) image->rows; y++)
3286  {
3287  const Quantum
3288  *magick_restrict p;
3289 
3290  Quantum
3291  *magick_restrict q;
3292 
3293  ssize_t
3294  x;
3295 
3296  if (status == MagickFalse)
3297  continue;
3298  p=GetCacheViewVirtualPixels(mask_view,0,y,mask->columns,1,exception);
3299  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3300  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
3301  {
3302  status=MagickFalse;
3303  continue;
3304  }
3305  for (x=0; x < (ssize_t) image->columns; x++)
3306  {
3307  MagickRealType
3308  intensity;
3309 
3310  intensity=0.0;
3311  if ((x < (ssize_t) mask->columns) && (y < (ssize_t) mask->rows))
3312  intensity=GetPixelIntensity(mask,p);
3313  switch (type)
3314  {
3315  case ReadPixelMask:
3316  {
3317  SetPixelReadMask(image,ClampToQuantum(intensity),q);
3318  break;
3319  }
3320  case WritePixelMask:
3321  {
3322  SetPixelWriteMask(image,ClampToQuantum(intensity),q);
3323  break;
3324  }
3325  default:
3326  {
3327  SetPixelCompositeMask(image,ClampToQuantum(intensity),q);
3328  break;
3329  }
3330  }
3331  p+=(ptrdiff_t) GetPixelChannels(mask);
3332  q+=(ptrdiff_t) GetPixelChannels(image);
3333  }
3334  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3335  status=MagickFalse;
3336  }
3337  image->mask_trait=UndefinedPixelTrait;
3338  mask_view=DestroyCacheView(mask_view);
3339  image_view=DestroyCacheView(image_view);
3340  return(status);
3341 }
3342 
3343 /*
3344 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3345 % %
3346 % %
3347 % %
3348 % S e t I m a g e R e g i o n M a s k %
3349 % %
3350 % %
3351 % %
3352 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3353 %
3354 % SetImageRegionMask() associates a mask with the image as defined by the
3355 % specified region.
3356 %
3357 % The format of the SetImageRegionMask method is:
3358 %
3359 % MagickBooleanType SetImageRegionMask(Image *image,const PixelMask type,
3360 % const RectangleInfo *region,ExceptionInfo *exception)
3361 %
3362 % A description of each parameter follows:
3363 %
3364 % o image: the image.
3365 %
3366 % o type: the mask type, ReadPixelMask or WritePixelMask.
3367 %
3368 % o geometry: the mask region.
3369 %
3370 % o exception: return any errors or warnings in this structure.
3371 %
3372 */
3373 MagickExport MagickBooleanType SetImageRegionMask(Image *image,
3374  const PixelMask type,const RectangleInfo *region,ExceptionInfo *exception)
3375 {
3376  CacheView
3377  *image_view;
3378 
3379  MagickBooleanType
3380  status;
3381 
3382  ssize_t
3383  y;
3384 
3385  /*
3386  Set image mask as defined by the region.
3387  */
3388  assert(image != (Image *) NULL);
3389  assert(image->signature == MagickCoreSignature);
3390  if (IsEventLogging() != MagickFalse)
3391  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3392  if (region == (const RectangleInfo *) NULL)
3393  {
3394  switch (type)
3395  {
3396  case ReadPixelMask:
3397  {
3398  image->channels=(ChannelType) ((unsigned int) image->channels &
3399  (unsigned int) ~ReadMaskChannel);
3400  break;
3401  }
3402  case WritePixelMask:
3403  {
3404  image->channels=(ChannelType) ((unsigned int) image->channels &
3405  (unsigned int) ~WriteMaskChannel);
3406  break;
3407  }
3408  default:
3409  {
3410  image->channels=(ChannelType) ((unsigned int) image->channels &
3411  (unsigned int) ~CompositeMaskChannel);
3412  break;
3413  }
3414  }
3415  return(SyncImagePixelCache(image,exception));
3416  }
3417  switch (type)
3418  {
3419  case ReadPixelMask:
3420  {
3421  image->channels=(ChannelType) (image->channels | ReadMaskChannel);
3422  break;
3423  }
3424  case WritePixelMask:
3425  {
3426  image->channels=(ChannelType) (image->channels | WriteMaskChannel);
3427  break;
3428  }
3429  default:
3430  {
3431  image->channels=(ChannelType) (image->channels | CompositeMaskChannel);
3432  break;
3433  }
3434  }
3435  if (SyncImagePixelCache(image,exception) == MagickFalse)
3436  return(MagickFalse);
3437  status=MagickTrue;
3438  image->mask_trait=UpdatePixelTrait;
3439  image_view=AcquireAuthenticCacheView(image,exception);
3440 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3441  #pragma omp parallel for schedule(static) shared(status) \
3442  magick_number_threads(image,image,image->rows,2)
3443 #endif
3444  for (y=0; y < (ssize_t) image->rows; y++)
3445  {
3446  Quantum
3447  *magick_restrict q;
3448 
3449  ssize_t
3450  x;
3451 
3452  if (status == MagickFalse)
3453  continue;
3454  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3455  if (q == (Quantum *) NULL)
3456  {
3457  status=MagickFalse;
3458  continue;
3459  }
3460  for (x=0; x < (ssize_t) image->columns; x++)
3461  {
3462  Quantum
3463  pixel;
3464 
3465  pixel=QuantumRange;
3466  if (((x >= region->x) && (x < (region->x+(ssize_t) region->width))) &&
3467  ((y >= region->y) && (y < (region->y+(ssize_t) region->height))))
3468  pixel=(Quantum) 0;
3469  switch (type)
3470  {
3471  case ReadPixelMask:
3472  {
3473  SetPixelReadMask(image,pixel,q);
3474  break;
3475  }
3476  case WritePixelMask:
3477  {
3478  SetPixelWriteMask(image,pixel,q);
3479  break;
3480  }
3481  default:
3482  {
3483  SetPixelCompositeMask(image,pixel,q);
3484  break;
3485  }
3486  }
3487  q+=(ptrdiff_t) GetPixelChannels(image);
3488  }
3489  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3490  status=MagickFalse;
3491  }
3492  image->mask_trait=UndefinedPixelTrait;
3493  image_view=DestroyCacheView(image_view);
3494  return(status);
3495 }
3496 
3497 /*
3498 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3499 % %
3500 % %
3501 % %
3502 % S e t I m a g e V i r t u a l P i x e l M e t h o d %
3503 % %
3504 % %
3505 % %
3506 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3507 %
3508 % SetImageVirtualPixelMethod() sets the "virtual pixels" method for the
3509 % image and returns the previous setting. A virtual pixel is any pixel access
3510 % that is outside the boundaries of the image cache.
3511 %
3512 % The format of the SetImageVirtualPixelMethod() method is:
3513 %
3514 % VirtualPixelMethod SetImageVirtualPixelMethod(Image *image,
3515 % const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
3516 %
3517 % A description of each parameter follows:
3518 %
3519 % o image: the image.
3520 %
3521 % o virtual_pixel_method: choose the type of virtual pixel.
3522 %
3523 % o exception: return any errors or warnings in this structure.
3524 %
3525 */
3526 MagickExport VirtualPixelMethod SetImageVirtualPixelMethod(Image *image,
3527  const VirtualPixelMethod virtual_pixel_method,ExceptionInfo *exception)
3528 {
3529  assert(image != (const Image *) NULL);
3530  assert(image->signature == MagickCoreSignature);
3531  if (IsEventLogging() != MagickFalse)
3532  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3533  return(SetPixelCacheVirtualMethod(image,virtual_pixel_method,exception));
3534 }
3535 
3536 /*
3537 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3538 % %
3539 % %
3540 % %
3541 % S m u s h I m a g e s %
3542 % %
3543 % %
3544 % %
3545 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3546 %
3547 % SmushImages() takes all images from the current image pointer to the end
3548 % of the image list and smushes them to each other top-to-bottom if the
3549 % stack parameter is true, otherwise left-to-right.
3550 %
3551 % The current gravity setting now effects how the image is justified in the
3552 % final image.
3553 %
3554 % The format of the SmushImages method is:
3555 %
3556 % Image *SmushImages(const Image *images,const MagickBooleanType stack,
3557 % ExceptionInfo *exception)
3558 %
3559 % A description of each parameter follows:
3560 %
3561 % o images: the image sequence.
3562 %
3563 % o stack: A value other than 0 stacks the images top-to-bottom.
3564 %
3565 % o offset: minimum distance in pixels between images.
3566 %
3567 % o exception: return any errors or warnings in this structure.
3568 %
3569 */
3570 
3571 static ssize_t SmushXGap(const Image *smush_image,const Image *images,
3572  const ssize_t offset,ExceptionInfo *exception)
3573 {
3574  CacheView
3575  *left_view,
3576  *right_view;
3577 
3578  const Image
3579  *left_image,
3580  *right_image;
3581 
3583  left_geometry,
3584  right_geometry;
3585 
3586  const Quantum
3587  *p;
3588 
3589  ssize_t
3590  i,
3591  y;
3592 
3593  size_t
3594  gap;
3595 
3596  ssize_t
3597  x;
3598 
3599  if (images->previous == (Image *) NULL)
3600  return(0);
3601  right_image=images;
3602  SetGeometry(smush_image,&right_geometry);
3603  GravityAdjustGeometry(right_image->columns,right_image->rows,
3604  right_image->gravity,&right_geometry);
3605  left_image=images->previous;
3606  SetGeometry(smush_image,&left_geometry);
3607  GravityAdjustGeometry(left_image->columns,left_image->rows,
3608  left_image->gravity,&left_geometry);
3609  gap=right_image->columns;
3610  left_view=AcquireVirtualCacheView(left_image,exception);
3611  right_view=AcquireVirtualCacheView(right_image,exception);
3612  for (y=0; y < (ssize_t) smush_image->rows; y++)
3613  {
3614  for (x=(ssize_t) left_image->columns-1; x > 0; x--)
3615  {
3616  p=GetCacheViewVirtualPixels(left_view,x,left_geometry.y+y,1,1,exception);
3617  if ((p == (const Quantum *) NULL) ||
3618  (GetPixelAlpha(left_image,p) != TransparentAlpha) ||
3619  (((ssize_t) left_image->columns-x-1) >= (ssize_t) gap))
3620  break;
3621  }
3622  i=(ssize_t) left_image->columns-x-1;
3623  for (x=0; x < (ssize_t) right_image->columns; x++)
3624  {
3625  p=GetCacheViewVirtualPixels(right_view,x,right_geometry.y+y,1,1,
3626  exception);
3627  if ((p == (const Quantum *) NULL) ||
3628  (GetPixelAlpha(right_image,p) != TransparentAlpha) ||
3629  ((x+i) >= (ssize_t) gap))
3630  break;
3631  }
3632  if ((x+i) < (ssize_t) gap)
3633  gap=(size_t) (x+i);
3634  }
3635  right_view=DestroyCacheView(right_view);
3636  left_view=DestroyCacheView(left_view);
3637  if (y < (ssize_t) smush_image->rows)
3638  return(offset);
3639  return((ssize_t) gap-offset);
3640 }
3641 
3642 static ssize_t SmushYGap(const Image *smush_image,const Image *images,
3643  const ssize_t offset,ExceptionInfo *exception)
3644 {
3645  CacheView
3646  *bottom_view,
3647  *top_view;
3648 
3649  const Image
3650  *bottom_image,
3651  *top_image;
3652 
3654  bottom_geometry,
3655  top_geometry;
3656 
3657  const Quantum
3658  *p;
3659 
3660  ssize_t
3661  i,
3662  x;
3663 
3664  size_t
3665  gap;
3666 
3667  ssize_t
3668  y;
3669 
3670  if (images->previous == (Image *) NULL)
3671  return(0);
3672  bottom_image=images;
3673  SetGeometry(smush_image,&bottom_geometry);
3674  GravityAdjustGeometry(bottom_image->columns,bottom_image->rows,
3675  bottom_image->gravity,&bottom_geometry);
3676  top_image=images->previous;
3677  SetGeometry(smush_image,&top_geometry);
3678  GravityAdjustGeometry(top_image->columns,top_image->rows,top_image->gravity,
3679  &top_geometry);
3680  gap=bottom_image->rows;
3681  top_view=AcquireVirtualCacheView(top_image,exception);
3682  bottom_view=AcquireVirtualCacheView(bottom_image,exception);
3683  for (x=0; x < (ssize_t) smush_image->columns; x++)
3684  {
3685  for (y=(ssize_t) top_image->rows-1; y > 0; y--)
3686  {
3687  p=GetCacheViewVirtualPixels(top_view,top_geometry.x+x,y,1,1,exception);
3688  if ((p == (const Quantum *) NULL) ||
3689  (GetPixelAlpha(top_image,p) != TransparentAlpha) ||
3690  (((ssize_t) top_image->rows-y-1) >= (ssize_t) gap))
3691  break;
3692  }
3693  i=(ssize_t) top_image->rows-y-1;
3694  for (y=0; y < (ssize_t) bottom_image->rows; y++)
3695  {
3696  p=GetCacheViewVirtualPixels(bottom_view,bottom_geometry.x+x,y,1,1,
3697  exception);
3698  if ((p == (const Quantum *) NULL) ||
3699  (GetPixelAlpha(bottom_image,p) != TransparentAlpha) ||
3700  ((y+i) >= (ssize_t) gap))
3701  break;
3702  }
3703  if ((y+i) < (ssize_t) gap)
3704  gap=(size_t) (y+i);
3705  }
3706  bottom_view=DestroyCacheView(bottom_view);
3707  top_view=DestroyCacheView(top_view);
3708  if (x < (ssize_t) smush_image->columns)
3709  return(offset);
3710  return((ssize_t) gap-offset);
3711 }
3712 
3713 MagickExport Image *SmushImages(const Image *images,
3714  const MagickBooleanType stack,const ssize_t offset,ExceptionInfo *exception)
3715 {
3716 #define SmushImageTag "Smush/Image"
3717 
3718  const Image
3719  *image;
3720 
3721  Image
3722  *smush_image;
3723 
3724  MagickBooleanType
3725  proceed,
3726  status;
3727 
3728  MagickOffsetType
3729  n;
3730 
3731  PixelTrait
3732  alpha_trait;
3733 
3735  geometry;
3736 
3737  const Image
3738  *next;
3739 
3740  size_t
3741  height,
3742  number_images,
3743  width;
3744 
3745  ssize_t
3746  x_offset,
3747  y_offset;
3748 
3749  /*
3750  Compute maximum area of smushed area.
3751  */
3752  assert(images != (Image *) NULL);
3753  assert(images->signature == MagickCoreSignature);
3754  assert(exception != (ExceptionInfo *) NULL);
3755  assert(exception->signature == MagickCoreSignature);
3756  if (IsEventLogging() != MagickFalse)
3757  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
3758  image=images;
3759  alpha_trait=image->alpha_trait;
3760  number_images=1;
3761  width=image->columns;
3762  height=image->rows;
3763  next=GetNextImageInList(image);
3764  for ( ; next != (Image *) NULL; next=GetNextImageInList(next))
3765  {
3766  if (next->alpha_trait != UndefinedPixelTrait)
3767  alpha_trait=BlendPixelTrait;
3768  number_images++;
3769  if (stack != MagickFalse)
3770  {
3771  if (next->columns > width)
3772  width=next->columns;
3773  height+=next->rows;
3774  if (next->previous != (Image *) NULL)
3775  height=(size_t) MagickMax((ssize_t) height+offset,0U);
3776  continue;
3777  }
3778  width+=next->columns;
3779  if (next->previous != (Image *) NULL)
3780  width=(size_t) MagickMax((ssize_t) width+offset,0U);
3781  if (next->rows > height)
3782  height=next->rows;
3783  }
3784  /*
3785  Smush images.
3786  */
3787  smush_image=CloneImage(image,width,height,MagickTrue,exception);
3788  if (smush_image == (Image *) NULL)
3789  return((Image *) NULL);
3790  if (SetImageStorageClass(smush_image,DirectClass,exception) == MagickFalse)
3791  {
3792  smush_image=DestroyImage(smush_image);
3793  return((Image *) NULL);
3794  }
3795  smush_image->alpha_trait=alpha_trait;
3796  (void) SetImageBackgroundColor(smush_image,exception);
3797  status=MagickTrue;
3798  x_offset=0;
3799  y_offset=0;
3800  for (n=0; n < (MagickOffsetType) number_images; n++)
3801  {
3802  SetGeometry(smush_image,&geometry);
3803  GravityAdjustGeometry(image->columns,image->rows,image->gravity,&geometry);
3804  if (stack != MagickFalse)
3805  {
3806  x_offset-=geometry.x;
3807  y_offset-=SmushYGap(smush_image,image,offset,exception);
3808  }
3809  else
3810  {
3811  x_offset-=SmushXGap(smush_image,image,offset,exception);
3812  y_offset-=geometry.y;
3813  }
3814  status=CompositeImage(smush_image,image,OverCompositeOp,MagickTrue,x_offset,
3815  y_offset,exception);
3816  proceed=SetImageProgress(image,SmushImageTag,n,number_images);
3817  if (proceed == MagickFalse)
3818  break;
3819  if (stack == MagickFalse)
3820  {
3821  x_offset+=(ssize_t) image->columns;
3822  y_offset=0;
3823  }
3824  else
3825  {
3826  x_offset=0;
3827  y_offset+=(ssize_t) image->rows;
3828  }
3829  image=GetNextImageInList(image);
3830  }
3831  if (stack == MagickFalse)
3832  smush_image->columns=(size_t) x_offset;
3833  else
3834  smush_image->rows=(size_t) y_offset;
3835  if (status == MagickFalse)
3836  smush_image=DestroyImage(smush_image);
3837  return(smush_image);
3838 }
3839 
3840 /*
3841 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3842 % %
3843 % %
3844 % %
3845 % S t r i p I m a g e %
3846 % %
3847 % %
3848 % %
3849 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3850 %
3851 % StripImage() strips an image of all profiles and comments.
3852 %
3853 % The format of the StripImage method is:
3854 %
3855 % MagickBooleanType StripImage(Image *image,ExceptionInfo *exception)
3856 %
3857 % A description of each parameter follows:
3858 %
3859 % o image: the image.
3860 %
3861 % o exception: return any errors or warnings in this structure.
3862 %
3863 */
3864 MagickExport MagickBooleanType StripImage(Image *image,
3865  ExceptionInfo *magick_unused(exception))
3866 {
3867  MagickBooleanType
3868  status;
3869 
3870  magick_unreferenced(exception);
3871  assert(image != (Image *) NULL);
3872  if (IsEventLogging() != MagickFalse)
3873  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3874  DestroyImageProfiles(image);
3875  (void) DeleteImageProperty(image,"comment");
3876  (void) DeleteImageProperty(image,"date:create");
3877  (void) DeleteImageProperty(image,"date:modify");
3878  (void) DeleteImageProperty(image,"date:timestamp");
3879  status=SetImageArtifact(image,"png:exclude-chunk",
3880  "bKGD,caNv,cHRM,eXIf,gAMA,iCCP,iTXt,pHYs,sRGB,tEXt,zCCP,zTXt,date");
3881  return(status);
3882 }
3883 
3884 /*
3885 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3886 % %
3887 % %
3888 % %
3889 + S y n c I m a g e %
3890 % %
3891 % %
3892 % %
3893 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3894 %
3895 % SyncImage() initializes the red, green, and blue intensities of each pixel
3896 % as defined by the colormap index.
3897 %
3898 % The format of the SyncImage method is:
3899 %
3900 % MagickBooleanType SyncImage(Image *image,ExceptionInfo *exception)
3901 %
3902 % A description of each parameter follows:
3903 %
3904 % o image: the image.
3905 %
3906 % o exception: return any errors or warnings in this structure.
3907 %
3908 */
3909 
3910 static inline Quantum PushColormapIndex(Image *image,const Quantum index,
3911  MagickBooleanType *range_exception)
3912 {
3913  if ((size_t) index < image->colors)
3914  return(index);
3915  *range_exception=MagickTrue;
3916  return((Quantum) 0);
3917 }
3918 
3919 MagickExport MagickBooleanType SyncImage(Image *image,ExceptionInfo *exception)
3920 {
3921  CacheView
3922  *image_view;
3923 
3924  MagickBooleanType
3925  range_exception,
3926  status,
3927  taint;
3928 
3929  ssize_t
3930  y;
3931 
3932  assert(image != (Image *) NULL);
3933  assert(image->signature == MagickCoreSignature);
3934  if (IsEventLogging() != MagickFalse)
3935  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3936  if (image->ping != MagickFalse)
3937  return(MagickTrue);
3938  if (image->storage_class != PseudoClass)
3939  return(MagickFalse);
3940  assert(image->colormap != (PixelInfo *) NULL);
3941  range_exception=MagickFalse;
3942  status=MagickTrue;
3943  taint=image->taint;
3944  image_view=AcquireAuthenticCacheView(image,exception);
3945 #if defined(MAGICKCORE_OPENMP_SUPPORT)
3946  #pragma omp parallel for schedule(static) shared(range_exception,status) \
3947  magick_number_threads(image,image,image->rows,2)
3948 #endif
3949  for (y=0; y < (ssize_t) image->rows; y++)
3950  {
3951  Quantum
3952  index;
3953 
3954  Quantum
3955  *magick_restrict q;
3956 
3957  ssize_t
3958  x;
3959 
3960  if (status == MagickFalse)
3961  continue;
3962  q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3963  if (q == (Quantum *) NULL)
3964  {
3965  status=MagickFalse;
3966  continue;
3967  }
3968  for (x=0; x < (ssize_t) image->columns; x++)
3969  {
3970  index=PushColormapIndex(image,GetPixelIndex(image,q),&range_exception);
3971  SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
3972  q+=(ptrdiff_t) GetPixelChannels(image);
3973  }
3974  if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3975  status=MagickFalse;
3976  }
3977  image_view=DestroyCacheView(image_view);
3978  image->taint=taint;
3979  if ((image->ping == MagickFalse) && (range_exception != MagickFalse))
3980  (void) ThrowMagickException(exception,GetMagickModule(),
3981  CorruptImageWarning,"InvalidColormapIndex","`%s'",image->filename);
3982  return(status);
3983 }
3984 
3985 /*
3986 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3987 % %
3988 % %
3989 % %
3990 % S y n c I m a g e S e t t i n g s %
3991 % %
3992 % %
3993 % %
3994 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3995 %
3996 % SyncImageSettings() syncs any image_info global options into per-image
3997 % attributes.
3998 %
3999 % Note: in IMv6 free form 'options' were always mapped into 'artifacts', so
4000 % that operations and coders can find such settings. In IMv7 if a desired
4001 % per-image artifact is not set, then it will directly look for a global
4002 % option as a fallback, as such this copy is no longer needed, only the
4003 % link set up.
4004 %
4005 % The format of the SyncImageSettings method is:
4006 %
4007 % MagickBooleanType SyncImageSettings(const ImageInfo *image_info,
4008 % Image *image,ExceptionInfo *exception)
4009 % MagickBooleanType SyncImagesSettings(const ImageInfo *image_info,
4010 % Image *image,ExceptionInfo *exception)
4011 %
4012 % A description of each parameter follows:
4013 %
4014 % o image_info: the image info.
4015 %
4016 % o image: the image.
4017 %
4018 % o exception: return any errors or warnings in this structure.
4019 %
4020 */
4021 
4022 MagickExport MagickBooleanType SyncImagesSettings(ImageInfo *image_info,
4023  Image *images,ExceptionInfo *exception)
4024 {
4025  Image
4026  *image;
4027 
4028  assert(image_info != (const ImageInfo *) NULL);
4029  assert(image_info->signature == MagickCoreSignature);
4030  assert(images != (Image *) NULL);
4031  assert(images->signature == MagickCoreSignature);
4032  if (IsEventLogging() != MagickFalse)
4033  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
4034  image=images;
4035  for ( ; image != (Image *) NULL; image=GetNextImageInList(image))
4036  (void) SyncImageSettings(image_info,image,exception);
4037  (void) DeleteImageOption(image_info,"page");
4038  return(MagickTrue);
4039 }
4040 
4041 MagickExport MagickBooleanType SyncImageSettings(const ImageInfo *image_info,
4042  Image *image,ExceptionInfo *exception)
4043 {
4044  const char
4045  *option;
4046 
4047  GeometryInfo
4048  geometry_info;
4049 
4050  MagickStatusType
4051  flags;
4052 
4053  ResolutionType
4054  units;
4055 
4056  /*
4057  Sync image options.
4058  */
4059  assert(image_info != (const ImageInfo *) NULL);
4060  assert(image_info->signature == MagickCoreSignature);
4061  assert(image != (Image *) NULL);
4062  assert(image->signature == MagickCoreSignature);
4063  if (IsEventLogging() != MagickFalse)
4064  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4065  option=GetImageOption(image_info,"background");
4066  if (option != (const char *) NULL)
4067  (void) QueryColorCompliance(option,AllCompliance,&image->background_color,
4068  exception);
4069  option=GetImageOption(image_info,"black-point-compensation");
4070  if (option != (const char *) NULL)
4071  image->black_point_compensation=(MagickBooleanType) ParseCommandOption(
4072  MagickBooleanOptions,MagickFalse,option);
4073  option=GetImageOption(image_info,"blue-primary");
4074  if (option != (const char *) NULL)
4075  {
4076  flags=ParseGeometry(option,&geometry_info);
4077  if ((flags & RhoValue) != 0)
4078  image->chromaticity.blue_primary.x=geometry_info.rho;
4079  image->chromaticity.blue_primary.y=image->chromaticity.blue_primary.x;
4080  if ((flags & SigmaValue) != 0)
4081  image->chromaticity.blue_primary.y=geometry_info.sigma;
4082  }
4083  option=GetImageOption(image_info,"bordercolor");
4084  if (option != (const char *) NULL)
4085  (void) QueryColorCompliance(option,AllCompliance,&image->border_color,
4086  exception);
4087  /* FUTURE: do not sync compose to per-image compose setting here */
4088  option=GetImageOption(image_info,"compose");
4089  if (option != (const char *) NULL)
4090  image->compose=(CompositeOperator) ParseCommandOption(MagickComposeOptions,
4091  MagickFalse,option);
4092  /* -- */
4093  option=GetImageOption(image_info,"compress");
4094  if (option != (const char *) NULL)
4095  image->compression=(CompressionType) ParseCommandOption(
4096  MagickCompressOptions,MagickFalse,option);
4097  option=GetImageOption(image_info,"debug");
4098  if (option != (const char *) NULL)
4099  image->debug=(MagickBooleanType) ParseCommandOption(MagickBooleanOptions,
4100  MagickFalse,option);
4101  option=GetImageOption(image_info,"density");
4102  if (option != (const char *) NULL)
4103  {
4104  flags=ParseGeometry(option,&geometry_info);
4105  if ((flags & RhoValue) != 0)
4106  image->resolution.x=geometry_info.rho;
4107  image->resolution.y=image->resolution.x;
4108  if ((flags & SigmaValue) != 0)
4109  image->resolution.y=geometry_info.sigma;
4110  }
4111  option=GetImageOption(image_info,"depth");
4112  if (option != (const char *) NULL)
4113  image->depth=StringToUnsignedLong(option);
4114  option=GetImageOption(image_info,"endian");
4115  if (option != (const char *) NULL)
4116  image->endian=(EndianType) ParseCommandOption(MagickEndianOptions,
4117  MagickFalse,option);
4118  option=GetImageOption(image_info,"filter");
4119  if (option != (const char *) NULL)
4120  image->filter=(FilterType) ParseCommandOption(MagickFilterOptions,
4121  MagickFalse,option);
4122  option=GetImageOption(image_info,"fuzz");
4123  if (option != (const char *) NULL)
4124  image->fuzz=StringToDoubleInterval(option,(double) QuantumRange+1.0);
4125  option=GetImageOption(image_info,"gravity");
4126  if (option != (const char *) NULL)
4127  image->gravity=(GravityType) ParseCommandOption(MagickGravityOptions,
4128  MagickFalse,option);
4129  option=GetImageOption(image_info,"green-primary");
4130  if (option != (const char *) NULL)
4131  {
4132  flags=ParseGeometry(option,&geometry_info);
4133  if ((flags & RhoValue) != 0)
4134  image->chromaticity.green_primary.x=geometry_info.rho;
4135  image->chromaticity.green_primary.y=image->chromaticity.green_primary.x;
4136  if ((flags & SigmaValue) != 0)
4137  image->chromaticity.green_primary.y=geometry_info.sigma;
4138  }
4139  option=GetImageOption(image_info,"intent");
4140  if (option != (const char *) NULL)
4141  image->rendering_intent=(RenderingIntent) ParseCommandOption(
4142  MagickIntentOptions,MagickFalse,option);
4143  option=GetImageOption(image_info,"intensity");
4144  if (option != (const char *) NULL)
4145  image->intensity=(PixelIntensityMethod) ParseCommandOption(
4146  MagickPixelIntensityOptions,MagickFalse,option);
4147  option=GetImageOption(image_info,"interlace");
4148  if (option != (const char *) NULL)
4149  image->interlace=(InterlaceType) ParseCommandOption(MagickInterlaceOptions,
4150  MagickFalse,option);
4151  option=GetImageOption(image_info,"interpolate");
4152  if (option != (const char *) NULL)
4153  image->interpolate=(PixelInterpolateMethod) ParseCommandOption(
4154  MagickInterpolateOptions,MagickFalse,option);
4155  option=GetImageOption(image_info,"loop");
4156  if (option != (const char *) NULL)
4157  image->iterations=StringToUnsignedLong(option);
4158  option=GetImageOption(image_info,"mattecolor");
4159  if (option != (const char *) NULL)
4160  (void) QueryColorCompliance(option,AllCompliance,&image->matte_color,
4161  exception);
4162  option=GetImageOption(image_info,"orient");
4163  if (option != (const char *) NULL)
4164  image->orientation=(OrientationType) ParseCommandOption(
4165  MagickOrientationOptions,MagickFalse,option);
4166  option=GetImageOption(image_info,"page");
4167  if (option != (const char *) NULL)
4168  {
4169  char
4170  *geometry;
4171 
4172  geometry=GetPageGeometry(option);
4173  flags=ParseAbsoluteGeometry(geometry,&image->page);
4174  geometry=DestroyString(geometry);
4175  }
4176  option=GetImageOption(image_info,"quality");
4177  if (option != (const char *) NULL)
4178  image->quality=StringToUnsignedLong(option);
4179  option=GetImageOption(image_info,"red-primary");
4180  if (option != (const char *) NULL)
4181  {
4182  flags=ParseGeometry(option,&geometry_info);
4183  if ((flags & RhoValue) != 0)
4184  image->chromaticity.red_primary.x=geometry_info.rho;
4185  image->chromaticity.red_primary.y=image->chromaticity.red_primary.x;
4186  if ((flags & SigmaValue) != 0)
4187  image->chromaticity.red_primary.y=geometry_info.sigma;
4188  }
4189  if (image_info->quality != UndefinedCompressionQuality)
4190  image->quality=image_info->quality;
4191  option=GetImageOption(image_info,"scene");
4192  if (option != (const char *) NULL)
4193  image->scene=StringToUnsignedLong(option);
4194  option=GetImageOption(image_info,"taint");
4195  if (option != (const char *) NULL)
4196  image->taint=(MagickBooleanType) ParseCommandOption(MagickBooleanOptions,
4197  MagickFalse,option);
4198  option=GetImageOption(image_info,"tile-offset");
4199  if (option != (const char *) NULL)
4200  {
4201  char
4202  *geometry;
4203 
4204  geometry=GetPageGeometry(option);
4205  flags=ParseAbsoluteGeometry(geometry,&image->tile_offset);
4206  geometry=DestroyString(geometry);
4207  }
4208  option=GetImageOption(image_info,"transparent-color");
4209  if (option != (const char *) NULL)
4210  (void) QueryColorCompliance(option,AllCompliance,&image->transparent_color,
4211  exception);
4212  option=GetImageOption(image_info,"type");
4213  if (option != (const char *) NULL)
4214  image->type=(ImageType) ParseCommandOption(MagickTypeOptions,MagickFalse,
4215  option);
4216  option=GetImageOption(image_info,"units");
4217  units=image_info->units;
4218  if (option != (const char *) NULL)
4219  units=(ResolutionType) ParseCommandOption(MagickResolutionOptions,
4220  MagickFalse,option);
4221  if (units != UndefinedResolution)
4222  {
4223  if (image->units != units)
4224  switch (image->units)
4225  {
4226  case PixelsPerInchResolution:
4227  {
4228  if (units == PixelsPerCentimeterResolution)
4229  {
4230  image->resolution.x/=2.54;
4231  image->resolution.y/=2.54;
4232  }
4233  break;
4234  }
4235  case PixelsPerCentimeterResolution:
4236  {
4237  if (units == PixelsPerInchResolution)
4238  {
4239  image->resolution.x=(double) ((size_t) (100.0*2.54*
4240  image->resolution.x+0.5))/100.0;
4241  image->resolution.y=(double) ((size_t) (100.0*2.54*
4242  image->resolution.y+0.5))/100.0;
4243  }
4244  break;
4245  }
4246  default:
4247  break;
4248  }
4249  image->units=units;
4250  option=GetImageOption(image_info,"density");
4251  if (option != (const char *) NULL)
4252  {
4253  flags=ParseGeometry(option,&geometry_info);
4254  if ((flags & RhoValue) != 0)
4255  image->resolution.x=geometry_info.rho;
4256  image->resolution.y=image->resolution.x;
4257  if ((flags & SigmaValue) != 0)
4258  image->resolution.y=geometry_info.sigma;
4259  }
4260  }
4261  option=GetImageOption(image_info,"virtual-pixel");
4262  if (option != (const char *) NULL)
4263  (void) SetImageVirtualPixelMethod(image,(VirtualPixelMethod)
4264  ParseCommandOption(MagickVirtualPixelOptions,MagickFalse,option),
4265  exception);
4266  option=GetImageOption(image_info,"white-point");
4267  if (option != (const char *) NULL)
4268  {
4269  flags=ParseGeometry(option,&geometry_info);
4270  if ((flags & RhoValue) != 0)
4271  image->chromaticity.white_point.x=geometry_info.rho;
4272  image->chromaticity.white_point.y=image->chromaticity.white_point.x;
4273  if ((flags & SigmaValue) != 0)
4274  image->chromaticity.white_point.y=geometry_info.sigma;
4275  }
4276  /*
4277  Pointer to allow the lookup of pre-image artifact will fallback to a global
4278  option setting/define. This saves a lot of duplication of global options
4279  into per-image artifacts, while ensuring only specifically set per-image
4280  artifacts are preserved when parenthesis ends.
4281  */
4282  if (image->image_info != (ImageInfo *) NULL)
4283  image->image_info=DestroyImageInfo(image->image_info);
4284  image->image_info=CloneImageInfo(image_info);
4285  return(MagickTrue);
4286 }
_RectangleInfo
Definition: geometry.h:129
_MagickInfo
Definition: magick.h:66
_GeometryInfo
Definition: geometry.h:105
_CacheView
Definition: cache-view.c:65
_BlobInfo
Definition: blob.c:135
SemaphoreInfo
Definition: semaphore.c:60
_Image
Definition: image.h:131
_PixelInfo
Definition: pixel.h:181
_ImageInfo
Definition: image.h:358
_CustomStreamInfo
Definition: blob.c:198
_OffsetInfo
Definition: geometry.h:115
_Ascii85Info
Definition: compress.c:69
_ExceptionInfo
Definition: exception.h:101
_DelegateInfo
Definition: delegate.h:28
_MagicInfo
Definition: magic.c:89
_StringInfo
Definition: string_.h:27