SPTImage.php
Go to the documentation of this file.
00001 <?PHP 00002 00003 # 00004 # FILE: SPT--SPTImage.php 00005 # 00006 # METHODS PROVIDED: 00007 # SPTImage($ImageIdOrFileNameOrImageObj, 00008 # $MaxPreviewWidth = NULL, $MaxPreviewHeight = NULL, 00009 # $MaxThumbnailWidth = NULL, $MaxThumbnailHeight = NULL) 00010 # - object constructor 00011 # Delete() 00012 # - delete image and associated files and data 00013 # AltText($NewValue = NULL) 00014 # - get/set alt text attribute 00015 # Id() 00016 # Url() 00017 # PreviewUrl() 00018 # ThumbnailUrl() 00019 # Format() 00020 # Height() 00021 # Width() 00022 # PreviewHeight() 00023 # PreviewWidth() 00024 # ThumbnailHeight() 00025 # ThumbnailWidth() 00026 # - get attributes 00027 # 00028 # AUTHOR: Edward Almasy 00029 # 00030 # Part of the Scout Portal Toolkit 00031 # Copyright 2002-2003 Internet Scout Project 00032 # http://scout.wisc.edu 00033 # 00034 00035 00036 class SPTImage { 00037 00038 # ---- PUBLIC INTERFACE -------------------------------------------------- 00039 00040 # object constructor 00041 function SPTImage($ImageIdOrFileNameOrImageObj, 00042 $MaxPreviewWidth = NULL, $MaxPreviewHeight = NULL, 00043 $MaxThumbnailWidth = NULL, $MaxThumbnailHeight = NULL) 00044 { 00045 # clear error status (0 = AI_OKAY) 00046 $this->ErrorStatus = 0; 00047 00048 # trigger the Image class file to be autoloaded since some parts of this 00049 # class (SPTImage) use constants defined in it but don't construct Image 00050 # objects 00051 new Image(NULL); 00052 00053 # set base path for image storage 00054 # (NOTE: This is also used for URLs, so it must be a relative path.) 00055 # (NOTE: These must match paths in SPTImage::CheckDirectories()!!!) 00056 $this->ImagePath = "ImageStorage/"; 00057 $this->PreviewPath = $this->ImagePath."Previews/"; 00058 $this->ThumbnailPath = $this->ImagePath."Thumbnails/"; 00059 00060 # create and save a database handle for our use 00061 $this->DB = new SPTDatabase(); 00062 00063 # if image object was passed in 00064 if (is_object($ImageIdOrFileNameOrImageObj) 00065 && method_exists($ImageIdOrFileNameOrImageObj, "SPTImage")) 00066 { 00067 # create copy of image passed in 00068 $this->CreateCopyOfImage($ImageIdOrFileNameOrImageObj); 00069 } 00070 # else if image ID was passed in 00071 elseif (($ImageIdOrFileNameOrImageObj > 0) 00072 && preg_match("/[0-9]+/", $ImageIdOrFileNameOrImageObj)) 00073 { 00074 # load info on existing image 00075 $this->LoadImageInfo($ImageIdOrFileNameOrImageObj); 00076 } 00077 # else assume that value passed in is file name 00078 else 00079 { 00080 # create new image from named file 00081 $this->CreateNewImage($ImageIdOrFileNameOrImageObj, 00082 $MaxPreviewWidth, $MaxPreviewHeight, 00083 $MaxThumbnailWidth, $MaxThumbnailHeight); 00084 } 00085 } 00086 00087 # get attributes 00088 function Id() { return $this->Id; } 00089 function Url() { return $this->FileName; } 00090 function PreviewUrl() { return $this->PreviewFileName; } 00091 function ThumbnailUrl() { return $this->ThumbnailFileName; } 00092 function Format() { return $this->Format; } 00093 function Height() { return $this->Height; } 00094 function Width() { return $this->Width; } 00095 function PreviewHeight() { return $this->PreviewHeight; } 00096 function PreviewWidth() { return $this->PreviewWidth; } 00097 function ThumbnailHeight() { return $this->ThumbnailHeight; } 00098 function ThumbnailWidth() { return $this->ThumbnailWidth; } 00099 function ImageStorageDirectory() { return $this->ImagePath; } 00100 function PreviewStorageDirectory() { return $this->PreviewPath; } 00101 function ThumbnailStorageDirectory() { return $this->ThumbnailPath; } 00102 function GetLink() { return $this->FileName; } 00103 00104 # get/set attributes 00105 function AltText($NewValue = NULL) 00106 { 00107 # if new value supplied and new value differs from existing value 00108 if (($NewValue !== NULL) && ($NewValue != $this->AltText)) 00109 { 00110 # save new value to database 00111 $this->DB->Query("UPDATE Images SET" 00112 ." AltText = '".addslashes($NewValue)."'" 00113 ." WHERE ImageId = ".$this->Id); 00114 00115 # save new value locally 00116 $this->AltText = $NewValue; 00117 } 00118 00119 # return attribute value to caller 00120 return $this->AltText; 00121 } 00122 00123 # delete image and associated files and data 00124 function Delete() 00125 { 00126 # delete base image file 00127 if (file_exists($this->FileName)) { unlink($this->FileName); } 00128 00129 # delete preview image file 00130 if (file_exists($this->PreviewFileName)) { unlink($this->PreviewFileName); } 00131 00132 # delete thumbnail image file 00133 if (file_exists($this->ThumbnailFileName)) { unlink($this->ThumbnailFileName); } 00134 00135 # delete image info record in database 00136 $this->DB->Query("DELETE FROM Images WHERE ImageId = ".$this->Id); 00137 } 00138 00139 # return error status set by the constructor 00140 function Status() 00141 { 00142 return $this->ErrorStatus; 00143 } 00144 00145 # check to make sure image storage directories are available 00146 # (returns array of error codes or NULL if no errors found) 00147 # (may be called statically) 00148 function CheckDirectories() 00149 { 00150 # determine paths 00151 # (NOTE: These must match paths in the constructur!!!) 00152 $ImagePath = "ImageStorage/"; 00153 $PreviewPath = $ImagePath."Previews/"; 00154 $ThumbnailPath = $ImagePath."Thumbnails/"; 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 00227 # ---- PRIVATE INTERFACE ------------------------------------------------- 00228 00229 var $Id; 00230 var $FileName; 00231 var $ImagePath; 00232 var $PreviewPath; 00233 var $ThumbnailPath; 00234 var $PreviewFileName; 00235 var $ThumbnailFileName; 00236 var $Format; 00237 var $AltText; 00238 var $Url; 00239 var $PreviewUrl; 00240 var $ThumbnailUrl; 00241 var $Height; 00242 var $Width; 00243 var $PreviewHeight; 00244 var $PreviewWidth; 00245 var $ThumbnailHeight; 00246 var $ThumbnailWidth; 00247 var $DB; 00248 var $ErrorStatus; 00249 00250 function CreateNewImage($FileName, $MaxPreviewWidth, $MaxPreviewHeight, 00251 $MaxThumbnailWidth, $MaxThumbnailHeight) 00252 { 00253 # if file does not exist or is not readable 00254 if (!is_readable($FileName)) 00255 { 00256 # set error status 00257 $this->ErrorStatus = AI_FILEUNREADABLE; 00258 } 00259 else 00260 { 00261 # if image is invalid or unsupported type 00262 $SrcImage = new Image($FileName); 00263 if ($SrcImage->Status() != AI_OKAY) 00264 { 00265 # set error status 00266 $this->ErrorStatus = $SrcImage->Status(); 00267 } 00268 else 00269 { 00270 # retrieve image type 00271 $this->Format = $SrcImage->Type(); 00272 00273 # generate new image ID 00274 $this->Id = $this->GenerateNewImageId(); 00275 00276 # generate and set file names 00277 $this->SetFileNames(); 00278 00279 # if our image file name differs from file name passed in 00280 if (realpath($this->FileName) != realpath($FileName)) 00281 { 00282 # create image file 00283 $SrcImage->SaveAs($this->FileName); 00284 00285 # if create failed set error status and bail out 00286 if ($SrcImage->Status() != AI_OKAY) 00287 { 00288 echo "create failed<br>"; 00289 echo "Status: ".$SrcImage->Status()."<br>"; 00290 echo "Failed Command: ".$SrcImage->FailedExternalCommand()."<br>"; 00291 echo "Missing External Executables: "; 00292 print_r(Image::MissingExternalExecutables()); 00293 echo "<br>"; 00294 $this->ErrorStatus = $SrcImage->Status(); 00295 return; 00296 } 00297 } 00298 00299 # retrieve image width and height 00300 $this->Height = $SrcImage->YSize(); 00301 $this->Width = $SrcImage->XSize(); 00302 00303 # generate preview image and calculate width and height 00304 $MaxPreviewWidth = min($MaxPreviewWidth, $this->Width); 00305 $MaxPreviewHeight = min($MaxPreviewHeight, $this->Height); 00306 $SrcImage->ScaleTo($MaxPreviewWidth, $MaxPreviewHeight, TRUE); 00307 $SrcImage->SaveAs($this->PreviewFileName, IMGTYPE_JPEG); 00308 if ($SrcImage->Status() != AI_OKAY) 00309 { 00310 echo "preview save as failed<br>"; 00311 $this->ErrorStatus = $SrcImage->Status(); 00312 return; 00313 } 00314 if (($this->Width * $MaxPreviewHeight) 00315 > ($this->Height * $MaxPreviewWidth)) 00316 { 00317 $this->PreviewWidth = $MaxPreviewWidth; 00318 $this->PreviewHeight = 00319 ($MaxPreviewWidth * $SrcImage->YSize()) / $SrcImage->XSize(); 00320 } 00321 else 00322 { 00323 $this->PreviewWidth = 00324 ($MaxPreviewHeight * $SrcImage->XSize()) / $SrcImage->YSize(); 00325 $this->PreviewHeight = $MaxPreviewHeight; 00326 } 00327 00328 # generate thumbnail image and calculate width and height 00329 $MaxThumbnailWidth = min($MaxThumbnailWidth, $this->Width); 00330 $MaxThumbnailHeight = min($MaxThumbnailHeight, $this->Height); 00331 $SrcImage->ScaleTo($MaxThumbnailWidth, $MaxThumbnailHeight, TRUE); 00332 $SrcImage->SaveAs($this->ThumbnailFileName, IMGTYPE_JPEG); 00333 if ($SrcImage->Status() != AI_OKAY) 00334 { 00335 echo "thumbnail SaveAs failed.<br>"; 00336 $this->ErrorStatus = $SrcImage->Status(); 00337 return; 00338 } 00339 if (($this->Width * $MaxThumbnailHeight) 00340 > ($this->Height * $MaxThumbnailWidth)) 00341 { 00342 $this->ThumbnailWidth = $MaxThumbnailWidth; 00343 $this->ThumbnailHeight = 00344 ($MaxThumbnailWidth * $SrcImage->YSize()) / $SrcImage->XSize(); 00345 } 00346 else 00347 { 00348 $this->ThumbnailWidth = ($MaxThumbnailHeight * $SrcImage->XSize()) / $SrcImage->YSize(); 00349 $this->ThumbnailHeight = $MaxThumbnailHeight; 00350 } 00351 00352 # save image attributes to database 00353 $this->SaveImageInfo(); 00354 } 00355 } 00356 } 00357 00358 function LoadImageInfo($ImageId) 00359 { 00360 # save image ID 00361 $this->Id = $ImageId; 00362 00363 # load image record from database 00364 $this->DB->Query("SELECT * FROM Images WHERE ImageId = ".$ImageId); 00365 00366 # if the ID is invalid 00367 if (!$this->DB->NumRowsSelected()) 00368 { 00369 $this->ErrorStatus = AI_INTERNALERROR; 00370 return; 00371 } 00372 00373 $Record = $this->DB->FetchRow(); 00374 00375 # load in values from record 00376 $this->Format = $Record["Format"]; 00377 $this->AltText = $Record["AltText"]; 00378 $this->Height = $Record["Height"]; 00379 $this->Width = $Record["Width"]; 00380 $this->PreviewHeight = $Record["PreviewHeight"]; 00381 $this->PreviewWidth = $Record["PreviewWidth"]; 00382 $this->ThumbnailHeight = $Record["ThumbnailHeight"]; 00383 $this->ThumbnailWidth = $Record["ThumbnailWidth"]; 00384 00385 # generate file names 00386 $this->SetFileNames(); 00387 } 00388 00389 function CreateCopyOfImage($SrcImage) 00390 { 00391 $Image = new Image($SrcImage->Url()); 00392 if ($Image->Status() != AI_OKAY) 00393 { 00394 # set error status 00395 $this->ErrorStatus = $Image->Status(); 00396 return; 00397 } 00398 00399 # generate new image ID 00400 $this->Id = $this->GenerateNewImageId(); 00401 00402 # generate file names 00403 $this->SetFileNames(); 00404 00405 # copy attributes from source image 00406 $this->Format = $SrcImage->Format(); 00407 $this->AltText = $SrcImage->AltText(); 00408 $this->Width = $SrcImage->Width(); 00409 $this->Height = $SrcImage->Height(); 00410 $this->PreviewWidth = $SrcImage->PreviewWidth(); 00411 $this->PreviewHeight = $SrcImage->PreviewHeight(); 00412 $this->ThumbnailWidth = $SrcImage->ThumbnailWidth(); 00413 $this->ThumbnailHeight = $SrcImage->ThumbnailHeight(); 00414 00415 # copy source image files 00416 copy($SrcImage->Url(), $this->FileName); 00417 copy($SrcImage->PreviewUrl(), $this->PreviewFileName); 00418 copy($SrcImage->ThumbnailUrl(), $this->ThumbnailFileName); 00419 00420 # save image attributes to database 00421 $this->SaveImageInfo(); 00422 } 00423 00424 # generate and save image, preview, and thumnail file names 00425 # (requires image ID and format to be set beforehand) 00426 function SetFileNames() 00427 { 00428 if (Image::Extension($this->Format)) 00429 { 00430 $FileExtension = Image::Extension($this->Format); 00431 } 00432 else 00433 { 00434 $FileExtension = ""; 00435 } 00436 00437 $this->FileName = $this->ImagePath."Img--" 00438 .sprintf("%08d.", $this->Id).$FileExtension; 00439 $this->PreviewFileName = $this->PreviewPath."Preview--" 00440 .sprintf("%08d.", $this->Id).$FileExtension; 00441 $this->ThumbnailFileName = $this->ThumbnailPath."Thumb--" 00442 .sprintf("%08d.", $this->Id).$FileExtension; 00443 } 00444 00445 # retrieve next image ID 00446 function GenerateNewImageId() 00447 { 00448 # look up highest image ID in database 00449 $CurrentHighestId = $this->DB->Query("SELECT ImageId FROM Images" 00450 ." ORDER BY ImageId DESC LIMIT 1", 00451 "ImageId"); 00452 00453 # return next highest ID or 1 if no ID yet used 00454 return ($CurrentHighestId > 0) ? ($CurrentHighestId + 1) : 1; 00455 } 00456 00457 # store image attributes to database 00458 function SaveImageInfo() 00459 { 00460 # look for existing image record with matching ID 00461 $RecordCount = $this->DB->Query("SELECT COUNT(*) AS RecordCount FROM Images" 00462 ." WHERE ImageId = ".$this->Id, 00463 "RecordCount"); 00464 00465 # if matching ID found 00466 if ($RecordCount > 0) 00467 { 00468 # update existing image record 00469 $this->DB->Query("UPDATE Images SET" 00470 ." Format = '" .$this->Format."'," 00471 ." AltText = '" .addslashes($this->AltText)."'," 00472 ." Height = '" .$this->Height."'," 00473 ." Width = '" .$this->Width."'," 00474 ." PreviewHeight = '" .$this->PreviewHeight."'," 00475 ." PreviewWidth = '" .$this->PreviewWidth."'," 00476 ." ThumbnailHeight = '".$this->ThumbnailHeight."'," 00477 ." ThumbnailWidth = '" .$this->ThumbnailWidth."'" 00478 ." WHERE ImageId = ".$this->Id); 00479 } 00480 else 00481 { 00482 # add new image record 00483 $this->DB->Query("INSERT INTO Images SET" 00484 ." ImageId = '" .$this->Id."'," 00485 ." Format = '" .$this->Format."'," 00486 ." AltText = '" .addslashes($this->AltText)."'," 00487 ." Height = '" .$this->Height."'," 00488 ." Width = '" .$this->Width."'," 00489 ." PreviewHeight = '" .$this->PreviewHeight."'," 00490 ." PreviewWidth = '" .$this->PreviewWidth."'," 00491 ." ThumbnailHeight = '".$this->ThumbnailHeight."'," 00492 ." ThumbnailWidth = '" .$this->ThumbnailWidth."'"); 00493 } 00494 } 00495 } 00496 00497 00498 ?>