blob: a96af7a2aac0cf8d4e7db9fb9ff5d9d850d058d4 [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 {
cristyce70c172010-01-07 17:15:30 +0000592 SetRedPixelComponent(q,GetRedPixelComponent(p));
593 SetGreenPixelComponent(q,GetGreenPixelComponent(p));
594 SetBluePixelComponent(q,GetBluePixelComponent(p));
595 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +0000596 if (image->matte != MagickFalse)
cristyce70c172010-01-07 17:15:30 +0000597 SetOpacityPixelComponent(q,GetOpacityPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +0000598 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 {
cristyce70c172010-01-07 17:15:30 +00001138 SetRedPixelComponent(q,PixelIntensityToQuantum(p));
cristy3ed852e2009-09-05 21:47:34 +00001139 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 {
cristyce70c172010-01-07 17:15:30 +00001154 SetGreenPixelComponent(q,PixelIntensityToQuantum(p));
cristy3ed852e2009-09-05 21:47:34 +00001155 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 {
cristyce70c172010-01-07 17:15:30 +00001170 SetBluePixelComponent(q,PixelIntensityToQuantum(p));
cristy3ed852e2009-09-05 21:47:34 +00001171 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 {
cristyce70c172010-01-07 17:15:30 +00001186 SetOpacityPixelComponent(q,PixelIntensityToQuantum(p));
cristy3ed852e2009-09-05 21:47:34 +00001187 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;
cristyf84a1932010-01-03 18:00:18 +00001270 LockSemaphoreInfo(image->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001271 image->reference_count--;
1272 if (image->reference_count == 0)
1273 destroy=MagickTrue;
cristyf84a1932010-01-03 18:00:18 +00001274 UnlockSemaphoreInfo(image->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001275 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);
cristyf84a1932010-01-03 18:00:18 +00001659 LockSemaphoreInfo(image->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001660 reference_count=image->reference_count;
cristyf84a1932010-01-03 18:00:18 +00001661 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);
cristyf84a1932010-01-03 18:00:18 +00002098 LockSemaphoreInfo((*image)->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00002099 (*image)->reference_count--;
cristyf84a1932010-01-03 18:00:18 +00002100 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);
cristy48974b92009-12-19 02:36:06 +00002170#if defined(MAGICKCORE_OPENMP_SUPPORT)
2171 #pragma omp parallel for schedule(dynamic,4) shared(status)
2172#endif
cristy3ed852e2009-09-05 21:47:34 +00002173 for (y=0; y < (long) image->rows; y++)
2174 {
2175 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00002176 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00002177
2178 register long
2179 x;
2180
2181 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002182 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002183
cristy48974b92009-12-19 02:36:06 +00002184 if (status == MagickFalse)
2185 continue;
cristy3ed852e2009-09-05 21:47:34 +00002186 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2187 if (q == (PixelPacket *) NULL)
2188 {
2189 status=MagickFalse;
2190 continue;
2191 }
2192 indexes=GetCacheViewAuthenticIndexQueue(image_view);
2193 for (x=0; x < (long) image->columns; x++)
2194 {
2195 SetPixelPacket(image,background,q,indexes+x);
2196 q++;
2197 }
2198 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2199 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00002200 }
2201 image_view=DestroyCacheView(image_view);
2202 if (status == MagickFalse)
2203 image=DestroyImage(image);
2204 return(image);
2205}
2206
2207/*
2208%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2209% %
2210% %
2211% %
2212% R e f e r e n c e I m a g e %
2213% %
2214% %
2215% %
2216%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2217%
2218% ReferenceImage() increments the reference count associated with an image
2219% returning a pointer to the image.
2220%
2221% The format of the ReferenceImage method is:
2222%
2223% Image *ReferenceImage(Image *image)
2224%
2225% A description of each parameter follows:
2226%
2227% o image: the image.
2228%
2229*/
2230MagickExport Image *ReferenceImage(Image *image)
2231{
2232 assert(image != (Image *) NULL);
2233 if (image->debug != MagickFalse)
2234 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2235 assert(image->signature == MagickSignature);
cristyf84a1932010-01-03 18:00:18 +00002236 LockSemaphoreInfo(image->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00002237 image->reference_count++;
cristyf84a1932010-01-03 18:00:18 +00002238 UnlockSemaphoreInfo(image->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00002239 return(image);
2240}
2241
2242/*
2243%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2244% %
2245% %
2246% %
2247% R e s e t I m a g e P a g e %
2248% %
2249% %
2250% %
2251%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2252%
2253% ResetImagePage() resets the image page canvas and position.
2254%
2255% The format of the ResetImagePage method is:
2256%
2257% MagickBooleanType ResetImagePage(Image *image,const char *page)
2258%
2259% A description of each parameter follows:
2260%
2261% o image: the image.
2262%
2263% o page: the relative page specification.
2264%
2265*/
2266MagickExport MagickBooleanType ResetImagePage(Image *image,const char *page)
2267{
2268 MagickStatusType
2269 flags;
2270
2271 RectangleInfo
2272 geometry;
2273
2274 assert(image != (Image *) NULL);
2275 assert(image->signature == MagickSignature);
2276 if (image->debug != MagickFalse)
2277 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2278 flags=ParseAbsoluteGeometry(page,&geometry);
2279 if ((flags & WidthValue) != 0)
2280 {
2281 if ((flags & HeightValue) == 0)
2282 geometry.height=geometry.width;
2283 image->page.width=geometry.width;
2284 image->page.height=geometry.height;
2285 }
2286 if ((flags & AspectValue) != 0)
2287 {
2288 if ((flags & XValue) != 0)
2289 image->page.x+=geometry.x;
2290 if ((flags & YValue) != 0)
2291 image->page.y+=geometry.y;
2292 }
2293 else
2294 {
2295 if ((flags & XValue) != 0)
2296 {
2297 image->page.x=geometry.x;
2298 if ((image->page.width == 0) && (geometry.x > 0))
2299 image->page.width=image->columns+geometry.x;
2300 }
2301 if ((flags & YValue) != 0)
2302 {
2303 image->page.y=geometry.y;
2304 if ((image->page.height == 0) && (geometry.y > 0))
2305 image->page.height=image->rows+geometry.y;
2306 }
2307 }
2308 return(MagickTrue);
2309}
2310
2311/*
2312%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2313% %
2314% %
2315% %
2316% S e p a r a t e I m a g e C h a n n e l %
2317% %
2318% %
2319% %
2320%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2321%
2322% SeparateImageChannel() separates a channel from the image and returns it as
2323% a grayscale image. A channel is a particular color component of each pixel
2324% in the image.
2325%
2326% The format of the SeparateImageChannel method is:
2327%
2328% MagickBooleanType SeparateImageChannel(Image *image,
2329% const ChannelType channel)
2330%
2331% A description of each parameter follows:
2332%
2333% o image: the image.
2334%
2335% o channel: Identify which channel to extract: RedChannel, GreenChannel,
2336% BlueChannel, OpacityChannel, CyanChannel, MagentaChannel,
2337% YellowChannel, or BlackChannel.
2338%
2339*/
2340MagickExport MagickBooleanType SeparateImageChannel(Image *image,
2341 const ChannelType channel)
2342{
2343#define SeparateImageTag "Separate/Image"
2344
2345 CacheView
2346 *image_view;
2347
2348 ExceptionInfo
2349 *exception;
2350
2351 long
2352 progress,
2353 y;
2354
2355 MagickBooleanType
2356 status;
2357
2358 assert(image != (Image *) NULL);
2359 assert(image->signature == MagickSignature);
2360 if (image->debug != MagickFalse)
2361 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2362 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2363 return(MagickFalse);
2364 /*
2365 Separate image channels.
2366 */
2367 status=MagickTrue;
2368 if ( channel == GrayChannels )
2369 image->matte=MagickTrue;
2370 progress=0;
2371 exception=(&image->exception);
2372 image_view=AcquireCacheView(image);
cristyb5d5f722009-11-04 03:03:49 +00002373#if defined(MAGICKCORE_OPENMP_SUPPORT)
2374 #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
cristy3ed852e2009-09-05 21:47:34 +00002375#endif
2376 for (y=0; y < (long) image->rows; y++)
2377 {
2378 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00002379 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00002380
2381 register long
2382 x;
2383
2384 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002385 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002386
2387 if (status == MagickFalse)
2388 continue;
2389 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2390 if (q == (PixelPacket *) NULL)
2391 {
2392 status=MagickFalse;
2393 continue;
2394 }
2395 indexes=GetCacheViewAuthenticIndexQueue(image_view);
2396 switch (channel)
2397 {
2398 case RedChannel:
2399 {
2400 for (x=0; x < (long) image->columns; x++)
2401 {
2402 q->green=q->red;
2403 q->blue=q->red;
2404 q++;
2405 }
2406 break;
2407 }
2408 case GreenChannel:
2409 {
2410 for (x=0; x < (long) image->columns; x++)
2411 {
2412 q->red=q->green;
2413 q->blue=q->green;
2414 q++;
2415 }
2416 break;
2417 }
2418 case BlueChannel:
2419 {
2420 for (x=0; x < (long) image->columns; x++)
2421 {
2422 q->red=q->blue;
2423 q->green=q->blue;
2424 q++;
2425 }
2426 break;
2427 }
2428 case OpacityChannel:
2429 {
2430 for (x=0; x < (long) image->columns; x++)
2431 {
2432 q->red=q->opacity;
2433 q->green=q->opacity;
2434 q->blue=q->opacity;
2435 q++;
2436 }
2437 break;
2438 }
2439 case BlackChannel:
2440 {
2441 if ((image->storage_class != PseudoClass) &&
2442 (image->colorspace != CMYKColorspace))
2443 break;
2444 for (x=0; x < (long) image->columns; x++)
2445 {
2446 q->red=indexes[x];
2447 q->green=indexes[x];
2448 q->blue=indexes[x];
2449 q++;
2450 }
2451 break;
2452 }
2453 case TrueAlphaChannel:
2454 {
2455 for (x=0; x < (long) image->columns; x++)
2456 {
cristy46f08202010-01-10 04:04:21 +00002457 q->red=(Quantum) GetAlphaPixelComponent(q);
2458 q->green=(Quantum) GetAlphaPixelComponent(q);
2459 q->blue=(Quantum) GetAlphaPixelComponent(q);
cristy3ed852e2009-09-05 21:47:34 +00002460 q++;
2461 }
2462 break;
2463 }
2464 case GrayChannels:
2465 {
2466 for (x=0; x < (long) image->columns; x++)
2467 {
2468 q->opacity=(Quantum) (QuantumRange-PixelIntensityToQuantum(q));
2469 q++;
2470 }
2471 break;
2472 }
2473 default:
2474 break;
2475 }
2476 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2477 status=MagickFalse;
2478 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2479 {
2480 MagickBooleanType
2481 proceed;
2482
cristyb5d5f722009-11-04 03:03:49 +00002483#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00002484 #pragma omp critical (MagickCore_SeparateImageChannel)
2485#endif
2486 proceed=SetImageProgress(image,SeparateImageTag,progress++,image->rows);
2487 if (proceed == MagickFalse)
2488 status=MagickFalse;
2489 }
2490 }
2491 image_view=DestroyCacheView(image_view);
2492 if ( channel != GrayChannels )
2493 image->matte=MagickFalse;
2494 (void) SetImageColorspace(image,RGBColorspace);
2495 return(status);
2496}
2497
2498/*
2499%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2500% %
2501% %
2502% %
2503% S e p a r a t e I m a g e s %
2504% %
2505% %
2506% %
2507%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2508%
2509% SeparateImages() returns a separate grayscale image for each channel
2510% specified.
2511%
2512% The format of the SeparateImages method is:
2513%
2514% MagickBooleanType SeparateImages(const Image *image,
2515% const ChannelType channel,ExceptionInfo *exception)
2516%
2517% A description of each parameter follows:
2518%
2519% o image: the image.
2520%
2521% o channel: Identify which channels to extract: RedChannel, GreenChannel,
2522% BlueChannel, OpacityChannel, CyanChannel, MagentaChannel,
2523% YellowChannel, or BlackChannel.
2524%
2525% o exception: return any errors or warnings in this structure.
2526%
2527*/
2528MagickExport Image *SeparateImages(const Image *image,const ChannelType channel,
2529 ExceptionInfo *exception)
2530{
2531 Image
2532 *images,
2533 *separate_image;
2534
2535 assert(image != (Image *) NULL);
2536 assert(image->signature == MagickSignature);
2537 if (image->debug != MagickFalse)
2538 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2539 images=NewImageList();
2540 if ((channel & RedChannel) != 0)
2541 {
2542 separate_image=CloneImage(image,0,0,MagickTrue,exception);
2543 (void) SeparateImageChannel(separate_image,RedChannel);
2544 AppendImageToList(&images,separate_image);
2545 }
2546 if ((channel & GreenChannel) != 0)
2547 {
2548 separate_image=CloneImage(image,0,0,MagickTrue,exception);
2549 (void) SeparateImageChannel(separate_image,GreenChannel);
2550 AppendImageToList(&images,separate_image);
2551 }
2552 if ((channel & BlueChannel) != 0)
2553 {
2554 separate_image=CloneImage(image,0,0,MagickTrue,exception);
2555 (void) SeparateImageChannel(separate_image,BlueChannel);
2556 AppendImageToList(&images,separate_image);
2557 }
2558 if (((channel & BlackChannel) != 0) && (image->colorspace == CMYKColorspace))
2559 {
2560 separate_image=CloneImage(image,0,0,MagickTrue,exception);
2561 (void) SeparateImageChannel(separate_image,BlackChannel);
2562 AppendImageToList(&images,separate_image);
2563 }
2564 if ((channel & OpacityChannel) != 0)
2565 {
2566 separate_image=CloneImage(image,0,0,MagickTrue,exception);
2567 (void) SeparateImageChannel(separate_image,OpacityChannel);
2568 AppendImageToList(&images,separate_image);
2569 }
2570 return(images);
2571}
2572
2573/*
2574%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2575% %
2576% %
2577% %
2578% S e t I m a g e A l p h a C h a n n e l %
2579% %
2580% %
2581% %
2582%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2583%
2584% SetImageAlphaChannel() activates, deactivates, resets, or sets the alpha
2585% channel.
2586%
2587% The format of the SetImageAlphaChannel method is:
2588%
2589% MagickBooleanType SetImageAlphaChannel(Image *image,
2590% const AlphaChannelType alpha_type)
2591%
2592% A description of each parameter follows:
2593%
2594% o image: the image.
2595%
2596% o alpha_type: The alpha channel type: ActivateAlphaChannel,
2597% CopyAlphaChannel, DeactivateAlphaChannel, ExtractAlphaChannel,
2598% OpaqueAlphaChannel, ResetAlphaChannel, SetAlphaChannel,
2599% ShapeAlphaChannel, and TransparentAlphaChannel.
2600%
2601*/
2602MagickExport MagickBooleanType SetImageAlphaChannel(Image *image,
2603 const AlphaChannelType alpha_type)
2604{
2605 MagickBooleanType
2606 status;
2607
2608 assert(image != (Image *) NULL);
2609 if (image->debug != MagickFalse)
2610 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2611 assert(image->signature == MagickSignature);
2612 status=MagickFalse;
2613 switch (alpha_type)
2614 {
2615 case ActivateAlphaChannel:
2616 {
2617 image->matte=MagickTrue;
2618 break;
2619 }
2620 case BackgroundAlphaChannel:
2621 {
2622 CacheView
2623 *image_view;
2624
2625 ExceptionInfo
2626 *exception;
2627
2628 IndexPacket
2629 index;
2630
2631 long
2632 y;
2633
2634 MagickBooleanType
2635 status;
2636
2637 MagickPixelPacket
2638 background;
2639
2640 PixelPacket
2641 pixel;
2642
2643 /*
2644 Set transparent pixels to background color.
2645 */
2646 if (image->matte == MagickFalse)
2647 break;
2648 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2649 break;
2650 GetMagickPixelPacket(image,&background);
2651 SetMagickPixelPacket(image,&image->background_color,(const IndexPacket *)
2652 NULL,&background);
2653 if (image->colorspace == CMYKColorspace)
2654 ConvertRGBToCMYK(&background);
2655 index=0;
2656 SetPixelPacket(image,&background,&pixel,&index);
2657 status=MagickTrue;
2658 exception=(&image->exception);
2659 image_view=AcquireCacheView(image);
cristyb5d5f722009-11-04 03:03:49 +00002660 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2661 #pragma omp parallel for schedule(dynamic,4) shared(status)
cristy3ed852e2009-09-05 21:47:34 +00002662 #endif
2663 for (y=0; y < (long) image->rows; y++)
2664 {
2665 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00002666 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00002667
2668 register long
2669 x;
2670
2671 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002672 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002673
2674 if (status == MagickFalse)
2675 continue;
2676 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2677 exception);
2678 if (q == (PixelPacket *) NULL)
2679 {
2680 status=MagickFalse;
2681 continue;
2682 }
2683 for (x=0; x < (long) image->columns; x++)
2684 {
2685 if (q->opacity == TransparentOpacity)
2686 {
2687 q->red=pixel.red;
2688 q->green=pixel.green;
2689 q->blue=pixel.blue;
2690 }
2691 q++;
2692 }
2693 if (image->colorspace == CMYKColorspace)
2694 {
2695 indexes=GetCacheViewAuthenticIndexQueue(image_view);
2696 for (x=0; x < (long) image->columns; x++)
2697 indexes[x]=index;
2698 }
2699 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2700 status=MagickFalse;
2701 }
2702 image_view=DestroyCacheView(image_view);
2703 return(status);
2704 }
2705 case DeactivateAlphaChannel:
2706 {
2707 image->matte=MagickFalse;
2708 break;
2709 }
2710 case ShapeAlphaChannel:
2711 case CopyAlphaChannel:
2712 {
2713 /*
2714 Special usage case for SeparateImageChannel(): copy grayscale color to
2715 the alpha channel.
2716 */
2717 status=SeparateImageChannel(image,GrayChannels);
2718 image->matte=MagickTrue; /* make sure transparency is now on! */
2719 if (alpha_type == ShapeAlphaChannel)
2720 {
2721 MagickPixelPacket
2722 background;
2723
2724 /*
2725 Reset all color channels to background color.
2726 */
2727 GetMagickPixelPacket(image,&background);
2728 SetMagickPixelPacket(image,&(image->background_color),(IndexPacket *)
2729 NULL,&background);
cristy308b4e62009-09-21 14:40:44 +00002730 (void) LevelColorsImage(image,&background,&background,MagickTrue);
cristy3ed852e2009-09-05 21:47:34 +00002731 }
2732 break;
2733 }
2734 case ExtractAlphaChannel:
2735 {
2736 status=SeparateImageChannel(image,TrueAlphaChannel);
2737 image->matte=MagickFalse;
2738 break;
2739 }
2740 case ResetAlphaChannel:
2741 case OpaqueAlphaChannel:
2742 {
2743 status=SetImageOpacity(image,OpaqueOpacity);
2744 image->matte=MagickTrue;
2745 break;
2746 }
2747 case TransparentAlphaChannel:
2748 {
2749 status=SetImageOpacity(image,TransparentOpacity);
2750 image->matte=MagickTrue;
2751 break;
2752 }
2753 case SetAlphaChannel:
2754 {
2755 if (image->matte == MagickFalse)
2756 {
2757 status=SetImageOpacity(image,OpaqueOpacity);
2758 image->matte=MagickTrue;
2759 }
2760 break;
2761 }
2762 case UndefinedAlphaChannel:
2763 break;
2764 }
2765 return(status);
2766}
2767
2768/*
2769%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2770% %
2771% %
2772% %
2773% S e t I m a g e B a c k g r o u n d C o l o r %
2774% %
2775% %
2776% %
2777%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2778%
2779% SetImageBackgroundColor() initializes the image pixels to the image
2780% background color. The background color is defined by the background_color
2781% member of the image structure.
2782%
2783% The format of the SetImage method is:
2784%
2785% MagickBooleanType SetImageBackgroundColor(Image *image)
2786%
2787% A description of each parameter follows:
2788%
2789% o image: the image.
2790%
2791*/
2792MagickExport MagickBooleanType SetImageBackgroundColor(Image *image)
2793{
2794 CacheView
2795 *image_view;
2796
2797 ExceptionInfo
2798 *exception;
2799
2800 IndexPacket
2801 index;
2802
2803 long
2804 y;
2805
2806 MagickBooleanType
2807 status;
2808
2809 MagickPixelPacket
2810 background;
2811
2812 PixelPacket
2813 pixel;
2814
2815 assert(image != (Image *) NULL);
2816 if (image->debug != MagickFalse)
2817 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2818 assert(image->signature == MagickSignature);
2819 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2820 return(MagickFalse);
2821 if (image->background_color.opacity != OpaqueOpacity)
2822 image->matte=MagickTrue;
2823 GetMagickPixelPacket(image,&background);
2824 SetMagickPixelPacket(image,&image->background_color,(const IndexPacket *)
2825 NULL,&background);
2826 if (image->colorspace == CMYKColorspace)
2827 ConvertRGBToCMYK(&background);
2828 index=0;
2829 SetPixelPacket(image,&background,&pixel,&index);
2830 /*
2831 Set image background color.
2832 */
2833 status=MagickTrue;
2834 exception=(&image->exception);
2835 image_view=AcquireCacheView(image);
cristyb5d5f722009-11-04 03:03:49 +00002836#if defined(MAGICKCORE_OPENMP_SUPPORT)
2837 #pragma omp parallel for schedule(dynamic,4) shared(status)
cristy3ed852e2009-09-05 21:47:34 +00002838#endif
2839 for (y=0; y < (long) image->rows; y++)
2840 {
2841 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00002842 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00002843
2844 register long
2845 x;
2846
2847 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002848 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002849
2850 if (status == MagickFalse)
2851 continue;
2852 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2853 if (q == (PixelPacket *) NULL)
2854 {
2855 status=MagickFalse;
2856 continue;
2857 }
2858 for (x=0; x < (long) image->columns; x++)
2859 *q++=pixel;
2860 if (image->colorspace == CMYKColorspace)
2861 {
2862 indexes=GetCacheViewAuthenticIndexQueue(image_view);
2863 for (x=0; x < (long) image->columns; x++)
2864 indexes[x]=index;
2865 }
2866 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2867 status=MagickFalse;
2868 }
2869 image_view=DestroyCacheView(image_view);
2870 return(status);
2871}
2872
2873/*
2874%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2875% %
2876% %
2877% %
2878% S e t I m a g e S t o r a g e C l a s s %
2879% %
2880% %
2881% %
2882%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2883%
2884% SetImageStorageClass() sets the image class: DirectClass for true color
2885% images or PseudoClass for colormapped images.
2886%
2887% The format of the SetImageStorageClass method is:
2888%
2889% MagickBooleanType SetImageStorageClass(Image *image,
2890% const ClassType storage_class)
2891%
2892% A description of each parameter follows:
2893%
2894% o image: the image.
2895%
2896% o storage_class: The image class.
2897%
2898*/
2899MagickExport MagickBooleanType SetImageStorageClass(Image *image,
2900 const ClassType storage_class)
2901{
2902 Cache
2903 cache;
2904
2905 if (image->storage_class == storage_class)
2906 return(MagickTrue);
2907 image->storage_class=storage_class;
2908 cache=GetImagePixelCache(image,MagickTrue,&image->exception);
2909 return(cache == (Cache) NULL ? MagickFalse : MagickTrue);
2910}
2911
2912/*
2913%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2914% %
2915% %
2916% %
2917% S e t I m a g e C l i p M a s k %
2918% %
2919% %
2920% %
2921%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2922%
2923% SetImageClipMask() associates a clip path with the image. The clip path
2924% must be the same dimensions as the image. Set any pixel component of
2925% the clip path to TransparentOpacity to prevent that corresponding image
2926% pixel component from being updated when SyncAuthenticPixels() is applied.
2927%
2928% The format of the SetImageClipMask method is:
2929%
2930% MagickBooleanType SetImageClipMask(Image *image,const Image *clip_mask)
2931%
2932% A description of each parameter follows:
2933%
2934% o image: the image.
2935%
2936% o clip_mask: the image clip path.
2937%
2938*/
2939MagickExport MagickBooleanType SetImageClipMask(Image *image,
2940 const Image *clip_mask)
2941{
2942 assert(image != (Image *) NULL);
2943 if (image->debug != MagickFalse)
2944 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2945 assert(image->signature == MagickSignature);
2946 if (clip_mask != (const Image *) NULL)
2947 if ((clip_mask->columns != image->columns) ||
2948 (clip_mask->rows != image->rows))
2949 ThrowBinaryException(ImageError,"ImageSizeDiffers",image->filename);
2950 if (image->clip_mask != (Image *) NULL)
2951 image->clip_mask=DestroyImage(image->clip_mask);
2952 image->clip_mask=NewImageList();
2953 if (clip_mask == (Image *) NULL)
2954 return(MagickTrue);
2955 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2956 return(MagickFalse);
2957 image->clip_mask=CloneImage(clip_mask,0,0,MagickTrue,&image->exception);
2958 if (image->clip_mask == (Image *) NULL)
2959 return(MagickFalse);
2960 return(MagickTrue);
2961}
2962
2963/*
2964%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2965% %
2966% %
2967% %
2968% S e t I m a g e E x t e n t %
2969% %
2970% %
2971% %
2972%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2973%
2974% SetImageExtent() sets the image size (i.e. columns & rows).
2975%
2976% The format of the SetImageExtent method is:
2977%
2978% MagickBooleanType SetImageExtent(Image *image,
2979% const unsigned long columns,const unsigned long rows)
2980%
2981% A description of each parameter follows:
2982%
2983% o image: the image.
2984%
2985% o columns: The image width in pixels.
2986%
2987% o rows: The image height in pixels.
2988%
2989*/
2990MagickExport MagickBooleanType SetImageExtent(Image *image,
2991 const unsigned long columns,const unsigned long rows)
2992{
2993 Cache
2994 cache;
2995
2996 if ((columns != 0) && (rows != 0))
2997 {
2998 image->columns=columns;
2999 image->rows=rows;
3000 }
3001 cache=GetImagePixelCache(image,MagickTrue,&image->exception);
3002 return(cache == (Cache) NULL ? MagickFalse : MagickTrue);
3003}
3004
3005/*
3006%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3007% %
3008% %
3009% %
3010+ S e t I m a g e I n f o %
3011% %
3012% %
3013% %
3014%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3015%
3016% SetImageInfo() initializes the `magick' field of the ImageInfo structure.
3017% It is set to a type of image format based on the prefix or suffix of the
3018% filename. For example, `ps:image' returns PS indicating a Postscript image.
3019% JPEG is returned for this filename: `image.jpg'. The filename prefix has
3020% precendence over the suffix. Use an optional index enclosed in brackets
3021% after a file name to specify a desired scene of a multi-resolution image
3022% format like Photo CD (e.g. img0001.pcd[4]). A True (non-zero) return value
3023% indicates success.
3024%
3025% The format of the SetImageInfo method is:
3026%
3027% MagickBooleanType SetImageInfo(ImageInfo *image_info,
3028% const MagickBooleanType rectify,ExceptionInfo *exception)
3029%
3030% A description of each parameter follows:
3031%
3032% o image_info: the image info..
3033%
3034% o rectify: an unsigned value other than zero rectifies the attribute for
3035% multi-frame support (user may want multi-frame but image format may not
3036% support it).
3037%
3038% o exception: return any errors or warnings in this structure.
3039%
3040*/
3041MagickExport MagickBooleanType SetImageInfo(ImageInfo *image_info,
3042 const MagickBooleanType rectify,ExceptionInfo *exception)
3043{
3044 char
3045 extension[MaxTextExtent],
3046 filename[MaxTextExtent],
3047 magic[MaxTextExtent],
3048 *q,
3049 subimage[MaxTextExtent];
3050
3051 const MagicInfo
3052 *magic_info;
3053
3054 const MagickInfo
3055 *magick_info;
3056
3057 ExceptionInfo
3058 *sans_exception;
3059
3060 Image
3061 *image;
3062
3063 MagickBooleanType
3064 status;
3065
3066 register const char
3067 *p;
3068
3069 ssize_t
3070 count;
3071
3072 unsigned char
3073 magick[2*MaxTextExtent];
3074
3075 /*
3076 Look for 'image.format' in filename.
3077 */
3078 assert(image_info != (ImageInfo *) NULL);
3079 assert(image_info->signature == MagickSignature);
3080 if (image_info->debug != MagickFalse)
3081 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3082 image_info->filename);
3083 *subimage='\0';
3084 GetPathComponent(image_info->filename,SubimagePath,subimage);
3085 if (*subimage != '\0')
3086 {
3087 /*
3088 Look for scene specification (e.g. img0001.pcd[4]).
3089 */
3090 if (IsSceneGeometry(subimage,MagickFalse) == MagickFalse)
3091 {
3092 if (IsGeometry(subimage) != MagickFalse)
3093 (void) CloneString(&image_info->extract,subimage);
3094 }
3095 else
3096 {
3097 unsigned long
3098 first,
3099 last;
3100
3101 (void) CloneString(&image_info->scenes,subimage);
cristye27293e2009-12-18 02:53:20 +00003102 image_info->scene=StringToUnsignedLong(image_info->scenes);
cristy3ed852e2009-09-05 21:47:34 +00003103 image_info->number_scenes=image_info->scene;
3104 p=image_info->scenes;
3105 for (q=(char *) image_info->scenes; *q != '\0'; p++)
3106 {
3107 while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ','))
3108 p++;
3109 first=(unsigned long) strtol(p,&q,10);
3110 last=first;
3111 while (isspace((int) ((unsigned char) *q)) != 0)
3112 q++;
3113 if (*q == '-')
3114 last=(unsigned long) strtol(q+1,&q,10);
3115 if (first > last)
3116 Swap(first,last);
3117 if (first < image_info->scene)
3118 image_info->scene=first;
3119 if (last > image_info->number_scenes)
3120 image_info->number_scenes=last;
3121 p=q;
3122 }
3123 image_info->number_scenes-=image_info->scene-1;
3124 image_info->subimage=image_info->scene;
3125 image_info->subrange=image_info->number_scenes;
3126 }
3127 }
3128 *extension='\0';
3129 GetPathComponent(image_info->filename,ExtensionPath,extension);
3130#if defined(MAGICKCORE_ZLIB_DELEGATE)
3131 if (*extension != '\0')
3132 if ((LocaleCompare(extension,"gz") == 0) ||
3133 (LocaleCompare(extension,"Z") == 0) ||
3134 (LocaleCompare(extension,"wmz") == 0))
3135 {
3136 char
3137 path[MaxTextExtent];
3138
3139 (void) CopyMagickString(path,image_info->filename,MaxTextExtent);
3140 path[strlen(path)-strlen(extension)-1]='\0';
3141 GetPathComponent(path,ExtensionPath,extension);
3142 }
3143#endif
3144#if defined(MAGICKCORE_BZLIB_DELEGATE)
3145 if (*extension != '\0')
3146 if (LocaleCompare(extension,"bz2") == 0)
3147 {
3148 char
3149 path[MaxTextExtent];
3150
3151 (void) CopyMagickString(path,image_info->filename,MaxTextExtent);
3152 path[strlen(path)-strlen(extension)-1]='\0';
3153 GetPathComponent(path,ExtensionPath,extension);
3154 }
3155#endif
3156 image_info->affirm=MagickFalse;
3157 sans_exception=AcquireExceptionInfo();
3158 if (*extension != '\0')
3159 {
3160 MagickFormatType
3161 format_type;
3162
3163 register long
3164 i;
3165
3166 static const char
3167 *format_type_formats[] =
3168 {
3169 "AUTOTRACE",
3170 "BROWSE",
3171 "DCRAW",
3172 "EDIT",
3173 "EPHEMERAL",
3174 "LAUNCH",
3175 "MPEG:DECODE",
3176 "MPEG:ENCODE",
3177 "PRINT",
3178 "PS:ALPHA",
3179 "PS:CMYK",
3180 "PS:COLOR",
3181 "PS:GRAY",
3182 "PS:MONO",
3183 "SCAN",
3184 "SHOW",
3185 "WIN",
3186 (char *) NULL
3187 };
3188
3189 /*
3190 User specified image format.
3191 */
3192 (void) CopyMagickString(magic,extension,MaxTextExtent);
3193 LocaleUpper(magic);
3194 /*
3195 Look for explicit image formats.
3196 */
3197 format_type=UndefinedFormatType;
3198 i=0;
3199 while ((format_type != UndefinedFormatType) &&
3200 (format_type_formats[i] != (char *) NULL))
3201 {
3202 if ((*magic == *format_type_formats[i]) &&
3203 (LocaleCompare(magic,format_type_formats[i]) == 0))
3204 format_type=ExplicitFormatType;
3205 i++;
3206 }
3207 magick_info=GetMagickInfo(magic,sans_exception);
3208 if ((magick_info != (const MagickInfo *) NULL) &&
3209 (magick_info->format_type != UndefinedFormatType))
3210 format_type=magick_info->format_type;
3211 if (format_type == UndefinedFormatType)
3212 (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
3213 else
3214 if (format_type == ExplicitFormatType)
3215 {
3216 image_info->affirm=MagickTrue;
3217 (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
3218 }
3219 if (LocaleCompare(magic,"RGB") == 0)
3220 image_info->affirm=MagickFalse; /* maybe SGI disguised as RGB */
3221 }
3222 /*
3223 Look for explicit 'format:image' in filename.
3224 */
3225 *magic='\0';
3226 GetPathComponent(image_info->filename,MagickPath,magic);
3227 if (*magic == '\0')
3228 (void) CopyMagickString(magic,image_info->magick,MaxTextExtent);
3229 else
3230 {
3231 /*
3232 User specified image format.
3233 */
3234 LocaleUpper(magic);
3235 if (IsMagickConflict(magic) == MagickFalse)
3236 {
3237 (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
3238 if (LocaleCompare(magic,"EPHEMERAL") != 0)
3239 image_info->affirm=MagickTrue;
3240 else
3241 image_info->temporary=MagickTrue;
3242 }
3243 }
3244 magick_info=GetMagickInfo(magic,sans_exception);
3245 sans_exception=DestroyExceptionInfo(sans_exception);
3246 if ((magick_info == (const MagickInfo *) NULL) ||
3247 (GetMagickEndianSupport(magick_info) == MagickFalse))
3248 image_info->endian=UndefinedEndian;
3249 GetPathComponent(image_info->filename,CanonicalPath,filename);
3250 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
3251 if (rectify != MagickFalse)
3252 {
3253 /*
3254 Rectify multi-image file support.
3255 */
3256 (void) InterpretImageFilename(image_info,(Image *) NULL,
3257 image_info->filename,(int) image_info->scene,filename);
3258 if ((LocaleCompare(filename,image_info->filename) != 0) &&
3259 (strchr(filename,'%') == (char *) NULL))
3260 image_info->adjoin=MagickFalse;
3261 magick_info=GetMagickInfo(magic,exception);
3262 if (magick_info != (const MagickInfo *) NULL)
3263 if (GetMagickAdjoin(magick_info) == MagickFalse)
3264 image_info->adjoin=MagickFalse;
3265 return(MagickTrue);
3266 }
3267 if (image_info->affirm != MagickFalse)
3268 return(MagickTrue);
3269 /*
3270 Determine the image format from the first few bytes of the file.
3271 */
3272 image=AcquireImage(image_info);
3273 (void) CopyMagickString(image->filename,image_info->filename,MaxTextExtent);
3274 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
3275 if (status == MagickFalse)
3276 {
3277 image=DestroyImage(image);
3278 return(MagickFalse);
3279 }
3280 if ((IsBlobSeekable(image) == MagickFalse) ||
3281 (IsBlobExempt(image) != MagickFalse))
3282 {
3283 /*
3284 Copy standard input or pipe to temporary file.
3285 */
3286 *filename='\0';
3287 status=ImageToFile(image,filename,exception);
3288 (void) CloseBlob(image);
3289 if (status == MagickFalse)
3290 {
3291 image=DestroyImage(image);
3292 return(MagickFalse);
3293 }
3294 SetImageInfoFile(image_info,(FILE *) NULL);
3295 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
3296 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
3297 if (status == MagickFalse)
3298 {
3299 image=DestroyImage(image);
3300 return(MagickFalse);
3301 }
3302 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
3303 image_info->temporary=MagickTrue;
3304 }
3305 (void) ResetMagickMemory(magick,0,sizeof(magick));
3306 count=ReadBlob(image,2*MaxTextExtent,magick);
3307 (void) CloseBlob(image);
3308 image=DestroyImage(image);
3309 /*
3310 Check magic.xml configuration file.
3311 */
3312 sans_exception=AcquireExceptionInfo();
3313 magic_info=GetMagicInfo(magick,(size_t) count,sans_exception);
3314 if ((magic_info != (const MagicInfo *) NULL) &&
3315 (GetMagicName(magic_info) != (char *) NULL))
3316 {
3317 (void) CopyMagickString(image_info->magick,GetMagicName(magic_info),
3318 MaxTextExtent);
3319 magick_info=GetMagickInfo(image_info->magick,sans_exception);
3320 if ((magick_info == (const MagickInfo *) NULL) ||
3321 (GetMagickEndianSupport(magick_info) == MagickFalse))
3322 image_info->endian=UndefinedEndian;
3323 sans_exception=DestroyExceptionInfo(sans_exception);
3324 return(MagickTrue);
3325 }
3326 magick_info=GetMagickInfo(image_info->magick,sans_exception);
3327 if ((magick_info == (const MagickInfo *) NULL) ||
3328 (GetMagickEndianSupport(magick_info) == MagickFalse))
3329 image_info->endian=UndefinedEndian;
3330 sans_exception=DestroyExceptionInfo(sans_exception);
3331 return(MagickTrue);
3332}
3333
3334/*
3335%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3336% %
3337% %
3338% %
3339% S e t I m a g e I n f o B l o b %
3340% %
3341% %
3342% %
3343%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3344%
3345% SetImageInfoBlob() sets the image info blob member.
3346%
3347% The format of the SetImageInfoBlob method is:
3348%
3349% void SetImageInfoBlob(ImageInfo *image_info,const void *blob,
3350% const size_t length)
3351%
3352% A description of each parameter follows:
3353%
3354% o image_info: the image info.
3355%
3356% o blob: the blob.
3357%
3358% o length: the blob length.
3359%
3360*/
3361MagickExport void SetImageInfoBlob(ImageInfo *image_info,const void *blob,
3362 const size_t length)
3363{
3364 assert(image_info != (ImageInfo *) NULL);
3365 assert(image_info->signature == MagickSignature);
3366 if (image_info->debug != MagickFalse)
3367 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3368 image_info->filename);
3369 image_info->blob=(void *) blob;
3370 image_info->length=length;
3371}
3372
3373/*
3374%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3375% %
3376% %
3377% %
3378% S e t I m a g e I n f o F i l e %
3379% %
3380% %
3381% %
3382%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3383%
3384% SetImageInfoFile() sets the image info file member.
3385%
3386% The format of the SetImageInfoFile method is:
3387%
3388% void SetImageInfoFile(ImageInfo *image_info,FILE *file)
3389%
3390% A description of each parameter follows:
3391%
3392% o image_info: the image info.
3393%
3394% o file: the file.
3395%
3396*/
3397MagickExport void SetImageInfoFile(ImageInfo *image_info,FILE *file)
3398{
3399 assert(image_info != (ImageInfo *) NULL);
3400 assert(image_info->signature == MagickSignature);
3401 if (image_info->debug != MagickFalse)
3402 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3403 image_info->filename);
3404 image_info->file=file;
3405}
3406
3407/*
3408%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3409% %
3410% %
3411% %
3412% S e t I m a g e M a s k %
3413% %
3414% %
3415% %
3416%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3417%
3418% SetImageMask() associates a mask with the image. The mask must be the same
3419% dimensions as the image.
3420%
3421% The format of the SetImageMask method is:
3422%
3423% MagickBooleanType SetImageMask(Image *image,const Image *mask)
3424%
3425% A description of each parameter follows:
3426%
3427% o image: the image.
3428%
3429% o mask: the image mask.
3430%
3431*/
3432MagickExport MagickBooleanType SetImageMask(Image *image,
3433 const Image *mask)
3434{
3435 assert(image != (Image *) NULL);
3436 if (image->debug != MagickFalse)
3437 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3438 assert(image->signature == MagickSignature);
3439 if (mask != (const Image *) NULL)
3440 if ((mask->columns != image->columns) || (mask->rows != image->rows))
3441 ThrowBinaryException(ImageError,"ImageSizeDiffers",image->filename);
3442 if (image->mask != (Image *) NULL)
3443 image->mask=DestroyImage(image->mask);
3444 image->mask=NewImageList();
3445 if (mask == (Image *) NULL)
3446 return(MagickTrue);
3447 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
3448 return(MagickFalse);
3449 image->mask=CloneImage(mask,0,0,MagickTrue,&image->exception);
3450 if (image->mask == (Image *) NULL)
3451 return(MagickFalse);
3452 return(MagickTrue);
3453}
3454
3455/*
3456%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3457% %
3458% %
3459% %
3460% S e t I m a g e O p a c i t y %
3461% %
3462% %
3463% %
3464%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3465%
3466% SetImageOpacity() sets the opacity levels of the image.
3467%
3468% The format of the SetImageOpacity method is:
3469%
3470% MagickBooleanType SetImageOpacity(Image *image,const Quantum opacity)
3471%
3472% A description of each parameter follows:
3473%
3474% o image: the image.
3475%
3476% o opacity: the level of transparency: 0 is fully opaque and QuantumRange is
3477% fully transparent.
3478%
3479*/
3480MagickExport MagickBooleanType SetImageOpacity(Image *image,
3481 const Quantum opacity)
3482{
3483 CacheView
3484 *image_view;
3485
3486 ExceptionInfo
3487 *exception;
3488
3489 long
3490 y;
3491
3492 MagickBooleanType
3493 status;
3494
3495 assert(image != (Image *) NULL);
3496 if (image->debug != MagickFalse)
3497 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3498 assert(image->signature == MagickSignature);
3499 image->matte=opacity != OpaqueOpacity ? MagickTrue : MagickFalse;
3500 status=MagickTrue;
3501 exception=(&image->exception);
3502 image_view=AcquireCacheView(image);
cristyb5d5f722009-11-04 03:03:49 +00003503#if defined(MAGICKCORE_OPENMP_SUPPORT)
3504 #pragma omp parallel for schedule(dynamic,4) shared(status)
cristy3ed852e2009-09-05 21:47:34 +00003505#endif
3506 for (y=0; y < (long) image->rows; y++)
3507 {
3508 register long
3509 x;
3510
3511 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00003512 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00003513
3514 if (status == MagickFalse)
3515 continue;
3516 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3517 if (q == (PixelPacket *) NULL)
3518 {
3519 status=MagickFalse;
3520 continue;
3521 }
3522 for (x=0; x < (long) image->columns; x++)
3523 {
cristy46f08202010-01-10 04:04:21 +00003524 SetOpacityPixelComponent(q,opacity);
cristy3ed852e2009-09-05 21:47:34 +00003525 q++;
3526 }
3527 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3528 status=MagickFalse;
3529 }
3530 image_view=DestroyCacheView(image_view);
3531 return(status);
3532}
3533
3534/*
3535%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3536% %
3537% %
3538% %
3539% S e t I m a g e T y p e %
3540% %
3541% %
3542% %
3543%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3544%
3545% SetImageType() sets the type of image. Choose from these types:
3546%
3547% Bilevel Grayscale GrayscaleMatte
3548% Palette PaletteMatte TrueColor
3549% TrueColorMatte ColorSeparation ColorSeparationMatte
3550% OptimizeType
3551%
3552% The format of the SetImageType method is:
3553%
3554% MagickBooleanType SetImageType(Image *image,const ImageType type)
3555%
3556% A description of each parameter follows:
3557%
3558% o image: the image.
3559%
3560% o type: Image type.
3561%
3562*/
3563MagickExport MagickBooleanType SetImageType(Image *image,const ImageType type)
3564{
3565 const char
3566 *artifact;
3567
3568 ImageInfo
3569 *image_info;
3570
3571 MagickBooleanType
3572 status;
3573
3574 QuantizeInfo
3575 *quantize_info;
3576
3577 assert(image != (Image *) NULL);
3578 if (image->debug != MagickFalse)
3579 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3580 assert(image->signature == MagickSignature);
3581 status=MagickTrue;
3582 image_info=AcquireImageInfo();
3583 image_info->dither=image->dither;
3584 artifact=GetImageArtifact(image,"dither");
3585 if (artifact != (const char *) NULL)
3586 (void) SetImageOption(image_info,"dither",artifact);
3587 switch (type)
3588 {
3589 case BilevelType:
3590 {
3591 if (IsGrayImage(image,&image->exception) == MagickFalse)
3592 status=TransformImageColorspace(image,GRAYColorspace);
3593 if (IsMonochromeImage(image,&image->exception) == MagickFalse)
3594 {
3595 quantize_info=AcquireQuantizeInfo(image_info);
3596 quantize_info->number_colors=2;
3597 quantize_info->colorspace=GRAYColorspace;
3598 status=QuantizeImage(quantize_info,image);
3599 quantize_info=DestroyQuantizeInfo(quantize_info);
3600 }
3601 image->matte=MagickFalse;
3602 break;
3603 }
3604 case GrayscaleType:
3605 {
3606 if (IsGrayImage(image,&image->exception) == MagickFalse)
3607 status=TransformImageColorspace(image,GRAYColorspace);
3608 image->matte=MagickFalse;
3609 break;
3610 }
3611 case GrayscaleMatteType:
3612 {
3613 if (IsGrayImage(image,&image->exception) == MagickFalse)
3614 status=TransformImageColorspace(image,GRAYColorspace);
3615 if (image->matte == MagickFalse)
3616 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
3617 break;
3618 }
3619 case PaletteType:
3620 {
3621 if (image->colorspace != RGBColorspace)
3622 status=TransformImageColorspace(image,RGBColorspace);
3623 if ((image->storage_class == DirectClass) || (image->colors > 256))
3624 {
3625 quantize_info=AcquireQuantizeInfo(image_info);
3626 quantize_info->number_colors=256;
3627 status=QuantizeImage(quantize_info,image);
3628 quantize_info=DestroyQuantizeInfo(quantize_info);
3629 }
3630 image->matte=MagickFalse;
3631 break;
3632 }
3633 case PaletteBilevelMatteType:
3634 {
3635 if (image->colorspace != RGBColorspace)
3636 status=TransformImageColorspace(image,RGBColorspace);
3637 if (image->matte == MagickFalse)
3638 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
3639 (void) BilevelImageChannel(image,AlphaChannel,(double) QuantumRange/2.0);
3640 quantize_info=AcquireQuantizeInfo(image_info);
3641 status=QuantizeImage(quantize_info,image);
3642 quantize_info=DestroyQuantizeInfo(quantize_info);
3643 break;
3644 }
3645 case PaletteMatteType:
3646 {
3647 if (image->colorspace != RGBColorspace)
3648 status=TransformImageColorspace(image,RGBColorspace);
3649 if (image->matte == MagickFalse)
3650 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
3651 quantize_info=AcquireQuantizeInfo(image_info);
3652 quantize_info->colorspace=TransparentColorspace;
3653 status=QuantizeImage(quantize_info,image);
3654 quantize_info=DestroyQuantizeInfo(quantize_info);
3655 break;
3656 }
3657 case TrueColorType:
3658 {
3659 if (image->colorspace != RGBColorspace)
3660 status=TransformImageColorspace(image,RGBColorspace);
3661 if (image->storage_class != DirectClass)
3662 status=SetImageStorageClass(image,DirectClass);
3663 image->matte=MagickFalse;
3664 break;
3665 }
3666 case TrueColorMatteType:
3667 {
3668 if (image->colorspace != RGBColorspace)
3669 status=TransformImageColorspace(image,RGBColorspace);
3670 if (image->storage_class != DirectClass)
3671 status=SetImageStorageClass(image,DirectClass);
3672 if (image->matte == MagickFalse)
3673 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
3674 break;
3675 }
3676 case ColorSeparationType:
3677 {
3678 if (image->colorspace != CMYKColorspace)
3679 {
3680 if (image->colorspace != RGBColorspace)
3681 status=TransformImageColorspace(image,RGBColorspace);
3682 status=TransformImageColorspace(image,CMYKColorspace);
3683 }
3684 if (image->storage_class != DirectClass)
3685 status=SetImageStorageClass(image,DirectClass);
3686 image->matte=MagickFalse;
3687 break;
3688 }
3689 case ColorSeparationMatteType:
3690 {
3691 if (image->colorspace != CMYKColorspace)
3692 {
3693 if (image->colorspace != RGBColorspace)
3694 status=TransformImageColorspace(image,RGBColorspace);
3695 status=TransformImageColorspace(image,CMYKColorspace);
3696 }
3697 if (image->storage_class != DirectClass)
3698 status=SetImageStorageClass(image,DirectClass);
3699 if (image->matte == MagickFalse)
3700 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
3701 break;
3702 }
3703 case OptimizeType:
3704 case UndefinedType:
3705 break;
3706 }
3707 image->type=type;
3708 image_info=DestroyImageInfo(image_info);
3709 return(status);
3710}
3711
3712/*
3713%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3714% %
3715% %
3716% %
3717% 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 %
3718% %
3719% %
3720% %
3721%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3722%
3723% SetImageVirtualPixelMethod() sets the "virtual pixels" method for the
3724% image and returns the previous setting. A virtual pixel is any pixel access
3725% that is outside the boundaries of the image cache.
3726%
3727% The format of the SetImageVirtualPixelMethod() method is:
3728%
3729% VirtualPixelMethod SetImageVirtualPixelMethod(const Image *image,
3730% const VirtualPixelMethod virtual_pixel_method)
3731%
3732% A description of each parameter follows:
3733%
3734% o image: the image.
3735%
3736% o virtual_pixel_method: choose the type of virtual pixel.
3737%
3738*/
3739MagickExport VirtualPixelMethod SetImageVirtualPixelMethod(const Image *image,
3740 const VirtualPixelMethod virtual_pixel_method)
3741{
3742 assert(image != (const Image *) NULL);
3743 assert(image->signature == MagickSignature);
3744 if (image->debug != MagickFalse)
3745 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3746 return(SetPixelCacheVirtualMethod(image,virtual_pixel_method));
3747}
3748
3749/*
3750%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3751% %
3752% %
3753% %
cristy3ed852e2009-09-05 21:47:34 +00003754% S t r i p I m a g e %
3755% %
3756% %
3757% %
3758%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3759%
cristy376bda92009-12-22 21:15:23 +00003760% StripImage() strips an image of all profiles and comments.
cristy3ed852e2009-09-05 21:47:34 +00003761%
3762% The format of the StripImage method is:
3763%
3764% MagickBooleanType StripImage(Image *image)
3765%
3766% A description of each parameter follows:
3767%
3768% o image: the image.
3769%
3770*/
3771MagickExport MagickBooleanType StripImage(Image *image)
3772{
3773 assert(image != (Image *) NULL);
3774 if (image->debug != MagickFalse)
3775 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3776 DestroyImageProfiles(image);
cristy376bda92009-12-22 21:15:23 +00003777 DeleteImageProperty(image,"comment");
cristy3ed852e2009-09-05 21:47:34 +00003778 return(MagickTrue);
3779}
3780
3781/*
3782%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3783% %
3784% %
3785% %
3786+ S y n c I m a g e %
3787% %
3788% %
3789% %
3790%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3791%
3792% SyncImage() initializes the red, green, and blue intensities of each pixel
3793% as defined by the colormap index.
3794%
3795% The format of the SyncImage method is:
3796%
3797% MagickBooleanType SyncImage(Image *image)
3798%
3799% A description of each parameter follows:
3800%
3801% o image: the image.
3802%
3803*/
3804
3805static inline IndexPacket PushColormapIndex(Image *image,
3806 const unsigned long index,MagickBooleanType *range_exception)
3807{
3808 if (index < image->colors)
3809 return((IndexPacket) index);
3810 *range_exception=MagickTrue;
3811 return((IndexPacket) 0);
3812}
3813
3814MagickExport MagickBooleanType SyncImage(Image *image)
3815{
3816 CacheView
3817 *image_view;
3818
3819 ExceptionInfo
3820 *exception;
3821
3822 long
3823 y;
3824
3825 MagickBooleanType
3826 range_exception,
3827 status;
3828
3829 assert(image != (Image *) NULL);
3830 if (image->debug != MagickFalse)
3831 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3832 assert(image->signature == MagickSignature);
3833 if (image->storage_class == DirectClass)
3834 return(MagickFalse);
3835 range_exception=MagickFalse;
3836 status=MagickTrue;
3837 exception=(&image->exception);
3838 image_view=AcquireCacheView(image);
cristy48974b92009-12-19 02:36:06 +00003839#if defined(MAGICKCORE_OPENMP_SUPPORT)
3840 #pragma omp parallel for schedule(dynamic,4) shared(status)
3841#endif
cristy3ed852e2009-09-05 21:47:34 +00003842 for (y=0; y < (long) image->rows; y++)
3843 {
3844 IndexPacket
3845 index;
3846
3847 PixelPacket
3848 pixel;
3849
3850 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00003851 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00003852
3853 register long
3854 x;
3855
3856 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00003857 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00003858
cristy48974b92009-12-19 02:36:06 +00003859 if (status == MagickFalse)
3860 continue;
cristy3ed852e2009-09-05 21:47:34 +00003861 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3862 if (q == (PixelPacket *) NULL)
3863 {
3864 status=MagickFalse;
3865 continue;
3866 }
3867 indexes=GetCacheViewAuthenticIndexQueue(image_view);
3868 for (x=0; x < (long) image->columns; x++)
3869 {
3870 index=PushColormapIndex(image,(unsigned long) indexes[x],
3871 &range_exception);
3872 pixel=image->colormap[(long) index];
3873 q->red=pixel.red;
3874 q->green=pixel.green;
3875 q->blue=pixel.blue;
3876 q++;
3877 }
3878 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3879 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00003880 }
3881 image_view=DestroyCacheView(image_view);
3882 if (range_exception != MagickFalse)
3883 (void) ThrowMagickException(&image->exception,GetMagickModule(),
3884 CorruptImageError,"InvalidColormapIndex","`%s'",image->filename);
3885 return(status);
3886}
cristy1626d332009-11-10 16:58:17 +00003887
3888/*
3889%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3890% %
3891% %
3892% %
3893% S y n c I m a g e S e t t i n g s %
3894% %
3895% %
3896% %
3897%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3898%
3899% SyncImageSettings() sync the image info options to the image.
3900%
3901% The format of the SyncImageSettings method is:
3902%
3903% MagickBooleanType SyncImageSettings(const ImageInfo *image_info,
3904% Image *image)
3905% MagickBooleanType SyncImagesSettings(const ImageInfo *image_info,
3906% Image *image)
3907%
3908% A description of each parameter follows:
3909%
3910% o image_info: the image info.
3911%
3912% o image: the image.
3913%
3914*/
3915
3916MagickExport MagickBooleanType SyncImagesSettings(ImageInfo *image_info,
3917 Image *images)
3918{
3919 Image
3920 *image;
3921
3922 assert(image_info != (const ImageInfo *) NULL);
3923 assert(image_info->signature == MagickSignature);
3924 assert(images != (Image *) NULL);
3925 assert(images->signature == MagickSignature);
3926 if (images->debug != MagickFalse)
3927 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
3928 image=images;
3929 for ( ; image != (Image *) NULL; image=GetNextImageInList(image))
3930 (void) SyncImageSettings(image_info,image);
3931 (void) DeleteImageOption(image_info,"page");
3932 return(MagickTrue);
3933}
3934
3935MagickExport MagickBooleanType SyncImageSettings(const ImageInfo *image_info,
3936 Image *image)
3937{
3938 char
3939 property[MaxTextExtent];
3940
3941 const char
3942 *value,
3943 *option;
3944
3945 GeometryInfo
3946 geometry_info;
3947
3948 MagickStatusType
3949 flags;
3950
3951 /*
3952 Sync image options.
3953 */
3954 assert(image_info != (const ImageInfo *) NULL);
3955 assert(image_info->signature == MagickSignature);
3956 assert(image != (Image *) NULL);
3957 assert(image->signature == MagickSignature);
3958 if (image->debug != MagickFalse)
3959 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3960 option=GetImageOption(image_info,"background");
3961 if (option != (const char *) NULL)
3962 (void) QueryColorDatabase(option,&image->background_color,
3963 &image->exception);
3964 option=GetImageOption(image_info,"bias");
3965 if (option != (const char *) NULL)
cristyf2f27272009-12-17 14:48:46 +00003966 image->bias=SiPrefixToDouble(option,QuantumRange);
cristy1626d332009-11-10 16:58:17 +00003967 option=GetImageOption(image_info,"black-point-compensation");
3968 if (option != (const char *) NULL)
3969 image->black_point_compensation=(MagickBooleanType) ParseMagickOption(
3970 MagickBooleanOptions,MagickFalse,option);
3971 option=GetImageOption(image_info,"blue-primary");
3972 if (option != (const char *) NULL)
3973 {
3974 flags=ParseGeometry(option,&geometry_info);
3975 image->chromaticity.blue_primary.x=geometry_info.rho;
3976 image->chromaticity.blue_primary.y=geometry_info.sigma;
3977 if ((flags & SigmaValue) == 0)
3978 image->chromaticity.blue_primary.y=image->chromaticity.blue_primary.x;
3979 }
3980 option=GetImageOption(image_info,"bordercolor");
3981 if (option != (const char *) NULL)
3982 (void) QueryColorDatabase(option,&image->border_color,&image->exception);
3983 option=GetImageOption(image_info,"colors");
3984 if (option != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00003985 image->colors=StringToUnsignedLong(option);
cristy1626d332009-11-10 16:58:17 +00003986 option=GetImageOption(image_info,"compose");
3987 if (option != (const char *) NULL)
3988 image->compose=(CompositeOperator) ParseMagickOption(MagickComposeOptions,
3989 MagickFalse,option);
3990 option=GetImageOption(image_info,"compress");
3991 if (option != (const char *) NULL)
3992 image->compression=(CompressionType) ParseMagickOption(
3993 MagickCompressOptions,MagickFalse,option);
3994 option=GetImageOption(image_info,"debug");
3995 if (option != (const char *) NULL)
3996 image->debug=(MagickBooleanType) ParseMagickOption(MagickBooleanOptions,
3997 MagickFalse,option);
3998 option=GetImageOption(image_info,"delay");
3999 if (option != (const char *) NULL)
4000 {
4001 GeometryInfo
4002 geometry_info;
4003
4004 flags=ParseGeometry(option,&geometry_info);
4005 if ((flags & GreaterValue) != 0)
4006 {
4007 if (image->delay > (unsigned long) (geometry_info.rho+0.5))
4008 image->delay=(unsigned long) (geometry_info.rho+0.5);
4009 }
4010 else
4011 if ((flags & LessValue) != 0)
4012 {
4013 if (image->delay < (unsigned long) (geometry_info.rho+0.5))
4014 image->ticks_per_second=(long) (geometry_info.sigma+0.5);
4015 }
4016 else
4017 image->delay=(unsigned long) (geometry_info.rho+0.5);
4018 if ((flags & SigmaValue) != 0)
4019 image->ticks_per_second=(long) (geometry_info.sigma+0.5);
4020 }
4021 option=GetImageOption(image_info,"density");
4022 if (option != (const char *) NULL)
4023 {
4024 GeometryInfo
4025 geometry_info;
4026
4027 /*
4028 Set image density.
4029 */
4030 flags=ParseGeometry(option,&geometry_info);
4031 image->x_resolution=geometry_info.rho;
4032 image->y_resolution=geometry_info.sigma;
4033 if ((flags & SigmaValue) == 0)
4034 image->y_resolution=image->x_resolution;
4035 }
4036 option=GetImageOption(image_info,"depth");
4037 if (option != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00004038 image->depth=StringToUnsignedLong(option);
cristy1626d332009-11-10 16:58:17 +00004039 option=GetImageOption(image_info,"dispose");
4040 if (option != (const char *) NULL)
4041 image->dispose=(DisposeType) ParseMagickOption(MagickDisposeOptions,
4042 MagickFalse,option);
4043 option=GetImageOption(image_info,"endian");
4044 if (option != (const char *) NULL)
4045 image->endian=(EndianType) ParseMagickOption(MagickEndianOptions,
4046 MagickFalse,option);
4047 if (image_info->extract != (char *) NULL)
4048 (void) ParseAbsoluteGeometry(image_info->extract,&image->extract_info);
4049 option=GetImageOption(image_info,"filter");
4050 if (option != (const char *) NULL)
4051 image->filter=(FilterTypes) ParseMagickOption(MagickFilterOptions,
4052 MagickFalse,option);
4053 option=GetImageOption(image_info,"fuzz");
4054 if (option != (const char *) NULL)
cristyf2f27272009-12-17 14:48:46 +00004055 image->fuzz=SiPrefixToDouble(option,QuantumRange);
cristy1626d332009-11-10 16:58:17 +00004056 option=GetImageOption(image_info,"gravity");
4057 if (option != (const char *) NULL)
4058 image->gravity=(GravityType) ParseMagickOption(MagickGravityOptions,
4059 MagickFalse,option);
4060 option=GetImageOption(image_info,"green-primary");
4061 if (option != (const char *) NULL)
4062 {
4063 flags=ParseGeometry(option,&geometry_info);
4064 image->chromaticity.green_primary.x=geometry_info.rho;
4065 image->chromaticity.green_primary.y=geometry_info.sigma;
4066 if ((flags & SigmaValue) == 0)
4067 image->chromaticity.green_primary.y=image->chromaticity.green_primary.x;
4068 }
4069 option=GetImageOption(image_info,"intent");
4070 if (option != (const char *) NULL)
4071 image->rendering_intent=(RenderingIntent) ParseMagickOption(
4072 MagickIntentOptions,MagickFalse,option);
4073 option=GetImageOption(image_info,"interlace");
4074 if (option != (const char *) NULL)
4075 image->interlace=(InterlaceType) ParseMagickOption(MagickInterlaceOptions,
4076 MagickFalse,option);
4077 option=GetImageOption(image_info,"interpolate");
4078 if (option != (const char *) NULL)
4079 image->interpolate=(InterpolatePixelMethod) ParseMagickOption(
4080 MagickInterpolateOptions,MagickFalse,option);
4081 option=GetImageOption(image_info,"loop");
4082 if (option != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00004083 image->iterations=StringToUnsignedLong(option);
cristy1626d332009-11-10 16:58:17 +00004084 option=GetImageOption(image_info,"mattecolor");
4085 if (option != (const char *) NULL)
4086 (void) QueryColorDatabase(option,&image->matte_color,&image->exception);
4087 option=GetImageOption(image_info,"orient");
4088 if (option != (const char *) NULL)
4089 image->orientation=(OrientationType) ParseMagickOption(
4090 MagickOrientationOptions,MagickFalse,option);
4091 option=GetImageOption(image_info,"quality");
4092 if (option != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00004093 image->quality=StringToUnsignedLong(option);
cristy1626d332009-11-10 16:58:17 +00004094 option=GetImageOption(image_info,"page");
4095 if (option != (const char *) NULL)
4096 {
4097 char
4098 *geometry;
4099
4100 geometry=GetPageGeometry(option);
4101 flags=ParseAbsoluteGeometry(geometry,&image->page);
4102 geometry=DestroyString(geometry);
4103 }
4104 option=GetImageOption(image_info,"red-primary");
4105 if (option != (const char *) NULL)
4106 {
4107 flags=ParseGeometry(option,&geometry_info);
4108 image->chromaticity.red_primary.x=geometry_info.rho;
4109 image->chromaticity.red_primary.y=geometry_info.sigma;
4110 if ((flags & SigmaValue) == 0)
4111 image->chromaticity.red_primary.y=image->chromaticity.red_primary.x;
4112 }
4113 if (image_info->quality != UndefinedCompressionQuality)
4114 image->quality=image_info->quality;
4115 option=GetImageOption(image_info,"scene");
4116 if (option != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00004117 image->scene=StringToUnsignedLong(option);
cristy1626d332009-11-10 16:58:17 +00004118 option=GetImageOption(image_info,"taint");
4119 if (option != (const char *) NULL)
4120 image->taint=(MagickBooleanType) ParseMagickOption(MagickBooleanOptions,
4121 MagickFalse,option);
4122 option=GetImageOption(image_info,"tile-offset");
4123 if (option != (const char *) NULL)
4124 {
4125 char
4126 *geometry;
4127
4128 geometry=GetPageGeometry(option);
4129 flags=ParseAbsoluteGeometry(geometry,&image->tile_offset);
4130 geometry=DestroyString(geometry);
4131 }
4132 option=GetImageOption(image_info,"transparent-color");
4133 if (option != (const char *) NULL)
4134 (void) QueryColorDatabase(option,&image->transparent_color,
4135 &image->exception);
4136 option=GetImageOption(image_info,"type");
4137 if (option != (const char *) NULL)
4138 image->type=(ImageType) ParseMagickOption(MagickTypeOptions,MagickFalse,
4139 option);
4140 option=GetImageOption(image_info,"units");
4141 if (option != (const char *) NULL)
4142 image->units=(ResolutionType) ParseMagickOption(MagickResolutionOptions,
4143 MagickFalse,option);
4144 if (image_info->units != UndefinedResolution)
4145 {
4146 if (image->units != image_info->units)
4147 switch (image->units)
4148 {
4149 case PixelsPerInchResolution:
4150 {
4151 if (image_info->units == PixelsPerCentimeterResolution)
4152 {
4153 image->x_resolution/=2.54;
4154 image->y_resolution/=2.54;
4155 }
4156 break;
4157 }
4158 case PixelsPerCentimeterResolution:
4159 {
4160 if (image_info->units == PixelsPerInchResolution)
4161 {
4162 image->x_resolution*=2.54;
4163 image->y_resolution*=2.54;
4164 }
4165 break;
4166 }
4167 default:
4168 break;
4169 }
4170 image->units=image_info->units;
4171 }
4172 option=GetImageOption(image_info,"white-point");
4173 if (option != (const char *) NULL)
4174 {
4175 flags=ParseGeometry(option,&geometry_info);
4176 image->chromaticity.white_point.x=geometry_info.rho;
4177 image->chromaticity.white_point.y=geometry_info.sigma;
4178 if ((flags & SigmaValue) == 0)
4179 image->chromaticity.white_point.y=image->chromaticity.white_point.x;
4180 }
4181 ResetImageOptionIterator(image_info);
4182 for (option=GetNextImageOption(image_info); option != (const char *) NULL; )
4183 {
4184 value=GetImageOption(image_info,option);
4185 if (value != (const char *) NULL)
4186 {
4187 (void) FormatMagickString(property,MaxTextExtent,"%s",option);
4188 (void) SetImageArtifact(image,property,value);
4189 }
4190 option=GetNextImageOption(image_info);
4191 }
4192 return(MagickTrue);
4193}