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