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 # set base path for image storage 00049 # (NOTE: This is also used for URLs, so it must be a relative path.) 00050 # (NOTE: These must match paths in SPTImage::CheckDirectories()!!!) 00051 $this->ImagePath = "ImageStorage/"; 00052 $this->PreviewPath = $this->ImagePath."Previews/"; 00053 $this->ThumbnailPath = $this->ImagePath."Thumbnails/"; 00054 00055 # create and save a database handle for our use 00056 $this->DB = new SPTDatabase(); 00057 00058 # if image object was passed in 00059 if (is_object($ImageIdOrFileNameOrImageObj) 00060 && method_exists($ImageIdOrFileNameOrImageObj, "SPTImage")) 00061 { 00062 # create copy of image passed in 00063 $this->CreateCopyOfImage($ImageIdOrFileNameOrImageObj); 00064 } 00065 # else if image ID was passed in 00066 elseif (($ImageIdOrFileNameOrImageObj > 0) 00067 && preg_match("/[0-9]+/", $ImageIdOrFileNameOrImageObj)) 00068 { 00069 # load info on existing image 00070 $this->LoadImageInfo($ImageIdOrFileNameOrImageObj); 00071 } 00072 # else assume that value passed in is file name 00073 else 00074 { 00075 # create new image from named file 00076 $this->CreateNewImage($ImageIdOrFileNameOrImageObj, 00077 $MaxPreviewWidth, $MaxPreviewHeight, 00078 $MaxThumbnailWidth, $MaxThumbnailHeight); 00079 } 00080 } 00081 00082 # get attributes 00083 function Id() { return $this->Id; } 00084 function Url() { return $this->FileName; } 00085 function PreviewUrl() { return $this->PreviewFileName; } 00086 function ThumbnailUrl() { return $this->ThumbnailFileName; } 00087 function Format() { return $this->Format; } 00088 function Height() { return $this->Height; } 00089 function Width() { return $this->Width; } 00090 function PreviewHeight() { return $this->PreviewHeight; } 00091 function PreviewWidth() { return $this->PreviewWidth; } 00092 function ThumbnailHeight() { return $this->ThumbnailHeight; } 00093 function ThumbnailWidth() { return $this->ThumbnailWidth; } 00094 function ImageStorageDirectory() { return $this->ImagePath; } 00095 function PreviewStorageDirectory() { return $this->PreviewPath; } 00096 function ThumbnailStorageDirectory() { return $this->ThumbnailPath; } 00097 function GetLink() { return $this->FileName; } 00098 00099 # get/set attributes 00100 function AltText($NewValue = NULL) 00101 { 00102 # if new value supplied and new value differs from existing value 00103 if (($NewValue !== NULL) && ($NewValue != $this->AltText)) 00104 { 00105 # save new value to database 00106 $this->DB->Query("UPDATE Images SET" 00107 ." AltText = '".addslashes($NewValue)."'" 00108 ." WHERE ImageId = ".$this->Id); 00109 00110 # save new value locally 00111 $this->AltText = $NewValue; 00112 } 00113 00114 # return attribute value to caller 00115 return $this->AltText; 00116 } 00117 00118 # delete image and associated files and data 00119 function Delete() 00120 { 00121 # delete base image file 00122 if (file_exists($this->FileName)) { unlink($this->FileName); } 00123 00124 # delete preview image file 00125 if (file_exists($this->PreviewFileName)) { unlink($this->PreviewFileName); } 00126 00127 # delete thumbnail image file 00128 if (file_exists($this->ThumbnailFileName)) { unlink($this->ThumbnailFileName); } 00129 00130 # delete image info record in database 00131 $this->DB->Query("DELETE FROM Images WHERE ImageId = ".$this->Id); 00132 } 00133 00134 # return error status set by the constructor 00135 function Status() 00136 { 00137 return $this->ErrorStatus; 00138 } 00139 00140 # check to make sure image storage directories are available 00141 # (returns array of error codes or NULL if no errors found) 00142 # (may be called statically) 00143 function CheckDirectories() 00144 { 00145 # determine paths 00146 # (NOTE: These must match paths in the constructur!!!) 00147 $ImagePath = "ImageStorage/"; 00148 $PreviewPath = $ImagePath."Previews/"; 00149 $ThumbnailPath = $ImagePath."Thumbnails/"; 00150 00151 # assume everything will be okay 00152 $ErrorsFound = NULL; 00153 00154 # check base image directory 00155 if (!is_dir($ImagePath) || !is_writable($ImagePath)) 00156 { 00157 if (!is_dir($ImagePath)) 00158 { 00159 @mkdir($ImagePath, 0755); 00160 } 00161 else 00162 { 00163 @chmod($ImagePath, 0755); 00164 } 00165 if (!is_dir($ImagePath)) 00166 { 00167 $ErrorsFound[] = "Image Storage Directory Not Found"; 00168 } 00169 elseif (!is_writable($ImagePath)) 00170 { 00171 $ErrorsFound[] = "Image Storage Directory Not Writable"; 00172 } 00173 } 00174 00175 # check preview directory 00176 if (!is_dir($PreviewPath) || !is_writable($PreviewPath)) 00177 { 00178 if (!is_dir($PreviewPath)) 00179 { 00180 @mkdir($PreviewPath, 0755); 00181 } 00182 else 00183 { 00184 @chmod($PreviewPath, 0755); 00185 } 00186 if (!is_dir($PreviewPath)) 00187 { 00188 $ErrorsFound[] = "Preview Storage Directory Not Found"; 00189 } 00190 elseif (!is_writable($PreviewPath)) 00191 { 00192 $ErrorsFound[] = "Preview Storage Directory Not Writable"; 00193 } 00194 } 00195 00196 # check thumbnail directory 00197 if (!is_dir($ThumbnailPath) || !is_writable($ThumbnailPath)) 00198 { 00199 if (!is_dir($ThumbnailPath)) 00200 { 00201 @mkdir($ThumbnailPath, 0755); 00202 } 00203 else 00204 { 00205 @chmod($ThumbnailPath, 0755); 00206 } 00207 if (!is_dir($ThumbnailPath)) 00208 { 00209 $ErrorsFound[] = "Thumbnail Storage Directory Not Found"; 00210 } 00211 elseif (!is_writable($ThumbnailPath)) 00212 { 00213 $ErrorsFound[] = "Thumbnail Storage Directory Not Writable"; 00214 } 00215 } 00216 00217 # return any errors found to caller 00218 return $ErrorsFound; 00219 } 00220 00221 00222 # ---- PRIVATE INTERFACE ------------------------------------------------- 00223 00224 var $Id; 00225 var $FileName; 00226 var $ImagePath; 00227 var $PreviewPath; 00228 var $ThumbnailPath; 00229 var $PreviewFileName; 00230 var $ThumbnailFileName; 00231 var $Format; 00232 var $AltText; 00233 var $Url; 00234 var $PreviewUrl; 00235 var $ThumbnailUrl; 00236 var $Height; 00237 var $Width; 00238 var $PreviewHeight; 00239 var $PreviewWidth; 00240 var $ThumbnailHeight; 00241 var $ThumbnailWidth; 00242 var $DB; 00243 var $ErrorStatus; 00244 00245 function CreateNewImage($FileName, $MaxPreviewWidth, $MaxPreviewHeight, 00246 $MaxThumbnailWidth, $MaxThumbnailHeight) 00247 { 00248 # if file does not exist or is not readable 00249 if (!is_readable($FileName)) 00250 { 00251 # set error status 00252 $this->ErrorStatus = AI_FILEUNREADABLE; 00253 } 00254 else 00255 { 00256 # if image is invalid or unsupported type 00257 $SrcImage = new Image($FileName); 00258 if ($SrcImage->Status() != AI_OKAY) 00259 { 00260 # set error status 00261 $this->ErrorStatus = $SrcImage->Status(); 00262 } 00263 else 00264 { 00265 # retrieve image type 00266 $this->Format = $SrcImage->Type(); 00267 00268 # generate new image ID 00269 $this->Id = $this->GenerateNewImageId(); 00270 00271 # generate and set file names 00272 $this->SetFileNames(); 00273 00274 # if our image file name differs from file name passed in 00275 if (realpath($this->FileName) != realpath($FileName)) 00276 { 00277 # create image file 00278 $SrcImage->SaveAs($this->FileName); 00279 00280 # if create failed set error status and bail out 00281 if ($SrcImage->Status() != AI_OKAY) 00282 { 00283 echo "create failed<br>"; 00284 echo "Status: ".$SrcImage->Status()."<br>"; 00285 echo "Failed Command: ".$SrcImage->FailedExternalCommand()."<br>"; 00286 echo "Missing External Executables: "; 00287 print_r(Image::MissingExternalExecutables()); 00288 echo "<br>"; 00289 $this->ErrorStatus = $SrcImage->Status(); 00290 return; 00291 } 00292 } 00293 00294 # retrieve image width and height 00295 $this->Height = $SrcImage->YSize(); 00296 $this->Width = $SrcImage->XSize(); 00297 00298 # generate preview image and calculate width and height 00299 $MaxPreviewWidth = min($MaxPreviewWidth, $this->Width); 00300 $MaxPreviewHeight = min($MaxPreviewHeight, $this->Height); 00301 $SrcImage->ScaleTo($MaxPreviewWidth, $MaxPreviewHeight, TRUE); 00302 $SrcImage->SaveAs($this->PreviewFileName, IMGTYPE_JPEG); 00303 if ($SrcImage->Status() != AI_OKAY) 00304 { 00305 echo "preview save as failed<br>"; 00306 $this->ErrorStatus = $SrcImage->Status(); 00307 return; 00308 } 00309 if (($this->Width * $MaxPreviewHeight) 00310 > ($this->Height * $MaxPreviewWidth)) 00311 { 00312 $this->PreviewWidth = $MaxPreviewWidth; 00313 $this->PreviewHeight = 00314 ($MaxPreviewWidth * $SrcImage->YSize()) / $SrcImage->XSize(); 00315 } 00316 else 00317 { 00318 $this->PreviewWidth = 00319 ($MaxPreviewHeight * $SrcImage->XSize()) / $SrcImage->YSize(); 00320 $this->PreviewHeight = $MaxPreviewHeight; 00321 } 00322 00323 # generate thumbnail image and calculate width and height 00324 $MaxThumbnailWidth = min($MaxThumbnailWidth, $this->Width); 00325 $MaxThumbnailHeight = min($MaxThumbnailHeight, $this->Height); 00326 $SrcImage->ScaleTo($MaxThumbnailWidth, $MaxThumbnailHeight, TRUE); 00327 $SrcImage->SaveAs($this->ThumbnailFileName, IMGTYPE_JPEG); 00328 if ($SrcImage->Status() != AI_OKAY) 00329 { 00330 echo "thumbnail SaveAs failed.<br>"; 00331 $this->ErrorStatus = $SrcImage->Status(); 00332 return; 00333 } 00334 if (($this->Width * $MaxThumbnailHeight) 00335 > ($this->Height * $MaxThumbnailWidth)) 00336 { 00337 $this->ThumbnailWidth = $MaxThumbnailWidth; 00338 $this->ThumbnailHeight = 00339 ($MaxThumbnailWidth * $SrcImage->YSize()) / $SrcImage->XSize(); 00340 } 00341 else 00342 { 00343 $this->ThumbnailWidth = ($MaxThumbnailHeight * $SrcImage->XSize()) / $SrcImage->YSize(); 00344 $this->ThumbnailHeight = $MaxThumbnailHeight; 00345 } 00346 00347 # save image attributes to database 00348 $this->SaveImageInfo(); 00349 } 00350 } 00351 } 00352 00353 function LoadImageInfo($ImageId) 00354 { 00355 # save image ID 00356 $this->Id = $ImageId; 00357 00358 # load image record from database 00359 $this->DB->Query("SELECT * FROM Images WHERE ImageId = ".$ImageId); 00360 $Record = $this->DB->FetchRow(); 00361 00362 # load in values from record 00363 $this->Format = $Record["Format"]; 00364 $this->AltText = $Record["AltText"]; 00365 $this->Height = $Record["Height"]; 00366 $this->Width = $Record["Width"]; 00367 $this->PreviewHeight = $Record["PreviewHeight"]; 00368 $this->PreviewWidth = $Record["PreviewWidth"]; 00369 $this->ThumbnailHeight = $Record["ThumbnailHeight"]; 00370 $this->ThumbnailWidth = $Record["ThumbnailWidth"]; 00371 00372 # generate file names 00373 $this->SetFileNames(); 00374 } 00375 00376 function CreateCopyOfImage($SrcImage) 00377 { 00378 # generate new image ID 00379 $this->Id = $this->GenerateNewImageId(); 00380 00381 # generate file names 00382 $this->SetFileNames(); 00383 00384 # copy attributes from source image 00385 $this->Format = $SrcImage->Format(); 00386 $this->AltText = $SrcImage->AltText(); 00387 $this->Width = $SrcImage->Width(); 00388 $this->Height = $SrcImage->Height(); 00389 $this->PreviewWidth = $SrcImage->PreviewWidth(); 00390 $this->PreviewHeight = $SrcImage->PreviewHeight(); 00391 $this->ThumbnailWidth = $SrcImage->ThumbnailWidth(); 00392 $this->ThumbnailHeight = $SrcImage->ThumbnailHeight(); 00393 00394 # copy source image files 00395 copy($SrcImage->Url(), $this->FileName); 00396 copy($SrcImage->PreviewUrl(), $this->PreviewFileName); 00397 copy($SrcImage->ThumbnailUrl(), $this->ThumbnailFileName); 00398 00399 # save image attributes to database 00400 $this->SaveImageInfo(); 00401 } 00402 00403 # generate and save image, preview, and thumnail file names 00404 # (requires image ID and format to be set beforehand) 00405 function SetFileNames() 00406 { 00407 if (Image::Extension($this->Format)) 00408 { 00409 $FileExtension = Image::Extension($this->Format); 00410 } 00411 else 00412 { 00413 $FileExtension = ""; 00414 } 00415 00416 $this->FileName = $this->ImagePath."Img--" 00417 .sprintf("%08d.", $this->Id).$FileExtension; 00418 $this->PreviewFileName = $this->PreviewPath."Preview--" 00419 .sprintf("%08d.", $this->Id).$FileExtension; 00420 $this->ThumbnailFileName = $this->ThumbnailPath."Thumb--" 00421 .sprintf("%08d.", $this->Id).$FileExtension; 00422 } 00423 00424 # retrieve next image ID 00425 function GenerateNewImageId() 00426 { 00427 # look up highest image ID in database 00428 $CurrentHighestId = $this->DB->Query("SELECT ImageId FROM Images" 00429 ." ORDER BY ImageId DESC LIMIT 1", 00430 "ImageId"); 00431 00432 # return next highest ID or 1 if no ID yet used 00433 return ($CurrentHighestId > 0) ? ($CurrentHighestId + 1) : 1; 00434 } 00435 00436 # store image attributes to database 00437 function SaveImageInfo() 00438 { 00439 # look for existing image record with matching ID 00440 $RecordCount = $this->DB->Query("SELECT COUNT(*) AS RecordCount FROM Images" 00441 ." WHERE ImageId = ".$this->Id, 00442 "RecordCount"); 00443 00444 # if matching ID found 00445 if ($RecordCount > 0) 00446 { 00447 # update existing image record 00448 $this->DB->Query("UPDATE Images SET" 00449 ." Format = '" .$this->Format."'," 00450 ." AltText = '" .addslashes($this->AltText)."'," 00451 ." Height = '" .$this->Height."'," 00452 ." Width = '" .$this->Width."'," 00453 ." PreviewHeight = '" .$this->PreviewHeight."'," 00454 ." PreviewWidth = '" .$this->PreviewWidth."'," 00455 ." ThumbnailHeight = '".$this->ThumbnailHeight."'," 00456 ." ThumbnailWidth = '" .$this->ThumbnailWidth."'" 00457 ." WHERE ImageId = ".$this->Id); 00458 } 00459 else 00460 { 00461 # add new image record 00462 $this->DB->Query("INSERT INTO Images SET" 00463 ." ImageId = '" .$this->Id."'," 00464 ." Format = '" .$this->Format."'," 00465 ." AltText = '" .addslashes($this->AltText)."'," 00466 ." Height = '" .$this->Height."'," 00467 ." Width = '" .$this->Width."'," 00468 ." PreviewHeight = '" .$this->PreviewHeight."'," 00469 ." PreviewWidth = '" .$this->PreviewWidth."'," 00470 ." ThumbnailHeight = '".$this->ThumbnailHeight."'," 00471 ." ThumbnailWidth = '" .$this->ThumbnailWidth."'"); 00472 } 00473 } 00474 } 00475 00476 00477 ?>