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  }
180 
181  # determine area of source image to use
182  if (isset($this->CroppedXSize))
183  {
184  $SrcXSize = $this->CroppedXSize;
185  $SrcYSize = $this->CroppedYSize;
186  }
187  else
188  {
189  $SrcXSize = $this->XSize();
190  $SrcYSize = $this->YSize();
191  }
192 
193  # copy/scale portion of original image to destination image
194  if ($this->GDVersion >= 2)
195  {
196  imagecopyresampled($DstImage, $this->ImageObj,
197  0, 0,
198  $this->CroppedXOrigin, $this->CroppedYOrigin,
199  $DstXSize, $DstYSize,
200  $SrcXSize, $SrcYSize);
201  }
202  else
203  {
204  imagecopyresized($DstImage, $this->ImageObj,
205  0, 0,
206  $this->CroppedXOrigin, $this->CroppedYOrigin,
207  $DstXSize, $DstYSize,
208  $SrcXSize, $SrcYSize);
209  }
210  }
211  else
212  {
213  $DstImage =& $this->ImageObj;
214  }
215 
216  # save image to new file
217  switch ($NewImageType)
218  {
219  case IMGTYPE_GIF:
220  imagegif($DstImage, $FileName);
221  break;
222 
223  case IMGTYPE_JPEG:
224  imagejpeg($DstImage, $FileName, $this->JpegSaveQuality);
225  break;
226 
227  case IMGTYPE_PNG:
228  imagepng($DstImage, $FileName, 9);
229  break;
230 
231  case IMGTYPE_BMP:
232  imagewbmp($DstImage, $FileName);
233 
234  default:
235  $this->ErrorStatus = AI_INTERNALERROR;
236  break;
237  }
238  }
239  else
240  {
241  # set error status to indicate unsupported image format
242  $this->ErrorStatus = AI_UNSUPPORTEDFORMAT;
243  }
244  }
245 
246  # report success or failure to caller
247  return $this->ErrorStatus;
248  }
249 
250  # return the X (horizontal) image size in pixels
251  function XSize()
252  {
253  $this->ReadSize();
254  return $this->ImageXSize;
255  }
256 
257  # return the Y (vertical) image size in pixels
258  function YSize()
259  {
260  $this->ReadSize();
261  return $this->ImageYSize;
262  }
263 
264  # specify the size to scale the image to for the next SaveAs()
266  {
267  # save size for scaling
268  $this->ScaledXSize = $ScaledXSize;
269  $this->ScaledYSize = $ScaledYSize;
270  $this->MaintainAspectRatio = $MaintainAspectRatio;
271  }
272 
273  # specify the size to crop the image to for the next SaveAs()
275  {
276  # save origin and size for cropping
277  $this->CroppedXSize = $CroppedXSize;
278  $this->CroppedYSize = $CroppedYSize;
279  $this->CroppedXOrigin = $CroppedXOrigin;
280  $this->CroppedYOrigin = $CroppedYOrigin;
281  }
282 
290  function Type($FileName = NULL)
291  {
292  if ($FileName == NULL) { $FileName = $this->SourceFileName; }
293  if (is_readable($FileName))
294  {
295  switch (exif_imagetype($FileName))
296  {
297  case IMAGETYPE_GIF: return IMGTYPE_GIF;
298  case IMAGETYPE_JPEG: return IMGTYPE_JPEG;
299  case IMAGETYPE_PNG: return IMGTYPE_PNG;
300  case IMAGETYPE_BMP: return IMGTYPE_BMP;
301  }
302  }
303  if (preg_match("/.*\\.jp[e]{0,1}g$/i", $FileName))
304  { return IMGTYPE_JPEG; }
305  elseif (preg_match("/.*\\.gif$/i", $FileName))
306  { return IMGTYPE_GIF; }
307  elseif (preg_match("/.*\\.bmp$/i", $FileName))
308  { return IMGTYPE_BMP; }
309  elseif (preg_match("/.*\\.png$/i", $FileName))
310  { return IMGTYPE_PNG; }
311  return IMGTYPE_UNKNOWN;
312  }
313 
318  public function Mimetype()
319  {
320  switch ($this->Type())
321  {
322  # if the image type is known
323  case IMGTYPE_JPEG: return "image/jpeg";
324  case IMGTYPE_PNG: return "image/png";
325  case IMGTYPE_GIF: return "image/gif";
326  case IMGTYPE_BMP: return "image/bmp";
327 
328  # the image type isn't known
329  default:
330  $Mimetype = NULL;
331  $FilePath = $this->SourceFileName;
332 
333  # PHP >= 5.3
334  if (function_exists("finfo_open"))
335  {
336  # construct a handle to get mimetype info
337  $FInfoHandle = finfo_open(FILEINFO_MIME);
338 
339  # if the handle is okay
340  if ($FInfoHandle)
341  {
342  # get the mimetype info for the file
343  $FInfoMime = finfo_file($FInfoHandle, $FilePath);
344 
345  # close the handle
346  finfo_close($FInfoHandle);
347 
348  # if the mimetype info fetch was successful
349  if ($FInfoMime)
350  {
351  $Mimetype = $FInfoMime;
352  }
353  }
354  }
355 
356  # PHP < 5.3
357  else if (function_exists("mime_content_type"))
358  {
359  # mime_content_type has been deprecated, but it may be
360  # the only way to get the mimetype for PHP < 5.3
361  $MimeType = mime_content_type($FilePath);
362 
363  # if the mimetype info fetch was successful
364  if ($MimeType)
365  {
366  $Mimetype = $MimeType;
367  }
368  }
369 
370  return $Mimetype;
371  }
372  }
373 
374  # return the file name extension for the image
375  static function Extension($Type = NULL)
376  {
377  if ($Type === NULL)
378  {
379  return Image::$AxisImageFileExtensions[$this->Type()];
380  }
381  else
382  {
383  if (isset(Image::$AxisImageFileExtensions[$Type]))
384  {
385  return Image::$AxisImageFileExtensions[$Type];
386  }
387  else
388  {
389  return NULL;
390  }
391  }
392  }
393 
394  # set/get the quality (0-100) for JPEG images created with SaveAs()
395  function JpegQuality($NewSetting = NULL)
396  {
397  if ($NewSetting != NULL) { $this->JpegSaveQuality = $NewSetting; }
398  return $this->JpegSaveQuality;
399  }
400 
401  # return supported image formats
402  static function SupportedFormats()
403  {
404  # start out assuming no formats are supported
405  $Supported = 0;
406 
407  # if JPEG is supported by PHP
408  if (function_exists("imagetypes") && defined("IMG_JPG")
409  && (imagetypes() & IMG_JPG))
410  {
411  # add JPEG to list of supported formats
412  $Supported |= IMGTYPE_JPEG;
413  }
414 
415  # if GIF is supported by PHP
416  if (function_exists("imagetypes") && defined("IMG_GIF")
417  && (imagetypes() & IMG_GIF))
418  {
419  # add GIF to list of supported formats
420  $Supported |= IMGTYPE_GIF;
421  }
422 
423  # if PNG is supported by PHP
424  if (function_exists("imagetypes") && defined("IMG_PNG")
425  && (imagetypes() & IMG_PNG))
426  {
427  # add PNG to list of supported formats
428  $Supported |= IMGTYPE_PNG;
429  }
430 
431  # report to caller what formats are supported
432  return $Supported;
433  }
434 
435  # return names (upper-case extensions) of supported image formats
436  static function SupportedFormatNames()
437  {
438  # assume that no formats are supported
439  $FormatNames = array();
440 
441  # retrieve supported formats
442  $SupportedFormats = Image::SupportedFormats();
443 
444  # for each possible supported format
445  foreach (Image::$AxisImageFileExtensions as $ImageType => $ImageExtension)
446  {
447  # if format is supported
448  if ($ImageType & $SupportedFormats)
449  {
450  # add format extension to list of supported image format names
451  $FormatNames[] = strtoupper($ImageExtension);
452  }
453  }
454 
455  # return supported image format names to caller
456  return $FormatNames;
457  }
458 
459  # return the error status set by the constructor or the last call to SaveAs()
460  function Status()
461  {
462  return $this->ErrorStatus;
463  }
464 
465  # return string containing external command that failed
467  {
468  return $this->FailedCommand;
469  }
470 
471 
472  # ---- PRIVATE INTERFACE -------------------------------------------------
473 
491 
492  # image file extensions
493  private static $AxisImageFileExtensions = array(
494  IMGTYPE_JPEG => "jpg",
495  IMGTYPE_GIF => "gif",
496  IMGTYPE_BMP => "bmp",
497  IMGTYPE_PNG => "png",
498  );
499 
500  function ReadSize()
501  {
502  # if we do not already have image info
503  if (!isset($this->ImageXSize))
504  {
505  # read size information from image object
506  $this->ImageXSize = imagesx($this->ImageObj);
507  $this->ImageYSize = imagesy($this->ImageObj);
508  }
509  }
510 
511  function ImageFormatSupportedByPhp($Format = NULL)
512  {
513  if ($Format == NULL) { $Format = $this->Type(); }
514 
515  if (!function_exists("imagetypes")) { return FALSE; }
516 
517  switch ($Format)
518  {
519  case IMGTYPE_JPEG:
520  return (imagetypes() & IMG_JPG) ? TRUE : FALSE;
521  break;
522 
523  case IMGTYPE_GIF:
524  return (imagetypes() & IMG_GIF) ? TRUE : FALSE;
525  break;
526 
527  case IMGTYPE_BMP:
528  return FALSE;
529  break;
530 
531  case IMGTYPE_PNG:
532  return (imagetypes() & IMG_PNG) ? TRUE : FALSE;
533  break;
534 
535  default:
536  return FALSE;
537  break;
538  }
539  }
540 }
541 
542 # image type definitions (these are purposefully different from those defined by PHP GD lib)
543 define("IMGTYPE_UNKNOWN", 0);
544 define("IMGTYPE_JPEG", 1);
545 define("IMGTYPE_GIF", 2);
546 define("IMGTYPE_BMP", 4);
547 define("IMGTYPE_PNG", 8);
548 
549 # error status definitions
550 define("AI_OKAY", 0);
551 define("AI_FILEUNREADABLE", 1);
552 define("AI_IMGOBJCREATEFAILED", 2);
553 define("AI_PPMCMDFAILED", 4);
554 define("AI_INTERNALERROR", 8);
555 define("AI_UNKNOWNTYPE", 16);
556 define("AI_UNSUPPORTEDFORMAT", 32);
557 define("AI_DESTINATIONUNWRITABLE", 64);
558 
559 # supply imagetypes() function if not defined
560 if (!function_exists("imagetypes"))
561 {
562  # (returning 0 indicates no image types supported)
563  function imagetypes() { return 0; }
564 }
565 
static SupportedFormatNames()
Definition: Image.php:436
const IMGTYPE_JPEG
Definition: Image.php:544
SaveAs($FileName, $NewImageType=NULL)
Definition: Image.php:104
$ImageObj
Definition: Image.php:475
ScaleTo($ScaledXSize, $ScaledYSize, $MaintainAspectRatio=FALSE)
Definition: Image.php:265
CropTo($CroppedXSize, $CroppedYSize, $CroppedXOrigin=0, $CroppedYOrigin=0)
Definition: Image.php:274
$GDVersion
Definition: Image.php:474
ReadSize()
Definition: Image.php:500
const AI_OKAY
Definition: Image.php:550
YSize()
Definition: Image.php:258
XSize()
Definition: Image.php:251
$CroppedYOrigin
Definition: Image.php:485
$DecodeCommand
Definition: Image.php:487
$CroppedXOrigin
Definition: Image.php:484
const IMGTYPE_UNKNOWN
Definition: Image.php:543
const AI_DESTINATIONUNWRITABLE
Definition: Image.php:557
$JpegSaveQuality
Definition: Image.php:486
$ScaledXSize
Definition: Image.php:479
JpegQuality($NewSetting=NULL)
Definition: Image.php:395
$ImageXSize
Definition: Image.php:477
$ErrorStatus
Definition: Image.php:488
ImageFormatSupportedByPhp($Format=NULL)
Definition: Image.php:511
$MaintainAspectRatio
Definition: Image.php:481
$ScaledYSize
Definition: Image.php:480
$CroppedXSize
Definition: Image.php:482
const AI_FILEUNREADABLE
Definition: Image.php:551
const AI_IMGOBJCREATEFAILED
Definition: Image.php:552
Status()
Definition: Image.php:460
const IMGTYPE_PNG
Definition: Image.php:547
Mimetype()
Get the MIME type for the image.
Definition: Image.php:318
Definition: Image.php:15
Type($FileName=NULL)
Get the image type.
Definition: Image.php:290
$DebugLevel
Definition: Image.php:490
__construct($SourceFileName, $DebugLevel=0)
Definition: Image.php:19
const IMGTYPE_GIF
Definition: Image.php:545
$ImageYSize
Definition: Image.php:478
static SupportedFormats()
Definition: Image.php:402
FailedExternalCommand()
Definition: Image.php:466
const AI_INTERNALERROR
Definition: Image.php:554
$FailedCommand
Definition: Image.php:489
$CroppedYSize
Definition: Image.php:483
const IMGTYPE_BMP
Definition: Image.php:546
$SourceFileName
Definition: Image.php:476
static Extension($Type=NULL)
Definition: Image.php:375
const AI_UNSUPPORTEDFORMAT
Definition: Image.php:556