blob: 17e09bfec701a225425a5db3f9afbd07d8dd9b3d [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% IIIII M M AAA GGGG EEEEE %
7% I MM MM A A G E %
8% I M M M AAAAA G GG EEE %
9% I M M A A G G E %
10% IIIII M M A A GGGG EEEEE %
11% %
12% %
13% MagickCore Image Methods %
14% %
15% Software Design %
16% John Cristy %
17% July 1992 %
18% %
19% %
cristy16af1cb2009-12-11 21:38:29 +000020% Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
28% Unless required by applicable law or agreed to in writing, software %
29% distributed under the License is distributed on an "AS IS" BASIS, %
30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31% See the License for the specific language governing permissions and %
32% limitations under the License. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37%
38*/
39
40/*
41 Include declarations.
42*/
43#include "magick/studio.h"
44#include "magick/animate.h"
45#include "magick/artifact.h"
46#include "magick/blob.h"
47#include "magick/blob-private.h"
48#include "magick/cache.h"
49#include "magick/cache-private.h"
50#include "magick/cache-view.h"
51#include "magick/client.h"
52#include "magick/color.h"
53#include "magick/color-private.h"
cristy316d5172009-09-17 19:31:25 +000054#include "magick/colormap.h"
cristy3ed852e2009-09-05 21:47:34 +000055#include "magick/colorspace.h"
56#include "magick/colorspace-private.h"
57#include "magick/composite.h"
58#include "magick/composite-private.h"
59#include "magick/compress.h"
60#include "magick/constitute.h"
61#include "magick/deprecate.h"
62#include "magick/display.h"
63#include "magick/draw.h"
64#include "magick/enhance.h"
65#include "magick/exception.h"
66#include "magick/exception-private.h"
67#include "magick/gem.h"
68#include "magick/geometry.h"
cristyf2e11662009-10-14 01:24:43 +000069#include "magick/histogram.h"
cristy3ed852e2009-09-05 21:47:34 +000070#include "magick/image-private.h"
cristyf2e11662009-10-14 01:24:43 +000071#include "magick/list.h"
cristy3ed852e2009-09-05 21:47:34 +000072#include "magick/magic.h"
73#include "magick/magick.h"
74#include "magick/memory_.h"
75#include "magick/module.h"
76#include "magick/monitor.h"
77#include "magick/monitor-private.h"
78#include "magick/option.h"
79#include "magick/paint.h"
80#include "magick/pixel-private.h"
81#include "magick/profile.h"
82#include "magick/property.h"
83#include "magick/quantize.h"
84#include "magick/random_.h"
85#include "magick/segment.h"
86#include "magick/semaphore.h"
87#include "magick/signature-private.h"
88#include "magick/statistic.h"
89#include "magick/string_.h"
cristyf2f27272009-12-17 14:48:46 +000090#include "magick/string-private.h"
cristy3ed852e2009-09-05 21:47:34 +000091#include "magick/thread-private.h"
92#include "magick/threshold.h"
93#include "magick/timer.h"
94#include "magick/utility.h"
95#include "magick/version.h"
96#include "magick/xwindow-private.h"
97
98/*
99 Constant declaration.
100*/
101const char
cristy7138c592009-09-08 13:58:52 +0000102 BackgroundColor[] = "#ffffff", /* white */
103 BorderColor[] = "#dfdfdf", /* gray */
104 DefaultTileFrame[] = "15x15+3+3",
105 DefaultTileGeometry[] = "120x120+4+3>",
106 DefaultTileLabel[] = "%f\n%G\n%b",
107 ForegroundColor[] = "#000", /* black */
108 LoadImageTag[] = "Load/Image",
109 LoadImagesTag[] = "Load/Images",
110 MatteColor[] = "#bdbdbd", /* gray */
111 PSDensityGeometry[] = "72.0x72.0",
112 PSPageGeometry[] = "612x792",
113 SaveImageTag[] = "Save/Image",
114 SaveImagesTag[] = "Save/Images",
115 TransparentColor[] = "#00000000"; /* transparent black */
cristy3ed852e2009-09-05 21:47:34 +0000116
117const double
118 DefaultResolution = 72.0;
119
120/*
121%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
122% %
123% %
124% %
125% A c q u i r e I m a g e %
126% %
127% %
128% %
129%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
130%
131% AcquireImage() returns a pointer to an image structure initialized to
132% default values.
133%
134% The format of the AcquireImage method is:
135%
136% Image *AcquireImage(const ImageInfo *image_info)
137%
138% A description of each parameter follows:
139%
140% o image_info: Many of the image default values are set from this
141% structure. For example, filename, compression, depth, background color,
142% and others.
143%
144*/
145MagickExport Image *AcquireImage(const ImageInfo *image_info)
146{
cristye412c892010-07-26 12:31:36 +0000147 const char
cristyf3a660a2010-07-26 14:17:52 +0000148 *option;
cristye412c892010-07-26 12:31:36 +0000149
cristy3ed852e2009-09-05 21:47:34 +0000150 Image
151 *image;
152
153 MagickStatusType
154 flags;
155
156 /*
157 Allocate image structure.
158 */
159 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
cristy73bd4a52010-10-05 11:24:23 +0000160 image=(Image *) AcquireMagickMemory(sizeof(*image));
cristy3ed852e2009-09-05 21:47:34 +0000161 if (image == (Image *) NULL)
162 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
163 (void) ResetMagickMemory(image,0,sizeof(*image));
164 /*
165 Initialize Image structure.
166 */
167 (void) CopyMagickString(image->magick,"MIFF",MaxTextExtent);
168 image->storage_class=DirectClass;
169 image->depth=MAGICKCORE_QUANTUM_DEPTH;
170 image->colorspace=RGBColorspace;
171 image->interlace=NoInterlace;
172 image->ticks_per_second=UndefinedTicksPerSecond;
173 image->compose=OverCompositeOp;
174 image->blur=1.0;
175 GetExceptionInfo(&image->exception);
176 (void) QueryColorDatabase(BackgroundColor,&image->background_color,
177 &image->exception);
178 (void) QueryColorDatabase(BorderColor,&image->border_color,&image->exception);
179 (void) QueryColorDatabase(MatteColor,&image->matte_color,&image->exception);
180 (void) QueryColorDatabase(TransparentColor,&image->transparent_color,
181 &image->exception);
182 image->x_resolution=DefaultResolution;
183 image->y_resolution=DefaultResolution;
184 image->units=PixelsPerInchResolution;
185 GetTimerInfo(&image->timer);
cristy73724512010-04-12 14:43:14 +0000186 image->ping=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000187 image->cache=AcquirePixelCache(0);
188 image->blob=CloneBlobInfo((BlobInfo *) NULL);
189 image->debug=IsEventLogging();
190 image->reference_count=1;
191 image->semaphore=AllocateSemaphoreInfo();
192 image->signature=MagickSignature;
193 if (image_info == (ImageInfo *) NULL)
194 return(image);
195 /*
196 Transfer image info.
197 */
198 SetBlobExempt(image,image_info->file != (FILE *) NULL ? MagickTrue :
199 MagickFalse);
200 (void) CopyMagickString(image->filename,image_info->filename,MaxTextExtent);
201 (void) CopyMagickString(image->magick_filename,image_info->filename,
202 MaxTextExtent);
203 (void) CopyMagickString(image->magick,image_info->magick,MaxTextExtent);
204 if (image_info->size != (char *) NULL)
205 {
206 (void) ParseAbsoluteGeometry(image_info->size,&image->extract_info);
207 image->columns=image->extract_info.width;
208 image->rows=image->extract_info.height;
209 image->offset=image->extract_info.x;
210 image->extract_info.x=0;
211 image->extract_info.y=0;
212 }
213 if (image_info->extract != (char *) NULL)
214 {
215 RectangleInfo
216 geometry;
217
218 flags=ParseAbsoluteGeometry(image_info->extract,&geometry);
219 if (((flags & XValue) != 0) || ((flags & YValue) != 0))
220 {
221 image->extract_info=geometry;
222 Swap(image->columns,image->extract_info.width);
223 Swap(image->rows,image->extract_info.height);
224 }
225 }
226 image->compression=image_info->compression;
227 image->quality=image_info->quality;
228 image->endian=image_info->endian;
229 image->interlace=image_info->interlace;
230 image->units=image_info->units;
231 if (image_info->density != (char *) NULL)
232 {
233 GeometryInfo
234 geometry_info;
235
236 flags=ParseGeometry(image_info->density,&geometry_info);
237 image->x_resolution=geometry_info.rho;
238 image->y_resolution=geometry_info.sigma;
239 if ((flags & SigmaValue) == 0)
240 image->y_resolution=image->x_resolution;
241 }
242 if (image_info->page != (char *) NULL)
243 {
244 char
245 *geometry;
246
247 image->page=image->extract_info;
248 geometry=GetPageGeometry(image_info->page);
249 (void) ParseAbsoluteGeometry(geometry,&image->page);
250 geometry=DestroyString(geometry);
251 }
252 if (image_info->depth != 0)
253 image->depth=image_info->depth;
254 image->dither=image_info->dither;
255 image->background_color=image_info->background_color;
256 image->border_color=image_info->border_color;
257 image->matte_color=image_info->matte_color;
258 image->transparent_color=image_info->transparent_color;
cristy73724512010-04-12 14:43:14 +0000259 image->ping=image_info->ping;
cristy3ed852e2009-09-05 21:47:34 +0000260 image->progress_monitor=image_info->progress_monitor;
261 image->client_data=image_info->client_data;
262 if (image_info->cache != (void *) NULL)
263 ClonePixelCacheMethods(image->cache,image_info->cache);
264 (void) SetImageVirtualPixelMethod(image,image_info->virtual_pixel_method);
cristy6b9aca12010-02-21 01:50:11 +0000265 (void) SyncImageSettings(image_info,image);
cristye412c892010-07-26 12:31:36 +0000266 option=GetImageOption(image_info,"delay");
267 if (option != (const char *) NULL)
268 {
269 GeometryInfo
270 geometry_info;
271
272 flags=ParseGeometry(option,&geometry_info);
273 if ((flags & GreaterValue) != 0)
274 {
275 if (image->delay > (size_t) floor(geometry_info.rho+0.5))
276 image->delay=(size_t) floor(geometry_info.rho+0.5);
277 }
278 else
279 if ((flags & LessValue) != 0)
280 {
281 if (image->delay < (size_t) floor(geometry_info.rho+0.5))
282 image->ticks_per_second=(ssize_t) floor(geometry_info.sigma+0.5);
283 }
284 else
285 image->delay=(size_t) floor(geometry_info.rho+0.5);
286 if ((flags & SigmaValue) != 0)
287 image->ticks_per_second=(ssize_t) floor(geometry_info.sigma+0.5);
288 }
289 option=GetImageOption(image_info,"dispose");
290 if (option != (const char *) NULL)
291 image->dispose=(DisposeType) ParseMagickOption(MagickDisposeOptions,
292 MagickFalse,option);
cristy3ed852e2009-09-05 21:47:34 +0000293 return(image);
294}
295
296/*
297%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
298% %
299% %
300% %
cristy3ed852e2009-09-05 21:47:34 +0000301% A c q u i r e I m a g e I n f o %
302% %
303% %
304% %
305%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
306%
307% AcquireImageInfo() allocates the ImageInfo structure.
308%
309% The format of the AcquireImageInfo method is:
310%
311% ImageInfo *AcquireImageInfo(void)
312%
313*/
314MagickExport ImageInfo *AcquireImageInfo(void)
315{
316 ImageInfo
317 *image_info;
318
cristy73bd4a52010-10-05 11:24:23 +0000319 image_info=(ImageInfo *) AcquireMagickMemory(sizeof(*image_info));
cristy3ed852e2009-09-05 21:47:34 +0000320 if (image_info == (ImageInfo *) NULL)
321 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
322 GetImageInfo(image_info);
323 return(image_info);
324}
325
326/*
327%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
328% %
329% %
330% %
331% A c q u i r e N e x t I m a g e %
332% %
333% %
334% %
335%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
336%
337% AcquireNextImage() initializes the next image in a sequence to
338% default values. The next member of image points to the newly allocated
339% image. If there is a memory shortage, next is assigned NULL.
340%
341% The format of the AcquireNextImage method is:
342%
343% void AcquireNextImage(const ImageInfo *image_info,Image *image)
344%
345% A description of each parameter follows:
346%
347% o image_info: Many of the image default values are set from this
348% structure. For example, filename, compression, depth, background color,
349% and others.
350%
351% o image: the image.
352%
353*/
354MagickExport void AcquireNextImage(const ImageInfo *image_info,Image *image)
355{
356 /*
357 Allocate image structure.
358 */
359 assert(image != (Image *) NULL);
360 assert(image->signature == MagickSignature);
361 if (image->debug != MagickFalse)
362 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
363 image->next=AcquireImage(image_info);
364 if (GetNextImageInList(image) == (Image *) NULL)
365 return;
366 (void) CopyMagickString(GetNextImageInList(image)->filename,image->filename,
367 MaxTextExtent);
368 if (image_info != (ImageInfo *) NULL)
369 (void) CopyMagickString(GetNextImageInList(image)->filename,
370 image_info->filename,MaxTextExtent);
371 DestroyBlob(GetNextImageInList(image));
372 image->next->blob=ReferenceBlob(image->blob);
373 image->next->endian=image->endian;
374 image->next->scene=image->scene+1;
375 image->next->previous=image;
376}
377
378/*
379%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
380% %
381% %
382% %
383% A p p e n d I m a g e s %
384% %
385% %
386% %
387%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
388%
389% AppendImages() takes all images from the current image pointer to the end
390% of the image list and appends them to each other top-to-bottom if the
391% stack parameter is true, otherwise left-to-right.
392%
393% The current gravity setting now effects how the image is justified in the
394% final image.
395%
396% The format of the AppendImages method is:
397%
398% Image *AppendImages(const Image *image,const MagickBooleanType stack,
399% ExceptionInfo *exception)
400%
401% A description of each parameter follows:
402%
403% o image: the image sequence.
404%
405% o stack: A value other than 0 stacks the images top-to-bottom.
406%
407% o exception: return any errors or warnings in this structure.
408%
409*/
410MagickExport Image *AppendImages(const Image *image,
411 const MagickBooleanType stack,ExceptionInfo *exception)
412{
413#define AppendImageTag "Append/Image"
414
415 CacheView
416 *append_view,
417 *image_view;
418
419 Image
420 *append_image;
421
cristy3ed852e2009-09-05 21:47:34 +0000422 MagickBooleanType
423 matte,
424 proceed,
425 status;
426
cristybb503372010-05-27 20:51:26 +0000427 MagickOffsetType
428 n;
429
cristy3ed852e2009-09-05 21:47:34 +0000430 RectangleInfo
431 geometry;
432
433 register const Image
434 *next;
435
cristybb503372010-05-27 20:51:26 +0000436 size_t
cristy3ed852e2009-09-05 21:47:34 +0000437 height,
438 number_images,
439 width;
440
cristybb503372010-05-27 20:51:26 +0000441 ssize_t
442 x_offset,
443 y,
444 y_offset;
445
cristy3ed852e2009-09-05 21:47:34 +0000446 /*
447 Ensure the image have the same column width.
448 */
449 assert(image != (Image *) NULL);
450 assert(image->signature == MagickSignature);
451 if (image->debug != MagickFalse)
452 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
453 assert(exception != (ExceptionInfo *) NULL);
454 assert(exception->signature == MagickSignature);
455 matte=image->matte;
456 number_images=1;
457 width=image->columns;
458 height=image->rows;
459 next=GetNextImageInList(image);
460 for ( ; next != (Image *) NULL; next=GetNextImageInList(next))
461 {
462 if (next->matte != MagickFalse)
463 matte=MagickTrue;
464 number_images++;
465 if (stack != MagickFalse)
466 {
467 if (next->columns > width)
468 width=next->columns;
469 height+=next->rows;
470 continue;
471 }
472 width+=next->columns;
473 if (next->rows > height)
474 height=next->rows;
475 }
476 /*
477 Initialize append next attributes.
478 */
479 append_image=CloneImage(image,width,height,MagickTrue,exception);
480 if (append_image == (Image *) NULL)
481 return((Image *) NULL);
482 if (SetImageStorageClass(append_image,DirectClass) == MagickFalse)
483 {
484 InheritException(exception,&append_image->exception);
485 append_image=DestroyImage(append_image);
486 return((Image *) NULL);
487 }
488 append_image->matte=matte;
489 (void) SetImageBackgroundColor(append_image);
490 status=MagickTrue;
491 x_offset=0;
492 y_offset=0;
493 append_view=AcquireCacheView(append_image);
cristybb503372010-05-27 20:51:26 +0000494 for (n=0; n < (MagickOffsetType) number_images; n++)
cristy3ed852e2009-09-05 21:47:34 +0000495 {
496 SetGeometry(append_image,&geometry);
497 GravityAdjustGeometry(image->columns,image->rows,image->gravity,&geometry);
498 if (stack != MagickFalse)
499 x_offset-=geometry.x;
500 else
501 y_offset-=geometry.y;
502 image_view=AcquireCacheView(image);
cristyb5d5f722009-11-04 03:03:49 +0000503#if defined(MAGICKCORE_OPENMP_SUPPORT)
504 #pragma omp parallel for schedule(dynamic,4) shared(status)
cristy3ed852e2009-09-05 21:47:34 +0000505#endif
cristybb503372010-05-27 20:51:26 +0000506 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000507 {
508 MagickBooleanType
509 sync;
510
511 register const IndexPacket
cristyc47d1f82009-11-26 01:44:43 +0000512 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +0000513
514 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000515 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000516
517 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +0000518 *restrict append_indexes;
cristy3ed852e2009-09-05 21:47:34 +0000519
cristy3ed852e2009-09-05 21:47:34 +0000520 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000521 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000522
cristycb6d09b2010-06-19 01:59:36 +0000523 register ssize_t
524 x;
525
cristy3ed852e2009-09-05 21:47:34 +0000526 if (status == MagickFalse)
527 continue;
528 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
529 q=QueueCacheViewAuthenticPixels(append_view,x_offset,y+y_offset,
530 image->columns,1,exception);
531 if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
532 {
533 status=MagickFalse;
534 continue;
535 }
536 indexes=GetCacheViewVirtualIndexQueue(image_view);
537 append_indexes=GetCacheViewAuthenticIndexQueue(append_view);
cristybb503372010-05-27 20:51:26 +0000538 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000539 {
cristyce70c172010-01-07 17:15:30 +0000540 SetRedPixelComponent(q,GetRedPixelComponent(p));
541 SetGreenPixelComponent(q,GetGreenPixelComponent(p));
542 SetBluePixelComponent(q,GetBluePixelComponent(p));
543 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +0000544 if (image->matte != MagickFalse)
cristyce70c172010-01-07 17:15:30 +0000545 SetOpacityPixelComponent(q,GetOpacityPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +0000546 if (image->colorspace == CMYKColorspace)
547 append_indexes[x]=indexes[x];
548 p++;
549 q++;
550 }
551 sync=SyncCacheViewAuthenticPixels(append_view,exception);
552 if (sync == MagickFalse)
cristya65f35b2010-04-20 01:10:41 +0000553 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000554 }
555 image_view=DestroyCacheView(image_view);
556 proceed=SetImageProgress(image,AppendImageTag,n,number_images);
557 if (proceed == MagickFalse)
558 break;
559 if (stack == MagickFalse)
560 {
cristyeaedf062010-05-29 22:36:02 +0000561 x_offset+=(ssize_t) image->columns;
cristy3ed852e2009-09-05 21:47:34 +0000562 y_offset=0;
563 }
564 else
565 {
566 x_offset=0;
cristyeaedf062010-05-29 22:36:02 +0000567 y_offset+=(ssize_t) image->rows;
cristy3ed852e2009-09-05 21:47:34 +0000568 }
569 image=GetNextImageInList(image);
570 }
571 append_view=DestroyCacheView(append_view);
572 if (status == MagickFalse)
573 append_image=DestroyImage(append_image);
574 return(append_image);
575}
576
577/*
578%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
579% %
580% %
581% %
cristy3ed852e2009-09-05 21:47:34 +0000582% C a t c h I m a g e E x c e p t i o n %
583% %
584% %
585% %
586%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
587%
588% CatchImageException() returns if no exceptions are found in the image
589% sequence, otherwise it determines the most severe exception and reports
590% it as a warning or error depending on the severity.
591%
592% The format of the CatchImageException method is:
593%
594% ExceptionType CatchImageException(Image *image)
595%
596% A description of each parameter follows:
597%
598% o image: An image sequence.
599%
600*/
601MagickExport ExceptionType CatchImageException(Image *image)
602{
603 ExceptionInfo
604 *exception;
605
606 ExceptionType
607 severity;
608
609 assert(image != (const Image *) NULL);
610 assert(image->signature == MagickSignature);
611 if (image->debug != MagickFalse)
612 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
613 exception=AcquireExceptionInfo();
614 GetImageException(image,exception);
615 CatchException(exception);
616 severity=exception->severity;
617 exception=DestroyExceptionInfo(exception);
618 return(severity);
619}
620
621/*
622%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
623% %
624% %
625% %
626% C l i p I m a g e P a t h %
627% %
628% %
629% %
630%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
631%
632% ClipImagePath() sets the image clip mask based any clipping path information
633% if it exists.
634%
635% The format of the ClipImagePath method is:
636%
637% MagickBooleanType ClipImagePath(Image *image,const char *pathname,
638% const MagickBooleanType inside)
639%
640% A description of each parameter follows:
641%
642% o image: the image.
643%
644% o pathname: name of clipping path resource. If name is preceded by #, use
645% clipping path numbered by name.
646%
647% o inside: if non-zero, later operations take effect inside clipping path.
648% Otherwise later operations take effect outside clipping path.
649%
650*/
651
652MagickExport MagickBooleanType ClipImage(Image *image)
653{
654 return(ClipImagePath(image,"#1",MagickTrue));
655}
656
657MagickExport MagickBooleanType ClipImagePath(Image *image,const char *pathname,
658 const MagickBooleanType inside)
659{
660#define ClipImagePathTag "ClipPath/Image"
661
662 char
663 *property;
664
665 const char
666 *value;
667
668 Image
669 *clip_mask;
670
671 ImageInfo
672 *image_info;
673
674 assert(image != (const Image *) NULL);
675 assert(image->signature == MagickSignature);
676 if (image->debug != MagickFalse)
677 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
678 assert(pathname != NULL);
679 property=AcquireString(pathname);
680 (void) FormatMagickString(property,MaxTextExtent,"8BIM:1999,2998:%s",
681 pathname);
682 value=GetImageProperty(image,property);
683 property=DestroyString(property);
684 if (value == (const char *) NULL)
685 {
686 ThrowFileException(&image->exception,OptionError,"NoClipPathDefined",
687 image->filename);
688 return(MagickFalse);
689 }
690 image_info=AcquireImageInfo();
691 (void) CopyMagickString(image_info->filename,image->filename,MaxTextExtent);
692 (void) ConcatenateMagickString(image_info->filename,pathname,MaxTextExtent);
693 clip_mask=BlobToImage(image_info,value,strlen(value),&image->exception);
694 image_info=DestroyImageInfo(image_info);
695 if (clip_mask == (Image *) NULL)
696 return(MagickFalse);
697 if (clip_mask->storage_class == PseudoClass)
698 {
699 (void) SyncImage(clip_mask);
700 if (SetImageStorageClass(clip_mask,DirectClass) == MagickFalse)
701 return(MagickFalse);
702 }
703 if (inside == MagickFalse)
704 (void) NegateImage(clip_mask,MagickFalse);
705 (void) FormatMagickString(clip_mask->magick_filename,MaxTextExtent,
706 "8BIM:1999,2998:%s\nPS",pathname);
707 (void) SetImageClipMask(image,clip_mask);
708 clip_mask=DestroyImage(clip_mask);
709 return(MagickTrue);
710}
711
712/*
713%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
714% %
715% %
716% %
717% C l o n e I m a g e %
718% %
719% %
720% %
721%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
722%
723% CloneImage() copies an image and returns the copy as a new image object.
724% If the specified columns and rows is 0, an exact copy of the image is
725% returned, otherwise the pixel data is undefined and must be initialized
726% with the QueueAuthenticPixels() and SyncAuthenticPixels() methods. On
727% failure, a NULL image is returned and exception describes the reason for the
728% failure.
729%
730% The format of the CloneImage method is:
731%
cristybb503372010-05-27 20:51:26 +0000732% Image *CloneImage(const Image *image,const size_t columns,
733% const size_t rows,const MagickBooleanType orphan,
cristy3ed852e2009-09-05 21:47:34 +0000734% ExceptionInfo *exception)
735%
736% A description of each parameter follows:
737%
738% o image: the image.
739%
740% o columns: the number of columns in the cloned image.
741%
742% o rows: the number of rows in the cloned image.
743%
744% o detach: With a value other than 0, the cloned image is detached from
745% its parent I/O stream.
746%
747% o exception: return any errors or warnings in this structure.
748%
749*/
cristybb503372010-05-27 20:51:26 +0000750MagickExport Image *CloneImage(const Image *image,const size_t columns,
751 const size_t rows,const MagickBooleanType detach,
cristy3ed852e2009-09-05 21:47:34 +0000752 ExceptionInfo *exception)
753{
754 Image
755 *clone_image;
756
757 MagickRealType
758 scale;
759
760 size_t
761 length;
762
763 /*
764 Clone the image.
765 */
766 assert(image != (const Image *) NULL);
767 assert(image->signature == MagickSignature);
768 if (image->debug != MagickFalse)
769 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
770 assert(exception != (ExceptionInfo *) NULL);
771 assert(exception->signature == MagickSignature);
cristy73bd4a52010-10-05 11:24:23 +0000772 clone_image=(Image *) AcquireMagickMemory(sizeof(*clone_image));
cristy3ed852e2009-09-05 21:47:34 +0000773 if (clone_image == (Image *) NULL)
774 ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
775 (void) ResetMagickMemory(clone_image,0,sizeof(*clone_image));
776 clone_image->signature=MagickSignature;
777 clone_image->storage_class=image->storage_class;
778 clone_image->colorspace=image->colorspace;
779 clone_image->matte=image->matte;
780 clone_image->columns=image->columns;
781 clone_image->rows=image->rows;
782 clone_image->dither=image->dither;
783 if (image->colormap != (PixelPacket *) NULL)
784 {
785 /*
786 Allocate and copy the image colormap.
787 */
788 clone_image->colors=image->colors;
789 length=(size_t) image->colors;
790 clone_image->colormap=(PixelPacket *) AcquireQuantumMemory(length,
791 sizeof(*clone_image->colormap));
792 if (clone_image->colormap == (PixelPacket *) NULL)
793 ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
794 (void) CopyMagickMemory(clone_image->colormap,image->colormap,length*
795 sizeof(*clone_image->colormap));
796 }
797 (void) CloneImageProfiles(clone_image,image);
798 (void) CloneImageProperties(clone_image,image);
799 (void) CloneImageArtifacts(clone_image,image);
800 GetTimerInfo(&clone_image->timer);
801 GetExceptionInfo(&clone_image->exception);
802 InheritException(&clone_image->exception,&image->exception);
803 if (image->ascii85 != (void *) NULL)
804 Ascii85Initialize(clone_image);
805 clone_image->magick_columns=image->magick_columns;
806 clone_image->magick_rows=image->magick_rows;
807 clone_image->type=image->type;
808 (void) CopyMagickString(clone_image->magick_filename,image->magick_filename,
809 MaxTextExtent);
810 (void) CopyMagickString(clone_image->magick,image->magick,MaxTextExtent);
811 (void) CopyMagickString(clone_image->filename,image->filename,MaxTextExtent);
812 clone_image->progress_monitor=image->progress_monitor;
813 clone_image->client_data=image->client_data;
814 clone_image->reference_count=1;
815 clone_image->next=NewImageList();
816 clone_image->previous=NewImageList();
817 clone_image->list=NewImageList();
818 clone_image->clip_mask=NewImageList();
819 clone_image->mask=NewImageList();
820 if (detach == MagickFalse)
821 clone_image->blob=ReferenceBlob(image->blob);
822 else
823 clone_image->blob=CloneBlobInfo((BlobInfo *) NULL);
cristy73724512010-04-12 14:43:14 +0000824 clone_image->ping=image->ping;
cristy3ed852e2009-09-05 21:47:34 +0000825 clone_image->debug=IsEventLogging();
826 clone_image->semaphore=AllocateSemaphoreInfo();
827 if ((columns == 0) && (rows == 0))
828 {
829 if (image->montage != (char *) NULL)
830 (void) CloneString(&clone_image->montage,image->montage);
831 if (image->directory != (char *) NULL)
832 (void) CloneString(&clone_image->directory,image->directory);
833 if (image->clip_mask != (Image *) NULL)
834 clone_image->clip_mask=CloneImage(image->clip_mask,0,0,MagickTrue,
835 exception);
836 if (image->mask != (Image *) NULL)
837 clone_image->mask=CloneImage(image->mask,0,0,MagickTrue,exception);
838 clone_image->cache=ReferencePixelCache(image->cache);
839 return(clone_image);
840 }
841 scale=(MagickRealType) columns/(MagickRealType) image->columns;
cristybb503372010-05-27 20:51:26 +0000842 clone_image->page.width=(size_t) floor(scale*image->page.width+0.5);
843 clone_image->page.x=(ssize_t) ceil(scale*image->page.x-0.5);
844 clone_image->tile_offset.x=(ssize_t) ceil(scale*image->tile_offset.x-0.5);
cristy3ed852e2009-09-05 21:47:34 +0000845 scale=(MagickRealType) rows/(MagickRealType) image->rows;
cristybb503372010-05-27 20:51:26 +0000846 clone_image->page.height=(size_t) floor(scale*image->page.height+0.5);
847 clone_image->page.y=(ssize_t) ceil(scale*image->page.y-0.5);
848 clone_image->tile_offset.y=(ssize_t) ceil(scale*image->tile_offset.y-0.5);
cristy3ed852e2009-09-05 21:47:34 +0000849 clone_image->columns=columns;
850 clone_image->rows=rows;
851 clone_image->cache=ClonePixelCache(image->cache);
852 return(clone_image);
853}
854
855/*
856%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
857% %
858% %
859% %
860% C l o n e I m a g e I n f o %
861% %
862% %
863% %
864%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
865%
866% CloneImageInfo() makes a copy of the given image info structure. If
867% NULL is specified, a new image info structure is created initialized to
868% default values.
869%
870% The format of the CloneImageInfo method is:
871%
872% ImageInfo *CloneImageInfo(const ImageInfo *image_info)
873%
874% A description of each parameter follows:
875%
876% o image_info: the image info.
877%
878*/
879MagickExport ImageInfo *CloneImageInfo(const ImageInfo *image_info)
880{
881 ImageInfo
882 *clone_info;
883
884 clone_info=AcquireImageInfo();
885 if (image_info == (ImageInfo *) NULL)
886 return(clone_info);
887 clone_info->compression=image_info->compression;
888 clone_info->temporary=image_info->temporary;
889 clone_info->adjoin=image_info->adjoin;
890 clone_info->antialias=image_info->antialias;
891 clone_info->scene=image_info->scene;
892 clone_info->number_scenes=image_info->number_scenes;
893 clone_info->depth=image_info->depth;
894 if (image_info->size != (char *) NULL)
895 (void) CloneString(&clone_info->size,image_info->size);
896 if (image_info->extract != (char *) NULL)
897 (void) CloneString(&clone_info->extract,image_info->extract);
898 if (image_info->scenes != (char *) NULL)
899 (void) CloneString(&clone_info->scenes,image_info->scenes);
900 if (image_info->page != (char *) NULL)
901 (void) CloneString(&clone_info->page,image_info->page);
902 clone_info->interlace=image_info->interlace;
903 clone_info->endian=image_info->endian;
904 clone_info->units=image_info->units;
905 clone_info->quality=image_info->quality;
906 if (image_info->sampling_factor != (char *) NULL)
907 (void) CloneString(&clone_info->sampling_factor,
908 image_info->sampling_factor);
909 if (image_info->server_name != (char *) NULL)
910 (void) CloneString(&clone_info->server_name,image_info->server_name);
911 if (image_info->font != (char *) NULL)
912 (void) CloneString(&clone_info->font,image_info->font);
913 if (image_info->texture != (char *) NULL)
914 (void) CloneString(&clone_info->texture,image_info->texture);
915 if (image_info->density != (char *) NULL)
916 (void) CloneString(&clone_info->density,image_info->density);
917 clone_info->pointsize=image_info->pointsize;
918 clone_info->fuzz=image_info->fuzz;
919 clone_info->pen=image_info->pen;
920 clone_info->background_color=image_info->background_color;
921 clone_info->border_color=image_info->border_color;
922 clone_info->matte_color=image_info->matte_color;
923 clone_info->transparent_color=image_info->transparent_color;
924 clone_info->dither=image_info->dither;
925 clone_info->monochrome=image_info->monochrome;
926 clone_info->colors=image_info->colors;
927 clone_info->colorspace=image_info->colorspace;
928 clone_info->type=image_info->type;
929 clone_info->orientation=image_info->orientation;
930 clone_info->preview_type=image_info->preview_type;
931 clone_info->group=image_info->group;
932 clone_info->ping=image_info->ping;
933 clone_info->verbose=image_info->verbose;
934 if (image_info->view != (char *) NULL)
935 (void) CloneString(&clone_info->view,image_info->view);
936 if (image_info->authenticate != (char *) NULL)
937 (void) CloneString(&clone_info->authenticate,image_info->authenticate);
938 (void) CloneImageOptions(clone_info,image_info);
939 clone_info->progress_monitor=image_info->progress_monitor;
940 clone_info->client_data=image_info->client_data;
941 clone_info->cache=image_info->cache;
942 if (image_info->cache != (void *) NULL)
943 clone_info->cache=ReferencePixelCache(image_info->cache);
944 if (image_info->profile != (void *) NULL)
945 clone_info->profile=(void *) CloneStringInfo((StringInfo *)
946 image_info->profile);
947 SetImageInfoFile(clone_info,image_info->file);
948 SetImageInfoBlob(clone_info,image_info->blob,image_info->length);
949 clone_info->stream=image_info->stream;
950 clone_info->virtual_pixel_method=image_info->virtual_pixel_method;
951 (void) CopyMagickString(clone_info->magick,image_info->magick,MaxTextExtent);
952 (void) CopyMagickString(clone_info->unique,image_info->unique,MaxTextExtent);
953 (void) CopyMagickString(clone_info->zero,image_info->zero,MaxTextExtent);
954 (void) CopyMagickString(clone_info->filename,image_info->filename,
955 MaxTextExtent);
956 clone_info->subimage=image_info->scene; /* deprecated */
957 clone_info->subrange=image_info->number_scenes; /* deprecated */
958 clone_info->channel=image_info->channel;
959 clone_info->debug=IsEventLogging();
960 clone_info->signature=image_info->signature;
961 return(clone_info);
962}
963
964/*
965%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
966% %
967% %
968% %
969% C o m b i n e I m a g e s %
970% %
971% %
972% %
973%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
974%
975% CombineImages() combines one or more images into a single image. The
976% grayscale value of the pixels of each image in the sequence is assigned in
977% order to the specified channels of the combined image. The typical
978% ordering would be image 1 => Red, 2 => Green, 3 => Blue, etc.
979%
980% The format of the CombineImages method is:
981%
982% Image *CombineImages(const Image *image,const ChannelType channel,
983% ExceptionInfo *exception)
984%
985% A description of each parameter follows:
986%
987% o image: the image.
988%
989% o exception: return any errors or warnings in this structure.
990%
991*/
992MagickExport Image *CombineImages(const Image *image,const ChannelType channel,
993 ExceptionInfo *exception)
994{
995#define CombineImageTag "Combine/Image"
996
997 CacheView
998 *combine_view;
999
1000 const Image
1001 *next;
1002
1003 Image
1004 *combine_image;
1005
cristy3ed852e2009-09-05 21:47:34 +00001006 MagickBooleanType
1007 status;
1008
cristybb503372010-05-27 20:51:26 +00001009 MagickOffsetType
1010 progress;
1011
1012 ssize_t
1013 y;
1014
cristy3ed852e2009-09-05 21:47:34 +00001015 /*
1016 Ensure the image are the same size.
1017 */
1018 assert(image != (const Image *) NULL);
1019 assert(image->signature == MagickSignature);
1020 if (image->debug != MagickFalse)
1021 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1022 assert(exception != (ExceptionInfo *) NULL);
1023 assert(exception->signature == MagickSignature);
1024 for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
1025 {
1026 if ((next->columns != image->columns) || (next->rows != image->rows))
1027 ThrowImageException(OptionError,"ImagesAreNotTheSameSize");
1028 }
1029 combine_image=CloneImage(image,0,0,MagickTrue,exception);
1030 if (combine_image == (Image *) NULL)
1031 return((Image *) NULL);
1032 if (SetImageStorageClass(combine_image,DirectClass) == MagickFalse)
1033 {
1034 InheritException(exception,&combine_image->exception);
1035 combine_image=DestroyImage(combine_image);
1036 return((Image *) NULL);
1037 }
1038 if ((channel & OpacityChannel) != 0)
1039 combine_image->matte=MagickTrue;
1040 (void) SetImageBackgroundColor(combine_image);
1041 /*
1042 Combine images.
1043 */
1044 status=MagickTrue;
1045 progress=0;
1046 combine_view=AcquireCacheView(combine_image);
cristyb5d5f722009-11-04 03:03:49 +00001047#if defined(MAGICKCORE_OPENMP_SUPPORT)
1048 #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
cristy3ed852e2009-09-05 21:47:34 +00001049#endif
cristybb503372010-05-27 20:51:26 +00001050 for (y=0; y < (ssize_t) combine_image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001051 {
1052 CacheView
1053 *image_view;
1054
1055 const Image
1056 *next;
1057
1058 PixelPacket
1059 *pixels;
1060
1061 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001062 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001063
cristy3ed852e2009-09-05 21:47:34 +00001064 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001065 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00001066
cristycb6d09b2010-06-19 01:59:36 +00001067 register ssize_t
1068 x;
1069
cristy3ed852e2009-09-05 21:47:34 +00001070 if (status == MagickFalse)
1071 continue;
1072 pixels=GetCacheViewAuthenticPixels(combine_view,0,y,combine_image->columns,
1073 1,exception);
1074 if (pixels == (PixelPacket *) NULL)
1075 {
1076 status=MagickFalse;
1077 continue;
1078 }
1079 next=image;
1080 if (((channel & RedChannel) != 0) && (next != (Image *) NULL))
1081 {
1082 image_view=AcquireCacheView(next);
1083 p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
1084 if (p == (const PixelPacket *) NULL)
1085 continue;
1086 q=pixels;
cristybb503372010-05-27 20:51:26 +00001087 for (x=0; x < (ssize_t) combine_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001088 {
cristyce70c172010-01-07 17:15:30 +00001089 SetRedPixelComponent(q,PixelIntensityToQuantum(p));
cristy3ed852e2009-09-05 21:47:34 +00001090 p++;
1091 q++;
1092 }
1093 image_view=DestroyCacheView(image_view);
1094 next=GetNextImageInList(next);
1095 }
1096 if (((channel & GreenChannel) != 0) && (next != (Image *) NULL))
1097 {
1098 image_view=AcquireCacheView(next);
1099 p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
1100 if (p == (const PixelPacket *) NULL)
1101 continue;
1102 q=pixels;
cristybb503372010-05-27 20:51:26 +00001103 for (x=0; x < (ssize_t) combine_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001104 {
cristyce70c172010-01-07 17:15:30 +00001105 SetGreenPixelComponent(q,PixelIntensityToQuantum(p));
cristy3ed852e2009-09-05 21:47:34 +00001106 p++;
1107 q++;
1108 }
1109 image_view=DestroyCacheView(image_view);
1110 next=GetNextImageInList(next);
1111 }
1112 if (((channel & BlueChannel) != 0) && (next != (Image *) NULL))
1113 {
1114 image_view=AcquireCacheView(next);
1115 p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
1116 if (p == (const PixelPacket *) NULL)
1117 continue;
1118 q=pixels;
cristybb503372010-05-27 20:51:26 +00001119 for (x=0; x < (ssize_t) combine_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001120 {
cristyce70c172010-01-07 17:15:30 +00001121 SetBluePixelComponent(q,PixelIntensityToQuantum(p));
cristy3ed852e2009-09-05 21:47:34 +00001122 p++;
1123 q++;
1124 }
1125 image_view=DestroyCacheView(image_view);
1126 next=GetNextImageInList(next);
1127 }
1128 if (((channel & OpacityChannel) != 0) && (next != (Image *) NULL))
1129 {
1130 image_view=AcquireCacheView(next);
1131 p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
1132 if (p == (const PixelPacket *) NULL)
1133 continue;
1134 q=pixels;
cristybb503372010-05-27 20:51:26 +00001135 for (x=0; x < (ssize_t) combine_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001136 {
cristyce70c172010-01-07 17:15:30 +00001137 SetOpacityPixelComponent(q,PixelIntensityToQuantum(p));
cristy3ed852e2009-09-05 21:47:34 +00001138 p++;
1139 q++;
1140 }
1141 image_view=DestroyCacheView(image_view);
1142 next=GetNextImageInList(next);
1143 }
1144 if (((channel & IndexChannel) != 0) &&
1145 (image->colorspace == CMYKColorspace) && (next != (Image *) NULL))
1146 {
1147 IndexPacket
1148 *indexes;
1149
1150 image_view=AcquireCacheView(next);
1151 p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
1152 if (p == (const PixelPacket *) NULL)
1153 continue;
1154 indexes=GetCacheViewAuthenticIndexQueue(combine_view);
cristybb503372010-05-27 20:51:26 +00001155 for (x=0; x < (ssize_t) combine_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001156 {
1157 indexes[x]=PixelIntensityToQuantum(p);
1158 p++;
1159 }
1160 image_view=DestroyCacheView(image_view);
1161 next=GetNextImageInList(next);
1162 }
1163 if (SyncCacheViewAuthenticPixels(combine_view,exception) == MagickFalse)
1164 status=MagickFalse;
1165 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1166 {
1167 MagickBooleanType
1168 proceed;
1169
cristyb5d5f722009-11-04 03:03:49 +00001170#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00001171 #pragma omp critical (MagickCore_CombineImages)
1172#endif
1173 proceed=SetImageProgress(image,CombineImageTag,progress++,
1174 combine_image->rows);
1175 if (proceed == MagickFalse)
1176 status=MagickFalse;
1177 }
1178 }
1179 combine_view=DestroyCacheView(combine_view);
1180 if (status == MagickFalse)
1181 combine_image=DestroyImage(combine_image);
1182 return(combine_image);
1183}
1184
1185/*
1186%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1187% %
1188% %
1189% %
cristy3ed852e2009-09-05 21:47:34 +00001190% D e s t r o y I m a g e %
1191% %
1192% %
1193% %
1194%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1195%
1196% DestroyImage() dereferences an image, deallocating memory associated with
1197% the image if the reference count becomes zero.
1198%
1199% The format of the DestroyImage method is:
1200%
1201% Image *DestroyImage(Image *image)
1202%
1203% A description of each parameter follows:
1204%
1205% o image: the image.
1206%
1207*/
1208MagickExport Image *DestroyImage(Image *image)
1209{
1210 MagickBooleanType
1211 destroy;
1212
1213 /*
1214 Dereference image.
1215 */
1216 assert(image != (Image *) NULL);
1217 assert(image->signature == MagickSignature);
1218 if (image->debug != MagickFalse)
1219 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1220 destroy=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +00001221 LockSemaphoreInfo(image->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001222 image->reference_count--;
1223 if (image->reference_count == 0)
1224 destroy=MagickTrue;
cristyf84a1932010-01-03 18:00:18 +00001225 UnlockSemaphoreInfo(image->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001226 if (destroy == MagickFalse)
1227 return((Image *) NULL);
1228 /*
1229 Destroy image.
1230 */
1231 DestroyImagePixels(image);
1232 if (image->clip_mask != (Image *) NULL)
1233 image->clip_mask=DestroyImage(image->clip_mask);
1234 if (image->mask != (Image *) NULL)
1235 image->mask=DestroyImage(image->mask);
1236 if (image->montage != (char *) NULL)
1237 image->montage=DestroyString(image->montage);
1238 if (image->directory != (char *) NULL)
1239 image->directory=DestroyString(image->directory);
1240 if (image->colormap != (PixelPacket *) NULL)
1241 image->colormap=(PixelPacket *) RelinquishMagickMemory(image->colormap);
1242 if (image->geometry != (char *) NULL)
1243 image->geometry=DestroyString(image->geometry);
cristy3ed852e2009-09-05 21:47:34 +00001244 DestroyImageProfiles(image);
1245 DestroyImageProperties(image);
1246 DestroyImageArtifacts(image);
1247 if (image->ascii85 != (Ascii85Info*) NULL)
1248 image->ascii85=(Ascii85Info *) RelinquishMagickMemory(image->ascii85);
1249 DestroyBlob(image);
1250 (void) DestroyExceptionInfo(&image->exception);
1251 if (image->semaphore != (SemaphoreInfo *) NULL)
1252 DestroySemaphoreInfo(&image->semaphore);
1253 image->signature=(~MagickSignature);
1254 image=(Image *) RelinquishMagickMemory(image);
1255 return(image);
1256}
1257
1258/*
1259%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1260% %
1261% %
1262% %
1263% D e s t r o y I m a g e I n f o %
1264% %
1265% %
1266% %
1267%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1268%
1269% DestroyImageInfo() deallocates memory associated with an ImageInfo
1270% structure.
1271%
1272% The format of the DestroyImageInfo method is:
1273%
1274% ImageInfo *DestroyImageInfo(ImageInfo *image_info)
1275%
1276% A description of each parameter follows:
1277%
1278% o image_info: the image info.
1279%
1280*/
1281MagickExport ImageInfo *DestroyImageInfo(ImageInfo *image_info)
1282{
1283 assert(image_info != (ImageInfo *) NULL);
1284 assert(image_info->signature == MagickSignature);
1285 if (image_info->debug != MagickFalse)
1286 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1287 image_info->filename);
1288 if (image_info->size != (char *) NULL)
1289 image_info->size=DestroyString(image_info->size);
1290 if (image_info->extract != (char *) NULL)
1291 image_info->extract=DestroyString(image_info->extract);
1292 if (image_info->scenes != (char *) NULL)
1293 image_info->scenes=DestroyString(image_info->scenes);
1294 if (image_info->page != (char *) NULL)
1295 image_info->page=DestroyString(image_info->page);
1296 if (image_info->sampling_factor != (char *) NULL)
1297 image_info->sampling_factor=DestroyString(
1298 image_info->sampling_factor);
1299 if (image_info->server_name != (char *) NULL)
1300 image_info->server_name=DestroyString(
1301 image_info->server_name);
1302 if (image_info->font != (char *) NULL)
1303 image_info->font=DestroyString(image_info->font);
1304 if (image_info->texture != (char *) NULL)
1305 image_info->texture=DestroyString(image_info->texture);
1306 if (image_info->density != (char *) NULL)
1307 image_info->density=DestroyString(image_info->density);
1308 if (image_info->view != (char *) NULL)
1309 image_info->view=DestroyString(image_info->view);
1310 if (image_info->authenticate != (char *) NULL)
1311 image_info->authenticate=DestroyString(
1312 image_info->authenticate);
1313 DestroyImageOptions(image_info);
1314 if (image_info->cache != (void *) NULL)
1315 image_info->cache=DestroyPixelCache(image_info->cache);
1316 if (image_info->profile != (StringInfo *) NULL)
1317 image_info->profile=(void *) DestroyStringInfo((StringInfo *)
1318 image_info->profile);
1319 image_info->signature=(~MagickSignature);
1320 image_info=(ImageInfo *) RelinquishMagickMemory(image_info);
1321 return(image_info);
1322}
1323
1324/*
1325%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1326% %
1327% %
1328% %
1329+ D i s a s s o c i a t e I m a g e S t r e a m %
1330% %
1331% %
1332% %
1333%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1334%
1335% DisassociateImageStream() disassociates the image stream.
1336%
1337% The format of the DisassociateImageStream method is:
1338%
1339% MagickBooleanType DisassociateImageStream(const Image *image)
1340%
1341% A description of each parameter follows:
1342%
1343% o image: the image.
1344%
1345*/
1346MagickExport void DisassociateImageStream(Image *image)
1347{
1348 assert(image != (const Image *) NULL);
1349 assert(image->signature == MagickSignature);
1350 if (image->debug != MagickFalse)
1351 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1352 (void) DetachBlob(image->blob);
1353}
1354
1355/*
1356%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1357% %
1358% %
1359% %
1360% G e t I m a g e A l p h a C h a n n e l %
1361% %
1362% %
1363% %
1364%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1365%
1366% GetImageAlphaChannel() returns MagickFalse if the image alpha channel is
1367% not activated. That is, the image is RGB rather than RGBA or CMYK rather
1368% than CMYKA.
1369%
1370% The format of the GetImageAlphaChannel method is:
1371%
1372% MagickBooleanType GetImageAlphaChannel(const Image *image)
1373%
1374% A description of each parameter follows:
1375%
1376% o image: the image.
1377%
1378*/
1379MagickExport MagickBooleanType GetImageAlphaChannel(const Image *image)
1380{
1381 assert(image != (const Image *) NULL);
1382 if (image->debug != MagickFalse)
1383 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1384 assert(image->signature == MagickSignature);
1385 return(image->matte);
1386}
1387
1388/*
1389%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1390% %
1391% %
1392% %
1393% G e t I m a g e C l i p M a s k %
1394% %
1395% %
1396% %
1397%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1398%
1399% GetImageClipMask() returns the clip path associated with the image.
1400%
1401% The format of the GetImageClipMask method is:
1402%
1403% Image *GetImageClipMask(const Image *image,ExceptionInfo *exception)
1404%
1405% A description of each parameter follows:
1406%
1407% o image: the image.
1408%
1409*/
1410MagickExport Image *GetImageClipMask(const Image *image,
1411 ExceptionInfo *exception)
1412{
1413 assert(image != (const Image *) NULL);
1414 if (image->debug != MagickFalse)
1415 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1416 assert(image->signature == MagickSignature);
1417 if (image->clip_mask == (Image *) NULL)
1418 return((Image *) NULL);
1419 return(CloneImage(image->clip_mask,0,0,MagickTrue,exception));
1420}
1421
1422/*
1423%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1424% %
1425% %
1426% %
1427% G e t I m a g e E x c e p t i o n %
1428% %
1429% %
1430% %
1431%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1432%
1433% GetImageException() traverses an image sequence and returns any
1434% error more severe than noted by the exception parameter.
1435%
1436% The format of the GetImageException method is:
1437%
1438% void GetImageException(Image *image,ExceptionInfo *exception)
1439%
1440% A description of each parameter follows:
1441%
1442% o image: Specifies a pointer to a list of one or more images.
1443%
1444% o exception: return the highest severity exception.
1445%
1446*/
1447MagickExport void GetImageException(Image *image,ExceptionInfo *exception)
1448{
1449 register Image
1450 *next;
1451
1452 assert(image != (Image *) NULL);
1453 assert(image->signature == MagickSignature);
1454 if (image->debug != MagickFalse)
1455 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1456 assert(exception != (ExceptionInfo *) NULL);
1457 assert(exception->signature == MagickSignature);
1458 for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
1459 {
1460 if (next->exception.severity == UndefinedException)
1461 continue;
1462 if (next->exception.severity > exception->severity)
1463 InheritException(exception,&next->exception);
1464 next->exception.severity=UndefinedException;
1465 }
1466}
1467
1468/*
1469%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1470% %
1471% %
1472% %
1473% G e t I m a g e I n f o %
1474% %
1475% %
1476% %
1477%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1478%
1479% GetImageInfo() initializes image_info to default values.
1480%
1481% The format of the GetImageInfo method is:
1482%
1483% void GetImageInfo(ImageInfo *image_info)
1484%
1485% A description of each parameter follows:
1486%
1487% o image_info: the image info.
1488%
1489*/
1490MagickExport void GetImageInfo(ImageInfo *image_info)
1491{
1492 ExceptionInfo
1493 *exception;
1494
1495 /*
1496 File and image dimension members.
1497 */
1498 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1499 assert(image_info != (ImageInfo *) NULL);
1500 (void) ResetMagickMemory(image_info,0,sizeof(*image_info));
1501 image_info->adjoin=MagickTrue;
1502 image_info->interlace=NoInterlace;
1503 image_info->channel=DefaultChannels;
1504 image_info->quality=UndefinedCompressionQuality;
1505 image_info->antialias=MagickTrue;
1506 image_info->dither=MagickTrue;
1507 exception=AcquireExceptionInfo();
1508 (void) QueryColorDatabase(BackgroundColor,&image_info->background_color,
1509 exception);
1510 (void) QueryColorDatabase(BorderColor,&image_info->border_color,exception);
1511 (void) QueryColorDatabase(MatteColor,&image_info->matte_color,exception);
1512 (void) QueryColorDatabase(TransparentColor,&image_info->transparent_color,
1513 exception);
1514 exception=DestroyExceptionInfo(exception);
1515 image_info->debug=IsEventLogging();
1516 image_info->signature=MagickSignature;
1517}
1518
1519/*
1520%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1521% %
1522% %
1523% %
cristy15781e52009-12-05 23:05:27 +00001524% G e t I m a g e I n f o F i l e %
1525% %
1526% %
1527% %
1528%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1529%
1530% GetImageInfoFile() returns the image info file member.
1531%
1532% The format of the GetImageInfoFile method is:
1533%
1534% FILE *GetImageInfoFile(const ImageInfo *image_info)
1535%
1536% A description of each parameter follows:
1537%
1538% o image_info: the image info.
1539%
1540*/
1541MagickExport FILE *GetImageInfoFile(const ImageInfo *image_info)
1542{
1543 return(image_info->file);
1544}
1545
1546/*
1547%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1548% %
1549% %
1550% %
cristy3ed852e2009-09-05 21:47:34 +00001551% G e t I m a g e M a s k %
1552% %
1553% %
1554% %
1555%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1556%
1557% GetImageMask() returns the mask associated with the image.
1558%
1559% The format of the GetImageMask method is:
1560%
1561% Image *GetImageMask(const Image *image,ExceptionInfo *exception)
1562%
1563% A description of each parameter follows:
1564%
1565% o image: the image.
1566%
1567*/
1568MagickExport Image *GetImageMask(const Image *image,ExceptionInfo *exception)
1569{
1570 assert(image != (const Image *) NULL);
1571 if (image->debug != MagickFalse)
1572 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1573 assert(image->signature == MagickSignature);
1574 if (image->mask == (Image *) NULL)
1575 return((Image *) NULL);
1576 return(CloneImage(image->mask,0,0,MagickTrue,exception));
1577}
1578
1579/*
1580%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1581% %
1582% %
1583% %
1584+ G e t I m a g e R e f e r e n c e C o u n t %
1585% %
1586% %
1587% %
1588%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1589%
1590% GetImageReferenceCount() returns the image reference count.
1591%
1592% The format of the GetReferenceCount method is:
1593%
cristybb503372010-05-27 20:51:26 +00001594% ssize_t GetImageReferenceCount(Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001595%
1596% A description of each parameter follows:
1597%
1598% o image: the image.
1599%
1600*/
cristybb503372010-05-27 20:51:26 +00001601MagickExport ssize_t GetImageReferenceCount(Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001602{
cristybb503372010-05-27 20:51:26 +00001603 ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001604 reference_count;
1605
1606 assert(image != (Image *) NULL);
1607 assert(image->signature == MagickSignature);
1608 if (image->debug != MagickFalse)
1609 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristyf84a1932010-01-03 18:00:18 +00001610 LockSemaphoreInfo(image->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001611 reference_count=image->reference_count;
cristyf84a1932010-01-03 18:00:18 +00001612 UnlockSemaphoreInfo(image->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001613 return(reference_count);
1614}
1615
1616/*
1617%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1618% %
1619% %
1620% %
cristy3ed852e2009-09-05 21:47:34 +00001621% 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 %
1622% %
1623% %
1624% %
1625%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1626%
1627% GetImageVirtualPixelMethod() gets the "virtual pixels" method for the
1628% image. A virtual pixel is any pixel access that is outside the boundaries
1629% of the image cache.
1630%
1631% The format of the GetImageVirtualPixelMethod() method is:
1632%
1633% VirtualPixelMethod GetImageVirtualPixelMethod(const Image *image)
1634%
1635% A description of each parameter follows:
1636%
1637% o image: the image.
1638%
1639*/
1640MagickExport VirtualPixelMethod GetImageVirtualPixelMethod(const Image *image)
1641{
1642 assert(image != (Image *) NULL);
1643 assert(image->signature == MagickSignature);
1644 if (image->debug != MagickFalse)
1645 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1646 return(GetPixelCacheVirtualMethod(image));
1647}
1648
1649/*
1650%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1651% %
1652% %
1653% %
1654% I n t e r p r e t I m a g e F i l e n a m e %
1655% %
1656% %
1657% %
1658%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1659%
1660% InterpretImageFilename() interprets embedded characters in an image filename.
1661% The filename length is returned.
1662%
1663% The format of the InterpretImageFilename method is:
1664%
1665% size_t InterpretImageFilename(const ImageInfo *image_info,
1666% Image *image,const char *format,int value,char *filename)
1667%
1668% A description of each parameter follows.
1669%
1670% o image_info: the image info..
1671%
1672% o image: the image.
1673%
1674% o format: A filename describing the format to use to write the numeric
1675% argument. Only the first numeric format identifier is replaced.
1676%
1677% o value: Numeric value to substitute into format filename.
1678%
1679% o filename: return the formatted filename in this character buffer.
1680%
1681*/
1682MagickExport size_t InterpretImageFilename(const ImageInfo *image_info,
1683 Image *image,const char *format,int value,char *filename)
1684{
1685 char
1686 *q;
1687
1688 int
1689 c;
1690
1691 MagickBooleanType
1692 canonical;
1693
1694 register const char
1695 *p;
1696
1697 canonical=MagickFalse;
1698 (void) CopyMagickString(filename,format,MaxTextExtent);
1699 for (p=strchr(format,'%'); p != (char *) NULL; p=strchr(p+1,'%'))
1700 {
1701 q=(char *) p+1;
1702 if (*q == '%')
1703 {
1704 p=q+1;
1705 continue;
1706 }
1707 if (*q == '0')
1708 {
cristybb503372010-05-27 20:51:26 +00001709 ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001710 value;
1711
cristybb503372010-05-27 20:51:26 +00001712 value=(ssize_t) strtol(q,&q,10);
cristy3ed852e2009-09-05 21:47:34 +00001713 }
1714 switch (*q)
1715 {
1716 case 'd':
1717 case 'o':
1718 case 'x':
1719 {
1720 q++;
1721 c=(*q);
1722 *q='\0';
1723 (void) FormatMagickString(filename+(p-format),(size_t) (MaxTextExtent-
1724 (p-format)),p,value);
1725 *q=c;
1726 (void) ConcatenateMagickString(filename,q,MaxTextExtent);
1727 canonical=MagickTrue;
1728 if (*(q-1) != '%')
1729 break;
1730 p++;
1731 break;
1732 }
1733 case '[':
1734 {
1735 char
1736 pattern[MaxTextExtent];
1737
1738 const char
1739 *value;
1740
cristy3ed852e2009-09-05 21:47:34 +00001741 register char
1742 *r;
1743
cristybb503372010-05-27 20:51:26 +00001744 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001745 i;
1746
cristycb6d09b2010-06-19 01:59:36 +00001747 ssize_t
1748 depth;
1749
cristy3ed852e2009-09-05 21:47:34 +00001750 /*
1751 Image option.
1752 */
1753 if (strchr(p,']') == (char *) NULL)
1754 break;
1755 depth=1;
1756 r=q+1;
1757 for (i=0; (i < (MaxTextExtent-1L)) && (*r != '\0'); i++)
1758 {
1759 if (*r == '[')
1760 depth++;
1761 if (*r == ']')
1762 depth--;
1763 if (depth <= 0)
1764 break;
1765 pattern[i]=(*r++);
1766 }
1767 pattern[i]='\0';
1768 if (LocaleNCompare(pattern,"filename:",9) != 0)
1769 break;
1770 value=(const char *) NULL;
1771 if ((image_info != (const ImageInfo *) NULL) &&
1772 (image != (const Image *) NULL))
cristy86fe49e2010-06-25 01:18:11 +00001773 value=GetMagickProperty(image_info,image,pattern);
cristy3ed852e2009-09-05 21:47:34 +00001774 else
1775 if (image != (Image *) NULL)
cristy86fe49e2010-06-25 01:18:11 +00001776 value=GetImageProperty(image,pattern);
cristy3ed852e2009-09-05 21:47:34 +00001777 else
1778 if (image_info != (ImageInfo *) NULL)
cristy86fe49e2010-06-25 01:18:11 +00001779 value=GetImageOption(image_info,pattern);
cristy3ed852e2009-09-05 21:47:34 +00001780 if (value == (const char *) NULL)
1781 break;
1782 q--;
1783 c=(*q);
1784 *q='\0';
1785 (void) CopyMagickString(filename+(p-format),value,(size_t)
1786 (MaxTextExtent-(p-format)));
1787 *q=c;
1788 (void) ConcatenateMagickString(filename,r+1,MaxTextExtent);
1789 canonical=MagickTrue;
1790 if (*(q-1) != '%')
1791 break;
1792 p++;
1793 break;
1794 }
1795 default:
1796 break;
1797 }
1798 }
1799 for (q=filename; *q != '\0'; q++)
1800 if ((*q == '%') && (*(q+1) == '%'))
1801 (void) CopyMagickString(q,q+1,(size_t) (MaxTextExtent-(q-filename)));
1802 if (canonical == MagickFalse)
1803 (void) CopyMagickString(filename,format,MaxTextExtent);
1804 return(strlen(filename));
1805}
1806
1807/*
1808%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1809% %
1810% %
1811% %
1812% I s H i g h D y n a m i c R a n g e I m a g e %
1813% %
1814% %
1815% %
1816%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1817%
1818% IsHighDynamicRangeImage() returns MagickTrue if any pixel component is
1819% non-integer or exceeds the bounds of the quantum depth (e.g. for Q16
1820% 0..65535.
1821%
1822% The format of the IsHighDynamicRangeImage method is:
1823%
1824% MagickBooleanType IsHighDynamicRangeImage(const Image *image,
1825% ExceptionInfo *exception)
1826%
1827% A description of each parameter follows:
1828%
1829% o image: the image.
1830%
1831% o exception: return any errors or warnings in this structure.
1832%
1833*/
1834MagickExport MagickBooleanType IsHighDynamicRangeImage(const Image *image,
1835 ExceptionInfo *exception)
1836{
1837#if !defined(MAGICKCORE_HDRI_SUPPORT)
1838 (void) image;
1839 (void) exception;
1840 return(MagickFalse);
1841#else
1842 CacheView
1843 *image_view;
1844
cristy3ed852e2009-09-05 21:47:34 +00001845 MagickBooleanType
1846 status;
1847
1848 MagickPixelPacket
1849 zero;
1850
cristycb6d09b2010-06-19 01:59:36 +00001851 ssize_t
1852 y;
1853
cristy3ed852e2009-09-05 21:47:34 +00001854 assert(image != (Image *) NULL);
1855 assert(image->signature == MagickSignature);
1856 if (image->debug != MagickFalse)
1857 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1858 status=MagickTrue;
1859 GetMagickPixelPacket(image,&zero);
1860 image_view=AcquireCacheView(image);
cristyb5d5f722009-11-04 03:03:49 +00001861#if defined(MAGICKCORE_OPENMP_SUPPORT)
1862 #pragma omp parallel for schedule(dynamic,4) shared(status)
cristy3ed852e2009-09-05 21:47:34 +00001863#endif
cristybb503372010-05-27 20:51:26 +00001864 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001865 {
1866 MagickPixelPacket
1867 pixel;
1868
1869 register const IndexPacket
1870 *indexes;
1871
1872 register const PixelPacket
1873 *p;
1874
cristybb503372010-05-27 20:51:26 +00001875 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001876 x;
1877
1878 if (status == MagickFalse)
1879 continue;
1880 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1881 if (p == (const PixelPacket *) NULL)
1882 {
1883 status=MagickFalse;
1884 continue;
1885 }
1886 indexes=GetCacheViewVirtualIndexQueue(image_view);
1887 pixel=zero;
cristybb503372010-05-27 20:51:26 +00001888 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001889 {
1890 SetMagickPixelPacket(image,p,indexes+x,&pixel);
1891 if ((pixel.red < 0.0) || (pixel.red > QuantumRange) ||
1892 (pixel.red != (QuantumAny) pixel.red))
1893 break;
1894 if ((pixel.green < 0.0) || (pixel.green > QuantumRange) ||
1895 (pixel.green != (QuantumAny) pixel.green))
1896 break;
1897 if ((pixel.blue < 0.0) || (pixel.blue > QuantumRange) ||
1898 (pixel.blue != (QuantumAny) pixel.blue))
1899 break;
1900 if (pixel.matte != MagickFalse)
1901 {
1902 if ((pixel.opacity < 0.0) || (pixel.opacity > QuantumRange) ||
1903 (pixel.opacity != (QuantumAny) pixel.opacity))
1904 break;
1905 }
1906 if (pixel.colorspace == CMYKColorspace)
1907 {
1908 if ((pixel.index < 0.0) || (pixel.index > QuantumRange) ||
1909 (pixel.index != (QuantumAny) pixel.index))
1910 break;
1911 }
1912 p++;
1913 }
cristybb503372010-05-27 20:51:26 +00001914 if (x < (ssize_t) image->columns)
cristy3ed852e2009-09-05 21:47:34 +00001915 status=MagickFalse;
1916 }
1917 image_view=DestroyCacheView(image_view);
1918 return(status != MagickFalse ? MagickFalse : MagickTrue);
1919#endif
1920}
1921
1922/*
1923%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1924% %
1925% %
1926% %
1927% I s I m a g e O b j e c t %
1928% %
1929% %
1930% %
1931%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1932%
1933% IsImageObject() returns MagickTrue if the image sequence contains a valid
1934% set of image objects.
1935%
1936% The format of the IsImageObject method is:
1937%
1938% MagickBooleanType IsImageObject(const Image *image)
1939%
1940% A description of each parameter follows:
1941%
1942% o image: the image.
1943%
1944*/
1945MagickExport MagickBooleanType IsImageObject(const Image *image)
1946{
1947 register const Image
1948 *p;
1949
1950 assert(image != (Image *) NULL);
1951 if (image->debug != MagickFalse)
1952 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1953 for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
1954 if (p->signature != MagickSignature)
1955 return(MagickFalse);
1956 return(MagickTrue);
1957}
1958
1959/*
1960%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1961% %
1962% %
1963% %
1964% I s T a i n t I m a g e %
1965% %
1966% %
1967% %
1968%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1969%
1970% IsTaintImage() returns MagickTrue any pixel in the image has been altered
1971% since it was first constituted.
1972%
1973% The format of the IsTaintImage method is:
1974%
1975% MagickBooleanType IsTaintImage(const Image *image)
1976%
1977% A description of each parameter follows:
1978%
1979% o image: the image.
1980%
1981*/
1982MagickExport MagickBooleanType IsTaintImage(const Image *image)
1983{
1984 char
1985 magick[MaxTextExtent],
1986 filename[MaxTextExtent];
1987
1988 register const Image
1989 *p;
1990
1991 assert(image != (Image *) NULL);
1992 if (image->debug != MagickFalse)
1993 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1994 assert(image->signature == MagickSignature);
1995 (void) CopyMagickString(magick,image->magick,MaxTextExtent);
1996 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
1997 for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
1998 {
1999 if (p->taint != MagickFalse)
2000 return(MagickTrue);
2001 if (LocaleCompare(p->magick,magick) != 0)
2002 return(MagickTrue);
2003 if (LocaleCompare(p->filename,filename) != 0)
2004 return(MagickTrue);
2005 }
2006 return(MagickFalse);
2007}
2008
2009/*
2010%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2011% %
2012% %
2013% %
2014% M o d i f y I m a g e %
2015% %
2016% %
2017% %
2018%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2019%
2020% ModifyImage() ensures that there is only a single reference to the image
2021% to be modified, updating the provided image pointer to point to a clone of
2022% the original image if necessary.
2023%
2024% The format of the ModifyImage method is:
2025%
2026% MagickBooleanType ModifyImage(Image *image,ExceptionInfo *exception)
2027%
2028% A description of each parameter follows:
2029%
2030% o image: the image.
2031%
2032% o exception: return any errors or warnings in this structure.
2033%
2034*/
2035MagickExport MagickBooleanType ModifyImage(Image **image,
2036 ExceptionInfo *exception)
2037{
2038 Image
2039 *clone_image;
2040
2041 assert(image != (Image **) NULL);
2042 assert(*image != (Image *) NULL);
2043 assert((*image)->signature == MagickSignature);
2044 if ((*image)->debug != MagickFalse)
2045 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
2046 if (GetImageReferenceCount(*image) <= 1)
2047 return(MagickTrue);
2048 clone_image=CloneImage(*image,0,0,MagickTrue,exception);
cristyf84a1932010-01-03 18:00:18 +00002049 LockSemaphoreInfo((*image)->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00002050 (*image)->reference_count--;
cristyf84a1932010-01-03 18:00:18 +00002051 UnlockSemaphoreInfo((*image)->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00002052 *image=clone_image;
2053 return(MagickTrue);
2054}
2055
2056/*
2057%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2058% %
2059% %
2060% %
2061% N e w M a g i c k I m a g e %
2062% %
2063% %
2064% %
2065%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2066%
2067% NewMagickImage() creates a blank image canvas of the specified size and
2068% background color.
2069%
2070% The format of the NewMagickImage method is:
2071%
2072% Image *NewMagickImage(const ImageInfo *image_info,
cristybb503372010-05-27 20:51:26 +00002073% const size_t width,const size_t height,
cristy3ed852e2009-09-05 21:47:34 +00002074% const MagickPixelPacket *background)
2075%
2076% A description of each parameter follows:
2077%
2078% o image: the image.
2079%
2080% o width: the image width.
2081%
2082% o height: the image height.
2083%
2084% o background: the image color.
2085%
2086*/
2087MagickExport Image *NewMagickImage(const ImageInfo *image_info,
cristybb503372010-05-27 20:51:26 +00002088 const size_t width,const size_t height,
cristy3ed852e2009-09-05 21:47:34 +00002089 const MagickPixelPacket *background)
2090{
2091 CacheView
2092 *image_view;
2093
2094 ExceptionInfo
2095 *exception;
2096
2097 Image
2098 *image;
2099
cristybb503372010-05-27 20:51:26 +00002100 ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002101 y;
2102
2103 MagickBooleanType
2104 status;
2105
2106 assert(image_info != (const ImageInfo *) NULL);
2107 if (image_info->debug != MagickFalse)
2108 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2109 assert(image_info->signature == MagickSignature);
2110 assert(background != (const MagickPixelPacket *) NULL);
2111 image=AcquireImage(image_info);
2112 image->columns=width;
2113 image->rows=height;
2114 image->colorspace=background->colorspace;
2115 image->matte=background->matte;
2116 image->fuzz=background->fuzz;
2117 image->depth=background->depth;
2118 status=MagickTrue;
2119 exception=(&image->exception);
2120 image_view=AcquireCacheView(image);
cristy48974b92009-12-19 02:36:06 +00002121#if defined(MAGICKCORE_OPENMP_SUPPORT)
2122 #pragma omp parallel for schedule(dynamic,4) shared(status)
2123#endif
cristybb503372010-05-27 20:51:26 +00002124 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002125 {
2126 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00002127 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00002128
cristy3ed852e2009-09-05 21:47:34 +00002129 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002130 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002131
cristycb6d09b2010-06-19 01:59:36 +00002132 register ssize_t
2133 x;
2134
cristy48974b92009-12-19 02:36:06 +00002135 if (status == MagickFalse)
2136 continue;
cristy3ed852e2009-09-05 21:47:34 +00002137 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2138 if (q == (PixelPacket *) NULL)
2139 {
2140 status=MagickFalse;
2141 continue;
2142 }
2143 indexes=GetCacheViewAuthenticIndexQueue(image_view);
cristybb503372010-05-27 20:51:26 +00002144 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002145 {
2146 SetPixelPacket(image,background,q,indexes+x);
2147 q++;
2148 }
2149 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2150 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00002151 }
2152 image_view=DestroyCacheView(image_view);
2153 if (status == MagickFalse)
2154 image=DestroyImage(image);
2155 return(image);
2156}
2157
2158/*
2159%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2160% %
2161% %
2162% %
2163% R e f e r e n c e I m a g e %
2164% %
2165% %
2166% %
2167%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2168%
2169% ReferenceImage() increments the reference count associated with an image
2170% returning a pointer to the image.
2171%
2172% The format of the ReferenceImage method is:
2173%
2174% Image *ReferenceImage(Image *image)
2175%
2176% A description of each parameter follows:
2177%
2178% o image: the image.
2179%
2180*/
2181MagickExport Image *ReferenceImage(Image *image)
2182{
2183 assert(image != (Image *) NULL);
2184 if (image->debug != MagickFalse)
2185 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2186 assert(image->signature == MagickSignature);
cristyf84a1932010-01-03 18:00:18 +00002187 LockSemaphoreInfo(image->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00002188 image->reference_count++;
cristyf84a1932010-01-03 18:00:18 +00002189 UnlockSemaphoreInfo(image->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00002190 return(image);
2191}
2192
2193/*
2194%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2195% %
2196% %
2197% %
2198% R e s e t I m a g e P a g e %
2199% %
2200% %
2201% %
2202%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2203%
2204% ResetImagePage() resets the image page canvas and position.
2205%
2206% The format of the ResetImagePage method is:
2207%
2208% MagickBooleanType ResetImagePage(Image *image,const char *page)
2209%
2210% A description of each parameter follows:
2211%
2212% o image: the image.
2213%
2214% o page: the relative page specification.
2215%
2216*/
2217MagickExport MagickBooleanType ResetImagePage(Image *image,const char *page)
2218{
2219 MagickStatusType
2220 flags;
2221
2222 RectangleInfo
2223 geometry;
2224
2225 assert(image != (Image *) NULL);
2226 assert(image->signature == MagickSignature);
2227 if (image->debug != MagickFalse)
2228 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2229 flags=ParseAbsoluteGeometry(page,&geometry);
2230 if ((flags & WidthValue) != 0)
2231 {
2232 if ((flags & HeightValue) == 0)
2233 geometry.height=geometry.width;
2234 image->page.width=geometry.width;
2235 image->page.height=geometry.height;
2236 }
2237 if ((flags & AspectValue) != 0)
2238 {
2239 if ((flags & XValue) != 0)
2240 image->page.x+=geometry.x;
2241 if ((flags & YValue) != 0)
2242 image->page.y+=geometry.y;
2243 }
2244 else
2245 {
2246 if ((flags & XValue) != 0)
2247 {
2248 image->page.x=geometry.x;
2249 if ((image->page.width == 0) && (geometry.x > 0))
2250 image->page.width=image->columns+geometry.x;
2251 }
2252 if ((flags & YValue) != 0)
2253 {
2254 image->page.y=geometry.y;
2255 if ((image->page.height == 0) && (geometry.y > 0))
2256 image->page.height=image->rows+geometry.y;
2257 }
2258 }
2259 return(MagickTrue);
2260}
2261
2262/*
2263%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2264% %
2265% %
2266% %
2267% S e p a r a t e I m a g e C h a n n e l %
2268% %
2269% %
2270% %
2271%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2272%
2273% SeparateImageChannel() separates a channel from the image and returns it as
2274% a grayscale image. A channel is a particular color component of each pixel
2275% in the image.
2276%
2277% The format of the SeparateImageChannel method is:
2278%
2279% MagickBooleanType SeparateImageChannel(Image *image,
2280% const ChannelType channel)
2281%
2282% A description of each parameter follows:
2283%
2284% o image: the image.
2285%
2286% o channel: Identify which channel to extract: RedChannel, GreenChannel,
2287% BlueChannel, OpacityChannel, CyanChannel, MagentaChannel,
2288% YellowChannel, or BlackChannel.
2289%
2290*/
2291MagickExport MagickBooleanType SeparateImageChannel(Image *image,
2292 const ChannelType channel)
2293{
2294#define SeparateImageTag "Separate/Image"
2295
2296 CacheView
2297 *image_view;
2298
2299 ExceptionInfo
2300 *exception;
2301
cristy3ed852e2009-09-05 21:47:34 +00002302 MagickBooleanType
2303 status;
2304
cristybb503372010-05-27 20:51:26 +00002305 MagickOffsetType
2306 progress;
2307
2308 ssize_t
2309 y;
2310
cristy3ed852e2009-09-05 21:47:34 +00002311 assert(image != (Image *) NULL);
2312 assert(image->signature == MagickSignature);
2313 if (image->debug != MagickFalse)
2314 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2315 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2316 return(MagickFalse);
2317 /*
2318 Separate image channels.
2319 */
2320 status=MagickTrue;
cristy11b66ce2010-03-11 13:34:19 +00002321 if (channel == GrayChannels)
cristy3ed852e2009-09-05 21:47:34 +00002322 image->matte=MagickTrue;
2323 progress=0;
2324 exception=(&image->exception);
2325 image_view=AcquireCacheView(image);
cristyb5d5f722009-11-04 03:03:49 +00002326#if defined(MAGICKCORE_OPENMP_SUPPORT)
2327 #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
cristy3ed852e2009-09-05 21:47:34 +00002328#endif
cristybb503372010-05-27 20:51:26 +00002329 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002330 {
2331 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00002332 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00002333
cristy3ed852e2009-09-05 21:47:34 +00002334 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002335 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002336
cristycb6d09b2010-06-19 01:59:36 +00002337 register ssize_t
2338 x;
2339
cristy3ed852e2009-09-05 21:47:34 +00002340 if (status == MagickFalse)
2341 continue;
2342 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2343 if (q == (PixelPacket *) NULL)
2344 {
2345 status=MagickFalse;
2346 continue;
2347 }
2348 indexes=GetCacheViewAuthenticIndexQueue(image_view);
2349 switch (channel)
2350 {
2351 case RedChannel:
2352 {
cristybb503372010-05-27 20:51:26 +00002353 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002354 {
2355 q->green=q->red;
2356 q->blue=q->red;
2357 q++;
2358 }
2359 break;
2360 }
2361 case GreenChannel:
2362 {
cristybb503372010-05-27 20:51:26 +00002363 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002364 {
2365 q->red=q->green;
2366 q->blue=q->green;
2367 q++;
2368 }
2369 break;
2370 }
2371 case BlueChannel:
2372 {
cristybb503372010-05-27 20:51:26 +00002373 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002374 {
2375 q->red=q->blue;
2376 q->green=q->blue;
2377 q++;
2378 }
2379 break;
2380 }
2381 case OpacityChannel:
2382 {
cristybb503372010-05-27 20:51:26 +00002383 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002384 {
2385 q->red=q->opacity;
2386 q->green=q->opacity;
2387 q->blue=q->opacity;
2388 q++;
2389 }
2390 break;
2391 }
2392 case BlackChannel:
2393 {
2394 if ((image->storage_class != PseudoClass) &&
2395 (image->colorspace != CMYKColorspace))
2396 break;
cristybb503372010-05-27 20:51:26 +00002397 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002398 {
2399 q->red=indexes[x];
2400 q->green=indexes[x];
2401 q->blue=indexes[x];
2402 q++;
2403 }
2404 break;
2405 }
2406 case TrueAlphaChannel:
2407 {
cristybb503372010-05-27 20:51:26 +00002408 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002409 {
cristy46f08202010-01-10 04:04:21 +00002410 q->red=(Quantum) GetAlphaPixelComponent(q);
2411 q->green=(Quantum) GetAlphaPixelComponent(q);
2412 q->blue=(Quantum) GetAlphaPixelComponent(q);
cristy3ed852e2009-09-05 21:47:34 +00002413 q++;
2414 }
2415 break;
2416 }
2417 case GrayChannels:
2418 {
cristybb503372010-05-27 20:51:26 +00002419 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002420 {
2421 q->opacity=(Quantum) (QuantumRange-PixelIntensityToQuantum(q));
2422 q++;
2423 }
2424 break;
2425 }
2426 default:
2427 break;
2428 }
2429 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2430 status=MagickFalse;
2431 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2432 {
2433 MagickBooleanType
2434 proceed;
2435
cristyb5d5f722009-11-04 03:03:49 +00002436#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00002437 #pragma omp critical (MagickCore_SeparateImageChannel)
2438#endif
2439 proceed=SetImageProgress(image,SeparateImageTag,progress++,image->rows);
2440 if (proceed == MagickFalse)
2441 status=MagickFalse;
2442 }
2443 }
2444 image_view=DestroyCacheView(image_view);
cristy11b66ce2010-03-11 13:34:19 +00002445 if (channel != GrayChannels)
cristy3ed852e2009-09-05 21:47:34 +00002446 image->matte=MagickFalse;
2447 (void) SetImageColorspace(image,RGBColorspace);
2448 return(status);
2449}
2450
2451/*
2452%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2453% %
2454% %
2455% %
2456% S e p a r a t e I m a g e s %
2457% %
2458% %
2459% %
2460%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2461%
2462% SeparateImages() returns a separate grayscale image for each channel
2463% specified.
2464%
2465% The format of the SeparateImages method is:
2466%
2467% MagickBooleanType SeparateImages(const Image *image,
2468% const ChannelType channel,ExceptionInfo *exception)
2469%
2470% A description of each parameter follows:
2471%
2472% o image: the image.
2473%
2474% o channel: Identify which channels to extract: RedChannel, GreenChannel,
2475% BlueChannel, OpacityChannel, CyanChannel, MagentaChannel,
2476% YellowChannel, or BlackChannel.
2477%
2478% o exception: return any errors or warnings in this structure.
2479%
2480*/
2481MagickExport Image *SeparateImages(const Image *image,const ChannelType channel,
2482 ExceptionInfo *exception)
2483{
2484 Image
2485 *images,
2486 *separate_image;
2487
2488 assert(image != (Image *) NULL);
2489 assert(image->signature == MagickSignature);
2490 if (image->debug != MagickFalse)
2491 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2492 images=NewImageList();
2493 if ((channel & RedChannel) != 0)
2494 {
2495 separate_image=CloneImage(image,0,0,MagickTrue,exception);
2496 (void) SeparateImageChannel(separate_image,RedChannel);
2497 AppendImageToList(&images,separate_image);
2498 }
2499 if ((channel & GreenChannel) != 0)
2500 {
2501 separate_image=CloneImage(image,0,0,MagickTrue,exception);
2502 (void) SeparateImageChannel(separate_image,GreenChannel);
2503 AppendImageToList(&images,separate_image);
2504 }
2505 if ((channel & BlueChannel) != 0)
2506 {
2507 separate_image=CloneImage(image,0,0,MagickTrue,exception);
2508 (void) SeparateImageChannel(separate_image,BlueChannel);
2509 AppendImageToList(&images,separate_image);
2510 }
2511 if (((channel & BlackChannel) != 0) && (image->colorspace == CMYKColorspace))
2512 {
2513 separate_image=CloneImage(image,0,0,MagickTrue,exception);
2514 (void) SeparateImageChannel(separate_image,BlackChannel);
2515 AppendImageToList(&images,separate_image);
2516 }
2517 if ((channel & OpacityChannel) != 0)
2518 {
2519 separate_image=CloneImage(image,0,0,MagickTrue,exception);
2520 (void) SeparateImageChannel(separate_image,OpacityChannel);
2521 AppendImageToList(&images,separate_image);
2522 }
2523 return(images);
2524}
2525
2526/*
2527%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2528% %
2529% %
2530% %
2531% S e t I m a g e A l p h a C h a n n e l %
2532% %
2533% %
2534% %
2535%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2536%
2537% SetImageAlphaChannel() activates, deactivates, resets, or sets the alpha
2538% channel.
2539%
2540% The format of the SetImageAlphaChannel method is:
2541%
2542% MagickBooleanType SetImageAlphaChannel(Image *image,
2543% const AlphaChannelType alpha_type)
2544%
2545% A description of each parameter follows:
2546%
2547% o image: the image.
2548%
2549% o alpha_type: The alpha channel type: ActivateAlphaChannel,
2550% CopyAlphaChannel, DeactivateAlphaChannel, ExtractAlphaChannel,
2551% OpaqueAlphaChannel, ResetAlphaChannel, SetAlphaChannel,
2552% ShapeAlphaChannel, and TransparentAlphaChannel.
2553%
2554*/
2555MagickExport MagickBooleanType SetImageAlphaChannel(Image *image,
2556 const AlphaChannelType alpha_type)
2557{
2558 MagickBooleanType
2559 status;
2560
2561 assert(image != (Image *) NULL);
2562 if (image->debug != MagickFalse)
2563 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2564 assert(image->signature == MagickSignature);
2565 status=MagickFalse;
2566 switch (alpha_type)
2567 {
2568 case ActivateAlphaChannel:
2569 {
2570 image->matte=MagickTrue;
2571 break;
2572 }
2573 case BackgroundAlphaChannel:
2574 {
2575 CacheView
2576 *image_view;
2577
2578 ExceptionInfo
2579 *exception;
2580
2581 IndexPacket
2582 index;
2583
cristy3ed852e2009-09-05 21:47:34 +00002584 MagickBooleanType
2585 status;
2586
2587 MagickPixelPacket
2588 background;
2589
2590 PixelPacket
2591 pixel;
2592
cristycb6d09b2010-06-19 01:59:36 +00002593 ssize_t
2594 y;
2595
cristy3ed852e2009-09-05 21:47:34 +00002596 /*
2597 Set transparent pixels to background color.
2598 */
2599 if (image->matte == MagickFalse)
2600 break;
2601 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2602 break;
2603 GetMagickPixelPacket(image,&background);
2604 SetMagickPixelPacket(image,&image->background_color,(const IndexPacket *)
2605 NULL,&background);
2606 if (image->colorspace == CMYKColorspace)
2607 ConvertRGBToCMYK(&background);
2608 index=0;
2609 SetPixelPacket(image,&background,&pixel,&index);
2610 status=MagickTrue;
2611 exception=(&image->exception);
2612 image_view=AcquireCacheView(image);
cristyb5d5f722009-11-04 03:03:49 +00002613 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2614 #pragma omp parallel for schedule(dynamic,4) shared(status)
cristy3ed852e2009-09-05 21:47:34 +00002615 #endif
cristybb503372010-05-27 20:51:26 +00002616 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002617 {
2618 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00002619 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00002620
cristy3ed852e2009-09-05 21:47:34 +00002621 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002622 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002623
cristycb6d09b2010-06-19 01:59:36 +00002624 register ssize_t
2625 x;
2626
cristy3ed852e2009-09-05 21:47:34 +00002627 if (status == MagickFalse)
2628 continue;
2629 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2630 exception);
2631 if (q == (PixelPacket *) NULL)
2632 {
2633 status=MagickFalse;
2634 continue;
2635 }
cristybb503372010-05-27 20:51:26 +00002636 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002637 {
2638 if (q->opacity == TransparentOpacity)
2639 {
2640 q->red=pixel.red;
2641 q->green=pixel.green;
2642 q->blue=pixel.blue;
2643 }
2644 q++;
2645 }
2646 if (image->colorspace == CMYKColorspace)
2647 {
2648 indexes=GetCacheViewAuthenticIndexQueue(image_view);
cristybb503372010-05-27 20:51:26 +00002649 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002650 indexes[x]=index;
2651 }
2652 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2653 status=MagickFalse;
2654 }
2655 image_view=DestroyCacheView(image_view);
2656 return(status);
2657 }
2658 case DeactivateAlphaChannel:
2659 {
2660 image->matte=MagickFalse;
2661 break;
2662 }
2663 case ShapeAlphaChannel:
2664 case CopyAlphaChannel:
2665 {
2666 /*
2667 Special usage case for SeparateImageChannel(): copy grayscale color to
2668 the alpha channel.
2669 */
2670 status=SeparateImageChannel(image,GrayChannels);
2671 image->matte=MagickTrue; /* make sure transparency is now on! */
2672 if (alpha_type == ShapeAlphaChannel)
2673 {
2674 MagickPixelPacket
2675 background;
2676
2677 /*
2678 Reset all color channels to background color.
2679 */
2680 GetMagickPixelPacket(image,&background);
2681 SetMagickPixelPacket(image,&(image->background_color),(IndexPacket *)
2682 NULL,&background);
cristy308b4e62009-09-21 14:40:44 +00002683 (void) LevelColorsImage(image,&background,&background,MagickTrue);
cristy3ed852e2009-09-05 21:47:34 +00002684 }
2685 break;
2686 }
2687 case ExtractAlphaChannel:
2688 {
2689 status=SeparateImageChannel(image,TrueAlphaChannel);
2690 image->matte=MagickFalse;
2691 break;
2692 }
cristyf64d18b2010-04-30 12:47:03 +00002693 case ResetAlphaChannel: /* deprecated */
cristy3ed852e2009-09-05 21:47:34 +00002694 case OpaqueAlphaChannel:
2695 {
2696 status=SetImageOpacity(image,OpaqueOpacity);
2697 image->matte=MagickTrue;
2698 break;
2699 }
2700 case TransparentAlphaChannel:
2701 {
2702 status=SetImageOpacity(image,TransparentOpacity);
2703 image->matte=MagickTrue;
2704 break;
2705 }
2706 case SetAlphaChannel:
2707 {
2708 if (image->matte == MagickFalse)
2709 {
2710 status=SetImageOpacity(image,OpaqueOpacity);
2711 image->matte=MagickTrue;
2712 }
2713 break;
2714 }
2715 case UndefinedAlphaChannel:
2716 break;
2717 }
2718 return(status);
2719}
2720
2721/*
2722%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2723% %
2724% %
2725% %
2726% S e t I m a g e B a c k g r o u n d C o l o r %
2727% %
2728% %
2729% %
2730%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2731%
2732% SetImageBackgroundColor() initializes the image pixels to the image
2733% background color. The background color is defined by the background_color
2734% member of the image structure.
2735%
2736% The format of the SetImage method is:
2737%
2738% MagickBooleanType SetImageBackgroundColor(Image *image)
2739%
2740% A description of each parameter follows:
2741%
2742% o image: the image.
2743%
2744*/
2745MagickExport MagickBooleanType SetImageBackgroundColor(Image *image)
2746{
2747 CacheView
2748 *image_view;
2749
2750 ExceptionInfo
2751 *exception;
2752
2753 IndexPacket
2754 index;
2755
cristy3ed852e2009-09-05 21:47:34 +00002756 MagickBooleanType
2757 status;
2758
2759 MagickPixelPacket
2760 background;
2761
2762 PixelPacket
2763 pixel;
2764
cristycb6d09b2010-06-19 01:59:36 +00002765 ssize_t
2766 y;
2767
cristy3ed852e2009-09-05 21:47:34 +00002768 assert(image != (Image *) NULL);
2769 if (image->debug != MagickFalse)
2770 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2771 assert(image->signature == MagickSignature);
2772 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2773 return(MagickFalse);
2774 if (image->background_color.opacity != OpaqueOpacity)
2775 image->matte=MagickTrue;
2776 GetMagickPixelPacket(image,&background);
2777 SetMagickPixelPacket(image,&image->background_color,(const IndexPacket *)
2778 NULL,&background);
2779 if (image->colorspace == CMYKColorspace)
2780 ConvertRGBToCMYK(&background);
2781 index=0;
2782 SetPixelPacket(image,&background,&pixel,&index);
2783 /*
2784 Set image background color.
2785 */
2786 status=MagickTrue;
2787 exception=(&image->exception);
2788 image_view=AcquireCacheView(image);
cristyb5d5f722009-11-04 03:03:49 +00002789#if defined(MAGICKCORE_OPENMP_SUPPORT)
2790 #pragma omp parallel for schedule(dynamic,4) shared(status)
cristy3ed852e2009-09-05 21:47:34 +00002791#endif
cristybb503372010-05-27 20:51:26 +00002792 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002793 {
2794 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00002795 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00002796
cristy3ed852e2009-09-05 21:47:34 +00002797 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002798 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002799
cristycb6d09b2010-06-19 01:59:36 +00002800 register ssize_t
2801 x;
2802
cristy3ed852e2009-09-05 21:47:34 +00002803 if (status == MagickFalse)
2804 continue;
2805 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2806 if (q == (PixelPacket *) NULL)
2807 {
2808 status=MagickFalse;
2809 continue;
2810 }
cristybb503372010-05-27 20:51:26 +00002811 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002812 *q++=pixel;
2813 if (image->colorspace == CMYKColorspace)
2814 {
2815 indexes=GetCacheViewAuthenticIndexQueue(image_view);
cristybb503372010-05-27 20:51:26 +00002816 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002817 indexes[x]=index;
2818 }
2819 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2820 status=MagickFalse;
2821 }
2822 image_view=DestroyCacheView(image_view);
2823 return(status);
2824}
2825
2826/*
2827%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2828% %
2829% %
2830% %
cristya5b77cb2010-05-07 19:34:48 +00002831% S e t I m a g e C o l o r %
2832% %
2833% %
2834% %
2835%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2836%
2837% SetImageColor() set the entire image canvas to the specified color.
2838%
2839% The format of the SetImageColor method is:
2840%
2841% MagickBooleanType SetImageColor(Image *image,
2842% const MagickPixelPacket *color)
2843%
2844% A description of each parameter follows:
2845%
2846% o image: the image.
2847%
2848% o background: the image color.
2849%
2850*/
2851MagickExport MagickBooleanType SetImageColor(Image *image,
2852 const MagickPixelPacket *color)
2853{
2854 CacheView
2855 *image_view;
2856
2857 ExceptionInfo
2858 *exception;
2859
cristya5b77cb2010-05-07 19:34:48 +00002860 MagickBooleanType
2861 status;
2862
cristycb6d09b2010-06-19 01:59:36 +00002863 ssize_t
2864 y;
2865
cristya5b77cb2010-05-07 19:34:48 +00002866 assert(image != (Image *) NULL);
2867 if (image->debug != MagickFalse)
2868 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2869 assert(image->signature == MagickSignature);
2870 assert(color != (const MagickPixelPacket *) NULL);
2871 image->colorspace=color->colorspace;
2872 image->matte=color->matte;
2873 image->fuzz=color->fuzz;
2874 image->depth=color->depth;
2875 status=MagickTrue;
2876 exception=(&image->exception);
2877 image_view=AcquireCacheView(image);
2878#if defined(MAGICKCORE_OPENMP_SUPPORT)
2879 #pragma omp parallel for schedule(dynamic,4) shared(status)
2880#endif
cristybb503372010-05-27 20:51:26 +00002881 for (y=0; y < (ssize_t) image->rows; y++)
cristya5b77cb2010-05-07 19:34:48 +00002882 {
2883 register IndexPacket
2884 *restrict indexes;
2885
cristya5b77cb2010-05-07 19:34:48 +00002886 register PixelPacket
2887 *restrict q;
2888
cristycb6d09b2010-06-19 01:59:36 +00002889 register ssize_t
2890 x;
2891
cristya5b77cb2010-05-07 19:34:48 +00002892 if (status == MagickFalse)
2893 continue;
2894 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2895 if (q == (PixelPacket *) NULL)
2896 {
2897 status=MagickFalse;
2898 continue;
2899 }
2900 indexes=GetCacheViewAuthenticIndexQueue(image_view);
cristybb503372010-05-27 20:51:26 +00002901 for (x=0; x < (ssize_t) image->columns; x++)
cristya5b77cb2010-05-07 19:34:48 +00002902 {
2903 SetPixelPacket(image,color,q,indexes+x);
2904 q++;
2905 }
2906 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2907 status=MagickFalse;
2908 }
2909 image_view=DestroyCacheView(image_view);
2910 return(status);
2911}
2912
2913/*
2914%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2915% %
2916% %
2917% %
cristy3ed852e2009-09-05 21:47:34 +00002918% S e t I m a g e S t o r a g e C l a s s %
2919% %
2920% %
2921% %
2922%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2923%
2924% SetImageStorageClass() sets the image class: DirectClass for true color
2925% images or PseudoClass for colormapped images.
2926%
2927% The format of the SetImageStorageClass method is:
2928%
2929% MagickBooleanType SetImageStorageClass(Image *image,
2930% const ClassType storage_class)
2931%
2932% A description of each parameter follows:
2933%
2934% o image: the image.
2935%
2936% o storage_class: The image class.
2937%
2938*/
2939MagickExport MagickBooleanType SetImageStorageClass(Image *image,
2940 const ClassType storage_class)
2941{
cristy3ed852e2009-09-05 21:47:34 +00002942 image->storage_class=storage_class;
cristy537e2722010-09-21 15:30:59 +00002943 return(MagickTrue);
cristy3ed852e2009-09-05 21:47:34 +00002944}
2945
2946/*
2947%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2948% %
2949% %
2950% %
2951% S e t I m a g e C l i p M a s k %
2952% %
2953% %
2954% %
2955%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2956%
2957% SetImageClipMask() associates a clip path with the image. The clip path
2958% must be the same dimensions as the image. Set any pixel component of
2959% the clip path to TransparentOpacity to prevent that corresponding image
2960% pixel component from being updated when SyncAuthenticPixels() is applied.
2961%
2962% The format of the SetImageClipMask method is:
2963%
2964% MagickBooleanType SetImageClipMask(Image *image,const Image *clip_mask)
2965%
2966% A description of each parameter follows:
2967%
2968% o image: the image.
2969%
2970% o clip_mask: the image clip path.
2971%
2972*/
2973MagickExport MagickBooleanType SetImageClipMask(Image *image,
2974 const Image *clip_mask)
2975{
2976 assert(image != (Image *) NULL);
2977 if (image->debug != MagickFalse)
2978 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2979 assert(image->signature == MagickSignature);
2980 if (clip_mask != (const Image *) NULL)
2981 if ((clip_mask->columns != image->columns) ||
2982 (clip_mask->rows != image->rows))
2983 ThrowBinaryException(ImageError,"ImageSizeDiffers",image->filename);
2984 if (image->clip_mask != (Image *) NULL)
2985 image->clip_mask=DestroyImage(image->clip_mask);
2986 image->clip_mask=NewImageList();
2987 if (clip_mask == (Image *) NULL)
2988 return(MagickTrue);
2989 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2990 return(MagickFalse);
2991 image->clip_mask=CloneImage(clip_mask,0,0,MagickTrue,&image->exception);
2992 if (image->clip_mask == (Image *) NULL)
2993 return(MagickFalse);
2994 return(MagickTrue);
2995}
2996
2997/*
2998%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2999% %
3000% %
3001% %
3002% S e t I m a g e E x t e n t %
3003% %
3004% %
3005% %
3006%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3007%
3008% SetImageExtent() sets the image size (i.e. columns & rows).
3009%
3010% The format of the SetImageExtent method is:
3011%
3012% MagickBooleanType SetImageExtent(Image *image,
cristybb503372010-05-27 20:51:26 +00003013% const size_t columns,const size_t rows)
cristy3ed852e2009-09-05 21:47:34 +00003014%
3015% A description of each parameter follows:
3016%
3017% o image: the image.
3018%
3019% o columns: The image width in pixels.
3020%
3021% o rows: The image height in pixels.
3022%
3023*/
3024MagickExport MagickBooleanType SetImageExtent(Image *image,
cristybb503372010-05-27 20:51:26 +00003025 const size_t columns,const size_t rows)
cristy3ed852e2009-09-05 21:47:34 +00003026{
cristy537e2722010-09-21 15:30:59 +00003027 if ((columns == 0) || (rows == 0))
3028 return(MagickFalse);
3029 image->columns=columns;
3030 image->rows=rows;
3031 return(MagickTrue);
cristy3ed852e2009-09-05 21:47:34 +00003032}
3033
3034/*
3035%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3036% %
3037% %
3038% %
3039+ S e t I m a g e I n f o %
3040% %
3041% %
3042% %
3043%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3044%
3045% SetImageInfo() initializes the `magick' field of the ImageInfo structure.
3046% It is set to a type of image format based on the prefix or suffix of the
3047% filename. For example, `ps:image' returns PS indicating a Postscript image.
3048% JPEG is returned for this filename: `image.jpg'. The filename prefix has
3049% precendence over the suffix. Use an optional index enclosed in brackets
3050% after a file name to specify a desired scene of a multi-resolution image
3051% format like Photo CD (e.g. img0001.pcd[4]). A True (non-zero) return value
3052% indicates success.
3053%
3054% The format of the SetImageInfo method is:
3055%
3056% MagickBooleanType SetImageInfo(ImageInfo *image_info,
cristyd965a422010-03-03 17:47:35 +00003057% const unsigned int frames,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003058%
3059% A description of each parameter follows:
3060%
cristyd965a422010-03-03 17:47:35 +00003061% o image_info: the image info.
cristy3ed852e2009-09-05 21:47:34 +00003062%
cristyd965a422010-03-03 17:47:35 +00003063% o frames: the number of images you intend to write.
cristy3ed852e2009-09-05 21:47:34 +00003064%
3065% o exception: return any errors or warnings in this structure.
3066%
3067*/
3068MagickExport MagickBooleanType SetImageInfo(ImageInfo *image_info,
cristyd965a422010-03-03 17:47:35 +00003069 const unsigned int frames,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003070{
3071 char
3072 extension[MaxTextExtent],
3073 filename[MaxTextExtent],
3074 magic[MaxTextExtent],
3075 *q,
3076 subimage[MaxTextExtent];
3077
3078 const MagicInfo
3079 *magic_info;
3080
3081 const MagickInfo
3082 *magick_info;
3083
3084 ExceptionInfo
3085 *sans_exception;
3086
3087 Image
3088 *image;
3089
3090 MagickBooleanType
3091 status;
3092
3093 register const char
3094 *p;
3095
3096 ssize_t
3097 count;
3098
3099 unsigned char
3100 magick[2*MaxTextExtent];
3101
3102 /*
3103 Look for 'image.format' in filename.
3104 */
3105 assert(image_info != (ImageInfo *) NULL);
3106 assert(image_info->signature == MagickSignature);
3107 if (image_info->debug != MagickFalse)
3108 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3109 image_info->filename);
3110 *subimage='\0';
cristyd965a422010-03-03 17:47:35 +00003111 if (frames == 0)
cristy3ed852e2009-09-05 21:47:34 +00003112 {
cristyd965a422010-03-03 17:47:35 +00003113 GetPathComponent(image_info->filename,SubimagePath,subimage);
3114 if (*subimage != '\0')
cristy3ed852e2009-09-05 21:47:34 +00003115 {
cristyd965a422010-03-03 17:47:35 +00003116 /*
3117 Look for scene specification (e.g. img0001.pcd[4]).
3118 */
3119 if (IsSceneGeometry(subimage,MagickFalse) == MagickFalse)
3120 {
3121 if (IsGeometry(subimage) != MagickFalse)
3122 (void) CloneString(&image_info->extract,subimage);
3123 }
3124 else
3125 {
cristybb503372010-05-27 20:51:26 +00003126 size_t
cristyd965a422010-03-03 17:47:35 +00003127 first,
3128 last;
cristy3ed852e2009-09-05 21:47:34 +00003129
cristyd965a422010-03-03 17:47:35 +00003130 (void) CloneString(&image_info->scenes,subimage);
3131 image_info->scene=StringToUnsignedLong(image_info->scenes);
3132 image_info->number_scenes=image_info->scene;
3133 p=image_info->scenes;
3134 for (q=(char *) image_info->scenes; *q != '\0'; p++)
3135 {
3136 while ((isspace((int) ((unsigned char) *p)) != 0) ||
3137 (*p == ','))
3138 p++;
cristybb503372010-05-27 20:51:26 +00003139 first=(size_t) strtol(p,&q,10);
cristyd965a422010-03-03 17:47:35 +00003140 last=first;
3141 while (isspace((int) ((unsigned char) *q)) != 0)
3142 q++;
3143 if (*q == '-')
cristybb503372010-05-27 20:51:26 +00003144 last=(size_t) strtol(q+1,&q,10);
cristyd965a422010-03-03 17:47:35 +00003145 if (first > last)
3146 Swap(first,last);
3147 if (first < image_info->scene)
3148 image_info->scene=first;
3149 if (last > image_info->number_scenes)
3150 image_info->number_scenes=last;
3151 p=q;
3152 }
3153 image_info->number_scenes-=image_info->scene-1;
3154 image_info->subimage=image_info->scene;
3155 image_info->subrange=image_info->number_scenes;
3156 }
cristy3ed852e2009-09-05 21:47:34 +00003157 }
3158 }
3159 *extension='\0';
3160 GetPathComponent(image_info->filename,ExtensionPath,extension);
3161#if defined(MAGICKCORE_ZLIB_DELEGATE)
3162 if (*extension != '\0')
3163 if ((LocaleCompare(extension,"gz") == 0) ||
3164 (LocaleCompare(extension,"Z") == 0) ||
3165 (LocaleCompare(extension,"wmz") == 0))
3166 {
3167 char
3168 path[MaxTextExtent];
3169
3170 (void) CopyMagickString(path,image_info->filename,MaxTextExtent);
3171 path[strlen(path)-strlen(extension)-1]='\0';
3172 GetPathComponent(path,ExtensionPath,extension);
3173 }
3174#endif
3175#if defined(MAGICKCORE_BZLIB_DELEGATE)
3176 if (*extension != '\0')
3177 if (LocaleCompare(extension,"bz2") == 0)
3178 {
3179 char
3180 path[MaxTextExtent];
3181
3182 (void) CopyMagickString(path,image_info->filename,MaxTextExtent);
3183 path[strlen(path)-strlen(extension)-1]='\0';
3184 GetPathComponent(path,ExtensionPath,extension);
3185 }
3186#endif
3187 image_info->affirm=MagickFalse;
3188 sans_exception=AcquireExceptionInfo();
3189 if (*extension != '\0')
3190 {
3191 MagickFormatType
3192 format_type;
3193
cristybb503372010-05-27 20:51:26 +00003194 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003195 i;
3196
3197 static const char
3198 *format_type_formats[] =
3199 {
3200 "AUTOTRACE",
3201 "BROWSE",
3202 "DCRAW",
3203 "EDIT",
3204 "EPHEMERAL",
3205 "LAUNCH",
3206 "MPEG:DECODE",
3207 "MPEG:ENCODE",
3208 "PRINT",
3209 "PS:ALPHA",
3210 "PS:CMYK",
3211 "PS:COLOR",
3212 "PS:GRAY",
3213 "PS:MONO",
3214 "SCAN",
3215 "SHOW",
3216 "WIN",
3217 (char *) NULL
3218 };
3219
3220 /*
3221 User specified image format.
3222 */
3223 (void) CopyMagickString(magic,extension,MaxTextExtent);
3224 LocaleUpper(magic);
3225 /*
3226 Look for explicit image formats.
3227 */
3228 format_type=UndefinedFormatType;
3229 i=0;
cristydd9a2532010-02-20 19:26:46 +00003230 while ((format_type == UndefinedFormatType) &&
cristy3ed852e2009-09-05 21:47:34 +00003231 (format_type_formats[i] != (char *) NULL))
3232 {
3233 if ((*magic == *format_type_formats[i]) &&
3234 (LocaleCompare(magic,format_type_formats[i]) == 0))
3235 format_type=ExplicitFormatType;
3236 i++;
3237 }
3238 magick_info=GetMagickInfo(magic,sans_exception);
3239 if ((magick_info != (const MagickInfo *) NULL) &&
3240 (magick_info->format_type != UndefinedFormatType))
3241 format_type=magick_info->format_type;
3242 if (format_type == UndefinedFormatType)
3243 (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
3244 else
3245 if (format_type == ExplicitFormatType)
3246 {
3247 image_info->affirm=MagickTrue;
3248 (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
3249 }
3250 if (LocaleCompare(magic,"RGB") == 0)
3251 image_info->affirm=MagickFalse; /* maybe SGI disguised as RGB */
3252 }
3253 /*
3254 Look for explicit 'format:image' in filename.
3255 */
3256 *magic='\0';
3257 GetPathComponent(image_info->filename,MagickPath,magic);
3258 if (*magic == '\0')
3259 (void) CopyMagickString(magic,image_info->magick,MaxTextExtent);
3260 else
3261 {
3262 /*
3263 User specified image format.
3264 */
3265 LocaleUpper(magic);
3266 if (IsMagickConflict(magic) == MagickFalse)
3267 {
3268 (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
3269 if (LocaleCompare(magic,"EPHEMERAL") != 0)
3270 image_info->affirm=MagickTrue;
3271 else
3272 image_info->temporary=MagickTrue;
3273 }
3274 }
3275 magick_info=GetMagickInfo(magic,sans_exception);
3276 sans_exception=DestroyExceptionInfo(sans_exception);
3277 if ((magick_info == (const MagickInfo *) NULL) ||
3278 (GetMagickEndianSupport(magick_info) == MagickFalse))
3279 image_info->endian=UndefinedEndian;
3280 GetPathComponent(image_info->filename,CanonicalPath,filename);
3281 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
cristyd965a422010-03-03 17:47:35 +00003282 if ((image_info->adjoin != MagickFalse) && (frames > 1))
cristy3ed852e2009-09-05 21:47:34 +00003283 {
3284 /*
cristyd965a422010-03-03 17:47:35 +00003285 Test for multiple image support (e.g. image%02d.png).
cristy3ed852e2009-09-05 21:47:34 +00003286 */
cristyd965a422010-03-03 17:47:35 +00003287 (void) InterpretImageFilename(image_info,(Image *) NULL,
3288 image_info->filename,(int) image_info->scene,filename);
3289 if ((LocaleCompare(filename,image_info->filename) != 0) &&
3290 (strchr(filename,'%') == (char *) NULL))
3291 image_info->adjoin=MagickFalse;
3292 }
3293 if ((image_info->adjoin != MagickFalse) && (frames > 0))
3294 {
3295 /*
3296 Some image formats do not support multiple frames per file.
3297 */
cristy3ed852e2009-09-05 21:47:34 +00003298 magick_info=GetMagickInfo(magic,exception);
3299 if (magick_info != (const MagickInfo *) NULL)
3300 if (GetMagickAdjoin(magick_info) == MagickFalse)
3301 image_info->adjoin=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00003302 }
3303 if (image_info->affirm != MagickFalse)
3304 return(MagickTrue);
cristyd965a422010-03-03 17:47:35 +00003305 if (frames == 0)
cristy3ed852e2009-09-05 21:47:34 +00003306 {
3307 /*
cristyd965a422010-03-03 17:47:35 +00003308 Determine the image format from the first few bytes of the file.
cristy3ed852e2009-09-05 21:47:34 +00003309 */
cristyd965a422010-03-03 17:47:35 +00003310 image=AcquireImage(image_info);
3311 (void) CopyMagickString(image->filename,image_info->filename,
3312 MaxTextExtent);
cristy3ed852e2009-09-05 21:47:34 +00003313 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
3314 if (status == MagickFalse)
3315 {
3316 image=DestroyImage(image);
3317 return(MagickFalse);
3318 }
cristyd965a422010-03-03 17:47:35 +00003319 if ((IsBlobSeekable(image) == MagickFalse) ||
3320 (IsBlobExempt(image) != MagickFalse))
3321 {
3322 /*
3323 Copy standard input or pipe to temporary file.
3324 */
3325 *filename='\0';
3326 status=ImageToFile(image,filename,exception);
3327 (void) CloseBlob(image);
3328 if (status == MagickFalse)
3329 {
3330 image=DestroyImage(image);
3331 return(MagickFalse);
3332 }
3333 SetImageInfoFile(image_info,(FILE *) NULL);
3334 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
3335 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
3336 if (status == MagickFalse)
3337 {
3338 image=DestroyImage(image);
3339 return(MagickFalse);
3340 }
3341 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
3342 image_info->temporary=MagickTrue;
3343 }
3344 (void) ResetMagickMemory(magick,0,sizeof(magick));
3345 count=ReadBlob(image,2*MaxTextExtent,magick);
3346 (void) CloseBlob(image);
3347 image=DestroyImage(image);
3348 /*
3349 Check magic.xml configuration file.
3350 */
3351 sans_exception=AcquireExceptionInfo();
3352 magic_info=GetMagicInfo(magick,(size_t) count,sans_exception);
3353 if ((magic_info != (const MagicInfo *) NULL) &&
3354 (GetMagicName(magic_info) != (char *) NULL))
3355 {
3356 (void) CopyMagickString(image_info->magick,GetMagicName(magic_info),
3357 MaxTextExtent);
3358 magick_info=GetMagickInfo(image_info->magick,sans_exception);
3359 if ((magick_info == (const MagickInfo *) NULL) ||
3360 (GetMagickEndianSupport(magick_info) == MagickFalse))
3361 image_info->endian=UndefinedEndian;
3362 sans_exception=DestroyExceptionInfo(sans_exception);
3363 return(MagickTrue);
3364 }
cristy3ed852e2009-09-05 21:47:34 +00003365 magick_info=GetMagickInfo(image_info->magick,sans_exception);
3366 if ((magick_info == (const MagickInfo *) NULL) ||
3367 (GetMagickEndianSupport(magick_info) == MagickFalse))
3368 image_info->endian=UndefinedEndian;
3369 sans_exception=DestroyExceptionInfo(sans_exception);
cristy3ed852e2009-09-05 21:47:34 +00003370 }
cristy3ed852e2009-09-05 21:47:34 +00003371 return(MagickTrue);
3372}
3373
3374/*
3375%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3376% %
3377% %
3378% %
3379% S e t I m a g e I n f o B l o b %
3380% %
3381% %
3382% %
3383%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3384%
3385% SetImageInfoBlob() sets the image info blob member.
3386%
3387% The format of the SetImageInfoBlob method is:
3388%
3389% void SetImageInfoBlob(ImageInfo *image_info,const void *blob,
3390% const size_t length)
3391%
3392% A description of each parameter follows:
3393%
3394% o image_info: the image info.
3395%
3396% o blob: the blob.
3397%
3398% o length: the blob length.
3399%
3400*/
3401MagickExport void SetImageInfoBlob(ImageInfo *image_info,const void *blob,
3402 const size_t length)
3403{
3404 assert(image_info != (ImageInfo *) NULL);
3405 assert(image_info->signature == MagickSignature);
3406 if (image_info->debug != MagickFalse)
3407 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3408 image_info->filename);
3409 image_info->blob=(void *) blob;
3410 image_info->length=length;
3411}
3412
3413/*
3414%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3415% %
3416% %
3417% %
3418% S e t I m a g e I n f o F i l e %
3419% %
3420% %
3421% %
3422%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3423%
3424% SetImageInfoFile() sets the image info file member.
3425%
3426% The format of the SetImageInfoFile method is:
3427%
3428% void SetImageInfoFile(ImageInfo *image_info,FILE *file)
3429%
3430% A description of each parameter follows:
3431%
3432% o image_info: the image info.
3433%
3434% o file: the file.
3435%
3436*/
3437MagickExport void SetImageInfoFile(ImageInfo *image_info,FILE *file)
3438{
3439 assert(image_info != (ImageInfo *) NULL);
3440 assert(image_info->signature == MagickSignature);
3441 if (image_info->debug != MagickFalse)
3442 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3443 image_info->filename);
3444 image_info->file=file;
3445}
3446
3447/*
3448%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3449% %
3450% %
3451% %
3452% S e t I m a g e M a s k %
3453% %
3454% %
3455% %
3456%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3457%
3458% SetImageMask() associates a mask with the image. The mask must be the same
3459% dimensions as the image.
3460%
3461% The format of the SetImageMask method is:
3462%
3463% MagickBooleanType SetImageMask(Image *image,const Image *mask)
3464%
3465% A description of each parameter follows:
3466%
3467% o image: the image.
3468%
3469% o mask: the image mask.
3470%
3471*/
3472MagickExport MagickBooleanType SetImageMask(Image *image,
3473 const Image *mask)
3474{
3475 assert(image != (Image *) NULL);
3476 if (image->debug != MagickFalse)
3477 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3478 assert(image->signature == MagickSignature);
3479 if (mask != (const Image *) NULL)
3480 if ((mask->columns != image->columns) || (mask->rows != image->rows))
3481 ThrowBinaryException(ImageError,"ImageSizeDiffers",image->filename);
3482 if (image->mask != (Image *) NULL)
3483 image->mask=DestroyImage(image->mask);
3484 image->mask=NewImageList();
3485 if (mask == (Image *) NULL)
3486 return(MagickTrue);
3487 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
3488 return(MagickFalse);
3489 image->mask=CloneImage(mask,0,0,MagickTrue,&image->exception);
3490 if (image->mask == (Image *) NULL)
3491 return(MagickFalse);
3492 return(MagickTrue);
3493}
3494
3495/*
3496%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3497% %
3498% %
3499% %
3500% S e t I m a g e O p a c i t y %
3501% %
3502% %
3503% %
3504%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3505%
3506% SetImageOpacity() sets the opacity levels of the image.
3507%
3508% The format of the SetImageOpacity method is:
3509%
3510% MagickBooleanType SetImageOpacity(Image *image,const Quantum opacity)
3511%
3512% A description of each parameter follows:
3513%
3514% o image: the image.
3515%
3516% o opacity: the level of transparency: 0 is fully opaque and QuantumRange is
3517% fully transparent.
3518%
3519*/
3520MagickExport MagickBooleanType SetImageOpacity(Image *image,
3521 const Quantum opacity)
3522{
3523 CacheView
3524 *image_view;
3525
3526 ExceptionInfo
3527 *exception;
3528
cristy3ed852e2009-09-05 21:47:34 +00003529 MagickBooleanType
3530 status;
3531
cristycb6d09b2010-06-19 01:59:36 +00003532 ssize_t
3533 y;
3534
cristy3ed852e2009-09-05 21:47:34 +00003535 assert(image != (Image *) NULL);
3536 if (image->debug != MagickFalse)
3537 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3538 assert(image->signature == MagickSignature);
3539 image->matte=opacity != OpaqueOpacity ? MagickTrue : MagickFalse;
3540 status=MagickTrue;
3541 exception=(&image->exception);
3542 image_view=AcquireCacheView(image);
cristyb5d5f722009-11-04 03:03:49 +00003543#if defined(MAGICKCORE_OPENMP_SUPPORT)
3544 #pragma omp parallel for schedule(dynamic,4) shared(status)
cristy3ed852e2009-09-05 21:47:34 +00003545#endif
cristybb503372010-05-27 20:51:26 +00003546 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00003547 {
cristy3ed852e2009-09-05 21:47:34 +00003548 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00003549 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00003550
cristycb6d09b2010-06-19 01:59:36 +00003551 register ssize_t
3552 x;
3553
cristy3ed852e2009-09-05 21:47:34 +00003554 if (status == MagickFalse)
3555 continue;
3556 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3557 if (q == (PixelPacket *) NULL)
3558 {
3559 status=MagickFalse;
3560 continue;
3561 }
cristybb503372010-05-27 20:51:26 +00003562 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00003563 {
cristy46f08202010-01-10 04:04:21 +00003564 SetOpacityPixelComponent(q,opacity);
cristy3ed852e2009-09-05 21:47:34 +00003565 q++;
3566 }
3567 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3568 status=MagickFalse;
3569 }
3570 image_view=DestroyCacheView(image_view);
3571 return(status);
3572}
3573
3574/*
3575%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3576% %
3577% %
3578% %
3579% S e t I m a g e T y p e %
3580% %
3581% %
3582% %
3583%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3584%
3585% SetImageType() sets the type of image. Choose from these types:
3586%
3587% Bilevel Grayscale GrayscaleMatte
3588% Palette PaletteMatte TrueColor
3589% TrueColorMatte ColorSeparation ColorSeparationMatte
3590% OptimizeType
3591%
3592% The format of the SetImageType method is:
3593%
3594% MagickBooleanType SetImageType(Image *image,const ImageType type)
3595%
3596% A description of each parameter follows:
3597%
3598% o image: the image.
3599%
3600% o type: Image type.
3601%
3602*/
3603MagickExport MagickBooleanType SetImageType(Image *image,const ImageType type)
3604{
3605 const char
3606 *artifact;
3607
3608 ImageInfo
3609 *image_info;
3610
3611 MagickBooleanType
3612 status;
3613
3614 QuantizeInfo
3615 *quantize_info;
3616
3617 assert(image != (Image *) NULL);
3618 if (image->debug != MagickFalse)
3619 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3620 assert(image->signature == MagickSignature);
3621 status=MagickTrue;
3622 image_info=AcquireImageInfo();
3623 image_info->dither=image->dither;
3624 artifact=GetImageArtifact(image,"dither");
3625 if (artifact != (const char *) NULL)
3626 (void) SetImageOption(image_info,"dither",artifact);
3627 switch (type)
3628 {
3629 case BilevelType:
3630 {
3631 if (IsGrayImage(image,&image->exception) == MagickFalse)
3632 status=TransformImageColorspace(image,GRAYColorspace);
3633 if (IsMonochromeImage(image,&image->exception) == MagickFalse)
3634 {
3635 quantize_info=AcquireQuantizeInfo(image_info);
3636 quantize_info->number_colors=2;
3637 quantize_info->colorspace=GRAYColorspace;
3638 status=QuantizeImage(quantize_info,image);
3639 quantize_info=DestroyQuantizeInfo(quantize_info);
3640 }
3641 image->matte=MagickFalse;
3642 break;
3643 }
3644 case GrayscaleType:
3645 {
3646 if (IsGrayImage(image,&image->exception) == MagickFalse)
3647 status=TransformImageColorspace(image,GRAYColorspace);
3648 image->matte=MagickFalse;
3649 break;
3650 }
3651 case GrayscaleMatteType:
3652 {
3653 if (IsGrayImage(image,&image->exception) == MagickFalse)
3654 status=TransformImageColorspace(image,GRAYColorspace);
3655 if (image->matte == MagickFalse)
3656 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
3657 break;
3658 }
3659 case PaletteType:
3660 {
3661 if (image->colorspace != RGBColorspace)
3662 status=TransformImageColorspace(image,RGBColorspace);
3663 if ((image->storage_class == DirectClass) || (image->colors > 256))
3664 {
3665 quantize_info=AcquireQuantizeInfo(image_info);
3666 quantize_info->number_colors=256;
3667 status=QuantizeImage(quantize_info,image);
3668 quantize_info=DestroyQuantizeInfo(quantize_info);
3669 }
3670 image->matte=MagickFalse;
3671 break;
3672 }
3673 case PaletteBilevelMatteType:
3674 {
3675 if (image->colorspace != RGBColorspace)
3676 status=TransformImageColorspace(image,RGBColorspace);
3677 if (image->matte == MagickFalse)
3678 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
3679 (void) BilevelImageChannel(image,AlphaChannel,(double) QuantumRange/2.0);
3680 quantize_info=AcquireQuantizeInfo(image_info);
3681 status=QuantizeImage(quantize_info,image);
3682 quantize_info=DestroyQuantizeInfo(quantize_info);
3683 break;
3684 }
3685 case PaletteMatteType:
3686 {
3687 if (image->colorspace != RGBColorspace)
3688 status=TransformImageColorspace(image,RGBColorspace);
3689 if (image->matte == MagickFalse)
3690 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
3691 quantize_info=AcquireQuantizeInfo(image_info);
3692 quantize_info->colorspace=TransparentColorspace;
3693 status=QuantizeImage(quantize_info,image);
3694 quantize_info=DestroyQuantizeInfo(quantize_info);
3695 break;
3696 }
3697 case TrueColorType:
3698 {
3699 if (image->colorspace != RGBColorspace)
3700 status=TransformImageColorspace(image,RGBColorspace);
3701 if (image->storage_class != DirectClass)
3702 status=SetImageStorageClass(image,DirectClass);
3703 image->matte=MagickFalse;
3704 break;
3705 }
3706 case TrueColorMatteType:
3707 {
3708 if (image->colorspace != RGBColorspace)
3709 status=TransformImageColorspace(image,RGBColorspace);
3710 if (image->storage_class != DirectClass)
3711 status=SetImageStorageClass(image,DirectClass);
3712 if (image->matte == MagickFalse)
3713 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
3714 break;
3715 }
3716 case ColorSeparationType:
3717 {
3718 if (image->colorspace != CMYKColorspace)
3719 {
3720 if (image->colorspace != RGBColorspace)
3721 status=TransformImageColorspace(image,RGBColorspace);
3722 status=TransformImageColorspace(image,CMYKColorspace);
3723 }
3724 if (image->storage_class != DirectClass)
3725 status=SetImageStorageClass(image,DirectClass);
3726 image->matte=MagickFalse;
3727 break;
3728 }
3729 case ColorSeparationMatteType:
3730 {
3731 if (image->colorspace != CMYKColorspace)
3732 {
3733 if (image->colorspace != RGBColorspace)
3734 status=TransformImageColorspace(image,RGBColorspace);
3735 status=TransformImageColorspace(image,CMYKColorspace);
3736 }
3737 if (image->storage_class != DirectClass)
3738 status=SetImageStorageClass(image,DirectClass);
3739 if (image->matte == MagickFalse)
3740 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
3741 break;
3742 }
3743 case OptimizeType:
3744 case UndefinedType:
3745 break;
3746 }
3747 image->type=type;
3748 image_info=DestroyImageInfo(image_info);
3749 return(status);
3750}
3751
3752/*
3753%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3754% %
3755% %
3756% %
3757% 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 %
3758% %
3759% %
3760% %
3761%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3762%
3763% SetImageVirtualPixelMethod() sets the "virtual pixels" method for the
3764% image and returns the previous setting. A virtual pixel is any pixel access
3765% that is outside the boundaries of the image cache.
3766%
3767% The format of the SetImageVirtualPixelMethod() method is:
3768%
3769% VirtualPixelMethod SetImageVirtualPixelMethod(const Image *image,
3770% const VirtualPixelMethod virtual_pixel_method)
3771%
3772% A description of each parameter follows:
3773%
3774% o image: the image.
3775%
3776% o virtual_pixel_method: choose the type of virtual pixel.
3777%
3778*/
3779MagickExport VirtualPixelMethod SetImageVirtualPixelMethod(const Image *image,
3780 const VirtualPixelMethod virtual_pixel_method)
3781{
3782 assert(image != (const Image *) NULL);
3783 assert(image->signature == MagickSignature);
3784 if (image->debug != MagickFalse)
3785 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3786 return(SetPixelCacheVirtualMethod(image,virtual_pixel_method));
3787}
3788
3789/*
3790%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3791% %
3792% %
3793% %
cristy3ed852e2009-09-05 21:47:34 +00003794% S t r i p I m a g e %
3795% %
3796% %
3797% %
3798%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3799%
cristy376bda92009-12-22 21:15:23 +00003800% StripImage() strips an image of all profiles and comments.
cristy3ed852e2009-09-05 21:47:34 +00003801%
3802% The format of the StripImage method is:
3803%
3804% MagickBooleanType StripImage(Image *image)
3805%
3806% A description of each parameter follows:
3807%
3808% o image: the image.
3809%
3810*/
3811MagickExport MagickBooleanType StripImage(Image *image)
3812{
3813 assert(image != (Image *) NULL);
3814 if (image->debug != MagickFalse)
3815 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3816 DestroyImageProfiles(image);
cristy6b9aca12010-02-21 01:50:11 +00003817 (void) DeleteImageProperty(image,"comment");
cristy7c99caa2010-09-13 17:19:54 +00003818 (void) DeleteImageProperty(image,"date:create");
3819 (void) DeleteImageProperty(image,"date:modify");
cristy3ed852e2009-09-05 21:47:34 +00003820 return(MagickTrue);
3821}
3822
3823/*
3824%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3825% %
3826% %
3827% %
3828+ S y n c I m a g e %
3829% %
3830% %
3831% %
3832%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3833%
3834% SyncImage() initializes the red, green, and blue intensities of each pixel
3835% as defined by the colormap index.
3836%
3837% The format of the SyncImage method is:
3838%
3839% MagickBooleanType SyncImage(Image *image)
3840%
3841% A description of each parameter follows:
3842%
3843% o image: the image.
3844%
3845*/
3846
3847static inline IndexPacket PushColormapIndex(Image *image,
cristybb503372010-05-27 20:51:26 +00003848 const size_t index,MagickBooleanType *range_exception)
cristy3ed852e2009-09-05 21:47:34 +00003849{
3850 if (index < image->colors)
3851 return((IndexPacket) index);
3852 *range_exception=MagickTrue;
3853 return((IndexPacket) 0);
3854}
3855
3856MagickExport MagickBooleanType SyncImage(Image *image)
3857{
3858 CacheView
3859 *image_view;
3860
3861 ExceptionInfo
3862 *exception;
3863
cristy3ed852e2009-09-05 21:47:34 +00003864 MagickBooleanType
3865 range_exception,
3866 status;
3867
cristycb6d09b2010-06-19 01:59:36 +00003868 ssize_t
3869 y;
3870
cristy3ed852e2009-09-05 21:47:34 +00003871 assert(image != (Image *) NULL);
3872 if (image->debug != MagickFalse)
3873 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3874 assert(image->signature == MagickSignature);
3875 if (image->storage_class == DirectClass)
3876 return(MagickFalse);
3877 range_exception=MagickFalse;
3878 status=MagickTrue;
3879 exception=(&image->exception);
3880 image_view=AcquireCacheView(image);
cristy48974b92009-12-19 02:36:06 +00003881#if defined(MAGICKCORE_OPENMP_SUPPORT)
3882 #pragma omp parallel for schedule(dynamic,4) shared(status)
3883#endif
cristybb503372010-05-27 20:51:26 +00003884 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00003885 {
3886 IndexPacket
3887 index;
3888
3889 PixelPacket
3890 pixel;
3891
3892 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00003893 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00003894
cristy3ed852e2009-09-05 21:47:34 +00003895 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00003896 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00003897
cristycb6d09b2010-06-19 01:59:36 +00003898 register ssize_t
3899 x;
3900
cristy48974b92009-12-19 02:36:06 +00003901 if (status == MagickFalse)
3902 continue;
cristy3ed852e2009-09-05 21:47:34 +00003903 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3904 if (q == (PixelPacket *) NULL)
3905 {
3906 status=MagickFalse;
3907 continue;
3908 }
3909 indexes=GetCacheViewAuthenticIndexQueue(image_view);
cristybb503372010-05-27 20:51:26 +00003910 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00003911 {
cristybb503372010-05-27 20:51:26 +00003912 index=PushColormapIndex(image,(size_t) indexes[x],
cristy3ed852e2009-09-05 21:47:34 +00003913 &range_exception);
cristybb503372010-05-27 20:51:26 +00003914 pixel=image->colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +00003915 q->red=pixel.red;
3916 q->green=pixel.green;
3917 q->blue=pixel.blue;
cristyd0272592010-04-21 01:01:49 +00003918 if (image->matte != MagickFalse)
3919 q->opacity=pixel.opacity;
cristy3ed852e2009-09-05 21:47:34 +00003920 q++;
3921 }
3922 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3923 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00003924 }
3925 image_view=DestroyCacheView(image_view);
3926 if (range_exception != MagickFalse)
3927 (void) ThrowMagickException(&image->exception,GetMagickModule(),
3928 CorruptImageError,"InvalidColormapIndex","`%s'",image->filename);
3929 return(status);
3930}
cristy1626d332009-11-10 16:58:17 +00003931
3932/*
3933%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3934% %
3935% %
3936% %
3937% S y n c I m a g e S e t t i n g s %
3938% %
3939% %
3940% %
3941%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3942%
3943% SyncImageSettings() sync the image info options to the image.
3944%
3945% The format of the SyncImageSettings method is:
3946%
3947% MagickBooleanType SyncImageSettings(const ImageInfo *image_info,
3948% Image *image)
3949% MagickBooleanType SyncImagesSettings(const ImageInfo *image_info,
3950% Image *image)
3951%
3952% A description of each parameter follows:
3953%
3954% o image_info: the image info.
3955%
3956% o image: the image.
3957%
3958*/
3959
3960MagickExport MagickBooleanType SyncImagesSettings(ImageInfo *image_info,
3961 Image *images)
3962{
3963 Image
3964 *image;
3965
3966 assert(image_info != (const ImageInfo *) NULL);
3967 assert(image_info->signature == MagickSignature);
3968 assert(images != (Image *) NULL);
3969 assert(images->signature == MagickSignature);
3970 if (images->debug != MagickFalse)
3971 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
3972 image=images;
3973 for ( ; image != (Image *) NULL; image=GetNextImageInList(image))
3974 (void) SyncImageSettings(image_info,image);
3975 (void) DeleteImageOption(image_info,"page");
3976 return(MagickTrue);
3977}
3978
3979MagickExport MagickBooleanType SyncImageSettings(const ImageInfo *image_info,
3980 Image *image)
3981{
3982 char
3983 property[MaxTextExtent];
3984
3985 const char
cristy9a703812010-07-26 14:50:29 +00003986 *option,
3987 *value;
cristy1626d332009-11-10 16:58:17 +00003988
3989 GeometryInfo
3990 geometry_info;
3991
3992 MagickStatusType
3993 flags;
3994
cristy19eb6412010-04-23 14:42:29 +00003995 ResolutionType
3996 units;
3997
cristy1626d332009-11-10 16:58:17 +00003998 /*
3999 Sync image options.
4000 */
4001 assert(image_info != (const ImageInfo *) NULL);
4002 assert(image_info->signature == MagickSignature);
4003 assert(image != (Image *) NULL);
4004 assert(image->signature == MagickSignature);
4005 if (image->debug != MagickFalse)
4006 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4007 option=GetImageOption(image_info,"background");
4008 if (option != (const char *) NULL)
4009 (void) QueryColorDatabase(option,&image->background_color,
4010 &image->exception);
4011 option=GetImageOption(image_info,"bias");
4012 if (option != (const char *) NULL)
cristyf2f27272009-12-17 14:48:46 +00004013 image->bias=SiPrefixToDouble(option,QuantumRange);
cristy1626d332009-11-10 16:58:17 +00004014 option=GetImageOption(image_info,"black-point-compensation");
4015 if (option != (const char *) NULL)
4016 image->black_point_compensation=(MagickBooleanType) ParseMagickOption(
4017 MagickBooleanOptions,MagickFalse,option);
4018 option=GetImageOption(image_info,"blue-primary");
4019 if (option != (const char *) NULL)
4020 {
4021 flags=ParseGeometry(option,&geometry_info);
4022 image->chromaticity.blue_primary.x=geometry_info.rho;
4023 image->chromaticity.blue_primary.y=geometry_info.sigma;
4024 if ((flags & SigmaValue) == 0)
4025 image->chromaticity.blue_primary.y=image->chromaticity.blue_primary.x;
4026 }
4027 option=GetImageOption(image_info,"bordercolor");
4028 if (option != (const char *) NULL)
4029 (void) QueryColorDatabase(option,&image->border_color,&image->exception);
4030 option=GetImageOption(image_info,"colors");
4031 if (option != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00004032 image->colors=StringToUnsignedLong(option);
cristy1626d332009-11-10 16:58:17 +00004033 option=GetImageOption(image_info,"compose");
4034 if (option != (const char *) NULL)
4035 image->compose=(CompositeOperator) ParseMagickOption(MagickComposeOptions,
4036 MagickFalse,option);
4037 option=GetImageOption(image_info,"compress");
4038 if (option != (const char *) NULL)
4039 image->compression=(CompressionType) ParseMagickOption(
4040 MagickCompressOptions,MagickFalse,option);
4041 option=GetImageOption(image_info,"debug");
4042 if (option != (const char *) NULL)
4043 image->debug=(MagickBooleanType) ParseMagickOption(MagickBooleanOptions,
4044 MagickFalse,option);
cristydd5f5912010-07-31 23:37:23 +00004045 option=GetImageOption(image_info,"density");
4046 if (option != (const char *) NULL)
4047 {
4048 GeometryInfo
4049 geometry_info;
4050
4051 /*
4052 Set image density.
4053 */
4054 flags=ParseGeometry(option,&geometry_info);
4055 image->x_resolution=geometry_info.rho;
4056 image->y_resolution=geometry_info.sigma;
4057 if ((flags & SigmaValue) == 0)
4058 image->y_resolution=image->x_resolution;
4059 }
cristy1626d332009-11-10 16:58:17 +00004060 option=GetImageOption(image_info,"depth");
4061 if (option != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00004062 image->depth=StringToUnsignedLong(option);
cristy1626d332009-11-10 16:58:17 +00004063 option=GetImageOption(image_info,"endian");
4064 if (option != (const char *) NULL)
4065 image->endian=(EndianType) ParseMagickOption(MagickEndianOptions,
4066 MagickFalse,option);
4067 if (image_info->extract != (char *) NULL)
4068 (void) ParseAbsoluteGeometry(image_info->extract,&image->extract_info);
4069 option=GetImageOption(image_info,"filter");
4070 if (option != (const char *) NULL)
4071 image->filter=(FilterTypes) ParseMagickOption(MagickFilterOptions,
4072 MagickFalse,option);
4073 option=GetImageOption(image_info,"fuzz");
4074 if (option != (const char *) NULL)
cristyf2f27272009-12-17 14:48:46 +00004075 image->fuzz=SiPrefixToDouble(option,QuantumRange);
cristy1626d332009-11-10 16:58:17 +00004076 option=GetImageOption(image_info,"gravity");
4077 if (option != (const char *) NULL)
4078 image->gravity=(GravityType) ParseMagickOption(MagickGravityOptions,
4079 MagickFalse,option);
4080 option=GetImageOption(image_info,"green-primary");
4081 if (option != (const char *) NULL)
4082 {
4083 flags=ParseGeometry(option,&geometry_info);
4084 image->chromaticity.green_primary.x=geometry_info.rho;
4085 image->chromaticity.green_primary.y=geometry_info.sigma;
4086 if ((flags & SigmaValue) == 0)
4087 image->chromaticity.green_primary.y=image->chromaticity.green_primary.x;
4088 }
4089 option=GetImageOption(image_info,"intent");
4090 if (option != (const char *) NULL)
4091 image->rendering_intent=(RenderingIntent) ParseMagickOption(
4092 MagickIntentOptions,MagickFalse,option);
4093 option=GetImageOption(image_info,"interlace");
4094 if (option != (const char *) NULL)
4095 image->interlace=(InterlaceType) ParseMagickOption(MagickInterlaceOptions,
4096 MagickFalse,option);
4097 option=GetImageOption(image_info,"interpolate");
4098 if (option != (const char *) NULL)
4099 image->interpolate=(InterpolatePixelMethod) ParseMagickOption(
4100 MagickInterpolateOptions,MagickFalse,option);
4101 option=GetImageOption(image_info,"loop");
4102 if (option != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00004103 image->iterations=StringToUnsignedLong(option);
cristy1626d332009-11-10 16:58:17 +00004104 option=GetImageOption(image_info,"mattecolor");
4105 if (option != (const char *) NULL)
4106 (void) QueryColorDatabase(option,&image->matte_color,&image->exception);
4107 option=GetImageOption(image_info,"orient");
4108 if (option != (const char *) NULL)
4109 image->orientation=(OrientationType) ParseMagickOption(
4110 MagickOrientationOptions,MagickFalse,option);
cristy9a703812010-07-26 14:50:29 +00004111 option=GetImageOption(image_info,"page");
4112 if (option != (const char *) NULL)
4113 {
4114 char
4115 *geometry;
4116
4117 geometry=GetPageGeometry(option);
4118 flags=ParseAbsoluteGeometry(geometry,&image->page);
4119 geometry=DestroyString(geometry);
4120 }
cristy1626d332009-11-10 16:58:17 +00004121 option=GetImageOption(image_info,"quality");
4122 if (option != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00004123 image->quality=StringToUnsignedLong(option);
cristy1626d332009-11-10 16:58:17 +00004124 option=GetImageOption(image_info,"red-primary");
4125 if (option != (const char *) NULL)
4126 {
4127 flags=ParseGeometry(option,&geometry_info);
4128 image->chromaticity.red_primary.x=geometry_info.rho;
4129 image->chromaticity.red_primary.y=geometry_info.sigma;
4130 if ((flags & SigmaValue) == 0)
4131 image->chromaticity.red_primary.y=image->chromaticity.red_primary.x;
4132 }
4133 if (image_info->quality != UndefinedCompressionQuality)
4134 image->quality=image_info->quality;
4135 option=GetImageOption(image_info,"scene");
4136 if (option != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00004137 image->scene=StringToUnsignedLong(option);
cristy1626d332009-11-10 16:58:17 +00004138 option=GetImageOption(image_info,"taint");
4139 if (option != (const char *) NULL)
4140 image->taint=(MagickBooleanType) ParseMagickOption(MagickBooleanOptions,
4141 MagickFalse,option);
4142 option=GetImageOption(image_info,"tile-offset");
4143 if (option != (const char *) NULL)
4144 {
4145 char
4146 *geometry;
4147
4148 geometry=GetPageGeometry(option);
4149 flags=ParseAbsoluteGeometry(geometry,&image->tile_offset);
4150 geometry=DestroyString(geometry);
4151 }
4152 option=GetImageOption(image_info,"transparent-color");
4153 if (option != (const char *) NULL)
4154 (void) QueryColorDatabase(option,&image->transparent_color,
4155 &image->exception);
4156 option=GetImageOption(image_info,"type");
4157 if (option != (const char *) NULL)
4158 image->type=(ImageType) ParseMagickOption(MagickTypeOptions,MagickFalse,
4159 option);
4160 option=GetImageOption(image_info,"units");
4161 if (option != (const char *) NULL)
cristy19eb6412010-04-23 14:42:29 +00004162 units=(ResolutionType) ParseMagickOption(MagickResolutionOptions,
cristy1626d332009-11-10 16:58:17 +00004163 MagickFalse,option);
cristy19eb6412010-04-23 14:42:29 +00004164 else
4165 units = image_info->units;
4166 if (units != UndefinedResolution)
cristy1626d332009-11-10 16:58:17 +00004167 {
cristy19eb6412010-04-23 14:42:29 +00004168 if (image->units != units)
cristy1626d332009-11-10 16:58:17 +00004169 switch (image->units)
4170 {
4171 case PixelsPerInchResolution:
4172 {
cristy19eb6412010-04-23 14:42:29 +00004173 if (units == PixelsPerCentimeterResolution)
cristy1626d332009-11-10 16:58:17 +00004174 {
4175 image->x_resolution/=2.54;
4176 image->y_resolution/=2.54;
4177 }
4178 break;
4179 }
4180 case PixelsPerCentimeterResolution:
4181 {
cristy19eb6412010-04-23 14:42:29 +00004182 if (units == PixelsPerInchResolution)
cristy1626d332009-11-10 16:58:17 +00004183 {
cristybb503372010-05-27 20:51:26 +00004184 image->x_resolution=(double) ((size_t) (100.0*2.54*
cristy1f9ce9f2010-04-28 11:55:12 +00004185 image->x_resolution+0.5))/100.0;
cristybb503372010-05-27 20:51:26 +00004186 image->y_resolution=(double) ((size_t) (100.0*2.54*
cristy1f9ce9f2010-04-28 11:55:12 +00004187 image->y_resolution+0.5))/100.0;
cristy1626d332009-11-10 16:58:17 +00004188 }
4189 break;
4190 }
4191 default:
4192 break;
4193 }
cristy19eb6412010-04-23 14:42:29 +00004194 image->units=units;
cristy1626d332009-11-10 16:58:17 +00004195 }
4196 option=GetImageOption(image_info,"white-point");
4197 if (option != (const char *) NULL)
4198 {
4199 flags=ParseGeometry(option,&geometry_info);
4200 image->chromaticity.white_point.x=geometry_info.rho;
4201 image->chromaticity.white_point.y=geometry_info.sigma;
4202 if ((flags & SigmaValue) == 0)
4203 image->chromaticity.white_point.y=image->chromaticity.white_point.x;
4204 }
4205 ResetImageOptionIterator(image_info);
4206 for (option=GetNextImageOption(image_info); option != (const char *) NULL; )
4207 {
4208 value=GetImageOption(image_info,option);
4209 if (value != (const char *) NULL)
4210 {
4211 (void) FormatMagickString(property,MaxTextExtent,"%s",option);
4212 (void) SetImageArtifact(image,property,value);
4213 }
4214 option=GetNextImageOption(image_info);
4215 }
4216 return(MagickTrue);
4217}