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); 2001042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy /* 2011042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Apply complex mathematics to image pixels. 2021042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy */ 20334b78eacf3bef963cade67c70f5f12785b9fe702cristy artifact=GetImageArtifact(image,"complex:snr"); 20434b78eacf3bef963cade67c70f5f12785b9fe702cristy snr=0.0; 20534b78eacf3bef963cade67c70f5f12785b9fe702cristy if (artifact != (const char *) NULL) 20634b78eacf3bef963cade67c70f5f12785b9fe702cristy snr=StringToDouble(artifact,(char **) NULL); 2071042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Ar_image=images; 2081042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Ai_image=images->next; 2098dc6a07d751896a7c400a6d888a5964c538fad2dcristy Br_image=images; 2108dc6a07d751896a7c400a6d888a5964c538fad2dcristy Bi_image=images->next; 2118dc6a07d751896a7c400a6d888a5964c538fad2dcristy if ((images->next->next != (Image *) NULL) && 2128dc6a07d751896a7c400a6d888a5964c538fad2dcristy (images->next->next->next != (Image *) NULL)) 2131042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy { 2141042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Br_image=images->next->next; 2151042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Bi_image=images->next->next->next; 2161042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy } 2171042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Cr_image=complex_images; 2181042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Ci_image=complex_images->next; 2191042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Ar_view=AcquireVirtualCacheView(Ar_image,exception); 2201042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Ai_view=AcquireVirtualCacheView(Ai_image,exception); 2211042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Br_view=AcquireVirtualCacheView(Br_image,exception); 2221042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Bi_view=AcquireVirtualCacheView(Bi_image,exception); 2231042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Cr_view=AcquireAuthenticCacheView(Cr_image,exception); 2241042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Ci_view=AcquireAuthenticCacheView(Ci_image,exception); 2251042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy status=MagickTrue; 2261042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy progress=0; 2271042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 2284167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy #pragma omp parallel for schedule(static,4) shared(progress,status) \ 2294167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy magick_threads(images,complex_images,images->rows,1L) 2301042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy#endif 2311042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy for (y=0; y < (ssize_t) images->rows; y++) 2321042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy { 2331042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy register const Quantum 23405d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict Ai, 23505d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict Ar, 23605d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict Bi, 23705d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict Br; 2381042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy 2391042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy register Quantum 24005d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict Ci, 24105d2ff7ebf21f659f5b11e45afb294e152f4330cdirk *magick_restrict Cr; 2421042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy 2431042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy register ssize_t 2441042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy x; 2451042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy 24634919ed07da683cc334cd74e3c9d9c29c8b79b98cristy if (status == MagickFalse) 24734919ed07da683cc334cd74e3c9d9c29c8b79b98cristy continue; 2484167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Ar=GetCacheViewVirtualPixels(Ar_view,0,y,Ar_image->columns,1,exception); 2494167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Ai=GetCacheViewVirtualPixels(Ai_view,0,y,Ai_image->columns,1,exception); 2504167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Br=GetCacheViewVirtualPixels(Br_view,0,y,Br_image->columns,1,exception); 2514167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Bi=GetCacheViewVirtualPixels(Bi_view,0,y,Bi_image->columns,1,exception); 2524167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Cr=QueueCacheViewAuthenticPixels(Cr_view,0,y,Cr_image->columns,1,exception); 2534167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Ci=QueueCacheViewAuthenticPixels(Ci_view,0,y,Ci_image->columns,1,exception); 2541042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy if ((Ar == (const Quantum *) NULL) || (Ai == (const Quantum *) NULL) || 2551042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy (Br == (const Quantum *) NULL) || (Bi == (const Quantum *) NULL) || 2561042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy (Cr == (Quantum *) NULL) || (Ci == (Quantum *) NULL)) 2571042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy { 2581042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy status=MagickFalse; 2591042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy continue; 2601042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy } 2611042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy for (x=0; x < (ssize_t) images->columns; x++) 2621042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy { 2639f654472e80883bb7c4ec299036733e0e23570d7cristy register ssize_t 2649f654472e80883bb7c4ec299036733e0e23570d7cristy i; 2659f654472e80883bb7c4ec299036733e0e23570d7cristy 2669f654472e80883bb7c4ec299036733e0e23570d7cristy for (i=0; i < (ssize_t) GetPixelChannels(images); i++) 2679f654472e80883bb7c4ec299036733e0e23570d7cristy { 268220c4d505bfb9cf557e8ec1616d7cdc0596379b8cristy switch (op) 2699f654472e80883bb7c4ec299036733e0e23570d7cristy { 27019f7886e4423cd5ce3eef31092942f55ba770983cristy case AddComplexOperator: 27119f7886e4423cd5ce3eef31092942f55ba770983cristy { 27219f7886e4423cd5ce3eef31092942f55ba770983cristy Cr[i]=Ar[i]+Br[i]; 27319f7886e4423cd5ce3eef31092942f55ba770983cristy Ci[i]=Ai[i]+Bi[i]; 27419f7886e4423cd5ce3eef31092942f55ba770983cristy break; 27519f7886e4423cd5ce3eef31092942f55ba770983cristy } 2769f654472e80883bb7c4ec299036733e0e23570d7cristy case ConjugateComplexOperator: 2779f654472e80883bb7c4ec299036733e0e23570d7cristy default: 2789f654472e80883bb7c4ec299036733e0e23570d7cristy { 2799f654472e80883bb7c4ec299036733e0e23570d7cristy Cr[i]=Ar[i]; 2809f654472e80883bb7c4ec299036733e0e23570d7cristy Ci[i]=(-Bi[i]); 2819f654472e80883bb7c4ec299036733e0e23570d7cristy break; 2829f654472e80883bb7c4ec299036733e0e23570d7cristy } 2839f654472e80883bb7c4ec299036733e0e23570d7cristy case DivideComplexOperator: 2849f654472e80883bb7c4ec299036733e0e23570d7cristy { 2859f654472e80883bb7c4ec299036733e0e23570d7cristy double 2869f654472e80883bb7c4ec299036733e0e23570d7cristy gamma; 2879f654472e80883bb7c4ec299036733e0e23570d7cristy 28834b78eacf3bef963cade67c70f5f12785b9fe702cristy gamma=PerceptibleReciprocal(Br[i]*Br[i]+Bi[i]*Bi[i]+snr); 2899f654472e80883bb7c4ec299036733e0e23570d7cristy Cr[i]=gamma*(Ar[i]*Br[i]+Ai[i]*Bi[i]); 290857c8a100c50bd902586a902c27fccab271dce1dcristy Ci[i]=gamma*(Ai[i]*Br[i]-Ar[i]*Bi[i]); 2919f654472e80883bb7c4ec299036733e0e23570d7cristy break; 2929f654472e80883bb7c4ec299036733e0e23570d7cristy } 293f46941ca310386db5b9939840c884c6f8a5c7189cristy case MagnitudePhaseComplexOperator: 294f46941ca310386db5b9939840c884c6f8a5c7189cristy { 2958526a9763e0671ebad481fd00679fb857ce8d84acristy Cr[i]=sqrt(Ar[i]*Ar[i]+Ai[i]*Ai[i]); 2964ab069406391dd3d34359d17a6ab7333f7200729cristy Ci[i]=atan2(Ai[i],Ar[i])/(2.0*MagickPI)+0.5; 297f46941ca310386db5b9939840c884c6f8a5c7189cristy break; 298f46941ca310386db5b9939840c884c6f8a5c7189cristy } 2999f654472e80883bb7c4ec299036733e0e23570d7cristy case MultiplyComplexOperator: 3009f654472e80883bb7c4ec299036733e0e23570d7cristy { 30115b07b3f81434e5cee2ed16d51ec3f504949d992cristy Cr[i]=QuantumScale*(Ar[i]*Br[i]-Ai[i]*Bi[i]); 30215b07b3f81434e5cee2ed16d51ec3f504949d992cristy Ci[i]=QuantumScale*(Ai[i]*Br[i]+Ar[i]*Bi[i]); 303f46941ca310386db5b9939840c884c6f8a5c7189cristy break; 304f46941ca310386db5b9939840c884c6f8a5c7189cristy } 305f46941ca310386db5b9939840c884c6f8a5c7189cristy case RealImaginaryComplexOperator: 306f46941ca310386db5b9939840c884c6f8a5c7189cristy { 3074ab069406391dd3d34359d17a6ab7333f7200729cristy Cr[i]=Ar[i]*cos(2.0*MagickPI*(Ai[i]-0.5)); 3084ab069406391dd3d34359d17a6ab7333f7200729cristy Ci[i]=Ar[i]*sin(2.0*MagickPI*(Ai[i]-0.5)); 3099f654472e80883bb7c4ec299036733e0e23570d7cristy break; 3109f654472e80883bb7c4ec299036733e0e23570d7cristy } 31119f7886e4423cd5ce3eef31092942f55ba770983cristy case SubtractComplexOperator: 31219f7886e4423cd5ce3eef31092942f55ba770983cristy { 31319f7886e4423cd5ce3eef31092942f55ba770983cristy Cr[i]=Ar[i]-Br[i]; 31419f7886e4423cd5ce3eef31092942f55ba770983cristy Ci[i]=Ai[i]-Bi[i]; 31519f7886e4423cd5ce3eef31092942f55ba770983cristy break; 31619f7886e4423cd5ce3eef31092942f55ba770983cristy } 3179f654472e80883bb7c4ec299036733e0e23570d7cristy } 3189f654472e80883bb7c4ec299036733e0e23570d7cristy } 3194167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Ar+=GetPixelChannels(Ar_image); 3204167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Ai+=GetPixelChannels(Ai_image); 3214167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Br+=GetPixelChannels(Br_image); 3224167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Bi+=GetPixelChannels(Bi_image); 3234167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Cr+=GetPixelChannels(Cr_image); 3244167f3a934b7c75a501ac7b4f1ceaf3e1bb192fdcristy Ci+=GetPixelChannels(Ci_image); 3251042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy } 3261042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy if (SyncCacheViewAuthenticPixels(Ci_view,exception) == MagickFalse) 3271042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy status=MagickFalse; 3281042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy if (SyncCacheViewAuthenticPixels(Cr_view,exception) == MagickFalse) 3291042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy status=MagickFalse; 3301042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy if (images->progress_monitor != (MagickProgressMonitor) NULL) 3311042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy { 3321042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy MagickBooleanType 3331042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy proceed; 3341042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy 3351042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 3361042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy #pragma omp critical (MagickCore_ComplexImages) 3371042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy#endif 3381042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy proceed=SetImageProgress(images,ComplexImageTag,progress++, 3391042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy images->rows); 3401042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy if (proceed == MagickFalse) 3411042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy status=MagickFalse; 3421042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy } 3431042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy } 3441042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Cr_view=DestroyCacheView(Cr_view); 3451042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Ci_view=DestroyCacheView(Ci_view); 3461042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Br_view=DestroyCacheView(Br_view); 3471042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Bi_view=DestroyCacheView(Bi_view); 3481042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Ar_view=DestroyCacheView(Ar_view); 3491042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy Ai_view=DestroyCacheView(Ai_view); 3501042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy if (status == MagickFalse) 3511042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy complex_images=DestroyImageList(complex_images); 3521042ed2a43b6a660a6f6dd803e1ee79897da4c3fcristy return(complex_images); 353790190d9d1e6f011220d0003ce5b51063f0ab417cristy} 354790190d9d1e6f011220d0003ce5b51063f0ab417cristy 355790190d9d1e6f011220d0003ce5b51063f0ab417cristy/* 356790190d9d1e6f011220d0003ce5b51063f0ab417cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 357790190d9d1e6f011220d0003ce5b51063f0ab417cristy% % 358790190d9d1e6f011220d0003ce5b51063f0ab417cristy% % 3593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 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 % 3613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 3643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% ForwardFourierTransformImage() implements the discrete Fourier transform 3673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% (DFT) of the image either as a magnitude / phase or real / imaginary image 3683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% pair. 3693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% The format of the ForwadFourierTransformImage method is: 3713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% Image *ForwardFourierTransformImage(const Image *image, 3733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% const MagickBooleanType modulus,ExceptionInfo *exception) 3743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% A description of each parameter follows: 3763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o image: the image. 3783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o modulus: if true, return as transform as a magnitude / phase pair 3803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% otherwise a real / imaginary image pair. 3813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o exception: return any errors or warnings in this structure. 3833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 3843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 3853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 3863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_FFTW_DELEGATE) 3873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 388c4ea4a479c90f81168aa2b99e7680c7b0459d415cristystatic MagickBooleanType RollFourier(const size_t width,const size_t height, 389699ae5b6cbee363e53f58e0fedd414f282d07eddcristy const ssize_t x_offset,const ssize_t y_offset,double *roll_pixels) 3903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 3913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy double 392699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *source_pixels; 3933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 3947d4aa38318c20a4309d855f45e3744c9f300f697cristy MemoryInfo 395699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *source_info; 3967d4aa38318c20a4309d855f45e3744c9f300f697cristy 397c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy register ssize_t 398c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy i, 399c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy x; 400c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy 401bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy ssize_t 4023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy u, 4033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy v, 4043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy y; 4053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 4063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 4072da0535a82cc655e5a48deac466bd6fcef1f4924cristy Move zero frequency (DC, average color) from (0,0) to (width/2,height/2). 4083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 4092e035cd272c0993d28f757f4a913070170095939Cristy source_info=AcquireVirtualMemory(width,height*sizeof(*source_pixels)); 410699ae5b6cbee363e53f58e0fedd414f282d07eddcristy if (source_info == (MemoryInfo *) NULL) 4113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 412699ae5b6cbee363e53f58e0fedd414f282d07eddcristy source_pixels=(double *) GetVirtualMemoryBlob(source_info); 4133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 414bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) height; y++) 4153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 4163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (y_offset < 0L) 417bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy v=((y+y_offset) < 0L) ? y+y_offset+(ssize_t) height : y+y_offset; 4183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy else 419bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy v=((y+y_offset) > ((ssize_t) height-1L)) ? y+y_offset-(ssize_t) height : 4203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy y+y_offset; 421bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) width; x++) 4223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 4233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (x_offset < 0L) 424bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy u=((x+x_offset) < 0L) ? x+x_offset+(ssize_t) width : x+x_offset; 4253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy else 426bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy u=((x+x_offset) > ((ssize_t) width-1L)) ? x+x_offset-(ssize_t) width : 4273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy x+x_offset; 428699ae5b6cbee363e53f58e0fedd414f282d07eddcristy source_pixels[v*width+u]=roll_pixels[i++]; 429c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy } 4303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 431699ae5b6cbee363e53f58e0fedd414f282d07eddcristy (void) CopyMagickMemory(roll_pixels,source_pixels,height*width* 432699ae5b6cbee363e53f58e0fedd414f282d07eddcristy sizeof(*source_pixels)); 433699ae5b6cbee363e53f58e0fedd414f282d07eddcristy source_info=RelinquishVirtualMemory(source_info); 4343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickTrue); 4353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 4363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 437bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristystatic MagickBooleanType ForwardQuadrantSwap(const size_t width, 438699ae5b6cbee363e53f58e0fedd414f282d07eddcristy const size_t height,double *source_pixels,double *forward_pixels) 4393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 4403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 4413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status; 4423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 443bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 4443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy x; 4453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 446c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy ssize_t 447c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy center, 448c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy y; 449c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy 4503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 4513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Swap quadrants. 4523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 4532e035cd272c0993d28f757f4a913070170095939Cristy center=(ssize_t) (width/2L)+1L; 454699ae5b6cbee363e53f58e0fedd414f282d07eddcristy status=RollFourier((size_t) center,height,0L,(ssize_t) height/2L, 455699ae5b6cbee363e53f58e0fedd414f282d07eddcristy source_pixels); 4563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status == MagickFalse) 4573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 458bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) height; y++) 4596831e2f47f00e8b78275319e4aec01d120a3876fCristy for (x=0L; x < (ssize_t) (width/2L); x++) 4603d04ed7ddc7a93c09476e84cc64412687bf5261acristy forward_pixels[y*width+x+width/2L]=source_pixels[y*center+x]; 461bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=1; y < (ssize_t) height; y++) 4626831e2f47f00e8b78275319e4aec01d120a3876fCristy for (x=0L; x < (ssize_t) (width/2L); x++) 4639b1d6c756cb32746846b038ccb0439db540ba509cristy forward_pixels[(height-y)*width+width/2L-x-1L]= 4643d04ed7ddc7a93c09476e84cc64412687bf5261acristy source_pixels[y*center+x+1L]; 465bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) (width/2L); x++) 4666831e2f47f00e8b78275319e4aec01d120a3876fCristy forward_pixels[width/2L-x-1L]=source_pixels[x+1L]; 4673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickTrue); 4683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 4693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 470c4ea4a479c90f81168aa2b99e7680c7b0459d415cristystatic void CorrectPhaseLHS(const size_t width,const size_t height, 471699ae5b6cbee363e53f58e0fedd414f282d07eddcristy double *fourier_pixels) 4723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 473bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 4743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy x; 4753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 4769d314ff2c17a77996c05413c2013880387e50f0ecristy ssize_t 4779d314ff2c17a77996c05413c2013880387e50f0ecristy y; 4789d314ff2c17a77996c05413c2013880387e50f0ecristy 479bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) height; y++) 480bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) (width/2L); x++) 481699ae5b6cbee363e53f58e0fedd414f282d07eddcristy fourier_pixels[y*width+x]*=(-1.0); 4823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 4833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 4843ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType ForwardFourier(const FourierInfo *fourier_info, 4853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Image *image,double *magnitude,double *phase,ExceptionInfo *exception) 4863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 4873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy CacheView 4883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *magnitude_view, 4893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *phase_view; 4903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 4913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy double 4927d4aa38318c20a4309d855f45e3744c9f300f697cristy *magnitude_pixels, 4937d4aa38318c20a4309d855f45e3744c9f300f697cristy *phase_pixels; 4943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 4953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Image 4963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *magnitude_image, 4973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *phase_image; 4983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 4993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 5003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status; 5013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 5027d4aa38318c20a4309d855f45e3744c9f300f697cristy MemoryInfo 5037d4aa38318c20a4309d855f45e3744c9f300f697cristy *magnitude_info, 5047d4aa38318c20a4309d855f45e3744c9f300f697cristy *phase_info; 5057d4aa38318c20a4309d855f45e3744c9f300f697cristy 5064c08aed51c5899665ade97263692328eea4af106cristy register Quantum 5073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *q; 5083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 509f5742794873c63f8b052150a2f44015e1ad55356cristy register ssize_t 510f5742794873c63f8b052150a2f44015e1ad55356cristy x; 511f5742794873c63f8b052150a2f44015e1ad55356cristy 512c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy ssize_t 513c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy i, 514c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy y; 515c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy 5163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy magnitude_image=GetFirstImageInList(image); 5173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy phase_image=GetNextImageInList(image); 5183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (phase_image == (Image *) NULL) 5193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 5203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) ThrowMagickException(exception,GetMagickModule(),ImageError, 5212e035cd272c0993d28f757f4a913070170095939Cristy "ImageSequenceRequired","`%s'",image->filename); 5223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 5233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 5243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 5253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Create "Fourier Transform" image from constituent arrays. 5263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 5272e035cd272c0993d28f757f4a913070170095939Cristy magnitude_info=AcquireVirtualMemory((size_t) fourier_info->width, 5282e035cd272c0993d28f757f4a913070170095939Cristy fourier_info->height*sizeof(*magnitude_pixels)); 5292e035cd272c0993d28f757f4a913070170095939Cristy phase_info=AcquireVirtualMemory((size_t) fourier_info->width, 5302e035cd272c0993d28f757f4a913070170095939Cristy fourier_info->height*sizeof(*phase_pixels)); 531bb3c02e054634545e7595cea2048c07de0407f1acristy if ((magnitude_info == (MemoryInfo *) NULL) || 532bb3c02e054634545e7595cea2048c07de0407f1acristy (phase_info == (MemoryInfo *) NULL)) 5333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 5347d4aa38318c20a4309d855f45e3744c9f300f697cristy if (phase_info != (MemoryInfo *) NULL) 5357d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_info=RelinquishVirtualMemory(phase_info); 5367d4aa38318c20a4309d855f45e3744c9f300f697cristy if (magnitude_info != (MemoryInfo *) NULL) 5377d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_info=RelinquishVirtualMemory(magnitude_info); 5383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) ThrowMagickException(exception,GetMagickModule(), 539efe601ce9ea5ad34ad0e8ad6e61d9be9b148b2a3cristy ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); 5403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 5413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 5427d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels=(double *) GetVirtualMemoryBlob(magnitude_info); 5432a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy (void) ResetMagickMemory(magnitude_pixels,0,fourier_info->width* 5442a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy fourier_info->height*sizeof(*magnitude_pixels)); 545bb3c02e054634545e7595cea2048c07de0407f1acristy phase_pixels=(double *) GetVirtualMemoryBlob(phase_info); 5462a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy (void) ResetMagickMemory(phase_pixels,0,fourier_info->width* 5472a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy fourier_info->height*sizeof(*phase_pixels)); 54813c99c4243ef58ec6f752aba6df9970ec16c87e6cristy status=ForwardQuadrantSwap(fourier_info->width,fourier_info->height, 5497d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude,magnitude_pixels); 5503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status != MagickFalse) 55113c99c4243ef58ec6f752aba6df9970ec16c87e6cristy status=ForwardQuadrantSwap(fourier_info->width,fourier_info->height,phase, 5527d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels); 55313c99c4243ef58ec6f752aba6df9970ec16c87e6cristy CorrectPhaseLHS(fourier_info->width,fourier_info->height,phase_pixels); 5543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (fourier_info->modulus != MagickFalse) 5553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 5563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 557bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 558bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->width; x++) 5593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 5607d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]/=(2.0*MagickPI); 5617d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]+=0.5; 5623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 5633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 5643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 56546ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy magnitude_view=AcquireAuthenticCacheView(magnitude_image,exception); 5663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 567bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 5683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 5695570fc587fc1fb64666649c75bb7531e08e96a0aCristy q=GetCacheViewAuthenticPixels(magnitude_view,0L,y,fourier_info->width,1UL, 5703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy exception); 571acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy if (q == (Quantum *) NULL) 5723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 573bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->width; x++) 5743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 5753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy switch (fourier_info->channel) 5763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 577d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case RedPixelChannel: 5783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy default: 5793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 5804c08aed51c5899665ade97263692328eea4af106cristy SetPixelRed(magnitude_image,ClampToQuantum(QuantumRange* 5817d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels[i]),q); 5823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 5833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 584d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case GreenPixelChannel: 5853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 5864c08aed51c5899665ade97263692328eea4af106cristy SetPixelGreen(magnitude_image,ClampToQuantum(QuantumRange* 5877d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels[i]),q); 5883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 5893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 590d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case BluePixelChannel: 5913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 5924c08aed51c5899665ade97263692328eea4af106cristy SetPixelBlue(magnitude_image,ClampToQuantum(QuantumRange* 5937d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels[i]),q); 5943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 5953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 596d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case BlackPixelChannel: 5973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 5984c08aed51c5899665ade97263692328eea4af106cristy SetPixelBlack(magnitude_image,ClampToQuantum(QuantumRange* 5997d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels[i]),q); 6003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 602d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case AlphaPixelChannel: 6033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6044c08aed51c5899665ade97263692328eea4af106cristy SetPixelAlpha(magnitude_image,ClampToQuantum(QuantumRange* 6057d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels[i]),q); 6063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 6083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 6093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 610ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy q+=GetPixelChannels(magnitude_image); 6113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 6123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=SyncCacheViewAuthenticPixels(magnitude_view,exception); 6133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status == MagickFalse) 6143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 616db070957cf6bf959df9283a482377e8854c3d4d2cristy magnitude_view=DestroyCacheView(magnitude_view); 6173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 61846ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy phase_view=AcquireAuthenticCacheView(phase_image,exception); 619bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 6203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6215570fc587fc1fb64666649c75bb7531e08e96a0aCristy q=GetCacheViewAuthenticPixels(phase_view,0L,y,fourier_info->width,1UL, 6223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy exception); 623acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy if (q == (Quantum *) NULL) 6243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 625bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->width; x++) 6263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy switch (fourier_info->channel) 6283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 629d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case RedPixelChannel: 6303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy default: 6313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6324c08aed51c5899665ade97263692328eea4af106cristy SetPixelRed(phase_image,ClampToQuantum(QuantumRange* 6337d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]),q); 6343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 636d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case GreenPixelChannel: 6373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6384c08aed51c5899665ade97263692328eea4af106cristy SetPixelGreen(phase_image,ClampToQuantum(QuantumRange* 6397d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]),q); 6403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 642d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case BluePixelChannel: 6433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6444c08aed51c5899665ade97263692328eea4af106cristy SetPixelBlue(phase_image,ClampToQuantum(QuantumRange* 6457d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]),q); 6463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 648d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case BlackPixelChannel: 6493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6504c08aed51c5899665ade97263692328eea4af106cristy SetPixelBlack(phase_image,ClampToQuantum(QuantumRange* 6517d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]),q); 6523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 654d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case AlphaPixelChannel: 6553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 6564c08aed51c5899665ade97263692328eea4af106cristy SetPixelAlpha(phase_image,ClampToQuantum(QuantumRange* 6577d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]),q); 6583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 6603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 6613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 662ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy q+=GetPixelChannels(phase_image); 6633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 6643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=SyncCacheViewAuthenticPixels(phase_view,exception); 6653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status == MagickFalse) 6663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 6673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 6683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy phase_view=DestroyCacheView(phase_view); 6697d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_info=RelinquishVirtualMemory(phase_info); 6707d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_info=RelinquishVirtualMemory(magnitude_info); 6713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(status); 6723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 6733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 6743ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType ForwardFourierTransform(FourierInfo *fourier_info, 675699ae5b6cbee363e53f58e0fedd414f282d07eddcristy const Image *image,double *magnitude_pixels,double *phase_pixels, 676699ae5b6cbee363e53f58e0fedd414f282d07eddcristy ExceptionInfo *exception) 6773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 6783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy CacheView 6793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *image_view; 6803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 68199dc036190f292a67801dc4b141898bf18c96b36cristy const char 68299dc036190f292a67801dc4b141898bf18c96b36cristy *value; 68399dc036190f292a67801dc4b141898bf18c96b36cristy 6843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy double 685bb3c02e054634545e7595cea2048c07de0407f1acristy *source_pixels; 6863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 6873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fftw_complex 688699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *forward_pixels; 6893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 6903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fftw_plan 6913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fftw_r2c_plan; 6923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 6937d4aa38318c20a4309d855f45e3744c9f300f697cristy MemoryInfo 694699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *forward_info, 6957d4aa38318c20a4309d855f45e3744c9f300f697cristy *source_info; 6967d4aa38318c20a4309d855f45e3744c9f300f697cristy 6974c08aed51c5899665ade97263692328eea4af106cristy register const Quantum 6983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *p; 6993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 700bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 7013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i, 7023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy x; 7033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 704c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy ssize_t 705c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy y; 706c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy 7073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 7083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Generate the forward Fourier transform. 7093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 7102e035cd272c0993d28f757f4a913070170095939Cristy source_info=AcquireVirtualMemory((size_t) fourier_info->width, 7112e035cd272c0993d28f757f4a913070170095939Cristy fourier_info->height*sizeof(*source_pixels)); 7127d4aa38318c20a4309d855f45e3744c9f300f697cristy if (source_info == (MemoryInfo *) NULL) 7133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 7143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) ThrowMagickException(exception,GetMagickModule(), 715efe601ce9ea5ad34ad0e8ad6e61d9be9b148b2a3cristy ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); 7163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 7173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 718bb3c02e054634545e7595cea2048c07de0407f1acristy source_pixels=(double *) GetVirtualMemoryBlob(source_info); 7192a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy ResetMagickMemory(source_pixels,0,fourier_info->width*fourier_info->height* 720bb3c02e054634545e7595cea2048c07de0407f1acristy sizeof(*source_pixels)); 7213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 72246ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy image_view=AcquireVirtualCacheView(image,exception); 723bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 7243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 7253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy p=GetCacheViewVirtualPixels(image_view,0L,y,fourier_info->width,1UL, 7263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy exception); 7274c08aed51c5899665ade97263692328eea4af106cristy if (p == (const Quantum *) NULL) 7283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 729bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->width; x++) 7303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 7313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy switch (fourier_info->channel) 7323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 733d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case RedPixelChannel: 7343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy default: 7353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 736bb3c02e054634545e7595cea2048c07de0407f1acristy source_pixels[i]=QuantumScale*GetPixelRed(image,p); 7373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 7383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 739d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case GreenPixelChannel: 7403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 741bb3c02e054634545e7595cea2048c07de0407f1acristy source_pixels[i]=QuantumScale*GetPixelGreen(image,p); 7423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 7433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 744d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case BluePixelChannel: 7453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 746bb3c02e054634545e7595cea2048c07de0407f1acristy source_pixels[i]=QuantumScale*GetPixelBlue(image,p); 7473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 7483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 749d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case BlackPixelChannel: 7503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 751bb3c02e054634545e7595cea2048c07de0407f1acristy source_pixels[i]=QuantumScale*GetPixelBlack(image,p); 7523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 7533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 754d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case AlphaPixelChannel: 7553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 756bb3c02e054634545e7595cea2048c07de0407f1acristy source_pixels[i]=QuantumScale*GetPixelAlpha(image,p); 7573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 7583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 7593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 7603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 761ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy p+=GetPixelChannels(image); 7623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 7633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 7643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy image_view=DestroyCacheView(image_view); 765bbc9a95a7875c8c9b4a8e0b87491aa52e56ec849Cristy forward_info=AcquireVirtualMemory((size_t) fourier_info->width, 7662e035cd272c0993d28f757f4a913070170095939Cristy (fourier_info->height/2+1)*sizeof(*forward_pixels)); 767699ae5b6cbee363e53f58e0fedd414f282d07eddcristy if (forward_info == (MemoryInfo *) NULL) 7683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 7693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) ThrowMagickException(exception,GetMagickModule(), 770efe601ce9ea5ad34ad0e8ad6e61d9be9b148b2a3cristy ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); 771bb3c02e054634545e7595cea2048c07de0407f1acristy source_info=(MemoryInfo *) RelinquishVirtualMemory(source_info); 7723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 7733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 774699ae5b6cbee363e53f58e0fedd414f282d07eddcristy forward_pixels=(fftw_complex *) GetVirtualMemoryBlob(forward_info); 775b5d5f725fef80ff5d50db3111c05a1a521b81e7fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 7763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy #pragma omp critical (MagickCore_ForwardFourierTransform) 7773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 77870841a141aec156091268e1c6e20938abffbfa5ccristy fftw_r2c_plan=fftw_plan_dft_r2c_2d(fourier_info->width,fourier_info->height, 779699ae5b6cbee363e53f58e0fedd414f282d07eddcristy source_pixels,forward_pixels,FFTW_ESTIMATE); 780bbc9a95a7875c8c9b4a8e0b87491aa52e56ec849Cristy fftw_execute_dft_r2c(fftw_r2c_plan,source_pixels,forward_pixels); 7813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fftw_destroy_plan(fftw_r2c_plan); 782bb3c02e054634545e7595cea2048c07de0407f1acristy source_info=(MemoryInfo *) RelinquishVirtualMemory(source_info); 78399dc036190f292a67801dc4b141898bf18c96b36cristy value=GetImageArtifact(image,"fourier:normalize"); 784f8ecbfdd4702c1b9dcc8f35870b60d61e6d32d79cristy if ((value == (const char *) NULL) || (LocaleCompare(value,"forward") == 0)) 78556ed31cc763800a9fb1f0df96104c354b40d2cbccristy { 78699dc036190f292a67801dc4b141898bf18c96b36cristy double 78799dc036190f292a67801dc4b141898bf18c96b36cristy gamma; 78899dc036190f292a67801dc4b141898bf18c96b36cristy 78999dc036190f292a67801dc4b141898bf18c96b36cristy /* 7902e035cd272c0993d28f757f4a913070170095939Cristy Normalize fourier transform. 79199dc036190f292a67801dc4b141898bf18c96b36cristy */ 79299dc036190f292a67801dc4b141898bf18c96b36cristy i=0L; 79399dc036190f292a67801dc4b141898bf18c96b36cristy gamma=PerceptibleReciprocal((double) fourier_info->width* 79499dc036190f292a67801dc4b141898bf18c96b36cristy fourier_info->height); 79599dc036190f292a67801dc4b141898bf18c96b36cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 79699dc036190f292a67801dc4b141898bf18c96b36cristy for (x=0L; x < (ssize_t) fourier_info->center; x++) 79799dc036190f292a67801dc4b141898bf18c96b36cristy { 79856ed31cc763800a9fb1f0df96104c354b40d2cbccristy#if defined(MAGICKCORE_HAVE_COMPLEX_H) 79999dc036190f292a67801dc4b141898bf18c96b36cristy forward_pixels[i]*=gamma; 80056ed31cc763800a9fb1f0df96104c354b40d2cbccristy#else 80199dc036190f292a67801dc4b141898bf18c96b36cristy forward_pixels[i][0]*=gamma; 80299dc036190f292a67801dc4b141898bf18c96b36cristy forward_pixels[i][1]*=gamma; 80356ed31cc763800a9fb1f0df96104c354b40d2cbccristy#endif 80499dc036190f292a67801dc4b141898bf18c96b36cristy i++; 80599dc036190f292a67801dc4b141898bf18c96b36cristy } 80656ed31cc763800a9fb1f0df96104c354b40d2cbccristy } 8073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 8083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Generate magnitude and phase (or real and imaginary). 8093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 8103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 8113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (fourier_info->modulus != MagickFalse) 812bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 813bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->center; x++) 8143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 815699ae5b6cbee363e53f58e0fedd414f282d07eddcristy magnitude_pixels[i]=cabs(forward_pixels[i]); 816699ae5b6cbee363e53f58e0fedd414f282d07eddcristy phase_pixels[i]=carg(forward_pixels[i]); 8173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 8183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 8193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy else 820bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 821bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->center; x++) 8223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 823699ae5b6cbee363e53f58e0fedd414f282d07eddcristy magnitude_pixels[i]=creal(forward_pixels[i]); 824699ae5b6cbee363e53f58e0fedd414f282d07eddcristy phase_pixels[i]=cimag(forward_pixels[i]); 8253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 8263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 827699ae5b6cbee363e53f58e0fedd414f282d07eddcristy forward_info=(MemoryInfo *) RelinquishVirtualMemory(forward_info); 8283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickTrue); 8293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 8303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 8313ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType ForwardFourierTransformChannel(const Image *image, 832d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy const PixelChannel channel,const MagickBooleanType modulus, 8333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Image *fourier_image,ExceptionInfo *exception) 8343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 8353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy double 836ce9fe78c6f9452d2bc114f6e4075838313943a82cristy *magnitude_pixels, 837ce9fe78c6f9452d2bc114f6e4075838313943a82cristy *phase_pixels; 838bb3c02e054634545e7595cea2048c07de0407f1acristy 83956ed31cc763800a9fb1f0df96104c354b40d2cbccristy FourierInfo 84056ed31cc763800a9fb1f0df96104c354b40d2cbccristy fourier_info; 84156ed31cc763800a9fb1f0df96104c354b40d2cbccristy 842c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy MagickBooleanType 843c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy status; 844c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy 845ce9fe78c6f9452d2bc114f6e4075838313943a82cristy MemoryInfo 846ce9fe78c6f9452d2bc114f6e4075838313943a82cristy *magnitude_info, 847ce9fe78c6f9452d2bc114f6e4075838313943a82cristy *phase_info; 848ce9fe78c6f9452d2bc114f6e4075838313943a82cristy 8493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fourier_info.width=image->columns; 850740b4f1b3bbfb255bd4bd08132acfd0ee9977ccecristy fourier_info.height=image->rows; 8512a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy if ((image->columns != image->rows) || ((image->columns % 2) != 0) || 8522a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy ((image->rows % 2) != 0)) 8532a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy { 8542a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy size_t extent=image->columns < image->rows ? image->rows : image->columns; 8552a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy fourier_info.width=(extent & 0x01) == 1 ? extent+1UL : extent; 8562a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy } 8572a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy fourier_info.height=fourier_info.width; 8582e035cd272c0993d28f757f4a913070170095939Cristy fourier_info.center=(ssize_t) (fourier_info.width/2L)+1L; 8593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fourier_info.channel=channel; 8603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fourier_info.modulus=modulus; 8612e035cd272c0993d28f757f4a913070170095939Cristy magnitude_info=AcquireVirtualMemory((size_t) fourier_info.width, 8622e035cd272c0993d28f757f4a913070170095939Cristy (fourier_info.height/2+1)*sizeof(*magnitude_pixels)); 8632e035cd272c0993d28f757f4a913070170095939Cristy phase_info=AcquireVirtualMemory((size_t) fourier_info.width, 8642e035cd272c0993d28f757f4a913070170095939Cristy (fourier_info.height/2+1)*sizeof(*phase_pixels)); 865ce9fe78c6f9452d2bc114f6e4075838313943a82cristy if ((magnitude_info == (MemoryInfo *) NULL) || 866ce9fe78c6f9452d2bc114f6e4075838313943a82cristy (phase_info == (MemoryInfo *) NULL)) 867bb3c02e054634545e7595cea2048c07de0407f1acristy { 868ce9fe78c6f9452d2bc114f6e4075838313943a82cristy if (phase_info != (MemoryInfo *) NULL) 869ce9fe78c6f9452d2bc114f6e4075838313943a82cristy phase_info=RelinquishVirtualMemory(phase_info); 870ce9fe78c6f9452d2bc114f6e4075838313943a82cristy if (magnitude_info == (MemoryInfo *) NULL) 871ce9fe78c6f9452d2bc114f6e4075838313943a82cristy magnitude_info=RelinquishVirtualMemory(magnitude_info); 872bb3c02e054634545e7595cea2048c07de0407f1acristy (void) ThrowMagickException(exception,GetMagickModule(), 873bb3c02e054634545e7595cea2048c07de0407f1acristy ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); 8743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 8753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 876ce9fe78c6f9452d2bc114f6e4075838313943a82cristy magnitude_pixels=(double *) GetVirtualMemoryBlob(magnitude_info); 877ce9fe78c6f9452d2bc114f6e4075838313943a82cristy phase_pixels=(double *) GetVirtualMemoryBlob(phase_info); 878ce9fe78c6f9452d2bc114f6e4075838313943a82cristy status=ForwardFourierTransform(&fourier_info,image,magnitude_pixels, 879ce9fe78c6f9452d2bc114f6e4075838313943a82cristy phase_pixels,exception); 8803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status != MagickFalse) 881ce9fe78c6f9452d2bc114f6e4075838313943a82cristy status=ForwardFourier(&fourier_info,fourier_image,magnitude_pixels, 882ce9fe78c6f9452d2bc114f6e4075838313943a82cristy phase_pixels,exception); 883ce9fe78c6f9452d2bc114f6e4075838313943a82cristy phase_info=RelinquishVirtualMemory(phase_info); 884ce9fe78c6f9452d2bc114f6e4075838313943a82cristy magnitude_info=RelinquishVirtualMemory(magnitude_info); 8853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(status); 8863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 8873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 8883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 8893ed852eea50f9d4cd633efb8c2b054b8e33c253cristyMagickExport Image *ForwardFourierTransformImage(const Image *image, 8903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy const MagickBooleanType modulus,ExceptionInfo *exception) 8913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 8923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Image 8933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *fourier_image; 8943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 8953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fourier_image=NewImageList(); 8963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if !defined(MAGICKCORE_FFTW_DELEGATE) 8973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) modulus; 8983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) ThrowMagickException(exception,GetMagickModule(), 8992e035cd272c0993d28f757f4a913070170095939Cristy MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn","`%s' (FFTW)", 9003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy image->filename); 9013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else 9023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 9033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Image 9043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *magnitude_image; 9053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 906bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy size_t 907c9721ffe0e76156deb0d518ec41c0431e1b61922cristy height, 9083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy width; 9093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 9103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy width=image->columns; 911c9721ffe0e76156deb0d518ec41c0431e1b61922cristy height=image->rows; 9122a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy if ((image->columns != image->rows) || ((image->columns % 2) != 0) || 9132a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy ((image->rows % 2) != 0)) 9142a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy { 9152a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy size_t extent=image->columns < image->rows ? image->rows : 9162a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy image->columns; 9172a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy width=(extent & 0x01) == 1 ? extent+1UL : extent; 9182a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy } 9192a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy height=width; 920c9721ffe0e76156deb0d518ec41c0431e1b61922cristy magnitude_image=CloneImage(image,width,height,MagickTrue,exception); 9213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (magnitude_image != (Image *) NULL) 9223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 9233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Image 9243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *phase_image; 9253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 9263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy magnitude_image->storage_class=DirectClass; 9273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy magnitude_image->depth=32UL; 928c9721ffe0e76156deb0d518ec41c0431e1b61922cristy phase_image=CloneImage(image,width,height,MagickTrue,exception); 9293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (phase_image == (Image *) NULL) 9303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy magnitude_image=DestroyImage(magnitude_image); 9313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy else 9323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 9333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 9343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy is_gray, 9353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status; 9363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 9373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy phase_image->storage_class=DirectClass; 9383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy phase_image->depth=32UL; 9393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy AppendImageToList(&fourier_image,magnitude_image); 9403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy AppendImageToList(&fourier_image,phase_image); 9413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=MagickTrue; 942c6f2ac9fbacb63eb30ab87d80dba97d634742d4bcristy is_gray=IsImageGray(image); 943b5d5f725fef80ff5d50db3111c05a1a521b81e7fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 944564a56979706a30a3d0f920fd5f538a408efd4f1cristy #pragma omp parallel sections 9453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 9463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 947b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 948b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp section 949b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#endif 9503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 951b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy MagickBooleanType 952b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status; 953b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy 954b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (is_gray != MagickFalse) 955b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=ForwardFourierTransformChannel(image, 956d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy GrayPixelChannel,modulus,fourier_image,exception); 957b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy else 958b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=ForwardFourierTransformChannel(image, 959d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy RedPixelChannel,modulus,fourier_image,exception); 960b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (thread_status == MagickFalse) 961b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy status=thread_status; 962b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy } 963b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 964b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp section 965b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#endif 966b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy { 967b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy MagickBooleanType 968b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status; 969b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy 970b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=MagickTrue; 971b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (is_gray == MagickFalse) 972b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=ForwardFourierTransformChannel(image, 973d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy GreenPixelChannel,modulus,fourier_image,exception); 974b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (thread_status == MagickFalse) 975b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy status=thread_status; 976b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy } 977b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 978b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp section 979b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#endif 980b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy { 981b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy MagickBooleanType 982b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status; 983b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy 984b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=MagickTrue; 985b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (is_gray == MagickFalse) 986b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=ForwardFourierTransformChannel(image, 987d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy BluePixelChannel,modulus,fourier_image,exception); 988b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (thread_status == MagickFalse) 989b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy status=thread_status; 990b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy } 991b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 992b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp section 993b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#endif 994b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy { 995b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy MagickBooleanType 996b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status; 997b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy 998b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=MagickTrue; 9994c08aed51c5899665ade97263692328eea4af106cristy if (image->colorspace == CMYKColorspace) 1000b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=ForwardFourierTransformChannel(image, 1001d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy BlackPixelChannel,modulus,fourier_image,exception); 1002b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (thread_status == MagickFalse) 1003b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy status=thread_status; 1004b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy } 1005b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 1006b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp section 1007b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#endif 1008b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy { 1009b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy MagickBooleanType 1010b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status; 1011b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy 1012b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=MagickTrue; 101317f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (image->alpha_trait != UndefinedPixelTrait) 1014b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=ForwardFourierTransformChannel(image, 1015d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy AlphaPixelChannel,modulus,fourier_image,exception); 1016b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (thread_status == MagickFalse) 1017b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy status=thread_status; 10183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 10193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 10203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status == MagickFalse) 10213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fourier_image=DestroyImageList(fourier_image); 10223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fftw_cleanup(); 10233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 10243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 10253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 10263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 10273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(fourier_image); 10283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 10293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 10303ed852eea50f9d4cd633efb8c2b054b8e33c253cristy/* 10313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 10333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 10343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 10353ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 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 % 10363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 10373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 10383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% % 10393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 10413ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% InverseFourierTransformImage() implements the inverse discrete Fourier 10423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% transform (DFT) of the image either as a magnitude / phase or real / 10433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% imaginary image pair. 10443ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 10453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% The format of the InverseFourierTransformImage method is: 10463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 1047c9550792cd47c57370cd82fef338304f9e576473cristy% Image *InverseFourierTransformImage(const Image *magnitude_image, 1048c9550792cd47c57370cd82fef338304f9e576473cristy% const Image *phase_image,const MagickBooleanType modulus, 1049c9550792cd47c57370cd82fef338304f9e576473cristy% ExceptionInfo *exception) 10503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 10513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% A description of each parameter follows: 10523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 1053c9550792cd47c57370cd82fef338304f9e576473cristy% o magnitude_image: the magnitude or real image. 1054c9550792cd47c57370cd82fef338304f9e576473cristy% 1055c9550792cd47c57370cd82fef338304f9e576473cristy% o phase_image: the phase or imaginary image. 10563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 10573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o modulus: if true, return transform as a magnitude / phase pair 10583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% otherwise a real / imaginary image pair. 10593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 10603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% o exception: return any errors or warnings in this structure. 10613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy% 10623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy*/ 10633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 10643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if defined(MAGICKCORE_FFTW_DELEGATE) 1065bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristystatic MagickBooleanType InverseQuadrantSwap(const size_t width, 1066bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy const size_t height,const double *source,double *destination) 10673ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 1068c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy register ssize_t 1069c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy x; 1070c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy 1071bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy ssize_t 10723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy center, 10733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy y; 10743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 10753ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 10763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Swap quadrants. 10773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 10782e035cd272c0993d28f757f4a913070170095939Cristy center=(ssize_t) (width/2L)+1L; 1079bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=1L; y < (ssize_t) height; y++) 1080bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) (width/2L+1L); x++) 10819b1d6c756cb32746846b038ccb0439db540ba509cristy destination[(height-y)*center-x+width/2L]=source[y*width+x]; 1082bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) height; y++) 10833d04ed7ddc7a93c09476e84cc64412687bf5261acristy destination[y*center]=source[y*width+width/2L]; 10843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy for (x=0L; x < center; x++) 10853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy destination[x]=source[center-x-1L]; 1086bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy return(RollFourier(center,height,0L,(ssize_t) height/-2L,destination)); 10873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 10883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 10893ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType InverseFourier(FourierInfo *fourier_info, 1090699ae5b6cbee363e53f58e0fedd414f282d07eddcristy const Image *magnitude_image,const Image *phase_image, 1091699ae5b6cbee363e53f58e0fedd414f282d07eddcristy fftw_complex *fourier_pixels,ExceptionInfo *exception) 10923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 10933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy CacheView 10943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *magnitude_view, 10953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *phase_view; 10963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 10973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy double 1098699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *inverse_pixels, 10997d4aa38318c20a4309d855f45e3744c9f300f697cristy *magnitude_pixels, 11007d4aa38318c20a4309d855f45e3744c9f300f697cristy *phase_pixels; 11013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 11023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 11033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status; 11043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1105699ae5b6cbee363e53f58e0fedd414f282d07eddcristy MemoryInfo 1106699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *inverse_info, 1107699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *magnitude_info, 1108699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *phase_info; 1109699ae5b6cbee363e53f58e0fedd414f282d07eddcristy 11104c08aed51c5899665ade97263692328eea4af106cristy register const Quantum 11113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *p; 11123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1113bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 11143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i, 11153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy x; 11163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1117c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy ssize_t 1118c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy y; 1119c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy 11203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 11213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Inverse fourier - read image and break down into a double array. 11223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 11232e035cd272c0993d28f757f4a913070170095939Cristy magnitude_info=AcquireVirtualMemory((size_t) fourier_info->width, 11242e035cd272c0993d28f757f4a913070170095939Cristy fourier_info->height*sizeof(*magnitude_pixels)); 11252e035cd272c0993d28f757f4a913070170095939Cristy phase_info=AcquireVirtualMemory((size_t) fourier_info->width, 11262e035cd272c0993d28f757f4a913070170095939Cristy fourier_info->height*sizeof(*phase_pixels)); 11272e035cd272c0993d28f757f4a913070170095939Cristy inverse_info=AcquireVirtualMemory((size_t) fourier_info->width, 11282e035cd272c0993d28f757f4a913070170095939Cristy (fourier_info->height/2+1)*sizeof(*inverse_pixels)); 1129699ae5b6cbee363e53f58e0fedd414f282d07eddcristy if ((magnitude_info == (MemoryInfo *) NULL) || 1130699ae5b6cbee363e53f58e0fedd414f282d07eddcristy (phase_info == (MemoryInfo *) NULL) || 1131699ae5b6cbee363e53f58e0fedd414f282d07eddcristy (inverse_info == (MemoryInfo *) NULL)) 11323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 1133699ae5b6cbee363e53f58e0fedd414f282d07eddcristy if (magnitude_info != (MemoryInfo *) NULL) 1134699ae5b6cbee363e53f58e0fedd414f282d07eddcristy magnitude_info=RelinquishVirtualMemory(magnitude_info); 1135699ae5b6cbee363e53f58e0fedd414f282d07eddcristy if (phase_info != (MemoryInfo *) NULL) 1136699ae5b6cbee363e53f58e0fedd414f282d07eddcristy phase_info=RelinquishVirtualMemory(phase_info); 1137699ae5b6cbee363e53f58e0fedd414f282d07eddcristy if (inverse_info != (MemoryInfo *) NULL) 1138699ae5b6cbee363e53f58e0fedd414f282d07eddcristy inverse_info=RelinquishVirtualMemory(inverse_info); 11393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) ThrowMagickException(exception,GetMagickModule(), 1140efe601ce9ea5ad34ad0e8ad6e61d9be9b148b2a3cristy ResourceLimitError,"MemoryAllocationFailed","`%s'", 1141c9550792cd47c57370cd82fef338304f9e576473cristy magnitude_image->filename); 11423ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 11433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1144699ae5b6cbee363e53f58e0fedd414f282d07eddcristy magnitude_pixels=(double *) GetVirtualMemoryBlob(magnitude_info); 1145699ae5b6cbee363e53f58e0fedd414f282d07eddcristy phase_pixels=(double *) GetVirtualMemoryBlob(phase_info); 1146699ae5b6cbee363e53f58e0fedd414f282d07eddcristy inverse_pixels=(double *) GetVirtualMemoryBlob(inverse_info); 11473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 114846ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy magnitude_view=AcquireVirtualCacheView(magnitude_image,exception); 1149bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 11503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 11513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy p=GetCacheViewVirtualPixels(magnitude_view,0L,y,fourier_info->width,1UL, 11523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy exception); 11534c08aed51c5899665ade97263692328eea4af106cristy if (p == (const Quantum *) NULL) 11543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 1155bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->width; x++) 11563ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 11573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy switch (fourier_info->channel) 11583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 1159d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case RedPixelChannel: 11603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy default: 11613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 11627d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels[i]=QuantumScale*GetPixelRed(magnitude_image,p); 11633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 11643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1165d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case GreenPixelChannel: 11663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 11677d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels[i]=QuantumScale*GetPixelGreen(magnitude_image,p); 11683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 11693ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1170d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case BluePixelChannel: 11713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 11727d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels[i]=QuantumScale*GetPixelBlue(magnitude_image,p); 11733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 11743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1175d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case BlackPixelChannel: 11763ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 11777d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels[i]=QuantumScale*GetPixelBlack(magnitude_image,p); 11783ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 11793ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1180d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case AlphaPixelChannel: 11813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 11827d4aa38318c20a4309d855f45e3744c9f300f697cristy magnitude_pixels[i]=QuantumScale*GetPixelAlpha(magnitude_image,p); 11833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 11843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 11853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 11863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 1187ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy p+=GetPixelChannels(magnitude_image); 11883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 11893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1190699ae5b6cbee363e53f58e0fedd414f282d07eddcristy magnitude_view=DestroyCacheView(magnitude_view); 1191699ae5b6cbee363e53f58e0fedd414f282d07eddcristy status=InverseQuadrantSwap(fourier_info->width,fourier_info->height, 1192699ae5b6cbee363e53f58e0fedd414f282d07eddcristy magnitude_pixels,inverse_pixels); 1193699ae5b6cbee363e53f58e0fedd414f282d07eddcristy (void) CopyMagickMemory(magnitude_pixels,inverse_pixels,fourier_info->height* 1194699ae5b6cbee363e53f58e0fedd414f282d07eddcristy fourier_info->center*sizeof(*magnitude_pixels)); 11953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 119646ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy phase_view=AcquireVirtualCacheView(phase_image,exception); 1197bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 11983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 11993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy p=GetCacheViewVirtualPixels(phase_view,0,y,fourier_info->width,1, 12003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy exception); 12014c08aed51c5899665ade97263692328eea4af106cristy if (p == (const Quantum *) NULL) 12023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 1203bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->width; x++) 12043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 12053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy switch (fourier_info->channel) 12063ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 1207d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case RedPixelChannel: 12083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy default: 12093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 12107d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]=QuantumScale*GetPixelRed(phase_image,p); 12113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 12123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1213d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case GreenPixelChannel: 12143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 12157d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]=QuantumScale*GetPixelGreen(phase_image,p); 12163ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 12173ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1218d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case BluePixelChannel: 12193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 12207d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]=QuantumScale*GetPixelBlue(phase_image,p); 12213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 12223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1223d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case BlackPixelChannel: 12243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 12257d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]=QuantumScale*GetPixelBlack(phase_image,p); 12263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 12273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1228d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy case AlphaPixelChannel: 12293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 12307d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]=QuantumScale*GetPixelAlpha(phase_image,p); 12313ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 12323ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 12333ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 12343ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 1235ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy p+=GetPixelChannels(phase_image); 12363ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 12373ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 12383ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (fourier_info->modulus != MagickFalse) 12393ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 12403ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 1241bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 1242bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->width; x++) 12433ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 12447d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]-=0.5; 12457d4aa38318c20a4309d855f45e3744c9f300f697cristy phase_pixels[i]*=(2.0*MagickPI); 12463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 12473ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 12483ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 12493ed852eea50f9d4cd633efb8c2b054b8e33c253cristy phase_view=DestroyCacheView(phase_view); 125013c99c4243ef58ec6f752aba6df9970ec16c87e6cristy CorrectPhaseLHS(fourier_info->width,fourier_info->height,phase_pixels); 12513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status != MagickFalse) 12523ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=InverseQuadrantSwap(fourier_info->width,fourier_info->height, 1253699ae5b6cbee363e53f58e0fedd414f282d07eddcristy phase_pixels,inverse_pixels); 1254699ae5b6cbee363e53f58e0fedd414f282d07eddcristy (void) CopyMagickMemory(phase_pixels,inverse_pixels,fourier_info->height* 1255699ae5b6cbee363e53f58e0fedd414f282d07eddcristy fourier_info->center*sizeof(*phase_pixels)); 1256699ae5b6cbee363e53f58e0fedd414f282d07eddcristy inverse_info=RelinquishVirtualMemory(inverse_info); 12573ed852eea50f9d4cd633efb8c2b054b8e33c253cristy /* 12583ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Merge two sets. 12593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy */ 12603ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 12613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (fourier_info->modulus != MagickFalse) 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]*cos(phase_pixels[i])+I* 1267699ae5b6cbee363e53f58e0fedd414f282d07eddcristy magnitude_pixels[i]*sin(phase_pixels[i]); 126856ed31cc763800a9fb1f0df96104c354b40d2cbccristy#else 1269699ae5b6cbee363e53f58e0fedd414f282d07eddcristy fourier_pixels[i][0]=magnitude_pixels[i]*cos(phase_pixels[i]); 1270699ae5b6cbee363e53f58e0fedd414f282d07eddcristy fourier_pixels[i][1]=magnitude_pixels[i]*sin(phase_pixels[i]); 127156ed31cc763800a9fb1f0df96104c354b40d2cbccristy#endif 12723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 12733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 12743ed852eea50f9d4cd633efb8c2b054b8e33c253cristy else 1275bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 1276bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->center; x++) 12773ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 127856ed31cc763800a9fb1f0df96104c354b40d2cbccristy#if defined(MAGICKCORE_HAVE_COMPLEX_H) 1279699ae5b6cbee363e53f58e0fedd414f282d07eddcristy fourier_pixels[i]=magnitude_pixels[i]+I*phase_pixels[i]; 128056ed31cc763800a9fb1f0df96104c354b40d2cbccristy#else 1281699ae5b6cbee363e53f58e0fedd414f282d07eddcristy fourier_pixels[i][0]=magnitude_pixels[i]; 1282699ae5b6cbee363e53f58e0fedd414f282d07eddcristy fourier_pixels[i][1]=phase_pixels[i]; 128356ed31cc763800a9fb1f0df96104c354b40d2cbccristy#endif 12843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 12853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1286699ae5b6cbee363e53f58e0fedd414f282d07eddcristy magnitude_info=RelinquishVirtualMemory(magnitude_info); 1287699ae5b6cbee363e53f58e0fedd414f282d07eddcristy phase_info=RelinquishVirtualMemory(phase_info); 12883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(status); 12893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 12903ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 12913ed852eea50f9d4cd633efb8c2b054b8e33c253cristystatic MagickBooleanType InverseFourierTransform(FourierInfo *fourier_info, 1292699ae5b6cbee363e53f58e0fedd414f282d07eddcristy fftw_complex *fourier_pixels,Image *image,ExceptionInfo *exception) 12933ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 12943ed852eea50f9d4cd633efb8c2b054b8e33c253cristy CacheView 12953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *image_view; 12963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 129799dc036190f292a67801dc4b141898bf18c96b36cristy const char 129899dc036190f292a67801dc4b141898bf18c96b36cristy *value; 129999dc036190f292a67801dc4b141898bf18c96b36cristy 13003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy double 1301699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *source_pixels; 13023ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 13033ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fftw_plan 13043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fftw_c2r_plan; 13053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1306699ae5b6cbee363e53f58e0fedd414f282d07eddcristy MemoryInfo 1307699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *source_info; 1308699ae5b6cbee363e53f58e0fedd414f282d07eddcristy 13094c08aed51c5899665ade97263692328eea4af106cristy register Quantum 1310c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy *q; 1311c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy 1312bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy register ssize_t 13133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i, 13143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy x; 13153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1316c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy ssize_t 1317c4ea4a479c90f81168aa2b99e7680c7b0459d415cristy y; 13183ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 13192e035cd272c0993d28f757f4a913070170095939Cristy source_info=AcquireVirtualMemory((size_t) fourier_info->width, 13202e035cd272c0993d28f757f4a913070170095939Cristy fourier_info->height*sizeof(*source_pixels)); 1321699ae5b6cbee363e53f58e0fedd414f282d07eddcristy if (source_info == (MemoryInfo *) NULL) 13223ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 13233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) ThrowMagickException(exception,GetMagickModule(), 1324efe601ce9ea5ad34ad0e8ad6e61d9be9b148b2a3cristy ResourceLimitError,"MemoryAllocationFailed","`%s'",image->filename); 13253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 13263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1327699ae5b6cbee363e53f58e0fedd414f282d07eddcristy source_pixels=(double *) GetVirtualMemoryBlob(source_info); 132899dc036190f292a67801dc4b141898bf18c96b36cristy value=GetImageArtifact(image,"fourier:normalize"); 1329f8ecbfdd4702c1b9dcc8f35870b60d61e6d32d79cristy if (LocaleCompare(value,"inverse") == 0) 133099dc036190f292a67801dc4b141898bf18c96b36cristy { 133199dc036190f292a67801dc4b141898bf18c96b36cristy double 133299dc036190f292a67801dc4b141898bf18c96b36cristy gamma; 133399dc036190f292a67801dc4b141898bf18c96b36cristy 133499dc036190f292a67801dc4b141898bf18c96b36cristy /* 133599dc036190f292a67801dc4b141898bf18c96b36cristy Normalize inverse transform. 133699dc036190f292a67801dc4b141898bf18c96b36cristy */ 133799dc036190f292a67801dc4b141898bf18c96b36cristy i=0L; 133899dc036190f292a67801dc4b141898bf18c96b36cristy gamma=PerceptibleReciprocal((double) fourier_info->width* 133999dc036190f292a67801dc4b141898bf18c96b36cristy fourier_info->height); 134099dc036190f292a67801dc4b141898bf18c96b36cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 134199dc036190f292a67801dc4b141898bf18c96b36cristy for (x=0L; x < (ssize_t) fourier_info->center; x++) 134299dc036190f292a67801dc4b141898bf18c96b36cristy { 134399dc036190f292a67801dc4b141898bf18c96b36cristy#if defined(MAGICKCORE_HAVE_COMPLEX_H) 134499dc036190f292a67801dc4b141898bf18c96b36cristy fourier_pixels[i]*=gamma; 134599dc036190f292a67801dc4b141898bf18c96b36cristy#else 134699dc036190f292a67801dc4b141898bf18c96b36cristy fourier_pixels[i][0]*=gamma; 134799dc036190f292a67801dc4b141898bf18c96b36cristy fourier_pixels[i][1]*=gamma; 134899dc036190f292a67801dc4b141898bf18c96b36cristy#endif 134999dc036190f292a67801dc4b141898bf18c96b36cristy i++; 135099dc036190f292a67801dc4b141898bf18c96b36cristy } 135199dc036190f292a67801dc4b141898bf18c96b36cristy } 1352b5d5f725fef80ff5d50db3111c05a1a521b81e7fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 13533ed852eea50f9d4cd633efb8c2b054b8e33c253cristy #pragma omp critical (MagickCore_InverseFourierTransform) 13543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 1355bbc9a95a7875c8c9b4a8e0b87491aa52e56ec849Cristy fftw_c2r_plan=fftw_plan_dft_c2r_2d(fourier_info->width,fourier_info->height, 1356bbc9a95a7875c8c9b4a8e0b87491aa52e56ec849Cristy fourier_pixels,source_pixels,FFTW_ESTIMATE); 1357bbc9a95a7875c8c9b4a8e0b87491aa52e56ec849Cristy fftw_execute_dft_c2r(fftw_c2r_plan,fourier_pixels,source_pixels); 1358bbc9a95a7875c8c9b4a8e0b87491aa52e56ec849Cristy fftw_destroy_plan(fftw_c2r_plan); 13593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i=0L; 136046ff2676b1044ea4101ac7a59b83289cd8f6cfdacristy image_view=AcquireAuthenticCacheView(image,exception); 1361bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (y=0L; y < (ssize_t) fourier_info->height; y++) 13623ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 136385812051623aa663ad40386ebfc4b8d0ca87bd55cristy if (y >= (ssize_t) image->rows) 136485812051623aa663ad40386ebfc4b8d0ca87bd55cristy break; 136585812051623aa663ad40386ebfc4b8d0ca87bd55cristy q=GetCacheViewAuthenticPixels(image_view,0L,y,fourier_info->width > 136685812051623aa663ad40386ebfc4b8d0ca87bd55cristy image->columns ? image->columns : fourier_info->width,1UL,exception); 1367acd2ed254c18c254a0ab5aafa06d1645e5d079d8cristy if (q == (Quantum *) NULL) 13683ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 1369bb50337b2a8a16ca7e903cc04ab195ff0fd47ae6cristy for (x=0L; x < (ssize_t) fourier_info->width; x++) 13703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 1371233fe5816db8ff3930e64adebd232757d8d2c06ecristy if (x < (ssize_t) image->columns) 1372233fe5816db8ff3930e64adebd232757d8d2c06ecristy switch (fourier_info->channel) 13733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 1374233fe5816db8ff3930e64adebd232757d8d2c06ecristy case RedPixelChannel: 1375233fe5816db8ff3930e64adebd232757d8d2c06ecristy default: 1376233fe5816db8ff3930e64adebd232757d8d2c06ecristy { 1377699ae5b6cbee363e53f58e0fedd414f282d07eddcristy SetPixelRed(image,ClampToQuantum(QuantumRange*source_pixels[i]),q); 1378233fe5816db8ff3930e64adebd232757d8d2c06ecristy break; 1379233fe5816db8ff3930e64adebd232757d8d2c06ecristy } 1380233fe5816db8ff3930e64adebd232757d8d2c06ecristy case GreenPixelChannel: 1381233fe5816db8ff3930e64adebd232757d8d2c06ecristy { 1382699ae5b6cbee363e53f58e0fedd414f282d07eddcristy SetPixelGreen(image,ClampToQuantum(QuantumRange*source_pixels[i]), 1383699ae5b6cbee363e53f58e0fedd414f282d07eddcristy q); 1384233fe5816db8ff3930e64adebd232757d8d2c06ecristy break; 1385233fe5816db8ff3930e64adebd232757d8d2c06ecristy } 1386233fe5816db8ff3930e64adebd232757d8d2c06ecristy case BluePixelChannel: 1387233fe5816db8ff3930e64adebd232757d8d2c06ecristy { 1388699ae5b6cbee363e53f58e0fedd414f282d07eddcristy SetPixelBlue(image,ClampToQuantum(QuantumRange*source_pixels[i]), 1389699ae5b6cbee363e53f58e0fedd414f282d07eddcristy q); 1390233fe5816db8ff3930e64adebd232757d8d2c06ecristy break; 1391233fe5816db8ff3930e64adebd232757d8d2c06ecristy } 1392233fe5816db8ff3930e64adebd232757d8d2c06ecristy case BlackPixelChannel: 1393233fe5816db8ff3930e64adebd232757d8d2c06ecristy { 1394699ae5b6cbee363e53f58e0fedd414f282d07eddcristy SetPixelBlack(image,ClampToQuantum(QuantumRange*source_pixels[i]), 1395699ae5b6cbee363e53f58e0fedd414f282d07eddcristy q); 1396233fe5816db8ff3930e64adebd232757d8d2c06ecristy break; 1397233fe5816db8ff3930e64adebd232757d8d2c06ecristy } 1398233fe5816db8ff3930e64adebd232757d8d2c06ecristy case AlphaPixelChannel: 1399233fe5816db8ff3930e64adebd232757d8d2c06ecristy { 1400699ae5b6cbee363e53f58e0fedd414f282d07eddcristy SetPixelAlpha(image,ClampToQuantum(QuantumRange*source_pixels[i]), 1401699ae5b6cbee363e53f58e0fedd414f282d07eddcristy q); 1402233fe5816db8ff3930e64adebd232757d8d2c06ecristy break; 1403233fe5816db8ff3930e64adebd232757d8d2c06ecristy } 14043ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 14053ed852eea50f9d4cd633efb8c2b054b8e33c253cristy i++; 1406ed2315769b26818ed9d0c1291dc0457f0d8da0a4cristy q+=GetPixelChannels(image); 14073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 14083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse) 14093ed852eea50f9d4cd633efb8c2b054b8e33c253cristy break; 14103ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 14113ed852eea50f9d4cd633efb8c2b054b8e33c253cristy image_view=DestroyCacheView(image_view); 1412699ae5b6cbee363e53f58e0fedd414f282d07eddcristy source_info=RelinquishVirtualMemory(source_info); 14133ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickTrue); 14143ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 14153ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1416c9550792cd47c57370cd82fef338304f9e576473cristystatic MagickBooleanType InverseFourierTransformChannel( 1417c9550792cd47c57370cd82fef338304f9e576473cristy const Image *magnitude_image,const Image *phase_image, 1418d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy const PixelChannel channel,const MagickBooleanType modulus, 14193ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Image *fourier_image,ExceptionInfo *exception) 14203ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 14213ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fftw_complex 1422699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *inverse_pixels; 14233ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 14243ed852eea50f9d4cd633efb8c2b054b8e33c253cristy FourierInfo 14253ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fourier_info; 14263ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 14273ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 14283ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status; 14293ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1430699ae5b6cbee363e53f58e0fedd414f282d07eddcristy MemoryInfo 1431699ae5b6cbee363e53f58e0fedd414f282d07eddcristy *inverse_info; 1432699ae5b6cbee363e53f58e0fedd414f282d07eddcristy 1433c9550792cd47c57370cd82fef338304f9e576473cristy fourier_info.width=magnitude_image->columns; 14340a69e6429fff81c8de551ed10e358df7b0b2a585cristy fourier_info.height=magnitude_image->rows; 14352a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy if ((magnitude_image->columns != magnitude_image->rows) || 14362a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy ((magnitude_image->columns % 2) != 0) || 14372a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy ((magnitude_image->rows % 2) != 0)) 14382a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy { 14392a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy size_t extent=magnitude_image->columns < magnitude_image->rows ? 14402a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy magnitude_image->rows : magnitude_image->columns; 14412a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy fourier_info.width=(extent & 0x01) == 1 ? extent+1UL : extent; 14422a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy } 14432a5f27cd841820bdf64d9aa42d02c54df8ea7885Cristy fourier_info.height=fourier_info.width; 14442e035cd272c0993d28f757f4a913070170095939Cristy fourier_info.center=(ssize_t) (fourier_info.width/2L)+1L; 14453ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fourier_info.channel=channel; 14463ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fourier_info.modulus=modulus; 14472e035cd272c0993d28f757f4a913070170095939Cristy inverse_info=AcquireVirtualMemory((size_t) fourier_info.width, 14482e035cd272c0993d28f757f4a913070170095939Cristy (fourier_info.height/2+1)*sizeof(*inverse_pixels)); 1449699ae5b6cbee363e53f58e0fedd414f282d07eddcristy if (inverse_info == (MemoryInfo *) NULL) 14503ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 14513ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) ThrowMagickException(exception,GetMagickModule(), 1452efe601ce9ea5ad34ad0e8ad6e61d9be9b148b2a3cristy ResourceLimitError,"MemoryAllocationFailed","`%s'", 1453c9550792cd47c57370cd82fef338304f9e576473cristy magnitude_image->filename); 14543ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(MagickFalse); 14553ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1456699ae5b6cbee363e53f58e0fedd414f282d07eddcristy inverse_pixels=(fftw_complex *) GetVirtualMemoryBlob(inverse_info); 1457699ae5b6cbee363e53f58e0fedd414f282d07eddcristy status=InverseFourier(&fourier_info,magnitude_image,phase_image, 1458699ae5b6cbee363e53f58e0fedd414f282d07eddcristy inverse_pixels,exception); 14593ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status != MagickFalse) 1460699ae5b6cbee363e53f58e0fedd414f282d07eddcristy status=InverseFourierTransform(&fourier_info,inverse_pixels,fourier_image, 14613ed852eea50f9d4cd633efb8c2b054b8e33c253cristy exception); 1462699ae5b6cbee363e53f58e0fedd414f282d07eddcristy inverse_info=RelinquishVirtualMemory(inverse_info); 14633ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(status); 14643ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 14653ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 14663ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1467c9550792cd47c57370cd82fef338304f9e576473cristyMagickExport Image *InverseFourierTransformImage(const Image *magnitude_image, 1468c9550792cd47c57370cd82fef338304f9e576473cristy const Image *phase_image,const MagickBooleanType modulus, 1469c9550792cd47c57370cd82fef338304f9e576473cristy ExceptionInfo *exception) 14703ed852eea50f9d4cd633efb8c2b054b8e33c253cristy{ 14713ed852eea50f9d4cd633efb8c2b054b8e33c253cristy Image 14723ed852eea50f9d4cd633efb8c2b054b8e33c253cristy *fourier_image; 14733ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 1474c9550792cd47c57370cd82fef338304f9e576473cristy assert(magnitude_image != (Image *) NULL); 1475e1c94d9d25db6b0dd7a5028ffee31d1057855d73cristy assert(magnitude_image->signature == MagickCoreSignature); 1476c9550792cd47c57370cd82fef338304f9e576473cristy if (magnitude_image->debug != MagickFalse) 1477c9550792cd47c57370cd82fef338304f9e576473cristy (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 1478c9550792cd47c57370cd82fef338304f9e576473cristy magnitude_image->filename); 1479c9550792cd47c57370cd82fef338304f9e576473cristy if (phase_image == (Image *) NULL) 1480c9550792cd47c57370cd82fef338304f9e576473cristy { 1481c9550792cd47c57370cd82fef338304f9e576473cristy (void) ThrowMagickException(exception,GetMagickModule(),ImageError, 14822e035cd272c0993d28f757f4a913070170095939Cristy "ImageSequenceRequired","`%s'",magnitude_image->filename); 14839372a158e662d81ce4df26249238df39d66102ffcristy return((Image *) NULL); 1484c9550792cd47c57370cd82fef338304f9e576473cristy } 14853ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#if !defined(MAGICKCORE_FFTW_DELEGATE) 14863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fourier_image=(Image *) NULL; 14873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) modulus; 14883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy (void) ThrowMagickException(exception,GetMagickModule(), 14892e035cd272c0993d28f757f4a913070170095939Cristy MissingDelegateWarning,"DelegateLibrarySupportNotBuiltIn","`%s' (FFTW)", 1490c9550792cd47c57370cd82fef338304f9e576473cristy magnitude_image->filename); 14913ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#else 14923ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 1493c9550792cd47c57370cd82fef338304f9e576473cristy fourier_image=CloneImage(magnitude_image,magnitude_image->columns, 14944c9c4d0c413e922bc941efc7657a5c075a944c1fcristy magnitude_image->rows,MagickTrue,exception); 14953ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (fourier_image != (Image *) NULL) 14963ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 14973ed852eea50f9d4cd633efb8c2b054b8e33c253cristy MagickBooleanType 14983ed852eea50f9d4cd633efb8c2b054b8e33c253cristy is_gray, 14993ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status; 15003ed852eea50f9d4cd633efb8c2b054b8e33c253cristy 15013ed852eea50f9d4cd633efb8c2b054b8e33c253cristy status=MagickTrue; 1502c6f2ac9fbacb63eb30ab87d80dba97d634742d4bcristy is_gray=IsImageGray(magnitude_image); 1503c9550792cd47c57370cd82fef338304f9e576473cristy if (is_gray != MagickFalse) 1504c6f2ac9fbacb63eb30ab87d80dba97d634742d4bcristy is_gray=IsImageGray(phase_image); 1505b5d5f725fef80ff5d50db3111c05a1a521b81e7fcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 1506b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp parallel sections 15073ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 15083ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 1509b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 1510b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp section 1511b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#endif 15123ed852eea50f9d4cd633efb8c2b054b8e33c253cristy { 1513b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy MagickBooleanType 1514b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status; 1515b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy 1516b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (is_gray != MagickFalse) 1517b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=InverseFourierTransformChannel(magnitude_image, 1518d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy phase_image,GrayPixelChannel,modulus,fourier_image,exception); 1519b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy else 1520c9550792cd47c57370cd82fef338304f9e576473cristy thread_status=InverseFourierTransformChannel(magnitude_image, 1521d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy phase_image,RedPixelChannel,modulus,fourier_image,exception); 1522b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (thread_status == MagickFalse) 1523b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy status=thread_status; 1524b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy } 1525b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 1526b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp section 1527b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#endif 1528b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy { 1529b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy MagickBooleanType 1530b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status; 1531b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy 1532b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=MagickTrue; 1533b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (is_gray == MagickFalse) 1534b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=InverseFourierTransformChannel(magnitude_image, 1535d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy phase_image,GreenPixelChannel,modulus,fourier_image,exception); 1536b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (thread_status == MagickFalse) 1537b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy status=thread_status; 1538b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy } 1539b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 1540b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp section 1541b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#endif 1542b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy { 1543b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy MagickBooleanType 1544b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status; 1545b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy 1546b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=MagickTrue; 1547b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (is_gray == MagickFalse) 1548b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=InverseFourierTransformChannel(magnitude_image, 1549d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy phase_image,BluePixelChannel,modulus,fourier_image,exception); 1550b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (thread_status == MagickFalse) 1551b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy status=thread_status; 1552b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy } 1553b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 1554b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp section 1555b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#endif 1556b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy { 1557b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy MagickBooleanType 1558b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status; 1559b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy 1560b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=MagickTrue; 15614c08aed51c5899665ade97263692328eea4af106cristy if (magnitude_image->colorspace == CMYKColorspace) 1562b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=InverseFourierTransformChannel(magnitude_image, 1563d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy phase_image,BlackPixelChannel,modulus,fourier_image,exception); 1564b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (thread_status == MagickFalse) 1565b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy status=thread_status; 1566b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy } 1567b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#if defined(MAGICKCORE_OPENMP_SUPPORT) 1568b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy #pragma omp section 1569b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy#endif 1570b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy { 1571b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy MagickBooleanType 1572b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status; 1573b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy 1574b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=MagickTrue; 157517f11b056210f082a6d0e54ac5d68e6d72fa76b2cristy if (magnitude_image->alpha_trait != UndefinedPixelTrait) 1576b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy thread_status=InverseFourierTransformChannel(magnitude_image, 1577d3090f92b8f346df0a8191d5aa3f9d14be5a32d5cristy phase_image,AlphaPixelChannel,modulus,fourier_image,exception); 1578b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy if (thread_status == MagickFalse) 1579b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy status=thread_status; 15803ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 15813ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 15823ed852eea50f9d4cd633efb8c2b054b8e33c253cristy if (status == MagickFalse) 15833ed852eea50f9d4cd633efb8c2b054b8e33c253cristy fourier_image=DestroyImage(fourier_image); 15843ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 1585b34ef05f2607256ec3d54920fb4dbace9d0db20dcristy fftw_cleanup(); 15863ed852eea50f9d4cd633efb8c2b054b8e33c253cristy } 15873ed852eea50f9d4cd633efb8c2b054b8e33c253cristy#endif 15883ed852eea50f9d4cd633efb8c2b054b8e33c253cristy return(fourier_image); 15893ed852eea50f9d4cd633efb8c2b054b8e33c253cristy} 1590