]> granicus.if.org Git - imagemagick/blob - filters/analyze.c
...
[imagemagick] / filters / analyze.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
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               %
10 %                                                                             %
11 %                             Analyze An Image                                %
12 %                                                                             %
13 %                             Software Design                                 %
14 %                               Bill Corbis                                   %
15 %                              December 1998                                  %
16 %                                                                             %
17 %                                                                             %
18 %  Copyright 1999-2018 ImageMagick Studio LLC, a non-profit organization      %
19 %  dedicated to making software imaging solutions freely available.           %
20 %                                                                             %
21 %  You may not use this file except in compliance with the License.  You may  %
22 %  obtain a copy of the License at                                            %
23 %                                                                             %
24 %    https://imagemagick.org/script/license.php                               %
25 %                                                                             %
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.                                             %
31 %                                                                             %
32 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33 %
34 */
35 \f
36 /*
37   Include declarations.
38 */
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <time.h>
43 #include <assert.h>
44 #include <math.h>
45 #include "MagickCore/MagickCore.h"
46 \f
47 /*
48 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
49 %                                                                             %
50 %                                                                             %
51 %                                                                             %
52 %   a n a l y z e I m a g e                                                   %
53 %                                                                             %
54 %                                                                             %
55 %                                                                             %
56 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
57 %
58 %  analyzeImage() computes the brightness and saturation mean,  standard
59 %  deviation, kurtosis and skewness and stores these values as attributes 
60 %  of the image.
61 %
62 %  The format of the analyzeImage method is:
63 %
64 %      size_t analyzeImage(Image *images,const int argc,
65 %        char **argv,ExceptionInfo *exception)
66 %
67 %  A description of each parameter follows:
68 %
69 %    o image: the address of a structure of type Image.
70 %
71 %    o argc: Specifies a pointer to an integer describing the number of
72 %      elements in the argument vector.
73 %
74 %    o argv: Specifies a pointer to a text array containing the command line
75 %      arguments.
76 %
77 %    o exception: return any errors or warnings in this structure.
78 %
79 */
80 ModuleExport size_t analyzeImage(Image **images,const int argc,
81   const char **argv,ExceptionInfo *exception)
82 {
83   char
84     text[MagickPathExtent];
85
86   double
87     area,
88     brightness,
89     brightness_mean,
90     brightness_standard_deviation,
91     brightness_kurtosis,
92     brightness_skewness,
93     brightness_sum_x,
94     brightness_sum_x2,
95     brightness_sum_x3,
96     brightness_sum_x4,
97     hue,
98     saturation,
99     saturation_mean,
100     saturation_standard_deviation,
101     saturation_kurtosis,
102     saturation_skewness,
103     saturation_sum_x,
104     saturation_sum_x2,
105     saturation_sum_x3,
106     saturation_sum_x4;
107
108   Image
109     *image;
110
111   assert(images != (Image **) NULL);
112   assert(*images != (Image *) NULL);
113   assert((*images)->signature == MagickCoreSignature);
114   (void) argc;
115   (void) argv;
116   image=(*images);
117   for ( ; image != (Image *) NULL; image=GetNextImageInList(image))
118   {
119     CacheView
120       *image_view;
121
122     ssize_t
123       y;
124
125     MagickBooleanType
126       status;
127
128     brightness_sum_x=0.0;
129     brightness_sum_x2=0.0;
130     brightness_sum_x3=0.0;
131     brightness_sum_x4=0.0;
132     brightness_mean=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;
140     saturation_mean=0.0;
141     saturation_standard_deviation=0.0;
142     saturation_kurtosis=0.0;
143     saturation_skewness=0.0;
144     area=0.0;
145     status=MagickTrue;
146     image_view=AcquireVirtualCacheView(image,exception);
147 #if defined(MAGICKCORE_OPENMP_SUPPORT)
148     #pragma omp parallel for schedule(static) shared(status) \
149       magick_number_threads(image,image,image->rows,1)
150 #endif
151     for (y=0; y < (ssize_t) image->rows; y++)
152     {
153       register const Quantum
154         *p;
155
156       register ssize_t
157         x;
158
159       if (status == MagickFalse)
160         continue;
161       p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
162       if (p == (const Quantum *) NULL)
163         {
164           status=MagickFalse;
165           continue;
166         }
167       for (x=0; x < (ssize_t) image->columns; x++)
168       {
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;
181         area++;
182         p+=GetPixelChannels(image);
183       }
184     }
185     image_view=DestroyCacheView(image_view);
186     if (area <= 0.0)
187       break;
188     brightness_mean=brightness_sum_x/area;
189     (void) FormatLocaleString(text,MagickPathExtent,"%g",brightness_mean);
190     (void) SetImageProperty(image,"filter:brightness:mean",text,
191       exception);
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,
197       exception);
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,
207       exception);
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,
215       exception);
216     saturation_mean=saturation_sum_x/area;
217     (void) FormatLocaleString(text,MagickPathExtent,"%g",saturation_mean);
218     (void) SetImageProperty(image,"filter:saturation:mean",text,
219       exception);
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,
225       exception);
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,
235       exception);
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,
243       exception);
244   }
245   return(MagickImageFilterSignature);
246 }