2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5 % AAA N N AAA L Y Y ZZZZZ EEEEE %
6 % A A NN N A A L Y Y ZZ E %
7 % AAAAA N N N AAAAA L Y ZZZ EEE %
8 % A A N NN A A L Y ZZ E %
9 % A A N N A A LLLLL Y ZZZZZ EEEEE %
18 % Copyright 1999-2017 ImageMagick Studio LLC, a non-profit organization %
19 % dedicated to making software imaging solutions freely available. %
21 % You may not use this file except in compliance with the License. You may %
22 % obtain a copy of the License at %
24 % http://www.imagemagick.org/script/license.php %
26 % Unless required by applicable law or agreed to in writing, software %
27 % distributed under the License is distributed on an "AS IS" BASIS, %
28 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
29 % See the License for the specific language governing permissions and %
30 % limitations under the License. %
32 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
45 #include "MagickCore/MagickCore.h"
48 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
52 % a n a l y z e I m a g e %
56 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
58 % analyzeImage() computes the brightness and saturation mean, standard
59 % deviation, kurtosis and skewness and stores these values as attributes
62 % The format of the analyzeImage method is:
64 % size_t analyzeImage(Image *images,const int argc,
65 % char **argv,ExceptionInfo *exception)
67 % A description of each parameter follows:
69 % o image: the address of a structure of type Image.
71 % o argc: Specifies a pointer to an integer describing the number of
72 % elements in the argument vector.
74 % o argv: Specifies a pointer to a text array containing the command line
77 % o exception: return any errors or warnings in this structure.
80 ModuleExport size_t analyzeImage(Image **images,const int argc,
81 const char **argv,ExceptionInfo *exception)
84 text[MagickPathExtent];
90 brightness_standard_deviation,
100 saturation_standard_deviation,
111 assert(images != (Image **) NULL);
112 assert(*images != (Image *) NULL);
113 assert((*images)->signature == MagickCoreSignature);
117 for ( ; image != (Image *) NULL; image=GetNextImageInList(image))
128 brightness_sum_x=0.0;
129 brightness_sum_x2=0.0;
130 brightness_sum_x3=0.0;
131 brightness_sum_x4=0.0;
133 brightness_standard_deviation=0.0;
134 brightness_kurtosis=0.0;
135 brightness_skewness=0.0;
136 saturation_sum_x=0.0;
137 saturation_sum_x2=0.0;
138 saturation_sum_x3=0.0;
139 saturation_sum_x4=0.0;
141 saturation_standard_deviation=0.0;
142 saturation_kurtosis=0.0;
143 saturation_skewness=0.0;
146 image_view=AcquireVirtualCacheView(image,exception);
147 #if defined(MAGICKCORE_OPENMP_SUPPORT)
148 #pragma omp parallel for schedule(static,4) shared(status) \
149 magick_threads(image,image,image->rows,1)
151 for (y=0; y < (ssize_t) image->rows; y++)
153 register const Quantum
159 if (status == MagickFalse)
161 p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
162 if (p == (const Quantum *) NULL)
167 for (x=0; x < (ssize_t) image->columns; x++)
169 ConvertRGBToHSL(GetPixelRed(image,p),GetPixelGreen(image,p),
170 GetPixelBlue(image,p),&hue,&saturation,&brightness);
171 brightness*=QuantumRange;
172 brightness_sum_x+=brightness;
173 brightness_sum_x2+=brightness*brightness;
174 brightness_sum_x3+=brightness*brightness*brightness;
175 brightness_sum_x4+=brightness*brightness*brightness*brightness;
176 saturation*=QuantumRange;
177 saturation_sum_x+=saturation;
178 saturation_sum_x2+=saturation*saturation;
179 saturation_sum_x3+=saturation*saturation*saturation;
180 saturation_sum_x4+=saturation*saturation*saturation*saturation;
182 p+=GetPixelChannels(image);
185 image_view=DestroyCacheView(image_view);
188 brightness_mean=brightness_sum_x/area;
189 (void) FormatLocaleString(text,MagickPathExtent,"%g",brightness_mean);
190 (void) SetImageProperty(image,"filter:brightness:mean",text,
192 brightness_standard_deviation=sqrt(brightness_sum_x2/area-(brightness_sum_x/
193 area*brightness_sum_x/area));
194 (void) FormatLocaleString(text,MagickPathExtent,"%g",
195 brightness_standard_deviation);
196 (void) SetImageProperty(image,"filter:brightness:standard-deviation",text,
198 if (fabs(brightness_standard_deviation) >= MagickEpsilon)
199 brightness_kurtosis=(brightness_sum_x4/area-4.0*brightness_mean*
200 brightness_sum_x3/area+6.0*brightness_mean*brightness_mean*
201 brightness_sum_x2/area-3.0*brightness_mean*brightness_mean*
202 brightness_mean*brightness_mean)/(brightness_standard_deviation*
203 brightness_standard_deviation*brightness_standard_deviation*
204 brightness_standard_deviation)-3.0;
205 (void) FormatLocaleString(text,MagickPathExtent,"%g",brightness_kurtosis);
206 (void) SetImageProperty(image,"filter:brightness:kurtosis",text,
208 if (brightness_standard_deviation != 0)
209 brightness_skewness=(brightness_sum_x3/area-3.0*brightness_mean*
210 brightness_sum_x2/area+2.0*brightness_mean*brightness_mean*
211 brightness_mean)/(brightness_standard_deviation*
212 brightness_standard_deviation*brightness_standard_deviation);
213 (void) FormatLocaleString(text,MagickPathExtent,"%g",brightness_skewness);
214 (void) SetImageProperty(image,"filter:brightness:skewness",text,
216 saturation_mean=saturation_sum_x/area;
217 (void) FormatLocaleString(text,MagickPathExtent,"%g",saturation_mean);
218 (void) SetImageProperty(image,"filter:saturation:mean",text,
220 saturation_standard_deviation=sqrt(saturation_sum_x2/area-(saturation_sum_x/
221 area*saturation_sum_x/area));
222 (void) FormatLocaleString(text,MagickPathExtent,"%g",
223 saturation_standard_deviation);
224 (void) SetImageProperty(image,"filter:saturation:standard-deviation",text,
226 if (fabs(saturation_standard_deviation) >= MagickEpsilon)
227 saturation_kurtosis=(saturation_sum_x4/area-4.0*saturation_mean*
228 saturation_sum_x3/area+6.0*saturation_mean*saturation_mean*
229 saturation_sum_x2/area-3.0*saturation_mean*saturation_mean*
230 saturation_mean*saturation_mean)/(saturation_standard_deviation*
231 saturation_standard_deviation*saturation_standard_deviation*
232 saturation_standard_deviation)-3.0;
233 (void) FormatLocaleString(text,MagickPathExtent,"%g",saturation_kurtosis);
234 (void) SetImageProperty(image,"filter:saturation:kurtosis",text,
236 if (fabs(saturation_standard_deviation) >= MagickEpsilon)
237 saturation_skewness=(saturation_sum_x3/area-3.0*saturation_mean*
238 saturation_sum_x2/area+2.0*saturation_mean*saturation_mean*
239 saturation_mean)/(saturation_standard_deviation*
240 saturation_standard_deviation*saturation_standard_deviation);
241 (void) FormatLocaleString(text,MagickPathExtent,"%g",saturation_skewness);
242 (void) SetImageProperty(image,"filter:saturation:skewness",text,
245 return(MagickImageFilterSignature);