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