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