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