CWIS Developer Documentation
Image.php
Go to the documentation of this file.
1 <?PHP
2 #
3 # Axis--Image.php
4 # A PHP Object to Support Image File Manipulation
5 #
6 # Copyright 1999-2013 Axis Data
7 # This code is free software that can be used or redistributed under the
8 # terms of Version 2 of the GNU General Public License, as published by the
9 # Free Software Foundation (http://www.fsf.org).
10 #
11 # Part of the AxisPHP library v1.2.5
12 # For more information see http://www.axisdata.com/AxisPHP/
13 #
14 
15 class Image {
16 
17  # ---- PUBLIC INTERFACE --------------------------------------------------
18 
20  {
21  # set debug level
22  $this->DebugLevel = $DebugLevel;
23 
24  # save source file name
25  $this->SourceFileName = $SourceFileName;
26 
27  # set default values
28  $this->JpegSaveQuality = 80;
29  $this->ErrorStatus = AI_OKAY;
30  $this->FailedCommand = "";
31 
32  # get GD library version
33  if (extension_loaded("gd"))
34  {
35  if (in_array("imagecreatetruecolor", get_extension_funcs("gd")))
36  {
37  $this->GDVersion = 2;
38  }
39  else
40  {
41  $this->GDVersion = 1;
42  }
43  }
44  else
45  {
46  $this->GDVersion = 0;
47  }
48 
49  # if source file is readable
50  if (is_readable(realpath($SourceFileName)))
51  {
52  # if support is available for this image type
53  if ($this->ImageFormatSupportedByPhp())
54  {
55  # create PHP image object
56  switch ($this->Type())
57  {
58  case IMGTYPE_JPEG:
59  if ($this->DebugLevel > 1) { print("AI: file format is JPEG<br>\n"); }
60  $this->ImageObj = imagecreatefromjpeg($this->SourceFileName);
61  break;
62 
63  case IMGTYPE_GIF:
64  if ($this->DebugLevel > 1) { print("AI: file format is GIF<br>\n"); }
65  $this->ImageObj = imagecreatefromgif($this->SourceFileName);
66  break;
67 
68  case IMGTYPE_BMP:
69  if ($this->DebugLevel > 1) { print("AI: file format is BMP<br>\n"); }
70  $this->ImageObj = imagecreatefrombmp($this->SourceFileName);
71  break;
72 
73  case IMGTYPE_PNG:
74  if ($this->DebugLevel > 1) { print("AI: file format is PNG<br>\n"); }
75  $this->ImageObj = imagecreatefrompng($this->SourceFileName);
76  break;
77 
78  default:
79  $this->ErrorStatus = AI_INTERNALERROR;
80  break;
81  }
82 
83  # if PHP image object creation failed
84  if (FALSE === $this->ImageObj)
85  {
86  # set error status
87  $this->ErrorStatus = AI_IMGOBJCREATEFAILED;
88  }
89  }
90  else
91  {
92  # set error status to indicate unsupported image format
93  $this->ErrorStatus = AI_UNSUPPORTEDFORMAT;
94  }
95  }
96  else
97  {
98  # set error status
99  $this->ErrorStatus = AI_FILEUNREADABLE;
100  }
101  }
102 
103  # save image with a new name and (optionally) a new type
104  function SaveAs($FileName, $NewImageType = NULL)
105  {
106  # assume we will succeed
107  $this->ErrorStatus = AI_OKAY;
108 
109  # if destination file exists and is not writable
110  if (file_exists($FileName) && (is_writable($FileName) != TRUE))
111  {
112  # set error code
113  $this->ErrorStatus = AI_DESTINATIONUNWRITABLE;
114  }
115  # else if destination directory is not writable
116  elseif (is_writable(dirname($FileName)) != TRUE)
117  {
118  # set error code
119  $this->ErrorStatus = AI_DESTINATIONUNWRITABLE;
120  }
121  else
122  {
123  # if no image type specified try to determine based on file name or use source file type
124  if ($NewImageType == NULL)
125  {
126  if ($this->Type($FileName) != IMGTYPE_UNKNOWN)
127  { $NewImageType = $this->Type($FileName); }
128  else
129  { $NewImageType = $this->Type(); }
130  }
131 
132  # if input and output types both supported
133  if ($this->ImageFormatSupportedByPhp() && $this->ImageFormatSupportedByPhp($NewImageType))
134  {
135  # if image cropping or scaling was requested
136  if (isset($this->CroppedXSize)
137  || isset($this->ScaledXSize)
138  || isset($this->ScaledYSize))
139  {
140  # determine destination image size
141  if (isset($this->ScaledXSize) && isset($this->ScaledYSize)
142  && ($this->MaintainAspectRatio != TRUE))
143  {
144  $DstXSize = $this->ScaledXSize;
145  $DstYSize = $this->ScaledYSize;
146  }
147  elseif (isset($this->ScaledXSize)
148  || ($this->ScaledXSize > $this->ScaledYSize))
149  {
150  $DstXSize = $this->ScaledXSize;
151  $DstYSize = ($this->ScaledXSize * $this->YSize())
152  / $this->XSize();
153  }
154  elseif (isset($this->ScaledYSize))
155  {
156  $DstXSize = ($this->ScaledYSize * $this->XSize())
157  / $this->YSize();
158  $DstYSize = $this->ScaledYSize;
159  }
160  elseif (isset($this->CroppedXSize))
161  {
162  $DstXSize = $this->CroppedXSize;
163  $DstYSize = $this->CroppedYSize;
164  }
165  else
166  {
167  $DstXSize = $this->XSize();
168  $DstYSize = $this->YSize();
169  }
170 
171  # create destination image object
172  if (($NewImageType == IMGTYPE_GIF) || ($this->GDVersion < 2))
173  {
174  $DstImage = imagecreate($DstXSize, $DstYSize);
175  }
176  else
177  {
178  $DstImage = imagecreatetruecolor($DstXSize, $DstYSize);
179  imagealphablending($DstImage, FALSE);
180  imagesavealpha($DstImage, TRUE);
181  }
182 
183  # determine area of source image to use
184  if (isset($this->CroppedXSize))
185  {
186  $SrcXSize = $this->CroppedXSize;
187  $SrcYSize = $this->CroppedYSize;
188  }
189  else
190  {
191  $SrcXSize = $this->XSize();
192  $SrcYSize = $this->YSize();
193  }
194 
195  # copy/scale portion of original image to destination image
196  if ($this->GDVersion >= 2)
197  {
198  imagecopyresampled($DstImage, $this->ImageObj,
199  0, 0,
200  $this->CroppedXOrigin, $this->CroppedYOrigin,
201  $DstXSize, $DstYSize,
202  $SrcXSize, $SrcYSize);
203  }
204  else
205  {
206  imagecopyresized($DstImage, $this->ImageObj,
207  0, 0,
208  $this->CroppedXOrigin, $this->CroppedYOrigin,
209  $DstXSize, $DstYSize,
210  $SrcXSize, $SrcYSize);
211  }
212  }
213  else
214  {
215  $DstImage =& $this->ImageObj;
216  }
217 
218  # save image to new file
219  switch ($NewImageType)
220  {
221  case IMGTYPE_GIF:
222  imagegif($DstImage, $FileName);
223  break;
224 
225  case IMGTYPE_JPEG:
226  imagejpeg($DstImage, $FileName, $this->JpegSaveQuality);
227  break;
228 
229  case IMGTYPE_PNG:
230  imagepng($DstImage, $FileName, 9);
231  break;
232 
233  case IMGTYPE_BMP:
234  imagewbmp($DstImage, $FileName);
235 
236  default:
237  $this->ErrorStatus = AI_INTERNALERROR;
238  break;
239  }
240  }
241  else
242  {
243  # set error status to indicate unsupported image format
244  $this->ErrorStatus = AI_UNSUPPORTEDFORMAT;
245  }
246  }
247 
248  # report success or failure to caller
249  return $this->ErrorStatus;
250  }
251 
252  # return the X (horizontal) image size in pixels
253  function XSize()
254  {
255  $this->ReadSize();
256  return $this->ImageXSize;
257  }
258 
259  # return the Y (vertical) image size in pixels
260  function YSize()
261  {
262  $this->ReadSize();
263  return $this->ImageYSize;
264  }
265 
266  # specify the size to scale the image to for the next SaveAs()
268  {
269  # save size for scaling
270  $this->ScaledXSize = $ScaledXSize;
271  $this->ScaledYSize = $ScaledYSize;
272  $this->MaintainAspectRatio = $MaintainAspectRatio;
273  }
274 
275  # specify the size to crop the image to for the next SaveAs()
277  {
278  # save origin and size for cropping
279  $this->CroppedXSize = $CroppedXSize;
280  $this->CroppedYSize = $CroppedYSize;
281  $this->CroppedXOrigin = $CroppedXOrigin;
282  $this->CroppedYOrigin = $CroppedYOrigin;
283  }
284 
292  function Type($FileName = NULL)
293  {
294  if ($FileName == NULL) { $FileName = $this->SourceFileName; }
295  if (is_readable($FileName))
296  {
297  switch (exif_imagetype($FileName))
298  {
299  case IMAGETYPE_GIF: return IMGTYPE_GIF;
300  case IMAGETYPE_JPEG: return IMGTYPE_JPEG;
301  case IMAGETYPE_PNG: return IMGTYPE_PNG;
302  case IMAGETYPE_BMP: return IMGTYPE_BMP;
303  }
304  }
305  if (preg_match("/.*\\.jp[e]{0,1}g$/i", $FileName))
306  { return IMGTYPE_JPEG; }
307  elseif (preg_match("/.*\\.gif$/i", $FileName))
308  { return IMGTYPE_GIF; }
309  elseif (preg_match("/.*\\.bmp$/i", $FileName))
310  { return IMGTYPE_BMP; }
311  elseif (preg_match("/.*\\.png$/i", $FileName))
312  { return IMGTYPE_PNG; }
313  return IMGTYPE_UNKNOWN;
314  }
315 
320  public function Mimetype()
321  {
322  switch ($this->Type())
323  {
324  # if the image type is known
325  case IMGTYPE_JPEG: return "image/jpeg";
326  case IMGTYPE_PNG: return "image/png";
327  case IMGTYPE_GIF: return "image/gif";
328  case IMGTYPE_BMP: return "image/bmp";
329 
330  # the image type isn't known
331  default:
332  $Mimetype = NULL;
333  $FilePath = $this->SourceFileName;
334 
335  # PHP >= 5.3
336  if (function_exists("finfo_open"))
337  {
338  # construct a handle to get mimetype info
339  $FInfoHandle = finfo_open(FILEINFO_MIME);
340 
341  # if the handle is okay
342  if ($FInfoHandle)
343  {
344  # get the mimetype info for the file
345  $FInfoMime = finfo_file($FInfoHandle, $FilePath);
346 
347  # close the handle
348  finfo_close($FInfoHandle);
349 
350  # if the mimetype info fetch was successful
351  if ($FInfoMime)
352  {
353  $Mimetype = $FInfoMime;
354  }
355  }
356  }
357 
358  # PHP < 5.3
359  else if (function_exists("mime_content_type"))
360  {
361  # mime_content_type has been deprecated, but it may be
362  # the only way to get the mimetype for PHP < 5.3
363  $MimeType = mime_content_type($FilePath);
364 
365  # if the mimetype info fetch was successful
366  if ($MimeType)
367  {
368  $Mimetype = $MimeType;
369  }
370  }
371 
372  return $Mimetype;
373  }
374  }
375 
376  # return the file name extension for the image
377  static function Extension($Type = NULL)
378  {
379  if ($Type === NULL)
380  {
381  return Image::$AxisImageFileExtensions[$this->Type()];
382  }
383  else
384  {
385  if (isset(Image::$AxisImageFileExtensions[$Type]))
386  {
387  return Image::$AxisImageFileExtensions[$Type];
388  }
389  else
390  {
391  return NULL;
392  }
393  }
394  }
395 
396  # set/get the quality (0-100) for JPEG images created with SaveAs()
397  function JpegQuality($NewSetting = NULL)
398  {
399  if ($NewSetting != NULL) { $this->JpegSaveQuality = $NewSetting; }
400  return $this->JpegSaveQuality;
401  }
402 
403  # return supported image formats
404  static function SupportedFormats()
405  {
406  # start out assuming no formats are supported
407  $Supported = 0;
408 
409  # if JPEG is supported by PHP
410  if (function_exists("imagetypes") && defined("IMG_JPG")
411  && (imagetypes() & IMG_JPG))
412  {
413  # add JPEG to list of supported formats
414  $Supported |= IMGTYPE_JPEG;
415  }
416 
417  # if GIF is supported by PHP
418  if (function_exists("imagetypes") && defined("IMG_GIF")
419  && (imagetypes() & IMG_GIF))
420  {
421  # add GIF to list of supported formats
422  $Supported |= IMGTYPE_GIF;
423  }
424 
425  # if PNG is supported by PHP
426  if (function_exists("imagetypes") && defined("IMG_PNG")
427  && (imagetypes() & IMG_PNG))
428  {
429  # add PNG to list of supported formats
430  $Supported |= IMGTYPE_PNG;
431  }
432 
433  # report to caller what formats are supported
434  return $Supported;
435  }
436 
437  # return names (upper-case extensions) of supported image formats
438  static function SupportedFormatNames()
439  {
440  # assume that no formats are supported
441  $FormatNames = array();
442 
443  # retrieve supported formats
444  $SupportedFormats = Image::SupportedFormats();
445 
446  # for each possible supported format
447  foreach (Image::$AxisImageFileExtensions as $ImageType => $ImageExtension)
448  {
449  # if format is supported
450  if ($ImageType & $SupportedFormats)
451  {
452  # add format extension to list of supported image format names
453  $FormatNames[] = strtoupper($ImageExtension);
454  }
455  }
456 
457  # return supported image format names to caller
458  return $FormatNames;
459  }
460 
461  # return the error status set by the constructor or the last call to SaveAs()
462  function Status()
463  {
464  return $this->ErrorStatus;
465  }
466 
467  # return string containing external command that failed
469  {
470  return $this->FailedCommand;
471  }
472 
473 
474  # ---- PRIVATE INTERFACE -------------------------------------------------
475 
493 
494  # image file extensions
495  private static $AxisImageFileExtensions = array(
496  IMGTYPE_JPEG => "jpg",
497  IMGTYPE_GIF => "gif",
498  IMGTYPE_BMP => "bmp",
499  IMGTYPE_PNG => "png",
500  );
501 
502  function ReadSize()
503  {
504  # if we do not already have image info
505  if (!isset($this->ImageXSize))
506  {
507  # read size information from image object
508  $this->ImageXSize = imagesx($this->ImageObj);
509  $this->ImageYSize = imagesy($this->ImageObj);
510  }
511  }
512 
513  function ImageFormatSupportedByPhp($Format = NULL)
514  {
515  if ($Format == NULL) { $Format = $this->Type(); }
516 
517  if (!function_exists("imagetypes")) { return FALSE; }
518 
519  switch ($Format)
520  {
521  case IMGTYPE_JPEG:
522  return (imagetypes() & IMG_JPG) ? TRUE : FALSE;
523  break;
524 
525  case IMGTYPE_GIF:
526  return (imagetypes() & IMG_GIF) ? TRUE : FALSE;
527  break;
528 
529  case IMGTYPE_BMP:
530  return FALSE;
531  break;
532 
533  case IMGTYPE_PNG:
534  return (imagetypes() & IMG_PNG) ? TRUE : FALSE;
535  break;
536 
537  default:
538  return FALSE;
539  break;
540  }
541  }
542 }
543 
544 # image type definitions (these are purposefully different from those defined by PHP GD lib)
545 define("IMGTYPE_UNKNOWN", 0);
546 define("IMGTYPE_JPEG", 1);
547 define("IMGTYPE_GIF", 2);
548 define("IMGTYPE_BMP", 4);
549 define("IMGTYPE_PNG", 8);
550 
551 # error status definitions
552 define("AI_OKAY", 0);
553 define("AI_FILEUNREADABLE", 1);
554 define("AI_IMGOBJCREATEFAILED", 2);
555 define("AI_PPMCMDFAILED", 4);
556 define("AI_INTERNALERROR", 8);
557 define("AI_UNKNOWNTYPE", 16);
558 define("AI_UNSUPPORTEDFORMAT", 32);
559 define("AI_DESTINATIONUNWRITABLE", 64);
560 
561 # supply imagetypes() function if not defined
562 if (!function_exists("imagetypes"))
563 {
564  # (returning 0 indicates no image types supported)
565  function imagetypes() { return 0; }
566 }
567 
static SupportedFormatNames()
Definition: Image.php:438
const IMGTYPE_JPEG
Definition: Image.php:546
SaveAs($FileName, $NewImageType=NULL)
Definition: Image.php:104
$ImageObj
Definition: Image.php:477
ScaleTo($ScaledXSize, $ScaledYSize, $MaintainAspectRatio=FALSE)
Definition: Image.php:267
CropTo($CroppedXSize, $CroppedYSize, $CroppedXOrigin=0, $CroppedYOrigin=0)
Definition: Image.php:276
$GDVersion
Definition: Image.php:476
ReadSize()
Definition: Image.php:502
const AI_OKAY
Definition: Image.php:552
YSize()
Definition: Image.php:260
XSize()
Definition: Image.php:253
$CroppedYOrigin
Definition: Image.php:487
$DecodeCommand
Definition: Image.php:489
$CroppedXOrigin
Definition: Image.php:486
const IMGTYPE_UNKNOWN
Definition: Image.php:545
const AI_DESTINATIONUNWRITABLE
Definition: Image.php:559
$JpegSaveQuality
Definition: Image.php:488
$ScaledXSize
Definition: Image.php:481
JpegQuality($NewSetting=NULL)
Definition: Image.php:397
$ImageXSize
Definition: Image.php:479
$ErrorStatus
Definition: Image.php:490
ImageFormatSupportedByPhp($Format=NULL)
Definition: Image.php:513
$MaintainAspectRatio
Definition: Image.php:483
$ScaledYSize
Definition: Image.php:482
$CroppedXSize
Definition: Image.php:484
const AI_FILEUNREADABLE
Definition: Image.php:553
const AI_IMGOBJCREATEFAILED
Definition: Image.php:554
Status()
Definition: Image.php:462
const IMGTYPE_PNG
Definition: Image.php:549
Mimetype()
Get the MIME type for the image.
Definition: Image.php:320
Definition: Image.php:15
Type($FileName=NULL)
Get the image type.
Definition: Image.php:292
$DebugLevel
Definition: Image.php:492
__construct($SourceFileName, $DebugLevel=0)
Definition: Image.php:19
const IMGTYPE_GIF
Definition: Image.php:547
$ImageYSize
Definition: Image.php:480
static SupportedFormats()
Definition: Image.php:404
FailedExternalCommand()
Definition: Image.php:468
const AI_INTERNALERROR
Definition: Image.php:556
$FailedCommand
Definition: Image.php:491
$CroppedYSize
Definition: Image.php:485
const IMGTYPE_BMP
Definition: Image.php:548
$SourceFileName
Definition: Image.php:478
static Extension($Type=NULL)
Definition: Image.php:377
const AI_UNSUPPORTEDFORMAT
Definition: Image.php:558