Home | History | Annotate | Download | only in source
      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 /*
     38   Include declarations.
     39 */
     40 #include <stdio.h>
     41 #include <stdlib.h>
     42 #include <string.h>
     43 #include <time.h>
     44 #include <assert.h>
     45 #include <math.h>
     46 #include "magick/MagickCore.h"
     47 
     48 /*
     50 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     51 %                                                                             %
     52 %                                                                             %
     53 %                                                                             %
     54 %   a n a l y z e I m a g e                                                   %
     55 %                                                                             %
     56 %                                                                             %
     57 %                                                                             %
     58 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     59 %
     60 %  analyzeImage() computes the brightness and saturation mean,  standard
     61 %  deviation, kurtosis and skewness and stores these values as attributes
     62 %  of the image.
     63 %
     64 %  The format of the analyzeImage method is:
     65 %
     66 %      size_t analyzeImage(Image *images,const int argc,
     67 %        char **argv,ExceptionInfo *exception)
     68 %
     69 %  A description of each parameter follows:
     70 %
     71 %    o image: the address of a structure of type Image.
     72 %
     73 %    o argc: Specifies a pointer to an integer describing the number of
     74 %      elements in the argument vector.
     75 %
     76 %    o argv: Specifies a pointer to a text array containing the command line
     77 %      arguments.
     78 %
     79 %    o exception: return any errors or warnings in this structure.
     80 %
     81 */
     82 ModuleExport size_t analyzeImage(Image **images,const int argc,
     83   const char **argv,ExceptionInfo *exception)
     84 {
     85   char
     86     text[MaxTextExtent];
     87 
     88   double
     89     area,
     90     brightness,
     91     brightness_mean,
     92     brightness_standard_deviation,
     93     brightness_kurtosis,
     94     brightness_skewness,
     95     brightness_sum_x,
     96     brightness_sum_x2,
     97     brightness_sum_x3,
     98     brightness_sum_x4,
     99     hue,
    100     saturation,
    101     saturation_mean,
    102     saturation_standard_deviation,
    103     saturation_kurtosis,
    104     saturation_skewness,
    105     saturation_sum_x,
    106     saturation_sum_x2,
    107     saturation_sum_x3,
    108     saturation_sum_x4;
    109 
    110   Image
    111     *image;
    112 
    113   assert(images != (Image **) NULL);
    114   assert(*images != (Image *) NULL);
    115   assert((*images)->signature == MagickSignature);
    116   (void) argc;
    117   (void) argv;
    118   image=(*images);
    119   for ( ; image != (Image *) NULL; image=GetNextImageInList(image))
    120   {
    121     CacheView
    122       *image_view;
    123 
    124     MagickBooleanType
    125       status;
    126 
    127     ssize_t
    128       y;
    129 
    130     brightness_sum_x=0.0;
    131     brightness_sum_x2=0.0;
    132     brightness_sum_x3=0.0;
    133     brightness_sum_x4=0.0;
    134     brightness_mean=0.0;
    135     brightness_standard_deviation=0.0;
    136     brightness_kurtosis=0.0;
    137     brightness_skewness=0.0;
    138     saturation_sum_x=0.0;
    139     saturation_sum_x2=0.0;
    140     saturation_sum_x3=0.0;
    141     saturation_sum_x4=0.0;
    142     saturation_mean=0.0;
    143     saturation_standard_deviation=0.0;
    144     saturation_kurtosis=0.0;
    145     saturation_skewness=0.0;
    146     area=0.0;
    147     status=MagickTrue;
    148     image_view=AcquireCacheView(image);
    149 #if defined(MAGICKCORE_OPENMP_SUPPORT)
    150     #pragma omp parallel for schedule(dynamic,4) shared(status)
    151 #endif
    152     for (y=0; y < (ssize_t) image->rows; y++)
    153     {
    154       register const PixelPacket
    155         *p;
    156 
    157       register ssize_t
    158         x;
    159 
    160       if (status == MagickFalse)
    161         continue;
    162       p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
    163       if (p == (const PixelPacket *) NULL)
    164         {
    165           status=MagickFalse;
    166           continue;
    167         }
    168       for (x=0; x < (ssize_t) image->columns; x++)
    169       {
    170         ConvertRGBToHSB(GetPixelRed(p),GetPixelGreen(p),
    171           GetPixelBlue(p),&hue,&saturation,&brightness);
    172         brightness*=QuantumRange;
    173         brightness_sum_x+=brightness;
    174         brightness_sum_x2+=brightness*brightness;
    175         brightness_sum_x3+=brightness*brightness*brightness;
    176         brightness_sum_x4+=brightness*brightness*brightness*brightness;
    177         saturation*=QuantumRange;
    178         saturation_sum_x+=saturation;
    179         saturation_sum_x2+=saturation*saturation;
    180         saturation_sum_x3+=saturation*saturation*saturation;
    181         saturation_sum_x4+=saturation*saturation*saturation*saturation;
    182         area++;
    183         p++;
    184       }
    185     }
    186     image_view=DestroyCacheView(image_view);
    187     if (area <= 0.0)
    188       break;
    189     brightness_mean=brightness_sum_x/area;
    190     (void) FormatMagickString(text,MaxTextExtent,"%g",brightness_mean);
    191     (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) FormatMagickString(text,MaxTextExtent,"%g",
    195       brightness_standard_deviation);
    196     (void) SetImageProperty(image,"filter:brightness:standard-deviation",text);
    197     if (brightness_standard_deviation != 0)
    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) FormatMagickString(text,MaxTextExtent,"%g",brightness_kurtosis);
    205     (void) SetImageProperty(image,"filter:brightness:kurtosis",text);
    206     if (brightness_standard_deviation != 0)
    207       brightness_skewness=(brightness_sum_x3/area-3.0*brightness_mean*
    208         brightness_sum_x2/area+2.0*brightness_mean*brightness_mean*
    209         brightness_mean)/(brightness_standard_deviation*
    210         brightness_standard_deviation*brightness_standard_deviation);
    211     (void) FormatMagickString(text,MaxTextExtent,"%g",brightness_skewness);
    212     (void) SetImageProperty(image,"filter:brightness:skewness",text);
    213     saturation_mean=saturation_sum_x/area;
    214     (void) FormatMagickString(text,MaxTextExtent,"%g",saturation_mean);
    215     (void) SetImageProperty(image,"filter:saturation:mean",text);
    216     saturation_standard_deviation=sqrt(saturation_sum_x2/area-(saturation_sum_x/
    217       area*saturation_sum_x/area));
    218     (void) FormatMagickString(text,MaxTextExtent,"%g",
    219       saturation_standard_deviation);
    220     (void) SetImageProperty(image,"filter:saturation:standard-deviation",text);
    221     if (saturation_standard_deviation != 0)
    222       saturation_kurtosis=(saturation_sum_x4/area-4.0*saturation_mean*
    223         saturation_sum_x3/area+6.0*saturation_mean*saturation_mean*
    224         saturation_sum_x2/area-3.0*saturation_mean*saturation_mean*
    225         saturation_mean*saturation_mean)/(saturation_standard_deviation*
    226         saturation_standard_deviation*saturation_standard_deviation*
    227         saturation_standard_deviation)-3.0;
    228     (void) FormatMagickString(text,MaxTextExtent,"%g",saturation_kurtosis);
    229     (void) SetImageProperty(image,"filter:saturation:kurtosis",text);
    230     if (saturation_standard_deviation != 0)
    231       saturation_skewness=(saturation_sum_x3/area-3.0*saturation_mean*
    232         saturation_sum_x2/area+2.0*saturation_mean*saturation_mean*
    233         saturation_mean)/(saturation_standard_deviation*
    234         saturation_standard_deviation*saturation_standard_deviation);
    235     (void) FormatMagickString(text,MaxTextExtent,"%g",saturation_skewness);
    236     (void) SetImageProperty(image,"filter:saturation:skewness",text);
    237   }
    238   return(MagickImageFilterSignature);
    239 }
    240