PageRenderTime 34ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/plugins/ImageMagick-6.3.2/magick/image.c

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