source: extensions/Histogram/hgram_histogram.class.inc.php @ 11529

Last change on this file since 11529 was 8511, checked in by grum, 13 years ago

Fix language key + minor bug on histogram rendering

  • Property svn:executable set to *
File size: 10.4 KB
Line 
1<?php
2/* -----------------------------------------------------------------------------
3  Plugin     : Histogram
4  Author     : Grum
5    email    : grum@grum.fr
6    website  : http://photos.grum.fr
7    PWG user : http://forum.piwigo.org/profile.php?id=3706
8
9    << May the Little SpaceFrog be with you ! >>
10  ------------------------------------------------------------------------------
11  See main.inc.php for release information
12
13  Provided classes :
14
15
16  --------------------------------------------------------------------------- */
17
18if(!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
19
20
21
22class Histogram {
23  static public $fileHistogram = Array(
24    'pixels' => 0,
25    'analyzed' => 0,
26    'time' => 0,
27    'fileName' => "",
28  );
29
30  /**
31   * returns histogram values for an image
32   *
33   *
34   * @param String $fileName : the picture's filename
35   * @return : -1 if file doesn't exist
36   *           -2 if file is not a PNG, a JPEG or a GIF file
37   *           -3 if a fatal error occurs
38   *            Array of L, R, G, and B values (% for values from 0 to 255)
39   */
40  static function read($fileName)
41  {
42    self::$fileHistogram=Array(
43      'pixels'   => 0,
44      'analyzed' => 0,
45      'time' => 0,
46      'pps' =>0,
47    );
48
49    $returned=array(
50      'L' => array(),
51      'A' => array(),
52      'M' => array(),
53      'R' => array(),
54      'G' => array(),
55      'B' => array()
56    );
57
58    for($i=0;$i<256;$i++)
59    {
60      $returned['L'][$i]=0;
61      $returned['A'][$i]=0;
62      $returned['M'][$i]=0;
63      $returned['R'][$i]=0;
64      $returned['G'][$i]=0;
65      $returned['B'][$i]=0;
66    }
67
68    if(file_exists($fileName))
69    {
70      $time=microtime(true);
71
72      try
73      {
74        if(preg_match('/.*\.gif$/i', $fileName))
75        {
76          $image = imagecreatefromgif($fileName);
77        }
78        elseif(preg_match('/.*\.(jpg|jpeg)$/i', $fileName))
79        {
80          $image = imagecreatefromjpeg($fileName);
81        }
82        elseif(preg_match('/.*\.png$/i', $fileName))
83        {
84          $image = imagecreatefrompng($fileName);
85        }
86        else
87        {
88          return(-2);
89        }
90
91        $imageWidth=imagesx($image);
92        $imageHeight=imagesy($image);
93
94        $i=0;
95        for($px=0;$px<$imageWidth;$px++)
96        {
97          for($py=0;$py<$imageHeight;$py++)
98          {
99            $i++;
100            $value=imagecolorat($image, $px, $py);
101
102            $rgb=self::IntToRGB($value);
103            $l=self::RGBtoL($rgb);
104            $a=self::RGBtoA($rgb);
105            $m=self::RGBtoM($rgb);
106
107            $returned['L'][$l]++;
108            $returned['A'][$a]++;
109            $returned['M'][$m]++;
110            $returned['R'][$rgb['R']]++;
111            $returned['G'][$rgb['G']]++;
112            $returned['B'][$rgb['B']]++;
113
114            unset($rgb);
115          }
116        }
117
118        imagedestroy($image);
119
120        self::$fileHistogram=Array(
121          'pixels'   => $imageWidth*$imageHeight,
122          'analyzed' => $i,
123          'time'     => microtime(true)-$time,
124          'pps'      => $i/(microtime(true)-$time),
125        );
126
127        ksort($returned['L']);
128        ksort($returned['A']);
129        ksort($returned['M']);
130        ksort($returned['R']);
131        ksort($returned['G']);
132        ksort($returned['B']);
133
134        foreach($returned as $key => $val)
135        {
136          $m=max($returned[$key]);
137          foreach($returned[$key] as $key2 => $val2)
138          {
139            $returned[$key][$key2]=round($val2/$m,4);
140          }
141        }
142
143        return($returned);
144      }
145      catch (Exception $e)
146      {
147        //echo "ERROR!<br>".print_r($e, true);
148        return(-3);
149      }
150    }
151    else
152    {
153      return(-1);
154    }
155  }
156
157
158  /**
159   * build the histogram and save it in an image file
160   *
161   * @param String $fileName : the histogram filename
162   * @param Array $values : array('L', 'R', 'G', 'B') of values
163   * @param Array $options : array of options for histogram rendering
164   *                'color_bg' : background color
165   *                'color_l'  : color for luminance drawing
166   *                'color_r'  : color for red drawing
167   *                'color_g'  : color for green drawing
168   *                'color_b'  : color for blue drawing
169   *                'color_ticks'  : color for ticks drawing
170   *                'mode_l'   : drawing mode for luminance
171   *                'mode_r'   : drawing mode for luminance
172   *                'mode_g'   : drawing mode for luminance
173   *                'mode_b'   : drawing mode for luminance
174   *                  => modes can takes 'line' or 'bar' or 'surface' or 'none' values
175   *                'mode_ticks_h' : drawing mode for horizontal ticks
176   *                'mode_ticks_v' : drawing mode for vertical ticks
177   *                  => can takes 'none' or 'dot' or 'solid'
178   *                'histo_width' : histogram width
179   *                'histo_height' : histogram height
180   */
181  static function build($fileName, $values, $options=array())
182  {
183    $options=self::checkHistoOptions($options);
184
185    $image=imagecreatetruecolor($options['histo_width'], $options['histo_height']);
186    $options['color_bg']=self::colorAllocate($image, $options['color_bg']);
187    $options['color_v']=self::colorAllocate($image, $options['color_v']);
188    $options['color_r']=self::colorAllocate($image, $options['color_r']);
189    $options['color_g']=self::colorAllocate($image, $options['color_g']);
190    $options['color_b']=self::colorAllocate($image, $options['color_b']);
191
192    imagefilledrectangle($image,0,0,$options['histo_width'], $options['histo_height'], $options['color_bg']);
193
194
195    $histoList=array('v', 'r', 'g', 'b');
196
197
198    foreach($histoList as $histo)
199    {
200      switch($options['mode_'.$histo])
201      {
202        case 'line':
203        case 'surface':
204          $points=array(0,$options['histo_height']);
205          if($histo=='v')
206          {
207            $histoKey=$options['histo_method'];
208          }
209          else
210          {
211            $histoKey=$histo;
212          }
213
214          foreach($values[strtoupper($histoKey)] as $key => $histoValue)
215          {
216            $points[]=$key * $options['histo_width']/255;
217            $points[]=$options['histo_height'] - $histoValue * $options['histo_height'];
218          }
219          $points[]=$options['histo_width'];
220          $points[]=$options['histo_height'];
221
222          if($options['mode_'.$histo]=='line')
223          {
224            imagepolygon($image,$points, count($points)/2, $options['color_'.$histo]);
225          }
226          else
227          {
228            imagefilledpolygon($image,$points, count($points)/2, $options['color_'.$histo]);
229          }
230          break;
231        case 'bar':
232          break;
233      }
234    }
235
236    imagepng($image, $fileName);
237    imagedestroy($image);
238  }
239
240
241  /**
242   *  Calculate the Luminance value from a RGB value
243   *
244   * @param Array $RGB : RGB object
245   * @return Integer : luminance color
246   */
247  static public function RGBtoL($RGB)
248  {
249    return(round($RGB['R']*0.299+$RGB['G']*0.587+$RGB['B']*0.114,0));
250  }
251
252  /**
253   *  Calculate the average grey value from a RGB value
254   *
255   * @param Array $RGB : RGB object
256   * @return Integer : average grey color
257   */
258  static public function RGBtoA($RGB)
259  {
260    return(round(($RGB['R']+$RGB['G']+$RGB['B'])/3,0));
261  }
262
263
264  /**
265   *  Calculate the max value from a RGB value
266   *
267   * @param Array $RGB : RGB object
268   * @return Integer : the max value
269   */
270  static public function RGBtoM($RGB)
271  {
272    return(max($RGB));
273  }
274
275
276  /**
277   *
278   * @param Int $rgb : an integer &hRRGGBB
279   * @return RGB : a RGB object
280   */
281  static public function IntToRGB($rgb)
282  {
283    return(
284      Array(
285        'R' => ($rgb >> 16) & 0xFF,
286        'G' => ($rgb >> 8) & 0xFF,
287        'B' => $rgb & 0xFF
288      )
289    );
290  }
291
292  /**
293   * convert a string like #rrggbb into a RGB array
294   *
295   * @param String $rgb : a #rrggbb string
296   * @return Array
297   */
298  static public function StringToRGB($rgb)
299  {
300    $returned=array(
301      'R' => 0,
302      'G' => 0,
303      'B' => 0
304    );
305
306    if(preg_match_all('/^#([A-F0-9]{2})([A-F0-9]{2})([A-F0-9]{2})$/i', $rgb, $values, PREG_SET_ORDER)>0)
307    {
308      $returned['R']=intval('0x'.$values[0][1],0);
309      $returned['G']=intval('0x'.$values[0][2],0);
310      $returned['B']=intval('0x'.$values[0][3],0);
311    }
312
313    return($returned);
314  }
315
316  /**
317   * convert a RGB array ('R'=>r, 'G'=>g, 'B'=>b ) into integer value
318   *
319   * @param Array $rgb : rgb array
320   * @return Integer
321   */
322  static public function RGBToInt($rgb)
323  {
324    return($rgb['R']*65536 + $rgb['G']*256 + $rgb['B']);
325  }
326
327  /**
328   * convert a RGB array ('R'=>r, 'G'=>g, 'B'=>b ) into string #rrggbb value
329   *
330   * @param Array $rgb : rgb array
331   * @return String
332   */
333  static public function RGBToString($rgb)
334  {
335    return(
336      sprintf('#%02X%02X%02X', $rgb['R'], $rgb['G'], $rgb['B'])
337    );
338  }
339
340  static public function checkHistoOptions($options)
341  {
342    if(!isset($options['color_bg']) or !is_numeric($options['color_bg'])) $options['color_bg']=0xffffff;
343    if(!isset($options['color_v']) or !is_numeric($options['color_v'])) $options['color_v']=0x808080;
344    if(!isset($options['color_r']) or !is_numeric($options['color_r'])) $options['color_r']=0xA00000;
345    if(!isset($options['color_g']) or !is_numeric($options['color_g'])) $options['color_g']=0x00A000;
346    if(!isset($options['color_b']) or !is_numeric($options['color_b'])) $options['color_b']=0x0000A0;
347
348    $modes=array('surface', 'line', 'bar', 'none');
349    if(!isset($options['mode_v']) or !in_array($options['mode_v'], $modes)) $options['mode_v']='surface';
350    if(!isset($options['mode_r']) or !in_array($options['mode_r'], $modes)) $options['mode_r']='line';
351    if(!isset($options['mode_g']) or !in_array($options['mode_g'], $modes)) $options['mode_g']='line';
352    if(!isset($options['mode_b']) or !in_array($options['mode_b'], $modes)) $options['mode_b']='line';
353
354    if(!isset($options['histo_width']) or !is_numeric($options['histo_width']) or $options['histo_width']<=0) $options['histo_width']=256;
355    if(!isset($options['histo_height']) or !is_numeric($options['histo_height']) or $options['histo_height']<=0) $options['histo_height']=100;
356    if(!isset($options['histo_method']) or !in_array($options['histo_method'], array('L', 'A', 'M'))) $options['histo_method']='L';
357
358    return($options);
359  }
360
361
362  static public function colorAllocate($im, $color)
363  {
364    $rgb=self::IntToRGB($color);
365    return(imagecolorallocate($im, $rgb['R'], $rgb['G'], $rgb['B']));
366  }
367
368  static public function colorAllocateA($im, $color, $alpha)
369  {
370    $rgb=self::IntToRGB($color);
371    return(imagecolorallocatealpha($im, $rgb['R'], $rgb['G'], $rgb['B'], $alpha));
372  }
373
374
375}
376
377
378?>
Note: See TracBrowser for help on using the repository browser.