SPTImage.php
Go to the documentation of this file.
00001 <?PHP 00002 # 00003 # FILE: SPTImage.php 00004 # 00005 # METHODS PROVIDED: 00006 # SPTImage($ImageIdOrFileNameOrImageObj, 00007 # $MaxPreviewWidth = NULL, $MaxPreviewHeight = NULL, 00008 # $MaxThumbnailWidth = NULL, $MaxThumbnailHeight = NULL) 00009 # - object constructor 00010 # Delete() 00011 # - delete image and associated files and data 00012 # AltText($NewValue = NULL) 00013 # - get/set alt text attribute 00014 # Id() 00015 # Url() 00016 # PreviewUrl() 00017 # ThumbnailUrl() 00018 # Format() 00019 # Height() 00020 # Width() 00021 # PreviewHeight() 00022 # PreviewWidth() 00023 # ThumbnailHeight() 00024 # ThumbnailWidth() 00025 # - get attributes 00026 # 00027 # AUTHOR: Edward Almasy 00028 # 00029 # Part of CWIS 00030 # Copyright 2002-2011 Internet Scout Project 00031 # http://scout.wisc.edu 00032 # 00033 00034 class SPTImage { 00035 00036 # ---- PUBLIC INTERFACE -------------------------------------------------- 00037 00043 const IMAGE_PATH = "ImageStorage/"; 00044 const PREVIEW_PATH = "ImageStorage/Previews/"; 00045 const THUMBNAIL_PATH = "ImageStorage/Thumbnails/"; 00046 00047 # object constructor 00048 function SPTImage($ImageIdOrFileNameOrImageObj, 00049 $MaxWidth = NULL, $MaxHeight = NULL, 00050 $MaxPreviewWidth = NULL, $MaxPreviewHeight = NULL, 00051 $MaxThumbnailWidth = NULL, $MaxThumbnailHeight = NULL) 00052 { 00053 # clear error status (0 = AI_OKAY) 00054 $this->ErrorStatus = 0; 00055 00056 # trigger the Image class file to be autoloaded since some parts of this 00057 # class (SPTImage) use constants defined in it but don't construct Image 00058 # objects 00059 new Image(NULL); 00060 00061 # create and save a database handle for our use 00062 $this->DB = new SPTDatabase(); 00063 00064 # if image object was passed in 00065 if (is_object($ImageIdOrFileNameOrImageObj) 00066 && method_exists($ImageIdOrFileNameOrImageObj, "SPTImage")) 00067 { 00068 # create copy of image passed in 00069 $this->CreateCopyOfImage($ImageIdOrFileNameOrImageObj); 00070 } 00071 # else if image ID was passed in 00072 elseif (($ImageIdOrFileNameOrImageObj > 0) 00073 && preg_match("/[0-9]+/", $ImageIdOrFileNameOrImageObj)) 00074 { 00075 # load info on existing image 00076 $this->LoadImageInfo($ImageIdOrFileNameOrImageObj); 00077 } 00078 # else assume that value passed in is file name 00079 else 00080 { 00081 # create new image from named file 00082 $this->CreateNewImage($ImageIdOrFileNameOrImageObj, 00083 $MaxWidth, $MaxHeight, 00084 $MaxPreviewWidth, $MaxPreviewHeight, 00085 $MaxThumbnailWidth, $MaxThumbnailHeight); 00086 } 00087 } 00088 00089 # get attributes 00090 function Id() { return $this->Id; } 00091 function Url() { return $this->FileName; } 00092 function PreviewUrl() { return $this->PreviewFileName; } 00093 function ThumbnailUrl() { return $this->ThumbnailFileName; } 00094 function Format() { return $this->Format; } 00095 function Height() { return $this->Height; } 00096 function Width() { return $this->Width; } 00097 function PreviewHeight() { return $this->PreviewHeight; } 00098 function PreviewWidth() { return $this->PreviewWidth; } 00099 function ThumbnailHeight() { return $this->ThumbnailHeight; } 00100 function ThumbnailWidth() { return $this->ThumbnailWidth; } 00101 function ImageStorageDirectory() { return self::IMAGE_PATH; } 00102 function PreviewStorageDirectory() { return self::PREVIEW_PATH; } 00103 function ThumbnailStorageDirectory() { return self::THUMBNAIL_PATH; } 00104 function GetLink() { return $this->FileName; } 00105 00106 # get/set attributes 00107 function AltText($NewValue = NULL) 00108 { 00109 # if new value supplied and new value differs from existing value 00110 if (($NewValue !== NULL) && ($NewValue != $this->AltText)) 00111 { 00112 # save new value to database 00113 $this->DB->Query("UPDATE Images SET" 00114 ." AltText = '".addslashes($NewValue)."'" 00115 ." WHERE ImageId = ".$this->Id); 00116 00117 # save new value locally 00118 $this->AltText = $NewValue; 00119 } 00120 00121 # return attribute value to caller 00122 return $this->AltText; 00123 } 00124 00125 # delete image and associated files and data 00126 function Delete() 00127 { 00128 # delete base image file 00129 if (file_exists($this->FileName)) { unlink($this->FileName); } 00130 00131 # delete preview image file 00132 if (file_exists($this->PreviewFileName)) { unlink($this->PreviewFileName); } 00133 00134 # delete thumbnail image file 00135 if (file_exists($this->ThumbnailFileName)) { unlink($this->ThumbnailFileName); } 00136 00137 # delete image info record in database 00138 $this->DB->Query("DELETE FROM Images WHERE ImageId = ".$this->Id); 00139 } 00140 00141 # return error status set by the constructor 00142 function Status() 00143 { 00144 return $this->ErrorStatus; 00145 } 00146 00147 # check to make sure image storage directories are available 00148 # (returns array of error codes or NULL if no errors found) 00149 static function CheckDirectories() 00150 { 00151 # determine paths 00152 $ImagePath = self::IMAGE_PATH; 00153 $PreviewPath = self::PREVIEW_PATH; 00154 $ThumbnailPath = self::THUMBNAIL_PATH; 00155 00156 # assume everything will be okay 00157 $ErrorsFound = NULL; 00158 00159 # check base image directory 00160 if (!is_dir($ImagePath) || !is_writable($ImagePath)) 00161 { 00162 if (!is_dir($ImagePath)) 00163 { 00164 @mkdir($ImagePath, 0755); 00165 } 00166 else 00167 { 00168 @chmod($ImagePath, 0755); 00169 } 00170 if (!is_dir($ImagePath)) 00171 { 00172 $ErrorsFound[] = "Image Storage Directory Not Found"; 00173 } 00174 elseif (!is_writable($ImagePath)) 00175 { 00176 $ErrorsFound[] = "Image Storage Directory Not Writable"; 00177 } 00178 } 00179 00180 # check preview directory 00181 if (!is_dir($PreviewPath) || !is_writable($PreviewPath)) 00182 { 00183 if (!is_dir($PreviewPath)) 00184 { 00185 @mkdir($PreviewPath, 0755); 00186 } 00187 else 00188 { 00189 @chmod($PreviewPath, 0755); 00190 } 00191 if (!is_dir($PreviewPath)) 00192 { 00193 $ErrorsFound[] = "Preview Storage Directory Not Found"; 00194 } 00195 elseif (!is_writable($PreviewPath)) 00196 { 00197 $ErrorsFound[] = "Preview Storage Directory Not Writable"; 00198 } 00199 } 00200 00201 # check thumbnail directory 00202 if (!is_dir($ThumbnailPath) || !is_writable($ThumbnailPath)) 00203 { 00204 if (!is_dir($ThumbnailPath)) 00205 { 00206 @mkdir($ThumbnailPath, 0755); 00207 } 00208 else 00209 { 00210 @chmod($ThumbnailPath, 0755); 00211 } 00212 if (!is_dir($ThumbnailPath)) 00213 { 00214 $ErrorsFound[] = "Thumbnail Storage Directory Not Found"; 00215 } 00216 elseif (!is_writable($ThumbnailPath)) 00217 { 00218 $ErrorsFound[] = "Thumbnail Storage Directory Not Writable"; 00219 } 00220 } 00221 00222 # return any errors found to caller 00223 return $ErrorsFound; 00224 } 00225 00226 public function Resize($MaxWidth, $MaxHeight, 00227 $MaxPreviewWidth, $MaxPreviewHeight, 00228 $MaxThumbnailWidth, $MaxThumbnailHeight) 00229 { 00230 $SrcImage = new Image($this->FileName); 00231 00232 # scale the original image if necessary 00233 $MaxWidth = min($MaxWidth, $SrcImage->XSize()); 00234 $MaxHeight = min($MaxHeight, $SrcImage->YSize()); 00235 $SrcImage->ScaleTo($MaxWidth, $MaxHeight, TRUE); 00236 00237 # save and reload image info 00238 $SrcImage->SaveAs($this->FileName); 00239 $SrcImage = new Image($this->FileName); 00240 00241 # retrieve image width and height 00242 $this->Height = $SrcImage->YSize(); 00243 $this->Width = $SrcImage->XSize(); 00244 00245 # generate preview image and calculate width and height 00246 $MaxPreviewWidth = min($MaxPreviewWidth, $this->Width); 00247 $MaxPreviewHeight = min($MaxPreviewHeight, $this->Height); 00248 $SrcImage->ScaleTo($MaxPreviewWidth, $MaxPreviewHeight, TRUE); 00249 $SrcImage->SaveAs($this->PreviewFileName, IMGTYPE_JPEG); 00250 if (($this->Width * $MaxPreviewHeight) 00251 > ($this->Height * $MaxPreviewWidth)) 00252 { 00253 $this->PreviewWidth = $MaxPreviewWidth; 00254 $this->PreviewHeight = 00255 ($MaxPreviewWidth * $SrcImage->YSize()) / $SrcImage->XSize(); 00256 } 00257 else 00258 { 00259 $this->PreviewWidth = 00260 ($MaxPreviewHeight * $SrcImage->XSize()) / $SrcImage->YSize(); 00261 $this->PreviewHeight = $MaxPreviewHeight; 00262 } 00263 00264 # generate thumbnail image and calculate width and height 00265 $MaxThumbnailWidth = min($MaxThumbnailWidth, $this->Width); 00266 $MaxThumbnailHeight = min($MaxThumbnailHeight, $this->Height); 00267 $SrcImage->ScaleTo($MaxThumbnailWidth, $MaxThumbnailHeight, TRUE); 00268 $SrcImage->SaveAs($this->ThumbnailFileName, IMGTYPE_JPEG); 00269 if (($this->Width * $MaxThumbnailHeight) 00270 > ($this->Height * $MaxThumbnailWidth)) 00271 { 00272 $this->ThumbnailWidth = $MaxThumbnailWidth; 00273 $this->ThumbnailHeight = 00274 ($MaxThumbnailWidth * $SrcImage->YSize()) / $SrcImage->XSize(); 00275 } 00276 else 00277 { 00278 $this->ThumbnailWidth = ($MaxThumbnailHeight * $SrcImage->XSize()) / $SrcImage->YSize(); 00279 $this->ThumbnailHeight = $MaxThumbnailHeight; 00280 } 00281 00282 # save image attributes to database 00283 $this->SaveImageInfo(); 00284 } 00285 00286 # ---- PRIVATE INTERFACE ------------------------------------------------- 00287 00288 var $Id; 00289 var $FileName; 00290 var $PreviewFileName; 00291 var $ThumbnailFileName; 00292 var $Format; 00293 var $AltText; 00294 var $Url; 00295 var $PreviewUrl; 00296 var $ThumbnailUrl; 00297 var $Height; 00298 var $Width; 00299 var $PreviewHeight; 00300 var $PreviewWidth; 00301 var $ThumbnailHeight; 00302 var $ThumbnailWidth; 00303 var $DB; 00304 var $ErrorStatus; 00305 00306 function CreateNewImage($FileName, $MaxWidth, $MaxHeight, 00307 $MaxPreviewWidth, $MaxPreviewHeight, 00308 $MaxThumbnailWidth, $MaxThumbnailHeight) 00309 { 00310 # if file does not exist or is not readable 00311 if (!is_readable($FileName)) 00312 { 00313 # set error status 00314 $this->ErrorStatus = AI_FILEUNREADABLE; 00315 } 00316 else 00317 { 00318 # if image is invalid or unsupported type 00319 $SrcImage = new Image($FileName); 00320 if ($SrcImage->Status() != AI_OKAY) 00321 { 00322 # set error status 00323 $this->ErrorStatus = $SrcImage->Status(); 00324 } 00325 else 00326 { 00327 # retrieve image type 00328 $this->Format = $SrcImage->Type(); 00329 00330 # generate new image ID 00331 $this->Id = $this->GenerateNewImageId(); 00332 00333 # generate and set file names 00334 $this->SetFileNames(); 00335 00336 # if our image file name differs from file name passed in 00337 if (realpath($this->FileName) != realpath($FileName)) 00338 { 00339 # create image file 00340 $SrcImage->SaveAs($this->FileName); 00341 00342 # if create failed set error status and bail out 00343 if ($SrcImage->Status() != AI_OKAY) 00344 { 00345 echo "create failed<br>"; 00346 echo "Status: ".$SrcImage->Status()."<br>"; 00347 echo "Failed Command: ".$SrcImage->FailedExternalCommand()."<br>"; 00348 echo "Missing External Executables: "; 00349 print_r(Image::MissingExternalExecutables()); 00350 echo "<br>"; 00351 $this->ErrorStatus = $SrcImage->Status(); 00352 return; 00353 } 00354 } 00355 00356 # scale the original image if necessary 00357 $MaxWidth = min($MaxWidth, $SrcImage->XSize()); 00358 $MaxHeight = min($MaxHeight, $SrcImage->YSize()); 00359 $SrcImage->ScaleTo($MaxWidth, $MaxHeight, TRUE); 00360 00361 # save and reload image info 00362 $SrcImage->SaveAs($this->FileName); 00363 $SrcImage = new Image($this->FileName); 00364 00365 # retrieve image width and height 00366 $this->Height = $SrcImage->YSize(); 00367 $this->Width = $SrcImage->XSize(); 00368 00369 # generate preview image and calculate width and height 00370 $MaxPreviewWidth = min($MaxPreviewWidth, $this->Width); 00371 $MaxPreviewHeight = min($MaxPreviewHeight, $this->Height); 00372 $SrcImage->ScaleTo($MaxPreviewWidth, $MaxPreviewHeight, TRUE); 00373 $SrcImage->SaveAs($this->PreviewFileName, IMGTYPE_JPEG); 00374 if ($SrcImage->Status() != AI_OKAY) 00375 { 00376 echo "preview save as failed<br>"; 00377 $this->ErrorStatus = $SrcImage->Status(); 00378 return; 00379 } 00380 if (($this->Width * $MaxPreviewHeight) 00381 > ($this->Height * $MaxPreviewWidth)) 00382 { 00383 $this->PreviewWidth = $MaxPreviewWidth; 00384 $this->PreviewHeight = 00385 ($MaxPreviewWidth * $SrcImage->YSize()) / $SrcImage->XSize(); 00386 } 00387 else 00388 { 00389 $this->PreviewWidth = 00390 ($MaxPreviewHeight * $SrcImage->XSize()) / $SrcImage->YSize(); 00391 $this->PreviewHeight = $MaxPreviewHeight; 00392 } 00393 00394 # generate thumbnail image and calculate width and height 00395 $MaxThumbnailWidth = min($MaxThumbnailWidth, $this->Width); 00396 $MaxThumbnailHeight = min($MaxThumbnailHeight, $this->Height); 00397 $SrcImage->ScaleTo($MaxThumbnailWidth, $MaxThumbnailHeight, TRUE); 00398 $SrcImage->SaveAs($this->ThumbnailFileName, IMGTYPE_JPEG); 00399 if ($SrcImage->Status() != AI_OKAY) 00400 { 00401 echo "thumbnail SaveAs failed.<br>"; 00402 $this->ErrorStatus = $SrcImage->Status(); 00403 return; 00404 } 00405 if (($this->Width * $MaxThumbnailHeight) 00406 > ($this->Height * $MaxThumbnailWidth)) 00407 { 00408 $this->ThumbnailWidth = $MaxThumbnailWidth; 00409 $this->ThumbnailHeight = 00410 ($MaxThumbnailWidth * $SrcImage->YSize()) / $SrcImage->XSize(); 00411 } 00412 else 00413 { 00414 $this->ThumbnailWidth = ($MaxThumbnailHeight * $SrcImage->XSize()) / $SrcImage->YSize(); 00415 $this->ThumbnailHeight = $MaxThumbnailHeight; 00416 } 00417 00418 # save image attributes to database 00419 $this->SaveImageInfo(); 00420 } 00421 } 00422 } 00423 00424 function LoadImageInfo($ImageId) 00425 { 00426 # save image ID 00427 $this->Id = $ImageId; 00428 00429 # load image record from database 00430 $this->DB->Query("SELECT * FROM Images WHERE ImageId = ".$ImageId); 00431 00432 # if the ID is invalid 00433 if (!$this->DB->NumRowsSelected()) 00434 { 00435 $this->ErrorStatus = AI_INTERNALERROR; 00436 return; 00437 } 00438 00439 $Record = $this->DB->FetchRow(); 00440 00441 # load in values from record 00442 $this->Format = $Record["Format"]; 00443 $this->AltText = $Record["AltText"]; 00444 $this->Height = $Record["Height"]; 00445 $this->Width = $Record["Width"]; 00446 $this->PreviewHeight = $Record["PreviewHeight"]; 00447 $this->PreviewWidth = $Record["PreviewWidth"]; 00448 $this->ThumbnailHeight = $Record["ThumbnailHeight"]; 00449 $this->ThumbnailWidth = $Record["ThumbnailWidth"]; 00450 00451 # generate file names 00452 $this->SetFileNames(); 00453 } 00454 00455 function CreateCopyOfImage($SrcImage) 00456 { 00457 $Image = new Image($SrcImage->Url()); 00458 if ($Image->Status() != AI_OKAY) 00459 { 00460 # set error status 00461 $this->ErrorStatus = $Image->Status(); 00462 return; 00463 } 00464 00465 # generate new image ID 00466 $this->Id = $this->GenerateNewImageId(); 00467 00468 # generate file names 00469 $this->SetFileNames(); 00470 00471 # copy attributes from source image 00472 $this->Format = $SrcImage->Format(); 00473 $this->AltText = $SrcImage->AltText(); 00474 $this->Width = $SrcImage->Width(); 00475 $this->Height = $SrcImage->Height(); 00476 $this->PreviewWidth = $SrcImage->PreviewWidth(); 00477 $this->PreviewHeight = $SrcImage->PreviewHeight(); 00478 $this->ThumbnailWidth = $SrcImage->ThumbnailWidth(); 00479 $this->ThumbnailHeight = $SrcImage->ThumbnailHeight(); 00480 00481 # copy source image files 00482 copy($SrcImage->Url(), $this->FileName); 00483 copy($SrcImage->PreviewUrl(), $this->PreviewFileName); 00484 copy($SrcImage->ThumbnailUrl(), $this->ThumbnailFileName); 00485 00486 # save image attributes to database 00487 $this->SaveImageInfo(); 00488 } 00489 00490 # generate and save image, preview, and thumnail file names 00491 # (requires image ID and format to be set beforehand) 00492 function SetFileNames() 00493 { 00494 if (Image::Extension($this->Format)) 00495 { 00496 $FileExtension = Image::Extension($this->Format); 00497 } 00498 else 00499 { 00500 $FileExtension = ""; 00501 } 00502 00503 $this->FileName = self::IMAGE_PATH . "Img--" 00504 .sprintf("%08d.", $this->Id).$FileExtension; 00505 $this->PreviewFileName = self::PREVIEW_PATH . "Preview--" 00506 .sprintf("%08d.", $this->Id).$FileExtension; 00507 $this->ThumbnailFileName = self::THUMBNAIL_PATH . "Thumb--" 00508 .sprintf("%08d.", $this->Id).$FileExtension; 00509 } 00510 00511 # retrieve next image ID 00512 function GenerateNewImageId() 00513 { 00514 # look up highest image ID in database 00515 $CurrentHighestId = $this->DB->Query("SELECT ImageId FROM Images" 00516 ." ORDER BY ImageId DESC LIMIT 1", 00517 "ImageId"); 00518 00519 # return next highest ID or 1 if no ID yet used 00520 return ($CurrentHighestId > 0) ? ($CurrentHighestId + 1) : 1; 00521 } 00522 00523 # store image attributes to database 00524 function SaveImageInfo() 00525 { 00526 # look for existing image record with matching ID 00527 $RecordCount = $this->DB->Query("SELECT COUNT(*) AS RecordCount FROM Images" 00528 ." WHERE ImageId = ".$this->Id, 00529 "RecordCount"); 00530 00531 # if matching ID found 00532 if ($RecordCount > 0) 00533 { 00534 # update existing image record 00535 $this->DB->Query("UPDATE Images SET" 00536 ." Format = '" .$this->Format."'," 00537 ." AltText = '" .addslashes($this->AltText)."'," 00538 ." Height = '" .$this->Height."'," 00539 ." Width = '" .$this->Width."'," 00540 ." PreviewHeight = '" .$this->PreviewHeight."'," 00541 ." PreviewWidth = '" .$this->PreviewWidth."'," 00542 ." ThumbnailHeight = '".$this->ThumbnailHeight."'," 00543 ." ThumbnailWidth = '" .$this->ThumbnailWidth."'" 00544 ." WHERE ImageId = ".$this->Id); 00545 } 00546 else 00547 { 00548 # add new image record 00549 $this->DB->Query("INSERT INTO Images SET" 00550 ." ImageId = '" .$this->Id."'," 00551 ." Format = '" .$this->Format."'," 00552 ." AltText = '" .addslashes($this->AltText)."'," 00553 ." Height = '" .$this->Height."'," 00554 ." Width = '" .$this->Width."'," 00555 ." PreviewHeight = '" .$this->PreviewHeight."'," 00556 ." PreviewWidth = '" .$this->PreviewWidth."'," 00557 ." ThumbnailHeight = '".$this->ThumbnailHeight."'," 00558 ." ThumbnailWidth = '" .$this->ThumbnailWidth."'"); 00559 } 00560 } 00561 }