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