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