]> 4ch.mooo.com Git - test.git/blob - lib/thumb/thumb.gd.php
modified: .gitignore
[test.git] / lib / thumb / thumb.gd.php
1 <?php\r
2 /**\r
3  * Thumbnail Generate API: GD Wrapper\r
4  *\r
5  * 提供程式便於以 GD Library 生成預覽圖的物件\r
6  *\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
10  */\r
11 \r
12 class ThumbWrapper{\r
13         var $sourceFile, $sourceWidth, $sourceHeight, $thumbWidth, $thumbHeight, $thumbQuality;\r
14 \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
19         }\r
20 \r
21         function _GetLeftShiftCount($dwVal,$len=4) {\r
22                 $nCount = 0;\r
23                 for ($i=0; $i<$len * 8; $i++) {\r
24                         if ($dwVal & 1) $nCount++;\r
25                         $dwVal >>= 1;\r
26                 }\r
27                 return (8 - $nCount);\r
28         }\r
29         function _GetRightShiftCount($dwVal,$len=4) {\r
30                 for ($i=0; $i<$len * 8; $i++) {\r
31                         if ($dwVal & 1) return $i;\r
32                         $dwVal >>= 1;\r
33                 }\r
34                 return -1;\r
35         }\r
36 \r
37         /* ImageCreateFromBMP : 讓GD可處理BMP圖檔\r
38         此為修改後最適化版本。原出處:http://www.php.net/imagecreate#53879\r
39         原作宣告:\r
40         *****************************\r
41         Function: ImageCreateFromBMP\r
42         Author: DHKold\r
43         Contact: admin@dhkold.com\r
44         Date: The 15th of June 2005\r
45         Version: 2.0B\r
46         *****************************/\r
47         function _ImageCreateFromBMP($filename){\r
48                 // 序章:以二進位模式開啟檔案流\r
49                 if(!$f1 = fopen($filename, 'rb')) return FALSE;\r
50 \r
51                 // 第一步:讀取BMP檔頭\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
54 \r
55                 // 第二步:讀取BMP資訊\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
65 \r
66                 // 第三步:讀取色盤資訊\r
67                 $PALETTE = array();\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
71                         else\r
72                                 $PALETTE = unpack('V'.$BMP['colors'], fread($f1,$BMP['colors']*4));\r
73                 }\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
78                 else {\r
79                         if($BMP['colors'] == 65536) $mask = array(array(0x7C00,0x3E0,0x1F),array(10,5,0),array(3,3,3));\r
80                 }\r
81 \r
82                 // 第四步:關閉檔案,變換每一個畫素\r
83                 $IMG = fread($f1, $BMP['size_bitmap']);\r
84                 fclose($f1);\r
85                 $VIDE = chr(0);\r
86 \r
87                 $res = ImageCreateTrueColor($BMP['width'], $BMP['height']);\r
88                 $P = 0;\r
89                 $Y = $BMP['height'] - 1;\r
90 \r
91                 if($BMP['compression'] == 1 && $BMP['colors'] == 256) { // BI_RLE8\r
92                         $imgDataLen=strlen($IMG);\r
93                         $RLEData='';\r
94                         while(true) {\r
95                                 $prefix=ord(substr($IMG, floor($P++), 1));\r
96                                 $suffix=ord(substr($IMG, floor($P++), 1));\r
97 \r
98                                 if(($prefix==0)&&($suffix==1)) break; // end of RLE stream\r
99                                 if($P>=$imgDataLen) break;\r
100 \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
104                                                 $P+=$suffix;\r
105                                                 if($P%2==1) $P++;\r
106                                         } elseif($prefix>0){ // Repeat\r
107                                                 for($r=0;$r<$prefix;$r++)\r
108                                                         $RLEData.=chr($suffix);\r
109                                         }\r
110                                         $prefix=ord(substr($IMG, floor($P++), 1));\r
111                                         $suffix=ord(substr($IMG, floor($P++), 1));\r
112                                 }\r
113                                 for($X=0;$X<strlen($RLEData);$X++) // Write\r
114                                         ImageSetPixel($res, $X, $Y, $PALETTE[ord($RLEData[$X])+1]);\r
115                                 $RLEData='';\r
116                                 $Y--;\r
117                         }\r
118                 } elseif($BMP['compression'] == 2 && $BMP['colors'] == 16) { // BI_RLE4\r
119                         $imgDataLen=strlen($IMG);\r
120                         $RLEData='';\r
121                         while(true) {\r
122                                 $prefix=ord(substr($IMG, floor($P++), 1));\r
123                                 $suffix=ord(substr($IMG, floor($P++), 1));\r
124 \r
125                                 if(($prefix==0)&&($suffix==1)) break; // end of RLE stream\r
126                                 if($P>=$imgDataLen) break;\r
127 \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
134                                                 }\r
135                                                 $P=ceil($P);\r
136                                                 if($P%2==1) $P++;\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
140                                         }\r
141                                         $prefix=ord(substr($IMG, floor($P++), 1));\r
142                                         $suffix=ord(substr($IMG, floor($P++), 1));\r
143                                 }\r
144 \r
145                                 for($X=0;$X<strlen($RLEData);$X++) // Write\r
146                                         ImageSetPixel($res, $X, $Y, $PALETTE[ord($RLEData[$X])+1]);\r
147                                 $RLEData='';\r
148                                 $Y--;\r
149 \r
150                         }\r
151                 } else {\r
152                         while($Y >= 0){\r
153                                 $X = 0;\r
154                                 while($X < $BMP['width']){\r
155                                         switch($BMP['bits_per_pixel']){\r
156                                                 case 32: \r
157                                                         $COLOR = unpack('V', substr($IMG, $P, 4));\r
158                                                         $COLOR[1] &= 0xFFFFFF; // 不處理Alpha\r
159                                                         break;\r
160                                                 case 24: $COLOR = unpack('V', substr($IMG, $P, 3).$VIDE); break;\r
161                                                 case 16:\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
166                                                         break;\r
167                                                 case 8: $COLOR = unpack('n', $VIDE.substr($IMG, $P, 1)); break;\r
168                                                 case 4:\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
172                                                         break;\r
173                                                 case 1:\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
184                                                         }\r
185                                                         break;\r
186                                                 default:\r
187                                                         return FALSE;\r
188                                         }\r
189                                         if($BMP['bits_per_pixel']<16) $COLOR[1] = $PALETTE[$COLOR[1]+1];\r
190                                         ImageSetPixel($res, $X, $Y, $COLOR[1]);\r
191                                         $X++;\r
192                                         $P += $BMP['bytes_per_pixel'];\r
193                                 }\r
194                                 $Y--;\r
195                                 $P += $BMP['decal'];\r
196                         }\r
197                 }\r
198 \r
199                 // 終章:回傳新圖像\r
200                 return $res;\r
201         }\r
202 \r
203         function getClass(){\r
204                 $str = 'GD Wrapper';\r
205                 if($this->isWorking()){\r
206                         $a = gd_info(); $str .= ' : '.$a['GD Version'];\r
207                 }\r
208                 return $str;\r
209         }\r
210 \r
211         function isWorking(){\r
212                 return extension_loaded('gd') && function_exists('ImageCreateTrueColor') && function_exists('ImageCopyResampled');\r
213         }\r
214 \r
215         function setThumbnailConfig($thumbWidth, $thumbHeight, $thumbQuality=50){\r
216                 $this->thumbWidth = $thumbWidth;\r
217                 $this->thumbHeight = $thumbHeight;\r
218                 $this->thumbQuality = $thumbQuality;\r
219         }\r
220 \r
221         function makeThumbnailtoFile($destFile){\r
222                 if(!$this->isWorking()) return false;\r
223                 switch(strtolower(strrchr($this->sourceFile, '.'))){ // 取出副檔名\r
224                         case '.jpg':\r
225                                 $im_in = @ImageCreateFromJPEG($this->sourceFile); break;\r
226                         case '.gif':\r
227                                 $im_in = @ImageCreateFromGIF($this->sourceFile); break;\r
228                         case '.png':\r
229                                 $im_in = @ImageCreateFromPNG($this->sourceFile); break;\r
230                         case '.rle':\r
231                         case '.bmp':\r
232                                 $im_in = $this->_ImageCreateFromBMP($this->sourceFile); break;\r
233                         default:\r
234                                 return false;\r
235                 }\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
241                 return true;\r
242         }\r
243 }\r
244 ?>