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; }
89 $Url = $this->FileName;
90 $SignalResult = $GLOBALS[
"AF"]->SignalEvent(
91 "EVENT_IMAGE_URL_FILTER", array(
93 "ImageSize" =>
"Full"));
94 $Url = $SignalResult[
"Url"];
104 $Url = $this->PreviewFileName;
105 $SignalResult = $GLOBALS[
"AF"]->SignalEvent(
106 "EVENT_IMAGE_URL_FILTER", array(
108 "ImageSize" =>
"Preview"));
109 $Url = $SignalResult[
"Url"];
119 $Url = $this->ThumbnailFileName;
120 $SignalResult = $GLOBALS[
"AF"]->SignalEvent(
121 "EVENT_IMAGE_URL_FILTER", array(
123 "ImageSize" =>
"Thumbnail"));
124 $Url = $SignalResult[
"Url"];
133 function Format() {
return $this->Format; }
141 $Image =
new Image($this->FileName);
142 return $Image->Mimetype();
149 function Height() {
return $this->Height; }
155 function Width() {
return $this->Width; }
187 # for each possible storage location
188 foreach (self::$ImageStorageLocations as $Dir)
193 # return location to caller
198 # return default (most preferred) location to caller
199 return self::$ImageStorageLocations[0];
208 # for each possible storage location
209 foreach (self::$PreviewStorageLocations as $Dir)
214 # return location to caller
219 # return default (most preferred) location to caller
220 return self::$PreviewStorageLocations[0];
229 # for each possible storage location
230 foreach (self::$ThumbnailStorageLocations as $Dir)
235 # return location to caller
240 # return default (most preferred) location to caller
241 return self::$ThumbnailStorageLocations[0];
248 function GetLink() {
return $this->FileName; }
258 # if new value supplied and new value differs from existing value
259 if (($NewValue !== NULL) && ($NewValue != $this->
AltText))
261 # save new value to database
262 $this->DB->Query(
"UPDATE Images SET"
263 .
" AltText = '".addslashes($NewValue).
"'"
264 .
" WHERE ImageId = ".$this->
Id);
266 # save new value locally
270 # return attribute value to caller
271 return $this->AltText;
280 # delete base image file
281 if (file_exists($this->FileName)) { unlink($this->FileName); }
283 # delete preview image file
284 if (file_exists($this->PreviewFileName)) { unlink($this->PreviewFileName); }
286 # delete thumbnail image file
287 if (file_exists($this->ThumbnailFileName)) { unlink($this->ThumbnailFileName); }
289 # delete image info record in database
290 $this->DB->Query(
"DELETE FROM Images WHERE ImageId = ".$this->
Id);
299 return $this->ErrorStatus;
310 $ImagePath = self::ImageStorageDirectory();
311 $PreviewPath = self::PreviewStorageDirectory();
312 $ThumbnailPath = self::ThumbnailStorageDirectory();
314 # assume everything will be okay
317 # check base image directory
318 if (!is_dir($ImagePath) || !is_writable($ImagePath))
320 if (!is_dir($ImagePath))
322 @mkdir($ImagePath, 0755);
326 @chmod($ImagePath, 0755);
328 if (!is_dir($ImagePath))
330 $ErrorsFound[] =
"Image Storage Directory Not Found";
332 elseif (!is_writable($ImagePath))
334 $ErrorsFound[] =
"Image Storage Directory Not Writable";
338 # check preview directory
339 if (!is_dir($PreviewPath) || !is_writable($PreviewPath))
341 if (!is_dir($PreviewPath))
343 @mkdir($PreviewPath, 0755);
347 @chmod($PreviewPath, 0755);
349 if (!is_dir($PreviewPath))
351 $ErrorsFound[] =
"Preview Storage Directory Not Found";
353 elseif (!is_writable($PreviewPath))
355 $ErrorsFound[] =
"Preview Storage Directory Not Writable";
359 # check thumbnail directory
360 if (!is_dir($ThumbnailPath) || !is_writable($ThumbnailPath))
362 if (!is_dir($ThumbnailPath))
364 @mkdir($ThumbnailPath, 0755);
368 @chmod($ThumbnailPath, 0755);
370 if (!is_dir($ThumbnailPath))
372 $ErrorsFound[] =
"Thumbnail Storage Directory Not Found";
374 elseif (!is_writable($ThumbnailPath))
376 $ErrorsFound[] =
"Thumbnail Storage Directory Not Writable";
380 # return any errors found to caller
394 public function Resize($MaxWidth, $MaxHeight,
395 $MaxPreviewWidth, $MaxPreviewHeight,
396 $MaxThumbnailWidth, $MaxThumbnailHeight)
398 $SrcImage =
new Image($this->FileName);
400 # scale the original image if necessary
401 $MaxWidth = min($MaxWidth, $SrcImage->XSize());
402 $MaxHeight = min($MaxHeight, $SrcImage->YSize());
403 $SrcImage->ScaleTo($MaxWidth, $MaxHeight, TRUE);
405 # save and reload image info
406 $SrcImage->SaveAs($this->FileName);
407 $SrcImage =
new Image($this->FileName);
409 # retrieve image width and height
410 $this->
Height = $SrcImage->YSize();
411 $this->
Width = $SrcImage->XSize();
413 # generate preview image and calculate width and height
414 $MaxPreviewWidth = min($MaxPreviewWidth, $this->
Width);
415 $MaxPreviewHeight = min($MaxPreviewHeight, $this->
Height);
416 $SrcImage->ScaleTo($MaxPreviewWidth, $MaxPreviewHeight, TRUE);
417 $SrcImage->SaveAs($this->PreviewFileName);
418 if (($this->
Width * $MaxPreviewHeight)
419 > ($this->
Height * $MaxPreviewWidth))
423 ($MaxPreviewWidth * $SrcImage->YSize()) / $SrcImage->XSize();
428 ($MaxPreviewHeight * $SrcImage->XSize()) / $SrcImage->YSize();
432 # generate thumbnail image and calculate width and height
433 $MaxThumbnailWidth = min($MaxThumbnailWidth, $this->
Width);
434 $MaxThumbnailHeight = min($MaxThumbnailHeight, $this->
Height);
435 $SrcImage->ScaleTo($MaxThumbnailWidth, $MaxThumbnailHeight, TRUE);
436 $SrcImage->SaveAs($this->ThumbnailFileName);
437 if (($this->
Width * $MaxThumbnailHeight)
438 > ($this->
Height * $MaxThumbnailWidth))
442 ($MaxThumbnailWidth * $SrcImage->YSize()) / $SrcImage->XSize();
446 $this->
ThumbnailWidth = ($MaxThumbnailHeight * $SrcImage->XSize()) / $SrcImage->YSize();
450 # save image attributes to database
451 $this->SaveImageInfo();
454 # ---- PRIVATE INTERFACE -------------------------------------------------
458 private $PreviewFileName;
459 private $ThumbnailFileName;
464 private $ThumbnailUrl;
467 private $PreviewHeight;
468 private $PreviewWidth;
469 private $ThumbnailHeight;
470 private $ThumbnailWidth;
472 private $ErrorStatus;
475 static private $ImageStorageLocations = array(
479 static private $PreviewStorageLocations = array(
480 "local/data/images/previews",
481 "ImageStorage/Previews",
483 static private $ThumbnailStorageLocations = array(
484 "local/data/images/thumbnails",
485 "ImageStorage/Thumbnails",
499 private function CreateNewImage($FileName, $MaxWidth, $MaxHeight,
500 $MaxPreviewWidth, $MaxPreviewHeight, $MaxThumbnailWidth, $MaxThumbnailHeight)
502 # if file does not exist or is not readable
503 if (!is_readable($FileName))
510 # if image is invalid or unsupported type
511 $SrcImage =
new Image($FileName);
512 $this->
Format = $SrcImage->Type();
513 if ($SrcImage->Status() !=
AI_OKAY)
516 $this->ErrorStatus = $SrcImage->Status();
520 # generate new image ID
521 $this->
Id = $this->GenerateNewImageId();
523 # generate and set file names
524 $this->SetFileNames();
526 # if our image file name differs from file name passed in
527 if (realpath($this->FileName) != realpath($FileName))
530 $SrcImage->SaveAs($this->FileName);
532 # if create failed set error status and bail out
533 if ($SrcImage->Status() !=
AI_OKAY)
535 $this->DB->Query(
"DELETE FROM Images WHERE ImageId = "
537 $this->ErrorStatus = $SrcImage->Status();
542 # scale the original image if necessary
543 $MaxWidth = min($MaxWidth, $SrcImage->XSize());
544 $MaxHeight = min($MaxHeight, $SrcImage->YSize());
546 # change the minimum width if the height is the limiting factor
547 if ($SrcImage->YSize() * $MaxWidth / $SrcImage->XSize() > $MaxHeight)
549 $MaxWidth = round($SrcImage->XSize() * $MaxHeight / $SrcImage->YSize());
552 # change the minimum height since the width is the limiting factor
555 $MaxHeight = round($SrcImage->YSize() * $MaxWidth / $SrcImage->XSize());
559 $SrcImage->ScaleTo($MaxWidth, $MaxHeight, TRUE);
561 # save and reload image info
562 $SrcImage->SaveAs($this->FileName);
563 $SrcImage =
new Image($this->FileName);
565 # retrieve image width and height
566 $this->
Height = $SrcImage->YSize();
567 $this->
Width = $SrcImage->XSize();
569 # create the preview and thumbnail images
570 foreach (array(
"Preview",
"Thumbnail") as $ImageType)
572 # variable name strings to use in the variable variables below
573 $MaxWidthVar =
"Max".$ImageType.
"Width";
574 $MaxHeightVar =
"Max".$ImageType.
"Height";
576 # find the mininum values for the width and height
577 $$MaxWidthVar = min($$MaxWidthVar, $this->
Width);
578 $$MaxHeightVar= min($$MaxHeightVar, $this->
Height);
580 # change the minimum width if the height is the limiting factor
581 if ($this->
Height * $$MaxWidthVar / $this->
Width > $$MaxHeightVar)
584 round($this->
Width * $$MaxHeightVar / $this->
Height);
587 # change the minimum height since the width is the limiting factor
591 round($this->
Height * $$MaxWidthVar / $this->
Width);
594 # scale the image and save it to a new file
595 $SrcImage->ScaleTo($$MaxWidthVar, $$MaxHeightVar, TRUE);
596 $SrcImage->SaveAs($this->{$ImageType.
"FileName"});
598 # scaling/saving failed
599 if ($SrcImage->Status() !=
AI_OKAY)
601 $this->DB->Query(
"DELETE FROM Images WHERE ImageId = "
603 $this->ErrorStatus = $SrcImage->Status();
607 # save the dimensions
608 $this->{$ImageType.
"Width"} = $$MaxWidthVar;
609 $this->{$ImageType.
"Height"} = $$MaxHeightVar;
612 # save image attributes to database
613 $this->SaveImageInfo();
622 private function LoadImageInfo($ImageId)
625 $this->
Id = $ImageId;
627 # load image record from database
628 $this->DB->Query(
"SELECT * FROM Images WHERE ImageId = ".$ImageId);
630 # if the ID is invalid
631 if (!$this->DB->NumRowsSelected())
637 $Record = $this->DB->FetchRow();
639 # load in values from record
640 $this->
Format = $Record[
"Format"];
641 $this->
AltText = $Record[
"AltText"];
642 $this->
Height = $Record[
"Height"];
643 $this->
Width = $Record[
"Width"];
649 # generate file names
650 $this->SetFileNames();
657 private function CreateCopyOfImage($SrcImage)
659 $Image =
new Image($SrcImage->Url());
660 if ($Image->Status() !=
AI_OKAY)
663 $this->ErrorStatus = $Image->
Status();
667 # generate new image ID
668 $this->
Id = $this->GenerateNewImageId();
670 # generate file names
671 $this->SetFileNames();
673 # copy attributes from source image
674 $this->
Format = $SrcImage->Format();
675 $this->
AltText = $SrcImage->AltText();
676 $this->
Width = $SrcImage->Width();
677 $this->
Height = $SrcImage->Height();
683 # copy source image files
684 copy($SrcImage->Url(), $this->FileName);
685 copy($SrcImage->PreviewUrl(), $this->PreviewFileName);
686 copy($SrcImage->ThumbnailUrl(), $this->ThumbnailFileName);
688 # save image attributes to database
689 $this->SaveImageInfo();
696 private function SetFileNames()
707 $this->FileName = $this->DetermineFileName(
708 self::$ImageStorageLocations,
"Img--", $FileExtension);
709 $this->PreviewFileName = $this->DetermineFileName(
710 self::$PreviewStorageLocations,
"Preview--", $FileExtension);
711 $this->ThumbnailFileName = $this->DetermineFileName(
712 self::$ThumbnailStorageLocations,
"Thumb--", $FileExtension);
724 private function DetermineFileName($Locations, $Prefix, $Extension)
726 # build base name for file
727 $BaseName = $Prefix.sprintf(
"%08d.", $this->
Id).$Extension;
729 # for each possible location
730 foreach ($Locations as $Dir)
732 # build full file name for location
733 $FileName = $Dir.
"/".$BaseName;
735 # if file exists in location return full file name
736 if (file_exists($FileName)) {
return $FileName; }
739 # for each possible location
740 foreach ($Locations as $Dir)
742 # build full file name for location
743 $FileName = $Dir.
"/".$BaseName;
745 # if location is writable return full file name
746 if (is_dir($Dir) && is_writable($Dir)) {
return $FileName; }
749 # return full file name for default location
750 return $Locations[0].
"/".$BaseName;
757 private function GenerateNewImageId()
759 # add new entry to database
760 $this->DB->Query(
"INSERT INTO Images (AltText) VALUES ('')");
762 # return ID of inserted image
763 return $this->DB->LastInsertId();
769 private function SaveImageInfo()
771 # update existing image record
772 $this->DB->Query(
"UPDATE Images SET"
773 .
" Format = '" .$this->
Format.
"',"
774 .
" AltText = '" .addslashes($this->AltText).
"',"
775 .
" Height = '" .$this->Height.
"',"
776 .
" Width = '" .$this->Width.
"',"
777 .
" PreviewHeight = '" .$this->PreviewHeight.
"',"
778 .
" PreviewWidth = '" .$this->PreviewWidth.
"',"
780 .
" ThumbnailWidth = '" .$this->ThumbnailWidth.
"'"
781 .
" 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)