CWIS Developer Documentation

- Home
- Main Page
- Classes
- Files

- File List
- File Members

SPTImage.php
Go to the documentation of this file.
1 <?PHP
2 #
3 # FILE: SPTImage.php
4 #
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/
8 #
9
13 class SPTImage {
14
15 # ---- PUBLIC INTERFACE --------------------------------------------------
16
18 const IMAGE_PATH = "ImageStorage/";
20 const PREVIEW_PATH = "ImageStorage/Previews/";
22 const THUMBNAIL_PATH = "ImageStorage/Thumbnails/";
23
36 function SPTImage($ImageIdOrFileNameOrImageObj,
37 $MaxWidth = NULL, $MaxHeight = NULL,
38 $MaxPreviewWidth = NULL, $MaxPreviewHeight = NULL,
39 $MaxThumbnailWidth = NULL, $MaxThumbnailHeight = NULL)
40 {
41 # clear error status (0 = AI_OKAY)
42 $this->ErrorStatus = 0;
43
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
46 # objects
47 new Image(NULL);
48
49 # create and save a database handle for our use
50 $this->DB = new Database();
51
52 # if image object was passed in
53 if (is_object($ImageIdOrFileNameOrImageObj)
54 && method_exists($ImageIdOrFileNameOrImageObj, "SPTImage"))
55 {
56 # create copy of image passed in
57 $this->CreateCopyOfImage($ImageIdOrFileNameOrImageObj);
58 }
59 # else if image ID was passed in
60 elseif (($ImageIdOrFileNameOrImageObj > 0)
61 && preg_match("/[0-9]+/", $ImageIdOrFileNameOrImageObj))
62 {
63 # load info on existing image
64 $this->LoadImageInfo($ImageIdOrFileNameOrImageObj);
65 }
66 # else assume that value passed in is file name
67 else
68 {
69 # create new image from named file
70 $this->CreateNewImage($ImageIdOrFileNameOrImageObj,
71 $MaxWidth, $MaxHeight,
72 $MaxPreviewWidth, $MaxPreviewHeight,
73 $MaxThumbnailWidth, $MaxThumbnailHeight);
74 }
75 }
76
81 function Id() { return $this->Id; }
82
87 function Url() { return $this->FileName; }
88
93 function PreviewUrl() { return $this->PreviewFileName; }
94
99 function ThumbnailUrl() { return $this->ThumbnailFileName; }
100
106 function Format() { return $this->Format; }
107
112 public function Mimetype()
113 {
114 $Image = new Image($this->FileName);
115 return $Image->Mimetype();
116 }
117
122 function Height() { return $this->Height; }
123
128 function Width() { return $this->Width; }
129
134 function PreviewHeight() { return $this->PreviewHeight; }
135
140 function PreviewWidth() { return $this->PreviewWidth; }
141
146 function ThumbnailHeight() { return $this->ThumbnailHeight; }
147
152 function ThumbnailWidth() { return $this->ThumbnailWidth; }
153
158 static function ImageStorageDirectory()
159 {
160 # for each possible storage location
161 foreach (self::$ImageStorageLocations as $Dir)
162 {
163 # if location exists
164 if (is_dir($Dir))
165 {
166 # return location to caller
167 return $Dir;
168 }
169 }
170
171 # return default (most preferred) location to caller
172 return self::$ImageStorageLocations[0];
173 }
174
179 static function PreviewStorageDirectory()
180 {
181 # for each possible storage location
182 foreach (self::$PreviewStorageLocations as $Dir)
183 {
184 # if location exists
185 if (is_dir($Dir))
186 {
187 # return location to caller
188 return $Dir;
189 }
190 }
191
192 # return default (most preferred) location to caller
193 return self::$PreviewStorageLocations[0];
194 }
195
200 static function ThumbnailStorageDirectory()
201 {
202 # for each possible storage location
203 foreach (self::$ThumbnailStorageLocations as $Dir)
204 {
205 # if location exists
206 if (is_dir($Dir))
207 {
208 # return location to caller
209 return $Dir;
210 }
211 }
212
213 # return default (most preferred) location to caller
214 return self::$ThumbnailStorageLocations[0];
215 }
216
221 function GetLink() { return $this->FileName; }
222
229 function AltText($NewValue = NULL)
230 {
231 # if new value supplied and new value differs from existing value
232 if (($NewValue !== NULL) && ($NewValue != $this->AltText))
233 {
234 # save new value to database
235 $this->DB->Query("UPDATE Images SET"
236 ." AltText = '".addslashes($NewValue)."'"
237 ." WHERE ImageId = ".$this->Id);
238
239 # save new value locally
240 $this->AltText = $NewValue;
241 }
242
243 # return attribute value to caller
244 return $this->AltText;
245 }
246
251 function Delete()
252 {
253 # delete base image file
254 if (file_exists($this->FileName)) { unlink($this->FileName); }
255
256 # delete preview image file
257 if (file_exists($this->PreviewFileName)) { unlink($this->PreviewFileName); }
258
259 # delete thumbnail image file
260 if (file_exists($this->ThumbnailFileName)) { unlink($this->ThumbnailFileName); }
261
262 # delete image info record in database
263 $this->DB->Query("DELETE FROM Images WHERE ImageId = ".$this->Id);
264 }
265
270 function Status()
271 {
272 return $this->ErrorStatus;
273 }
274
280 static function CheckDirectories()
281 {
282 # determine paths
283 $ImagePath = self::ImageStorageDirectory();
284 $PreviewPath = self::PreviewStorageDirectory();
285 $ThumbnailPath = self::ThumbnailStorageDirectory();
286
287 # assume everything will be okay
288 $ErrorsFound = NULL;
289
290 # check base image directory
291 if (!is_dir($ImagePath) || !is_writable($ImagePath))
292 {
293 if (!is_dir($ImagePath))
294 {
295 @mkdir($ImagePath, 0755);
296 }
297 else
298 {
299 @chmod($ImagePath, 0755);
300 }
301 if (!is_dir($ImagePath))
302 {
303 $ErrorsFound[] = "Image Storage Directory Not Found";
304 }
305 elseif (!is_writable($ImagePath))
306 {
307 $ErrorsFound[] = "Image Storage Directory Not Writable";
308 }
309 }
310
311 # check preview directory
312 if (!is_dir($PreviewPath) || !is_writable($PreviewPath))
313 {
314 if (!is_dir($PreviewPath))
315 {
316 @mkdir($PreviewPath, 0755);
317 }
318 else
319 {
320 @chmod($PreviewPath, 0755);
321 }
322 if (!is_dir($PreviewPath))
323 {
324 $ErrorsFound[] = "Preview Storage Directory Not Found";
325 }
326 elseif (!is_writable($PreviewPath))
327 {
328 $ErrorsFound[] = "Preview Storage Directory Not Writable";
329 }
330 }
331
332 # check thumbnail directory
333 if (!is_dir($ThumbnailPath) || !is_writable($ThumbnailPath))
334 {
335 if (!is_dir($ThumbnailPath))
336 {
337 @mkdir($ThumbnailPath, 0755);
338 }
339 else
340 {
341 @chmod($ThumbnailPath, 0755);
342 }
343 if (!is_dir($ThumbnailPath))
344 {
345 $ErrorsFound[] = "Thumbnail Storage Directory Not Found";
346 }
347 elseif (!is_writable($ThumbnailPath))
348 {
349 $ErrorsFound[] = "Thumbnail Storage Directory Not Writable";
350 }
351 }
352
353 # return any errors found to caller
354 return $ErrorsFound;
355 }
356
367 public function Resize($MaxWidth, $MaxHeight,
368 $MaxPreviewWidth, $MaxPreviewHeight,
369 $MaxThumbnailWidth, $MaxThumbnailHeight)
370 {
371 $SrcImage = new Image($this->FileName);
372
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);
377
378 # save and reload image info
379 $SrcImage->SaveAs($this->FileName);
380 $SrcImage = new Image($this->FileName);
381
382 # retrieve image width and height
383 $this->Height = $SrcImage->YSize();
384 $this->Width = $SrcImage->XSize();
385
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))
393 {
394 $this->PreviewWidth = $MaxPreviewWidth;
395 $this->PreviewHeight =
396 ($MaxPreviewWidth * $SrcImage->YSize()) / $SrcImage->XSize();
397 }
398 else
399 {
400 $this->PreviewWidth =
401 ($MaxPreviewHeight * $SrcImage->XSize()) / $SrcImage->YSize();
402 $this->PreviewHeight = $MaxPreviewHeight;
403 }
404
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))
412 {
413 $this->ThumbnailWidth = $MaxThumbnailWidth;
414 $this->ThumbnailHeight =
415 ($MaxThumbnailWidth * $SrcImage->YSize()) / $SrcImage->XSize();
416 }
417 else
418 {
419 $this->ThumbnailWidth = ($MaxThumbnailHeight * $SrcImage->XSize()) / $SrcImage->YSize();
420 $this->ThumbnailHeight = $MaxThumbnailHeight;
421 }
422
423 # save image attributes to database
424 $this->SaveImageInfo();
425 }
426
427 # ---- PRIVATE INTERFACE -------------------------------------------------
428
429 private $Id;
430 private $FileName;
431 private $PreviewFileName;
432 private $ThumbnailFileName;
433 private $Format;
434 private $AltText;
435 private $Url;
436 private $PreviewUrl;
437 private $ThumbnailUrl;
438 private $Height;
439 private $Width;
440 private $PreviewHeight;
441 private $PreviewWidth;
442 private $ThumbnailHeight;
443 private $ThumbnailWidth;
444 private $DB;
445 private $ErrorStatus;
446
448 static private $ImageStorageLocations = array(
449 "local/data/images",
450 "ImageStorage",
451 );
452 static private $PreviewStorageLocations = array(
453 "local/data/images/previews",
454 "ImageStorage/Previews",
455 );
456 static private $ThumbnailStorageLocations = array(
457 "local/data/images/thumbnails",
458 "ImageStorage/Thumbnails",
459 );
460
472 private function CreateNewImage($FileName, $MaxWidth, $MaxHeight,
473 $MaxPreviewWidth, $MaxPreviewHeight, $MaxThumbnailWidth, $MaxThumbnailHeight)
474 {
475 # if file does not exist or is not readable
476 if (!is_readable($FileName))
477 {
478 # set error status
479 $this->ErrorStatus = AI_FILEUNREADABLE;
480 }
481 else
482 {
483 # if image is invalid or unsupported type
484 $SrcImage = new Image($FileName);
485 if ($SrcImage->Status() != AI_OKAY)
486 {
487 # set error status
488 $this->ErrorStatus = $SrcImage->Status();
489 }
490 else
491 {
492 # retrieve image type
493 $this->Format = $SrcImage->Type();
494
495 # generate new image ID
496 $this->Id = $this->GenerateNewImageId();
497
498 # generate and set file names
499 $this->SetFileNames();
500
501 # if our image file name differs from file name passed in
502 if (realpath($this->FileName) != realpath($FileName))
503 {
504 # create image file
505 $SrcImage->SaveAs($this->FileName);
506
507 # if create failed set error status and bail out
508 if ($SrcImage->Status() != AI_OKAY)
509 {
510 $this->DB->Query("DELETE FROM Images WHERE ImageId = "
511 .intval($this->Id));
512 $this->ErrorStatus = $SrcImage->Status();
513 return;
514 }
515 }
516
517 # scale the original image if necessary
518 $MaxWidth = min($MaxWidth, $SrcImage->XSize());
519 $MaxHeight = min($MaxHeight, $SrcImage->YSize());
520
521 # change the minimum width if the height is the limiting factor
522 if ($SrcImage->YSize() * $MaxWidth / $SrcImage->XSize() > $MaxHeight)
523 {
524 $MaxWidth = round($SrcImage->XSize() * $MaxHeight / $SrcImage->YSize());
525 }
526
527 # change the minimum height since the width is the limiting factor
528 else
529 {
530 $MaxHeight = round($SrcImage->YSize() * $MaxWidth / $SrcImage->XSize());
531 }
532
533 # scale the image
534 $SrcImage->ScaleTo($MaxWidth, $MaxHeight, TRUE);
535
536 # save and reload image info
537 $SrcImage->SaveAs($this->FileName);
538 $SrcImage = new Image($this->FileName);
539
540 # retrieve image width and height
541 $this->Height = $SrcImage->YSize();
542 $this->Width = $SrcImage->XSize();
543
544 # create the preview and thumbnail images
545 foreach (array("Preview", "Thumbnail") as $ImageType)
546 {
547 # variable name strings to use in the variable variables below
548 $MaxWidthVar = "Max".$ImageType."Width";
549 $MaxHeightVar = "Max".$ImageType."Height";
550
551 # find the mininum values for the width and height
552 $$MaxWidthVar = min($$MaxWidthVar, $this->Width);
553 $$MaxHeightVar= min($$MaxHeightVar, $this->Height);
554
555 # change the minimum width if the height is the limiting factor
556 if ($this->Height * $$MaxWidthVar / $this->Width > $$MaxHeightVar)
557 {
558 $$MaxWidthVar =
559 round($this->Width * $$MaxHeightVar / $this->Height);
560 }
561
562 # change the minimum height since the width is the limiting factor
563 else
564 {
565 $$MaxHeightVar =
566 round($this->Height * $$MaxWidthVar / $this->Width);
567 }
568
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);
572
573 # scaling/saving failed
574 if ($SrcImage->Status() != AI_OKAY)
575 {
576 $this->DB->Query("DELETE FROM Images WHERE ImageId = "
577 .intval($this->Id));
578 $this->ErrorStatus = $SrcImage->Status();
579 return;
580 }
581
582 # save the dimensions
583 $this->{$ImageType."Width"} = $$MaxWidthVar;
584 $this->{$ImageType."Height"} = $$MaxHeightVar;
585 }
586
587 # save image attributes to database
588 $this->SaveImageInfo();
589 }
590 }
591 }
592
597 private function LoadImageInfo($ImageId)
598 {
599 # save image ID
600 $this->Id = $ImageId;
601
602 # load image record from database
603 $this->DB->Query("SELECT * FROM Images WHERE ImageId = ".$ImageId);
604
605 # if the ID is invalid
606 if (!$this->DB->NumRowsSelected())
607 {
608 $this->ErrorStatus = AI_INTERNALERROR;
609 return;
610 }
611
612 $Record = $this->DB->FetchRow();
613
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"];
619 $this->PreviewHeight = $Record["PreviewHeight"];
620 $this->PreviewWidth = $Record["PreviewWidth"];
621 $this->ThumbnailHeight = $Record["ThumbnailHeight"];
622 $this->ThumbnailWidth = $Record["ThumbnailWidth"];
623
624 # generate file names
625 $this->SetFileNames();
626 }
627
632 private function CreateCopyOfImage($SrcImage)
633 {
634 $Image = new Image($SrcImage->Url());
635 if ($Image->Status() != AI_OKAY)
636 {
637 # set error status
638 $this->ErrorStatus = $Image->Status();
639 return;
640 }
641
642 # generate new image ID
643 $this->Id = $this->GenerateNewImageId();
644
645 # generate file names
646 $this->SetFileNames();
647
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();
653 $this->PreviewWidth = $SrcImage->PreviewWidth();
654 $this->PreviewHeight = $SrcImage->PreviewHeight();
655 $this->ThumbnailWidth = $SrcImage->ThumbnailWidth();
656 $this->ThumbnailHeight = $SrcImage->ThumbnailHeight();
657
658 # copy source image files
659 copy($SrcImage->Url(), $this->FileName);
660 copy($SrcImage->PreviewUrl(), $this->PreviewFileName);
661 copy($SrcImage->ThumbnailUrl(), $this->ThumbnailFileName);
662
663 # save image attributes to database
664 $this->SaveImageInfo();
665 }
666
671 private function SetFileNames()
672 {
673 if (Image::Extension($this->Format))
674 {
675 $FileExtension = Image::Extension($this->Format);
676 }
677 else
678 {
679 $FileExtension = "";
680 }
681
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);
688 }
689
699 private function DetermineFileName($Locations, $Prefix, $Extension)
700 {
701 # build base name for file
702 $BaseName = $Prefix.sprintf("%08d.", $this->Id).$Extension;
703
704 # for each possible location
705 foreach ($Locations as $Dir)
706 {
707 # build full file name for location
708 $FileName = $Dir."/".$BaseName;
709
710 # if file exists in location return full file name
711 if (file_exists($FileName)) { return $FileName; }
712 }
713
714 # for each possible location
715 foreach ($Locations as $Dir)
716 {
717 # build full file name for location
718 $FileName = $Dir."/".$BaseName;
719
720 # if location is writable return full file name
721 if (is_dir($Dir) && is_writable($Dir)) { return $FileName; }
722 }
723
724 # return full file name for default location
725 return $Locations[0]."/".$BaseName;
726 }
727
732 private function GenerateNewImageId()
733 {
734 # add new entry to database
735 $this->DB->Query("INSERT INTO Images (AltText) VALUES ('')");
736
737 # return ID of inserted image
738 return $this->DB->LastInsertId();
739 }
740
744 private function SaveImageInfo()
745 {
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."',"
754 ." ThumbnailHeight = '".$this->ThumbnailHeight."',"
755 ." ThumbnailWidth = '" .$this->ThumbnailWidth."'"
756 ." WHERE ImageId = ".$this->Id);
757 }
758
759 }
SPTImage\Mimetype
Mimetype()
Get the MIME type for the image.
Definition: SPTImage.php:112
SPTImage\ThumbnailWidth
ThumbnailWidth()
Get the width of the thumbnail image for this image.
Definition: SPTImage.php:152
IMGTYPE_JPEG
const IMGTYPE_JPEG
Definition: Axis--Image.php:524
SPTImage\SPTImage
SPTImage($ImageIdOrFileNameOrImageObj, $MaxWidth=NULL, $MaxHeight=NULL, $MaxPreviewWidth=NULL, $MaxPreviewHeight=NULL, $MaxThumbnailWidth=NULL, $MaxThumbnailHeight=NULL)
Object constructor.
Definition: SPTImage.php:36
Database
SQL database abstraction object with smart query caching.
Definition: Axis--Database.php:22
SPTImage\Delete
Delete()
Delete the image, that is, remove its record from the database and delete the associated image files ...
Definition: SPTImage.php:251
SPTImage\PreviewHeight
PreviewHeight()
Get the height of the preview image for this image.
Definition: SPTImage.php:134
SPTImage\THUMBNAIL_PATH
const THUMBNAIL_PATH
path where thumbnail images are stored
Definition: SPTImage.php:22
AI_FILEUNREADABLE
const AI_FILEUNREADABLE
Definition: Axis--Image.php:531
SPTImage\PreviewWidth
PreviewWidth()
Get the width of the preview image for this image.
Definition: SPTImage.php:140
SPTImage\Status
Status()
Get the error status set by the constructor.
Definition: SPTImage.php:270
AI_INTERNALERROR
const AI_INTERNALERROR
Definition: Axis--Image.php:534
PHP
PHP
Definition: OAIClient.php:39
SPTImage\CheckDirectories
static CheckDirectories()
Check that the image storage directories are available, creating them and attempting to change their ...
Definition: SPTImage.php:280
SPTImage\ThumbnailHeight
ThumbnailHeight()
Get the height of the thumbnail image for this image.
Definition: SPTImage.php:146
SPTImage\Width
Width()
Get the width of the image.
Definition: SPTImage.php:128
SPTImage
Encapsulates a full-size, preview, and thumbnail image.
Definition: SPTImage.php:13
SPTImage\Url
Url()
Get the path to the image.
Definition: SPTImage.php:87
SPTImage\PreviewStorageDirectory
static PreviewStorageDirectory()
Get the path to the preview image storage directory.
Definition: SPTImage.php:179
SPTImage\PreviewUrl
PreviewUrl()
Get the path to the preview image for this image.
Definition: SPTImage.php:93
SPTImage\Format
Format()
Get the format of the image.
Definition: SPTImage.php:106
SPTImage\PREVIEW_PATH
const PREVIEW_PATH
path where preview images are stored
Definition: SPTImage.php:20
SPTImage\GetLink
GetLink()
Get the path to the full-size image.
Definition: SPTImage.php:221
SPTImage\Id
Id()
Get the ID of the image in the database.
Definition: SPTImage.php:81
Image\Status
Status()
Definition: Axis--Image.php:440
AI_OKAY
const AI_OKAY
Definition: Axis--Image.php:530
SPTImage\Height
Height()
Get the height of the image.
Definition: SPTImage.php:122
SPTImage\Resize
Resize($MaxWidth, $MaxHeight, $MaxPreviewWidth, $MaxPreviewHeight, $MaxThumbnailWidth, $MaxThumbnailHeight)
Resize the full-size, preview, and thumbnail images based on the given dimension restrictions.
Definition: SPTImage.php:367
Image
Definition: Axis--Image.php:15
SPTImage\AltText
AltText($NewValue=NULL)
Get or set the alternate text value for the image.
Definition: SPTImage.php:229
SPTImage\IMAGE_PATH
const IMAGE_PATH
base path where images are stored
Definition: SPTImage.php:18
SPTImage\ThumbnailStorageDirectory
static ThumbnailStorageDirectory()
Get the path to the thumbnail image storage directory.
Definition: SPTImage.php:200
SPTImage\ImageStorageDirectory
static ImageStorageDirectory()
Get the path to the (full-size) image storage directory.
Definition: SPTImage.php:158
SPTImage\ThumbnailUrl
ThumbnailUrl()
Get the path to the thumbnail image for this image.
Definition: SPTImage.php:99
Image\Extension
static Extension($Type=NULL)
Definition: Axis--Image.php:355