13ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 23ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 33ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 43ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 53ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 63ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% PPPP AAA IIIII N N TTTTT % 73ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% P P A A I NN N T % 83ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% PPPP AAAAA I N N N T % 93ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% P A A I N NN T % 103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% P A A IIIII N N T % 113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% Methods to Paint on an Image % 143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% Software Design % 16de984cdc3631106b1cbbb8d3972b76a0fc27e8e8cristy% Cristy % 173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% July 1998 % 183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 207ce65e7125a4e1df1a274ce373c537a9df9c16cdCristy% Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization % 213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% dedicated to making software imaging solutions freely available. % 223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% You may not use this file except in compliance with the License. You may % 243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% obtain a copy of the License at % 253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% http://www.imagemagick.org/script/license.php % 273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% Unless required by applicable law or agreed to in writing, software % 293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% distributed under the License is distributed on an "AS IS" BASIS, % 303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% See the License for the specific language governing permissions and % 323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% limitations under the License. % 333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Include declarations. 413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 424c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/studio.h" 43542697a1562bf7aef0df9d3e26add9e29373b3a9Cristy#include "MagickCore/artifact.h" 446a2180cee55312a7c0c633670803f9face88a82acristy#include "MagickCore/channel.h" 454c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/color.h" 464c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/color-private.h" 474c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/colorspace-private.h" 484c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/composite.h" 494c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/composite-private.h" 504c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/draw.h" 514c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/draw-private.h" 524c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception.h" 534c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/exception-private.h" 544c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/gem.h" 558ea81224e9ff022e56eb2cddb12860a8b2e90411cristy#include "MagickCore/gem-private.h" 564c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor.h" 574c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor-private.h" 58971aac4f549b1ff5321a6514714dae9354bfa459Cristy#include "MagickCore/option.h" 594c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/paint.h" 604c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/pixel-accessor.h" 61ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy#include "MagickCore/resource_.h" 6295f562af68c6bc67f4137b985c7d05c4eff4fddacristy#include "MagickCore/statistic.h" 634c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/string_.h" 6416f2933cdc208138fe39595082c0d3841d93739cCristy#include "MagickCore/string-private.h" 654c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/thread-private.h" 663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% F l o o d f i l l P a i n t I m a g e % 733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% FloodfillPaintImage() changes the color value of any pixel that matches 793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% target and is an immediate neighbor. If the method FillToBorderMethod is 803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% specified, the color value is changed for any neighbor pixel that does not 813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% match the bordercolor member of image. 823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 83908a0004c30aade661256ab433bdbe5c4dbce23ccristy% By default target must match a particular pixel color exactly. However, 84908a0004c30aade661256ab433bdbe5c4dbce23ccristy% in many cases two colors may differ by a small amount. The fuzz member of 85908a0004c30aade661256ab433bdbe5c4dbce23ccristy% image defines how much tolerance is acceptable to consider two colors as 86908a0004c30aade661256ab433bdbe5c4dbce23ccristy% the same. For example, set fuzz to 10 and the color red at intensities of 87908a0004c30aade661256ab433bdbe5c4dbce23ccristy% 100 and 102 respectively are now interpreted as the same color for the 88908a0004c30aade661256ab433bdbe5c4dbce23ccristy% purposes of the floodfill. 893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% The format of the FloodfillPaintImage method is: 913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% MagickBooleanType FloodfillPaintImage(Image *image, 93d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy% const DrawInfo *draw_info,const PixelInfo target, 94d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy% const ssize_t x_offset,const ssize_t y_offset, 95189e84ce7da8fbf4eb57c908846bcc0bdcbdc688cristy% const MagickBooleanType invert,ExceptionInfo *exception) 963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% A description of each parameter follows: 983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o image: the image. 1003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 1013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o draw_info: the draw info. 1023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 1033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o target: the RGB value of the target color. 1043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 1053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o x_offset,y_offset: the starting location of the operation. 1063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 1073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o invert: paint any pixel that does not match the target color. 1083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 109189e84ce7da8fbf4eb57c908846bcc0bdcbdc688cristy% o exception: return any errors or warnings in this structure. 110189e84ce7da8fbf4eb57c908846bcc0bdcbdc688cristy% 1113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 1123ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport MagickBooleanType FloodfillPaintImage(Image *image, 113d42d995b9cb2a16e13221e665554417a5b7ec7fbcristy const DrawInfo *draw_info,const PixelInfo *target,const ssize_t x_offset, 114189e84ce7da8fbf4eb57c908846bcc0bdcbdc688cristy const ssize_t y_offset,const MagickBooleanType invert, 115189e84ce7da8fbf4eb57c908846bcc0bdcbdc688cristy ExceptionInfo *exception) 1163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 117712467450377a5c8642d6f4aead1f11d803c78a9Cristy#define MaxStacksize 524288UL 1183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define PushSegmentStack(up,left,right,delta) \ 1193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ \ 1203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (s >= (segment_stack+MaxStacksize)) \ 1213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy ThrowBinaryException(DrawError,"SegmentStackOverflow",image->filename) \ 1223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy else \ 1233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { \ 124bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy if ((((up)+(delta)) >= 0) && (((up)+(delta)) < (ssize_t) image->rows)) \ 1253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { \ 1263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy s->x1=(double) (left); \ 1273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy s->y1=(double) (up); \ 1283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy s->x2=(double) (right); \ 1293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy s->y2=(double) (delta); \ 1303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy s++; \ 1313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } \ 1323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } \ 1333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 1343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 135b0d3bb93a8f69add9d2d000ff20e6951e3c1f885cristy CacheView 136b0d3bb93a8f69add9d2d000ff20e6951e3c1f885cristy *floodplane_view, 137b0d3bb93a8f69add9d2d000ff20e6951e3c1f885cristy *image_view; 138b0d3bb93a8f69add9d2d000ff20e6951e3c1f885cristy 1393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Image 1403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *floodplane_image; 1413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 14314973baa8fa5c79889bc4db247200bb7d4626324cristy skip, 14414973baa8fa5c79889bc4db247200bb7d4626324cristy status; 1453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 146aaaff84e53c6dba4988fc076523eb820fdecd084cristy MemoryInfo 147aaaff84e53c6dba4988fc076523eb820fdecd084cristy *segment_info; 148aaaff84e53c6dba4988fc076523eb820fdecd084cristy 1494c08aed51c5899665ade97263692328eea4af106cristy PixelInfo 150fdcc0185fe19084d4009bfc6e2fead8d86c67e64cristy fill_color, 1513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy pixel; 1523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy register SegmentInfo 1543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *s; 1553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy SegmentInfo 1573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *segment_stack; 1583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1599d314ff2c17a77996c05413c2013880387e50f0ecristy ssize_t 1609d314ff2c17a77996c05413c2013880387e50f0ecristy offset, 1619d314ff2c17a77996c05413c2013880387e50f0ecristy start, 1629d314ff2c17a77996c05413c2013880387e50f0ecristy x1, 1639d314ff2c17a77996c05413c2013880387e50f0ecristy x2, 1649d314ff2c17a77996c05413c2013880387e50f0ecristy y; 1659d314ff2c17a77996c05413c2013880387e50f0ecristy 1663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 1673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Check boundary conditions. 1683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 1693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy assert(image != (Image *) NULL); 170e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy assert(image->signature == MagickCoreSignature); 1713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (image->debug != MagickFalse) 1723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 1733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy assert(draw_info != (DrawInfo *) NULL); 174e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy assert(draw_info->signature == MagickCoreSignature); 175bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy if ((x_offset < 0) || (x_offset >= (ssize_t) image->columns)) 1763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 177bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy if ((y_offset < 0) || (y_offset >= (ssize_t) image->rows)) 1783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 179574cc26500992189f637cd1cdf93d0654e7df7aecristy if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 1803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 181a6400b1cfc3594644a0f02f3d77d920092f078eecristy if (IsGrayColorspace(image->colorspace) != MagickFalse) 1820c81d063030f7b30a97c7856e95534243cdc9e13cristy (void) SetImageColorspace(image,sRGBColorspace,exception); 18317f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if ((image->alpha_trait == UndefinedPixelTrait) && 18417f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy (draw_info->fill.alpha_trait != UndefinedPixelTrait)) 1855b67d4ea6079617babbc0142af28ed2d23040239cristy (void) SetImageAlpha(image,OpaqueAlpha,exception); 1863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 1873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Set floodfill state. 1883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 18995f562af68c6bc67f4137b985c7d05c4eff4fddacristy floodplane_image=CloneImage(image,image->columns,image->rows,MagickTrue, 19095f562af68c6bc67f4137b985c7d05c4eff4fddacristy exception); 1913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (floodplane_image == (Image *) NULL) 1923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 1938a46d827a124555f0c48fb2368ec1bba8e079ab6cristy floodplane_image->alpha_trait=UndefinedPixelTrait; 1942099010c8d4783cea99527ba89e157023c13ff95cristy floodplane_image->colorspace=GRAYColorspace; 1952099010c8d4783cea99527ba89e157023c13ff95cristy (void) QueryColorCompliance("#000",AllCompliance, 1962099010c8d4783cea99527ba89e157023c13ff95cristy &floodplane_image->background_color,exception); 1972099010c8d4783cea99527ba89e157023c13ff95cristy (void) SetImageBackgroundColor(floodplane_image,exception); 198aaaff84e53c6dba4988fc076523eb820fdecd084cristy segment_info=AcquireVirtualMemory(MaxStacksize,sizeof(*segment_stack)); 199aaaff84e53c6dba4988fc076523eb820fdecd084cristy if (segment_info == (MemoryInfo *) NULL) 2003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 2013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy floodplane_image=DestroyImage(floodplane_image); 2023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", 2033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy image->filename); 2043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 205aaaff84e53c6dba4988fc076523eb820fdecd084cristy segment_stack=(SegmentInfo *) GetVirtualMemoryBlob(segment_info); 2063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 2073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Push initial segment on stack. 2083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 20914973baa8fa5c79889bc4db247200bb7d4626324cristy status=MagickTrue; 2103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy start=0; 2113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy s=segment_stack; 212aa6a11c893e812e2b1f1c425353eaf72d3501a9edirk PushSegmentStack(y_offset,x_offset,x_offset,1); 213aa6a11c893e812e2b1f1c425353eaf72d3501a9edirk PushSegmentStack(y_offset+1,x_offset,x_offset,-1); 2144c08aed51c5899665ade97263692328eea4af106cristy GetPixelInfo(image,&pixel); 21546ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy image_view=AcquireVirtualCacheView(image,exception); 21646ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy floodplane_view=AcquireAuthenticCacheView(floodplane_image,exception); 2173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy while (s > segment_stack) 2183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 2194c08aed51c5899665ade97263692328eea4af106cristy register const Quantum 22005d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict p; 2213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 2224c08aed51c5899665ade97263692328eea4af106cristy register Quantum 22305d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict q; 2243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 22514973baa8fa5c79889bc4db247200bb7d4626324cristy register ssize_t 22614973baa8fa5c79889bc4db247200bb7d4626324cristy x; 22714973baa8fa5c79889bc4db247200bb7d4626324cristy 2283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 2293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Pop segment off stack. 2303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 2313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy s--; 232bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy x1=(ssize_t) s->x1; 233bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy x2=(ssize_t) s->x2; 234bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy offset=(ssize_t) s->y2; 235bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy y=(ssize_t) s->y1+offset; 2363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 2373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Recolor neighboring pixels. 2383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 239b0d3bb93a8f69add9d2d000ff20e6951e3c1f885cristy p=GetCacheViewVirtualPixels(image_view,0,y,(size_t) (x1+1),1,exception); 240b0d3bb93a8f69add9d2d000ff20e6951e3c1f885cristy q=GetCacheViewAuthenticPixels(floodplane_view,0,y,(size_t) (x1+1),1, 2413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy exception); 2424c08aed51c5899665ade97263692328eea4af106cristy if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) 2433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 244ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy p+=x1*GetPixelChannels(image); 245ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy q+=x1*GetPixelChannels(floodplane_image); 2463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy for (x=x1; x >= 0; x--) 2473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 24895f562af68c6bc67f4137b985c7d05c4eff4fddacristy if (GetPixelGray(floodplane_image,q) != 0) 2493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 250803640d20a6a664315eddfff6f8531d0c5e0871dcristy GetPixelInfoPixel(image,p,&pixel); 2514c08aed51c5899665ade97263692328eea4af106cristy if (IsFuzzyEquivalencePixelInfo(&pixel,target) == invert) 2523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 25395f562af68c6bc67f4137b985c7d05c4eff4fddacristy SetPixelGray(floodplane_image,QuantumRange,q); 254ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy p-=GetPixelChannels(image); 255ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy q-=GetPixelChannels(floodplane_image); 2563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 257b0d3bb93a8f69add9d2d000ff20e6951e3c1f885cristy if (SyncCacheViewAuthenticPixels(floodplane_view,exception) == MagickFalse) 2583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 2593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy skip=x >= x1 ? MagickTrue : MagickFalse; 2603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (skip == MagickFalse) 2613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 2623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy start=x+1; 2633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (start < x1) 2643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy PushSegmentStack(y,start,x1-1,-offset); 2653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy x=x1+1; 2663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 2673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy do 2683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 2693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (skip == MagickFalse) 2703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 271bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy if (x < (ssize_t) image->columns) 2723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 273b0d3bb93a8f69add9d2d000ff20e6951e3c1f885cristy p=GetCacheViewVirtualPixels(image_view,x,y,image->columns-x,1, 2743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy exception); 275fdcc0185fe19084d4009bfc6e2fead8d86c67e64cristy q=GetCacheViewAuthenticPixels(floodplane_view,x,y,image->columns- 276fdcc0185fe19084d4009bfc6e2fead8d86c67e64cristy x,1,exception); 277636dcb5dafb00d5c92540bb56bd04724f1535bf2cristy if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) 2783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 279bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for ( ; x < (ssize_t) image->columns; x++) 2803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 28195f562af68c6bc67f4137b985c7d05c4eff4fddacristy if (GetPixelGray(floodplane_image,q) != 0) 2823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 283803640d20a6a664315eddfff6f8531d0c5e0871dcristy GetPixelInfoPixel(image,p,&pixel); 2844c08aed51c5899665ade97263692328eea4af106cristy if (IsFuzzyEquivalencePixelInfo(&pixel,target) == invert) 2853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 28695f562af68c6bc67f4137b985c7d05c4eff4fddacristy SetPixelGray(floodplane_image,QuantumRange,q); 287ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy p+=GetPixelChannels(image); 288ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy q+=GetPixelChannels(floodplane_image); 2893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 29014973baa8fa5c79889bc4db247200bb7d4626324cristy status=SyncCacheViewAuthenticPixels(floodplane_view,exception); 29114973baa8fa5c79889bc4db247200bb7d4626324cristy if (status == MagickFalse) 2923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 2933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 2943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy PushSegmentStack(y,start,x-1,offset); 2953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (x > (x2+1)) 2963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy PushSegmentStack(y,x2+1,x-1,-offset); 2973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 2983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy skip=MagickFalse; 2993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy x++; 3003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (x <= x2) 3013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 302b0d3bb93a8f69add9d2d000ff20e6951e3c1f885cristy p=GetCacheViewVirtualPixels(image_view,x,y,(size_t) (x2-x+1),1, 303b0d3bb93a8f69add9d2d000ff20e6951e3c1f885cristy exception); 304b0d3bb93a8f69add9d2d000ff20e6951e3c1f885cristy q=GetCacheViewAuthenticPixels(floodplane_view,x,y,(size_t) (x2-x+1),1, 3053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy exception); 306636dcb5dafb00d5c92540bb56bd04724f1535bf2cristy if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) 3073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 3083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy for ( ; x <= x2; x++) 3093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 31095f562af68c6bc67f4137b985c7d05c4eff4fddacristy if (GetPixelGray(floodplane_image,q) != 0) 3113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 312803640d20a6a664315eddfff6f8531d0c5e0871dcristy GetPixelInfoPixel(image,p,&pixel); 3134c08aed51c5899665ade97263692328eea4af106cristy if (IsFuzzyEquivalencePixelInfo(&pixel,target) != invert) 3143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 315ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy p+=GetPixelChannels(image); 316ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy q+=GetPixelChannels(floodplane_image); 3173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 3183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 3193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy start=x; 3203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } while (x <= x2); 3213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 322aff02c2233a720f8a115f32d6d8db0dbe179dc86dirk status=MagickTrue; 323aff02c2233a720f8a115f32d6d8db0dbe179dc86dirk#if defined(MAGICKCORE_OPENMP_SUPPORT) 324aff02c2233a720f8a115f32d6d8db0dbe179dc86dirk #pragma omp parallel for schedule(static,4) shared(status) \ 325aff02c2233a720f8a115f32d6d8db0dbe179dc86dirk magick_threads(floodplane_image,image,floodplane_image->rows,1) 326aff02c2233a720f8a115f32d6d8db0dbe179dc86dirk#endif 327bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0; y < (ssize_t) image->rows; y++) 3283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 3294c08aed51c5899665ade97263692328eea4af106cristy register const Quantum 33005d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict p; 3313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 3324c08aed51c5899665ade97263692328eea4af106cristy register Quantum 33305d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict q; 3343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 33514973baa8fa5c79889bc4db247200bb7d4626324cristy register ssize_t 33614973baa8fa5c79889bc4db247200bb7d4626324cristy x; 33714973baa8fa5c79889bc4db247200bb7d4626324cristy 3383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 3393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Tile fill color onto floodplane. 3403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 341aff02c2233a720f8a115f32d6d8db0dbe179dc86dirk if (status == MagickFalse) 342aff02c2233a720f8a115f32d6d8db0dbe179dc86dirk continue; 34395f562af68c6bc67f4137b985c7d05c4eff4fddacristy p=GetCacheViewVirtualPixels(floodplane_view,0,y,image->columns,1,exception); 344b0d3bb93a8f69add9d2d000ff20e6951e3c1f885cristy q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 3454c08aed51c5899665ade97263692328eea4af106cristy if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) 346aff02c2233a720f8a115f32d6d8db0dbe179dc86dirk { 347aff02c2233a720f8a115f32d6d8db0dbe179dc86dirk status=MagickFalse; 348aff02c2233a720f8a115f32d6d8db0dbe179dc86dirk continue; 349aff02c2233a720f8a115f32d6d8db0dbe179dc86dirk } 350bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0; x < (ssize_t) image->columns; x++) 3513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 35295f562af68c6bc67f4137b985c7d05c4eff4fddacristy if (GetPixelGray(floodplane_image,p) != 0) 3533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 35450be538de7d724dfbd0cba7d434d1404b49ce90ddirk GetFillColor(draw_info,x,y,&fill_color,exception); 35511a06d3f2cac0f17af7963e83bc6e9ebd2a377c0cristy SetPixelViaPixelInfo(image,&fill_color,q); 3563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 357ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy p+=GetPixelChannels(floodplane_image); 358ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy q+=GetPixelChannels(image); 3593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 360b0d3bb93a8f69add9d2d000ff20e6951e3c1f885cristy if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 361aff02c2233a720f8a115f32d6d8db0dbe179dc86dirk status=MagickFalse; 3623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 363b0d3bb93a8f69add9d2d000ff20e6951e3c1f885cristy floodplane_view=DestroyCacheView(floodplane_view); 364b0d3bb93a8f69add9d2d000ff20e6951e3c1f885cristy image_view=DestroyCacheView(image_view); 365aaaff84e53c6dba4988fc076523eb820fdecd084cristy segment_info=RelinquishVirtualMemory(segment_info); 3663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy floodplane_image=DestroyImage(floodplane_image); 367aff02c2233a720f8a115f32d6d8db0dbe179dc86dirk return(status); 3683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 3693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 3703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 3713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy+ G r a d i e n t I m a g e % 3763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 381cee9711bbc334b5677d5ec4ea1cc70340d35ee35cristy% GradientImage() applies a continuously smooth color transitions along a 3823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% vector from one color to another. 3833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% Note, the interface of this method will change in the future to support 3853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% more than one transistion. 3863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% The format of the GradientImage method is: 3883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% MagickBooleanType GradientImage(Image *image,const GradientType type, 390101ab708b0574518ac5715da4d3915400e9df79acristy% const SpreadMethod method,const PixelInfo *start_color, 391101ab708b0574518ac5715da4d3915400e9df79acristy% const PixelInfo *stop_color,ExceptionInfo *exception) 3923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% A description of each parameter follows: 3943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o image: the image. 3963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o type: the gradient type: linear or radial. 3983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o spread: the gradient spread meathod: pad, reflect, or repeat. 4003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 4013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o start_color: the start color. 4023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 4033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o stop_color: the stop color. 4043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 405189e84ce7da8fbf4eb57c908846bcc0bdcbdc688cristy% o exception: return any errors or warnings in this structure. 406189e84ce7da8fbf4eb57c908846bcc0bdcbdc688cristy% 4073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 4087b575810f9584064cacda46e4917a1999199b06ddirkMagickExport MagickBooleanType GradientImage(Image *image, 40916f2933cdc208138fe39595082c0d3841d93739cCristy const GradientType type,const SpreadMethod method,const StopInfo *stops, 41016f2933cdc208138fe39595082c0d3841d93739cCristy const size_t number_stops,ExceptionInfo *exception) 4113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 41216f2933cdc208138fe39595082c0d3841d93739cCristy const char 413542697a1562bf7aef0df9d3e26add9e29373b3a9Cristy *artifact; 41416f2933cdc208138fe39595082c0d3841d93739cCristy 4153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy DrawInfo 4163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *draw_info; 4173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 4183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy GradientInfo 4193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *gradient; 4203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 4213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 4223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status; 4233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 4243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 4253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Set gradient start-stop end points. 4263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 4273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy assert(image != (const Image *) NULL); 428e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy assert(image->signature == MagickCoreSignature); 4293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (image->debug != MagickFalse) 4303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 431b6f578bf802306a759e9c1b51c8edc4d2041ec9bdirk assert(stops != (const StopInfo *) NULL); 432b6f578bf802306a759e9c1b51c8edc4d2041ec9bdirk assert(number_stops > 0); 4333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy draw_info=AcquireDrawInfo(); 4343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy gradient=(&draw_info->gradient); 4353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy gradient->type=type; 4363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy gradient->bounding_box.width=image->columns; 4373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy gradient->bounding_box.height=image->rows; 438542697a1562bf7aef0df9d3e26add9e29373b3a9Cristy artifact=GetImageArtifact(image,"gradient:bounding-box"); 439542697a1562bf7aef0df9d3e26add9e29373b3a9Cristy if (artifact != (const char *) NULL) 440542697a1562bf7aef0df9d3e26add9e29373b3a9Cristy (void) ParseAbsoluteGeometry(artifact,&gradient->bounding_box); 4413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy gradient->gradient_vector.x2=(double) image->columns-1.0; 4423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy gradient->gradient_vector.y2=(double) image->rows-1.0; 443971aac4f549b1ff5321a6514714dae9354bfa459Cristy artifact=GetImageArtifact(image,"gradient:direction"); 444542697a1562bf7aef0df9d3e26add9e29373b3a9Cristy if (artifact != (const char *) NULL) 44516f2933cdc208138fe39595082c0d3841d93739cCristy { 446971aac4f549b1ff5321a6514714dae9354bfa459Cristy GravityType 447971aac4f549b1ff5321a6514714dae9354bfa459Cristy direction; 448971aac4f549b1ff5321a6514714dae9354bfa459Cristy 449971aac4f549b1ff5321a6514714dae9354bfa459Cristy direction=(GravityType) ParseCommandOption(MagickGravityOptions, 450971aac4f549b1ff5321a6514714dae9354bfa459Cristy MagickFalse,artifact); 451971aac4f549b1ff5321a6514714dae9354bfa459Cristy switch (direction) 452971aac4f549b1ff5321a6514714dae9354bfa459Cristy { 453971aac4f549b1ff5321a6514714dae9354bfa459Cristy case NorthWestGravity: 454971aac4f549b1ff5321a6514714dae9354bfa459Cristy { 455971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.x1=(double) image->columns-1.0; 456971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.y1=(double) image->rows-1.0; 457971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.x2=0.0; 458971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.y2=0.0; 459971aac4f549b1ff5321a6514714dae9354bfa459Cristy break; 460971aac4f549b1ff5321a6514714dae9354bfa459Cristy } 461971aac4f549b1ff5321a6514714dae9354bfa459Cristy case NorthGravity: 462971aac4f549b1ff5321a6514714dae9354bfa459Cristy { 463971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.x1=0.0; 464971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.y1=(double) image->rows-1.0; 465971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.x2=0.0; 466971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.y2=0.0; 467971aac4f549b1ff5321a6514714dae9354bfa459Cristy break; 468971aac4f549b1ff5321a6514714dae9354bfa459Cristy } 469971aac4f549b1ff5321a6514714dae9354bfa459Cristy case NorthEastGravity: 470971aac4f549b1ff5321a6514714dae9354bfa459Cristy { 471971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.x1=0.0; 472971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.y1=(double) image->rows-1.0; 473971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.x2=(double) image->columns-1.0; 474971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.y2=0.0; 475971aac4f549b1ff5321a6514714dae9354bfa459Cristy break; 476971aac4f549b1ff5321a6514714dae9354bfa459Cristy } 477971aac4f549b1ff5321a6514714dae9354bfa459Cristy case WestGravity: 478971aac4f549b1ff5321a6514714dae9354bfa459Cristy { 479971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.x1=(double) image->columns-1.0; 480971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.y1=0.0; 481971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.x2=0.0; 482971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.y2=0.0; 483971aac4f549b1ff5321a6514714dae9354bfa459Cristy break; 484971aac4f549b1ff5321a6514714dae9354bfa459Cristy } 485971aac4f549b1ff5321a6514714dae9354bfa459Cristy case EastGravity: 486971aac4f549b1ff5321a6514714dae9354bfa459Cristy { 487971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.x1=0.0; 488971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.y1=0.0; 489971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.x2=(double) image->columns-1.0; 490971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.y2=0.0; 491971aac4f549b1ff5321a6514714dae9354bfa459Cristy break; 492971aac4f549b1ff5321a6514714dae9354bfa459Cristy } 493971aac4f549b1ff5321a6514714dae9354bfa459Cristy case SouthWestGravity: 494971aac4f549b1ff5321a6514714dae9354bfa459Cristy { 495971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.x1=(double) image->columns-1.0; 496971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.y1=0.0; 497971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.x2=0.0; 498971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.y2=(double) image->rows-1.0; 499971aac4f549b1ff5321a6514714dae9354bfa459Cristy break; 500971aac4f549b1ff5321a6514714dae9354bfa459Cristy } 501971aac4f549b1ff5321a6514714dae9354bfa459Cristy case SouthGravity: 502971aac4f549b1ff5321a6514714dae9354bfa459Cristy { 503971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.x1=0.0; 504971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.y1=0.0; 505971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.x2=0.0; 506971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.y2=(double) image->columns-1.0; 507971aac4f549b1ff5321a6514714dae9354bfa459Cristy break; 508971aac4f549b1ff5321a6514714dae9354bfa459Cristy } 509971aac4f549b1ff5321a6514714dae9354bfa459Cristy case SouthEastGravity: 510971aac4f549b1ff5321a6514714dae9354bfa459Cristy { 511971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.x1=0.0; 512971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.y1=0.0; 513971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.x2=(double) image->columns-1.0; 514971aac4f549b1ff5321a6514714dae9354bfa459Cristy gradient->gradient_vector.y2=(double) image->rows-1.0; 515971aac4f549b1ff5321a6514714dae9354bfa459Cristy break; 516971aac4f549b1ff5321a6514714dae9354bfa459Cristy } 517971aac4f549b1ff5321a6514714dae9354bfa459Cristy default: 518971aac4f549b1ff5321a6514714dae9354bfa459Cristy break; 519971aac4f549b1ff5321a6514714dae9354bfa459Cristy } 52016f2933cdc208138fe39595082c0d3841d93739cCristy } 521971aac4f549b1ff5321a6514714dae9354bfa459Cristy artifact=GetImageArtifact(image,"gradient:angle"); 522971aac4f549b1ff5321a6514714dae9354bfa459Cristy if (artifact != (const char *) NULL) 52395264c47a4a04033f2c1688819282e27bcf3f8b5Cristy gradient->angle=StringToDouble(artifact,(char **) NULL); 524971aac4f549b1ff5321a6514714dae9354bfa459Cristy artifact=GetImageArtifact(image,"gradient:vector"); 525971aac4f549b1ff5321a6514714dae9354bfa459Cristy if (artifact != (const char *) NULL) 526971aac4f549b1ff5321a6514714dae9354bfa459Cristy (void) sscanf(artifact,"%lf%*[ ,]%lf%*[ ,]%lf%*[ ,]%lf", 527971aac4f549b1ff5321a6514714dae9354bfa459Cristy &gradient->gradient_vector.x1,&gradient->gradient_vector.y1, 528971aac4f549b1ff5321a6514714dae9354bfa459Cristy &gradient->gradient_vector.x2,&gradient->gradient_vector.y2); 529f70f909b81f1b22be16a68856e56a975bd4c5454Cristy if ((GetImageArtifact(image,"gradient:angle") == (const char *) NULL) && 530f70f909b81f1b22be16a68856e56a975bd4c5454Cristy (GetImageArtifact(image,"gradient:direction") == (const char *) NULL) && 531f70f909b81f1b22be16a68856e56a975bd4c5454Cristy (GetImageArtifact(image,"gradient:extent") == (const char *) NULL) && 5329e46e8aa51c9bd73e8512c530ce3a74aef688f11Cristy (GetImageArtifact(image,"gradient:vector") == (const char *) NULL)) 5334f11a391a1d0ded2b4af92311fca972977661a88Cristy if ((type == LinearGradient) && (gradient->gradient_vector.y2 != 0.0)) 5344f11a391a1d0ded2b4af92311fca972977661a88Cristy gradient->gradient_vector.x2=0.0; 5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy gradient->center.x=(double) gradient->gradient_vector.x2/2.0; 5363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy gradient->center.y=(double) gradient->gradient_vector.y2/2.0; 537542697a1562bf7aef0df9d3e26add9e29373b3a9Cristy artifact=GetImageArtifact(image,"gradient:center"); 538542697a1562bf7aef0df9d3e26add9e29373b3a9Cristy if (artifact != (const char *) NULL) 539971aac4f549b1ff5321a6514714dae9354bfa459Cristy (void) sscanf(artifact,"%lf%*[ ,]%lf",&gradient->center.x, 540971aac4f549b1ff5321a6514714dae9354bfa459Cristy &gradient->center.y); 541c757d75f28b1234bc1e466ca740f5c146f37936eCristy artifact=GetImageArtifact(image,"gradient:angle"); 542c757d75f28b1234bc1e466ca740f5c146f37936eCristy if ((type == LinearGradient) && (artifact != (const char *) NULL)) 543c757d75f28b1234bc1e466ca740f5c146f37936eCristy { 544c757d75f28b1234bc1e466ca740f5c146f37936eCristy double 545c757d75f28b1234bc1e466ca740f5c146f37936eCristy sine, 546c757d75f28b1234bc1e466ca740f5c146f37936eCristy cosine, 547c757d75f28b1234bc1e466ca740f5c146f37936eCristy distance; 548c757d75f28b1234bc1e466ca740f5c146f37936eCristy 549c757d75f28b1234bc1e466ca740f5c146f37936eCristy /* 550c757d75f28b1234bc1e466ca740f5c146f37936eCristy Reference https://drafts.csswg.org/css-images-3/#linear-gradients. 551c757d75f28b1234bc1e466ca740f5c146f37936eCristy */ 552c757d75f28b1234bc1e466ca740f5c146f37936eCristy sine=sin((double) DegreesToRadians(gradient->angle-90.0)); 553c757d75f28b1234bc1e466ca740f5c146f37936eCristy cosine=cos((double) DegreesToRadians(gradient->angle-90.0)); 554c757d75f28b1234bc1e466ca740f5c146f37936eCristy distance=fabs((double) image->columns*cosine)+ 555c757d75f28b1234bc1e466ca740f5c146f37936eCristy fabs((double) image->rows*sine); 556c757d75f28b1234bc1e466ca740f5c146f37936eCristy gradient->gradient_vector.x1=0.5*(image->columns-distance*cosine); 557c757d75f28b1234bc1e466ca740f5c146f37936eCristy gradient->gradient_vector.y1=0.5*(image->rows-distance*sine); 558c757d75f28b1234bc1e466ca740f5c146f37936eCristy gradient->gradient_vector.x2=0.5*(image->columns+distance*cosine); 559c757d75f28b1234bc1e466ca740f5c146f37936eCristy gradient->gradient_vector.y2=0.5*(image->rows+distance*sine); 560c757d75f28b1234bc1e466ca740f5c146f37936eCristy } 561b2d350c97b5b7796cb5c867cfcf92c73b1cf44e1Cristy gradient->radii.x=(double) MagickMax(image->columns,image->rows)/2.0; 562abd2f5a29e1239a14c10f5219f4c18d1815ab9e3Cristy gradient->radii.y=gradient->radii.x; 563f70f909b81f1b22be16a68856e56a975bd4c5454Cristy artifact=GetImageArtifact(image,"gradient:extent"); 564f70f909b81f1b22be16a68856e56a975bd4c5454Cristy if (artifact != (const char *) NULL) 565f70f909b81f1b22be16a68856e56a975bd4c5454Cristy { 566c9dbca3091582bcb9f705775e798d58e6360908dCristy if (LocaleCompare(artifact,"Circle") == 0) 567c9dbca3091582bcb9f705775e798d58e6360908dCristy { 568b2d350c97b5b7796cb5c867cfcf92c73b1cf44e1Cristy gradient->radii.x=(double) MagickMax(image->columns,image->rows)/2.0; 569c9dbca3091582bcb9f705775e798d58e6360908dCristy gradient->radii.y=gradient->radii.x; 570c9dbca3091582bcb9f705775e798d58e6360908dCristy } 571f70f909b81f1b22be16a68856e56a975bd4c5454Cristy if (LocaleCompare(artifact,"Diagonal") == 0) 572f70f909b81f1b22be16a68856e56a975bd4c5454Cristy { 5732526e880b74424d234db67a26e7d466bc920c068Cristy gradient->radii.x=(double) (sqrt(image->columns*image->columns+ 5742526e880b74424d234db67a26e7d466bc920c068Cristy image->rows*image->rows))/2.0; 5750357183a8cdd6769d3e3879b9bd3ea9cd7c2491dCristy gradient->radii.y=gradient->radii.x; 576f70f909b81f1b22be16a68856e56a975bd4c5454Cristy } 577f70f909b81f1b22be16a68856e56a975bd4c5454Cristy if (LocaleCompare(artifact,"Ellipse") == 0) 578f70f909b81f1b22be16a68856e56a975bd4c5454Cristy { 5790357183a8cdd6769d3e3879b9bd3ea9cd7c2491dCristy gradient->radii.x=(double) image->columns/2.0; 5800357183a8cdd6769d3e3879b9bd3ea9cd7c2491dCristy gradient->radii.y=(double) image->rows/2.0; 581f70f909b81f1b22be16a68856e56a975bd4c5454Cristy } 582c9dbca3091582bcb9f705775e798d58e6360908dCristy if (LocaleCompare(artifact,"Maximum") == 0) 583c9dbca3091582bcb9f705775e798d58e6360908dCristy { 584b2d350c97b5b7796cb5c867cfcf92c73b1cf44e1Cristy gradient->radii.x=(double) MagickMax(image->columns,image->rows)/2.0; 585c9dbca3091582bcb9f705775e798d58e6360908dCristy gradient->radii.y=gradient->radii.x; 586c9dbca3091582bcb9f705775e798d58e6360908dCristy } 587a578020ecc9886360d733960cf33ecc611344550Cristy if (LocaleCompare(artifact,"Minimum") == 0) 588f70f909b81f1b22be16a68856e56a975bd4c5454Cristy { 5892526e880b74424d234db67a26e7d466bc920c068Cristy gradient->radii.x=(double) (MagickMin(image->columns,image->rows))/ 5902526e880b74424d234db67a26e7d466bc920c068Cristy 2.0; 591f70f909b81f1b22be16a68856e56a975bd4c5454Cristy gradient->radii.y=gradient->radii.x; 592f70f909b81f1b22be16a68856e56a975bd4c5454Cristy } 593f70f909b81f1b22be16a68856e56a975bd4c5454Cristy } 594c757d75f28b1234bc1e466ca740f5c146f37936eCristy artifact=GetImageArtifact(image,"gradient:radii"); 595c757d75f28b1234bc1e466ca740f5c146f37936eCristy if (artifact != (const char *) NULL) 596c757d75f28b1234bc1e466ca740f5c146f37936eCristy (void) sscanf(artifact,"%lf%*[ ,]%lf",&gradient->radii.x, 597c757d75f28b1234bc1e466ca740f5c146f37936eCristy &gradient->radii.y); 59850a6c9d68214f8b6a551d0e07b84035c1794213bCristy gradient->radius=MagickMax(gradient->radii.x,gradient->radii.y); 5993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy gradient->spread=method; 6003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 6013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Define the gradient to fill between the stops. 6023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 603b6f578bf802306a759e9c1b51c8edc4d2041ec9bdirk gradient->number_stops=number_stops; 6043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy gradient->stops=(StopInfo *) AcquireQuantumMemory(gradient->number_stops, 6053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy sizeof(*gradient->stops)); 6063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (gradient->stops == (StopInfo *) NULL) 6073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed", 6083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy image->filename); 609b6f578bf802306a759e9c1b51c8edc4d2041ec9bdirk (void) CopyMagickMemory(gradient->stops,stops,(size_t) number_stops* 610b6f578bf802306a759e9c1b51c8edc4d2041ec9bdirk sizeof(*stops)); 6113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 6123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Draw a gradient on the image. 6133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 614947cb4c68bebf79b15b6f3e824bc973491a77709cristy status=DrawGradientImage(image,draw_info,exception); 6153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy draw_info=DestroyDrawInfo(draw_info); 6163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(status); 6173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 6183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 6193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 6203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 6223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 6233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 6243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% O i l P a i n t I m a g e % 6253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 6263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 6273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 6283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 6303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% OilPaintImage() applies a special effect filter that simulates an oil 6313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% painting. Each pixel is replaced by the most frequent color occurring 6323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% in a circular region defined by radius. 6333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 6343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% The format of the OilPaintImage method is: 6353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 6363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% Image *OilPaintImage(const Image *image,const double radius, 63714973baa8fa5c79889bc4db247200bb7d4626324cristy% const double sigma,ExceptionInfo *exception) 6383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 6393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% A description of each parameter follows: 6403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 6413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o image: the image. 6423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 6433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o radius: the radius of the circular neighborhood. 6443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 64514973baa8fa5c79889bc4db247200bb7d4626324cristy% o sigma: the standard deviation of the Gaussian, in pixels. 64614973baa8fa5c79889bc4db247200bb7d4626324cristy% 6473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o exception: return any errors or warnings in this structure. 6483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 6493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 6503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 651bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristystatic size_t **DestroyHistogramThreadSet(size_t **histogram) 6523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 653bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 6543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i; 6553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 656bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy assert(histogram != (size_t **) NULL); 657ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy for (i=0; i < (ssize_t) GetMagickResourceLimit(ThreadResource); i++) 658bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy if (histogram[i] != (size_t *) NULL) 659bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy histogram[i]=(size_t *) RelinquishMagickMemory(histogram[i]); 660b41ee108904d5e1e75fd6a944caeceb5c7d6e64acristy histogram=(size_t **) RelinquishMagickMemory(histogram); 6613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(histogram); 6623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 6633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 664bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristystatic size_t **AcquireHistogramThreadSet(const size_t count) 6653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 666bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 6673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i; 6683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 669bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy size_t 6703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy **histogram, 6713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy number_threads; 6723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 6739357bdd9a30c3d65ef8812e45220f7552dc4376bcristy number_threads=(size_t) GetMagickResourceLimit(ThreadResource); 67414973baa8fa5c79889bc4db247200bb7d4626324cristy histogram=(size_t **) AcquireQuantumMemory(number_threads,sizeof(*histogram)); 675bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy if (histogram == (size_t **) NULL) 676bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy return((size_t **) NULL); 6773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) ResetMagickMemory(histogram,0,number_threads*sizeof(*histogram)); 678bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (i=0; i < (ssize_t) number_threads; i++) 6793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 68014973baa8fa5c79889bc4db247200bb7d4626324cristy histogram[i]=(size_t *) AcquireQuantumMemory(count,sizeof(**histogram)); 681bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy if (histogram[i] == (size_t *) NULL) 6823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(DestroyHistogramThreadSet(histogram)); 6833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 6843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(histogram); 6853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 6863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 6873ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport Image *OilPaintImage(const Image *image,const double radius, 68814973baa8fa5c79889bc4db247200bb7d4626324cristy const double sigma,ExceptionInfo *exception) 6893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 6903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define NumberPaintBins 256 6913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define OilPaintImageTag "OilPaint/Image" 6923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 693fa11211cadba55e3e038b805478e55b25908a152cristy CacheView 694fa11211cadba55e3e038b805478e55b25908a152cristy *image_view, 695fa11211cadba55e3e038b805478e55b25908a152cristy *paint_view; 696fa11211cadba55e3e038b805478e55b25908a152cristy 6973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Image 698404d0da35379e582eac5248a1b44184decd13eefcristy *linear_image, 6993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *paint_image; 7003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 7013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 7023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status; 7033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 704bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy MagickOffsetType 705bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy progress; 706bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy 707bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy size_t 70814973baa8fa5c79889bc4db247200bb7d4626324cristy **histograms, 7093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy width; 7103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 711bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy ssize_t 712f8561541d3e184b4f8ace71d6274cd27f40fbc79cristy center, 713bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy y; 714bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy 7153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 7163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Initialize painted image attributes. 7173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 7183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy assert(image != (const Image *) NULL); 719e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy assert(image->signature == MagickCoreSignature); 7203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (image->debug != MagickFalse) 7213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 7223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy assert(exception != (ExceptionInfo *) NULL); 723e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy assert(exception->signature == MagickCoreSignature); 72414973baa8fa5c79889bc4db247200bb7d4626324cristy width=GetOptimalKernelWidth2D(radius,sigma); 725404d0da35379e582eac5248a1b44184decd13eefcristy linear_image=CloneImage(image,0,0,MagickTrue,exception); 7263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy paint_image=CloneImage(image,image->columns,image->rows,MagickTrue,exception); 727404d0da35379e582eac5248a1b44184decd13eefcristy if ((linear_image == (Image *) NULL) || (paint_image == (Image *) NULL)) 728404d0da35379e582eac5248a1b44184decd13eefcristy { 729404d0da35379e582eac5248a1b44184decd13eefcristy if (linear_image != (Image *) NULL) 730404d0da35379e582eac5248a1b44184decd13eefcristy linear_image=DestroyImage(linear_image); 731404d0da35379e582eac5248a1b44184decd13eefcristy if (paint_image != (Image *) NULL) 732404d0da35379e582eac5248a1b44184decd13eefcristy linear_image=DestroyImage(paint_image); 733404d0da35379e582eac5248a1b44184decd13eefcristy return((Image *) NULL); 734404d0da35379e582eac5248a1b44184decd13eefcristy } 735574cc26500992189f637cd1cdf93d0654e7df7aecristy if (SetImageStorageClass(paint_image,DirectClass,exception) == MagickFalse) 7363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 737404d0da35379e582eac5248a1b44184decd13eefcristy linear_image=DestroyImage(linear_image); 7383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy paint_image=DestroyImage(paint_image); 7393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return((Image *) NULL); 7403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 7413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy histograms=AcquireHistogramThreadSet(NumberPaintBins); 742bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy if (histograms == (size_t **) NULL) 7433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 744404d0da35379e582eac5248a1b44184decd13eefcristy linear_image=DestroyImage(linear_image); 7453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy paint_image=DestroyImage(paint_image); 7463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy ThrowImageException(ResourceLimitError,"MemoryAllocationFailed"); 7473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 7483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 7493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Oil paint image. 7503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 7513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=MagickTrue; 7523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy progress=0; 753404d0da35379e582eac5248a1b44184decd13eefcristy center=(ssize_t) GetPixelChannels(linear_image)*(linear_image->columns+width)* 754404d0da35379e582eac5248a1b44184decd13eefcristy (width/2L)+GetPixelChannels(linear_image)*(width/2L); 755404d0da35379e582eac5248a1b44184decd13eefcristy image_view=AcquireVirtualCacheView(linear_image,exception); 75646ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy paint_view=AcquireAuthenticCacheView(paint_image,exception); 757b5d5f725fef80ff5d50db3111c05a1a521b81e7fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 758ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy #pragma omp parallel for schedule(static,4) shared(progress,status) \ 759404d0da35379e582eac5248a1b44184decd13eefcristy magick_threads(linear_image,paint_image,linear_image->rows,1) 7603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 761404d0da35379e582eac5248a1b44184decd13eefcristy for (y=0; y < (ssize_t) linear_image->rows; y++) 7623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 7634c08aed51c5899665ade97263692328eea4af106cristy register const Quantum 76405d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict p; 7653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 7664c08aed51c5899665ade97263692328eea4af106cristy register Quantum 76705d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict q; 7683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 769bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register size_t 7703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *histogram; 7713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 77214973baa8fa5c79889bc4db247200bb7d4626324cristy register ssize_t 77314973baa8fa5c79889bc4db247200bb7d4626324cristy x; 77414973baa8fa5c79889bc4db247200bb7d4626324cristy 7753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status == MagickFalse) 7763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy continue; 777fe4ba002ee50b147659ea0f84ad1526c3758f2f8cristy p=GetCacheViewVirtualPixels(image_view,-((ssize_t) width/2L),y-(ssize_t) 778404d0da35379e582eac5248a1b44184decd13eefcristy (width/2L),linear_image->columns+width,width,exception); 7793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy q=QueueCacheViewAuthenticPixels(paint_view,0,y,paint_image->columns,1, 7803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy exception); 7814c08aed51c5899665ade97263692328eea4af106cristy if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL)) 7823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 7833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=MagickFalse; 7843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy continue; 7853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 7863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy histogram=histograms[GetOpenMPThreadId()]; 787404d0da35379e582eac5248a1b44184decd13eefcristy for (x=0; x < (ssize_t) linear_image->columns; x++) 7883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 789bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 7903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i, 7913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy u; 7923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 793bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy size_t 7943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy count; 7953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 7969d314ff2c17a77996c05413c2013880387e50f0ecristy ssize_t 7979d314ff2c17a77996c05413c2013880387e50f0ecristy j, 7989d314ff2c17a77996c05413c2013880387e50f0ecristy k, 799f8561541d3e184b4f8ace71d6274cd27f40fbc79cristy n, 8009d314ff2c17a77996c05413c2013880387e50f0ecristy v; 8019d314ff2c17a77996c05413c2013880387e50f0ecristy 8023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 8033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Assign most frequent color. 8043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 805f8561541d3e184b4f8ace71d6274cd27f40fbc79cristy k=0; 8063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy j=0; 8073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy count=0; 808f8561541d3e184b4f8ace71d6274cd27f40fbc79cristy (void) ResetMagickMemory(histogram,0,NumberPaintBins* sizeof(*histogram)); 809bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (v=0; v < (ssize_t) width; v++) 8103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 811bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (u=0; u < (ssize_t) width; u++) 8123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 813404d0da35379e582eac5248a1b44184decd13eefcristy n=(ssize_t) ScaleQuantumToChar(ClampToQuantum(GetPixelIntensity( 814404d0da35379e582eac5248a1b44184decd13eefcristy linear_image,p+GetPixelChannels(linear_image)*(u+k)))); 815f8561541d3e184b4f8ace71d6274cd27f40fbc79cristy histogram[n]++; 816f8561541d3e184b4f8ace71d6274cd27f40fbc79cristy if (histogram[n] > count) 8173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 818f8561541d3e184b4f8ace71d6274cd27f40fbc79cristy j=k+u; 819f8561541d3e184b4f8ace71d6274cd27f40fbc79cristy count=histogram[n]; 8203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 8213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 822034ade9cf59ba9bf412eb2da3bab31b1de25929ecristy k+=(ssize_t) (linear_image->columns+width); 823f8561541d3e184b4f8ace71d6274cd27f40fbc79cristy } 824404d0da35379e582eac5248a1b44184decd13eefcristy for (i=0; i < (ssize_t) GetPixelChannels(linear_image); i++) 825f8561541d3e184b4f8ace71d6274cd27f40fbc79cristy { 8265a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy PixelChannel channel=GetPixelChannelChannel(linear_image,i); 8275a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy PixelTrait traits=GetPixelChannelTraits(linear_image,channel); 8285a23c55ddcfdf6ae717dd42d8a1c1a2ff8c6305fcristy PixelTrait paint_traits=GetPixelChannelTraits(paint_image,channel); 829f8561541d3e184b4f8ace71d6274cd27f40fbc79cristy if ((traits == UndefinedPixelTrait) || 830f8561541d3e184b4f8ace71d6274cd27f40fbc79cristy (paint_traits == UndefinedPixelTrait)) 831f8561541d3e184b4f8ace71d6274cd27f40fbc79cristy continue; 8321eced097f7f4f51d5aa14d46079292fa1dcf0e77cristy if (((paint_traits & CopyPixelTrait) != 0) || 833883fde11debec15cedb05dc5d7228d8588066bc0cristy (GetPixelReadMask(linear_image,p) == 0)) 834f8561541d3e184b4f8ace71d6274cd27f40fbc79cristy { 835f8561541d3e184b4f8ace71d6274cd27f40fbc79cristy SetPixelChannel(paint_image,channel,p[center+i],q); 836f8561541d3e184b4f8ace71d6274cd27f40fbc79cristy continue; 837f8561541d3e184b4f8ace71d6274cd27f40fbc79cristy } 838404d0da35379e582eac5248a1b44184decd13eefcristy SetPixelChannel(paint_image,channel,p[j*GetPixelChannels(linear_image)+ 839404d0da35379e582eac5248a1b44184decd13eefcristy i],q); 8403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 841404d0da35379e582eac5248a1b44184decd13eefcristy p+=GetPixelChannels(linear_image); 842ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy q+=GetPixelChannels(paint_image); 8433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 8443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (SyncCacheViewAuthenticPixels(paint_view,exception) == MagickFalse) 8453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=MagickFalse; 846404d0da35379e582eac5248a1b44184decd13eefcristy if (linear_image->progress_monitor != (MagickProgressMonitor) NULL) 8473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 8483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 8493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy proceed; 8503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 851b5d5f725fef80ff5d50db3111c05a1a521b81e7fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 85295338b312d2239543881a93d7bed923eed6eaff9cristy #pragma omp critical (MagickCore_OilPaintImage) 8533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 854404d0da35379e582eac5248a1b44184decd13eefcristy proceed=SetImageProgress(linear_image,OilPaintImageTag,progress++, 855404d0da35379e582eac5248a1b44184decd13eefcristy linear_image->rows); 8563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (proceed == MagickFalse) 8573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=MagickFalse; 8583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 8593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 8603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy paint_view=DestroyCacheView(paint_view); 8613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy image_view=DestroyCacheView(image_view); 8623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy histograms=DestroyHistogramThreadSet(histograms); 863404d0da35379e582eac5248a1b44184decd13eefcristy linear_image=DestroyImage(linear_image); 8643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status == MagickFalse) 8653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy paint_image=DestroyImage(paint_image); 8663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(paint_image); 8673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 8683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 8693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 8703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 8723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 8733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 8743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% O p a q u e P a i n t I m a g e % 8753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 8763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 8773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 8783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 8803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% OpaquePaintImage() changes any pixel that matches color with the color 8811f07555d1773dac3acebfce4ba017128246923c2cristy% defined by fill argument. 8823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 88314973baa8fa5c79889bc4db247200bb7d4626324cristy% By default color must match a particular pixel color exactly. However, in 88414973baa8fa5c79889bc4db247200bb7d4626324cristy% many cases two colors may differ by a small amount. Fuzz defines how much 88514973baa8fa5c79889bc4db247200bb7d4626324cristy% tolerance is acceptable to consider two colors as the same. For example, 88614973baa8fa5c79889bc4db247200bb7d4626324cristy% set fuzz to 10 and the color red at intensities of 100 and 102 respectively 88714973baa8fa5c79889bc4db247200bb7d4626324cristy% are now interpreted as the same color. 8883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 8893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% The format of the OpaquePaintImage method is: 8903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 8911f07555d1773dac3acebfce4ba017128246923c2cristy% MagickBooleanType OpaquePaintImage(Image *image,const PixelInfo *target, 8921f07555d1773dac3acebfce4ba017128246923c2cristy% const PixelInfo *fill,const MagickBooleanType invert, 8931f07555d1773dac3acebfce4ba017128246923c2cristy% ExceptionInfo *exception) 8943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 8953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% A description of each parameter follows: 8963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 8973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o image: the image. 8983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 8993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o target: the RGB value of the target color. 9003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 9013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o fill: the replacement color. 9023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 9033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o invert: paint any pixel that does not match the target color. 9043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 905189e84ce7da8fbf4eb57c908846bcc0bdcbdc688cristy% o exception: return any errors or warnings in this structure. 906189e84ce7da8fbf4eb57c908846bcc0bdcbdc688cristy% 9073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 9083ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport MagickBooleanType OpaquePaintImage(Image *image, 909189e84ce7da8fbf4eb57c908846bcc0bdcbdc688cristy const PixelInfo *target,const PixelInfo *fill,const MagickBooleanType invert, 910189e84ce7da8fbf4eb57c908846bcc0bdcbdc688cristy ExceptionInfo *exception) 9113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 9123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define OpaquePaintImageTag "Opaque/Image" 9133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 914c4c8d13c0996fea659ce63c682c803e74c1abc8acristy CacheView 915c4c8d13c0996fea659ce63c682c803e74c1abc8acristy *image_view; 916c4c8d13c0996fea659ce63c682c803e74c1abc8acristy 9173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 9183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status; 9193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 920bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy MagickOffsetType 921bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy progress; 922bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy 9234c08aed51c5899665ade97263692328eea4af106cristy PixelInfo 9241f07555d1773dac3acebfce4ba017128246923c2cristy conform_fill, 9251f07555d1773dac3acebfce4ba017128246923c2cristy conform_target, 9263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy zero; 9273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 928bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy ssize_t 929bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy y; 930bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy 9313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy assert(image != (Image *) NULL); 932e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy assert(image->signature == MagickCoreSignature); 9334c08aed51c5899665ade97263692328eea4af106cristy assert(target != (PixelInfo *) NULL); 9344c08aed51c5899665ade97263692328eea4af106cristy assert(fill != (PixelInfo *) NULL); 9353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (image->debug != MagickFalse) 9363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 937574cc26500992189f637cd1cdf93d0654e7df7aecristy if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 9383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 939bfdd5bc06830778f14dfa0659b389ff630b7fbfedirk ConformPixelInfo(image,fill,&conform_fill,exception); 940bfdd5bc06830778f14dfa0659b389ff630b7fbfedirk ConformPixelInfo(image,target,&conform_target,exception); 9413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 9423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Make image color opaque. 9433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 9443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=MagickTrue; 9453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy progress=0; 9464c08aed51c5899665ade97263692328eea4af106cristy GetPixelInfo(image,&zero); 94746ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy image_view=AcquireAuthenticCacheView(image,exception); 948b5d5f725fef80ff5d50db3111c05a1a521b81e7fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 949ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy #pragma omp parallel for schedule(static,4) shared(progress,status) \ 9505e6b259130f9dbe0da4666f734937017babe573acristy magick_threads(image,image,image->rows,1) 9513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 952bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0; y < (ssize_t) image->rows; y++) 9533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 9544c08aed51c5899665ade97263692328eea4af106cristy PixelInfo 9553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy pixel; 9563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 9574c08aed51c5899665ade97263692328eea4af106cristy register Quantum 95805d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict q; 9593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 96014973baa8fa5c79889bc4db247200bb7d4626324cristy register ssize_t 96114973baa8fa5c79889bc4db247200bb7d4626324cristy x; 96214973baa8fa5c79889bc4db247200bb7d4626324cristy 9633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status == MagickFalse) 9643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy continue; 9653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 96614973baa8fa5c79889bc4db247200bb7d4626324cristy if (q == (Quantum *) NULL) 9673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 9683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=MagickFalse; 9693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy continue; 9703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 9713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy pixel=zero; 972bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0; x < (ssize_t) image->columns; x++) 9733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 974803640d20a6a664315eddfff6f8531d0c5e0871dcristy GetPixelInfoPixel(image,q,&pixel); 9751f07555d1773dac3acebfce4ba017128246923c2cristy if (IsFuzzyEquivalencePixelInfo(&pixel,&conform_target) != invert) 97611a06d3f2cac0f17af7963e83bc6e9ebd2a377c0cristy SetPixelViaPixelInfo(image,&conform_fill,q); 977ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy q+=GetPixelChannels(image); 9783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 9793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 9803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=MagickFalse; 9813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (image->progress_monitor != (MagickProgressMonitor) NULL) 9823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 9833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 9843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy proceed; 9853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 986b5d5f725fef80ff5d50db3111c05a1a521b81e7fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 98795338b312d2239543881a93d7bed923eed6eaff9cristy #pragma omp critical (MagickCore_OpaquePaintImage) 9883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 9893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy proceed=SetImageProgress(image,OpaquePaintImageTag,progress++, 9903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy image->rows); 9913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (proceed == MagickFalse) 9923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=MagickFalse; 9933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 9943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 9953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy image_view=DestroyCacheView(image_view); 9963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(status); 9973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 9983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 9993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 10003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 10023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 10033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 10043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% T r a n s p a r e n t P a i n t I m a g e % 10053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 10063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 10073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 10083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 10103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% TransparentPaintImage() changes the opacity value associated with any pixel 10113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% that matches color to the value defined by opacity. 10123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 101314973baa8fa5c79889bc4db247200bb7d4626324cristy% By default color must match a particular pixel color exactly. However, in 101414973baa8fa5c79889bc4db247200bb7d4626324cristy% many cases two colors may differ by a small amount. Fuzz defines how much 101514973baa8fa5c79889bc4db247200bb7d4626324cristy% tolerance is acceptable to consider two colors as the same. For example, 101614973baa8fa5c79889bc4db247200bb7d4626324cristy% set fuzz to 10 and the color red at intensities of 100 and 102 respectively 101714973baa8fa5c79889bc4db247200bb7d4626324cristy% are now interpreted as the same color. 10183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 10193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% The format of the TransparentPaintImage method is: 10203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 10213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% MagickBooleanType TransparentPaintImage(Image *image, 10224c08aed51c5899665ade97263692328eea4af106cristy% const PixelInfo *target,const Quantum opacity, 1023189e84ce7da8fbf4eb57c908846bcc0bdcbdc688cristy% const MagickBooleanType invert,ExceptionInfo *exception) 10243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 10253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% A description of each parameter follows: 10263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 10273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o image: the image. 10283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 10293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o target: the target color. 10303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 10313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o opacity: the replacement opacity value. 10323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 10333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o invert: paint any pixel that does not match the target color. 10343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 1035189e84ce7da8fbf4eb57c908846bcc0bdcbdc688cristy% o exception: return any errors or warnings in this structure. 1036189e84ce7da8fbf4eb57c908846bcc0bdcbdc688cristy% 10373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 10383ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport MagickBooleanType TransparentPaintImage(Image *image, 103914973baa8fa5c79889bc4db247200bb7d4626324cristy const PixelInfo *target,const Quantum opacity,const MagickBooleanType invert, 104014973baa8fa5c79889bc4db247200bb7d4626324cristy ExceptionInfo *exception) 10413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 10423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define TransparentPaintImageTag "Transparent/Image" 10433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1044c4c8d13c0996fea659ce63c682c803e74c1abc8acristy CacheView 1045c4c8d13c0996fea659ce63c682c803e74c1abc8acristy *image_view; 1046c4c8d13c0996fea659ce63c682c803e74c1abc8acristy 10473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 10483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status; 10493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1050bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy MagickOffsetType 1051bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy progress; 1052bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy 10534c08aed51c5899665ade97263692328eea4af106cristy PixelInfo 10543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy zero; 10553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1056bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy ssize_t 1057bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy y; 1058bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy 10593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy assert(image != (Image *) NULL); 1060e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy assert(image->signature == MagickCoreSignature); 10614c08aed51c5899665ade97263692328eea4af106cristy assert(target != (PixelInfo *) NULL); 10623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (image->debug != MagickFalse) 10633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 1064574cc26500992189f637cd1cdf93d0654e7df7aecristy if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 10653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 106617f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait == UndefinedPixelTrait) 106763240888c3975789a09c2494a4654b523931df96cristy (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception); 10683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 10693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Make image color transparent. 10703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 10713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=MagickTrue; 10723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy progress=0; 10734c08aed51c5899665ade97263692328eea4af106cristy GetPixelInfo(image,&zero); 107446ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy image_view=AcquireAuthenticCacheView(image,exception); 1075b5d5f725fef80ff5d50db3111c05a1a521b81e7fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 1076ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy #pragma omp parallel for schedule(static,4) shared(progress,status) \ 10775e6b259130f9dbe0da4666f734937017babe573acristy magick_threads(image,image,image->rows,1) 10783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 1079bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0; y < (ssize_t) image->rows; y++) 10803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 10814c08aed51c5899665ade97263692328eea4af106cristy PixelInfo 10823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy pixel; 10833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1084bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 10853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy x; 10863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 10874c08aed51c5899665ade97263692328eea4af106cristy register Quantum 108805d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict q; 10893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 10903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status == MagickFalse) 10913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy continue; 10923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 109314973baa8fa5c79889bc4db247200bb7d4626324cristy if (q == (Quantum *) NULL) 10943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 10953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=MagickFalse; 10963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy continue; 10973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 10983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy pixel=zero; 1099bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0; x < (ssize_t) image->columns; x++) 11003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 1101803640d20a6a664315eddfff6f8531d0c5e0871dcristy GetPixelInfoPixel(image,q,&pixel); 11024c08aed51c5899665ade97263692328eea4af106cristy if (IsFuzzyEquivalencePixelInfo(&pixel,target) != invert) 11034c08aed51c5899665ade97263692328eea4af106cristy SetPixelAlpha(image,opacity,q); 1104ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy q+=GetPixelChannels(image); 11053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 11063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 11073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=MagickFalse; 11083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (image->progress_monitor != (MagickProgressMonitor) NULL) 11093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 11103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 11113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy proceed; 11123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1113b5d5f725fef80ff5d50db3111c05a1a521b81e7fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 111495338b312d2239543881a93d7bed923eed6eaff9cristy #pragma omp critical (MagickCore_TransparentPaintImage) 11153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 11163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy proceed=SetImageProgress(image,TransparentPaintImageTag,progress++, 11173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy image->rows); 11183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (proceed == MagickFalse) 11193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=MagickFalse; 11203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 11213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 11223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy image_view=DestroyCacheView(image_view); 11233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(status); 11243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 11253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 11263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 11273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 11283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 11293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 11303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 11313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% T r a n s p a r e n t P a i n t I m a g e C h r o m a % 11323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 11333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 11343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 11353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 11363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 11373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% TransparentPaintImageChroma() changes the opacity value associated with any 11383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% pixel that matches color to the value defined by opacity. 11393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 114014973baa8fa5c79889bc4db247200bb7d4626324cristy% As there is one fuzz value for the all the channels, TransparentPaintImage() 114114973baa8fa5c79889bc4db247200bb7d4626324cristy% is not suitable for the operations like chroma, where the tolerance for 114214973baa8fa5c79889bc4db247200bb7d4626324cristy% similarity of two color component (RGB) can be different. Thus we define 114314973baa8fa5c79889bc4db247200bb7d4626324cristy% this method to take two target pixels (one low and one high) and all the 114414973baa8fa5c79889bc4db247200bb7d4626324cristy% pixels of an image which are lying between these two pixels are made 114514973baa8fa5c79889bc4db247200bb7d4626324cristy% transparent. 11463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 114714973baa8fa5c79889bc4db247200bb7d4626324cristy% The format of the TransparentPaintImageChroma method is: 11483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 114914973baa8fa5c79889bc4db247200bb7d4626324cristy% MagickBooleanType TransparentPaintImageChroma(Image *image, 115014973baa8fa5c79889bc4db247200bb7d4626324cristy% const PixelInfo *low,const PixelInfo *high,const Quantum opacity, 115114973baa8fa5c79889bc4db247200bb7d4626324cristy% const MagickBooleanType invert,ExceptionInfo *exception) 11523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 11533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% A description of each parameter follows: 11543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 11553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o image: the image. 11563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 11573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o low: the low target color. 11583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 11593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o high: the high target color. 11603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 11613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o opacity: the replacement opacity value. 11623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 11633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o invert: paint any pixel that does not match the target color. 11643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 1165189e84ce7da8fbf4eb57c908846bcc0bdcbdc688cristy% o exception: return any errors or warnings in this structure. 1166189e84ce7da8fbf4eb57c908846bcc0bdcbdc688cristy% 11673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 11683ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport MagickBooleanType TransparentPaintImageChroma(Image *image, 1169189e84ce7da8fbf4eb57c908846bcc0bdcbdc688cristy const PixelInfo *low,const PixelInfo *high,const Quantum opacity, 1170189e84ce7da8fbf4eb57c908846bcc0bdcbdc688cristy const MagickBooleanType invert,ExceptionInfo *exception) 11713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 11723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#define TransparentPaintImageTag "Transparent/Image" 11733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1174c4c8d13c0996fea659ce63c682c803e74c1abc8acristy CacheView 1175c4c8d13c0996fea659ce63c682c803e74c1abc8acristy *image_view; 1176c4c8d13c0996fea659ce63c682c803e74c1abc8acristy 11773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 11783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status; 11793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1180bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy MagickOffsetType 1181bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy progress; 1182bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy 1183bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy ssize_t 1184bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy y; 1185bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy 11863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy assert(image != (Image *) NULL); 1187e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy assert(image->signature == MagickCoreSignature); 11884c08aed51c5899665ade97263692328eea4af106cristy assert(high != (PixelInfo *) NULL); 11894c08aed51c5899665ade97263692328eea4af106cristy assert(low != (PixelInfo *) NULL); 11903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (image->debug != MagickFalse) 11913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 1192574cc26500992189f637cd1cdf93d0654e7df7aecristy if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 11933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 119417f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait == UndefinedPixelTrait) 119563240888c3975789a09c2494a4654b523931df96cristy (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception); 11963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 11973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Make image color transparent. 11983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 11993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=MagickTrue; 12003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy progress=0; 120146ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy image_view=AcquireAuthenticCacheView(image,exception); 1202b5d5f725fef80ff5d50db3111c05a1a521b81e7fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 1203ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy #pragma omp parallel for schedule(static,4) shared(progress,status) \ 12045e6b259130f9dbe0da4666f734937017babe573acristy magick_threads(image,image,image->rows,1) 12053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 1206bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0; y < (ssize_t) image->rows; y++) 12073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 12083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 12093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy match; 12103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 12114c08aed51c5899665ade97263692328eea4af106cristy PixelInfo 12123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy pixel; 12133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 12144c08aed51c5899665ade97263692328eea4af106cristy register Quantum 121505d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict q; 12163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 121714973baa8fa5c79889bc4db247200bb7d4626324cristy register ssize_t 121814973baa8fa5c79889bc4db247200bb7d4626324cristy x; 121914973baa8fa5c79889bc4db247200bb7d4626324cristy 12203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status == MagickFalse) 12213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy continue; 12223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception); 122314973baa8fa5c79889bc4db247200bb7d4626324cristy if (q == (Quantum *) NULL) 12243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 12253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=MagickFalse; 12263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy continue; 12273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 12284c08aed51c5899665ade97263692328eea4af106cristy GetPixelInfo(image,&pixel); 1229bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0; x < (ssize_t) image->columns; x++) 12303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 1231803640d20a6a664315eddfff6f8531d0c5e0871dcristy GetPixelInfoPixel(image,q,&pixel); 12323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy match=((pixel.red >= low->red) && (pixel.red <= high->red) && 12333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (pixel.green >= low->green) && (pixel.green <= high->green) && 123414973baa8fa5c79889bc4db247200bb7d4626324cristy (pixel.blue >= low->blue) && (pixel.blue <= high->blue)) ? MagickTrue : 123514973baa8fa5c79889bc4db247200bb7d4626324cristy MagickFalse; 12363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (match != invert) 12374c08aed51c5899665ade97263692328eea4af106cristy SetPixelAlpha(image,opacity,q); 1238ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy q+=GetPixelChannels(image); 12393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 12403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 12413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=MagickFalse; 12423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (image->progress_monitor != (MagickProgressMonitor) NULL) 12433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 12443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 12453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy proceed; 12463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1247b5d5f725fef80ff5d50db3111c05a1a521b81e7fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 124895338b312d2239543881a93d7bed923eed6eaff9cristy #pragma omp critical (MagickCore_TransparentPaintImageChroma) 12493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 12503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy proceed=SetImageProgress(image,TransparentPaintImageTag,progress++, 12513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy image->rows); 12523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (proceed == MagickFalse) 12533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=MagickFalse; 12543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 12553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 12563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy image_view=DestroyCacheView(image_view); 12573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(status); 12583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 1259