3 * Thumbnail Generate API: GD Wrapper
\r
5 * 提供程式便於以 GD Library 生成預覽圖的物件
\r
7 * @package PMCLibrary
\r
8 * @version $Id: thumb.gd.php 603 2008-02-22 14:12:29Z scribe $
\r
9 * @date $Date: 2008-02-22 22:12:29 +0800 (星期五, 22 二月 2008) $
\r
13 var $sourceFile, $sourceWidth, $sourceHeight, $thumbWidth, $thumbHeight, $thumbQuality;
\r
15 function ThumbWrapper($sourceFile='', $sourceWidth=0, $sourceHeight=0){
\r
16 $this->sourceFile = $sourceFile;
\r
17 $this->sourceWidth = $sourceWidth;
\r
18 $this->sourceHeight = $sourceHeight;
\r
21 function _GetLeftShiftCount($dwVal,$len=4) {
\r
23 for ($i=0; $i<$len * 8; $i++) {
\r
24 if ($dwVal & 1) $nCount++;
\r
27 return (8 - $nCount);
\r
29 function _GetRightShiftCount($dwVal,$len=4) {
\r
30 for ($i=0; $i<$len * 8; $i++) {
\r
31 if ($dwVal & 1) return $i;
\r
37 /* ImageCreateFromBMP : 讓GD可處理BMP圖檔
\r
38 此為修改後最適化版本。原出處:http://www.php.net/imagecreate#53879
\r
40 *****************************
\r
41 Function: ImageCreateFromBMP
\r
43 Contact: admin@dhkold.com
\r
44 Date: The 15th of June 2005
\r
46 *****************************/
\r
47 function _ImageCreateFromBMP($filename){
\r
49 if(!$f1 = fopen($filename, 'rb')) return FALSE;
\r
52 $FILE = unpack('vfile_type/Vfile_size/Vreserved/Vbitmap_offset', fread($f1, 14));
\r
53 if($FILE['file_type']!=19778) return FALSE; // BM
\r
56 // 僅支援BITMAPINFOHEADER,不支援BITMAPV4HEADER及BITMAPV5HEADER
\r
57 $BMP = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel/Vcompression/Vsize_bitmap/Vhoriz_resolution/Vvert_resolution/Vcolors_used/Vcolors_important', fread($f1, 40));
\r
58 $BMP['colors'] = pow(2, $BMP['bits_per_pixel']);
\r
59 if($BMP['size_bitmap']==0) $BMP['size_bitmap'] = $FILE['file_size'] - $FILE['bitmap_offset'];
\r
60 $BMP['bytes_per_pixel'] = $BMP['bits_per_pixel'] / 8;
\r
61 $BMP['decal'] = ($BMP['width'] * $BMP['bytes_per_pixel'] / 4);
\r
62 $BMP['decal'] -= floor($BMP['width'] * $BMP['bytes_per_pixel'] / 4);
\r
63 $BMP['decal'] = 4 - (4 * $BMP['decal']);
\r
64 if($BMP['decal']==4) $BMP['decal'] = 0;
\r
68 if ($BMP['colors'] <=256 || $BMP['compression'] == 3) {
\r
69 if($BMP['compression'] == 3) // BI_BITFIELDS
\r
70 $PALETTE = unpack('V3', fread($f1,12));
\r
72 $PALETTE = unpack('V'.$BMP['colors'], fread($f1,$BMP['colors']*4));
\r
74 if($BMP['compression'] == 3) // BI_BITFIELDS
\r
75 $mask = array(array($PALETTE[1],$PALETTE[2],$PALETTE[3]),
\r
76 array($this->_GetRightShiftCount($PALETTE[1]),$this->_GetRightShiftCount($PALETTE[2]),$this->_GetRightShiftCount($PALETTE[3])),
\r
77 array($this->_GetLeftShiftCount($PALETTE[1]),$this->_GetLeftShiftCount($PALETTE[2]),$this->_GetLeftShiftCount($PALETTE[3])));
\r
79 if($BMP['colors'] == 65536) $mask = array(array(0x7C00,0x3E0,0x1F),array(10,5,0),array(3,3,3));
\r
83 $IMG = fread($f1, $BMP['size_bitmap']);
\r
87 $res = ImageCreateTrueColor($BMP['width'], $BMP['height']);
\r
89 $Y = $BMP['height'] - 1;
\r
91 if($BMP['compression'] == 1 && $BMP['colors'] == 256) { // BI_RLE8
\r
92 $imgDataLen=strlen($IMG);
\r
95 $prefix=ord(substr($IMG, floor($P++), 1));
\r
96 $suffix=ord(substr($IMG, floor($P++), 1));
\r
98 if(($prefix==0)&&($suffix==1)) break; // end of RLE stream
\r
99 if($P>=$imgDataLen) break;
\r
101 while(!(($prefix==0)&&($suffix==0))){ // ! end of RLE line
\r
102 if($prefix==0){ // Command
\r
103 $RLEData.=substr($IMG, floor($P), $suffix);
\r
106 } elseif($prefix>0){ // Repeat
\r
107 for($r=0;$r<$prefix;$r++)
\r
108 $RLEData.=chr($suffix);
\r
110 $prefix=ord(substr($IMG, floor($P++), 1));
\r
111 $suffix=ord(substr($IMG, floor($P++), 1));
\r
113 for($X=0;$X<strlen($RLEData);$X++) // Write
\r
114 ImageSetPixel($res, $X, $Y, $PALETTE[ord($RLEData[$X])+1]);
\r
118 } elseif($BMP['compression'] == 2 && $BMP['colors'] == 16) { // BI_RLE4
\r
119 $imgDataLen=strlen($IMG);
\r
122 $prefix=ord(substr($IMG, floor($P++), 1));
\r
123 $suffix=ord(substr($IMG, floor($P++), 1));
\r
125 if(($prefix==0)&&($suffix==1)) break; // end of RLE stream
\r
126 if($P>=$imgDataLen) break;
\r
128 while(!(($prefix==0)&&($suffix==0))){ // ! end of RLE line
\r
129 if($prefix==0){ // Command
\r
130 for($h=0;$h<$suffix;$h++) {
\r
131 $COLOR = ord(substr($IMG, floor($P), 1));
\r
132 $RLEData.=($h%2==0)?chr($COLOR >> 4):chr($COLOR & 0x0F);
\r
133 $P += $BMP['bytes_per_pixel'];
\r
137 } elseif($prefix>0){ // Repeat
\r
138 for($r=0;$r<$prefix;$r++)
\r
139 $RLEData.=($r%2==0)?chr($suffix >> 4):chr($suffix & 0x0F);
\r
141 $prefix=ord(substr($IMG, floor($P++), 1));
\r
142 $suffix=ord(substr($IMG, floor($P++), 1));
\r
145 for($X=0;$X<strlen($RLEData);$X++) // Write
\r
146 ImageSetPixel($res, $X, $Y, $PALETTE[ord($RLEData[$X])+1]);
\r
154 while($X < $BMP['width']){
\r
155 switch($BMP['bits_per_pixel']){
\r
157 $COLOR = unpack('V', substr($IMG, $P, 4));
\r
158 $COLOR[1] &= 0xFFFFFF; // 不處理Alpha
\r
160 case 24: $COLOR = unpack('V', substr($IMG, $P, 3).$VIDE); break;
\r
162 $COLOR = unpack("v",substr($IMG,$P,2));
\r
163 $COLOR[1] = (((($COLOR[1] & $mask[0][0])>>$mask[1][0])<<$mask[2][0])<<16) |
\r
164 (((($COLOR[1] & $mask[0][1])>>$mask[1][1])<<$mask[2][1])<<8) |
\r
165 ((($COLOR[1] & $mask[0][2])>>$mask[1][2])<<$mask[2][2]);
\r
167 case 8: $COLOR = unpack('n', $VIDE.substr($IMG, $P, 1)); break;
\r
169 $COLOR = unpack('n', $VIDE.substr($IMG, floor($P), 1));
\r
170 if(($P*2)%2==0) $COLOR[1] = ($COLOR[1] >> 4);
\r
171 else $COLOR[1] = ($COLOR[1] & 0x0F);
\r
174 $COLOR = unpack('n', $VIDE.substr($IMG, floor($P), 1));
\r
175 switch(($P * 8) % 8){
\r
176 case 0: $COLOR[1] = $COLOR[1] >> 7; break;
\r
177 case 1: $COLOR[1] = ($COLOR[1] & 0x40) >> 6; break;
\r
178 case 2: $COLOR[1] = ($COLOR[1] & 0x20) >> 5; break;
\r
179 case 3: $COLOR[1] = ($COLOR[1] & 0x10) >> 4; break;
\r
180 case 4: $COLOR[1] = ($COLOR[1] & 0x8) >> 3; break;
\r
181 case 5: $COLOR[1] = ($COLOR[1] & 0x4) >> 2; break;
\r
182 case 6: $COLOR[1] = ($COLOR[1] & 0x2) >> 1; break;
\r
183 case 7: $COLOR[1] = ($COLOR[1] & 0x1);
\r
189 if($BMP['bits_per_pixel']<16) $COLOR[1] = $PALETTE[$COLOR[1]+1];
\r
190 ImageSetPixel($res, $X, $Y, $COLOR[1]);
\r
192 $P += $BMP['bytes_per_pixel'];
\r
195 $P += $BMP['decal'];
\r
203 function getClass(){
\r
204 $str = 'GD Wrapper';
\r
205 if($this->isWorking()){
\r
206 $a = gd_info(); $str .= ' : '.$a['GD Version'];
\r
211 function isWorking(){
\r
212 return extension_loaded('gd') && function_exists('ImageCreateTrueColor') && function_exists('ImageCopyResampled');
\r
215 function setThumbnailConfig($thumbWidth, $thumbHeight, $thumbQuality=50){
\r
216 $this->thumbWidth = $thumbWidth;
\r
217 $this->thumbHeight = $thumbHeight;
\r
218 $this->thumbQuality = $thumbQuality;
\r
221 function makeThumbnailtoFile($destFile){
\r
222 if(!$this->isWorking()) return false;
\r
223 switch(strtolower(strrchr($this->sourceFile, '.'))){ // 取出副檔名
\r
225 $im_in = @ImageCreateFromJPEG($this->sourceFile); break;
\r
227 $im_in = @ImageCreateFromGIF($this->sourceFile); break;
\r
229 $im_in = @ImageCreateFromPNG($this->sourceFile); break;
\r
232 $im_in = $this->_ImageCreateFromBMP($this->sourceFile); break;
\r
236 if(!$im_in) return false;
\r
237 $im_out = ImageCreateTrueColor($this->thumbWidth, $this->thumbHeight);
\r
238 ImageCopyResampled($im_out, $im_in, 0, 0, 0, 0, $this->thumbWidth, $this->thumbHeight, $this->sourceWidth, $this->sourceHeight);
\r
239 ImageJPEG($im_out, $destFile, $this->thumbQuality);
\r
240 ImageDestroy($im_in); ImageDestroy($im_out);
\r