5 # Part of the Collection Workflow Integration System (CWIS)
6 # Copyright 2002-2013 Edward Almasy and Internet Scout Research Group
7 # http://scout.wisc.edu/cwis/
15 # ---- PUBLIC INTERFACE --------------------------------------------------
36 function SPTImage($ImageIdOrFileNameOrImageObj,
37 $MaxWidth = NULL, $MaxHeight = NULL,
38 $MaxPreviewWidth = NULL, $MaxPreviewHeight = NULL,
39 $MaxThumbnailWidth = NULL, $MaxThumbnailHeight = NULL)
41 # clear error status (0 = AI_OKAY)
42 $this->ErrorStatus = 0;
44 # trigger the Image class file to be autoloaded since some parts of this
45 # class (SPTImage) use constants defined in it but don't construct Image
49 # create and save a database handle for our use
52 # if image object was passed in
53 if (is_object($ImageIdOrFileNameOrImageObj)
54 && method_exists($ImageIdOrFileNameOrImageObj,
"SPTImage"))
56 # create copy of image passed in
57 $this->CreateCopyOfImage($ImageIdOrFileNameOrImageObj);
59 # else if image ID was passed in
60 elseif (($ImageIdOrFileNameOrImageObj > 0)
61 && preg_match(
"/[0-9]+/", $ImageIdOrFileNameOrImageObj))
63 # load info on existing image
64 $this->LoadImageInfo($ImageIdOrFileNameOrImageObj);
66 # else assume that value passed in is file name
69 # create new image from named file
70 $this->CreateNewImage($ImageIdOrFileNameOrImageObj,
71 $MaxWidth, $MaxHeight,
72 $MaxPreviewWidth, $MaxPreviewHeight,
73 $MaxThumbnailWidth, $MaxThumbnailHeight);
81 function Id() {
return $this->Id; }
87 function Url() {
return $this->FileName; }
106 function Format() {
return $this->Format; }
114 $Image =
new Image($this->FileName);
115 return $Image->Mimetype();
122 function Height() {
return $this->Height; }
128 function Width() {
return $this->Width; }
160 # for each possible storage location
161 foreach (self::$ImageStorageLocations as $Dir)
166 # return location to caller
171 # return default (most preferred) location to caller
172 return self::$ImageStorageLocations[0];
181 # for each possible storage location
182 foreach (self::$PreviewStorageLocations as $Dir)
187 # return location to caller
192 # return default (most preferred) location to caller
193 return self::$PreviewStorageLocations[0];
202 # for each possible storage location
203 foreach (self::$ThumbnailStorageLocations as $Dir)
208 # return location to caller
213 # return default (most preferred) location to caller
214 return self::$ThumbnailStorageLocations[0];
221 function GetLink() {
return $this->FileName; }
231 # if new value supplied and new value differs from existing value
232 if (($NewValue !== NULL) && ($NewValue != $this->
AltText))
234 # save new value to database
235 $this->DB->Query(
"UPDATE Images SET"
236 .
" AltText = '".addslashes($NewValue).
"'"
237 .
" WHERE ImageId = ".$this->
Id);
239 # save new value locally
243 # return attribute value to caller
244 return $this->AltText;
253 # delete base image file
254 if (file_exists($this->FileName)) { unlink($this->FileName); }
256 # delete preview image file
257 if (file_exists($this->PreviewFileName)) { unlink($this->PreviewFileName); }
259 # delete thumbnail image file
260 if (file_exists($this->ThumbnailFileName)) { unlink($this->ThumbnailFileName); }
262 # delete image info record in database
263 $this->DB->Query(
"DELETE FROM Images WHERE ImageId = ".$this->
Id);
272 return $this->ErrorStatus;
283 $ImagePath = self::ImageStorageDirectory();
284 $PreviewPath = self::PreviewStorageDirectory();
285 $ThumbnailPath = self::ThumbnailStorageDirectory();
287 # assume everything will be okay
290 # check base image directory
291 if (!is_dir($ImagePath) || !is_writable($ImagePath))
293 if (!is_dir($ImagePath))
295 @mkdir($ImagePath, 0755);
299 @chmod($ImagePath, 0755);
301 if (!is_dir($ImagePath))
303 $ErrorsFound[] =
"Image Storage Directory Not Found";
305 elseif (!is_writable($ImagePath))
307 $ErrorsFound[] =
"Image Storage Directory Not Writable";
311 # check preview directory
312 if (!is_dir($PreviewPath) || !is_writable($PreviewPath))
314 if (!is_dir($PreviewPath))
316 @mkdir($PreviewPath, 0755);
320 @chmod($PreviewPath, 0755);
322 if (!is_dir($PreviewPath))
324 $ErrorsFound[] =
"Preview Storage Directory Not Found";
326 elseif (!is_writable($PreviewPath))
328 $ErrorsFound[] =
"Preview Storage Directory Not Writable";
332 # check thumbnail directory
333 if (!is_dir($ThumbnailPath) || !is_writable($ThumbnailPath))
335 if (!is_dir($ThumbnailPath))
337 @mkdir($ThumbnailPath, 0755);
341 @chmod($ThumbnailPath, 0755);
343 if (!is_dir($ThumbnailPath))
345 $ErrorsFound[] =
"Thumbnail Storage Directory Not Found";
347 elseif (!is_writable($ThumbnailPath))
349 $ErrorsFound[] =
"Thumbnail Storage Directory Not Writable";
353 # return any errors found to caller
367 public function Resize($MaxWidth, $MaxHeight,
368 $MaxPreviewWidth, $MaxPreviewHeight,
369 $MaxThumbnailWidth, $MaxThumbnailHeight)
371 $SrcImage =
new Image($this->FileName);
373 # scale the original image if necessary
374 $MaxWidth = min($MaxWidth, $SrcImage->XSize());
375 $MaxHeight = min($MaxHeight, $SrcImage->YSize());
376 $SrcImage->ScaleTo($MaxWidth, $MaxHeight, TRUE);
378 # save and reload image info
379 $SrcImage->SaveAs($this->FileName);
380 $SrcImage =
new Image($this->FileName);
382 # retrieve image width and height
383 $this->
Height = $SrcImage->YSize();
384 $this->
Width = $SrcImage->XSize();
386 # generate preview image and calculate width and height
387 $MaxPreviewWidth = min($MaxPreviewWidth, $this->
Width);
388 $MaxPreviewHeight = min($MaxPreviewHeight, $this->
Height);
389 $SrcImage->ScaleTo($MaxPreviewWidth, $MaxPreviewHeight, TRUE);
390 $SrcImage->SaveAs($this->PreviewFileName,
IMGTYPE_JPEG);
391 if (($this->
Width * $MaxPreviewHeight)
392 > ($this->
Height * $MaxPreviewWidth))
396 ($MaxPreviewWidth * $SrcImage->YSize()) / $SrcImage->XSize();
401 ($MaxPreviewHeight * $SrcImage->XSize()) / $SrcImage->YSize();
405 # generate thumbnail image and calculate width and height
406 $MaxThumbnailWidth = min($MaxThumbnailWidth, $this->
Width);
407 $MaxThumbnailHeight = min($MaxThumbnailHeight, $this->
Height);
408 $SrcImage->ScaleTo($MaxThumbnailWidth, $MaxThumbnailHeight, TRUE);
409 $SrcImage->SaveAs($this->ThumbnailFileName,
IMGTYPE_JPEG);
410 if (($this->
Width * $MaxThumbnailHeight)
411 > ($this->
Height * $MaxThumbnailWidth))
415 ($MaxThumbnailWidth * $SrcImage->YSize()) / $SrcImage->XSize();
419 $this->
ThumbnailWidth = ($MaxThumbnailHeight * $SrcImage->XSize()) / $SrcImage->YSize();
423 # save image attributes to database
424 $this->SaveImageInfo();
427 # ---- PRIVATE INTERFACE -------------------------------------------------
431 private $PreviewFileName;
432 private $ThumbnailFileName;
437 private $ThumbnailUrl;
440 private $PreviewHeight;
441 private $PreviewWidth;
442 private $ThumbnailHeight;
443 private $ThumbnailWidth;
445 private $ErrorStatus;
448 static private $ImageStorageLocations = array(
452 static private $PreviewStorageLocations = array(
453 "local/data/images/previews",
454 "ImageStorage/Previews",
456 static private $ThumbnailStorageLocations = array(
457 "local/data/images/thumbnails",
458 "ImageStorage/Thumbnails",
472 private function CreateNewImage($FileName, $MaxWidth, $MaxHeight,
473 $MaxPreviewWidth, $MaxPreviewHeight, $MaxThumbnailWidth, $MaxThumbnailHeight)
475 # if file does not exist or is not readable
476 if (!is_readable($FileName))
483 # if image is invalid or unsupported type
484 $SrcImage =
new Image($FileName);
485 if ($SrcImage->Status() !=
AI_OKAY)
488 $this->ErrorStatus = $SrcImage->Status();
492 # retrieve image type
493 $this->
Format = $SrcImage->Type();
495 # generate new image ID
496 $this->
Id = $this->GenerateNewImageId();
498 # generate and set file names
499 $this->SetFileNames();
501 # if our image file name differs from file name passed in
502 if (realpath($this->FileName) != realpath($FileName))
505 $SrcImage->SaveAs($this->FileName);
507 # if create failed set error status and bail out
508 if ($SrcImage->Status() !=
AI_OKAY)
510 $this->DB->Query(
"DELETE FROM Images WHERE ImageId = "
512 $this->ErrorStatus = $SrcImage->Status();
517 # scale the original image if necessary
518 $MaxWidth = min($MaxWidth, $SrcImage->XSize());
519 $MaxHeight = min($MaxHeight, $SrcImage->YSize());
521 # change the minimum width if the height is the limiting factor
522 if ($SrcImage->YSize() * $MaxWidth / $SrcImage->XSize() > $MaxHeight)
524 $MaxWidth = round($SrcImage->XSize() * $MaxHeight / $SrcImage->YSize());
527 # change the minimum height since the width is the limiting factor
530 $MaxHeight = round($SrcImage->YSize() * $MaxWidth / $SrcImage->XSize());
534 $SrcImage->ScaleTo($MaxWidth, $MaxHeight, TRUE);
536 # save and reload image info
537 $SrcImage->SaveAs($this->FileName);
538 $SrcImage =
new Image($this->FileName);
540 # retrieve image width and height
541 $this->
Height = $SrcImage->YSize();
542 $this->
Width = $SrcImage->XSize();
544 # create the preview and thumbnail images
545 foreach (array(
"Preview",
"Thumbnail") as $ImageType)
547 # variable name strings to use in the variable variables below
548 $MaxWidthVar =
"Max".$ImageType.
"Width";
549 $MaxHeightVar =
"Max".$ImageType.
"Height";
551 # find the mininum values for the width and height
552 $$MaxWidthVar = min($$MaxWidthVar, $this->
Width);
553 $$MaxHeightVar= min($$MaxHeightVar, $this->
Height);
555 # change the minimum width if the height is the limiting factor
556 if ($this->
Height * $$MaxWidthVar / $this->
Width > $$MaxHeightVar)
559 round($this->
Width * $$MaxHeightVar / $this->
Height);
562 # change the minimum height since the width is the limiting factor
566 round($this->
Height * $$MaxWidthVar / $this->
Width);
569 # scale the image and save it to a new file
570 $SrcImage->ScaleTo($$MaxWidthVar, $$MaxHeightVar, TRUE);
571 $SrcImage->SaveAs($this->{$ImageType.
"FileName"},
IMGTYPE_JPEG);
573 # scaling/saving failed
574 if ($SrcImage->Status() !=
AI_OKAY)
576 $this->DB->Query(
"DELETE FROM Images WHERE ImageId = "
578 $this->ErrorStatus = $SrcImage->Status();
582 # save the dimensions
583 $this->{$ImageType.
"Width"} = $$MaxWidthVar;
584 $this->{$ImageType.
"Height"} = $$MaxHeightVar;
587 # save image attributes to database
588 $this->SaveImageInfo();
597 private function LoadImageInfo($ImageId)
600 $this->
Id = $ImageId;
602 # load image record from database
603 $this->DB->Query(
"SELECT * FROM Images WHERE ImageId = ".$ImageId);
605 # if the ID is invalid
606 if (!$this->DB->NumRowsSelected())
612 $Record = $this->DB->FetchRow();
614 # load in values from record
615 $this->
Format = $Record[
"Format"];
616 $this->
AltText = $Record[
"AltText"];
617 $this->
Height = $Record[
"Height"];
618 $this->
Width = $Record[
"Width"];
624 # generate file names
625 $this->SetFileNames();
632 private function CreateCopyOfImage($SrcImage)
634 $Image =
new Image($SrcImage->Url());
635 if ($Image->Status() !=
AI_OKAY)
638 $this->ErrorStatus = $Image->
Status();
642 # generate new image ID
643 $this->
Id = $this->GenerateNewImageId();
645 # generate file names
646 $this->SetFileNames();
648 # copy attributes from source image
649 $this->
Format = $SrcImage->Format();
650 $this->
AltText = $SrcImage->AltText();
651 $this->
Width = $SrcImage->Width();
652 $this->
Height = $SrcImage->Height();
658 # copy source image files
659 copy($SrcImage->Url(), $this->FileName);
660 copy($SrcImage->PreviewUrl(), $this->PreviewFileName);
661 copy($SrcImage->ThumbnailUrl(), $this->ThumbnailFileName);
663 # save image attributes to database
664 $this->SaveImageInfo();
671 private function SetFileNames()
682 $this->FileName = $this->DetermineFileName(
683 self::$ImageStorageLocations,
"Img--", $FileExtension);
684 $this->PreviewFileName = $this->DetermineFileName(
685 self::$PreviewStorageLocations,
"Preview--", $FileExtension);
686 $this->ThumbnailFileName = $this->DetermineFileName(
687 self::$ThumbnailStorageLocations,
"Thumb--", $FileExtension);
699 private function DetermineFileName($Locations, $Prefix, $Extension)
701 # build base name for file
702 $BaseName = $Prefix.sprintf(
"%08d.", $this->
Id).$Extension;
704 # for each possible location
705 foreach ($Locations as $Dir)
707 # build full file name for location
708 $FileName = $Dir.
"/".$BaseName;
710 # if file exists in location return full file name
711 if (file_exists($FileName)) {
return $FileName; }
714 # for each possible location
715 foreach ($Locations as $Dir)
717 # build full file name for location
718 $FileName = $Dir.
"/".$BaseName;
720 # if location is writable return full file name
721 if (is_dir($Dir) && is_writable($Dir)) {
return $FileName; }
724 # return full file name for default location
725 return $Locations[0].
"/".$BaseName;
732 private function GenerateNewImageId()
734 # add new entry to database
735 $this->DB->Query(
"INSERT INTO Images (AltText) VALUES ('')");
737 # return ID of inserted image
738 return $this->DB->LastInsertId();
744 private function SaveImageInfo()
746 # update existing image record
747 $this->DB->Query(
"UPDATE Images SET"
748 .
" Format = '" .$this->
Format.
"',"
749 .
" AltText = '" .addslashes($this->AltText).
"',"
750 .
" Height = '" .$this->Height.
"',"
751 .
" Width = '" .$this->Width.
"',"
752 .
" PreviewHeight = '" .$this->PreviewHeight.
"',"
753 .
" PreviewWidth = '" .$this->PreviewWidth.
"',"
755 .
" ThumbnailWidth = '" .$this->ThumbnailWidth.
"'"
756 .
" WHERE ImageId = ".$this->Id);
Mimetype()
Get the MIME type for the image.
ThumbnailWidth()
Get the width of the thumbnail image for this image.
SPTImage($ImageIdOrFileNameOrImageObj, $MaxWidth=NULL, $MaxHeight=NULL, $MaxPreviewWidth=NULL, $MaxPreviewHeight=NULL, $MaxThumbnailWidth=NULL, $MaxThumbnailHeight=NULL)
Object constructor.
SQL database abstraction object with smart query caching.
Delete()
Delete the image, that is, remove its record from the database and delete the associated image files ...
PreviewHeight()
Get the height of the preview image for this image.
const THUMBNAIL_PATH
path where thumbnail images are stored
PreviewWidth()
Get the width of the preview image for this image.
Status()
Get the error status set by the constructor.
static CheckDirectories()
Check that the image storage directories are available, creating them and attempting to change their ...
ThumbnailHeight()
Get the height of the thumbnail image for this image.
Width()
Get the width of the image.
Encapsulates a full-size, preview, and thumbnail image.
Url()
Get the path to the image.
static PreviewStorageDirectory()
Get the path to the preview image storage directory.
PreviewUrl()
Get the path to the preview image for this image.
Format()
Get the format of the image.
const PREVIEW_PATH
path where preview images are stored
GetLink()
Get the path to the full-size image.
Id()
Get the ID of the image in the database.
Height()
Get the height of the image.
Resize($MaxWidth, $MaxHeight, $MaxPreviewWidth, $MaxPreviewHeight, $MaxThumbnailWidth, $MaxThumbnailHeight)
Resize the full-size, preview, and thumbnail images based on the given dimension restrictions.
AltText($NewValue=NULL)
Get or set the alternate text value for the image.
const IMAGE_PATH
base path where images are stored
static ThumbnailStorageDirectory()
Get the path to the thumbnail image storage directory.
static ImageStorageDirectory()
Get the path to the (full-size) image storage directory.
ThumbnailUrl()
Get the path to the thumbnail image for this image.
static Extension($Type=NULL)