analyze.c revision d15e65928aec551b7388c2863de3e3e628e2e0dd
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-2011 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%    http://www.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
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
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*/
80ModuleExport size_t analyzeImage(Image **images,const int argc,
81  const char **argv,ExceptionInfo *exception)
82{
83  char
84    text[MaxTextExtent];
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 == MagickSignature);
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=AcquireCacheView(image);
147#if defined(MAGICKCORE_OPENMP_SUPPORT)
148    #pragma omp parallel for schedule(dynamic,4) shared(status)
149#endif
150    for (y=0; y < (ssize_t) image->rows; y++)
151    {
152      register const Quantum
153        *p;
154
155      register ssize_t
156        x;
157
158      if (status == MagickFalse)
159        continue;
160      p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
161      if (p == (const Quantum *) NULL)
162        {
163          status=MagickFalse;
164          continue;
165        }
166      for (x=0; x < (ssize_t) image->columns; x++)
167      {
168        ConvertRGBToHSL(GetPixelRed(image,p),GetPixelGreen(image,p),
169          GetPixelBlue(image,p),&hue,&saturation,&brightness);
170        brightness*=QuantumRange;
171        brightness_sum_x+=brightness;
172        brightness_sum_x2+=brightness*brightness;
173        brightness_sum_x3+=brightness*brightness*brightness;
174        brightness_sum_x4+=brightness*brightness*brightness*brightness;
175        saturation*=QuantumRange;
176        saturation_sum_x+=saturation;
177        saturation_sum_x2+=saturation*saturation;
178        saturation_sum_x3+=saturation*saturation*saturation;
179        saturation_sum_x4+=saturation*saturation*saturation*saturation;
180        area++;
181        p+=GetPixelChannels(image);
182      }
183    }
184    image_view=DestroyCacheView(image_view);
185    if (area <= 0.0)
186      break;
187    brightness_mean=brightness_sum_x/area;
188    (void) FormatLocaleString(text,MaxTextExtent,"%g",brightness_mean);
189    (void) SetImageProperty(image,"filter:brightness:mean",text,
190      exception);
191    brightness_standard_deviation=sqrt(brightness_sum_x2/area-(brightness_sum_x/
192      area*brightness_sum_x/area));
193    (void) FormatLocaleString(text,MaxTextExtent,"%g",
194      brightness_standard_deviation);
195    (void) SetImageProperty(image,"filter:brightness:standard-deviation",text,
196      exception);
197    if (fabs(brightness_standard_deviation) >= MagickEpsilon)
198      brightness_kurtosis=(brightness_sum_x4/area-4.0*brightness_mean*
199        brightness_sum_x3/area+6.0*brightness_mean*brightness_mean*
200        brightness_sum_x2/area-3.0*brightness_mean*brightness_mean*
201        brightness_mean*brightness_mean)/(brightness_standard_deviation*
202        brightness_standard_deviation*brightness_standard_deviation*
203        brightness_standard_deviation)-3.0;
204    (void) FormatLocaleString(text,MaxTextExtent,"%g",brightness_kurtosis);
205    (void) SetImageProperty(image,"filter:brightness:kurtosis",text,
206      exception);
207    if (brightness_standard_deviation != 0)
208      brightness_skewness=(brightness_sum_x3/area-3.0*brightness_mean*
209        brightness_sum_x2/area+2.0*brightness_mean*brightness_mean*
210        brightness_mean)/(brightness_standard_deviation*
211        brightness_standard_deviation*brightness_standard_deviation);
212    (void) FormatLocaleString(text,MaxTextExtent,"%g",brightness_skewness);
213    (void) SetImageProperty(image,"filter:brightness:skewness",text,
214      exception);
215    saturation_mean=saturation_sum_x/area;
216    (void) FormatLocaleString(text,MaxTextExtent,"%g",saturation_mean);
217    (void) SetImageProperty(image,"filter:saturation:mean",text,
218      exception);
219    saturation_standard_deviation=sqrt(saturation_sum_x2/area-(saturation_sum_x/
220      area*saturation_sum_x/area));
221    (void) FormatLocaleString(text,MaxTextExtent,"%g",
222      saturation_standard_deviation);
223    (void) SetImageProperty(image,"filter:saturation:standard-deviation",text,
224      exception);
225    if (fabs(saturation_standard_deviation) >= MagickEpsilon)
226      saturation_kurtosis=(saturation_sum_x4/area-4.0*saturation_mean*
227        saturation_sum_x3/area+6.0*saturation_mean*saturation_mean*
228        saturation_sum_x2/area-3.0*saturation_mean*saturation_mean*
229        saturation_mean*saturation_mean)/(saturation_standard_deviation*
230        saturation_standard_deviation*saturation_standard_deviation*
231        saturation_standard_deviation)-3.0;
232    (void) FormatLocaleString(text,MaxTextExtent,"%g",saturation_kurtosis);
233    (void) SetImageProperty(image,"filter:saturation:kurtosis",text,
234      exception);
235    if (fabs(saturation_standard_deviation) >= MagickEpsilon)
236      saturation_skewness=(saturation_sum_x3/area-3.0*saturation_mean*
237        saturation_sum_x2/area+2.0*saturation_mean*saturation_mean*
238        saturation_mean)/(saturation_standard_deviation*
239        saturation_standard_deviation*saturation_standard_deviation);
240    (void) FormatLocaleString(text,MaxTextExtent,"%g",saturation_skewness);
241    (void) SetImageProperty(image,"filter:saturation:skewness",text,
242      exception);
243  }
244  return(MagickImageFilterSignature);
245}
246