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 ?>