fourier.c revision 2e035cd272c0993d28f757f4a913070170095939
13ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 23ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 33ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 43ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 53ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 63ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% FFFFF OOO U U RRRR IIIII EEEEE RRRR % 73ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% F O O U U R R I E R R % 83ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% FFF O O U U RRRR I EEE RRRR % 93ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% F O O U U R R I E R R % 103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% F OOO UUU R R IIIII EEEEE R R % 113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% MagickCore Discrete Fourier Transform Methods % 143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% Software Design % 163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% Sean Burke % 173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% Fred Weinhaus % 18de984cdc3631106b1cbbb8d3972b76a0fc27e8e8cristy% Cristy % 193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% July 2009 % 203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 227ce65e7125a4e1df1a274ce373c537a9df9c16cdCristy% Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization % 233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% dedicated to making software imaging solutions freely available. % 243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% You may not use this file except in compliance with the License. You may % 263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% obtain a copy of the License at % 273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% http://www.imagemagick.org/script/license.php % 293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% Unless required by applicable law or agreed to in writing, software % 313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% distributed under the License is distributed on an "AS IS" BASIS, % 323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% See the License for the specific language governing permissions and % 343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% limitations under the License. % 353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Include declarations. 443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 454c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/studio.h" 4699dc036190f292a67801dc4b141898bf18c96b36cristy#include "MagickCore/artifact.h" 474c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/attribute.h" 487d4aa38318c20a4309d855f45e3744c9f300f697cristy#include "MagickCore/blob.h" 494c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/cache.h" 504c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image.h" 514c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/image-private.h" 524c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/list.h" 534c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/fourier.h" 544c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/log.h" 554c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/memory_.h" 564c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/monitor.h" 571042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy#include "MagickCore/monitor-private.h" 584c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/pixel-accessor.h" 5999dc036190f292a67801dc4b141898bf18c96b36cristy#include "MagickCore/pixel-private.h" 604c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/property.h" 614c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/quantum-private.h" 62ac245f8a51ea65b085d751c41d8ca4b426bdfe5bcristy#include "MagickCore/resource_.h" 6334b78eacf3bef963cade67c70f5f12785b9fe702cristy#include "MagickCore/string-private.h" 644c08aed51c5899665ade97263692328eea4af106cristy#include "MagickCore/thread-private.h" 653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_FFTW_DELEGATE) 6656ed31cc763800a9fb1f0df96104c354b40d2cbccristy#if defined(MAGICKCORE_HAVE_COMPLEX_H) 673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#include <complex.h> 6847b022b2592e21e468c453ad44f550b62f77b2cbcristy#endif 6947b022b2592e21e468c453ad44f550b62f77b2cbcristy#include <fftw3.h> 7047b022b2592e21e468c453ad44f550b62f77b2cbcristy#if !defined(MAGICKCORE_HAVE_CABS) 7156ed31cc763800a9fb1f0df96104c354b40d2cbccristy#define cabs(z) (sqrt(z[0]*z[0]+z[1]*z[1])) 7247b022b2592e21e468c453ad44f550b62f77b2cbcristy#endif 7347b022b2592e21e468c453ad44f550b62f77b2cbcristy#if !defined(MAGICKCORE_HAVE_CARG) 744da3ba3eedd349b48f5c8bbb9f15faee04f6e09fcristy#define carg(z) (atan2(cimag(z),creal(z))) 7547b022b2592e21e468c453ad44f550b62f77b2cbcristy#endif 7647b022b2592e21e468c453ad44f550b62f77b2cbcristy#if !defined(MAGICKCORE_HAVE_CIMAG) 7756ed31cc763800a9fb1f0df96104c354b40d2cbccristy#define cimag(z) (z[1]) 7856ed31cc763800a9fb1f0df96104c354b40d2cbccristy#endif 7947b022b2592e21e468c453ad44f550b62f77b2cbcristy#if !defined(MAGICKCORE_HAVE_CREAL) 8047b022b2592e21e468c453ad44f550b62f77b2cbcristy#define creal(z) (z[0]) 8147b022b2592e21e468c453ad44f550b62f77b2cbcristy#endif 823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Typedef declarations. 863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 873ed852eea50f9d4cd633efb8c2b054b8e33c253cristytypedef struct _FourierInfo 883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 89d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy PixelChannel 903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy channel; 913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy modulus; 943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 95bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy size_t 963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy width, 973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy height; 983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 99bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy ssize_t 1003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy center; 1013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} FourierInfo; 1023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 1043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 1063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 107790190d9d1e6f011220d0003ce5b51063f0ab417cristy% % 108790190d9d1e6f011220d0003ce5b51063f0ab417cristy% C o m p l e x I m a g e s % 109790190d9d1e6f011220d0003ce5b51063f0ab417cristy% % 110790190d9d1e6f011220d0003ce5b51063f0ab417cristy% % 111790190d9d1e6f011220d0003ce5b51063f0ab417cristy% % 112790190d9d1e6f011220d0003ce5b51063f0ab417cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 113790190d9d1e6f011220d0003ce5b51063f0ab417cristy% 114790190d9d1e6f011220d0003ce5b51063f0ab417cristy% ComplexImages() performs complex mathematics on an image sequence. 115790190d9d1e6f011220d0003ce5b51063f0ab417cristy% 116790190d9d1e6f011220d0003ce5b51063f0ab417cristy% The format of the ComplexImages method is: 117790190d9d1e6f011220d0003ce5b51063f0ab417cristy% 1184167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy% MagickBooleanType ComplexImages(Image *images,const ComplexOperator op, 1194167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy% ExceptionInfo *exception) 120790190d9d1e6f011220d0003ce5b51063f0ab417cristy% 121790190d9d1e6f011220d0003ce5b51063f0ab417cristy% A description of each parameter follows: 122790190d9d1e6f011220d0003ce5b51063f0ab417cristy% 123790190d9d1e6f011220d0003ce5b51063f0ab417cristy% o image: the image. 124790190d9d1e6f011220d0003ce5b51063f0ab417cristy% 1252e035cd272c0993d28f757f4a913070170095939Cristy% o op: A complex operator. 126790190d9d1e6f011220d0003ce5b51063f0ab417cristy% 127790190d9d1e6f011220d0003ce5b51063f0ab417cristy% o exception: return any errors or warnings in this structure. 128790190d9d1e6f011220d0003ce5b51063f0ab417cristy% 129790190d9d1e6f011220d0003ce5b51063f0ab417cristy*/ 130220c4d505bfb9cf557e8ec1616d7cdc0596379b8cristyMagickExport Image *ComplexImages(const Image *images,const ComplexOperator op, 131220c4d505bfb9cf557e8ec1616d7cdc0596379b8cristy ExceptionInfo *exception) 132790190d9d1e6f011220d0003ce5b51063f0ab417cristy{ 133790190d9d1e6f011220d0003ce5b51063f0ab417cristy#define ComplexImageTag "Complex/Image" 134790190d9d1e6f011220d0003ce5b51063f0ab417cristy 135790190d9d1e6f011220d0003ce5b51063f0ab417cristy CacheView 1361042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy *Ai_view, 1371042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy *Ar_view, 1381042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy *Bi_view, 1391042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy *Br_view, 1401042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy *Ci_view, 1411042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy *Cr_view; 1421042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy 14334b78eacf3bef963cade67c70f5f12785b9fe702cristy const char 14434b78eacf3bef963cade67c70f5f12785b9fe702cristy *artifact; 14534b78eacf3bef963cade67c70f5f12785b9fe702cristy 1461042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy const Image 1471042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy *Ai_image, 1481042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy *Ar_image, 1491042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy *Bi_image, 1501042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy *Br_image; 151790190d9d1e6f011220d0003ce5b51063f0ab417cristy 15234b78eacf3bef963cade67c70f5f12785b9fe702cristy double 15334b78eacf3bef963cade67c70f5f12785b9fe702cristy snr; 15434b78eacf3bef963cade67c70f5f12785b9fe702cristy 155790190d9d1e6f011220d0003ce5b51063f0ab417cristy Image 1561042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy *Ci_image, 1571042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy *complex_images, 15834919ed07da683cc334cd74e3c9d9c29c8b79b98cristy *Cr_image, 15934919ed07da683cc334cd74e3c9d9c29c8b79b98cristy *image; 160790190d9d1e6f011220d0003ce5b51063f0ab417cristy 161790190d9d1e6f011220d0003ce5b51063f0ab417cristy MagickBooleanType 162790190d9d1e6f011220d0003ce5b51063f0ab417cristy status; 163790190d9d1e6f011220d0003ce5b51063f0ab417cristy 164790190d9d1e6f011220d0003ce5b51063f0ab417cristy MagickOffsetType 165790190d9d1e6f011220d0003ce5b51063f0ab417cristy progress; 166790190d9d1e6f011220d0003ce5b51063f0ab417cristy 167790190d9d1e6f011220d0003ce5b51063f0ab417cristy ssize_t 168790190d9d1e6f011220d0003ce5b51063f0ab417cristy y; 169790190d9d1e6f011220d0003ce5b51063f0ab417cristy 170790190d9d1e6f011220d0003ce5b51063f0ab417cristy assert(images != (Image *) NULL); 171e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy assert(images->signature == MagickCoreSignature); 172790190d9d1e6f011220d0003ce5b51063f0ab417cristy if (images->debug != MagickFalse) 173790190d9d1e6f011220d0003ce5b51063f0ab417cristy (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",images->filename); 174790190d9d1e6f011220d0003ce5b51063f0ab417cristy assert(exception != (ExceptionInfo *) NULL); 175e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy assert(exception->signature == MagickCoreSignature); 1761042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy if (images->next == (Image *) NULL) 1771042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy { 1781042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy (void) ThrowMagickException(exception,GetMagickModule(),ImageError, 1791042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy "ImageSequenceRequired","`%s'",images->filename); 1801042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy return((Image *) NULL); 1811042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy } 18234919ed07da683cc334cd74e3c9d9c29c8b79b98cristy image=CloneImage(images,images->columns,images->rows,MagickTrue,exception); 18334919ed07da683cc334cd74e3c9d9c29c8b79b98cristy if (image == (Image *) NULL) 1841042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy return((Image *) NULL); 18534919ed07da683cc334cd74e3c9d9c29c8b79b98cristy if (SetImageStorageClass(image,DirectClass,exception) == MagickFalse) 18634919ed07da683cc334cd74e3c9d9c29c8b79b98cristy { 18734919ed07da683cc334cd74e3c9d9c29c8b79b98cristy image=DestroyImageList(image); 18834919ed07da683cc334cd74e3c9d9c29c8b79b98cristy return(image); 18934919ed07da683cc334cd74e3c9d9c29c8b79b98cristy } 1902e035cd272c0993d28f757f4a913070170095939Cristy image->depth=32UL; 19134919ed07da683cc334cd74e3c9d9c29c8b79b98cristy complex_images=NewImageList(); 19234919ed07da683cc334cd74e3c9d9c29c8b79b98cristy AppendImageToList(&complex_images,image); 19334919ed07da683cc334cd74e3c9d9c29c8b79b98cristy image=CloneImage(images,images->columns,images->rows,MagickTrue,exception); 19434919ed07da683cc334cd74e3c9d9c29c8b79b98cristy if (image == (Image *) NULL) 19534919ed07da683cc334cd74e3c9d9c29c8b79b98cristy { 19634919ed07da683cc334cd74e3c9d9c29c8b79b98cristy complex_images=DestroyImageList(complex_images); 19734919ed07da683cc334cd74e3c9d9c29c8b79b98cristy return(complex_images); 19834919ed07da683cc334cd74e3c9d9c29c8b79b98cristy } 199dc6589cac93cf46a2d9d7ee71c48df8c215f398fcristy AppendImageToList(&complex_images,image); 2002e035cd272c0993d28f757f4a913070170095939Cristy complex_images->storage_class=DirectClass; 2012e035cd272c0993d28f757f4a913070170095939Cristy complex_images->depth=32UL; 2021042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy /* 2031042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Apply complex mathematics to image pixels. 2041042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy */ 20534b78eacf3bef963cade67c70f5f12785b9fe702cristy artifact=GetImageArtifact(image,"complex:snr"); 20634b78eacf3bef963cade67c70f5f12785b9fe702cristy snr=0.0; 20734b78eacf3bef963cade67c70f5f12785b9fe702cristy if (artifact != (const char *) NULL) 20834b78eacf3bef963cade67c70f5f12785b9fe702cristy snr=StringToDouble(artifact,(char **) NULL); 2091042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Ar_image=images; 2101042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Ai_image=images->next; 2118dc6a07d751896a7c400a6d888a5964c538fad2dcristy Br_image=images; 2128dc6a07d751896a7c400a6d888a5964c538fad2dcristy Bi_image=images->next; 2138dc6a07d751896a7c400a6d888a5964c538fad2dcristy if ((images->next->next != (Image *) NULL) && 2148dc6a07d751896a7c400a6d888a5964c538fad2dcristy (images->next->next->next != (Image *) NULL)) 2151042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy { 2161042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Br_image=images->next->next; 2171042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Bi_image=images->next->next->next; 2181042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy } 2191042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Cr_image=complex_images; 2201042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Ci_image=complex_images->next; 2211042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Ar_view=AcquireVirtualCacheView(Ar_image,exception); 2221042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Ai_view=AcquireVirtualCacheView(Ai_image,exception); 2231042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Br_view=AcquireVirtualCacheView(Br_image,exception); 2241042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Bi_view=AcquireVirtualCacheView(Bi_image,exception); 2251042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Cr_view=AcquireAuthenticCacheView(Cr_image,exception); 2261042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Ci_view=AcquireAuthenticCacheView(Ci_image,exception); 2271042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy status=MagickTrue; 2281042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy progress=0; 2291042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 2304167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy #pragma omp parallel for schedule(static,4) shared(progress,status) \ 2314167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy magick_threads(images,complex_images,images->rows,1L) 2321042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy#endif 2331042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy for (y=0; y < (ssize_t) images->rows; y++) 2341042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy { 2351042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy register const Quantum 23605d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict Ai, 23705d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict Ar, 23805d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict Bi, 23905d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict Br; 2401042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy 2411042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy register Quantum 24205d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict Ci, 24305d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict Cr; 2441042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy 2451042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy register ssize_t 2461042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy x; 2471042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy 24834919ed07da683cc334cd74e3c9d9c29c8b79b98cristy if (status == MagickFalse) 24934919ed07da683cc334cd74e3c9d9c29c8b79b98cristy continue; 2504167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Ar=GetCacheViewVirtualPixels(Ar_view,0,y,Ar_image->columns,1,exception); 2514167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Ai=GetCacheViewVirtualPixels(Ai_view,0,y,Ai_image->columns,1,exception); 2524167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Br=GetCacheViewVirtualPixels(Br_view,0,y,Br_image->columns,1,exception); 2534167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Bi=GetCacheViewVirtualPixels(Bi_view,0,y,Bi_image->columns,1,exception); 2544167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Cr=QueueCacheViewAuthenticPixels(Cr_view,0,y,Cr_image->columns,1,exception); 2554167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Ci=QueueCacheViewAuthenticPixels(Ci_view,0,y,Ci_image->columns,1,exception); 2561042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy if ((Ar == (const Quantum *) NULL) || (Ai == (const Quantum *) NULL) || 2571042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy (Br == (const Quantum *) NULL) || (Bi == (const Quantum *) NULL) || 2581042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy (Cr == (Quantum *) NULL) || (Ci == (Quantum *) NULL)) 2591042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy { 2601042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy status=MagickFalse; 2611042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy continue; 2621042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy } 2631042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy for (x=0; x < (ssize_t) images->columns; x++) 2641042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy { 2659f654472e80883bb7c4ec299036733e0e23570d7cristy register ssize_t 2669f654472e80883bb7c4ec299036733e0e23570d7cristy i; 2679f654472e80883bb7c4ec299036733e0e23570d7cristy 2689f654472e80883bb7c4ec299036733e0e23570d7cristy for (i=0; i < (ssize_t) GetPixelChannels(images); i++) 2699f654472e80883bb7c4ec299036733e0e23570d7cristy { 270220c4d505bfb9cf557e8ec1616d7cdc0596379b8cristy switch (op) 2719f654472e80883bb7c4ec299036733e0e23570d7cristy { 27219f7886e4423cd5ce3eef31092942f55ba770983cristy case AddComplexOperator: 27319f7886e4423cd5ce3eef31092942f55ba770983cristy { 27419f7886e4423cd5ce3eef31092942f55ba770983cristy Cr[i]=Ar[i]+Br[i]; 27519f7886e4423cd5ce3eef31092942f55ba770983cristy Ci[i]=Ai[i]+Bi[i]; 27619f7886e4423cd5ce3eef31092942f55ba770983cristy break; 27719f7886e4423cd5ce3eef31092942f55ba770983cristy } 2789f654472e80883bb7c4ec299036733e0e23570d7cristy case ConjugateComplexOperator: 2799f654472e80883bb7c4ec299036733e0e23570d7cristy default: 2809f654472e80883bb7c4ec299036733e0e23570d7cristy { 2819f654472e80883bb7c4ec299036733e0e23570d7cristy Cr[i]=Ar[i]; 2829f654472e80883bb7c4ec299036733e0e23570d7cristy Ci[i]=(-Bi[i]); 2839f654472e80883bb7c4ec299036733e0e23570d7cristy break; 2849f654472e80883bb7c4ec299036733e0e23570d7cristy } 2859f654472e80883bb7c4ec299036733e0e23570d7cristy case DivideComplexOperator: 2869f654472e80883bb7c4ec299036733e0e23570d7cristy { 2879f654472e80883bb7c4ec299036733e0e23570d7cristy double 2889f654472e80883bb7c4ec299036733e0e23570d7cristy gamma; 2899f654472e80883bb7c4ec299036733e0e23570d7cristy 29034b78eacf3bef963cade67c70f5f12785b9fe702cristy gamma=PerceptibleReciprocal(Br[i]*Br[i]+Bi[i]*Bi[i]+snr); 2919f654472e80883bb7c4ec299036733e0e23570d7cristy Cr[i]=gamma*(Ar[i]*Br[i]+Ai[i]*Bi[i]); 292857c8a100c50bd902586a902c27fccab271dce1dcristy Ci[i]=gamma*(Ai[i]*Br[i]-Ar[i]*Bi[i]); 2939f654472e80883bb7c4ec299036733e0e23570d7cristy break; 2949f654472e80883bb7c4ec299036733e0e23570d7cristy } 295f46941ca310386db5b9939840c884c6f8a5c7189cristy case MagnitudePhaseComplexOperator: 296f46941ca310386db5b9939840c884c6f8a5c7189cristy { 2978526a9763e0671ebad481fd00679fb857ce8d84acristy Cr[i]=sqrt(Ar[i]*Ar[i]+Ai[i]*Ai[i]); 2984ab069406391dd3d34359d17a6ab7333f7200729cristy Ci[i]=atan2(Ai[i],Ar[i])/(2.0*MagickPI)+0.5; 299f46941ca310386db5b9939840c884c6f8a5c7189cristy break; 300f46941ca310386db5b9939840c884c6f8a5c7189cristy } 3019f654472e80883bb7c4ec299036733e0e23570d7cristy case MultiplyComplexOperator: 3029f654472e80883bb7c4ec299036733e0e23570d7cristy { 30315b07b3f81434e5cee2ed16d51ec3f504949d992cristy Cr[i]=QuantumScale*(Ar[i]*Br[i]-Ai[i]*Bi[i]); 30415b07b3f81434e5cee2ed16d51ec3f504949d992cristy Ci[i]=QuantumScale*(Ai[i]*Br[i]+Ar[i]*Bi[i]); 305f46941ca310386db5b9939840c884c6f8a5c7189cristy break; 306f46941ca310386db5b9939840c884c6f8a5c7189cristy } 307f46941ca310386db5b9939840c884c6f8a5c7189cristy case RealImaginaryComplexOperator: 308f46941ca310386db5b9939840c884c6f8a5c7189cristy { 3094ab069406391dd3d34359d17a6ab7333f7200729cristy Cr[i]=Ar[i]*cos(2.0*MagickPI*(Ai[i]-0.5)); 3104ab069406391dd3d34359d17a6ab7333f7200729cristy Ci[i]=Ar[i]*sin(2.0*MagickPI*(Ai[i]-0.5)); 3119f654472e80883bb7c4ec299036733e0e23570d7cristy break; 3129f654472e80883bb7c4ec299036733e0e23570d7cristy } 31319f7886e4423cd5ce3eef31092942f55ba770983cristy case SubtractComplexOperator: 31419f7886e4423cd5ce3eef31092942f55ba770983cristy { 31519f7886e4423cd5ce3eef31092942f55ba770983cristy Cr[i]=Ar[i]-Br[i]; 31619f7886e4423cd5ce3eef31092942f55ba770983cristy Ci[i]=Ai[i]-Bi[i]; 31719f7886e4423cd5ce3eef31092942f55ba770983cristy break; 31819f7886e4423cd5ce3eef31092942f55ba770983cristy } 3199f654472e80883bb7c4ec299036733e0e23570d7cristy } 3209f654472e80883bb7c4ec299036733e0e23570d7cristy } 3214167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Ar+=GetPixelChannels(Ar_image); 3224167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Ai+=GetPixelChannels(Ai_image); 3234167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Br+=GetPixelChannels(Br_image); 3244167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Bi+=GetPixelChannels(Bi_image); 3254167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Cr+=GetPixelChannels(Cr_image); 3264167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Ci+=GetPixelChannels(Ci_image); 3271042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy } 3281042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy if (SyncCacheViewAuthenticPixels(Ci_view,exception) == MagickFalse) 3291042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy status=MagickFalse; 3301042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy if (SyncCacheViewAuthenticPixels(Cr_view,exception) == MagickFalse) 3311042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy status=MagickFalse; 3321042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy if (images->progress_monitor != (MagickProgressMonitor) NULL) 3331042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy { 3341042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy MagickBooleanType 3351042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy proceed; 3361042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy 3371042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 3381042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy #pragma omp critical (MagickCore_ComplexImages) 3391042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy#endif 3401042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy proceed=SetImageProgress(images,ComplexImageTag,progress++, 3411042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy images->rows); 3421042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy if (proceed == MagickFalse) 3431042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy status=MagickFalse; 3441042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy } 3451042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy } 3461042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Cr_view=DestroyCacheView(Cr_view); 3471042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Ci_view=DestroyCacheView(Ci_view); 3481042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Br_view=DestroyCacheView(Br_view); 3491042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Bi_view=DestroyCacheView(Bi_view); 3501042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Ar_view=DestroyCacheView(Ar_view); 3511042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Ai_view=DestroyCacheView(Ai_view); 3521042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy if (status == MagickFalse) 3531042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy complex_images=DestroyImageList(complex_images); 3541042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy return(complex_images); 355790190d9d1e6f011220d0003ce5b51063f0ab417cristy} 356790190d9d1e6f011220d0003ce5b51063f0ab417cristy 357790190d9d1e6f011220d0003ce5b51063f0ab417cristy/* 358790190d9d1e6f011220d0003ce5b51063f0ab417cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 359790190d9d1e6f011220d0003ce5b51063f0ab417cristy% % 360790190d9d1e6f011220d0003ce5b51063f0ab417cristy% % 3613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% F o r w a r d F o u r i e r T r a n s f o r m I m a g e % 3633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% ForwardFourierTransformImage() implements the discrete Fourier transform 3693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% (DFT) of the image either as a magnitude / phase or real / imaginary image 3703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% pair. 3713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% The format of the ForwadFourierTransformImage method is: 3733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% Image *ForwardFourierTransformImage(const Image *image, 3753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% const MagickBooleanType modulus,ExceptionInfo *exception) 3763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% A description of each parameter follows: 3783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o image: the image. 3803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o modulus: if true, return as transform as a magnitude / phase pair 3823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% otherwise a real / imaginary image pair. 3833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o exception: return any errors or warnings in this structure. 3853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 3873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 3883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_FFTW_DELEGATE) 3893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 390c4ea4a479c90f81168aa2b99e7680c7b0459d415cristystatic MagickBooleanType RollFourier(const size_t width,const size_t height, 391699ae5b6cbee363e53f58e0fedd414f282d07eddcristy const ssize_t x_offset,const ssize_t y_offset,double *roll_pixels) 3923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 3933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy double 394699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *source_pixels; 3953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 3967d4aa38318c20a4309d855f45e3744c9f300f697cristy MemoryInfo 397699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *source_info; 3987d4aa38318c20a4309d855f45e3744c9f300f697cristy 399c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy register ssize_t 400c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy i, 401c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy x; 402c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy 403bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy ssize_t 4043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy u, 4053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy v, 4063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy y; 4073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 4083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 4092da0535a82cc655e5a48deac466bd6fcef1f4924cristy Move zero frequency (DC, average color) from (0,0) to (width/2,height/2). 4103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 4112e035cd272c0993d28f757f4a913070170095939Cristy source_info=AcquireVirtualMemory(width,height*sizeof(*source_pixels)); 412699ae5b6cbee363e53f58e0fedd414f282d07eddcristy if (source_info == (MemoryInfo *) NULL) 4133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 414699ae5b6cbee363e53f58e0fedd414f282d07eddcristy source_pixels=(double *) GetVirtualMemoryBlob(source_info); 4153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 416bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) height; y++) 4173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 4183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (y_offset < 0L) 419bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy v=((y+y_offset) < 0L) ? y+y_offset+(ssize_t) height : y+y_offset; 4203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy else 421bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy v=((y+y_offset) > ((ssize_t) height-1L)) ? y+y_offset-(ssize_t) height : 4223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy y+y_offset; 423bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) width; x++) 4243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 4253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (x_offset < 0L) 426bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy u=((x+x_offset) < 0L) ? x+x_offset+(ssize_t) width : x+x_offset; 4273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy else 428bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy u=((x+x_offset) > ((ssize_t) width-1L)) ? x+x_offset-(ssize_t) width : 4293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy x+x_offset; 430699ae5b6cbee363e53f58e0fedd414f282d07eddcristy source_pixels[v*width+u]=roll_pixels[i++]; 431c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy } 4323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 433699ae5b6cbee363e53f58e0fedd414f282d07eddcristy (void) CopyMagickMemory(roll_pixels,source_pixels,height*width* 434699ae5b6cbee363e53f58e0fedd414f282d07eddcristy sizeof(*source_pixels)); 435699ae5b6cbee363e53f58e0fedd414f282d07eddcristy source_info=RelinquishVirtualMemory(source_info); 4363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickTrue); 4373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 4383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 439bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristystatic MagickBooleanType ForwardQuadrantSwap(const size_t width, 440699ae5b6cbee363e53f58e0fedd414f282d07eddcristy const size_t height,double *source_pixels,double *forward_pixels) 4413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 4423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 4433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status; 4443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 445bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 4463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy x; 4473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 448c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy ssize_t 449c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy center, 450c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy y; 451c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy 4523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 4533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Swap quadrants. 4543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 4552e035cd272c0993d28f757f4a913070170095939Cristy center=(ssize_t) (width/2L)+1L; 456699ae5b6cbee363e53f58e0fedd414f282d07eddcristy status=RollFourier((size_t) center,height,0L,(ssize_t) height/2L, 457699ae5b6cbee363e53f58e0fedd414f282d07eddcristy source_pixels); 4583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status == MagickFalse) 4593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 460bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) height; y++) 4616831e2f47f00e8b78275319e4aec01d120a3876fCristy for (x=0L; x < (ssize_t) (width/2L); x++) 4623d04ed7ddc7a93c09476e84cc64412687bf5261acristy forward_pixels[y*width+x+width/2L]=source_pixels[y*center+x]; 463bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=1; y < (ssize_t) height; y++) 4646831e2f47f00e8b78275319e4aec01d120a3876fCristy for (x=0L; x < (ssize_t) (width/2L); x++) 4659b1d6c756cb32746846b038ccb0439db540ba509cristy forward_pixels[(height-y)*width+width/2L-x-1L]= 4663d04ed7ddc7a93c09476e84cc64412687bf5261acristy source_pixels[y*center+x+1L]; 467bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) (width/2L); x++) 4686831e2f47f00e8b78275319e4aec01d120a3876fCristy forward_pixels[width/2L-x-1L]=source_pixels[x+1L]; 4693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickTrue); 4703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 4713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 472c4ea4a479c90f81168aa2b99e7680c7b0459d415cristystatic void CorrectPhaseLHS(const size_t width,const size_t height, 473699ae5b6cbee363e53f58e0fedd414f282d07eddcristy double *fourier_pixels) 4743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 475bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 4763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy x; 4773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 4789d314ff2c17a77996c05413c2013880387e50f0ecristy ssize_t 4799d314ff2c17a77996c05413c2013880387e50f0ecristy y; 4809d314ff2c17a77996c05413c2013880387e50f0ecristy 481bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) height; y++) 482bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) (width/2L); x++) 483699ae5b6cbee363e53f58e0fedd414f282d07eddcristy fourier_pixels[y*width+x]*=(-1.0); 4843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 4853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 4863ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType ForwardFourier(const FourierInfo *fourier_info, 4873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Image *image,double *magnitude,double *phase,ExceptionInfo *exception) 4883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 4893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy CacheView 4903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *magnitude_view, 4913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *phase_view; 4923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 4933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy double 4947d4aa38318c20a4309d855f45e3744c9f300f697cristy *magnitude_pixels, 4957d4aa38318c20a4309d855f45e3744c9f300f697cristy *phase_pixels; 4963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 4973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Image 4983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *magnitude_image, 4993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *phase_image; 5003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 5013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 5023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status; 5033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 5047d4aa38318c20a4309d855f45e3744c9f300f697cristy MemoryInfo 5057d4aa38318c20a4309d855f45e3744c9f300f697cristy *magnitude_info, 5067d4aa38318c20a4309d855f45e3744c9f300f697cristy *phase_info; 5077d4aa38318c20a4309d855f45e3744c9f300f697cristy 5084c08aed51c5899665ade97263692328eea4af106cristy register Quantum 5093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *q; 5103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 511f5742794873c63f8b052150a2f44015e1ad55356cristy register ssize_t 512f5742794873c63f8b052150a2f44015e1ad55356cristy x; 513f5742794873c63f8b052150a2f44015e1ad55356cristy 514c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy ssize_t 515c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy i, 516c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy y; 517c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy 5183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy magnitude_image=GetFirstImageInList(image); 5193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy phase_image=GetNextImageInList(image); 5203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (phase_image == (Image *) NULL) 5213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 5223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) ThrowMagickException(exception,GetMagickModule(),ImageError, 5232e035cd272c0993d28f757f4a913070170095939Cristy "ImageSequenceRequired","`%s'",image->filename); 5243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 5253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 5263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 5273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Create "Fourier Transform" image from constituent arrays. 5283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 5292e035cd272c0993d28f757f4a913070170095939Cristy magnitude_info=AcquireVirtualMemory((size_t) fourier_info->width, 5302e035cd272c0993d28f757f4a913070170095939Cristy fourier_info->height*sizeof(*magnitude_pixels)); 5312e035cd272c0993d28f757f4a913070170095939Cristy phase_info=AcquireVirtualMemory((size_t) fourier_info->width, 5322e035cd272c0993d28f757f4a913070170095939Cristy fourier_info->height*sizeof(*phase_pixels)); 533bb3c02e054634545e7595cea2048c07de0407f1acristy if ((magnitude_info == (MemoryInfo *) NULL) || 534bb3c02e054634545e7595cea2048c07de0407f1acristy (phase_info == (MemoryInfo *) NULL)) 5353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 5367d4aa38318c20a4309d855f45e3744c9f300f697cristy if (phase_info != (MemoryInfo *) NULL) 5377d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_info=RelinquishVirtualMemory(phase_info); 5387d4aa38318c20a4309d855f45e3744c9f300f697cristy if (magnitude_info != (MemoryInfo *) NULL) 5397d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_info=RelinquishVirtualMemory(magnitude_info); 5403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) ThrowMagickException(exception,GetMagickModule(), 541efe601ce9ea5ad34ad0e8ad6e61d9be9b148b2a3cristy ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); 5423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 5433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 5447d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels=(double *) GetVirtualMemoryBlob(magnitude_info); 5457d4aa38318c20a4309d855f45e3744c9f300f697cristy (void) ResetMagickMemory(magnitude_pixels,0,fourier_info->height* 5467d4aa38318c20a4309d855f45e3744c9f300f697cristy fourier_info->width*sizeof(*magnitude_pixels)); 547bb3c02e054634545e7595cea2048c07de0407f1acristy phase_pixels=(double *) GetVirtualMemoryBlob(phase_info); 5487d4aa38318c20a4309d855f45e3744c9f300f697cristy (void) ResetMagickMemory(phase_pixels,0,fourier_info->height* 5497d4aa38318c20a4309d855f45e3744c9f300f697cristy fourier_info->width*sizeof(*phase_pixels)); 55013c99c4243ef58ec6f752aba6df9970ec16c87e6cristy status=ForwardQuadrantSwap(fourier_info->width,fourier_info->height, 5517d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude,magnitude_pixels); 5523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status != MagickFalse) 55313c99c4243ef58ec6f752aba6df9970ec16c87e6cristy status=ForwardQuadrantSwap(fourier_info->width,fourier_info->height,phase, 5547d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels); 55513c99c4243ef58ec6f752aba6df9970ec16c87e6cristy CorrectPhaseLHS(fourier_info->width,fourier_info->height,phase_pixels); 5563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (fourier_info->modulus != MagickFalse) 5573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 5583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 559bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 560bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->width; x++) 5613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 5627d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]/=(2.0*MagickPI); 5637d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]+=0.5; 5643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 5653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 5663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 56746ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy magnitude_view=AcquireAuthenticCacheView(magnitude_image,exception); 5683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 569bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 5703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 5715570fc587fc1fb64666649c75bb7531e08e96a0aCristy q=GetCacheViewAuthenticPixels(magnitude_view,0L,y,fourier_info->width,1UL, 5723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy exception); 573acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy if (q == (Quantum *) NULL) 5743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 575bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->width; x++) 5763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 5773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy switch (fourier_info->channel) 5783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 579d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case RedPixelChannel: 5803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy default: 5813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 5824c08aed51c5899665ade97263692328eea4af106cristy SetPixelRed(magnitude_image,ClampToQuantum(QuantumRange* 5837d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels[i]),q); 5843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 5853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 586d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case GreenPixelChannel: 5873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 5884c08aed51c5899665ade97263692328eea4af106cristy SetPixelGreen(magnitude_image,ClampToQuantum(QuantumRange* 5897d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels[i]),q); 5903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 5913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 592d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case BluePixelChannel: 5933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 5944c08aed51c5899665ade97263692328eea4af106cristy SetPixelBlue(magnitude_image,ClampToQuantum(QuantumRange* 5957d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels[i]),q); 5963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 5973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 598d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case BlackPixelChannel: 5993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6004c08aed51c5899665ade97263692328eea4af106cristy SetPixelBlack(magnitude_image,ClampToQuantum(QuantumRange* 6017d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels[i]),q); 6023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 604d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case AlphaPixelChannel: 6053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6064c08aed51c5899665ade97263692328eea4af106cristy SetPixelAlpha(magnitude_image,ClampToQuantum(QuantumRange* 6077d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels[i]),q); 6083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 6103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 6113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 612ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy q+=GetPixelChannels(magnitude_image); 6133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 6143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=SyncCacheViewAuthenticPixels(magnitude_view,exception); 6153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status == MagickFalse) 6163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 618db070957cf6bf959df9283a482377e8854c3d4d2cristy magnitude_view=DestroyCacheView(magnitude_view); 6193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 62046ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy phase_view=AcquireAuthenticCacheView(phase_image,exception); 621bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 6223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6235570fc587fc1fb64666649c75bb7531e08e96a0aCristy q=GetCacheViewAuthenticPixels(phase_view,0L,y,fourier_info->width,1UL, 6243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy exception); 625acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy if (q == (Quantum *) NULL) 6263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 627bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->width; x++) 6283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy switch (fourier_info->channel) 6303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 631d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case RedPixelChannel: 6323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy default: 6333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6344c08aed51c5899665ade97263692328eea4af106cristy SetPixelRed(phase_image,ClampToQuantum(QuantumRange* 6357d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]),q); 6363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 638d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case GreenPixelChannel: 6393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6404c08aed51c5899665ade97263692328eea4af106cristy SetPixelGreen(phase_image,ClampToQuantum(QuantumRange* 6417d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]),q); 6423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 644d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case BluePixelChannel: 6453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6464c08aed51c5899665ade97263692328eea4af106cristy SetPixelBlue(phase_image,ClampToQuantum(QuantumRange* 6477d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]),q); 6483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 650d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case BlackPixelChannel: 6513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6524c08aed51c5899665ade97263692328eea4af106cristy SetPixelBlack(phase_image,ClampToQuantum(QuantumRange* 6537d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]),q); 6543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 656d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case AlphaPixelChannel: 6573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6584c08aed51c5899665ade97263692328eea4af106cristy SetPixelAlpha(phase_image,ClampToQuantum(QuantumRange* 6597d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]),q); 6603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 6623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 6633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 664ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy q+=GetPixelChannels(phase_image); 6653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 6663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=SyncCacheViewAuthenticPixels(phase_view,exception); 6673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status == MagickFalse) 6683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 6703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy phase_view=DestroyCacheView(phase_view); 6717d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_info=RelinquishVirtualMemory(phase_info); 6727d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_info=RelinquishVirtualMemory(magnitude_info); 6733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(status); 6743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 6753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 6763ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType ForwardFourierTransform(FourierInfo *fourier_info, 677699ae5b6cbee363e53f58e0fedd414f282d07eddcristy const Image *image,double *magnitude_pixels,double *phase_pixels, 678699ae5b6cbee363e53f58e0fedd414f282d07eddcristy ExceptionInfo *exception) 6793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 6803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy CacheView 6813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *image_view; 6823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 68399dc036190f292a67801dc4b141898bf18c96b36cristy const char 68499dc036190f292a67801dc4b141898bf18c96b36cristy *value; 68599dc036190f292a67801dc4b141898bf18c96b36cristy 6863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy double 687bb3c02e054634545e7595cea2048c07de0407f1acristy *source_pixels; 6883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 6893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fftw_complex 690699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *forward_pixels; 6913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 6923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fftw_plan 6933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fftw_r2c_plan; 6943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 6957d4aa38318c20a4309d855f45e3744c9f300f697cristy MemoryInfo 696699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *forward_info, 6977d4aa38318c20a4309d855f45e3744c9f300f697cristy *source_info; 6987d4aa38318c20a4309d855f45e3744c9f300f697cristy 6994c08aed51c5899665ade97263692328eea4af106cristy register const Quantum 7003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *p; 7013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 702bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 7033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i, 7043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy x; 7053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 706c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy ssize_t 707c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy y; 708c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy 7093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 7103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Generate the forward Fourier transform. 7113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 7122e035cd272c0993d28f757f4a913070170095939Cristy source_info=AcquireVirtualMemory((size_t) fourier_info->width, 7132e035cd272c0993d28f757f4a913070170095939Cristy fourier_info->height*sizeof(*source_pixels)); 7147d4aa38318c20a4309d855f45e3744c9f300f697cristy if (source_info == (MemoryInfo *) NULL) 7153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 7163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) ThrowMagickException(exception,GetMagickModule(), 717efe601ce9ea5ad34ad0e8ad6e61d9be9b148b2a3cristy ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); 7183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 7193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 720bb3c02e054634545e7595cea2048c07de0407f1acristy source_pixels=(double *) GetVirtualMemoryBlob(source_info); 721bb3c02e054634545e7595cea2048c07de0407f1acristy ResetMagickMemory(source_pixels,0,fourier_info->height*fourier_info->width* 722bb3c02e054634545e7595cea2048c07de0407f1acristy sizeof(*source_pixels)); 7233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 72446ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy image_view=AcquireVirtualCacheView(image,exception); 725bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 7263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 7273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy p=GetCacheViewVirtualPixels(image_view,0L,y,fourier_info->width,1UL, 7283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy exception); 7294c08aed51c5899665ade97263692328eea4af106cristy if (p == (const Quantum *) NULL) 7303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 731bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->width; x++) 7323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 7333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy switch (fourier_info->channel) 7343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 735d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case RedPixelChannel: 7363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy default: 7373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 738bb3c02e054634545e7595cea2048c07de0407f1acristy source_pixels[i]=QuantumScale*GetPixelRed(image,p); 7393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 7403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 741d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case GreenPixelChannel: 7423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 743bb3c02e054634545e7595cea2048c07de0407f1acristy source_pixels[i]=QuantumScale*GetPixelGreen(image,p); 7443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 7453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 746d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case BluePixelChannel: 7473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 748bb3c02e054634545e7595cea2048c07de0407f1acristy source_pixels[i]=QuantumScale*GetPixelBlue(image,p); 7493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 7503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 751d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case BlackPixelChannel: 7523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 753bb3c02e054634545e7595cea2048c07de0407f1acristy source_pixels[i]=QuantumScale*GetPixelBlack(image,p); 7543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 7553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 756d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case AlphaPixelChannel: 7573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 758bb3c02e054634545e7595cea2048c07de0407f1acristy source_pixels[i]=QuantumScale*GetPixelAlpha(image,p); 7593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 7603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 7613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 7623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 763ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy p+=GetPixelChannels(image); 7643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 7653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 7663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy image_view=DestroyCacheView(image_view); 767bbc9a95a7875c8c9b4a8e0b87491aa52e56ec849Cristy forward_info=AcquireVirtualMemory((size_t) fourier_info->width, 7682e035cd272c0993d28f757f4a913070170095939Cristy (fourier_info->height/2+1)*sizeof(*forward_pixels)); 769699ae5b6cbee363e53f58e0fedd414f282d07eddcristy if (forward_info == (MemoryInfo *) NULL) 7703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 7713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) ThrowMagickException(exception,GetMagickModule(), 772efe601ce9ea5ad34ad0e8ad6e61d9be9b148b2a3cristy ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); 773bb3c02e054634545e7595cea2048c07de0407f1acristy source_info=(MemoryInfo *) RelinquishVirtualMemory(source_info); 7743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 7753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 776699ae5b6cbee363e53f58e0fedd414f282d07eddcristy forward_pixels=(fftw_complex *) GetVirtualMemoryBlob(forward_info); 777b5d5f725fef80ff5d50db3111c05a1a521b81e7fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 7783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy #pragma omp critical (MagickCore_ForwardFourierTransform) 7793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 78070841a141aec156091268e1c6e20938abffbfa5ccristy fftw_r2c_plan=fftw_plan_dft_r2c_2d(fourier_info->width,fourier_info->height, 781699ae5b6cbee363e53f58e0fedd414f282d07eddcristy source_pixels,forward_pixels,FFTW_ESTIMATE); 782bbc9a95a7875c8c9b4a8e0b87491aa52e56ec849Cristy fftw_execute_dft_r2c(fftw_r2c_plan,source_pixels,forward_pixels); 7833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fftw_destroy_plan(fftw_r2c_plan); 784bb3c02e054634545e7595cea2048c07de0407f1acristy source_info=(MemoryInfo *) RelinquishVirtualMemory(source_info); 78599dc036190f292a67801dc4b141898bf18c96b36cristy value=GetImageArtifact(image,"fourier:normalize"); 786f8ecbfdd4702c1b9dcc8f35870b60d61e6d32d79cristy if ((value == (const char *) NULL) || (LocaleCompare(value,"forward") == 0)) 78756ed31cc763800a9fb1f0df96104c354b40d2cbccristy { 78899dc036190f292a67801dc4b141898bf18c96b36cristy double 78999dc036190f292a67801dc4b141898bf18c96b36cristy gamma; 79099dc036190f292a67801dc4b141898bf18c96b36cristy 79199dc036190f292a67801dc4b141898bf18c96b36cristy /* 7922e035cd272c0993d28f757f4a913070170095939Cristy Normalize fourier transform. 79399dc036190f292a67801dc4b141898bf18c96b36cristy */ 79499dc036190f292a67801dc4b141898bf18c96b36cristy i=0L; 79599dc036190f292a67801dc4b141898bf18c96b36cristy gamma=PerceptibleReciprocal((double) fourier_info->width* 79699dc036190f292a67801dc4b141898bf18c96b36cristy fourier_info->height); 79799dc036190f292a67801dc4b141898bf18c96b36cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 79899dc036190f292a67801dc4b141898bf18c96b36cristy for (x=0L; x < (ssize_t) fourier_info->center; x++) 79999dc036190f292a67801dc4b141898bf18c96b36cristy { 80056ed31cc763800a9fb1f0df96104c354b40d2cbccristy#if defined(MAGICKCORE_HAVE_COMPLEX_H) 80199dc036190f292a67801dc4b141898bf18c96b36cristy forward_pixels[i]*=gamma; 80256ed31cc763800a9fb1f0df96104c354b40d2cbccristy#else 80399dc036190f292a67801dc4b141898bf18c96b36cristy forward_pixels[i][0]*=gamma; 80499dc036190f292a67801dc4b141898bf18c96b36cristy forward_pixels[i][1]*=gamma; 80556ed31cc763800a9fb1f0df96104c354b40d2cbccristy#endif 80699dc036190f292a67801dc4b141898bf18c96b36cristy i++; 80799dc036190f292a67801dc4b141898bf18c96b36cristy } 80856ed31cc763800a9fb1f0df96104c354b40d2cbccristy } 8093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 8103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Generate magnitude and phase (or real and imaginary). 8113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 8123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 8133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (fourier_info->modulus != MagickFalse) 814bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 815bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->center; x++) 8163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 817699ae5b6cbee363e53f58e0fedd414f282d07eddcristy magnitude_pixels[i]=cabs(forward_pixels[i]); 818699ae5b6cbee363e53f58e0fedd414f282d07eddcristy phase_pixels[i]=carg(forward_pixels[i]); 8193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 8203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 8213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy else 822bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 823bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->center; x++) 8243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 825699ae5b6cbee363e53f58e0fedd414f282d07eddcristy magnitude_pixels[i]=creal(forward_pixels[i]); 826699ae5b6cbee363e53f58e0fedd414f282d07eddcristy phase_pixels[i]=cimag(forward_pixels[i]); 8273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 8283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 829699ae5b6cbee363e53f58e0fedd414f282d07eddcristy forward_info=(MemoryInfo *) RelinquishVirtualMemory(forward_info); 8303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickTrue); 8313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 8323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 8333ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType ForwardFourierTransformChannel(const Image *image, 834d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy const PixelChannel channel,const MagickBooleanType modulus, 8353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Image *fourier_image,ExceptionInfo *exception) 8363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 8373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy double 838ce9fe78c6f9452d2bc114f6e4075838313943a82cristy *magnitude_pixels, 839ce9fe78c6f9452d2bc114f6e4075838313943a82cristy *phase_pixels; 840bb3c02e054634545e7595cea2048c07de0407f1acristy 84156ed31cc763800a9fb1f0df96104c354b40d2cbccristy FourierInfo 84256ed31cc763800a9fb1f0df96104c354b40d2cbccristy fourier_info; 84356ed31cc763800a9fb1f0df96104c354b40d2cbccristy 844c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy MagickBooleanType 845c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy status; 846c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy 847ce9fe78c6f9452d2bc114f6e4075838313943a82cristy MemoryInfo 848ce9fe78c6f9452d2bc114f6e4075838313943a82cristy *magnitude_info, 849ce9fe78c6f9452d2bc114f6e4075838313943a82cristy *phase_info; 850ce9fe78c6f9452d2bc114f6e4075838313943a82cristy 8513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fourier_info.width=image->columns; 852740b4f1b3bbfb255bd4bd08132acfd0ee9977ccecristy fourier_info.height=image->rows; 8532e035cd272c0993d28f757f4a913070170095939Cristy fourier_info.center=(ssize_t) (fourier_info.width/2L)+1L; 8543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fourier_info.channel=channel; 8553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fourier_info.modulus=modulus; 8562e035cd272c0993d28f757f4a913070170095939Cristy magnitude_info=AcquireVirtualMemory((size_t) fourier_info.width, 8572e035cd272c0993d28f757f4a913070170095939Cristy (fourier_info.height/2+1)*sizeof(*magnitude_pixels)); 8582e035cd272c0993d28f757f4a913070170095939Cristy phase_info=AcquireVirtualMemory((size_t) fourier_info.width, 8592e035cd272c0993d28f757f4a913070170095939Cristy (fourier_info.height/2+1)*sizeof(*phase_pixels)); 860ce9fe78c6f9452d2bc114f6e4075838313943a82cristy if ((magnitude_info == (MemoryInfo *) NULL) || 861ce9fe78c6f9452d2bc114f6e4075838313943a82cristy (phase_info == (MemoryInfo *) NULL)) 862bb3c02e054634545e7595cea2048c07de0407f1acristy { 863ce9fe78c6f9452d2bc114f6e4075838313943a82cristy if (phase_info != (MemoryInfo *) NULL) 864ce9fe78c6f9452d2bc114f6e4075838313943a82cristy phase_info=RelinquishVirtualMemory(phase_info); 865ce9fe78c6f9452d2bc114f6e4075838313943a82cristy if (magnitude_info == (MemoryInfo *) NULL) 866ce9fe78c6f9452d2bc114f6e4075838313943a82cristy magnitude_info=RelinquishVirtualMemory(magnitude_info); 867bb3c02e054634545e7595cea2048c07de0407f1acristy (void) ThrowMagickException(exception,GetMagickModule(), 868bb3c02e054634545e7595cea2048c07de0407f1acristy ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); 8693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 8703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 871ce9fe78c6f9452d2bc114f6e4075838313943a82cristy magnitude_pixels=(double *) GetVirtualMemoryBlob(magnitude_info); 872ce9fe78c6f9452d2bc114f6e4075838313943a82cristy phase_pixels=(double *) GetVirtualMemoryBlob(phase_info); 873ce9fe78c6f9452d2bc114f6e4075838313943a82cristy status=ForwardFourierTransform(&fourier_info,image,magnitude_pixels, 874ce9fe78c6f9452d2bc114f6e4075838313943a82cristy phase_pixels,exception); 8753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status != MagickFalse) 876ce9fe78c6f9452d2bc114f6e4075838313943a82cristy status=ForwardFourier(&fourier_info,fourier_image,magnitude_pixels, 877ce9fe78c6f9452d2bc114f6e4075838313943a82cristy phase_pixels,exception); 878ce9fe78c6f9452d2bc114f6e4075838313943a82cristy phase_info=RelinquishVirtualMemory(phase_info); 879ce9fe78c6f9452d2bc114f6e4075838313943a82cristy magnitude_info=RelinquishVirtualMemory(magnitude_info); 8803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(status); 8813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 8823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 8833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 8843ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport Image *ForwardFourierTransformImage(const Image *image, 8853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy const MagickBooleanType modulus,ExceptionInfo *exception) 8863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 8873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Image 8883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *fourier_image; 8893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 8903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fourier_image=NewImageList(); 8913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if !defined(MAGICKCORE_FFTW_DELEGATE) 8923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) modulus; 8933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) ThrowMagickException(exception,GetMagickModule(), 8942e035cd272c0993d28f757f4a913070170095939Cristy MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn","`%s' (FFTW)", 8953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy image->filename); 8963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else 8973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 8983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Image 8993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *magnitude_image; 9003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 901bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy size_t 902c9721ffe0e76156deb0d518ec41c0431e1b61922cristy height, 9033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy width; 9043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 9053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy width=image->columns; 906c9721ffe0e76156deb0d518ec41c0431e1b61922cristy height=image->rows; 907c9721ffe0e76156deb0d518ec41c0431e1b61922cristy magnitude_image=CloneImage(image,width,height,MagickTrue,exception); 9083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (magnitude_image != (Image *) NULL) 9093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 9103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Image 9113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *phase_image; 9123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 9133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy magnitude_image->storage_class=DirectClass; 9143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy magnitude_image->depth=32UL; 915c9721ffe0e76156deb0d518ec41c0431e1b61922cristy phase_image=CloneImage(image,width,height,MagickTrue,exception); 9163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (phase_image == (Image *) NULL) 9173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy magnitude_image=DestroyImage(magnitude_image); 9183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy else 9193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 9203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 9213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy is_gray, 9223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status; 9233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 9243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy phase_image->storage_class=DirectClass; 9253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy phase_image->depth=32UL; 9263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy AppendImageToList(&fourier_image,magnitude_image); 9273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy AppendImageToList(&fourier_image,phase_image); 9283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=MagickTrue; 929c6f2ac9fbacb63eb30ab87d80dba97d634742d4bcristy is_gray=IsImageGray(image); 930b5d5f725fef80ff5d50db3111c05a1a521b81e7fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 931564a56979706a30a3d0f920fd5f538a408efd4f1cristy #pragma omp parallel sections 9323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 9333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 934b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 935b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp section 936b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#endif 9373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 938b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy MagickBooleanType 939b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status; 940b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy 941b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (is_gray != MagickFalse) 942b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=ForwardFourierTransformChannel(image, 943d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy GrayPixelChannel,modulus,fourier_image,exception); 944b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy else 945b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=ForwardFourierTransformChannel(image, 946d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy RedPixelChannel,modulus,fourier_image,exception); 947b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (thread_status == MagickFalse) 948b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy status=thread_status; 949b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy } 950b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 951b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp section 952b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#endif 953b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy { 954b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy MagickBooleanType 955b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status; 956b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy 957b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=MagickTrue; 958b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (is_gray == MagickFalse) 959b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=ForwardFourierTransformChannel(image, 960d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy GreenPixelChannel,modulus,fourier_image,exception); 961b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (thread_status == MagickFalse) 962b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy status=thread_status; 963b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy } 964b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 965b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp section 966b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#endif 967b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy { 968b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy MagickBooleanType 969b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status; 970b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy 971b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=MagickTrue; 972b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (is_gray == MagickFalse) 973b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=ForwardFourierTransformChannel(image, 974d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy BluePixelChannel,modulus,fourier_image,exception); 975b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (thread_status == MagickFalse) 976b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy status=thread_status; 977b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy } 978b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 979b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp section 980b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#endif 981b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy { 982b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy MagickBooleanType 983b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status; 984b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy 985b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=MagickTrue; 9864c08aed51c5899665ade97263692328eea4af106cristy if (image->colorspace == CMYKColorspace) 987b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=ForwardFourierTransformChannel(image, 988d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy BlackPixelChannel,modulus,fourier_image,exception); 989b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (thread_status == MagickFalse) 990b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy status=thread_status; 991b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy } 992b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 993b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp section 994b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#endif 995b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy { 996b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy MagickBooleanType 997b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status; 998b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy 999b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=MagickTrue; 100017f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 1001b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=ForwardFourierTransformChannel(image, 1002d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy AlphaPixelChannel,modulus,fourier_image,exception); 1003b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (thread_status == MagickFalse) 1004b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy status=thread_status; 10053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 10063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 10073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status == MagickFalse) 10083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fourier_image=DestroyImageList(fourier_image); 10093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fftw_cleanup(); 10103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 10113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 10123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 10133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 10143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(fourier_image); 10153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 10163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 10173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 10183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 10203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 10213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 10223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% I n v e r s e F o u r i e r T r a n s f o r m I m a g e % 10233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 10243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 10253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 10263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 10283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% InverseFourierTransformImage() implements the inverse discrete Fourier 10293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% transform (DFT) of the image either as a magnitude / phase or real / 10303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% imaginary image pair. 10313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 10323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% The format of the InverseFourierTransformImage method is: 10333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 1034c9550792cd47c57370cd82fef338304f9e576473cristy% Image *InverseFourierTransformImage(const Image *magnitude_image, 1035c9550792cd47c57370cd82fef338304f9e576473cristy% const Image *phase_image,const MagickBooleanType modulus, 1036c9550792cd47c57370cd82fef338304f9e576473cristy% ExceptionInfo *exception) 10373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 10383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% A description of each parameter follows: 10393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 1040c9550792cd47c57370cd82fef338304f9e576473cristy% o magnitude_image: the magnitude or real image. 1041c9550792cd47c57370cd82fef338304f9e576473cristy% 1042c9550792cd47c57370cd82fef338304f9e576473cristy% o phase_image: the phase or imaginary image. 10433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 10443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o modulus: if true, return transform as a magnitude / phase pair 10453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% otherwise a real / imaginary image pair. 10463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 10473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o exception: return any errors or warnings in this structure. 10483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 10493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 10503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 10513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_FFTW_DELEGATE) 1052bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristystatic MagickBooleanType InverseQuadrantSwap(const size_t width, 1053bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy const size_t height,const double *source,double *destination) 10543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 1055c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy register ssize_t 1056c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy x; 1057c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy 1058bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy ssize_t 10593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy center, 10603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy y; 10613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 10623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 10633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Swap quadrants. 10643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 10652e035cd272c0993d28f757f4a913070170095939Cristy center=(ssize_t) (width/2L)+1L; 1066bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=1L; y < (ssize_t) height; y++) 1067bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) (width/2L+1L); x++) 10689b1d6c756cb32746846b038ccb0439db540ba509cristy destination[(height-y)*center-x+width/2L]=source[y*width+x]; 1069bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) height; y++) 10703d04ed7ddc7a93c09476e84cc64412687bf5261acristy destination[y*center]=source[y*width+width/2L]; 10713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy for (x=0L; x < center; x++) 10723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy destination[x]=source[center-x-1L]; 1073bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy return(RollFourier(center,height,0L,(ssize_t) height/-2L,destination)); 10743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 10753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 10763ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType InverseFourier(FourierInfo *fourier_info, 1077699ae5b6cbee363e53f58e0fedd414f282d07eddcristy const Image *magnitude_image,const Image *phase_image, 1078699ae5b6cbee363e53f58e0fedd414f282d07eddcristy fftw_complex *fourier_pixels,ExceptionInfo *exception) 10793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 10803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy CacheView 10813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *magnitude_view, 10823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *phase_view; 10833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 10843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy double 1085699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *inverse_pixels, 10867d4aa38318c20a4309d855f45e3744c9f300f697cristy *magnitude_pixels, 10877d4aa38318c20a4309d855f45e3744c9f300f697cristy *phase_pixels; 10883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 10893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 10903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status; 10913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1092699ae5b6cbee363e53f58e0fedd414f282d07eddcristy MemoryInfo 1093699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *inverse_info, 1094699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *magnitude_info, 1095699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *phase_info; 1096699ae5b6cbee363e53f58e0fedd414f282d07eddcristy 10974c08aed51c5899665ade97263692328eea4af106cristy register const Quantum 10983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *p; 10993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1100bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 11013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i, 11023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy x; 11033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1104c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy ssize_t 1105c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy y; 1106c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy 11073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 11083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Inverse fourier - read image and break down into a double array. 11093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 11102e035cd272c0993d28f757f4a913070170095939Cristy magnitude_info=AcquireVirtualMemory((size_t) fourier_info->width, 11112e035cd272c0993d28f757f4a913070170095939Cristy fourier_info->height*sizeof(*magnitude_pixels)); 11122e035cd272c0993d28f757f4a913070170095939Cristy phase_info=AcquireVirtualMemory((size_t) fourier_info->width, 11132e035cd272c0993d28f757f4a913070170095939Cristy fourier_info->height*sizeof(*phase_pixels)); 11142e035cd272c0993d28f757f4a913070170095939Cristy inverse_info=AcquireVirtualMemory((size_t) fourier_info->width, 11152e035cd272c0993d28f757f4a913070170095939Cristy (fourier_info->height/2+1)*sizeof(*inverse_pixels)); 1116699ae5b6cbee363e53f58e0fedd414f282d07eddcristy if ((magnitude_info == (MemoryInfo *) NULL) || 1117699ae5b6cbee363e53f58e0fedd414f282d07eddcristy (phase_info == (MemoryInfo *) NULL) || 1118699ae5b6cbee363e53f58e0fedd414f282d07eddcristy (inverse_info == (MemoryInfo *) NULL)) 11193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 1120699ae5b6cbee363e53f58e0fedd414f282d07eddcristy if (magnitude_info != (MemoryInfo *) NULL) 1121699ae5b6cbee363e53f58e0fedd414f282d07eddcristy magnitude_info=RelinquishVirtualMemory(magnitude_info); 1122699ae5b6cbee363e53f58e0fedd414f282d07eddcristy if (phase_info != (MemoryInfo *) NULL) 1123699ae5b6cbee363e53f58e0fedd414f282d07eddcristy phase_info=RelinquishVirtualMemory(phase_info); 1124699ae5b6cbee363e53f58e0fedd414f282d07eddcristy if (inverse_info != (MemoryInfo *) NULL) 1125699ae5b6cbee363e53f58e0fedd414f282d07eddcristy inverse_info=RelinquishVirtualMemory(inverse_info); 11263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) ThrowMagickException(exception,GetMagickModule(), 1127efe601ce9ea5ad34ad0e8ad6e61d9be9b148b2a3cristy ResourceLimitError,"MemoryAllocationFailed","`%s'", 1128c9550792cd47c57370cd82fef338304f9e576473cristy magnitude_image->filename); 11293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 11303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1131699ae5b6cbee363e53f58e0fedd414f282d07eddcristy magnitude_pixels=(double *) GetVirtualMemoryBlob(magnitude_info); 1132699ae5b6cbee363e53f58e0fedd414f282d07eddcristy phase_pixels=(double *) GetVirtualMemoryBlob(phase_info); 1133699ae5b6cbee363e53f58e0fedd414f282d07eddcristy inverse_pixels=(double *) GetVirtualMemoryBlob(inverse_info); 11343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 113546ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy magnitude_view=AcquireVirtualCacheView(magnitude_image,exception); 1136bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 11373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 11383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy p=GetCacheViewVirtualPixels(magnitude_view,0L,y,fourier_info->width,1UL, 11393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy exception); 11404c08aed51c5899665ade97263692328eea4af106cristy if (p == (const Quantum *) NULL) 11413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 1142bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->width; x++) 11433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 11443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy switch (fourier_info->channel) 11453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 1146d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case RedPixelChannel: 11473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy default: 11483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 11497d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels[i]=QuantumScale*GetPixelRed(magnitude_image,p); 11503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 11513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1152d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case GreenPixelChannel: 11533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 11547d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels[i]=QuantumScale*GetPixelGreen(magnitude_image,p); 11553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 11563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1157d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case BluePixelChannel: 11583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 11597d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels[i]=QuantumScale*GetPixelBlue(magnitude_image,p); 11603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 11613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1162d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case BlackPixelChannel: 11633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 11647d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels[i]=QuantumScale*GetPixelBlack(magnitude_image,p); 11653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 11663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1167d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case AlphaPixelChannel: 11683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 11697d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels[i]=QuantumScale*GetPixelAlpha(magnitude_image,p); 11703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 11713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 11723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 11733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 1174ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy p+=GetPixelChannels(magnitude_image); 11753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 11763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1177699ae5b6cbee363e53f58e0fedd414f282d07eddcristy magnitude_view=DestroyCacheView(magnitude_view); 1178699ae5b6cbee363e53f58e0fedd414f282d07eddcristy status=InverseQuadrantSwap(fourier_info->width,fourier_info->height, 1179699ae5b6cbee363e53f58e0fedd414f282d07eddcristy magnitude_pixels,inverse_pixels); 1180699ae5b6cbee363e53f58e0fedd414f282d07eddcristy (void) CopyMagickMemory(magnitude_pixels,inverse_pixels,fourier_info->height* 1181699ae5b6cbee363e53f58e0fedd414f282d07eddcristy fourier_info->center*sizeof(*magnitude_pixels)); 11823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 118346ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy phase_view=AcquireVirtualCacheView(phase_image,exception); 1184bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 11853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 11863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy p=GetCacheViewVirtualPixels(phase_view,0,y,fourier_info->width,1, 11873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy exception); 11884c08aed51c5899665ade97263692328eea4af106cristy if (p == (const Quantum *) NULL) 11893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 1190bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->width; x++) 11913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 11923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy switch (fourier_info->channel) 11933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 1194d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case RedPixelChannel: 11953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy default: 11963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 11977d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]=QuantumScale*GetPixelRed(phase_image,p); 11983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 11993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1200d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case GreenPixelChannel: 12013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 12027d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]=QuantumScale*GetPixelGreen(phase_image,p); 12033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 12043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1205d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case BluePixelChannel: 12063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 12077d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]=QuantumScale*GetPixelBlue(phase_image,p); 12083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 12093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1210d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case BlackPixelChannel: 12113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 12127d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]=QuantumScale*GetPixelBlack(phase_image,p); 12133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 12143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1215d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case AlphaPixelChannel: 12163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 12177d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]=QuantumScale*GetPixelAlpha(phase_image,p); 12183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 12193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 12203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 12213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 1222ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy p+=GetPixelChannels(phase_image); 12233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 12243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 12253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (fourier_info->modulus != MagickFalse) 12263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 12273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 1228bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 1229bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->width; x++) 12303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 12317d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]-=0.5; 12327d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]*=(2.0*MagickPI); 12333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 12343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 12353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 12363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy phase_view=DestroyCacheView(phase_view); 123713c99c4243ef58ec6f752aba6df9970ec16c87e6cristy CorrectPhaseLHS(fourier_info->width,fourier_info->height,phase_pixels); 12383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status != MagickFalse) 12393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=InverseQuadrantSwap(fourier_info->width,fourier_info->height, 1240699ae5b6cbee363e53f58e0fedd414f282d07eddcristy phase_pixels,inverse_pixels); 1241699ae5b6cbee363e53f58e0fedd414f282d07eddcristy (void) CopyMagickMemory(phase_pixels,inverse_pixels,fourier_info->height* 1242699ae5b6cbee363e53f58e0fedd414f282d07eddcristy fourier_info->center*sizeof(*phase_pixels)); 1243699ae5b6cbee363e53f58e0fedd414f282d07eddcristy inverse_info=RelinquishVirtualMemory(inverse_info); 12443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 12453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Merge two sets. 12463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 12473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 12483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (fourier_info->modulus != MagickFalse) 1249bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 1250bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->center; x++) 12513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 125256ed31cc763800a9fb1f0df96104c354b40d2cbccristy#if defined(MAGICKCORE_HAVE_COMPLEX_H) 1253699ae5b6cbee363e53f58e0fedd414f282d07eddcristy fourier_pixels[i]=magnitude_pixels[i]*cos(phase_pixels[i])+I* 1254699ae5b6cbee363e53f58e0fedd414f282d07eddcristy magnitude_pixels[i]*sin(phase_pixels[i]); 125556ed31cc763800a9fb1f0df96104c354b40d2cbccristy#else 1256699ae5b6cbee363e53f58e0fedd414f282d07eddcristy fourier_pixels[i][0]=magnitude_pixels[i]*cos(phase_pixels[i]); 1257699ae5b6cbee363e53f58e0fedd414f282d07eddcristy fourier_pixels[i][1]=magnitude_pixels[i]*sin(phase_pixels[i]); 125856ed31cc763800a9fb1f0df96104c354b40d2cbccristy#endif 12593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 12603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 12613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy else 1262bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 1263bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->center; x++) 12643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 126556ed31cc763800a9fb1f0df96104c354b40d2cbccristy#if defined(MAGICKCORE_HAVE_COMPLEX_H) 1266699ae5b6cbee363e53f58e0fedd414f282d07eddcristy fourier_pixels[i]=magnitude_pixels[i]+I*phase_pixels[i]; 126756ed31cc763800a9fb1f0df96104c354b40d2cbccristy#else 1268699ae5b6cbee363e53f58e0fedd414f282d07eddcristy fourier_pixels[i][0]=magnitude_pixels[i]; 1269699ae5b6cbee363e53f58e0fedd414f282d07eddcristy fourier_pixels[i][1]=phase_pixels[i]; 127056ed31cc763800a9fb1f0df96104c354b40d2cbccristy#endif 12713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 12723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1273699ae5b6cbee363e53f58e0fedd414f282d07eddcristy magnitude_info=RelinquishVirtualMemory(magnitude_info); 1274699ae5b6cbee363e53f58e0fedd414f282d07eddcristy phase_info=RelinquishVirtualMemory(phase_info); 12753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(status); 12763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 12773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 12783ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType InverseFourierTransform(FourierInfo *fourier_info, 1279699ae5b6cbee363e53f58e0fedd414f282d07eddcristy fftw_complex *fourier_pixels,Image *image,ExceptionInfo *exception) 12803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 12813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy CacheView 12823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *image_view; 12833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 128499dc036190f292a67801dc4b141898bf18c96b36cristy const char 128599dc036190f292a67801dc4b141898bf18c96b36cristy *value; 128699dc036190f292a67801dc4b141898bf18c96b36cristy 12873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy double 1288699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *source_pixels; 12893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 12903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fftw_plan 12913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fftw_c2r_plan; 12923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1293699ae5b6cbee363e53f58e0fedd414f282d07eddcristy MemoryInfo 1294699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *source_info; 1295699ae5b6cbee363e53f58e0fedd414f282d07eddcristy 12964c08aed51c5899665ade97263692328eea4af106cristy register Quantum 1297c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy *q; 1298c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy 1299bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 13003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i, 13013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy x; 13023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1303c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy ssize_t 1304c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy y; 13053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 13062e035cd272c0993d28f757f4a913070170095939Cristy source_info=AcquireVirtualMemory((size_t) fourier_info->width, 13072e035cd272c0993d28f757f4a913070170095939Cristy fourier_info->height*sizeof(*source_pixels)); 1308699ae5b6cbee363e53f58e0fedd414f282d07eddcristy if (source_info == (MemoryInfo *) NULL) 13093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 13103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) ThrowMagickException(exception,GetMagickModule(), 1311efe601ce9ea5ad34ad0e8ad6e61d9be9b148b2a3cristy ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); 13123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 13133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1314699ae5b6cbee363e53f58e0fedd414f282d07eddcristy source_pixels=(double *) GetVirtualMemoryBlob(source_info); 131599dc036190f292a67801dc4b141898bf18c96b36cristy value=GetImageArtifact(image,"fourier:normalize"); 1316f8ecbfdd4702c1b9dcc8f35870b60d61e6d32d79cristy if (LocaleCompare(value,"inverse") == 0) 131799dc036190f292a67801dc4b141898bf18c96b36cristy { 131899dc036190f292a67801dc4b141898bf18c96b36cristy double 131999dc036190f292a67801dc4b141898bf18c96b36cristy gamma; 132099dc036190f292a67801dc4b141898bf18c96b36cristy 132199dc036190f292a67801dc4b141898bf18c96b36cristy /* 132299dc036190f292a67801dc4b141898bf18c96b36cristy Normalize inverse transform. 132399dc036190f292a67801dc4b141898bf18c96b36cristy */ 132499dc036190f292a67801dc4b141898bf18c96b36cristy i=0L; 132599dc036190f292a67801dc4b141898bf18c96b36cristy gamma=PerceptibleReciprocal((double) fourier_info->width* 132699dc036190f292a67801dc4b141898bf18c96b36cristy fourier_info->height); 132799dc036190f292a67801dc4b141898bf18c96b36cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 132899dc036190f292a67801dc4b141898bf18c96b36cristy for (x=0L; x < (ssize_t) fourier_info->center; x++) 132999dc036190f292a67801dc4b141898bf18c96b36cristy { 133099dc036190f292a67801dc4b141898bf18c96b36cristy#if defined(MAGICKCORE_HAVE_COMPLEX_H) 133199dc036190f292a67801dc4b141898bf18c96b36cristy fourier_pixels[i]*=gamma; 133299dc036190f292a67801dc4b141898bf18c96b36cristy#else 133399dc036190f292a67801dc4b141898bf18c96b36cristy fourier_pixels[i][0]*=gamma; 133499dc036190f292a67801dc4b141898bf18c96b36cristy fourier_pixels[i][1]*=gamma; 133599dc036190f292a67801dc4b141898bf18c96b36cristy#endif 133699dc036190f292a67801dc4b141898bf18c96b36cristy i++; 133799dc036190f292a67801dc4b141898bf18c96b36cristy } 133899dc036190f292a67801dc4b141898bf18c96b36cristy } 1339b5d5f725fef80ff5d50db3111c05a1a521b81e7fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 13403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy #pragma omp critical (MagickCore_InverseFourierTransform) 13413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 1342bbc9a95a7875c8c9b4a8e0b87491aa52e56ec849Cristy fftw_c2r_plan=fftw_plan_dft_c2r_2d(fourier_info->width,fourier_info->height, 1343bbc9a95a7875c8c9b4a8e0b87491aa52e56ec849Cristy fourier_pixels,source_pixels,FFTW_ESTIMATE); 1344bbc9a95a7875c8c9b4a8e0b87491aa52e56ec849Cristy fftw_execute_dft_c2r(fftw_c2r_plan,fourier_pixels,source_pixels); 1345bbc9a95a7875c8c9b4a8e0b87491aa52e56ec849Cristy fftw_destroy_plan(fftw_c2r_plan); 13463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 134746ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy image_view=AcquireAuthenticCacheView(image,exception); 1348bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 13493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 135085812051623aa663ad40386ebfc4b8d0ca87bd55cristy if (y >= (ssize_t) image->rows) 135185812051623aa663ad40386ebfc4b8d0ca87bd55cristy break; 135285812051623aa663ad40386ebfc4b8d0ca87bd55cristy q=GetCacheViewAuthenticPixels(image_view,0L,y,fourier_info->width > 135385812051623aa663ad40386ebfc4b8d0ca87bd55cristy image->columns ? image->columns : fourier_info->width,1UL,exception); 1354acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy if (q == (Quantum *) NULL) 13553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 1356bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->width; x++) 13573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 1358233fe5816db8ff3930e64adebd232757d8d2c06ecristy if (x < (ssize_t) image->columns) 1359233fe5816db8ff3930e64adebd232757d8d2c06ecristy switch (fourier_info->channel) 13603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 1361233fe5816db8ff3930e64adebd232757d8d2c06ecristy case RedPixelChannel: 1362233fe5816db8ff3930e64adebd232757d8d2c06ecristy default: 1363233fe5816db8ff3930e64adebd232757d8d2c06ecristy { 1364699ae5b6cbee363e53f58e0fedd414f282d07eddcristy SetPixelRed(image,ClampToQuantum(QuantumRange*source_pixels[i]),q); 1365233fe5816db8ff3930e64adebd232757d8d2c06ecristy break; 1366233fe5816db8ff3930e64adebd232757d8d2c06ecristy } 1367233fe5816db8ff3930e64adebd232757d8d2c06ecristy case GreenPixelChannel: 1368233fe5816db8ff3930e64adebd232757d8d2c06ecristy { 1369699ae5b6cbee363e53f58e0fedd414f282d07eddcristy SetPixelGreen(image,ClampToQuantum(QuantumRange*source_pixels[i]), 1370699ae5b6cbee363e53f58e0fedd414f282d07eddcristy q); 1371233fe5816db8ff3930e64adebd232757d8d2c06ecristy break; 1372233fe5816db8ff3930e64adebd232757d8d2c06ecristy } 1373233fe5816db8ff3930e64adebd232757d8d2c06ecristy case BluePixelChannel: 1374233fe5816db8ff3930e64adebd232757d8d2c06ecristy { 1375699ae5b6cbee363e53f58e0fedd414f282d07eddcristy SetPixelBlue(image,ClampToQuantum(QuantumRange*source_pixels[i]), 1376699ae5b6cbee363e53f58e0fedd414f282d07eddcristy q); 1377233fe5816db8ff3930e64adebd232757d8d2c06ecristy break; 1378233fe5816db8ff3930e64adebd232757d8d2c06ecristy } 1379233fe5816db8ff3930e64adebd232757d8d2c06ecristy case BlackPixelChannel: 1380233fe5816db8ff3930e64adebd232757d8d2c06ecristy { 1381699ae5b6cbee363e53f58e0fedd414f282d07eddcristy SetPixelBlack(image,ClampToQuantum(QuantumRange*source_pixels[i]), 1382699ae5b6cbee363e53f58e0fedd414f282d07eddcristy q); 1383233fe5816db8ff3930e64adebd232757d8d2c06ecristy break; 1384233fe5816db8ff3930e64adebd232757d8d2c06ecristy } 1385233fe5816db8ff3930e64adebd232757d8d2c06ecristy case AlphaPixelChannel: 1386233fe5816db8ff3930e64adebd232757d8d2c06ecristy { 1387699ae5b6cbee363e53f58e0fedd414f282d07eddcristy SetPixelAlpha(image,ClampToQuantum(QuantumRange*source_pixels[i]), 1388699ae5b6cbee363e53f58e0fedd414f282d07eddcristy q); 1389233fe5816db8ff3930e64adebd232757d8d2c06ecristy break; 1390233fe5816db8ff3930e64adebd232757d8d2c06ecristy } 13913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 13923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 1393ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy q+=GetPixelChannels(image); 13943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 13953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 13963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 13973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 13983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy image_view=DestroyCacheView(image_view); 1399699ae5b6cbee363e53f58e0fedd414f282d07eddcristy source_info=RelinquishVirtualMemory(source_info); 14003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickTrue); 14013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 14023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1403c9550792cd47c57370cd82fef338304f9e576473cristystatic MagickBooleanType InverseFourierTransformChannel( 1404c9550792cd47c57370cd82fef338304f9e576473cristy const Image *magnitude_image,const Image *phase_image, 1405d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy const PixelChannel channel,const MagickBooleanType modulus, 14063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Image *fourier_image,ExceptionInfo *exception) 14073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 14083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fftw_complex 1409699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *inverse_pixels; 14103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 14113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy FourierInfo 14123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fourier_info; 14133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 14143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 14153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status; 14163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1417699ae5b6cbee363e53f58e0fedd414f282d07eddcristy MemoryInfo 1418699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *inverse_info; 1419699ae5b6cbee363e53f58e0fedd414f282d07eddcristy 1420c9550792cd47c57370cd82fef338304f9e576473cristy fourier_info.width=magnitude_image->columns; 14210a69e6429fff81c8de551ed10e358df7b0b2a585cristy fourier_info.height=magnitude_image->rows; 14222e035cd272c0993d28f757f4a913070170095939Cristy fourier_info.center=(ssize_t) (fourier_info.width/2L)+1L; 14233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fourier_info.channel=channel; 14243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fourier_info.modulus=modulus; 14252e035cd272c0993d28f757f4a913070170095939Cristy inverse_info=AcquireVirtualMemory((size_t) fourier_info.width, 14262e035cd272c0993d28f757f4a913070170095939Cristy (fourier_info.height/2+1)*sizeof(*inverse_pixels)); 1427699ae5b6cbee363e53f58e0fedd414f282d07eddcristy if (inverse_info == (MemoryInfo *) NULL) 14283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 14293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) ThrowMagickException(exception,GetMagickModule(), 1430efe601ce9ea5ad34ad0e8ad6e61d9be9b148b2a3cristy ResourceLimitError,"MemoryAllocationFailed","`%s'", 1431c9550792cd47c57370cd82fef338304f9e576473cristy magnitude_image->filename); 14323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 14333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1434699ae5b6cbee363e53f58e0fedd414f282d07eddcristy inverse_pixels=(fftw_complex *) GetVirtualMemoryBlob(inverse_info); 1435699ae5b6cbee363e53f58e0fedd414f282d07eddcristy status=InverseFourier(&fourier_info,magnitude_image,phase_image, 1436699ae5b6cbee363e53f58e0fedd414f282d07eddcristy inverse_pixels,exception); 14373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status != MagickFalse) 1438699ae5b6cbee363e53f58e0fedd414f282d07eddcristy status=InverseFourierTransform(&fourier_info,inverse_pixels,fourier_image, 14393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy exception); 1440699ae5b6cbee363e53f58e0fedd414f282d07eddcristy inverse_info=RelinquishVirtualMemory(inverse_info); 14413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(status); 14423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 14433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 14443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1445c9550792cd47c57370cd82fef338304f9e576473cristyMagickExport Image *InverseFourierTransformImage(const Image *magnitude_image, 1446c9550792cd47c57370cd82fef338304f9e576473cristy const Image *phase_image,const MagickBooleanType modulus, 1447c9550792cd47c57370cd82fef338304f9e576473cristy ExceptionInfo *exception) 14483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 14493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Image 14503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *fourier_image; 14513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1452c9550792cd47c57370cd82fef338304f9e576473cristy assert(magnitude_image != (Image *) NULL); 1453e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy assert(magnitude_image->signature == MagickCoreSignature); 1454c9550792cd47c57370cd82fef338304f9e576473cristy if (magnitude_image->debug != MagickFalse) 1455c9550792cd47c57370cd82fef338304f9e576473cristy (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 1456c9550792cd47c57370cd82fef338304f9e576473cristy magnitude_image->filename); 1457c9550792cd47c57370cd82fef338304f9e576473cristy if (phase_image == (Image *) NULL) 1458c9550792cd47c57370cd82fef338304f9e576473cristy { 1459c9550792cd47c57370cd82fef338304f9e576473cristy (void) ThrowMagickException(exception,GetMagickModule(),ImageError, 14602e035cd272c0993d28f757f4a913070170095939Cristy "ImageSequenceRequired","`%s'",magnitude_image->filename); 14619372a158e662d81ce4df26249238df39d66102ffcristy return((Image *) NULL); 1462c9550792cd47c57370cd82fef338304f9e576473cristy } 14633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if !defined(MAGICKCORE_FFTW_DELEGATE) 14643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fourier_image=(Image *) NULL; 14653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) modulus; 14663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) ThrowMagickException(exception,GetMagickModule(), 14672e035cd272c0993d28f757f4a913070170095939Cristy MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn","`%s' (FFTW)", 1468c9550792cd47c57370cd82fef338304f9e576473cristy magnitude_image->filename); 14693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else 14703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 1471c9550792cd47c57370cd82fef338304f9e576473cristy fourier_image=CloneImage(magnitude_image,magnitude_image->columns, 14724c9c4d0c413e922bc941efc7657a5c075a944c1fcristy magnitude_image->rows,MagickTrue,exception); 14733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (fourier_image != (Image *) NULL) 14743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 14753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 14763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy is_gray, 14773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status; 14783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 14793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=MagickTrue; 1480c6f2ac9fbacb63eb30ab87d80dba97d634742d4bcristy is_gray=IsImageGray(magnitude_image); 1481c9550792cd47c57370cd82fef338304f9e576473cristy if (is_gray != MagickFalse) 1482c6f2ac9fbacb63eb30ab87d80dba97d634742d4bcristy is_gray=IsImageGray(phase_image); 1483b5d5f725fef80ff5d50db3111c05a1a521b81e7fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 1484b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp parallel sections 14853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 14863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 1487b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 1488b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp section 1489b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#endif 14903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 1491b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy MagickBooleanType 1492b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status; 1493b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy 1494b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (is_gray != MagickFalse) 1495b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=InverseFourierTransformChannel(magnitude_image, 1496d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy phase_image,GrayPixelChannel,modulus,fourier_image,exception); 1497b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy else 1498c9550792cd47c57370cd82fef338304f9e576473cristy thread_status=InverseFourierTransformChannel(magnitude_image, 1499d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy phase_image,RedPixelChannel,modulus,fourier_image,exception); 1500b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (thread_status == MagickFalse) 1501b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy status=thread_status; 1502b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy } 1503b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 1504b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp section 1505b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#endif 1506b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy { 1507b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy MagickBooleanType 1508b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status; 1509b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy 1510b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=MagickTrue; 1511b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (is_gray == MagickFalse) 1512b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=InverseFourierTransformChannel(magnitude_image, 1513d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy phase_image,GreenPixelChannel,modulus,fourier_image,exception); 1514b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (thread_status == MagickFalse) 1515b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy status=thread_status; 1516b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy } 1517b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 1518b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp section 1519b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#endif 1520b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy { 1521b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy MagickBooleanType 1522b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status; 1523b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy 1524b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=MagickTrue; 1525b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (is_gray == MagickFalse) 1526b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=InverseFourierTransformChannel(magnitude_image, 1527d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy phase_image,BluePixelChannel,modulus,fourier_image,exception); 1528b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (thread_status == MagickFalse) 1529b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy status=thread_status; 1530b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy } 1531b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 1532b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp section 1533b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#endif 1534b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy { 1535b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy MagickBooleanType 1536b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status; 1537b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy 1538b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=MagickTrue; 15394c08aed51c5899665ade97263692328eea4af106cristy if (magnitude_image->colorspace == CMYKColorspace) 1540b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=InverseFourierTransformChannel(magnitude_image, 1541d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy phase_image,BlackPixelChannel,modulus,fourier_image,exception); 1542b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (thread_status == MagickFalse) 1543b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy status=thread_status; 1544b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy } 1545b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 1546b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp section 1547b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#endif 1548b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy { 1549b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy MagickBooleanType 1550b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status; 1551b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy 1552b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=MagickTrue; 155317f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (magnitude_image->alpha_trait != UndefinedPixelTrait) 1554b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=InverseFourierTransformChannel(magnitude_image, 1555d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy phase_image,AlphaPixelChannel,modulus,fourier_image,exception); 1556b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (thread_status == MagickFalse) 1557b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy status=thread_status; 15583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 15593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 15603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status == MagickFalse) 15613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fourier_image=DestroyImage(fourier_image); 15623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1563b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy fftw_cleanup(); 15643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 15653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 15663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(fourier_image); 15673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 1568