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