Rev Author Line No. Line
228 kaklik 1 <?php
2  
3 /**
4 * Thumbnail class.
5 *
6 * @author Tamlyn Rhodes <tam at zenology dot co dot uk>
7 * @license http://opensource.org/licenses/gpl-license.php GNU General Public License
8 * @copyright (c)2003-2005 Tamlyn Rhodes
9 * @version $Id: thumbnail.class.php,v 1.13 2006/06/24 20:33:00 tamlyn Exp $
10 */
11  
12  
13 /**
14 * Creates and manages image thumbnails
15 * @package singapore
16 * @author Tamlyn Rhodes <tam at zenology dot co dot uk>
17 * @copyright (c)2003-2005 Tamlyn Rhodes
18 */
19 class sgThumbnail
20 {
21 var $config;
22 var $maxWidth = 0;
23 var $maxHeight = 0;
24 var $thumbWidth = 0;
25 var $thumbHeight = 0;
26 var $cropWidth = 0;
27 var $cropHeight = 0;
28 var $forceSize = false;
29 var $imagePath = "";
30 var $thumbPath = "";
31  
32 function sgThumbnail(&$img, $type)
33 {
34 $this->config =& sgConfig::getInstance();
35 $this->image =& $img;
36  
37 $widthVar = "thumb_width_".$type;
38 $heightVar = "thumb_height_".$type;
39 $cropVar = "thumb_crop_".$type;
40 $this->maxWidth = $this->config->$widthVar;
41 $this->maxHeight = $this->config->$heightVar;
42 if(isset($this->config->$cropVar))
43 $this->forceSize = $this->config->$cropVar;
44  
45 if($this->image == null) return;
46  
47 $this->imagePath = $this->image->realPath();
48 $this->thumbPath = $this->config->base_path.Singapore::thumbnailPath($this->image->parent->id, $this->image->id, $this->maxWidth, $this->maxHeight, $this->forceSize);
49 $this->thumbURL = $this->config->base_url .Singapore::thumbnailPath($this->image->parent->id, $this->image->id, $this->maxWidth, $this->maxHeight, $this->forceSize);
50  
51 //security check: make sure requested file is in galleries directory
52 if(!Singapore::isSubPath($this->config->base_path.$this->config->pathto_galleries, $this->imagePath) && !$this->image->isRemote())
53 return;
54  
55 //security check: make sure $image has a valid extension
56 if(!$this->image->isRemote() && !preg_match("/.+\.(".$this->config->recognised_extensions.")$/i",$this->image->id))
57 return;
58  
59 $this->calculateDimensions();
60  
61 //link straight to image if it smaller than required size
62 if($this->image->width <= $this->thumbWidth && $this->image->height <= $this->thumbHeight) {
63 $this->thumbURL = $this->image->realURL();
64 return;
65 }
66  
67 $imageModified = @filemtime($this->imagePath);
68 $thumbModified = @filemtime($this->thumbPath);
69  
70 if($imageModified > $thumbModified || !$thumbModified)
71 $this->buildThumbnail();
72 }
73  
74 /** Accessor methods */
75 function width() { return $this->thumbWidth; }
76 function height() { return $this->thumbHeight; }
77 function URL() { return $this->thumbURL; }
78  
79 /** Private methods */
80  
81 /**
82 * Calculates thumbnail dimensions.
83 */
84 function calculateDimensions()
85 {
86 //if aspect ratio is to be constrained set crop size
87 if($this->forceSize) {
88 $newAspect = $this->maxWidth/$this->maxHeight;
89 $oldAspect = $this->image->realWidth()/$this->image->realHeight();
90 if($newAspect > $oldAspect) {
91 $this->cropWidth = $this->image->realWidth();
92 $this->cropHeight = round($this->image->realHeight()*($oldAspect/$newAspect));
93 } else {
94 $this->cropWidth = round($this->image->realWidth()*($newAspect/$oldAspect));
95 $this->cropHeight = $this->image->realHeight();
96 }
97 //else crop size is image size
98 } else {
99 $this->cropWidth = $this->image->realWidth();
100 $this->cropHeight = $this->image->realHeight();
101 }
102  
103 if($this->cropHeight > $this->maxHeight && ($this->cropWidth <= $this->maxWidth
104 || ($this->cropWidth > $this->maxWidth && round($this->cropHeight/$this->cropWidth * $this->maxWidth) > $this->maxHeight))) {
105 $this->thumbWidth = round($this->cropWidth/$this->cropHeight * $this->maxHeight);
106 $this->thumbHeight = $this->maxHeight;
107 } elseif($this->cropWidth > $this->maxWidth) {
108 $this->thumbWidth = $this->maxWidth;
109 $this->thumbHeight = round($this->cropHeight/$this->cropWidth * $this->maxWidth);
110 } else {
111 $this->thumbWidth = $this->image->realWidth();
112 $this->thumbHeight = $this->image->realHeight();
113 }
114 }
115  
116 function buildThumbnail() {
117 //set cropping offset
118 $cropX = floor(($this->image->width-$this->cropWidth)/2);
119 $cropY = floor(($this->image->height-$this->cropHeight)/2);
120  
121 //check thumbs directory exists and create it if not
122 if(!file_exists(dirname($this->thumbPath)))
123 Singapore::mkdir(dirname($this->thumbPath));
124  
125 //if file is remote then copy locally first
126 if($this->image->isRemote()) {
127 $ip = @fopen($this->imagePath, "rb");
128 $tp = @fopen($this->thumbPath, "wb");
129 if($ip && $tp) {
130 while(fwrite($tp,fread($ip, 4095)));
131 fclose($tp);
132 fclose($ip);
133 $this->imagePath = $this->thumbPath;
134 }
135 }
136  
137 switch($this->config->thumbnail_software) {
138 case "im" : //use ImageMagick v5.x
139 $cmd = '"'.$this->config->pathto_convert.'"';
140 if($this->forceSize) $cmd .= " -crop {$this->cropWidth}x{$this->cropHeight}+{$this->cropX}+{$this->cropY}";
141 $cmd .= " -geometry {$this->thumbWidth}x{$this->thumbHeight}";
142 if($this->image->type == 2) $cmd .= " -quality ".$this->config->thumbnail_quality;
143 if($this->config->progressive_thumbs) $cmd .= " -interlace Plane";
144 if($this->config->remove_jpeg_profile) $cmd .= ' +profile "*"';
145 $cmd .= ' '.escapeshellarg($this->imagePath).' '.escapeshellarg($this->thumbPath);
146  
147 exec($cmd);
148  
149 break;
150 case "im6" : //use ImageMagick v6.x
151 $cmd = '"'.$this->config->pathto_convert.'"';
152 $cmd .= ' '.escapeshellarg($this->imagePath);
153 if($this->config->progressive_thumbs) $cmd .= " -interlace Plane";
154 if($this->image->type == 2) $cmd .= " -quality ".$this->config->thumbnail_quality;
155 if($this->forceSize) $cmd .= " -crop {$this->cropWidth}x{$this->cropHeight}+{$this->cropX}+{$this->cropY}";
156 $cmd .= " -resize {$this->thumbWidth}x{$this->thumbHeight}";
157 if($this->config->remove_jpeg_profile) $cmd .= ' +profile "*"';
158 $cmd .= ' '.escapeshellarg($this->thumbPath);
159  
160 exec($cmd);
161  
162 break;
163 case "gd2" :
164 case "gd1" :
165 default : //use GD by default
166 //read in image as appropriate type
167 switch($this->image->type) {
168 case 1 : $image = ImageCreateFromGIF($this->imagePath); break;
169 case 3 : $image = ImageCreateFromPNG($this->imagePath); break;
170 case 2 :
171 default: $image = ImageCreateFromJPEG($this->imagePath); break;
172 }
173  
174 if($image) {
175 switch($this->config->thumbnail_software) {
176 case "gd2" :
177 //create blank truecolor image
178 $thumb = ImageCreateTrueColor($this->thumbWidth,$this->thumbHeight);
179 //resize image with resampling
180 ImageCopyResampled(
181 $thumb, $image,
182 0, 0, $cropX, $cropY,
183 $this->thumbWidth, $this->thumbHeight, $this->cropWidth, $this->cropHeight);
184 break;
185 case "gd1" :
186 default :
187 //create blank 256 color image
188 $thumb = ImageCreate($this->thumbWidth,$this->thumbHeight);
189 //resize image
190 ImageCopyResized(
191 $thumb, $image,
192 0, 0, $cropX, $cropY,
193 $this->thumbWidth, $this->thumbHeight, $this->cropWidth, $this->cropHeight);
194 break;
195 }
196 } /*else {
197 $thumb = ImageCreate($this->thumbWidth, $this->thumbHeight);
198 $bg = ImageColorAllocate($thumb, 255, 255, 255);
199 $text = ImageColorAllocate($thumb, 255, 0, 0);
200 ImageString($thumb, 1, 0, 0, "Cannot load source image", $text);
201 }*/
202  
203 //set image interlacing
204 @ImageInterlace($thumb, $this->config->progressive_thumbs);
205  
206 //output image of appropriate type
207 switch($this->image->type) {
208 case 1 :
209 //GIF images are saved as PNG
210 case 3 :
211 ImagePNG($thumb, $this->thumbPath);
212 break;
213 case 2 :
214 default:
215 ImageJPEG($thumb, $this->thumbPath, $this->config->thumbnail_quality);
216 break;
217 }
218 @ImageDestroy($image);
219 @ImageDestroy($thumb);
220 }
221  
222 //set file permissions on newly created thumbnail
223 @chmod($this->thumbPath, octdec($this->config->file_mode));
224 }
225  
226 }
227  
228 ?>