Home | History | Annotate | Download | only in filters
      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-2016 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 "MagickCore/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[MagickPathExtent];
     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 == MagickCoreSignature);
    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     ssize_t
    125       y;
    126 
    127     MagickBooleanType
    128       status;
    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=AcquireVirtualCacheView(image,exception);
    149 #if defined(MAGICKCORE_OPENMP_SUPPORT)
    150     #pragma omp parallel for schedule(static,4) shared(status) \
    151       magick_threads(image,image,image->rows,1)
    152 #endif
    153     for (y=0; y < (ssize_t) image->rows; y++)
    154     {
    155       register const Quantum
    156         *p;
    157 
    158       register ssize_t
    159         x;
    160 
    161       if (status == MagickFalse)
    162         continue;
    163       p=GetCacheViewVirtualPixels(image_view,0,y,image->columns,1,exception);
    164       if (p == (const Quantum *) NULL)
    165         {
    166           status=MagickFalse;
    167           continue;
    168         }
    169       for (x=0; x < (ssize_t) image->columns; x++)
    170       {
    171         ConvertRGBToHSL(GetPixelRed(image,p),GetPixelGreen(image,p),
    172           GetPixelBlue(image,p),&hue,&saturation,&brightness);
    173         brightness*=QuantumRange;
    174         brightness_sum_x+=brightness;
    175         brightness_sum_x2+=brightness*brightness;
    176         brightness_sum_x3+=brightness*brightness*brightness;
    177         brightness_sum_x4+=brightness*brightness*brightness*brightness;
    178         saturation*=QuantumRange;
    179         saturation_sum_x+=saturation;
    180         saturation_sum_x2+=saturation*saturation;
    181         saturation_sum_x3+=saturation*saturation*saturation;
    182         saturation_sum_x4+=saturation*saturation*saturation*saturation;
    183         area++;
    184         p+=GetPixelChannels(image);
    185       }
    186     }
    187     image_view=DestroyCacheView(image_view);
    188     if (area <= 0.0)
    189       break;
    190     brightness_mean=brightness_sum_x/area;
    191     (void) FormatLocaleString(text,MagickPathExtent,"%g",brightness_mean);
    192     (void) SetImageProperty(image,"filter:brightness:mean",text,
    193       exception);
    194     brightness_standard_deviation=sqrt(brightness_sum_x2/area-(brightness_sum_x/
    195       area*brightness_sum_x/area));
    196     (void) FormatLocaleString(text,MagickPathExtent,"%g",
    197       brightness_standard_deviation);
    198     (void) SetImageProperty(image,"filter:brightness:standard-deviation",text,
    199       exception);
    200     if (fabs(brightness_standard_deviation) >= MagickEpsilon)
    201       brightness_kurtosis=(brightness_sum_x4/area-4.0*brightness_mean*
    202         brightness_sum_x3/area+6.0*brightness_mean*brightness_mean*
    203         brightness_sum_x2/area-3.0*brightness_mean*brightness_mean*
    204         brightness_mean*brightness_mean)/(brightness_standard_deviation*
    205         brightness_standard_deviation*brightness_standard_deviation*
    206         brightness_standard_deviation)-3.0;
    207     (void) FormatLocaleString(text,MagickPathExtent,"%g",brightness_kurtosis);
    208     (void) SetImageProperty(image,"filter:brightness:kurtosis",text,
    209       exception);
    210     if (brightness_standard_deviation != 0)
    211       brightness_skewness=(brightness_sum_x3/area-3.0*brightness_mean*
    212         brightness_sum_x2/area+2.0*brightness_mean*brightness_mean*
    213         brightness_mean)/(brightness_standard_deviation*
    214         brightness_standard_deviation*brightness_standard_deviation);
    215     (void) FormatLocaleString(text,MagickPathExtent,"%g",brightness_skewness);
    216     (void) SetImageProperty(image,"filter:brightness:skewness",text,
    217       exception);
    218     saturation_mean=saturation_sum_x/area;
    219     (void) FormatLocaleString(text,MagickPathExtent,"%g",saturation_mean);
    220     (void) SetImageProperty(image,"filter:saturation:mean",text,
    221       exception);
    222     saturation_standard_deviation=sqrt(saturation_sum_x2/area-(saturation_sum_x/
    223       area*saturation_sum_x/area));
    224     (void) FormatLocaleString(text,MagickPathExtent,"%g",
    225       saturation_standard_deviation);
    226     (void) SetImageProperty(image,"filter:saturation:standard-deviation",text,
    227       exception);
    228     if (fabs(saturation_standard_deviation) >= MagickEpsilon)
    229       saturation_kurtosis=(saturation_sum_x4/area-4.0*saturation_mean*
    230         saturation_sum_x3/area+6.0*saturation_mean*saturation_mean*
    231         saturation_sum_x2/area-3.0*saturation_mean*saturation_mean*
    232         saturation_mean*saturation_mean)/(saturation_standard_deviation*
    233         saturation_standard_deviation*saturation_standard_deviation*
    234         saturation_standard_deviation)-3.0;
    235     (void) FormatLocaleString(text,MagickPathExtent,"%g",saturation_kurtosis);
    236     (void) SetImageProperty(image,"filter:saturation:kurtosis",text,
    237       exception);
    238     if (fabs(saturation_standard_deviation) >= MagickEpsilon)
    239       saturation_skewness=(saturation_sum_x3/area-3.0*saturation_mean*
    240         saturation_sum_x2/area+2.0*saturation_mean*saturation_mean*
    241         saturation_mean)/(saturation_standard_deviation*
    242         saturation_standard_deviation*saturation_standard_deviation);
    243     (void) FormatLocaleString(text,MagickPathExtent,"%g",saturation_skewness);
    244     (void) SetImageProperty(image,"filter:saturation:skewness",text,
    245       exception);
    246   }
    247   return(MagickImageFilterSignature);
    248 }
    249