blob: 56d6dd7a09a2e6938a342de756bdf525ccc49493 [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(),"...");
cristy90823212009-12-12 20:48:33 +0000160 image=(Image *) AcquireAlignedMemory(1,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,"density");
267 if (option != (const char *) NULL)
268 {
269 GeometryInfo
270 geometry_info;
271
272 /*
273 Set image density.
274 */
275 flags=ParseGeometry(option,&geometry_info);
276 image->x_resolution=geometry_info.rho;
277 image->y_resolution=geometry_info.sigma;
278 if ((flags & SigmaValue) == 0)
279 image->y_resolution=image->x_resolution;
280 }
281 option=GetImageOption(image_info,"delay");
282 if (option != (const char *) NULL)
283 {
284 GeometryInfo
285 geometry_info;
286
287 flags=ParseGeometry(option,&geometry_info);
288 if ((flags & GreaterValue) != 0)
289 {
290 if (image->delay > (size_t) floor(geometry_info.rho+0.5))
291 image->delay=(size_t) floor(geometry_info.rho+0.5);
292 }
293 else
294 if ((flags & LessValue) != 0)
295 {
296 if (image->delay < (size_t) floor(geometry_info.rho+0.5))
297 image->ticks_per_second=(ssize_t) floor(geometry_info.sigma+0.5);
298 }
299 else
300 image->delay=(size_t) floor(geometry_info.rho+0.5);
301 if ((flags & SigmaValue) != 0)
302 image->ticks_per_second=(ssize_t) floor(geometry_info.sigma+0.5);
303 }
304 option=GetImageOption(image_info,"dispose");
305 if (option != (const char *) NULL)
306 image->dispose=(DisposeType) ParseMagickOption(MagickDisposeOptions,
307 MagickFalse,option);
cristy3ed852e2009-09-05 21:47:34 +0000308 return(image);
309}
310
311/*
312%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
313% %
314% %
315% %
cristy3ed852e2009-09-05 21:47:34 +0000316% A c q u i r e I m a g e I n f o %
317% %
318% %
319% %
320%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
321%
322% AcquireImageInfo() allocates the ImageInfo structure.
323%
324% The format of the AcquireImageInfo method is:
325%
326% ImageInfo *AcquireImageInfo(void)
327%
328*/
329MagickExport ImageInfo *AcquireImageInfo(void)
330{
331 ImageInfo
332 *image_info;
333
cristy90823212009-12-12 20:48:33 +0000334 image_info=(ImageInfo *) AcquireAlignedMemory(1,sizeof(*image_info));
cristy3ed852e2009-09-05 21:47:34 +0000335 if (image_info == (ImageInfo *) NULL)
336 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
337 GetImageInfo(image_info);
338 return(image_info);
339}
340
341/*
342%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
343% %
344% %
345% %
346% A c q u i r e N e x t I m a g e %
347% %
348% %
349% %
350%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
351%
352% AcquireNextImage() initializes the next image in a sequence to
353% default values. The next member of image points to the newly allocated
354% image. If there is a memory shortage, next is assigned NULL.
355%
356% The format of the AcquireNextImage method is:
357%
358% void AcquireNextImage(const ImageInfo *image_info,Image *image)
359%
360% A description of each parameter follows:
361%
362% o image_info: Many of the image default values are set from this
363% structure. For example, filename, compression, depth, background color,
364% and others.
365%
366% o image: the image.
367%
368*/
369MagickExport void AcquireNextImage(const ImageInfo *image_info,Image *image)
370{
371 /*
372 Allocate image structure.
373 */
374 assert(image != (Image *) NULL);
375 assert(image->signature == MagickSignature);
376 if (image->debug != MagickFalse)
377 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
378 image->next=AcquireImage(image_info);
379 if (GetNextImageInList(image) == (Image *) NULL)
380 return;
381 (void) CopyMagickString(GetNextImageInList(image)->filename,image->filename,
382 MaxTextExtent);
383 if (image_info != (ImageInfo *) NULL)
384 (void) CopyMagickString(GetNextImageInList(image)->filename,
385 image_info->filename,MaxTextExtent);
386 DestroyBlob(GetNextImageInList(image));
387 image->next->blob=ReferenceBlob(image->blob);
388 image->next->endian=image->endian;
389 image->next->scene=image->scene+1;
390 image->next->previous=image;
391}
392
393/*
394%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
395% %
396% %
397% %
398% A p p e n d I m a g e s %
399% %
400% %
401% %
402%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
403%
404% AppendImages() takes all images from the current image pointer to the end
405% of the image list and appends them to each other top-to-bottom if the
406% stack parameter is true, otherwise left-to-right.
407%
408% The current gravity setting now effects how the image is justified in the
409% final image.
410%
411% The format of the AppendImages method is:
412%
413% Image *AppendImages(const Image *image,const MagickBooleanType stack,
414% ExceptionInfo *exception)
415%
416% A description of each parameter follows:
417%
418% o image: the image sequence.
419%
420% o stack: A value other than 0 stacks the images top-to-bottom.
421%
422% o exception: return any errors or warnings in this structure.
423%
424*/
425MagickExport Image *AppendImages(const Image *image,
426 const MagickBooleanType stack,ExceptionInfo *exception)
427{
428#define AppendImageTag "Append/Image"
429
430 CacheView
431 *append_view,
432 *image_view;
433
434 Image
435 *append_image;
436
cristy3ed852e2009-09-05 21:47:34 +0000437 MagickBooleanType
438 matte,
439 proceed,
440 status;
441
cristybb503372010-05-27 20:51:26 +0000442 MagickOffsetType
443 n;
444
cristy3ed852e2009-09-05 21:47:34 +0000445 RectangleInfo
446 geometry;
447
448 register const Image
449 *next;
450
cristybb503372010-05-27 20:51:26 +0000451 size_t
cristy3ed852e2009-09-05 21:47:34 +0000452 height,
453 number_images,
454 width;
455
cristybb503372010-05-27 20:51:26 +0000456 ssize_t
457 x_offset,
458 y,
459 y_offset;
460
cristy3ed852e2009-09-05 21:47:34 +0000461 /*
462 Ensure the image have the same column width.
463 */
464 assert(image != (Image *) NULL);
465 assert(image->signature == MagickSignature);
466 if (image->debug != MagickFalse)
467 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
468 assert(exception != (ExceptionInfo *) NULL);
469 assert(exception->signature == MagickSignature);
470 matte=image->matte;
471 number_images=1;
472 width=image->columns;
473 height=image->rows;
474 next=GetNextImageInList(image);
475 for ( ; next != (Image *) NULL; next=GetNextImageInList(next))
476 {
477 if (next->matte != MagickFalse)
478 matte=MagickTrue;
479 number_images++;
480 if (stack != MagickFalse)
481 {
482 if (next->columns > width)
483 width=next->columns;
484 height+=next->rows;
485 continue;
486 }
487 width+=next->columns;
488 if (next->rows > height)
489 height=next->rows;
490 }
491 /*
492 Initialize append next attributes.
493 */
494 append_image=CloneImage(image,width,height,MagickTrue,exception);
495 if (append_image == (Image *) NULL)
496 return((Image *) NULL);
497 if (SetImageStorageClass(append_image,DirectClass) == MagickFalse)
498 {
499 InheritException(exception,&append_image->exception);
500 append_image=DestroyImage(append_image);
501 return((Image *) NULL);
502 }
503 append_image->matte=matte;
504 (void) SetImageBackgroundColor(append_image);
505 status=MagickTrue;
506 x_offset=0;
507 y_offset=0;
508 append_view=AcquireCacheView(append_image);
cristybb503372010-05-27 20:51:26 +0000509 for (n=0; n < (MagickOffsetType) number_images; n++)
cristy3ed852e2009-09-05 21:47:34 +0000510 {
511 SetGeometry(append_image,&geometry);
512 GravityAdjustGeometry(image->columns,image->rows,image->gravity,&geometry);
513 if (stack != MagickFalse)
514 x_offset-=geometry.x;
515 else
516 y_offset-=geometry.y;
517 image_view=AcquireCacheView(image);
cristyb5d5f722009-11-04 03:03:49 +0000518#if defined(MAGICKCORE_OPENMP_SUPPORT)
519 #pragma omp parallel for schedule(dynamic,4) shared(status)
cristy3ed852e2009-09-05 21:47:34 +0000520#endif
cristybb503372010-05-27 20:51:26 +0000521 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000522 {
523 MagickBooleanType
524 sync;
525
526 register const IndexPacket
cristyc47d1f82009-11-26 01:44:43 +0000527 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +0000528
529 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000530 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +0000531
532 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +0000533 *restrict append_indexes;
cristy3ed852e2009-09-05 21:47:34 +0000534
cristy3ed852e2009-09-05 21:47:34 +0000535 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +0000536 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +0000537
cristycb6d09b2010-06-19 01:59:36 +0000538 register ssize_t
539 x;
540
cristy3ed852e2009-09-05 21:47:34 +0000541 if (status == MagickFalse)
542 continue;
543 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
544 q=QueueCacheViewAuthenticPixels(append_view,x_offset,y+y_offset,
545 image->columns,1,exception);
546 if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
547 {
548 status=MagickFalse;
549 continue;
550 }
551 indexes=GetCacheViewVirtualIndexQueue(image_view);
552 append_indexes=GetCacheViewAuthenticIndexQueue(append_view);
cristybb503372010-05-27 20:51:26 +0000553 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000554 {
cristyce70c172010-01-07 17:15:30 +0000555 SetRedPixelComponent(q,GetRedPixelComponent(p));
556 SetGreenPixelComponent(q,GetGreenPixelComponent(p));
557 SetBluePixelComponent(q,GetBluePixelComponent(p));
558 SetOpacityPixelComponent(q,OpaqueOpacity);
cristy3ed852e2009-09-05 21:47:34 +0000559 if (image->matte != MagickFalse)
cristyce70c172010-01-07 17:15:30 +0000560 SetOpacityPixelComponent(q,GetOpacityPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +0000561 if (image->colorspace == CMYKColorspace)
562 append_indexes[x]=indexes[x];
563 p++;
564 q++;
565 }
566 sync=SyncCacheViewAuthenticPixels(append_view,exception);
567 if (sync == MagickFalse)
cristya65f35b2010-04-20 01:10:41 +0000568 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +0000569 }
570 image_view=DestroyCacheView(image_view);
571 proceed=SetImageProgress(image,AppendImageTag,n,number_images);
572 if (proceed == MagickFalse)
573 break;
574 if (stack == MagickFalse)
575 {
cristyeaedf062010-05-29 22:36:02 +0000576 x_offset+=(ssize_t) image->columns;
cristy3ed852e2009-09-05 21:47:34 +0000577 y_offset=0;
578 }
579 else
580 {
581 x_offset=0;
cristyeaedf062010-05-29 22:36:02 +0000582 y_offset+=(ssize_t) image->rows;
cristy3ed852e2009-09-05 21:47:34 +0000583 }
584 image=GetNextImageInList(image);
585 }
586 append_view=DestroyCacheView(append_view);
587 if (status == MagickFalse)
588 append_image=DestroyImage(append_image);
589 return(append_image);
590}
591
592/*
593%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
594% %
595% %
596% %
cristy3ed852e2009-09-05 21:47:34 +0000597% C a t c h I m a g e E x c e p t i o n %
598% %
599% %
600% %
601%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
602%
603% CatchImageException() returns if no exceptions are found in the image
604% sequence, otherwise it determines the most severe exception and reports
605% it as a warning or error depending on the severity.
606%
607% The format of the CatchImageException method is:
608%
609% ExceptionType CatchImageException(Image *image)
610%
611% A description of each parameter follows:
612%
613% o image: An image sequence.
614%
615*/
616MagickExport ExceptionType CatchImageException(Image *image)
617{
618 ExceptionInfo
619 *exception;
620
621 ExceptionType
622 severity;
623
624 assert(image != (const Image *) NULL);
625 assert(image->signature == MagickSignature);
626 if (image->debug != MagickFalse)
627 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
628 exception=AcquireExceptionInfo();
629 GetImageException(image,exception);
630 CatchException(exception);
631 severity=exception->severity;
632 exception=DestroyExceptionInfo(exception);
633 return(severity);
634}
635
636/*
637%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
638% %
639% %
640% %
641% C l i p I m a g e P a t h %
642% %
643% %
644% %
645%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
646%
647% ClipImagePath() sets the image clip mask based any clipping path information
648% if it exists.
649%
650% The format of the ClipImagePath method is:
651%
652% MagickBooleanType ClipImagePath(Image *image,const char *pathname,
653% const MagickBooleanType inside)
654%
655% A description of each parameter follows:
656%
657% o image: the image.
658%
659% o pathname: name of clipping path resource. If name is preceded by #, use
660% clipping path numbered by name.
661%
662% o inside: if non-zero, later operations take effect inside clipping path.
663% Otherwise later operations take effect outside clipping path.
664%
665*/
666
667MagickExport MagickBooleanType ClipImage(Image *image)
668{
669 return(ClipImagePath(image,"#1",MagickTrue));
670}
671
672MagickExport MagickBooleanType ClipImagePath(Image *image,const char *pathname,
673 const MagickBooleanType inside)
674{
675#define ClipImagePathTag "ClipPath/Image"
676
677 char
678 *property;
679
680 const char
681 *value;
682
683 Image
684 *clip_mask;
685
686 ImageInfo
687 *image_info;
688
689 assert(image != (const Image *) NULL);
690 assert(image->signature == MagickSignature);
691 if (image->debug != MagickFalse)
692 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
693 assert(pathname != NULL);
694 property=AcquireString(pathname);
695 (void) FormatMagickString(property,MaxTextExtent,"8BIM:1999,2998:%s",
696 pathname);
697 value=GetImageProperty(image,property);
698 property=DestroyString(property);
699 if (value == (const char *) NULL)
700 {
701 ThrowFileException(&image->exception,OptionError,"NoClipPathDefined",
702 image->filename);
703 return(MagickFalse);
704 }
705 image_info=AcquireImageInfo();
706 (void) CopyMagickString(image_info->filename,image->filename,MaxTextExtent);
707 (void) ConcatenateMagickString(image_info->filename,pathname,MaxTextExtent);
708 clip_mask=BlobToImage(image_info,value,strlen(value),&image->exception);
709 image_info=DestroyImageInfo(image_info);
710 if (clip_mask == (Image *) NULL)
711 return(MagickFalse);
712 if (clip_mask->storage_class == PseudoClass)
713 {
714 (void) SyncImage(clip_mask);
715 if (SetImageStorageClass(clip_mask,DirectClass) == MagickFalse)
716 return(MagickFalse);
717 }
718 if (inside == MagickFalse)
719 (void) NegateImage(clip_mask,MagickFalse);
720 (void) FormatMagickString(clip_mask->magick_filename,MaxTextExtent,
721 "8BIM:1999,2998:%s\nPS",pathname);
722 (void) SetImageClipMask(image,clip_mask);
723 clip_mask=DestroyImage(clip_mask);
724 return(MagickTrue);
725}
726
727/*
728%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
729% %
730% %
731% %
732% C l o n e I m a g e %
733% %
734% %
735% %
736%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
737%
738% CloneImage() copies an image and returns the copy as a new image object.
739% If the specified columns and rows is 0, an exact copy of the image is
740% returned, otherwise the pixel data is undefined and must be initialized
741% with the QueueAuthenticPixels() and SyncAuthenticPixels() methods. On
742% failure, a NULL image is returned and exception describes the reason for the
743% failure.
744%
745% The format of the CloneImage method is:
746%
cristybb503372010-05-27 20:51:26 +0000747% Image *CloneImage(const Image *image,const size_t columns,
748% const size_t rows,const MagickBooleanType orphan,
cristy3ed852e2009-09-05 21:47:34 +0000749% ExceptionInfo *exception)
750%
751% A description of each parameter follows:
752%
753% o image: the image.
754%
755% o columns: the number of columns in the cloned image.
756%
757% o rows: the number of rows in the cloned image.
758%
759% o detach: With a value other than 0, the cloned image is detached from
760% its parent I/O stream.
761%
762% o exception: return any errors or warnings in this structure.
763%
764*/
cristybb503372010-05-27 20:51:26 +0000765MagickExport Image *CloneImage(const Image *image,const size_t columns,
766 const size_t rows,const MagickBooleanType detach,
cristy3ed852e2009-09-05 21:47:34 +0000767 ExceptionInfo *exception)
768{
769 Image
770 *clone_image;
771
772 MagickRealType
773 scale;
774
775 size_t
776 length;
777
778 /*
779 Clone the image.
780 */
781 assert(image != (const Image *) NULL);
782 assert(image->signature == MagickSignature);
783 if (image->debug != MagickFalse)
784 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
785 assert(exception != (ExceptionInfo *) NULL);
786 assert(exception->signature == MagickSignature);
cristy90823212009-12-12 20:48:33 +0000787 clone_image=(Image *) AcquireAlignedMemory(1,sizeof(*clone_image));
cristy3ed852e2009-09-05 21:47:34 +0000788 if (clone_image == (Image *) NULL)
789 ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
790 (void) ResetMagickMemory(clone_image,0,sizeof(*clone_image));
791 clone_image->signature=MagickSignature;
792 clone_image->storage_class=image->storage_class;
793 clone_image->colorspace=image->colorspace;
794 clone_image->matte=image->matte;
795 clone_image->columns=image->columns;
796 clone_image->rows=image->rows;
797 clone_image->dither=image->dither;
798 if (image->colormap != (PixelPacket *) NULL)
799 {
800 /*
801 Allocate and copy the image colormap.
802 */
803 clone_image->colors=image->colors;
804 length=(size_t) image->colors;
805 clone_image->colormap=(PixelPacket *) AcquireQuantumMemory(length,
806 sizeof(*clone_image->colormap));
807 if (clone_image->colormap == (PixelPacket *) NULL)
808 ThrowImageException(ResourceLimitError,"MemoryAllocationFailed");
809 (void) CopyMagickMemory(clone_image->colormap,image->colormap,length*
810 sizeof(*clone_image->colormap));
811 }
812 (void) CloneImageProfiles(clone_image,image);
813 (void) CloneImageProperties(clone_image,image);
814 (void) CloneImageArtifacts(clone_image,image);
815 GetTimerInfo(&clone_image->timer);
816 GetExceptionInfo(&clone_image->exception);
817 InheritException(&clone_image->exception,&image->exception);
818 if (image->ascii85 != (void *) NULL)
819 Ascii85Initialize(clone_image);
820 clone_image->magick_columns=image->magick_columns;
821 clone_image->magick_rows=image->magick_rows;
822 clone_image->type=image->type;
823 (void) CopyMagickString(clone_image->magick_filename,image->magick_filename,
824 MaxTextExtent);
825 (void) CopyMagickString(clone_image->magick,image->magick,MaxTextExtent);
826 (void) CopyMagickString(clone_image->filename,image->filename,MaxTextExtent);
827 clone_image->progress_monitor=image->progress_monitor;
828 clone_image->client_data=image->client_data;
829 clone_image->reference_count=1;
830 clone_image->next=NewImageList();
831 clone_image->previous=NewImageList();
832 clone_image->list=NewImageList();
833 clone_image->clip_mask=NewImageList();
834 clone_image->mask=NewImageList();
835 if (detach == MagickFalse)
836 clone_image->blob=ReferenceBlob(image->blob);
837 else
838 clone_image->blob=CloneBlobInfo((BlobInfo *) NULL);
cristy73724512010-04-12 14:43:14 +0000839 clone_image->ping=image->ping;
cristy3ed852e2009-09-05 21:47:34 +0000840 clone_image->debug=IsEventLogging();
841 clone_image->semaphore=AllocateSemaphoreInfo();
842 if ((columns == 0) && (rows == 0))
843 {
844 if (image->montage != (char *) NULL)
845 (void) CloneString(&clone_image->montage,image->montage);
846 if (image->directory != (char *) NULL)
847 (void) CloneString(&clone_image->directory,image->directory);
848 if (image->clip_mask != (Image *) NULL)
849 clone_image->clip_mask=CloneImage(image->clip_mask,0,0,MagickTrue,
850 exception);
851 if (image->mask != (Image *) NULL)
852 clone_image->mask=CloneImage(image->mask,0,0,MagickTrue,exception);
853 clone_image->cache=ReferencePixelCache(image->cache);
854 return(clone_image);
855 }
856 scale=(MagickRealType) columns/(MagickRealType) image->columns;
cristybb503372010-05-27 20:51:26 +0000857 clone_image->page.width=(size_t) floor(scale*image->page.width+0.5);
858 clone_image->page.x=(ssize_t) ceil(scale*image->page.x-0.5);
859 clone_image->tile_offset.x=(ssize_t) ceil(scale*image->tile_offset.x-0.5);
cristy3ed852e2009-09-05 21:47:34 +0000860 scale=(MagickRealType) rows/(MagickRealType) image->rows;
cristybb503372010-05-27 20:51:26 +0000861 clone_image->page.height=(size_t) floor(scale*image->page.height+0.5);
862 clone_image->page.y=(ssize_t) ceil(scale*image->page.y-0.5);
863 clone_image->tile_offset.y=(ssize_t) ceil(scale*image->tile_offset.y-0.5);
cristy3ed852e2009-09-05 21:47:34 +0000864 clone_image->columns=columns;
865 clone_image->rows=rows;
866 clone_image->cache=ClonePixelCache(image->cache);
867 return(clone_image);
868}
869
870/*
871%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
872% %
873% %
874% %
875% C l o n e I m a g e I n f o %
876% %
877% %
878% %
879%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
880%
881% CloneImageInfo() makes a copy of the given image info structure. If
882% NULL is specified, a new image info structure is created initialized to
883% default values.
884%
885% The format of the CloneImageInfo method is:
886%
887% ImageInfo *CloneImageInfo(const ImageInfo *image_info)
888%
889% A description of each parameter follows:
890%
891% o image_info: the image info.
892%
893*/
894MagickExport ImageInfo *CloneImageInfo(const ImageInfo *image_info)
895{
896 ImageInfo
897 *clone_info;
898
899 clone_info=AcquireImageInfo();
900 if (image_info == (ImageInfo *) NULL)
901 return(clone_info);
902 clone_info->compression=image_info->compression;
903 clone_info->temporary=image_info->temporary;
904 clone_info->adjoin=image_info->adjoin;
905 clone_info->antialias=image_info->antialias;
906 clone_info->scene=image_info->scene;
907 clone_info->number_scenes=image_info->number_scenes;
908 clone_info->depth=image_info->depth;
909 if (image_info->size != (char *) NULL)
910 (void) CloneString(&clone_info->size,image_info->size);
911 if (image_info->extract != (char *) NULL)
912 (void) CloneString(&clone_info->extract,image_info->extract);
913 if (image_info->scenes != (char *) NULL)
914 (void) CloneString(&clone_info->scenes,image_info->scenes);
915 if (image_info->page != (char *) NULL)
916 (void) CloneString(&clone_info->page,image_info->page);
917 clone_info->interlace=image_info->interlace;
918 clone_info->endian=image_info->endian;
919 clone_info->units=image_info->units;
920 clone_info->quality=image_info->quality;
921 if (image_info->sampling_factor != (char *) NULL)
922 (void) CloneString(&clone_info->sampling_factor,
923 image_info->sampling_factor);
924 if (image_info->server_name != (char *) NULL)
925 (void) CloneString(&clone_info->server_name,image_info->server_name);
926 if (image_info->font != (char *) NULL)
927 (void) CloneString(&clone_info->font,image_info->font);
928 if (image_info->texture != (char *) NULL)
929 (void) CloneString(&clone_info->texture,image_info->texture);
930 if (image_info->density != (char *) NULL)
931 (void) CloneString(&clone_info->density,image_info->density);
932 clone_info->pointsize=image_info->pointsize;
933 clone_info->fuzz=image_info->fuzz;
934 clone_info->pen=image_info->pen;
935 clone_info->background_color=image_info->background_color;
936 clone_info->border_color=image_info->border_color;
937 clone_info->matte_color=image_info->matte_color;
938 clone_info->transparent_color=image_info->transparent_color;
939 clone_info->dither=image_info->dither;
940 clone_info->monochrome=image_info->monochrome;
941 clone_info->colors=image_info->colors;
942 clone_info->colorspace=image_info->colorspace;
943 clone_info->type=image_info->type;
944 clone_info->orientation=image_info->orientation;
945 clone_info->preview_type=image_info->preview_type;
946 clone_info->group=image_info->group;
947 clone_info->ping=image_info->ping;
948 clone_info->verbose=image_info->verbose;
949 if (image_info->view != (char *) NULL)
950 (void) CloneString(&clone_info->view,image_info->view);
951 if (image_info->authenticate != (char *) NULL)
952 (void) CloneString(&clone_info->authenticate,image_info->authenticate);
953 (void) CloneImageOptions(clone_info,image_info);
954 clone_info->progress_monitor=image_info->progress_monitor;
955 clone_info->client_data=image_info->client_data;
956 clone_info->cache=image_info->cache;
957 if (image_info->cache != (void *) NULL)
958 clone_info->cache=ReferencePixelCache(image_info->cache);
959 if (image_info->profile != (void *) NULL)
960 clone_info->profile=(void *) CloneStringInfo((StringInfo *)
961 image_info->profile);
962 SetImageInfoFile(clone_info,image_info->file);
963 SetImageInfoBlob(clone_info,image_info->blob,image_info->length);
964 clone_info->stream=image_info->stream;
965 clone_info->virtual_pixel_method=image_info->virtual_pixel_method;
966 (void) CopyMagickString(clone_info->magick,image_info->magick,MaxTextExtent);
967 (void) CopyMagickString(clone_info->unique,image_info->unique,MaxTextExtent);
968 (void) CopyMagickString(clone_info->zero,image_info->zero,MaxTextExtent);
969 (void) CopyMagickString(clone_info->filename,image_info->filename,
970 MaxTextExtent);
971 clone_info->subimage=image_info->scene; /* deprecated */
972 clone_info->subrange=image_info->number_scenes; /* deprecated */
973 clone_info->channel=image_info->channel;
974 clone_info->debug=IsEventLogging();
975 clone_info->signature=image_info->signature;
976 return(clone_info);
977}
978
979/*
980%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
981% %
982% %
983% %
984% C o m b i n e I m a g e s %
985% %
986% %
987% %
988%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
989%
990% CombineImages() combines one or more images into a single image. The
991% grayscale value of the pixels of each image in the sequence is assigned in
992% order to the specified channels of the combined image. The typical
993% ordering would be image 1 => Red, 2 => Green, 3 => Blue, etc.
994%
995% The format of the CombineImages method is:
996%
997% Image *CombineImages(const Image *image,const ChannelType channel,
998% ExceptionInfo *exception)
999%
1000% A description of each parameter follows:
1001%
1002% o image: the image.
1003%
1004% o exception: return any errors or warnings in this structure.
1005%
1006*/
1007MagickExport Image *CombineImages(const Image *image,const ChannelType channel,
1008 ExceptionInfo *exception)
1009{
1010#define CombineImageTag "Combine/Image"
1011
1012 CacheView
1013 *combine_view;
1014
1015 const Image
1016 *next;
1017
1018 Image
1019 *combine_image;
1020
cristy3ed852e2009-09-05 21:47:34 +00001021 MagickBooleanType
1022 status;
1023
cristybb503372010-05-27 20:51:26 +00001024 MagickOffsetType
1025 progress;
1026
1027 ssize_t
1028 y;
1029
cristy3ed852e2009-09-05 21:47:34 +00001030 /*
1031 Ensure the image are the same size.
1032 */
1033 assert(image != (const Image *) NULL);
1034 assert(image->signature == MagickSignature);
1035 if (image->debug != MagickFalse)
1036 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1037 assert(exception != (ExceptionInfo *) NULL);
1038 assert(exception->signature == MagickSignature);
1039 for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
1040 {
1041 if ((next->columns != image->columns) || (next->rows != image->rows))
1042 ThrowImageException(OptionError,"ImagesAreNotTheSameSize");
1043 }
1044 combine_image=CloneImage(image,0,0,MagickTrue,exception);
1045 if (combine_image == (Image *) NULL)
1046 return((Image *) NULL);
1047 if (SetImageStorageClass(combine_image,DirectClass) == MagickFalse)
1048 {
1049 InheritException(exception,&combine_image->exception);
1050 combine_image=DestroyImage(combine_image);
1051 return((Image *) NULL);
1052 }
1053 if ((channel & OpacityChannel) != 0)
1054 combine_image->matte=MagickTrue;
1055 (void) SetImageBackgroundColor(combine_image);
1056 /*
1057 Combine images.
1058 */
1059 status=MagickTrue;
1060 progress=0;
1061 combine_view=AcquireCacheView(combine_image);
cristyb5d5f722009-11-04 03:03:49 +00001062#if defined(MAGICKCORE_OPENMP_SUPPORT)
1063 #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
cristy3ed852e2009-09-05 21:47:34 +00001064#endif
cristybb503372010-05-27 20:51:26 +00001065 for (y=0; y < (ssize_t) combine_image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001066 {
1067 CacheView
1068 *image_view;
1069
1070 const Image
1071 *next;
1072
1073 PixelPacket
1074 *pixels;
1075
1076 register const PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001077 *restrict p;
cristy3ed852e2009-09-05 21:47:34 +00001078
cristy3ed852e2009-09-05 21:47:34 +00001079 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00001080 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00001081
cristycb6d09b2010-06-19 01:59:36 +00001082 register ssize_t
1083 x;
1084
cristy3ed852e2009-09-05 21:47:34 +00001085 if (status == MagickFalse)
1086 continue;
1087 pixels=GetCacheViewAuthenticPixels(combine_view,0,y,combine_image->columns,
1088 1,exception);
1089 if (pixels == (PixelPacket *) NULL)
1090 {
1091 status=MagickFalse;
1092 continue;
1093 }
1094 next=image;
1095 if (((channel & RedChannel) != 0) && (next != (Image *) NULL))
1096 {
1097 image_view=AcquireCacheView(next);
1098 p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
1099 if (p == (const PixelPacket *) NULL)
1100 continue;
1101 q=pixels;
cristybb503372010-05-27 20:51:26 +00001102 for (x=0; x < (ssize_t) combine_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001103 {
cristyce70c172010-01-07 17:15:30 +00001104 SetRedPixelComponent(q,PixelIntensityToQuantum(p));
cristy3ed852e2009-09-05 21:47:34 +00001105 p++;
1106 q++;
1107 }
1108 image_view=DestroyCacheView(image_view);
1109 next=GetNextImageInList(next);
1110 }
1111 if (((channel & GreenChannel) != 0) && (next != (Image *) NULL))
1112 {
1113 image_view=AcquireCacheView(next);
1114 p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
1115 if (p == (const PixelPacket *) NULL)
1116 continue;
1117 q=pixels;
cristybb503372010-05-27 20:51:26 +00001118 for (x=0; x < (ssize_t) combine_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001119 {
cristyce70c172010-01-07 17:15:30 +00001120 SetGreenPixelComponent(q,PixelIntensityToQuantum(p));
cristy3ed852e2009-09-05 21:47:34 +00001121 p++;
1122 q++;
1123 }
1124 image_view=DestroyCacheView(image_view);
1125 next=GetNextImageInList(next);
1126 }
1127 if (((channel & BlueChannel) != 0) && (next != (Image *) NULL))
1128 {
1129 image_view=AcquireCacheView(next);
1130 p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
1131 if (p == (const PixelPacket *) NULL)
1132 continue;
1133 q=pixels;
cristybb503372010-05-27 20:51:26 +00001134 for (x=0; x < (ssize_t) combine_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001135 {
cristyce70c172010-01-07 17:15:30 +00001136 SetBluePixelComponent(q,PixelIntensityToQuantum(p));
cristy3ed852e2009-09-05 21:47:34 +00001137 p++;
1138 q++;
1139 }
1140 image_view=DestroyCacheView(image_view);
1141 next=GetNextImageInList(next);
1142 }
1143 if (((channel & OpacityChannel) != 0) && (next != (Image *) NULL))
1144 {
1145 image_view=AcquireCacheView(next);
1146 p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
1147 if (p == (const PixelPacket *) NULL)
1148 continue;
1149 q=pixels;
cristybb503372010-05-27 20:51:26 +00001150 for (x=0; x < (ssize_t) combine_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001151 {
cristyce70c172010-01-07 17:15:30 +00001152 SetOpacityPixelComponent(q,PixelIntensityToQuantum(p));
cristy3ed852e2009-09-05 21:47:34 +00001153 p++;
1154 q++;
1155 }
1156 image_view=DestroyCacheView(image_view);
1157 next=GetNextImageInList(next);
1158 }
1159 if (((channel & IndexChannel) != 0) &&
1160 (image->colorspace == CMYKColorspace) && (next != (Image *) NULL))
1161 {
1162 IndexPacket
1163 *indexes;
1164
1165 image_view=AcquireCacheView(next);
1166 p=GetCacheViewVirtualPixels(image_view,0,y,next->columns,1,exception);
1167 if (p == (const PixelPacket *) NULL)
1168 continue;
1169 indexes=GetCacheViewAuthenticIndexQueue(combine_view);
cristybb503372010-05-27 20:51:26 +00001170 for (x=0; x < (ssize_t) combine_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001171 {
1172 indexes[x]=PixelIntensityToQuantum(p);
1173 p++;
1174 }
1175 image_view=DestroyCacheView(image_view);
1176 next=GetNextImageInList(next);
1177 }
1178 if (SyncCacheViewAuthenticPixels(combine_view,exception) == MagickFalse)
1179 status=MagickFalse;
1180 if (image->progress_monitor != (MagickProgressMonitor) NULL)
1181 {
1182 MagickBooleanType
1183 proceed;
1184
cristyb5d5f722009-11-04 03:03:49 +00001185#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00001186 #pragma omp critical (MagickCore_CombineImages)
1187#endif
1188 proceed=SetImageProgress(image,CombineImageTag,progress++,
1189 combine_image->rows);
1190 if (proceed == MagickFalse)
1191 status=MagickFalse;
1192 }
1193 }
1194 combine_view=DestroyCacheView(combine_view);
1195 if (status == MagickFalse)
1196 combine_image=DestroyImage(combine_image);
1197 return(combine_image);
1198}
1199
1200/*
1201%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1202% %
1203% %
1204% %
cristy3ed852e2009-09-05 21:47:34 +00001205% D e s t r o y I m a g e %
1206% %
1207% %
1208% %
1209%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1210%
1211% DestroyImage() dereferences an image, deallocating memory associated with
1212% the image if the reference count becomes zero.
1213%
1214% The format of the DestroyImage method is:
1215%
1216% Image *DestroyImage(Image *image)
1217%
1218% A description of each parameter follows:
1219%
1220% o image: the image.
1221%
1222*/
1223MagickExport Image *DestroyImage(Image *image)
1224{
1225 MagickBooleanType
1226 destroy;
1227
1228 /*
1229 Dereference image.
1230 */
1231 assert(image != (Image *) NULL);
1232 assert(image->signature == MagickSignature);
1233 if (image->debug != MagickFalse)
1234 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1235 destroy=MagickFalse;
cristyf84a1932010-01-03 18:00:18 +00001236 LockSemaphoreInfo(image->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001237 image->reference_count--;
1238 if (image->reference_count == 0)
1239 destroy=MagickTrue;
cristyf84a1932010-01-03 18:00:18 +00001240 UnlockSemaphoreInfo(image->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001241 if (destroy == MagickFalse)
1242 return((Image *) NULL);
1243 /*
1244 Destroy image.
1245 */
1246 DestroyImagePixels(image);
1247 if (image->clip_mask != (Image *) NULL)
1248 image->clip_mask=DestroyImage(image->clip_mask);
1249 if (image->mask != (Image *) NULL)
1250 image->mask=DestroyImage(image->mask);
1251 if (image->montage != (char *) NULL)
1252 image->montage=DestroyString(image->montage);
1253 if (image->directory != (char *) NULL)
1254 image->directory=DestroyString(image->directory);
1255 if (image->colormap != (PixelPacket *) NULL)
1256 image->colormap=(PixelPacket *) RelinquishMagickMemory(image->colormap);
1257 if (image->geometry != (char *) NULL)
1258 image->geometry=DestroyString(image->geometry);
cristy3ed852e2009-09-05 21:47:34 +00001259 DestroyImageProfiles(image);
1260 DestroyImageProperties(image);
1261 DestroyImageArtifacts(image);
1262 if (image->ascii85 != (Ascii85Info*) NULL)
1263 image->ascii85=(Ascii85Info *) RelinquishMagickMemory(image->ascii85);
1264 DestroyBlob(image);
1265 (void) DestroyExceptionInfo(&image->exception);
1266 if (image->semaphore != (SemaphoreInfo *) NULL)
1267 DestroySemaphoreInfo(&image->semaphore);
1268 image->signature=(~MagickSignature);
1269 image=(Image *) RelinquishMagickMemory(image);
1270 return(image);
1271}
1272
1273/*
1274%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1275% %
1276% %
1277% %
1278% D e s t r o y I m a g e I n f o %
1279% %
1280% %
1281% %
1282%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1283%
1284% DestroyImageInfo() deallocates memory associated with an ImageInfo
1285% structure.
1286%
1287% The format of the DestroyImageInfo method is:
1288%
1289% ImageInfo *DestroyImageInfo(ImageInfo *image_info)
1290%
1291% A description of each parameter follows:
1292%
1293% o image_info: the image info.
1294%
1295*/
1296MagickExport ImageInfo *DestroyImageInfo(ImageInfo *image_info)
1297{
1298 assert(image_info != (ImageInfo *) NULL);
1299 assert(image_info->signature == MagickSignature);
1300 if (image_info->debug != MagickFalse)
1301 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1302 image_info->filename);
1303 if (image_info->size != (char *) NULL)
1304 image_info->size=DestroyString(image_info->size);
1305 if (image_info->extract != (char *) NULL)
1306 image_info->extract=DestroyString(image_info->extract);
1307 if (image_info->scenes != (char *) NULL)
1308 image_info->scenes=DestroyString(image_info->scenes);
1309 if (image_info->page != (char *) NULL)
1310 image_info->page=DestroyString(image_info->page);
1311 if (image_info->sampling_factor != (char *) NULL)
1312 image_info->sampling_factor=DestroyString(
1313 image_info->sampling_factor);
1314 if (image_info->server_name != (char *) NULL)
1315 image_info->server_name=DestroyString(
1316 image_info->server_name);
1317 if (image_info->font != (char *) NULL)
1318 image_info->font=DestroyString(image_info->font);
1319 if (image_info->texture != (char *) NULL)
1320 image_info->texture=DestroyString(image_info->texture);
1321 if (image_info->density != (char *) NULL)
1322 image_info->density=DestroyString(image_info->density);
1323 if (image_info->view != (char *) NULL)
1324 image_info->view=DestroyString(image_info->view);
1325 if (image_info->authenticate != (char *) NULL)
1326 image_info->authenticate=DestroyString(
1327 image_info->authenticate);
1328 DestroyImageOptions(image_info);
1329 if (image_info->cache != (void *) NULL)
1330 image_info->cache=DestroyPixelCache(image_info->cache);
1331 if (image_info->profile != (StringInfo *) NULL)
1332 image_info->profile=(void *) DestroyStringInfo((StringInfo *)
1333 image_info->profile);
1334 image_info->signature=(~MagickSignature);
1335 image_info=(ImageInfo *) RelinquishMagickMemory(image_info);
1336 return(image_info);
1337}
1338
1339/*
1340%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1341% %
1342% %
1343% %
1344+ D i s a s s o c i a t e I m a g e S t r e a m %
1345% %
1346% %
1347% %
1348%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1349%
1350% DisassociateImageStream() disassociates the image stream.
1351%
1352% The format of the DisassociateImageStream method is:
1353%
1354% MagickBooleanType DisassociateImageStream(const Image *image)
1355%
1356% A description of each parameter follows:
1357%
1358% o image: the image.
1359%
1360*/
1361MagickExport void DisassociateImageStream(Image *image)
1362{
1363 assert(image != (const Image *) NULL);
1364 assert(image->signature == MagickSignature);
1365 if (image->debug != MagickFalse)
1366 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1367 (void) DetachBlob(image->blob);
1368}
1369
1370/*
1371%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1372% %
1373% %
1374% %
1375% G e t I m a g e A l p h a C h a n n e l %
1376% %
1377% %
1378% %
1379%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1380%
1381% GetImageAlphaChannel() returns MagickFalse if the image alpha channel is
1382% not activated. That is, the image is RGB rather than RGBA or CMYK rather
1383% than CMYKA.
1384%
1385% The format of the GetImageAlphaChannel method is:
1386%
1387% MagickBooleanType GetImageAlphaChannel(const Image *image)
1388%
1389% A description of each parameter follows:
1390%
1391% o image: the image.
1392%
1393*/
1394MagickExport MagickBooleanType GetImageAlphaChannel(const Image *image)
1395{
1396 assert(image != (const Image *) NULL);
1397 if (image->debug != MagickFalse)
1398 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1399 assert(image->signature == MagickSignature);
1400 return(image->matte);
1401}
1402
1403/*
1404%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1405% %
1406% %
1407% %
1408% G e t I m a g e C l i p M a s k %
1409% %
1410% %
1411% %
1412%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1413%
1414% GetImageClipMask() returns the clip path associated with the image.
1415%
1416% The format of the GetImageClipMask method is:
1417%
1418% Image *GetImageClipMask(const Image *image,ExceptionInfo *exception)
1419%
1420% A description of each parameter follows:
1421%
1422% o image: the image.
1423%
1424*/
1425MagickExport Image *GetImageClipMask(const Image *image,
1426 ExceptionInfo *exception)
1427{
1428 assert(image != (const Image *) NULL);
1429 if (image->debug != MagickFalse)
1430 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1431 assert(image->signature == MagickSignature);
1432 if (image->clip_mask == (Image *) NULL)
1433 return((Image *) NULL);
1434 return(CloneImage(image->clip_mask,0,0,MagickTrue,exception));
1435}
1436
1437/*
1438%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1439% %
1440% %
1441% %
1442% G e t I m a g e E x c e p t i o n %
1443% %
1444% %
1445% %
1446%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1447%
1448% GetImageException() traverses an image sequence and returns any
1449% error more severe than noted by the exception parameter.
1450%
1451% The format of the GetImageException method is:
1452%
1453% void GetImageException(Image *image,ExceptionInfo *exception)
1454%
1455% A description of each parameter follows:
1456%
1457% o image: Specifies a pointer to a list of one or more images.
1458%
1459% o exception: return the highest severity exception.
1460%
1461*/
1462MagickExport void GetImageException(Image *image,ExceptionInfo *exception)
1463{
1464 register Image
1465 *next;
1466
1467 assert(image != (Image *) NULL);
1468 assert(image->signature == MagickSignature);
1469 if (image->debug != MagickFalse)
1470 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1471 assert(exception != (ExceptionInfo *) NULL);
1472 assert(exception->signature == MagickSignature);
1473 for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
1474 {
1475 if (next->exception.severity == UndefinedException)
1476 continue;
1477 if (next->exception.severity > exception->severity)
1478 InheritException(exception,&next->exception);
1479 next->exception.severity=UndefinedException;
1480 }
1481}
1482
1483/*
1484%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1485% %
1486% %
1487% %
1488% G e t I m a g e I n f o %
1489% %
1490% %
1491% %
1492%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1493%
1494% GetImageInfo() initializes image_info to default values.
1495%
1496% The format of the GetImageInfo method is:
1497%
1498% void GetImageInfo(ImageInfo *image_info)
1499%
1500% A description of each parameter follows:
1501%
1502% o image_info: the image info.
1503%
1504*/
1505MagickExport void GetImageInfo(ImageInfo *image_info)
1506{
1507 ExceptionInfo
1508 *exception;
1509
1510 /*
1511 File and image dimension members.
1512 */
1513 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1514 assert(image_info != (ImageInfo *) NULL);
1515 (void) ResetMagickMemory(image_info,0,sizeof(*image_info));
1516 image_info->adjoin=MagickTrue;
1517 image_info->interlace=NoInterlace;
1518 image_info->channel=DefaultChannels;
1519 image_info->quality=UndefinedCompressionQuality;
1520 image_info->antialias=MagickTrue;
1521 image_info->dither=MagickTrue;
1522 exception=AcquireExceptionInfo();
1523 (void) QueryColorDatabase(BackgroundColor,&image_info->background_color,
1524 exception);
1525 (void) QueryColorDatabase(BorderColor,&image_info->border_color,exception);
1526 (void) QueryColorDatabase(MatteColor,&image_info->matte_color,exception);
1527 (void) QueryColorDatabase(TransparentColor,&image_info->transparent_color,
1528 exception);
1529 exception=DestroyExceptionInfo(exception);
1530 image_info->debug=IsEventLogging();
1531 image_info->signature=MagickSignature;
1532}
1533
1534/*
1535%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1536% %
1537% %
1538% %
cristy15781e52009-12-05 23:05:27 +00001539% G e t I m a g e I n f o F i l e %
1540% %
1541% %
1542% %
1543%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1544%
1545% GetImageInfoFile() returns the image info file member.
1546%
1547% The format of the GetImageInfoFile method is:
1548%
1549% FILE *GetImageInfoFile(const ImageInfo *image_info)
1550%
1551% A description of each parameter follows:
1552%
1553% o image_info: the image info.
1554%
1555*/
1556MagickExport FILE *GetImageInfoFile(const ImageInfo *image_info)
1557{
1558 return(image_info->file);
1559}
1560
1561/*
1562%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1563% %
1564% %
1565% %
cristy3ed852e2009-09-05 21:47:34 +00001566% G e t I m a g e M a s k %
1567% %
1568% %
1569% %
1570%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1571%
1572% GetImageMask() returns the mask associated with the image.
1573%
1574% The format of the GetImageMask method is:
1575%
1576% Image *GetImageMask(const Image *image,ExceptionInfo *exception)
1577%
1578% A description of each parameter follows:
1579%
1580% o image: the image.
1581%
1582*/
1583MagickExport Image *GetImageMask(const Image *image,ExceptionInfo *exception)
1584{
1585 assert(image != (const Image *) NULL);
1586 if (image->debug != MagickFalse)
1587 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1588 assert(image->signature == MagickSignature);
1589 if (image->mask == (Image *) NULL)
1590 return((Image *) NULL);
1591 return(CloneImage(image->mask,0,0,MagickTrue,exception));
1592}
1593
1594/*
1595%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1596% %
1597% %
1598% %
1599+ G e t I m a g e R e f e r e n c e C o u n t %
1600% %
1601% %
1602% %
1603%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1604%
1605% GetImageReferenceCount() returns the image reference count.
1606%
1607% The format of the GetReferenceCount method is:
1608%
cristybb503372010-05-27 20:51:26 +00001609% ssize_t GetImageReferenceCount(Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001610%
1611% A description of each parameter follows:
1612%
1613% o image: the image.
1614%
1615*/
cristybb503372010-05-27 20:51:26 +00001616MagickExport ssize_t GetImageReferenceCount(Image *image)
cristy3ed852e2009-09-05 21:47:34 +00001617{
cristybb503372010-05-27 20:51:26 +00001618 ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001619 reference_count;
1620
1621 assert(image != (Image *) NULL);
1622 assert(image->signature == MagickSignature);
1623 if (image->debug != MagickFalse)
1624 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
cristyf84a1932010-01-03 18:00:18 +00001625 LockSemaphoreInfo(image->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001626 reference_count=image->reference_count;
cristyf84a1932010-01-03 18:00:18 +00001627 UnlockSemaphoreInfo(image->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00001628 return(reference_count);
1629}
1630
1631/*
1632%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1633% %
1634% %
1635% %
cristy3ed852e2009-09-05 21:47:34 +00001636% 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 %
1637% %
1638% %
1639% %
1640%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1641%
1642% GetImageVirtualPixelMethod() gets the "virtual pixels" method for the
1643% image. A virtual pixel is any pixel access that is outside the boundaries
1644% of the image cache.
1645%
1646% The format of the GetImageVirtualPixelMethod() method is:
1647%
1648% VirtualPixelMethod GetImageVirtualPixelMethod(const Image *image)
1649%
1650% A description of each parameter follows:
1651%
1652% o image: the image.
1653%
1654*/
1655MagickExport VirtualPixelMethod GetImageVirtualPixelMethod(const Image *image)
1656{
1657 assert(image != (Image *) NULL);
1658 assert(image->signature == MagickSignature);
1659 if (image->debug != MagickFalse)
1660 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1661 return(GetPixelCacheVirtualMethod(image));
1662}
1663
1664/*
1665%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1666% %
1667% %
1668% %
1669% I n t e r p r e t I m a g e F i l e n a m e %
1670% %
1671% %
1672% %
1673%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1674%
1675% InterpretImageFilename() interprets embedded characters in an image filename.
1676% The filename length is returned.
1677%
1678% The format of the InterpretImageFilename method is:
1679%
1680% size_t InterpretImageFilename(const ImageInfo *image_info,
1681% Image *image,const char *format,int value,char *filename)
1682%
1683% A description of each parameter follows.
1684%
1685% o image_info: the image info..
1686%
1687% o image: the image.
1688%
1689% o format: A filename describing the format to use to write the numeric
1690% argument. Only the first numeric format identifier is replaced.
1691%
1692% o value: Numeric value to substitute into format filename.
1693%
1694% o filename: return the formatted filename in this character buffer.
1695%
1696*/
1697MagickExport size_t InterpretImageFilename(const ImageInfo *image_info,
1698 Image *image,const char *format,int value,char *filename)
1699{
1700 char
1701 *q;
1702
1703 int
1704 c;
1705
1706 MagickBooleanType
1707 canonical;
1708
1709 register const char
1710 *p;
1711
1712 canonical=MagickFalse;
1713 (void) CopyMagickString(filename,format,MaxTextExtent);
1714 for (p=strchr(format,'%'); p != (char *) NULL; p=strchr(p+1,'%'))
1715 {
1716 q=(char *) p+1;
1717 if (*q == '%')
1718 {
1719 p=q+1;
1720 continue;
1721 }
1722 if (*q == '0')
1723 {
cristybb503372010-05-27 20:51:26 +00001724 ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001725 value;
1726
cristybb503372010-05-27 20:51:26 +00001727 value=(ssize_t) strtol(q,&q,10);
cristy3ed852e2009-09-05 21:47:34 +00001728 }
1729 switch (*q)
1730 {
1731 case 'd':
1732 case 'o':
1733 case 'x':
1734 {
1735 q++;
1736 c=(*q);
1737 *q='\0';
1738 (void) FormatMagickString(filename+(p-format),(size_t) (MaxTextExtent-
1739 (p-format)),p,value);
1740 *q=c;
1741 (void) ConcatenateMagickString(filename,q,MaxTextExtent);
1742 canonical=MagickTrue;
1743 if (*(q-1) != '%')
1744 break;
1745 p++;
1746 break;
1747 }
1748 case '[':
1749 {
1750 char
1751 pattern[MaxTextExtent];
1752
1753 const char
1754 *value;
1755
cristy3ed852e2009-09-05 21:47:34 +00001756 register char
1757 *r;
1758
cristybb503372010-05-27 20:51:26 +00001759 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001760 i;
1761
cristycb6d09b2010-06-19 01:59:36 +00001762 ssize_t
1763 depth;
1764
cristy3ed852e2009-09-05 21:47:34 +00001765 /*
1766 Image option.
1767 */
1768 if (strchr(p,']') == (char *) NULL)
1769 break;
1770 depth=1;
1771 r=q+1;
1772 for (i=0; (i < (MaxTextExtent-1L)) && (*r != '\0'); i++)
1773 {
1774 if (*r == '[')
1775 depth++;
1776 if (*r == ']')
1777 depth--;
1778 if (depth <= 0)
1779 break;
1780 pattern[i]=(*r++);
1781 }
1782 pattern[i]='\0';
1783 if (LocaleNCompare(pattern,"filename:",9) != 0)
1784 break;
1785 value=(const char *) NULL;
1786 if ((image_info != (const ImageInfo *) NULL) &&
1787 (image != (const Image *) NULL))
cristy86fe49e2010-06-25 01:18:11 +00001788 value=GetMagickProperty(image_info,image,pattern);
cristy3ed852e2009-09-05 21:47:34 +00001789 else
1790 if (image != (Image *) NULL)
cristy86fe49e2010-06-25 01:18:11 +00001791 value=GetImageProperty(image,pattern);
cristy3ed852e2009-09-05 21:47:34 +00001792 else
1793 if (image_info != (ImageInfo *) NULL)
cristy86fe49e2010-06-25 01:18:11 +00001794 value=GetImageOption(image_info,pattern);
cristy3ed852e2009-09-05 21:47:34 +00001795 if (value == (const char *) NULL)
1796 break;
1797 q--;
1798 c=(*q);
1799 *q='\0';
1800 (void) CopyMagickString(filename+(p-format),value,(size_t)
1801 (MaxTextExtent-(p-format)));
1802 *q=c;
1803 (void) ConcatenateMagickString(filename,r+1,MaxTextExtent);
1804 canonical=MagickTrue;
1805 if (*(q-1) != '%')
1806 break;
1807 p++;
1808 break;
1809 }
1810 default:
1811 break;
1812 }
1813 }
1814 for (q=filename; *q != '\0'; q++)
1815 if ((*q == '%') && (*(q+1) == '%'))
1816 (void) CopyMagickString(q,q+1,(size_t) (MaxTextExtent-(q-filename)));
1817 if (canonical == MagickFalse)
1818 (void) CopyMagickString(filename,format,MaxTextExtent);
1819 return(strlen(filename));
1820}
1821
1822/*
1823%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1824% %
1825% %
1826% %
1827% I s H i g h D y n a m i c R a n g e I m a g e %
1828% %
1829% %
1830% %
1831%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1832%
1833% IsHighDynamicRangeImage() returns MagickTrue if any pixel component is
1834% non-integer or exceeds the bounds of the quantum depth (e.g. for Q16
1835% 0..65535.
1836%
1837% The format of the IsHighDynamicRangeImage method is:
1838%
1839% MagickBooleanType IsHighDynamicRangeImage(const Image *image,
1840% ExceptionInfo *exception)
1841%
1842% A description of each parameter follows:
1843%
1844% o image: the image.
1845%
1846% o exception: return any errors or warnings in this structure.
1847%
1848*/
1849MagickExport MagickBooleanType IsHighDynamicRangeImage(const Image *image,
1850 ExceptionInfo *exception)
1851{
1852#if !defined(MAGICKCORE_HDRI_SUPPORT)
1853 (void) image;
1854 (void) exception;
1855 return(MagickFalse);
1856#else
1857 CacheView
1858 *image_view;
1859
cristy3ed852e2009-09-05 21:47:34 +00001860 MagickBooleanType
1861 status;
1862
1863 MagickPixelPacket
1864 zero;
1865
cristycb6d09b2010-06-19 01:59:36 +00001866 ssize_t
1867 y;
1868
cristy3ed852e2009-09-05 21:47:34 +00001869 assert(image != (Image *) NULL);
1870 assert(image->signature == MagickSignature);
1871 if (image->debug != MagickFalse)
1872 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1873 status=MagickTrue;
1874 GetMagickPixelPacket(image,&zero);
1875 image_view=AcquireCacheView(image);
cristyb5d5f722009-11-04 03:03:49 +00001876#if defined(MAGICKCORE_OPENMP_SUPPORT)
1877 #pragma omp parallel for schedule(dynamic,4) shared(status)
cristy3ed852e2009-09-05 21:47:34 +00001878#endif
cristybb503372010-05-27 20:51:26 +00001879 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001880 {
1881 MagickPixelPacket
1882 pixel;
1883
1884 register const IndexPacket
1885 *indexes;
1886
1887 register const PixelPacket
1888 *p;
1889
cristybb503372010-05-27 20:51:26 +00001890 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001891 x;
1892
1893 if (status == MagickFalse)
1894 continue;
1895 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
1896 if (p == (const PixelPacket *) NULL)
1897 {
1898 status=MagickFalse;
1899 continue;
1900 }
1901 indexes=GetCacheViewVirtualIndexQueue(image_view);
1902 pixel=zero;
cristybb503372010-05-27 20:51:26 +00001903 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00001904 {
1905 SetMagickPixelPacket(image,p,indexes+x,&pixel);
1906 if ((pixel.red < 0.0) || (pixel.red > QuantumRange) ||
1907 (pixel.red != (QuantumAny) pixel.red))
1908 break;
1909 if ((pixel.green < 0.0) || (pixel.green > QuantumRange) ||
1910 (pixel.green != (QuantumAny) pixel.green))
1911 break;
1912 if ((pixel.blue < 0.0) || (pixel.blue > QuantumRange) ||
1913 (pixel.blue != (QuantumAny) pixel.blue))
1914 break;
1915 if (pixel.matte != MagickFalse)
1916 {
1917 if ((pixel.opacity < 0.0) || (pixel.opacity > QuantumRange) ||
1918 (pixel.opacity != (QuantumAny) pixel.opacity))
1919 break;
1920 }
1921 if (pixel.colorspace == CMYKColorspace)
1922 {
1923 if ((pixel.index < 0.0) || (pixel.index > QuantumRange) ||
1924 (pixel.index != (QuantumAny) pixel.index))
1925 break;
1926 }
1927 p++;
1928 }
cristybb503372010-05-27 20:51:26 +00001929 if (x < (ssize_t) image->columns)
cristy3ed852e2009-09-05 21:47:34 +00001930 status=MagickFalse;
1931 }
1932 image_view=DestroyCacheView(image_view);
1933 return(status != MagickFalse ? MagickFalse : MagickTrue);
1934#endif
1935}
1936
1937/*
1938%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1939% %
1940% %
1941% %
1942% I s I m a g e O b j e c t %
1943% %
1944% %
1945% %
1946%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1947%
1948% IsImageObject() returns MagickTrue if the image sequence contains a valid
1949% set of image objects.
1950%
1951% The format of the IsImageObject method is:
1952%
1953% MagickBooleanType IsImageObject(const Image *image)
1954%
1955% A description of each parameter follows:
1956%
1957% o image: the image.
1958%
1959*/
1960MagickExport MagickBooleanType IsImageObject(const Image *image)
1961{
1962 register const Image
1963 *p;
1964
1965 assert(image != (Image *) NULL);
1966 if (image->debug != MagickFalse)
1967 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
1968 for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
1969 if (p->signature != MagickSignature)
1970 return(MagickFalse);
1971 return(MagickTrue);
1972}
1973
1974/*
1975%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1976% %
1977% %
1978% %
1979% I s T a i n t I m a g e %
1980% %
1981% %
1982% %
1983%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1984%
1985% IsTaintImage() returns MagickTrue any pixel in the image has been altered
1986% since it was first constituted.
1987%
1988% The format of the IsTaintImage method is:
1989%
1990% MagickBooleanType IsTaintImage(const Image *image)
1991%
1992% A description of each parameter follows:
1993%
1994% o image: the image.
1995%
1996*/
1997MagickExport MagickBooleanType IsTaintImage(const Image *image)
1998{
1999 char
2000 magick[MaxTextExtent],
2001 filename[MaxTextExtent];
2002
2003 register const Image
2004 *p;
2005
2006 assert(image != (Image *) NULL);
2007 if (image->debug != MagickFalse)
2008 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2009 assert(image->signature == MagickSignature);
2010 (void) CopyMagickString(magick,image->magick,MaxTextExtent);
2011 (void) CopyMagickString(filename,image->filename,MaxTextExtent);
2012 for (p=image; p != (Image *) NULL; p=GetNextImageInList(p))
2013 {
2014 if (p->taint != MagickFalse)
2015 return(MagickTrue);
2016 if (LocaleCompare(p->magick,magick) != 0)
2017 return(MagickTrue);
2018 if (LocaleCompare(p->filename,filename) != 0)
2019 return(MagickTrue);
2020 }
2021 return(MagickFalse);
2022}
2023
2024/*
2025%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2026% %
2027% %
2028% %
2029% M o d i f y I m a g e %
2030% %
2031% %
2032% %
2033%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2034%
2035% ModifyImage() ensures that there is only a single reference to the image
2036% to be modified, updating the provided image pointer to point to a clone of
2037% the original image if necessary.
2038%
2039% The format of the ModifyImage method is:
2040%
2041% MagickBooleanType ModifyImage(Image *image,ExceptionInfo *exception)
2042%
2043% A description of each parameter follows:
2044%
2045% o image: the image.
2046%
2047% o exception: return any errors or warnings in this structure.
2048%
2049*/
2050MagickExport MagickBooleanType ModifyImage(Image **image,
2051 ExceptionInfo *exception)
2052{
2053 Image
2054 *clone_image;
2055
2056 assert(image != (Image **) NULL);
2057 assert(*image != (Image *) NULL);
2058 assert((*image)->signature == MagickSignature);
2059 if ((*image)->debug != MagickFalse)
2060 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
2061 if (GetImageReferenceCount(*image) <= 1)
2062 return(MagickTrue);
2063 clone_image=CloneImage(*image,0,0,MagickTrue,exception);
cristyf84a1932010-01-03 18:00:18 +00002064 LockSemaphoreInfo((*image)->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00002065 (*image)->reference_count--;
cristyf84a1932010-01-03 18:00:18 +00002066 UnlockSemaphoreInfo((*image)->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00002067 *image=clone_image;
2068 return(MagickTrue);
2069}
2070
2071/*
2072%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2073% %
2074% %
2075% %
2076% N e w M a g i c k I m a g e %
2077% %
2078% %
2079% %
2080%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2081%
2082% NewMagickImage() creates a blank image canvas of the specified size and
2083% background color.
2084%
2085% The format of the NewMagickImage method is:
2086%
2087% 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% A description of each parameter follows:
2092%
2093% o image: the image.
2094%
2095% o width: the image width.
2096%
2097% o height: the image height.
2098%
2099% o background: the image color.
2100%
2101*/
2102MagickExport Image *NewMagickImage(const ImageInfo *image_info,
cristybb503372010-05-27 20:51:26 +00002103 const size_t width,const size_t height,
cristy3ed852e2009-09-05 21:47:34 +00002104 const MagickPixelPacket *background)
2105{
2106 CacheView
2107 *image_view;
2108
2109 ExceptionInfo
2110 *exception;
2111
2112 Image
2113 *image;
2114
cristybb503372010-05-27 20:51:26 +00002115 ssize_t
cristy3ed852e2009-09-05 21:47:34 +00002116 y;
2117
2118 MagickBooleanType
2119 status;
2120
2121 assert(image_info != (const ImageInfo *) NULL);
2122 if (image_info->debug != MagickFalse)
2123 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2124 assert(image_info->signature == MagickSignature);
2125 assert(background != (const MagickPixelPacket *) NULL);
2126 image=AcquireImage(image_info);
2127 image->columns=width;
2128 image->rows=height;
2129 image->colorspace=background->colorspace;
2130 image->matte=background->matte;
2131 image->fuzz=background->fuzz;
2132 image->depth=background->depth;
2133 status=MagickTrue;
2134 exception=(&image->exception);
2135 image_view=AcquireCacheView(image);
cristy48974b92009-12-19 02:36:06 +00002136#if defined(MAGICKCORE_OPENMP_SUPPORT)
2137 #pragma omp parallel for schedule(dynamic,4) shared(status)
2138#endif
cristybb503372010-05-27 20:51:26 +00002139 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002140 {
2141 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00002142 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00002143
cristy3ed852e2009-09-05 21:47:34 +00002144 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002145 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002146
cristycb6d09b2010-06-19 01:59:36 +00002147 register ssize_t
2148 x;
2149
cristy48974b92009-12-19 02:36:06 +00002150 if (status == MagickFalse)
2151 continue;
cristy3ed852e2009-09-05 21:47:34 +00002152 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2153 if (q == (PixelPacket *) NULL)
2154 {
2155 status=MagickFalse;
2156 continue;
2157 }
2158 indexes=GetCacheViewAuthenticIndexQueue(image_view);
cristybb503372010-05-27 20:51:26 +00002159 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002160 {
2161 SetPixelPacket(image,background,q,indexes+x);
2162 q++;
2163 }
2164 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2165 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00002166 }
2167 image_view=DestroyCacheView(image_view);
2168 if (status == MagickFalse)
2169 image=DestroyImage(image);
2170 return(image);
2171}
2172
2173/*
2174%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2175% %
2176% %
2177% %
2178% R e f e r e n c e I m a g e %
2179% %
2180% %
2181% %
2182%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2183%
2184% ReferenceImage() increments the reference count associated with an image
2185% returning a pointer to the image.
2186%
2187% The format of the ReferenceImage method is:
2188%
2189% Image *ReferenceImage(Image *image)
2190%
2191% A description of each parameter follows:
2192%
2193% o image: the image.
2194%
2195*/
2196MagickExport Image *ReferenceImage(Image *image)
2197{
2198 assert(image != (Image *) NULL);
2199 if (image->debug != MagickFalse)
2200 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2201 assert(image->signature == MagickSignature);
cristyf84a1932010-01-03 18:00:18 +00002202 LockSemaphoreInfo(image->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00002203 image->reference_count++;
cristyf84a1932010-01-03 18:00:18 +00002204 UnlockSemaphoreInfo(image->semaphore);
cristy3ed852e2009-09-05 21:47:34 +00002205 return(image);
2206}
2207
2208/*
2209%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2210% %
2211% %
2212% %
2213% R e s e t I m a g e P a g e %
2214% %
2215% %
2216% %
2217%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2218%
2219% ResetImagePage() resets the image page canvas and position.
2220%
2221% The format of the ResetImagePage method is:
2222%
2223% MagickBooleanType ResetImagePage(Image *image,const char *page)
2224%
2225% A description of each parameter follows:
2226%
2227% o image: the image.
2228%
2229% o page: the relative page specification.
2230%
2231*/
2232MagickExport MagickBooleanType ResetImagePage(Image *image,const char *page)
2233{
2234 MagickStatusType
2235 flags;
2236
2237 RectangleInfo
2238 geometry;
2239
2240 assert(image != (Image *) NULL);
2241 assert(image->signature == MagickSignature);
2242 if (image->debug != MagickFalse)
2243 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2244 flags=ParseAbsoluteGeometry(page,&geometry);
2245 if ((flags & WidthValue) != 0)
2246 {
2247 if ((flags & HeightValue) == 0)
2248 geometry.height=geometry.width;
2249 image->page.width=geometry.width;
2250 image->page.height=geometry.height;
2251 }
2252 if ((flags & AspectValue) != 0)
2253 {
2254 if ((flags & XValue) != 0)
2255 image->page.x+=geometry.x;
2256 if ((flags & YValue) != 0)
2257 image->page.y+=geometry.y;
2258 }
2259 else
2260 {
2261 if ((flags & XValue) != 0)
2262 {
2263 image->page.x=geometry.x;
2264 if ((image->page.width == 0) && (geometry.x > 0))
2265 image->page.width=image->columns+geometry.x;
2266 }
2267 if ((flags & YValue) != 0)
2268 {
2269 image->page.y=geometry.y;
2270 if ((image->page.height == 0) && (geometry.y > 0))
2271 image->page.height=image->rows+geometry.y;
2272 }
2273 }
2274 return(MagickTrue);
2275}
2276
2277/*
2278%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2279% %
2280% %
2281% %
2282% S e p a r a t e I m a g e C h a n n e l %
2283% %
2284% %
2285% %
2286%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2287%
2288% SeparateImageChannel() separates a channel from the image and returns it as
2289% a grayscale image. A channel is a particular color component of each pixel
2290% in the image.
2291%
2292% The format of the SeparateImageChannel method is:
2293%
2294% MagickBooleanType SeparateImageChannel(Image *image,
2295% const ChannelType channel)
2296%
2297% A description of each parameter follows:
2298%
2299% o image: the image.
2300%
2301% o channel: Identify which channel to extract: RedChannel, GreenChannel,
2302% BlueChannel, OpacityChannel, CyanChannel, MagentaChannel,
2303% YellowChannel, or BlackChannel.
2304%
2305*/
2306MagickExport MagickBooleanType SeparateImageChannel(Image *image,
2307 const ChannelType channel)
2308{
2309#define SeparateImageTag "Separate/Image"
2310
2311 CacheView
2312 *image_view;
2313
2314 ExceptionInfo
2315 *exception;
2316
cristy3ed852e2009-09-05 21:47:34 +00002317 MagickBooleanType
2318 status;
2319
cristybb503372010-05-27 20:51:26 +00002320 MagickOffsetType
2321 progress;
2322
2323 ssize_t
2324 y;
2325
cristy3ed852e2009-09-05 21:47:34 +00002326 assert(image != (Image *) NULL);
2327 assert(image->signature == MagickSignature);
2328 if (image->debug != MagickFalse)
2329 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2330 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2331 return(MagickFalse);
2332 /*
2333 Separate image channels.
2334 */
2335 status=MagickTrue;
cristy11b66ce2010-03-11 13:34:19 +00002336 if (channel == GrayChannels)
cristy3ed852e2009-09-05 21:47:34 +00002337 image->matte=MagickTrue;
2338 progress=0;
2339 exception=(&image->exception);
2340 image_view=AcquireCacheView(image);
cristyb5d5f722009-11-04 03:03:49 +00002341#if defined(MAGICKCORE_OPENMP_SUPPORT)
2342 #pragma omp parallel for schedule(dynamic,4) shared(progress,status)
cristy3ed852e2009-09-05 21:47:34 +00002343#endif
cristybb503372010-05-27 20:51:26 +00002344 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002345 {
2346 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00002347 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00002348
cristy3ed852e2009-09-05 21:47:34 +00002349 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002350 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002351
cristycb6d09b2010-06-19 01:59:36 +00002352 register ssize_t
2353 x;
2354
cristy3ed852e2009-09-05 21:47:34 +00002355 if (status == MagickFalse)
2356 continue;
2357 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2358 if (q == (PixelPacket *) NULL)
2359 {
2360 status=MagickFalse;
2361 continue;
2362 }
2363 indexes=GetCacheViewAuthenticIndexQueue(image_view);
2364 switch (channel)
2365 {
2366 case RedChannel:
2367 {
cristybb503372010-05-27 20:51:26 +00002368 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002369 {
2370 q->green=q->red;
2371 q->blue=q->red;
2372 q++;
2373 }
2374 break;
2375 }
2376 case GreenChannel:
2377 {
cristybb503372010-05-27 20:51:26 +00002378 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002379 {
2380 q->red=q->green;
2381 q->blue=q->green;
2382 q++;
2383 }
2384 break;
2385 }
2386 case BlueChannel:
2387 {
cristybb503372010-05-27 20:51:26 +00002388 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002389 {
2390 q->red=q->blue;
2391 q->green=q->blue;
2392 q++;
2393 }
2394 break;
2395 }
2396 case OpacityChannel:
2397 {
cristybb503372010-05-27 20:51:26 +00002398 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002399 {
2400 q->red=q->opacity;
2401 q->green=q->opacity;
2402 q->blue=q->opacity;
2403 q++;
2404 }
2405 break;
2406 }
2407 case BlackChannel:
2408 {
2409 if ((image->storage_class != PseudoClass) &&
2410 (image->colorspace != CMYKColorspace))
2411 break;
cristybb503372010-05-27 20:51:26 +00002412 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002413 {
2414 q->red=indexes[x];
2415 q->green=indexes[x];
2416 q->blue=indexes[x];
2417 q++;
2418 }
2419 break;
2420 }
2421 case TrueAlphaChannel:
2422 {
cristybb503372010-05-27 20:51:26 +00002423 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002424 {
cristy46f08202010-01-10 04:04:21 +00002425 q->red=(Quantum) GetAlphaPixelComponent(q);
2426 q->green=(Quantum) GetAlphaPixelComponent(q);
2427 q->blue=(Quantum) GetAlphaPixelComponent(q);
cristy3ed852e2009-09-05 21:47:34 +00002428 q++;
2429 }
2430 break;
2431 }
2432 case GrayChannels:
2433 {
cristybb503372010-05-27 20:51:26 +00002434 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002435 {
2436 q->opacity=(Quantum) (QuantumRange-PixelIntensityToQuantum(q));
2437 q++;
2438 }
2439 break;
2440 }
2441 default:
2442 break;
2443 }
2444 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2445 status=MagickFalse;
2446 if (image->progress_monitor != (MagickProgressMonitor) NULL)
2447 {
2448 MagickBooleanType
2449 proceed;
2450
cristyb5d5f722009-11-04 03:03:49 +00002451#if defined(MAGICKCORE_OPENMP_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00002452 #pragma omp critical (MagickCore_SeparateImageChannel)
2453#endif
2454 proceed=SetImageProgress(image,SeparateImageTag,progress++,image->rows);
2455 if (proceed == MagickFalse)
2456 status=MagickFalse;
2457 }
2458 }
2459 image_view=DestroyCacheView(image_view);
cristy11b66ce2010-03-11 13:34:19 +00002460 if (channel != GrayChannels)
cristy3ed852e2009-09-05 21:47:34 +00002461 image->matte=MagickFalse;
2462 (void) SetImageColorspace(image,RGBColorspace);
2463 return(status);
2464}
2465
2466/*
2467%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2468% %
2469% %
2470% %
2471% S e p a r a t e I m a g e s %
2472% %
2473% %
2474% %
2475%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2476%
2477% SeparateImages() returns a separate grayscale image for each channel
2478% specified.
2479%
2480% The format of the SeparateImages method is:
2481%
2482% MagickBooleanType SeparateImages(const Image *image,
2483% const ChannelType channel,ExceptionInfo *exception)
2484%
2485% A description of each parameter follows:
2486%
2487% o image: the image.
2488%
2489% o channel: Identify which channels to extract: RedChannel, GreenChannel,
2490% BlueChannel, OpacityChannel, CyanChannel, MagentaChannel,
2491% YellowChannel, or BlackChannel.
2492%
2493% o exception: return any errors or warnings in this structure.
2494%
2495*/
2496MagickExport Image *SeparateImages(const Image *image,const ChannelType channel,
2497 ExceptionInfo *exception)
2498{
2499 Image
2500 *images,
2501 *separate_image;
2502
2503 assert(image != (Image *) NULL);
2504 assert(image->signature == MagickSignature);
2505 if (image->debug != MagickFalse)
2506 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2507 images=NewImageList();
2508 if ((channel & RedChannel) != 0)
2509 {
2510 separate_image=CloneImage(image,0,0,MagickTrue,exception);
2511 (void) SeparateImageChannel(separate_image,RedChannel);
2512 AppendImageToList(&images,separate_image);
2513 }
2514 if ((channel & GreenChannel) != 0)
2515 {
2516 separate_image=CloneImage(image,0,0,MagickTrue,exception);
2517 (void) SeparateImageChannel(separate_image,GreenChannel);
2518 AppendImageToList(&images,separate_image);
2519 }
2520 if ((channel & BlueChannel) != 0)
2521 {
2522 separate_image=CloneImage(image,0,0,MagickTrue,exception);
2523 (void) SeparateImageChannel(separate_image,BlueChannel);
2524 AppendImageToList(&images,separate_image);
2525 }
2526 if (((channel & BlackChannel) != 0) && (image->colorspace == CMYKColorspace))
2527 {
2528 separate_image=CloneImage(image,0,0,MagickTrue,exception);
2529 (void) SeparateImageChannel(separate_image,BlackChannel);
2530 AppendImageToList(&images,separate_image);
2531 }
2532 if ((channel & OpacityChannel) != 0)
2533 {
2534 separate_image=CloneImage(image,0,0,MagickTrue,exception);
2535 (void) SeparateImageChannel(separate_image,OpacityChannel);
2536 AppendImageToList(&images,separate_image);
2537 }
2538 return(images);
2539}
2540
2541/*
2542%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2543% %
2544% %
2545% %
2546% S e t I m a g e A l p h a C h a n n e l %
2547% %
2548% %
2549% %
2550%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2551%
2552% SetImageAlphaChannel() activates, deactivates, resets, or sets the alpha
2553% channel.
2554%
2555% The format of the SetImageAlphaChannel method is:
2556%
2557% MagickBooleanType SetImageAlphaChannel(Image *image,
2558% const AlphaChannelType alpha_type)
2559%
2560% A description of each parameter follows:
2561%
2562% o image: the image.
2563%
2564% o alpha_type: The alpha channel type: ActivateAlphaChannel,
2565% CopyAlphaChannel, DeactivateAlphaChannel, ExtractAlphaChannel,
2566% OpaqueAlphaChannel, ResetAlphaChannel, SetAlphaChannel,
2567% ShapeAlphaChannel, and TransparentAlphaChannel.
2568%
2569*/
2570MagickExport MagickBooleanType SetImageAlphaChannel(Image *image,
2571 const AlphaChannelType alpha_type)
2572{
2573 MagickBooleanType
2574 status;
2575
2576 assert(image != (Image *) NULL);
2577 if (image->debug != MagickFalse)
2578 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2579 assert(image->signature == MagickSignature);
2580 status=MagickFalse;
2581 switch (alpha_type)
2582 {
2583 case ActivateAlphaChannel:
2584 {
2585 image->matte=MagickTrue;
2586 break;
2587 }
2588 case BackgroundAlphaChannel:
2589 {
2590 CacheView
2591 *image_view;
2592
2593 ExceptionInfo
2594 *exception;
2595
2596 IndexPacket
2597 index;
2598
cristy3ed852e2009-09-05 21:47:34 +00002599 MagickBooleanType
2600 status;
2601
2602 MagickPixelPacket
2603 background;
2604
2605 PixelPacket
2606 pixel;
2607
cristycb6d09b2010-06-19 01:59:36 +00002608 ssize_t
2609 y;
2610
cristy3ed852e2009-09-05 21:47:34 +00002611 /*
2612 Set transparent pixels to background color.
2613 */
2614 if (image->matte == MagickFalse)
2615 break;
2616 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2617 break;
2618 GetMagickPixelPacket(image,&background);
2619 SetMagickPixelPacket(image,&image->background_color,(const IndexPacket *)
2620 NULL,&background);
2621 if (image->colorspace == CMYKColorspace)
2622 ConvertRGBToCMYK(&background);
2623 index=0;
2624 SetPixelPacket(image,&background,&pixel,&index);
2625 status=MagickTrue;
2626 exception=(&image->exception);
2627 image_view=AcquireCacheView(image);
cristyb5d5f722009-11-04 03:03:49 +00002628 #if defined(MAGICKCORE_OPENMP_SUPPORT)
2629 #pragma omp parallel for schedule(dynamic,4) shared(status)
cristy3ed852e2009-09-05 21:47:34 +00002630 #endif
cristybb503372010-05-27 20:51:26 +00002631 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002632 {
2633 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00002634 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00002635
cristy3ed852e2009-09-05 21:47:34 +00002636 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002637 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002638
cristycb6d09b2010-06-19 01:59:36 +00002639 register ssize_t
2640 x;
2641
cristy3ed852e2009-09-05 21:47:34 +00002642 if (status == MagickFalse)
2643 continue;
2644 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,
2645 exception);
2646 if (q == (PixelPacket *) NULL)
2647 {
2648 status=MagickFalse;
2649 continue;
2650 }
cristybb503372010-05-27 20:51:26 +00002651 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002652 {
2653 if (q->opacity == TransparentOpacity)
2654 {
2655 q->red=pixel.red;
2656 q->green=pixel.green;
2657 q->blue=pixel.blue;
2658 }
2659 q++;
2660 }
2661 if (image->colorspace == CMYKColorspace)
2662 {
2663 indexes=GetCacheViewAuthenticIndexQueue(image_view);
cristybb503372010-05-27 20:51:26 +00002664 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002665 indexes[x]=index;
2666 }
2667 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2668 status=MagickFalse;
2669 }
2670 image_view=DestroyCacheView(image_view);
2671 return(status);
2672 }
2673 case DeactivateAlphaChannel:
2674 {
2675 image->matte=MagickFalse;
2676 break;
2677 }
2678 case ShapeAlphaChannel:
2679 case CopyAlphaChannel:
2680 {
2681 /*
2682 Special usage case for SeparateImageChannel(): copy grayscale color to
2683 the alpha channel.
2684 */
2685 status=SeparateImageChannel(image,GrayChannels);
2686 image->matte=MagickTrue; /* make sure transparency is now on! */
2687 if (alpha_type == ShapeAlphaChannel)
2688 {
2689 MagickPixelPacket
2690 background;
2691
2692 /*
2693 Reset all color channels to background color.
2694 */
2695 GetMagickPixelPacket(image,&background);
2696 SetMagickPixelPacket(image,&(image->background_color),(IndexPacket *)
2697 NULL,&background);
cristy308b4e62009-09-21 14:40:44 +00002698 (void) LevelColorsImage(image,&background,&background,MagickTrue);
cristy3ed852e2009-09-05 21:47:34 +00002699 }
2700 break;
2701 }
2702 case ExtractAlphaChannel:
2703 {
2704 status=SeparateImageChannel(image,TrueAlphaChannel);
2705 image->matte=MagickFalse;
2706 break;
2707 }
cristyf64d18b2010-04-30 12:47:03 +00002708 case ResetAlphaChannel: /* deprecated */
cristy3ed852e2009-09-05 21:47:34 +00002709 case OpaqueAlphaChannel:
2710 {
2711 status=SetImageOpacity(image,OpaqueOpacity);
2712 image->matte=MagickTrue;
2713 break;
2714 }
2715 case TransparentAlphaChannel:
2716 {
2717 status=SetImageOpacity(image,TransparentOpacity);
2718 image->matte=MagickTrue;
2719 break;
2720 }
2721 case SetAlphaChannel:
2722 {
2723 if (image->matte == MagickFalse)
2724 {
2725 status=SetImageOpacity(image,OpaqueOpacity);
2726 image->matte=MagickTrue;
2727 }
2728 break;
2729 }
2730 case UndefinedAlphaChannel:
2731 break;
2732 }
2733 return(status);
2734}
2735
2736/*
2737%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2738% %
2739% %
2740% %
2741% S e t I m a g e B a c k g r o u n d C o l o r %
2742% %
2743% %
2744% %
2745%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2746%
2747% SetImageBackgroundColor() initializes the image pixels to the image
2748% background color. The background color is defined by the background_color
2749% member of the image structure.
2750%
2751% The format of the SetImage method is:
2752%
2753% MagickBooleanType SetImageBackgroundColor(Image *image)
2754%
2755% A description of each parameter follows:
2756%
2757% o image: the image.
2758%
2759*/
2760MagickExport MagickBooleanType SetImageBackgroundColor(Image *image)
2761{
2762 CacheView
2763 *image_view;
2764
2765 ExceptionInfo
2766 *exception;
2767
2768 IndexPacket
2769 index;
2770
cristy3ed852e2009-09-05 21:47:34 +00002771 MagickBooleanType
2772 status;
2773
2774 MagickPixelPacket
2775 background;
2776
2777 PixelPacket
2778 pixel;
2779
cristycb6d09b2010-06-19 01:59:36 +00002780 ssize_t
2781 y;
2782
cristy3ed852e2009-09-05 21:47:34 +00002783 assert(image != (Image *) NULL);
2784 if (image->debug != MagickFalse)
2785 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2786 assert(image->signature == MagickSignature);
2787 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
2788 return(MagickFalse);
2789 if (image->background_color.opacity != OpaqueOpacity)
2790 image->matte=MagickTrue;
2791 GetMagickPixelPacket(image,&background);
2792 SetMagickPixelPacket(image,&image->background_color,(const IndexPacket *)
2793 NULL,&background);
2794 if (image->colorspace == CMYKColorspace)
2795 ConvertRGBToCMYK(&background);
2796 index=0;
2797 SetPixelPacket(image,&background,&pixel,&index);
2798 /*
2799 Set image background color.
2800 */
2801 status=MagickTrue;
2802 exception=(&image->exception);
2803 image_view=AcquireCacheView(image);
cristyb5d5f722009-11-04 03:03:49 +00002804#if defined(MAGICKCORE_OPENMP_SUPPORT)
2805 #pragma omp parallel for schedule(dynamic,4) shared(status)
cristy3ed852e2009-09-05 21:47:34 +00002806#endif
cristybb503372010-05-27 20:51:26 +00002807 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00002808 {
2809 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00002810 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00002811
cristy3ed852e2009-09-05 21:47:34 +00002812 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00002813 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00002814
cristycb6d09b2010-06-19 01:59:36 +00002815 register ssize_t
2816 x;
2817
cristy3ed852e2009-09-05 21:47:34 +00002818 if (status == MagickFalse)
2819 continue;
2820 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2821 if (q == (PixelPacket *) NULL)
2822 {
2823 status=MagickFalse;
2824 continue;
2825 }
cristybb503372010-05-27 20:51:26 +00002826 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002827 *q++=pixel;
2828 if (image->colorspace == CMYKColorspace)
2829 {
2830 indexes=GetCacheViewAuthenticIndexQueue(image_view);
cristybb503372010-05-27 20:51:26 +00002831 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00002832 indexes[x]=index;
2833 }
2834 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2835 status=MagickFalse;
2836 }
2837 image_view=DestroyCacheView(image_view);
2838 return(status);
2839}
2840
2841/*
2842%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2843% %
2844% %
2845% %
cristya5b77cb2010-05-07 19:34:48 +00002846% S e t I m a g e C o l o r %
2847% %
2848% %
2849% %
2850%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2851%
2852% SetImageColor() set the entire image canvas to the specified color.
2853%
2854% The format of the SetImageColor method is:
2855%
2856% MagickBooleanType SetImageColor(Image *image,
2857% const MagickPixelPacket *color)
2858%
2859% A description of each parameter follows:
2860%
2861% o image: the image.
2862%
2863% o background: the image color.
2864%
2865*/
2866MagickExport MagickBooleanType SetImageColor(Image *image,
2867 const MagickPixelPacket *color)
2868{
2869 CacheView
2870 *image_view;
2871
2872 ExceptionInfo
2873 *exception;
2874
cristya5b77cb2010-05-07 19:34:48 +00002875 MagickBooleanType
2876 status;
2877
cristycb6d09b2010-06-19 01:59:36 +00002878 ssize_t
2879 y;
2880
cristya5b77cb2010-05-07 19:34:48 +00002881 assert(image != (Image *) NULL);
2882 if (image->debug != MagickFalse)
2883 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
2884 assert(image->signature == MagickSignature);
2885 assert(color != (const MagickPixelPacket *) NULL);
2886 image->colorspace=color->colorspace;
2887 image->matte=color->matte;
2888 image->fuzz=color->fuzz;
2889 image->depth=color->depth;
2890 status=MagickTrue;
2891 exception=(&image->exception);
2892 image_view=AcquireCacheView(image);
2893#if defined(MAGICKCORE_OPENMP_SUPPORT)
2894 #pragma omp parallel for schedule(dynamic,4) shared(status)
2895#endif
cristybb503372010-05-27 20:51:26 +00002896 for (y=0; y < (ssize_t) image->rows; y++)
cristya5b77cb2010-05-07 19:34:48 +00002897 {
2898 register IndexPacket
2899 *restrict indexes;
2900
cristya5b77cb2010-05-07 19:34:48 +00002901 register PixelPacket
2902 *restrict q;
2903
cristycb6d09b2010-06-19 01:59:36 +00002904 register ssize_t
2905 x;
2906
cristya5b77cb2010-05-07 19:34:48 +00002907 if (status == MagickFalse)
2908 continue;
2909 q=QueueCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2910 if (q == (PixelPacket *) NULL)
2911 {
2912 status=MagickFalse;
2913 continue;
2914 }
2915 indexes=GetCacheViewAuthenticIndexQueue(image_view);
cristybb503372010-05-27 20:51:26 +00002916 for (x=0; x < (ssize_t) image->columns; x++)
cristya5b77cb2010-05-07 19:34:48 +00002917 {
2918 SetPixelPacket(image,color,q,indexes+x);
2919 q++;
2920 }
2921 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2922 status=MagickFalse;
2923 }
2924 image_view=DestroyCacheView(image_view);
2925 return(status);
2926}
2927
2928/*
2929%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2930% %
2931% %
2932% %
cristy3ed852e2009-09-05 21:47:34 +00002933% S e t I m a g e S t o r a g e C l a s s %
2934% %
2935% %
2936% %
2937%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2938%
2939% SetImageStorageClass() sets the image class: DirectClass for true color
2940% images or PseudoClass for colormapped images.
2941%
2942% The format of the SetImageStorageClass method is:
2943%
2944% MagickBooleanType SetImageStorageClass(Image *image,
2945% const ClassType storage_class)
2946%
2947% A description of each parameter follows:
2948%
2949% o image: the image.
2950%
2951% o storage_class: The image class.
2952%
2953*/
2954MagickExport MagickBooleanType SetImageStorageClass(Image *image,
2955 const ClassType storage_class)
2956{
2957 Cache
2958 cache;
2959
2960 if (image->storage_class == storage_class)
2961 return(MagickTrue);
2962 image->storage_class=storage_class;
2963 cache=GetImagePixelCache(image,MagickTrue,&image->exception);
2964 return(cache == (Cache) NULL ? MagickFalse : MagickTrue);
2965}
2966
2967/*
2968%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2969% %
2970% %
2971% %
2972% S e t I m a g e C l i p M a s k %
2973% %
2974% %
2975% %
2976%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2977%
2978% SetImageClipMask() associates a clip path with the image. The clip path
2979% must be the same dimensions as the image. Set any pixel component of
2980% the clip path to TransparentOpacity to prevent that corresponding image
2981% pixel component from being updated when SyncAuthenticPixels() is applied.
2982%
2983% The format of the SetImageClipMask method is:
2984%
2985% MagickBooleanType SetImageClipMask(Image *image,const Image *clip_mask)
2986%
2987% A description of each parameter follows:
2988%
2989% o image: the image.
2990%
2991% o clip_mask: the image clip path.
2992%
2993*/
2994MagickExport MagickBooleanType SetImageClipMask(Image *image,
2995 const Image *clip_mask)
2996{
2997 assert(image != (Image *) NULL);
2998 if (image->debug != MagickFalse)
2999 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3000 assert(image->signature == MagickSignature);
3001 if (clip_mask != (const Image *) NULL)
3002 if ((clip_mask->columns != image->columns) ||
3003 (clip_mask->rows != image->rows))
3004 ThrowBinaryException(ImageError,"ImageSizeDiffers",image->filename);
3005 if (image->clip_mask != (Image *) NULL)
3006 image->clip_mask=DestroyImage(image->clip_mask);
3007 image->clip_mask=NewImageList();
3008 if (clip_mask == (Image *) NULL)
3009 return(MagickTrue);
3010 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
3011 return(MagickFalse);
3012 image->clip_mask=CloneImage(clip_mask,0,0,MagickTrue,&image->exception);
3013 if (image->clip_mask == (Image *) NULL)
3014 return(MagickFalse);
3015 return(MagickTrue);
3016}
3017
3018/*
3019%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3020% %
3021% %
3022% %
3023% S e t I m a g e E x t e n t %
3024% %
3025% %
3026% %
3027%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3028%
3029% SetImageExtent() sets the image size (i.e. columns & rows).
3030%
3031% The format of the SetImageExtent method is:
3032%
3033% MagickBooleanType SetImageExtent(Image *image,
cristybb503372010-05-27 20:51:26 +00003034% const size_t columns,const size_t rows)
cristy3ed852e2009-09-05 21:47:34 +00003035%
3036% A description of each parameter follows:
3037%
3038% o image: the image.
3039%
3040% o columns: The image width in pixels.
3041%
3042% o rows: The image height in pixels.
3043%
3044*/
3045MagickExport MagickBooleanType SetImageExtent(Image *image,
cristybb503372010-05-27 20:51:26 +00003046 const size_t columns,const size_t rows)
cristy3ed852e2009-09-05 21:47:34 +00003047{
3048 Cache
3049 cache;
3050
3051 if ((columns != 0) && (rows != 0))
3052 {
3053 image->columns=columns;
3054 image->rows=rows;
3055 }
3056 cache=GetImagePixelCache(image,MagickTrue,&image->exception);
3057 return(cache == (Cache) NULL ? MagickFalse : MagickTrue);
3058}
3059
3060/*
3061%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3062% %
3063% %
3064% %
3065+ S e t I m a g e I n f o %
3066% %
3067% %
3068% %
3069%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3070%
3071% SetImageInfo() initializes the `magick' field of the ImageInfo structure.
3072% It is set to a type of image format based on the prefix or suffix of the
3073% filename. For example, `ps:image' returns PS indicating a Postscript image.
3074% JPEG is returned for this filename: `image.jpg'. The filename prefix has
3075% precendence over the suffix. Use an optional index enclosed in brackets
3076% after a file name to specify a desired scene of a multi-resolution image
3077% format like Photo CD (e.g. img0001.pcd[4]). A True (non-zero) return value
3078% indicates success.
3079%
3080% The format of the SetImageInfo method is:
3081%
3082% MagickBooleanType SetImageInfo(ImageInfo *image_info,
cristyd965a422010-03-03 17:47:35 +00003083% const unsigned int frames,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003084%
3085% A description of each parameter follows:
3086%
cristyd965a422010-03-03 17:47:35 +00003087% o image_info: the image info.
cristy3ed852e2009-09-05 21:47:34 +00003088%
cristyd965a422010-03-03 17:47:35 +00003089% o frames: the number of images you intend to write.
cristy3ed852e2009-09-05 21:47:34 +00003090%
3091% o exception: return any errors or warnings in this structure.
3092%
3093*/
3094MagickExport MagickBooleanType SetImageInfo(ImageInfo *image_info,
cristyd965a422010-03-03 17:47:35 +00003095 const unsigned int frames,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00003096{
3097 char
3098 extension[MaxTextExtent],
3099 filename[MaxTextExtent],
3100 magic[MaxTextExtent],
3101 *q,
3102 subimage[MaxTextExtent];
3103
3104 const MagicInfo
3105 *magic_info;
3106
3107 const MagickInfo
3108 *magick_info;
3109
3110 ExceptionInfo
3111 *sans_exception;
3112
3113 Image
3114 *image;
3115
3116 MagickBooleanType
3117 status;
3118
3119 register const char
3120 *p;
3121
3122 ssize_t
3123 count;
3124
3125 unsigned char
3126 magick[2*MaxTextExtent];
3127
3128 /*
3129 Look for 'image.format' in filename.
3130 */
3131 assert(image_info != (ImageInfo *) NULL);
3132 assert(image_info->signature == MagickSignature);
3133 if (image_info->debug != MagickFalse)
3134 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3135 image_info->filename);
3136 *subimage='\0';
cristyd965a422010-03-03 17:47:35 +00003137 if (frames == 0)
cristy3ed852e2009-09-05 21:47:34 +00003138 {
cristyd965a422010-03-03 17:47:35 +00003139 GetPathComponent(image_info->filename,SubimagePath,subimage);
3140 if (*subimage != '\0')
cristy3ed852e2009-09-05 21:47:34 +00003141 {
cristyd965a422010-03-03 17:47:35 +00003142 /*
3143 Look for scene specification (e.g. img0001.pcd[4]).
3144 */
3145 if (IsSceneGeometry(subimage,MagickFalse) == MagickFalse)
3146 {
3147 if (IsGeometry(subimage) != MagickFalse)
3148 (void) CloneString(&image_info->extract,subimage);
3149 }
3150 else
3151 {
cristybb503372010-05-27 20:51:26 +00003152 size_t
cristyd965a422010-03-03 17:47:35 +00003153 first,
3154 last;
cristy3ed852e2009-09-05 21:47:34 +00003155
cristyd965a422010-03-03 17:47:35 +00003156 (void) CloneString(&image_info->scenes,subimage);
3157 image_info->scene=StringToUnsignedLong(image_info->scenes);
3158 image_info->number_scenes=image_info->scene;
3159 p=image_info->scenes;
3160 for (q=(char *) image_info->scenes; *q != '\0'; p++)
3161 {
3162 while ((isspace((int) ((unsigned char) *p)) != 0) ||
3163 (*p == ','))
3164 p++;
cristybb503372010-05-27 20:51:26 +00003165 first=(size_t) strtol(p,&q,10);
cristyd965a422010-03-03 17:47:35 +00003166 last=first;
3167 while (isspace((int) ((unsigned char) *q)) != 0)
3168 q++;
3169 if (*q == '-')
cristybb503372010-05-27 20:51:26 +00003170 last=(size_t) strtol(q+1,&q,10);
cristyd965a422010-03-03 17:47:35 +00003171 if (first > last)
3172 Swap(first,last);
3173 if (first < image_info->scene)
3174 image_info->scene=first;
3175 if (last > image_info->number_scenes)
3176 image_info->number_scenes=last;
3177 p=q;
3178 }
3179 image_info->number_scenes-=image_info->scene-1;
3180 image_info->subimage=image_info->scene;
3181 image_info->subrange=image_info->number_scenes;
3182 }
cristy3ed852e2009-09-05 21:47:34 +00003183 }
3184 }
3185 *extension='\0';
3186 GetPathComponent(image_info->filename,ExtensionPath,extension);
3187#if defined(MAGICKCORE_ZLIB_DELEGATE)
3188 if (*extension != '\0')
3189 if ((LocaleCompare(extension,"gz") == 0) ||
3190 (LocaleCompare(extension,"Z") == 0) ||
3191 (LocaleCompare(extension,"wmz") == 0))
3192 {
3193 char
3194 path[MaxTextExtent];
3195
3196 (void) CopyMagickString(path,image_info->filename,MaxTextExtent);
3197 path[strlen(path)-strlen(extension)-1]='\0';
3198 GetPathComponent(path,ExtensionPath,extension);
3199 }
3200#endif
3201#if defined(MAGICKCORE_BZLIB_DELEGATE)
3202 if (*extension != '\0')
3203 if (LocaleCompare(extension,"bz2") == 0)
3204 {
3205 char
3206 path[MaxTextExtent];
3207
3208 (void) CopyMagickString(path,image_info->filename,MaxTextExtent);
3209 path[strlen(path)-strlen(extension)-1]='\0';
3210 GetPathComponent(path,ExtensionPath,extension);
3211 }
3212#endif
3213 image_info->affirm=MagickFalse;
3214 sans_exception=AcquireExceptionInfo();
3215 if (*extension != '\0')
3216 {
3217 MagickFormatType
3218 format_type;
3219
cristybb503372010-05-27 20:51:26 +00003220 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00003221 i;
3222
3223 static const char
3224 *format_type_formats[] =
3225 {
3226 "AUTOTRACE",
3227 "BROWSE",
3228 "DCRAW",
3229 "EDIT",
3230 "EPHEMERAL",
3231 "LAUNCH",
3232 "MPEG:DECODE",
3233 "MPEG:ENCODE",
3234 "PRINT",
3235 "PS:ALPHA",
3236 "PS:CMYK",
3237 "PS:COLOR",
3238 "PS:GRAY",
3239 "PS:MONO",
3240 "SCAN",
3241 "SHOW",
3242 "WIN",
3243 (char *) NULL
3244 };
3245
3246 /*
3247 User specified image format.
3248 */
3249 (void) CopyMagickString(magic,extension,MaxTextExtent);
3250 LocaleUpper(magic);
3251 /*
3252 Look for explicit image formats.
3253 */
3254 format_type=UndefinedFormatType;
3255 i=0;
cristydd9a2532010-02-20 19:26:46 +00003256 while ((format_type == UndefinedFormatType) &&
cristy3ed852e2009-09-05 21:47:34 +00003257 (format_type_formats[i] != (char *) NULL))
3258 {
3259 if ((*magic == *format_type_formats[i]) &&
3260 (LocaleCompare(magic,format_type_formats[i]) == 0))
3261 format_type=ExplicitFormatType;
3262 i++;
3263 }
3264 magick_info=GetMagickInfo(magic,sans_exception);
3265 if ((magick_info != (const MagickInfo *) NULL) &&
3266 (magick_info->format_type != UndefinedFormatType))
3267 format_type=magick_info->format_type;
3268 if (format_type == UndefinedFormatType)
3269 (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
3270 else
3271 if (format_type == ExplicitFormatType)
3272 {
3273 image_info->affirm=MagickTrue;
3274 (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
3275 }
3276 if (LocaleCompare(magic,"RGB") == 0)
3277 image_info->affirm=MagickFalse; /* maybe SGI disguised as RGB */
3278 }
3279 /*
3280 Look for explicit 'format:image' in filename.
3281 */
3282 *magic='\0';
3283 GetPathComponent(image_info->filename,MagickPath,magic);
3284 if (*magic == '\0')
3285 (void) CopyMagickString(magic,image_info->magick,MaxTextExtent);
3286 else
3287 {
3288 /*
3289 User specified image format.
3290 */
3291 LocaleUpper(magic);
3292 if (IsMagickConflict(magic) == MagickFalse)
3293 {
3294 (void) CopyMagickString(image_info->magick,magic,MaxTextExtent);
3295 if (LocaleCompare(magic,"EPHEMERAL") != 0)
3296 image_info->affirm=MagickTrue;
3297 else
3298 image_info->temporary=MagickTrue;
3299 }
3300 }
3301 magick_info=GetMagickInfo(magic,sans_exception);
3302 sans_exception=DestroyExceptionInfo(sans_exception);
3303 if ((magick_info == (const MagickInfo *) NULL) ||
3304 (GetMagickEndianSupport(magick_info) == MagickFalse))
3305 image_info->endian=UndefinedEndian;
3306 GetPathComponent(image_info->filename,CanonicalPath,filename);
3307 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
cristyd965a422010-03-03 17:47:35 +00003308 if ((image_info->adjoin != MagickFalse) && (frames > 1))
cristy3ed852e2009-09-05 21:47:34 +00003309 {
3310 /*
cristyd965a422010-03-03 17:47:35 +00003311 Test for multiple image support (e.g. image%02d.png).
cristy3ed852e2009-09-05 21:47:34 +00003312 */
cristyd965a422010-03-03 17:47:35 +00003313 (void) InterpretImageFilename(image_info,(Image *) NULL,
3314 image_info->filename,(int) image_info->scene,filename);
3315 if ((LocaleCompare(filename,image_info->filename) != 0) &&
3316 (strchr(filename,'%') == (char *) NULL))
3317 image_info->adjoin=MagickFalse;
3318 }
3319 if ((image_info->adjoin != MagickFalse) && (frames > 0))
3320 {
3321 /*
3322 Some image formats do not support multiple frames per file.
3323 */
cristy3ed852e2009-09-05 21:47:34 +00003324 magick_info=GetMagickInfo(magic,exception);
3325 if (magick_info != (const MagickInfo *) NULL)
3326 if (GetMagickAdjoin(magick_info) == MagickFalse)
3327 image_info->adjoin=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00003328 }
3329 if (image_info->affirm != MagickFalse)
3330 return(MagickTrue);
cristyd965a422010-03-03 17:47:35 +00003331 if (frames == 0)
cristy3ed852e2009-09-05 21:47:34 +00003332 {
3333 /*
cristyd965a422010-03-03 17:47:35 +00003334 Determine the image format from the first few bytes of the file.
cristy3ed852e2009-09-05 21:47:34 +00003335 */
cristyd965a422010-03-03 17:47:35 +00003336 image=AcquireImage(image_info);
3337 (void) CopyMagickString(image->filename,image_info->filename,
3338 MaxTextExtent);
cristy3ed852e2009-09-05 21:47:34 +00003339 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
3340 if (status == MagickFalse)
3341 {
3342 image=DestroyImage(image);
3343 return(MagickFalse);
3344 }
cristyd965a422010-03-03 17:47:35 +00003345 if ((IsBlobSeekable(image) == MagickFalse) ||
3346 (IsBlobExempt(image) != MagickFalse))
3347 {
3348 /*
3349 Copy standard input or pipe to temporary file.
3350 */
3351 *filename='\0';
3352 status=ImageToFile(image,filename,exception);
3353 (void) CloseBlob(image);
3354 if (status == MagickFalse)
3355 {
3356 image=DestroyImage(image);
3357 return(MagickFalse);
3358 }
3359 SetImageInfoFile(image_info,(FILE *) NULL);
3360 (void) CopyMagickString(image->filename,filename,MaxTextExtent);
3361 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
3362 if (status == MagickFalse)
3363 {
3364 image=DestroyImage(image);
3365 return(MagickFalse);
3366 }
3367 (void) CopyMagickString(image_info->filename,filename,MaxTextExtent);
3368 image_info->temporary=MagickTrue;
3369 }
3370 (void) ResetMagickMemory(magick,0,sizeof(magick));
3371 count=ReadBlob(image,2*MaxTextExtent,magick);
3372 (void) CloseBlob(image);
3373 image=DestroyImage(image);
3374 /*
3375 Check magic.xml configuration file.
3376 */
3377 sans_exception=AcquireExceptionInfo();
3378 magic_info=GetMagicInfo(magick,(size_t) count,sans_exception);
3379 if ((magic_info != (const MagicInfo *) NULL) &&
3380 (GetMagicName(magic_info) != (char *) NULL))
3381 {
3382 (void) CopyMagickString(image_info->magick,GetMagicName(magic_info),
3383 MaxTextExtent);
3384 magick_info=GetMagickInfo(image_info->magick,sans_exception);
3385 if ((magick_info == (const MagickInfo *) NULL) ||
3386 (GetMagickEndianSupport(magick_info) == MagickFalse))
3387 image_info->endian=UndefinedEndian;
3388 sans_exception=DestroyExceptionInfo(sans_exception);
3389 return(MagickTrue);
3390 }
cristy3ed852e2009-09-05 21:47:34 +00003391 magick_info=GetMagickInfo(image_info->magick,sans_exception);
3392 if ((magick_info == (const MagickInfo *) NULL) ||
3393 (GetMagickEndianSupport(magick_info) == MagickFalse))
3394 image_info->endian=UndefinedEndian;
3395 sans_exception=DestroyExceptionInfo(sans_exception);
cristy3ed852e2009-09-05 21:47:34 +00003396 }
cristy3ed852e2009-09-05 21:47:34 +00003397 return(MagickTrue);
3398}
3399
3400/*
3401%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3402% %
3403% %
3404% %
3405% S e t I m a g e I n f o B l o b %
3406% %
3407% %
3408% %
3409%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3410%
3411% SetImageInfoBlob() sets the image info blob member.
3412%
3413% The format of the SetImageInfoBlob method is:
3414%
3415% void SetImageInfoBlob(ImageInfo *image_info,const void *blob,
3416% const size_t length)
3417%
3418% A description of each parameter follows:
3419%
3420% o image_info: the image info.
3421%
3422% o blob: the blob.
3423%
3424% o length: the blob length.
3425%
3426*/
3427MagickExport void SetImageInfoBlob(ImageInfo *image_info,const void *blob,
3428 const size_t length)
3429{
3430 assert(image_info != (ImageInfo *) NULL);
3431 assert(image_info->signature == MagickSignature);
3432 if (image_info->debug != MagickFalse)
3433 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3434 image_info->filename);
3435 image_info->blob=(void *) blob;
3436 image_info->length=length;
3437}
3438
3439/*
3440%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3441% %
3442% %
3443% %
3444% S e t I m a g e I n f o F i l e %
3445% %
3446% %
3447% %
3448%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3449%
3450% SetImageInfoFile() sets the image info file member.
3451%
3452% The format of the SetImageInfoFile method is:
3453%
3454% void SetImageInfoFile(ImageInfo *image_info,FILE *file)
3455%
3456% A description of each parameter follows:
3457%
3458% o image_info: the image info.
3459%
3460% o file: the file.
3461%
3462*/
3463MagickExport void SetImageInfoFile(ImageInfo *image_info,FILE *file)
3464{
3465 assert(image_info != (ImageInfo *) NULL);
3466 assert(image_info->signature == MagickSignature);
3467 if (image_info->debug != MagickFalse)
3468 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
3469 image_info->filename);
3470 image_info->file=file;
3471}
3472
3473/*
3474%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3475% %
3476% %
3477% %
3478% S e t I m a g e M a s k %
3479% %
3480% %
3481% %
3482%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3483%
3484% SetImageMask() associates a mask with the image. The mask must be the same
3485% dimensions as the image.
3486%
3487% The format of the SetImageMask method is:
3488%
3489% MagickBooleanType SetImageMask(Image *image,const Image *mask)
3490%
3491% A description of each parameter follows:
3492%
3493% o image: the image.
3494%
3495% o mask: the image mask.
3496%
3497*/
3498MagickExport MagickBooleanType SetImageMask(Image *image,
3499 const Image *mask)
3500{
3501 assert(image != (Image *) NULL);
3502 if (image->debug != MagickFalse)
3503 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3504 assert(image->signature == MagickSignature);
3505 if (mask != (const Image *) NULL)
3506 if ((mask->columns != image->columns) || (mask->rows != image->rows))
3507 ThrowBinaryException(ImageError,"ImageSizeDiffers",image->filename);
3508 if (image->mask != (Image *) NULL)
3509 image->mask=DestroyImage(image->mask);
3510 image->mask=NewImageList();
3511 if (mask == (Image *) NULL)
3512 return(MagickTrue);
3513 if (SetImageStorageClass(image,DirectClass) == MagickFalse)
3514 return(MagickFalse);
3515 image->mask=CloneImage(mask,0,0,MagickTrue,&image->exception);
3516 if (image->mask == (Image *) NULL)
3517 return(MagickFalse);
3518 return(MagickTrue);
3519}
3520
3521/*
3522%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3523% %
3524% %
3525% %
3526% S e t I m a g e O p a c i t y %
3527% %
3528% %
3529% %
3530%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3531%
3532% SetImageOpacity() sets the opacity levels of the image.
3533%
3534% The format of the SetImageOpacity method is:
3535%
3536% MagickBooleanType SetImageOpacity(Image *image,const Quantum opacity)
3537%
3538% A description of each parameter follows:
3539%
3540% o image: the image.
3541%
3542% o opacity: the level of transparency: 0 is fully opaque and QuantumRange is
3543% fully transparent.
3544%
3545*/
3546MagickExport MagickBooleanType SetImageOpacity(Image *image,
3547 const Quantum opacity)
3548{
3549 CacheView
3550 *image_view;
3551
3552 ExceptionInfo
3553 *exception;
3554
cristy3ed852e2009-09-05 21:47:34 +00003555 MagickBooleanType
3556 status;
3557
cristycb6d09b2010-06-19 01:59:36 +00003558 ssize_t
3559 y;
3560
cristy3ed852e2009-09-05 21:47:34 +00003561 assert(image != (Image *) NULL);
3562 if (image->debug != MagickFalse)
3563 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3564 assert(image->signature == MagickSignature);
3565 image->matte=opacity != OpaqueOpacity ? MagickTrue : MagickFalse;
3566 status=MagickTrue;
3567 exception=(&image->exception);
3568 image_view=AcquireCacheView(image);
cristyb5d5f722009-11-04 03:03:49 +00003569#if defined(MAGICKCORE_OPENMP_SUPPORT)
3570 #pragma omp parallel for schedule(dynamic,4) shared(status)
cristy3ed852e2009-09-05 21:47:34 +00003571#endif
cristybb503372010-05-27 20:51:26 +00003572 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00003573 {
cristy3ed852e2009-09-05 21:47:34 +00003574 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00003575 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00003576
cristycb6d09b2010-06-19 01:59:36 +00003577 register ssize_t
3578 x;
3579
cristy3ed852e2009-09-05 21:47:34 +00003580 if (status == MagickFalse)
3581 continue;
3582 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3583 if (q == (PixelPacket *) NULL)
3584 {
3585 status=MagickFalse;
3586 continue;
3587 }
cristybb503372010-05-27 20:51:26 +00003588 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00003589 {
cristy46f08202010-01-10 04:04:21 +00003590 SetOpacityPixelComponent(q,opacity);
cristy3ed852e2009-09-05 21:47:34 +00003591 q++;
3592 }
3593 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3594 status=MagickFalse;
3595 }
3596 image_view=DestroyCacheView(image_view);
3597 return(status);
3598}
3599
3600/*
3601%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3602% %
3603% %
3604% %
3605% S e t I m a g e T y p e %
3606% %
3607% %
3608% %
3609%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3610%
3611% SetImageType() sets the type of image. Choose from these types:
3612%
3613% Bilevel Grayscale GrayscaleMatte
3614% Palette PaletteMatte TrueColor
3615% TrueColorMatte ColorSeparation ColorSeparationMatte
3616% OptimizeType
3617%
3618% The format of the SetImageType method is:
3619%
3620% MagickBooleanType SetImageType(Image *image,const ImageType type)
3621%
3622% A description of each parameter follows:
3623%
3624% o image: the image.
3625%
3626% o type: Image type.
3627%
3628*/
3629MagickExport MagickBooleanType SetImageType(Image *image,const ImageType type)
3630{
3631 const char
3632 *artifact;
3633
3634 ImageInfo
3635 *image_info;
3636
3637 MagickBooleanType
3638 status;
3639
3640 QuantizeInfo
3641 *quantize_info;
3642
3643 assert(image != (Image *) NULL);
3644 if (image->debug != MagickFalse)
3645 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3646 assert(image->signature == MagickSignature);
3647 status=MagickTrue;
3648 image_info=AcquireImageInfo();
3649 image_info->dither=image->dither;
3650 artifact=GetImageArtifact(image,"dither");
3651 if (artifact != (const char *) NULL)
3652 (void) SetImageOption(image_info,"dither",artifact);
3653 switch (type)
3654 {
3655 case BilevelType:
3656 {
3657 if (IsGrayImage(image,&image->exception) == MagickFalse)
3658 status=TransformImageColorspace(image,GRAYColorspace);
3659 if (IsMonochromeImage(image,&image->exception) == MagickFalse)
3660 {
3661 quantize_info=AcquireQuantizeInfo(image_info);
3662 quantize_info->number_colors=2;
3663 quantize_info->colorspace=GRAYColorspace;
3664 status=QuantizeImage(quantize_info,image);
3665 quantize_info=DestroyQuantizeInfo(quantize_info);
3666 }
3667 image->matte=MagickFalse;
3668 break;
3669 }
3670 case GrayscaleType:
3671 {
3672 if (IsGrayImage(image,&image->exception) == MagickFalse)
3673 status=TransformImageColorspace(image,GRAYColorspace);
3674 image->matte=MagickFalse;
3675 break;
3676 }
3677 case GrayscaleMatteType:
3678 {
3679 if (IsGrayImage(image,&image->exception) == MagickFalse)
3680 status=TransformImageColorspace(image,GRAYColorspace);
3681 if (image->matte == MagickFalse)
3682 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
3683 break;
3684 }
3685 case PaletteType:
3686 {
3687 if (image->colorspace != RGBColorspace)
3688 status=TransformImageColorspace(image,RGBColorspace);
3689 if ((image->storage_class == DirectClass) || (image->colors > 256))
3690 {
3691 quantize_info=AcquireQuantizeInfo(image_info);
3692 quantize_info->number_colors=256;
3693 status=QuantizeImage(quantize_info,image);
3694 quantize_info=DestroyQuantizeInfo(quantize_info);
3695 }
3696 image->matte=MagickFalse;
3697 break;
3698 }
3699 case PaletteBilevelMatteType:
3700 {
3701 if (image->colorspace != RGBColorspace)
3702 status=TransformImageColorspace(image,RGBColorspace);
3703 if (image->matte == MagickFalse)
3704 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
3705 (void) BilevelImageChannel(image,AlphaChannel,(double) QuantumRange/2.0);
3706 quantize_info=AcquireQuantizeInfo(image_info);
3707 status=QuantizeImage(quantize_info,image);
3708 quantize_info=DestroyQuantizeInfo(quantize_info);
3709 break;
3710 }
3711 case PaletteMatteType:
3712 {
3713 if (image->colorspace != RGBColorspace)
3714 status=TransformImageColorspace(image,RGBColorspace);
3715 if (image->matte == MagickFalse)
3716 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
3717 quantize_info=AcquireQuantizeInfo(image_info);
3718 quantize_info->colorspace=TransparentColorspace;
3719 status=QuantizeImage(quantize_info,image);
3720 quantize_info=DestroyQuantizeInfo(quantize_info);
3721 break;
3722 }
3723 case TrueColorType:
3724 {
3725 if (image->colorspace != RGBColorspace)
3726 status=TransformImageColorspace(image,RGBColorspace);
3727 if (image->storage_class != DirectClass)
3728 status=SetImageStorageClass(image,DirectClass);
3729 image->matte=MagickFalse;
3730 break;
3731 }
3732 case TrueColorMatteType:
3733 {
3734 if (image->colorspace != RGBColorspace)
3735 status=TransformImageColorspace(image,RGBColorspace);
3736 if (image->storage_class != DirectClass)
3737 status=SetImageStorageClass(image,DirectClass);
3738 if (image->matte == MagickFalse)
3739 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
3740 break;
3741 }
3742 case ColorSeparationType:
3743 {
3744 if (image->colorspace != CMYKColorspace)
3745 {
3746 if (image->colorspace != RGBColorspace)
3747 status=TransformImageColorspace(image,RGBColorspace);
3748 status=TransformImageColorspace(image,CMYKColorspace);
3749 }
3750 if (image->storage_class != DirectClass)
3751 status=SetImageStorageClass(image,DirectClass);
3752 image->matte=MagickFalse;
3753 break;
3754 }
3755 case ColorSeparationMatteType:
3756 {
3757 if (image->colorspace != CMYKColorspace)
3758 {
3759 if (image->colorspace != RGBColorspace)
3760 status=TransformImageColorspace(image,RGBColorspace);
3761 status=TransformImageColorspace(image,CMYKColorspace);
3762 }
3763 if (image->storage_class != DirectClass)
3764 status=SetImageStorageClass(image,DirectClass);
3765 if (image->matte == MagickFalse)
3766 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel);
3767 break;
3768 }
3769 case OptimizeType:
3770 case UndefinedType:
3771 break;
3772 }
3773 image->type=type;
3774 image_info=DestroyImageInfo(image_info);
3775 return(status);
3776}
3777
3778/*
3779%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3780% %
3781% %
3782% %
3783% 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 %
3784% %
3785% %
3786% %
3787%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3788%
3789% SetImageVirtualPixelMethod() sets the "virtual pixels" method for the
3790% image and returns the previous setting. A virtual pixel is any pixel access
3791% that is outside the boundaries of the image cache.
3792%
3793% The format of the SetImageVirtualPixelMethod() method is:
3794%
3795% VirtualPixelMethod SetImageVirtualPixelMethod(const Image *image,
3796% const VirtualPixelMethod virtual_pixel_method)
3797%
3798% A description of each parameter follows:
3799%
3800% o image: the image.
3801%
3802% o virtual_pixel_method: choose the type of virtual pixel.
3803%
3804*/
3805MagickExport VirtualPixelMethod SetImageVirtualPixelMethod(const Image *image,
3806 const VirtualPixelMethod virtual_pixel_method)
3807{
3808 assert(image != (const Image *) NULL);
3809 assert(image->signature == MagickSignature);
3810 if (image->debug != MagickFalse)
3811 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3812 return(SetPixelCacheVirtualMethod(image,virtual_pixel_method));
3813}
3814
3815/*
3816%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3817% %
3818% %
3819% %
cristy3ed852e2009-09-05 21:47:34 +00003820% S t r i p I m a g e %
3821% %
3822% %
3823% %
3824%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3825%
cristy376bda92009-12-22 21:15:23 +00003826% StripImage() strips an image of all profiles and comments.
cristy3ed852e2009-09-05 21:47:34 +00003827%
3828% The format of the StripImage method is:
3829%
3830% MagickBooleanType StripImage(Image *image)
3831%
3832% A description of each parameter follows:
3833%
3834% o image: the image.
3835%
3836*/
3837MagickExport MagickBooleanType StripImage(Image *image)
3838{
3839 assert(image != (Image *) NULL);
3840 if (image->debug != MagickFalse)
3841 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3842 DestroyImageProfiles(image);
cristy6b9aca12010-02-21 01:50:11 +00003843 (void) DeleteImageProperty(image,"comment");
cristy3ed852e2009-09-05 21:47:34 +00003844 return(MagickTrue);
3845}
3846
3847/*
3848%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3849% %
3850% %
3851% %
3852+ S y n c I m a g e %
3853% %
3854% %
3855% %
3856%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3857%
3858% SyncImage() initializes the red, green, and blue intensities of each pixel
3859% as defined by the colormap index.
3860%
3861% The format of the SyncImage method is:
3862%
3863% MagickBooleanType SyncImage(Image *image)
3864%
3865% A description of each parameter follows:
3866%
3867% o image: the image.
3868%
3869*/
3870
3871static inline IndexPacket PushColormapIndex(Image *image,
cristybb503372010-05-27 20:51:26 +00003872 const size_t index,MagickBooleanType *range_exception)
cristy3ed852e2009-09-05 21:47:34 +00003873{
3874 if (index < image->colors)
3875 return((IndexPacket) index);
3876 *range_exception=MagickTrue;
3877 return((IndexPacket) 0);
3878}
3879
3880MagickExport MagickBooleanType SyncImage(Image *image)
3881{
3882 CacheView
3883 *image_view;
3884
3885 ExceptionInfo
3886 *exception;
3887
cristy3ed852e2009-09-05 21:47:34 +00003888 MagickBooleanType
3889 range_exception,
3890 status;
3891
cristycb6d09b2010-06-19 01:59:36 +00003892 ssize_t
3893 y;
3894
cristy3ed852e2009-09-05 21:47:34 +00003895 assert(image != (Image *) NULL);
3896 if (image->debug != MagickFalse)
3897 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
3898 assert(image->signature == MagickSignature);
3899 if (image->storage_class == DirectClass)
3900 return(MagickFalse);
3901 range_exception=MagickFalse;
3902 status=MagickTrue;
3903 exception=(&image->exception);
3904 image_view=AcquireCacheView(image);
cristy48974b92009-12-19 02:36:06 +00003905#if defined(MAGICKCORE_OPENMP_SUPPORT)
3906 #pragma omp parallel for schedule(dynamic,4) shared(status)
3907#endif
cristybb503372010-05-27 20:51:26 +00003908 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00003909 {
3910 IndexPacket
3911 index;
3912
3913 PixelPacket
3914 pixel;
3915
3916 register IndexPacket
cristyc47d1f82009-11-26 01:44:43 +00003917 *restrict indexes;
cristy3ed852e2009-09-05 21:47:34 +00003918
cristy3ed852e2009-09-05 21:47:34 +00003919 register PixelPacket
cristyc47d1f82009-11-26 01:44:43 +00003920 *restrict q;
cristy3ed852e2009-09-05 21:47:34 +00003921
cristycb6d09b2010-06-19 01:59:36 +00003922 register ssize_t
3923 x;
3924
cristy48974b92009-12-19 02:36:06 +00003925 if (status == MagickFalse)
3926 continue;
cristy3ed852e2009-09-05 21:47:34 +00003927 q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
3928 if (q == (PixelPacket *) NULL)
3929 {
3930 status=MagickFalse;
3931 continue;
3932 }
3933 indexes=GetCacheViewAuthenticIndexQueue(image_view);
cristybb503372010-05-27 20:51:26 +00003934 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +00003935 {
cristybb503372010-05-27 20:51:26 +00003936 index=PushColormapIndex(image,(size_t) indexes[x],
cristy3ed852e2009-09-05 21:47:34 +00003937 &range_exception);
cristybb503372010-05-27 20:51:26 +00003938 pixel=image->colormap[(ssize_t) index];
cristy3ed852e2009-09-05 21:47:34 +00003939 q->red=pixel.red;
3940 q->green=pixel.green;
3941 q->blue=pixel.blue;
cristyd0272592010-04-21 01:01:49 +00003942 if (image->matte != MagickFalse)
3943 q->opacity=pixel.opacity;
cristy3ed852e2009-09-05 21:47:34 +00003944 q++;
3945 }
3946 if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
3947 status=MagickFalse;
cristy3ed852e2009-09-05 21:47:34 +00003948 }
3949 image_view=DestroyCacheView(image_view);
3950 if (range_exception != MagickFalse)
3951 (void) ThrowMagickException(&image->exception,GetMagickModule(),
3952 CorruptImageError,"InvalidColormapIndex","`%s'",image->filename);
3953 return(status);
3954}
cristy1626d332009-11-10 16:58:17 +00003955
3956/*
3957%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3958% %
3959% %
3960% %
3961% S y n c I m a g e S e t t i n g s %
3962% %
3963% %
3964% %
3965%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3966%
3967% SyncImageSettings() sync the image info options to the image.
3968%
3969% The format of the SyncImageSettings method is:
3970%
3971% MagickBooleanType SyncImageSettings(const ImageInfo *image_info,
3972% Image *image)
3973% MagickBooleanType SyncImagesSettings(const ImageInfo *image_info,
3974% Image *image)
3975%
3976% A description of each parameter follows:
3977%
3978% o image_info: the image info.
3979%
3980% o image: the image.
3981%
3982*/
3983
3984MagickExport MagickBooleanType SyncImagesSettings(ImageInfo *image_info,
3985 Image *images)
3986{
3987 Image
3988 *image;
3989
3990 assert(image_info != (const ImageInfo *) NULL);
3991 assert(image_info->signature == MagickSignature);
3992 assert(images != (Image *) NULL);
3993 assert(images->signature == MagickSignature);
3994 if (images->debug != MagickFalse)
3995 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename);
3996 image=images;
3997 for ( ; image != (Image *) NULL; image=GetNextImageInList(image))
3998 (void) SyncImageSettings(image_info,image);
3999 (void) DeleteImageOption(image_info,"page");
4000 return(MagickTrue);
4001}
4002
4003MagickExport MagickBooleanType SyncImageSettings(const ImageInfo *image_info,
4004 Image *image)
4005{
4006 char
4007 property[MaxTextExtent];
4008
4009 const char
cristy9a703812010-07-26 14:50:29 +00004010 *option,
4011 *value;
cristy1626d332009-11-10 16:58:17 +00004012
4013 GeometryInfo
4014 geometry_info;
4015
4016 MagickStatusType
4017 flags;
4018
cristy19eb6412010-04-23 14:42:29 +00004019 ResolutionType
4020 units;
4021
cristy1626d332009-11-10 16:58:17 +00004022 /*
4023 Sync image options.
4024 */
4025 assert(image_info != (const ImageInfo *) NULL);
4026 assert(image_info->signature == MagickSignature);
4027 assert(image != (Image *) NULL);
4028 assert(image->signature == MagickSignature);
4029 if (image->debug != MagickFalse)
4030 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
4031 option=GetImageOption(image_info,"background");
4032 if (option != (const char *) NULL)
4033 (void) QueryColorDatabase(option,&image->background_color,
4034 &image->exception);
4035 option=GetImageOption(image_info,"bias");
4036 if (option != (const char *) NULL)
cristyf2f27272009-12-17 14:48:46 +00004037 image->bias=SiPrefixToDouble(option,QuantumRange);
cristy1626d332009-11-10 16:58:17 +00004038 option=GetImageOption(image_info,"black-point-compensation");
4039 if (option != (const char *) NULL)
4040 image->black_point_compensation=(MagickBooleanType) ParseMagickOption(
4041 MagickBooleanOptions,MagickFalse,option);
4042 option=GetImageOption(image_info,"blue-primary");
4043 if (option != (const char *) NULL)
4044 {
4045 flags=ParseGeometry(option,&geometry_info);
4046 image->chromaticity.blue_primary.x=geometry_info.rho;
4047 image->chromaticity.blue_primary.y=geometry_info.sigma;
4048 if ((flags & SigmaValue) == 0)
4049 image->chromaticity.blue_primary.y=image->chromaticity.blue_primary.x;
4050 }
4051 option=GetImageOption(image_info,"bordercolor");
4052 if (option != (const char *) NULL)
4053 (void) QueryColorDatabase(option,&image->border_color,&image->exception);
4054 option=GetImageOption(image_info,"colors");
4055 if (option != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00004056 image->colors=StringToUnsignedLong(option);
cristy1626d332009-11-10 16:58:17 +00004057 option=GetImageOption(image_info,"compose");
4058 if (option != (const char *) NULL)
4059 image->compose=(CompositeOperator) ParseMagickOption(MagickComposeOptions,
4060 MagickFalse,option);
4061 option=GetImageOption(image_info,"compress");
4062 if (option != (const char *) NULL)
4063 image->compression=(CompressionType) ParseMagickOption(
4064 MagickCompressOptions,MagickFalse,option);
4065 option=GetImageOption(image_info,"debug");
4066 if (option != (const char *) NULL)
4067 image->debug=(MagickBooleanType) ParseMagickOption(MagickBooleanOptions,
4068 MagickFalse,option);
cristy1626d332009-11-10 16:58:17 +00004069 option=GetImageOption(image_info,"depth");
4070 if (option != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00004071 image->depth=StringToUnsignedLong(option);
cristy1626d332009-11-10 16:58:17 +00004072 option=GetImageOption(image_info,"endian");
4073 if (option != (const char *) NULL)
4074 image->endian=(EndianType) ParseMagickOption(MagickEndianOptions,
4075 MagickFalse,option);
4076 if (image_info->extract != (char *) NULL)
4077 (void) ParseAbsoluteGeometry(image_info->extract,&image->extract_info);
4078 option=GetImageOption(image_info,"filter");
4079 if (option != (const char *) NULL)
4080 image->filter=(FilterTypes) ParseMagickOption(MagickFilterOptions,
4081 MagickFalse,option);
4082 option=GetImageOption(image_info,"fuzz");
4083 if (option != (const char *) NULL)
cristyf2f27272009-12-17 14:48:46 +00004084 image->fuzz=SiPrefixToDouble(option,QuantumRange);
cristy1626d332009-11-10 16:58:17 +00004085 option=GetImageOption(image_info,"gravity");
4086 if (option != (const char *) NULL)
4087 image->gravity=(GravityType) ParseMagickOption(MagickGravityOptions,
4088 MagickFalse,option);
4089 option=GetImageOption(image_info,"green-primary");
4090 if (option != (const char *) NULL)
4091 {
4092 flags=ParseGeometry(option,&geometry_info);
4093 image->chromaticity.green_primary.x=geometry_info.rho;
4094 image->chromaticity.green_primary.y=geometry_info.sigma;
4095 if ((flags & SigmaValue) == 0)
4096 image->chromaticity.green_primary.y=image->chromaticity.green_primary.x;
4097 }
4098 option=GetImageOption(image_info,"intent");
4099 if (option != (const char *) NULL)
4100 image->rendering_intent=(RenderingIntent) ParseMagickOption(
4101 MagickIntentOptions,MagickFalse,option);
4102 option=GetImageOption(image_info,"interlace");
4103 if (option != (const char *) NULL)
4104 image->interlace=(InterlaceType) ParseMagickOption(MagickInterlaceOptions,
4105 MagickFalse,option);
4106 option=GetImageOption(image_info,"interpolate");
4107 if (option != (const char *) NULL)
4108 image->interpolate=(InterpolatePixelMethod) ParseMagickOption(
4109 MagickInterpolateOptions,MagickFalse,option);
4110 option=GetImageOption(image_info,"loop");
4111 if (option != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00004112 image->iterations=StringToUnsignedLong(option);
cristy1626d332009-11-10 16:58:17 +00004113 option=GetImageOption(image_info,"mattecolor");
4114 if (option != (const char *) NULL)
4115 (void) QueryColorDatabase(option,&image->matte_color,&image->exception);
4116 option=GetImageOption(image_info,"orient");
4117 if (option != (const char *) NULL)
4118 image->orientation=(OrientationType) ParseMagickOption(
4119 MagickOrientationOptions,MagickFalse,option);
cristy9a703812010-07-26 14:50:29 +00004120 option=GetImageOption(image_info,"page");
4121 if (option != (const char *) NULL)
4122 {
4123 char
4124 *geometry;
4125
4126 geometry=GetPageGeometry(option);
4127 flags=ParseAbsoluteGeometry(geometry,&image->page);
4128 geometry=DestroyString(geometry);
4129 }
cristy1626d332009-11-10 16:58:17 +00004130 option=GetImageOption(image_info,"quality");
4131 if (option != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00004132 image->quality=StringToUnsignedLong(option);
cristy1626d332009-11-10 16:58:17 +00004133 option=GetImageOption(image_info,"red-primary");
4134 if (option != (const char *) NULL)
4135 {
4136 flags=ParseGeometry(option,&geometry_info);
4137 image->chromaticity.red_primary.x=geometry_info.rho;
4138 image->chromaticity.red_primary.y=geometry_info.sigma;
4139 if ((flags & SigmaValue) == 0)
4140 image->chromaticity.red_primary.y=image->chromaticity.red_primary.x;
4141 }
4142 if (image_info->quality != UndefinedCompressionQuality)
4143 image->quality=image_info->quality;
4144 option=GetImageOption(image_info,"scene");
4145 if (option != (const char *) NULL)
cristye27293e2009-12-18 02:53:20 +00004146 image->scene=StringToUnsignedLong(option);
cristy1626d332009-11-10 16:58:17 +00004147 option=GetImageOption(image_info,"taint");
4148 if (option != (const char *) NULL)
4149 image->taint=(MagickBooleanType) ParseMagickOption(MagickBooleanOptions,
4150 MagickFalse,option);
4151 option=GetImageOption(image_info,"tile-offset");
4152 if (option != (const char *) NULL)
4153 {
4154 char
4155 *geometry;
4156
4157 geometry=GetPageGeometry(option);
4158 flags=ParseAbsoluteGeometry(geometry,&image->tile_offset);
4159 geometry=DestroyString(geometry);
4160 }
4161 option=GetImageOption(image_info,"transparent-color");
4162 if (option != (const char *) NULL)
4163 (void) QueryColorDatabase(option,&image->transparent_color,
4164 &image->exception);
4165 option=GetImageOption(image_info,"type");
4166 if (option != (const char *) NULL)
4167 image->type=(ImageType) ParseMagickOption(MagickTypeOptions,MagickFalse,
4168 option);
4169 option=GetImageOption(image_info,"units");
4170 if (option != (const char *) NULL)
cristy19eb6412010-04-23 14:42:29 +00004171 units=(ResolutionType) ParseMagickOption(MagickResolutionOptions,
cristy1626d332009-11-10 16:58:17 +00004172 MagickFalse,option);
cristy19eb6412010-04-23 14:42:29 +00004173 else
4174 units = image_info->units;
4175 if (units != UndefinedResolution)
cristy1626d332009-11-10 16:58:17 +00004176 {
cristy19eb6412010-04-23 14:42:29 +00004177 if (image->units != units)
cristy1626d332009-11-10 16:58:17 +00004178 switch (image->units)
4179 {
4180 case PixelsPerInchResolution:
4181 {
cristy19eb6412010-04-23 14:42:29 +00004182 if (units == PixelsPerCentimeterResolution)
cristy1626d332009-11-10 16:58:17 +00004183 {
4184 image->x_resolution/=2.54;
4185 image->y_resolution/=2.54;
4186 }
4187 break;
4188 }
4189 case PixelsPerCentimeterResolution:
4190 {
cristy19eb6412010-04-23 14:42:29 +00004191 if (units == PixelsPerInchResolution)
cristy1626d332009-11-10 16:58:17 +00004192 {
cristybb503372010-05-27 20:51:26 +00004193 image->x_resolution=(double) ((size_t) (100.0*2.54*
cristy1f9ce9f2010-04-28 11:55:12 +00004194 image->x_resolution+0.5))/100.0;
cristybb503372010-05-27 20:51:26 +00004195 image->y_resolution=(double) ((size_t) (100.0*2.54*
cristy1f9ce9f2010-04-28 11:55:12 +00004196 image->y_resolution+0.5))/100.0;
cristy1626d332009-11-10 16:58:17 +00004197 }
4198 break;
4199 }
4200 default:
4201 break;
4202 }
cristy19eb6412010-04-23 14:42:29 +00004203 image->units=units;
cristy1626d332009-11-10 16:58:17 +00004204 }
4205 option=GetImageOption(image_info,"white-point");
4206 if (option != (const char *) NULL)
4207 {
4208 flags=ParseGeometry(option,&geometry_info);
4209 image->chromaticity.white_point.x=geometry_info.rho;
4210 image->chromaticity.white_point.y=geometry_info.sigma;
4211 if ((flags & SigmaValue) == 0)
4212 image->chromaticity.white_point.y=image->chromaticity.white_point.x;
4213 }
4214 ResetImageOptionIterator(image_info);
4215 for (option=GetNextImageOption(image_info); option != (const char *) NULL; )
4216 {
4217 value=GetImageOption(image_info,option);
4218 if (value != (const char *) NULL)
4219 {
4220 (void) FormatMagickString(property,MaxTextExtent,"%s",option);
4221 (void) SetImageArtifact(image,property,value);
4222 }
4223 option=GetNextImageOption(image_info);
4224 }
4225 return(MagickTrue);
4226}