blob: 9c6610fba757876cc05940c24c29b4c14199de0d [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);
cristy6b9aca12010-02-21 01:50:11 +0000260 (void) 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;
cristy11b66ce2010-03-11 13:34:19 +00002368 if (channel == GrayChannels)
cristy3ed852e2009-09-05 21:47:34 +00002369 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);
cristy11b66ce2010-03-11 13:34:19 +00002492 if (channel != GrayChannels)
cristy3ed852e2009-09-05 21:47:34 +00002493 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,
cristyd965a422010-03-03 17:47:35 +00003028% const unsigned int frames,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003029%
3030% A description of each parameter follows:
3031%
cristyd965a422010-03-03 17:47:35 +00003032% o image_info: the image info.
cristy3ed852e2009-09-05 21:47:34 +00003033%
cristyd965a422010-03-03 17:47:35 +00003034% o frames: the number of images you intend to write.
cristy3ed852e2009-09-05 21:47:34 +00003035%
3036% o exception: return any errors or warnings in this structure.
3037%
3038*/
3039MagickExport MagickBooleanType SetImageInfo(ImageInfo *image_info,
cristyd965a422010-03-03 17:47:35 +00003040 const unsigned int frames,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003041{
3042 char
3043 extension[MaxTextExtent],
3044 filename[MaxTextExtent],
3045 magic[MaxTextExtent],
3046 *q,
3047 subimage[MaxTextExtent];
3048
3049 const MagicInfo
3050 *magic_info;
3051
3052 const MagickInfo
3053 *magick_info;
3054
3055 ExceptionInfo
3056 *sans_exception;
3057
3058 Image
3059 *image;
3060
3061 MagickBooleanType
3062 status;
3063
3064 register const char
3065 *p;
3066
3067 ssize_t
3068 count;
3069
3070 unsigned char
3071 magick[2*MaxTextExtent];
3072
3073 /*
3074 Look for 'image.format' in filename.
3075 */
3076 assert(image_info != (ImageInfo *) NULL);
3077 assert(image_info->signature == MagickSignature);
3078 if (image_info->debug != MagickFalse)
3079 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3080 image_info->filename);
3081 *subimage='\0';
cristyd965a422010-03-03 17:47:35 +00003082 if (frames == 0)
cristy3ed852e2009-09-05 21:47:34 +00003083 {
cristyd965a422010-03-03 17:47:35 +00003084 GetPathComponent(image_info->filename,SubimagePath,subimage);
3085 if (*subimage != '\0')
cristy3ed852e2009-09-05 21:47:34 +00003086 {
cristyd965a422010-03-03 17:47:35 +00003087 /*
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;
cristy3ed852e2009-09-05 21:47:34 +00003100
cristyd965a422010-03-03 17:47:35 +00003101 (void) CloneString(&image_info->scenes,subimage);
3102 image_info->scene=StringToUnsignedLong(image_info->scenes);
3103 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) ||
3108 (*p == ','))
3109 p++;
3110 first=(unsigned long) strtol(p,&q,10);
3111 last=first;
3112 while (isspace((int) ((unsigned char) *q)) != 0)
3113 q++;
3114 if (*q == '-')
3115 last=(unsigned long) strtol(q+1,&q,10);
3116 if (first > last)
3117 Swap(first,last);
3118 if (first < image_info->scene)
3119 image_info->scene=first;
3120 if (last > image_info->number_scenes)
3121 image_info->number_scenes=last;
3122 p=q;
3123 }
3124 image_info->number_scenes-=image_info->scene-1;
3125 image_info->subimage=image_info->scene;
3126 image_info->subrange=image_info->number_scenes;
3127 }
cristy3ed852e2009-09-05 21:47:34 +00003128 }
3129 }
3130 *extension='\0';
3131 GetPathComponent(image_info->filename,ExtensionPath,extension);
3132#if defined(MAGICKCORE_ZLIB_DELEGATE)
3133 if (*extension != '\0')
3134 if ((LocaleCompare(extension,"gz") == 0) ||
3135 (LocaleCompare(extension,"Z") == 0) ||
3136 (LocaleCompare(extension,"wmz") == 0))
3137 {
3138 char
3139 path[MaxTextExtent];
3140
3141 (void) CopyMagickString(path,image_info->filename,MaxTextExtent);
3142 path[strlen(path)-strlen(extension)-1]='\0';
3143 GetPathComponent(path,ExtensionPath,extension);
3144 }
3145#endif
3146#if defined(MAGICKCORE_BZLIB_DELEGATE)
3147 if (*extension != '\0')
3148 if (LocaleCompare(extension,"bz2") == 0)
3149 {
3150 char
3151 path[MaxTextExtent];
3152
3153 (void) CopyMagickString(path,image_info->filename,MaxTextExtent);
3154 path[strlen(path)-strlen(extension)-1]='\0';
3155 GetPathComponent(path,ExtensionPath,extension);
3156 }
3157#endif
3158 image_info->affirm=MagickFalse;
3159 sans_exception=AcquireExceptionInfo();
3160 if (*extension != '\0')
3161 {
3162 MagickFormatType
3163 format_type;
3164
3165 register long
3166 i;
3167
3168 static const char
3169 *format_type_formats[] =
3170 {
3171 "AUTOTRACE",
3172 "BROWSE",
3173 "DCRAW",
3174 "EDIT",
3175 "EPHEMERAL",
3176 "LAUNCH",
3177 "MPEG:DECODE",
3178 "MPEG:ENCODE",
3179 "PRINT",
3180 "PS:ALPHA",
3181 "PS:CMYK",
3182 "PS:COLOR",
3183 "PS:GRAY",
3184 "PS:MONO",
3185 "SCAN",
3186 "SHOW",
3187 "WIN",
3188 (char *) NULL
3189 };
3190
3191 /*
3192 User specified image format.
3193 */
3194 (void) CopyMagickString(magic,extension,MaxTextExtent);
3195 LocaleUpper(magic);
3196 /*
3197 Look for explicit image formats.
3198 */
3199 format_type=UndefinedFormatType;
3200 i=0;
cristydd9a2532010-02-20 19:26:46 +00003201 while ((format_type == UndefinedFormatType) &&
cristy3ed852e2009-09-05 21:47:34 +00003202 (format_type_formats[i] != (char *) NULL))
3203 {
3204 if ((*magic == *format_type_formats[i]) &&
3205 (LocaleCompare(magic,format_type_formats[i]) == 0))
3206 format_type=ExplicitFormatType;
3207 i++;
3208 }
3209 magick_info=GetMagickInfo(magic,sans_exception);
3210 if ((magick_info != (const MagickInfo *) NULL) &&
3211 (magick_info->format_type != UndefinedFormatType))
3212 format_type=magick_info->format_type;
3213 if (format_type == UndefinedFormatType)
3214 (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
3215 else
3216 if (format_type == ExplicitFormatType)
3217 {
3218 image_info->affirm=MagickTrue;
3219 (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
3220 }
3221 if (LocaleCompare(magic,"RGB") == 0)
3222 image_info->affirm=MagickFalse; /* maybe SGI disguised as RGB */
3223 }
3224 /*
3225 Look for explicit 'format:image' in filename.
3226 */
3227 *magic='\0';
3228 GetPathComponent(image_info->filename,MagickPath,magic);
3229 if (*magic == '\0')
3230 (void) CopyMagickString(magic,image_info->magick,MaxTextExtent);
3231 else
3232 {
3233 /*
3234 User specified image format.
3235 */
3236 LocaleUpper(magic);
3237 if (IsMagickConflict(magic) == MagickFalse)
3238 {
3239 (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
3240 if (LocaleCompare(magic,"EPHEMERAL") != 0)
3241 image_info->affirm=MagickTrue;
3242 else
3243 image_info->temporary=MagickTrue;
3244 }
3245 }
3246 magick_info=GetMagickInfo(magic,sans_exception);
3247 sans_exception=DestroyExceptionInfo(sans_exception);
3248 if ((magick_info == (const MagickInfo *) NULL) ||
3249 (GetMagickEndianSupport(magick_info) == MagickFalse))
3250 image_info->endian=UndefinedEndian;
3251 GetPathComponent(image_info->filename,CanonicalPath,filename);
3252 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
cristyd965a422010-03-03 17:47:35 +00003253 if ((image_info->adjoin != MagickFalse) && (frames > 1))
cristy3ed852e2009-09-05 21:47:34 +00003254 {
3255 /*
cristyd965a422010-03-03 17:47:35 +00003256 Test for multiple image support (e.g. image%02d.png).
cristy3ed852e2009-09-05 21:47:34 +00003257 */
cristyd965a422010-03-03 17:47:35 +00003258 (void) InterpretImageFilename(image_info,(Image *) NULL,
3259 image_info->filename,(int) image_info->scene,filename);
3260 if ((LocaleCompare(filename,image_info->filename) != 0) &&
3261 (strchr(filename,'%') == (char *) NULL))
3262 image_info->adjoin=MagickFalse;
3263 }
3264 if ((image_info->adjoin != MagickFalse) && (frames > 0))
3265 {
3266 /*
3267 Some image formats do not support multiple frames per file.
3268 */
cristy3ed852e2009-09-05 21:47:34 +00003269 magick_info=GetMagickInfo(magic,exception);
3270 if (magick_info != (const MagickInfo *) NULL)
3271 if (GetMagickAdjoin(magick_info) == MagickFalse)
3272 image_info->adjoin=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00003273 }
3274 if (image_info->affirm != MagickFalse)
3275 return(MagickTrue);
cristyd965a422010-03-03 17:47:35 +00003276 if (frames == 0)
cristy3ed852e2009-09-05 21:47:34 +00003277 {
3278 /*
cristyd965a422010-03-03 17:47:35 +00003279 Determine the image format from the first few bytes of the file.
cristy3ed852e2009-09-05 21:47:34 +00003280 */
cristyd965a422010-03-03 17:47:35 +00003281 image=AcquireImage(image_info);
3282 (void) CopyMagickString(image->filename,image_info->filename,
3283 MaxTextExtent);
cristy3ed852e2009-09-05 21:47:34 +00003284 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
3285 if (status == MagickFalse)
3286 {
3287 image=DestroyImage(image);
3288 return(MagickFalse);
3289 }
cristyd965a422010-03-03 17:47:35 +00003290 if ((IsBlobSeekable(image) == MagickFalse) ||
3291 (IsBlobExempt(image) != MagickFalse))
3292 {
3293 /*
3294 Copy standard input or pipe to temporary file.
3295 */
3296 *filename='\0';
3297 status=ImageToFile(image,filename,exception);
3298 (void) CloseBlob(image);
3299 if (status == MagickFalse)
3300 {
3301 image=DestroyImage(image);
3302 return(MagickFalse);
3303 }
3304 SetImageInfoFile(image_info,(FILE *) NULL);
3305 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
3306 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
3307 if (status == MagickFalse)
3308 {
3309 image=DestroyImage(image);
3310 return(MagickFalse);
3311 }
3312 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
3313 image_info->temporary=MagickTrue;
3314 }
3315 (void) ResetMagickMemory(magick,0,sizeof(magick));
3316 count=ReadBlob(image,2*MaxTextExtent,magick);
3317 (void) CloseBlob(image);
3318 image=DestroyImage(image);
3319 /*
3320 Check magic.xml configuration file.
3321 */
3322 sans_exception=AcquireExceptionInfo();
3323 magic_info=GetMagicInfo(magick,(size_t) count,sans_exception);
3324 if ((magic_info != (const MagicInfo *) NULL) &&
3325 (GetMagicName(magic_info) != (char *) NULL))
3326 {
3327 (void) CopyMagickString(image_info->magick,GetMagicName(magic_info),
3328 MaxTextExtent);
3329 magick_info=GetMagickInfo(image_info->magick,sans_exception);
3330 if ((magick_info == (const MagickInfo *) NULL) ||
3331 (GetMagickEndianSupport(magick_info) == MagickFalse))
3332 image_info->endian=UndefinedEndian;
3333 sans_exception=DestroyExceptionInfo(sans_exception);
3334 return(MagickTrue);
3335 }
cristy3ed852e2009-09-05 21:47:34 +00003336 magick_info=GetMagickInfo(image_info->magick,sans_exception);
3337 if ((magick_info == (const MagickInfo *) NULL) ||
3338 (GetMagickEndianSupport(magick_info) == MagickFalse))
3339 image_info->endian=UndefinedEndian;
3340 sans_exception=DestroyExceptionInfo(sans_exception);
cristy3ed852e2009-09-05 21:47:34 +00003341 }
cristy3ed852e2009-09-05 21:47:34 +00003342 return(MagickTrue);
3343}
3344
3345/*
3346%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3347% %
3348% %
3349% %
3350% S e t I m a g e I n f o B l o b %
3351% %
3352% %
3353% %
3354%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3355%
3356% SetImageInfoBlob() sets the image info blob member.
3357%
3358% The format of the SetImageInfoBlob method is:
3359%
3360% void SetImageInfoBlob(ImageInfo *image_info,const void *blob,
3361% const size_t length)
3362%
3363% A description of each parameter follows:
3364%
3365% o image_info: the image info.
3366%
3367% o blob: the blob.
3368%
3369% o length: the blob length.
3370%
3371*/
3372MagickExport void SetImageInfoBlob(ImageInfo *image_info,const void *blob,
3373 const size_t length)
3374{
3375 assert(image_info != (ImageInfo *) NULL);
3376 assert(image_info->signature == MagickSignature);
3377 if (image_info->debug != MagickFalse)
3378 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3379 image_info->filename);
3380 image_info->blob=(void *) blob;
3381 image_info->length=length;
3382}
3383
3384/*
3385%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3386% %
3387% %
3388% %
3389% S e t I m a g e I n f o F i l e %
3390% %
3391% %
3392% %
3393%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3394%
3395% SetImageInfoFile() sets the image info file member.
3396%
3397% The format of the SetImageInfoFile method is:
3398%
3399% void SetImageInfoFile(ImageInfo *image_info,FILE *file)
3400%
3401% A description of each parameter follows:
3402%
3403% o image_info: the image info.
3404%
3405% o file: the file.
3406%
3407*/
3408MagickExport void SetImageInfoFile(ImageInfo *image_info,FILE *file)
3409{
3410 assert(image_info != (ImageInfo *) NULL);
3411 assert(image_info->signature == MagickSignature);
3412 if (image_info->debug != MagickFalse)
3413 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3414 image_info->filename);
3415 image_info->file=file;
3416}
3417
3418/*
3419%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3420% %
3421% %
3422% %
3423% S e t I m a g e M a s k %
3424% %
3425% %
3426% %
3427%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3428%
3429% SetImageMask() associates a mask with the image. The mask must be the same
3430% dimensions as the image.
3431%
3432% The format of the SetImageMask method is:
3433%
3434% MagickBooleanType SetImageMask(Image *image,const Image *mask)
3435%
3436% A description of each parameter follows:
3437%
3438% o image: the image.
3439%
3440% o mask: the image mask.
3441%
3442*/
3443MagickExport MagickBooleanType SetImageMask(Image *image,
3444 const Image *mask)
3445{
3446 assert(image != (Image *) NULL);
3447 if (image->debug != MagickFalse)
3448 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3449 assert(image->signature == MagickSignature);
3450 if (mask != (const Image *) NULL)
3451 if ((mask->columns != image->columns) || (mask->rows != image->rows))
3452 ThrowBinaryException(ImageError,"ImageSizeDiffers",image->filename);
3453 if (image->mask != (Image *) NULL)
3454 image->mask=DestroyImage(image->mask);
3455 image->mask=NewImageList();
3456 if (mask == (Image *) NULL)
3457 return(MagickTrue);
3458 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
3459 return(MagickFalse);
3460 image->mask=CloneImage(mask,0,0,MagickTrue,&image->exception);
3461 if (image->mask == (Image *) NULL)
3462 return(MagickFalse);
3463 return(MagickTrue);
3464}
3465
3466/*
3467%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3468% %
3469% %
3470% %
3471% S e t I m a g e O p a c i t y %
3472% %
3473% %
3474% %
3475%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3476%
3477% SetImageOpacity() sets the opacity levels of the image.
3478%
3479% The format of the SetImageOpacity method is:
3480%
3481% MagickBooleanType SetImageOpacity(Image *image,const Quantum opacity)
3482%
3483% A description of each parameter follows:
3484%
3485% o image: the image.
3486%
3487% o opacity: the level of transparency: 0 is fully opaque and QuantumRange is
3488% fully transparent.
3489%
3490*/
3491MagickExport MagickBooleanType SetImageOpacity(Image *image,
3492 const Quantum opacity)
3493{
3494 CacheView
3495 *image_view;
3496
3497 ExceptionInfo
3498 *exception;
3499
3500 long
3501 y;
3502
3503 MagickBooleanType
3504 status;
3505
3506 assert(image != (Image *) NULL);
3507 if (image->debug != MagickFalse)
3508 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3509 assert(image->signature == MagickSignature);
3510 image->matte=opacity != OpaqueOpacity ? MagickTrue : MagickFalse;
3511 status=MagickTrue;
3512 exception=(&image->exception);
3513 image_view=AcquireCacheView(image);
cristyb5d5f722009-11-04 03:03:49 +00003514#if defined(MAGICKCORE_OPENMP_SUPPORT)
3515 #pragma omp parallel for schedule(dynamic,4) shared(status)
cristy3ed852e2009-09-05 21:47:34 +00003516#endif
3517 for (y=0; y < (long) image->rows; y++)
3518 {
3519 register long
3520 x;
3521
3522 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00003523 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00003524
3525 if (status == MagickFalse)
3526 continue;
3527 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3528 if (q == (PixelPacket *) NULL)
3529 {
3530 status=MagickFalse;
3531 continue;
3532 }
3533 for (x=0; x < (long) image->columns; x++)
3534 {
cristy46f08202010-01-10 04:04:21 +00003535 SetOpacityPixelComponent(q,opacity);
cristy3ed852e2009-09-05 21:47:34 +00003536 q++;
3537 }
3538 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3539 status=MagickFalse;
3540 }
3541 image_view=DestroyCacheView(image_view);
3542 return(status);
3543}
3544
3545/*
3546%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3547% %
3548% %
3549% %
3550% S e t I m a g e T y p e %
3551% %
3552% %
3553% %
3554%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3555%
3556% SetImageType() sets the type of image. Choose from these types:
3557%
3558% Bilevel Grayscale GrayscaleMatte
3559% Palette PaletteMatte TrueColor
3560% TrueColorMatte ColorSeparation ColorSeparationMatte
3561% OptimizeType
3562%
3563% The format of the SetImageType method is:
3564%
3565% MagickBooleanType SetImageType(Image *image,const ImageType type)
3566%
3567% A description of each parameter follows:
3568%
3569% o image: the image.
3570%
3571% o type: Image type.
3572%
3573*/
3574MagickExport MagickBooleanType SetImageType(Image *image,const ImageType type)
3575{
3576 const char
3577 *artifact;
3578
3579 ImageInfo
3580 *image_info;
3581
3582 MagickBooleanType
3583 status;
3584
3585 QuantizeInfo
3586 *quantize_info;
3587
3588 assert(image != (Image *) NULL);
3589 if (image->debug != MagickFalse)
3590 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3591 assert(image->signature == MagickSignature);
3592 status=MagickTrue;
3593 image_info=AcquireImageInfo();
3594 image_info->dither=image->dither;
3595 artifact=GetImageArtifact(image,"dither");
3596 if (artifact != (const char *) NULL)
3597 (void) SetImageOption(image_info,"dither",artifact);
3598 switch (type)
3599 {
3600 case BilevelType:
3601 {
3602 if (IsGrayImage(image,&image->exception) == MagickFalse)
3603 status=TransformImageColorspace(image,GRAYColorspace);
3604 if (IsMonochromeImage(image,&image->exception) == MagickFalse)
3605 {
3606 quantize_info=AcquireQuantizeInfo(image_info);
3607 quantize_info->number_colors=2;
3608 quantize_info->colorspace=GRAYColorspace;
3609 status=QuantizeImage(quantize_info,image);
3610 quantize_info=DestroyQuantizeInfo(quantize_info);
3611 }
3612 image->matte=MagickFalse;
3613 break;
3614 }
3615 case GrayscaleType:
3616 {
3617 if (IsGrayImage(image,&image->exception) == MagickFalse)
3618 status=TransformImageColorspace(image,GRAYColorspace);
3619 image->matte=MagickFalse;
3620 break;
3621 }
3622 case GrayscaleMatteType:
3623 {
3624 if (IsGrayImage(image,&image->exception) == MagickFalse)
3625 status=TransformImageColorspace(image,GRAYColorspace);
3626 if (image->matte == MagickFalse)
3627 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
3628 break;
3629 }
3630 case PaletteType:
3631 {
3632 if (image->colorspace != RGBColorspace)
3633 status=TransformImageColorspace(image,RGBColorspace);
3634 if ((image->storage_class == DirectClass) || (image->colors > 256))
3635 {
3636 quantize_info=AcquireQuantizeInfo(image_info);
3637 quantize_info->number_colors=256;
3638 status=QuantizeImage(quantize_info,image);
3639 quantize_info=DestroyQuantizeInfo(quantize_info);
3640 }
3641 image->matte=MagickFalse;
3642 break;
3643 }
3644 case PaletteBilevelMatteType:
3645 {
3646 if (image->colorspace != RGBColorspace)
3647 status=TransformImageColorspace(image,RGBColorspace);
3648 if (image->matte == MagickFalse)
3649 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
3650 (void) BilevelImageChannel(image,AlphaChannel,(double) QuantumRange/2.0);
3651 quantize_info=AcquireQuantizeInfo(image_info);
3652 status=QuantizeImage(quantize_info,image);
3653 quantize_info=DestroyQuantizeInfo(quantize_info);
3654 break;
3655 }
3656 case PaletteMatteType:
3657 {
3658 if (image->colorspace != RGBColorspace)
3659 status=TransformImageColorspace(image,RGBColorspace);
3660 if (image->matte == MagickFalse)
3661 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
3662 quantize_info=AcquireQuantizeInfo(image_info);
3663 quantize_info->colorspace=TransparentColorspace;
3664 status=QuantizeImage(quantize_info,image);
3665 quantize_info=DestroyQuantizeInfo(quantize_info);
3666 break;
3667 }
3668 case TrueColorType:
3669 {
3670 if (image->colorspace != RGBColorspace)
3671 status=TransformImageColorspace(image,RGBColorspace);
3672 if (image->storage_class != DirectClass)
3673 status=SetImageStorageClass(image,DirectClass);
3674 image->matte=MagickFalse;
3675 break;
3676 }
3677 case TrueColorMatteType:
3678 {
3679 if (image->colorspace != RGBColorspace)
3680 status=TransformImageColorspace(image,RGBColorspace);
3681 if (image->storage_class != DirectClass)
3682 status=SetImageStorageClass(image,DirectClass);
3683 if (image->matte == MagickFalse)
3684 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
3685 break;
3686 }
3687 case ColorSeparationType:
3688 {
3689 if (image->colorspace != CMYKColorspace)
3690 {
3691 if (image->colorspace != RGBColorspace)
3692 status=TransformImageColorspace(image,RGBColorspace);
3693 status=TransformImageColorspace(image,CMYKColorspace);
3694 }
3695 if (image->storage_class != DirectClass)
3696 status=SetImageStorageClass(image,DirectClass);
3697 image->matte=MagickFalse;
3698 break;
3699 }
3700 case ColorSeparationMatteType:
3701 {
3702 if (image->colorspace != CMYKColorspace)
3703 {
3704 if (image->colorspace != RGBColorspace)
3705 status=TransformImageColorspace(image,RGBColorspace);
3706 status=TransformImageColorspace(image,CMYKColorspace);
3707 }
3708 if (image->storage_class != DirectClass)
3709 status=SetImageStorageClass(image,DirectClass);
3710 if (image->matte == MagickFalse)
3711 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
3712 break;
3713 }
3714 case OptimizeType:
3715 case UndefinedType:
3716 break;
3717 }
3718 image->type=type;
3719 image_info=DestroyImageInfo(image_info);
3720 return(status);
3721}
3722
3723/*
3724%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3725% %
3726% %
3727% %
3728% 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 %
3729% %
3730% %
3731% %
3732%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3733%
3734% SetImageVirtualPixelMethod() sets the "virtual pixels" method for the
3735% image and returns the previous setting. A virtual pixel is any pixel access
3736% that is outside the boundaries of the image cache.
3737%
3738% The format of the SetImageVirtualPixelMethod() method is:
3739%
3740% VirtualPixelMethod SetImageVirtualPixelMethod(const Image *image,
3741% const VirtualPixelMethod virtual_pixel_method)
3742%
3743% A description of each parameter follows:
3744%
3745% o image: the image.
3746%
3747% o virtual_pixel_method: choose the type of virtual pixel.
3748%
3749*/
3750MagickExport VirtualPixelMethod SetImageVirtualPixelMethod(const Image *image,
3751 const VirtualPixelMethod virtual_pixel_method)
3752{
3753 assert(image != (const Image *) NULL);
3754 assert(image->signature == MagickSignature);
3755 if (image->debug != MagickFalse)
3756 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3757 return(SetPixelCacheVirtualMethod(image,virtual_pixel_method));
3758}
3759
3760/*
3761%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3762% %
3763% %
3764% %
cristy3ed852e2009-09-05 21:47:34 +00003765% S t r i p I m a g e %
3766% %
3767% %
3768% %
3769%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3770%
cristy376bda92009-12-22 21:15:23 +00003771% StripImage() strips an image of all profiles and comments.
cristy3ed852e2009-09-05 21:47:34 +00003772%
3773% The format of the StripImage method is:
3774%
3775% MagickBooleanType StripImage(Image *image)
3776%
3777% A description of each parameter follows:
3778%
3779% o image: the image.
3780%
3781*/
3782MagickExport MagickBooleanType StripImage(Image *image)
3783{
3784 assert(image != (Image *) NULL);
3785 if (image->debug != MagickFalse)
3786 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3787 DestroyImageProfiles(image);
cristy6b9aca12010-02-21 01:50:11 +00003788 (void) DeleteImageProperty(image,"comment");
cristy3ed852e2009-09-05 21:47:34 +00003789 return(MagickTrue);
3790}
3791
3792/*
3793%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3794% %
3795% %
3796% %
3797+ S y n c I m a g e %
3798% %
3799% %
3800% %
3801%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3802%
3803% SyncImage() initializes the red, green, and blue intensities of each pixel
3804% as defined by the colormap index.
3805%
3806% The format of the SyncImage method is:
3807%
3808% MagickBooleanType SyncImage(Image *image)
3809%
3810% A description of each parameter follows:
3811%
3812% o image: the image.
3813%
3814*/
3815
3816static inline IndexPacket PushColormapIndex(Image *image,
3817 const unsigned long index,MagickBooleanType *range_exception)
3818{
3819 if (index < image->colors)
3820 return((IndexPacket) index);
3821 *range_exception=MagickTrue;
3822 return((IndexPacket) 0);
3823}
3824
3825MagickExport MagickBooleanType SyncImage(Image *image)
3826{
3827 CacheView
3828 *image_view;
3829
3830 ExceptionInfo
3831 *exception;
3832
3833 long
3834 y;
3835
3836 MagickBooleanType
3837 range_exception,
3838 status;
3839
3840 assert(image != (Image *) NULL);
3841 if (image->debug != MagickFalse)
3842 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3843 assert(image->signature == MagickSignature);
3844 if (image->storage_class == DirectClass)
3845 return(MagickFalse);
3846 range_exception=MagickFalse;
3847 status=MagickTrue;
3848 exception=(&image->exception);
3849 image_view=AcquireCacheView(image);
cristy48974b92009-12-19 02:36:06 +00003850#if defined(MAGICKCORE_OPENMP_SUPPORT)
3851 #pragma omp parallel for schedule(dynamic,4) shared(status)
3852#endif
cristy3ed852e2009-09-05 21:47:34 +00003853 for (y=0; y < (long) image->rows; y++)
3854 {
3855 IndexPacket
3856 index;
3857
3858 PixelPacket
3859 pixel;
3860
3861 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00003862 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00003863
3864 register long
3865 x;
3866
3867 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00003868 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00003869
cristy48974b92009-12-19 02:36:06 +00003870 if (status == MagickFalse)
3871 continue;
cristy3ed852e2009-09-05 21:47:34 +00003872 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3873 if (q == (PixelPacket *) NULL)
3874 {
3875 status=MagickFalse;
3876 continue;
3877 }
3878 indexes=GetCacheViewAuthenticIndexQueue(image_view);
3879 for (x=0; x < (long) image->columns; x++)
3880 {
3881 index=PushColormapIndex(image,(unsigned long) indexes[x],
3882 &range_exception);
3883 pixel=image->colormap[(long) index];
3884 q->red=pixel.red;
3885 q->green=pixel.green;
3886 q->blue=pixel.blue;
3887 q++;
3888 }
3889 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3890 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00003891 }
3892 image_view=DestroyCacheView(image_view);
3893 if (range_exception != MagickFalse)
3894 (void) ThrowMagickException(&image->exception,GetMagickModule(),
3895 CorruptImageError,"InvalidColormapIndex","`%s'",image->filename);
3896 return(status);
3897}
cristy1626d332009-11-10 16:58:17 +00003898
3899/*
3900%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3901% %
3902% %
3903% %
3904% S y n c I m a g e S e t t i n g s %
3905% %
3906% %
3907% %
3908%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3909%
3910% SyncImageSettings() sync the image info options to the image.
3911%
3912% The format of the SyncImageSettings method is:
3913%
3914% MagickBooleanType SyncImageSettings(const ImageInfo *image_info,
3915% Image *image)
3916% MagickBooleanType SyncImagesSettings(const ImageInfo *image_info,
3917% Image *image)
3918%
3919% A description of each parameter follows:
3920%
3921% o image_info: the image info.
3922%
3923% o image: the image.
3924%
3925*/
3926
3927MagickExport MagickBooleanType SyncImagesSettings(ImageInfo *image_info,
3928 Image *images)
3929{
3930 Image
3931 *image;
3932
3933 assert(image_info != (const ImageInfo *) NULL);
3934 assert(image_info->signature == MagickSignature);
3935 assert(images != (Image *) NULL);
3936 assert(images->signature == MagickSignature);
3937 if (images->debug != MagickFalse)
3938 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
3939 image=images;
3940 for ( ; image != (Image *) NULL; image=GetNextImageInList(image))
3941 (void) SyncImageSettings(image_info,image);
3942 (void) DeleteImageOption(image_info,"page");
3943 return(MagickTrue);
3944}
3945
3946MagickExport MagickBooleanType SyncImageSettings(const ImageInfo *image_info,
3947 Image *image)
3948{
3949 char
3950 property[MaxTextExtent];
3951
3952 const char
3953 *value,
3954 *option;
3955
3956 GeometryInfo
3957 geometry_info;
3958
3959 MagickStatusType
3960 flags;
3961
3962 /*
3963 Sync image options.
3964 */
3965 assert(image_info != (const ImageInfo *) NULL);
3966 assert(image_info->signature == MagickSignature);
3967 assert(image != (Image *) NULL);
3968 assert(image->signature == MagickSignature);
3969 if (image->debug != MagickFalse)
3970 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3971 option=GetImageOption(image_info,"background");
3972 if (option != (const char *) NULL)
3973 (void) QueryColorDatabase(option,&image->background_color,
3974 &image->exception);
3975 option=GetImageOption(image_info,"bias");
3976 if (option != (const char *) NULL)
cristyf2f27272009-12-17 14:48:46 +00003977 image->bias=SiPrefixToDouble(option,QuantumRange);
cristy1626d332009-11-10 16:58:17 +00003978 option=GetImageOption(image_info,"black-point-compensation");
3979 if (option != (const char *) NULL)
3980 image->black_point_compensation=(MagickBooleanType) ParseMagickOption(
3981 MagickBooleanOptions,MagickFalse,option);
3982 option=GetImageOption(image_info,"blue-primary");
3983 if (option != (const char *) NULL)
3984 {
3985 flags=ParseGeometry(option,&geometry_info);
3986 image->chromaticity.blue_primary.x=geometry_info.rho;
3987 image->chromaticity.blue_primary.y=geometry_info.sigma;
3988 if ((flags & SigmaValue) == 0)
3989 image->chromaticity.blue_primary.y=image->chromaticity.blue_primary.x;
3990 }
3991 option=GetImageOption(image_info,"bordercolor");
3992 if (option != (const char *) NULL)
3993 (void) QueryColorDatabase(option,&image->border_color,&image->exception);
3994 option=GetImageOption(image_info,"colors");
3995 if (option != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00003996 image->colors=StringToUnsignedLong(option);
cristy1626d332009-11-10 16:58:17 +00003997 option=GetImageOption(image_info,"compose");
3998 if (option != (const char *) NULL)
3999 image->compose=(CompositeOperator) ParseMagickOption(MagickComposeOptions,
4000 MagickFalse,option);
4001 option=GetImageOption(image_info,"compress");
4002 if (option != (const char *) NULL)
4003 image->compression=(CompressionType) ParseMagickOption(
4004 MagickCompressOptions,MagickFalse,option);
4005 option=GetImageOption(image_info,"debug");
4006 if (option != (const char *) NULL)
4007 image->debug=(MagickBooleanType) ParseMagickOption(MagickBooleanOptions,
4008 MagickFalse,option);
4009 option=GetImageOption(image_info,"delay");
4010 if (option != (const char *) NULL)
4011 {
4012 GeometryInfo
4013 geometry_info;
4014
4015 flags=ParseGeometry(option,&geometry_info);
4016 if ((flags & GreaterValue) != 0)
4017 {
4018 if (image->delay > (unsigned long) (geometry_info.rho+0.5))
4019 image->delay=(unsigned long) (geometry_info.rho+0.5);
4020 }
4021 else
4022 if ((flags & LessValue) != 0)
4023 {
4024 if (image->delay < (unsigned long) (geometry_info.rho+0.5))
4025 image->ticks_per_second=(long) (geometry_info.sigma+0.5);
4026 }
4027 else
4028 image->delay=(unsigned long) (geometry_info.rho+0.5);
4029 if ((flags & SigmaValue) != 0)
4030 image->ticks_per_second=(long) (geometry_info.sigma+0.5);
4031 }
4032 option=GetImageOption(image_info,"density");
4033 if (option != (const char *) NULL)
4034 {
4035 GeometryInfo
4036 geometry_info;
4037
4038 /*
4039 Set image density.
4040 */
4041 flags=ParseGeometry(option,&geometry_info);
4042 image->x_resolution=geometry_info.rho;
4043 image->y_resolution=geometry_info.sigma;
4044 if ((flags & SigmaValue) == 0)
4045 image->y_resolution=image->x_resolution;
4046 }
4047 option=GetImageOption(image_info,"depth");
4048 if (option != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00004049 image->depth=StringToUnsignedLong(option);
cristy1626d332009-11-10 16:58:17 +00004050 option=GetImageOption(image_info,"dispose");
4051 if (option != (const char *) NULL)
4052 image->dispose=(DisposeType) ParseMagickOption(MagickDisposeOptions,
4053 MagickFalse,option);
4054 option=GetImageOption(image_info,"endian");
4055 if (option != (const char *) NULL)
4056 image->endian=(EndianType) ParseMagickOption(MagickEndianOptions,
4057 MagickFalse,option);
4058 if (image_info->extract != (char *) NULL)
4059 (void) ParseAbsoluteGeometry(image_info->extract,&image->extract_info);
4060 option=GetImageOption(image_info,"filter");
4061 if (option != (const char *) NULL)
4062 image->filter=(FilterTypes) ParseMagickOption(MagickFilterOptions,
4063 MagickFalse,option);
4064 option=GetImageOption(image_info,"fuzz");
4065 if (option != (const char *) NULL)
cristyf2f27272009-12-17 14:48:46 +00004066 image->fuzz=SiPrefixToDouble(option,QuantumRange);
cristy1626d332009-11-10 16:58:17 +00004067 option=GetImageOption(image_info,"gravity");
4068 if (option != (const char *) NULL)
4069 image->gravity=(GravityType) ParseMagickOption(MagickGravityOptions,
4070 MagickFalse,option);
4071 option=GetImageOption(image_info,"green-primary");
4072 if (option != (const char *) NULL)
4073 {
4074 flags=ParseGeometry(option,&geometry_info);
4075 image->chromaticity.green_primary.x=geometry_info.rho;
4076 image->chromaticity.green_primary.y=geometry_info.sigma;
4077 if ((flags & SigmaValue) == 0)
4078 image->chromaticity.green_primary.y=image->chromaticity.green_primary.x;
4079 }
4080 option=GetImageOption(image_info,"intent");
4081 if (option != (const char *) NULL)
4082 image->rendering_intent=(RenderingIntent) ParseMagickOption(
4083 MagickIntentOptions,MagickFalse,option);
4084 option=GetImageOption(image_info,"interlace");
4085 if (option != (const char *) NULL)
4086 image->interlace=(InterlaceType) ParseMagickOption(MagickInterlaceOptions,
4087 MagickFalse,option);
4088 option=GetImageOption(image_info,"interpolate");
4089 if (option != (const char *) NULL)
4090 image->interpolate=(InterpolatePixelMethod) ParseMagickOption(
4091 MagickInterpolateOptions,MagickFalse,option);
4092 option=GetImageOption(image_info,"loop");
4093 if (option != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00004094 image->iterations=StringToUnsignedLong(option);
cristy1626d332009-11-10 16:58:17 +00004095 option=GetImageOption(image_info,"mattecolor");
4096 if (option != (const char *) NULL)
4097 (void) QueryColorDatabase(option,&image->matte_color,&image->exception);
4098 option=GetImageOption(image_info,"orient");
4099 if (option != (const char *) NULL)
4100 image->orientation=(OrientationType) ParseMagickOption(
4101 MagickOrientationOptions,MagickFalse,option);
4102 option=GetImageOption(image_info,"quality");
4103 if (option != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00004104 image->quality=StringToUnsignedLong(option);
cristy1626d332009-11-10 16:58:17 +00004105 option=GetImageOption(image_info,"page");
4106 if (option != (const char *) NULL)
4107 {
4108 char
4109 *geometry;
4110
4111 geometry=GetPageGeometry(option);
4112 flags=ParseAbsoluteGeometry(geometry,&image->page);
4113 geometry=DestroyString(geometry);
4114 }
4115 option=GetImageOption(image_info,"red-primary");
4116 if (option != (const char *) NULL)
4117 {
4118 flags=ParseGeometry(option,&geometry_info);
4119 image->chromaticity.red_primary.x=geometry_info.rho;
4120 image->chromaticity.red_primary.y=geometry_info.sigma;
4121 if ((flags & SigmaValue) == 0)
4122 image->chromaticity.red_primary.y=image->chromaticity.red_primary.x;
4123 }
4124 if (image_info->quality != UndefinedCompressionQuality)
4125 image->quality=image_info->quality;
4126 option=GetImageOption(image_info,"scene");
4127 if (option != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00004128 image->scene=StringToUnsignedLong(option);
cristy1626d332009-11-10 16:58:17 +00004129 option=GetImageOption(image_info,"taint");
4130 if (option != (const char *) NULL)
4131 image->taint=(MagickBooleanType) ParseMagickOption(MagickBooleanOptions,
4132 MagickFalse,option);
4133 option=GetImageOption(image_info,"tile-offset");
4134 if (option != (const char *) NULL)
4135 {
4136 char
4137 *geometry;
4138
4139 geometry=GetPageGeometry(option);
4140 flags=ParseAbsoluteGeometry(geometry,&image->tile_offset);
4141 geometry=DestroyString(geometry);
4142 }
4143 option=GetImageOption(image_info,"transparent-color");
4144 if (option != (const char *) NULL)
4145 (void) QueryColorDatabase(option,&image->transparent_color,
4146 &image->exception);
4147 option=GetImageOption(image_info,"type");
4148 if (option != (const char *) NULL)
4149 image->type=(ImageType) ParseMagickOption(MagickTypeOptions,MagickFalse,
4150 option);
4151 option=GetImageOption(image_info,"units");
4152 if (option != (const char *) NULL)
4153 image->units=(ResolutionType) ParseMagickOption(MagickResolutionOptions,
4154 MagickFalse,option);
4155 if (image_info->units != UndefinedResolution)
4156 {
4157 if (image->units != image_info->units)
4158 switch (image->units)
4159 {
4160 case PixelsPerInchResolution:
4161 {
4162 if (image_info->units == PixelsPerCentimeterResolution)
4163 {
4164 image->x_resolution/=2.54;
4165 image->y_resolution/=2.54;
4166 }
4167 break;
4168 }
4169 case PixelsPerCentimeterResolution:
4170 {
4171 if (image_info->units == PixelsPerInchResolution)
4172 {
4173 image->x_resolution*=2.54;
4174 image->y_resolution*=2.54;
4175 }
4176 break;
4177 }
4178 default:
4179 break;
4180 }
4181 image->units=image_info->units;
4182 }
4183 option=GetImageOption(image_info,"white-point");
4184 if (option != (const char *) NULL)
4185 {
4186 flags=ParseGeometry(option,&geometry_info);
4187 image->chromaticity.white_point.x=geometry_info.rho;
4188 image->chromaticity.white_point.y=geometry_info.sigma;
4189 if ((flags & SigmaValue) == 0)
4190 image->chromaticity.white_point.y=image->chromaticity.white_point.x;
4191 }
4192 ResetImageOptionIterator(image_info);
4193 for (option=GetNextImageOption(image_info); option != (const char *) NULL; )
4194 {
4195 value=GetImageOption(image_info,option);
4196 if (value != (const char *) NULL)
4197 {
4198 (void) FormatMagickString(property,MaxTextExtent,"%s",option);
4199 (void) SetImageArtifact(image,property,value);
4200 }
4201 option=GetNextImageOption(image_info);
4202 }
4203 return(MagickTrue);
4204}