ここの情報は古いです。ご理解頂いた上でお取り扱いください。

source: OpenPNE/branches/work/ebihara/prj_renew_OpenPNE_Img/webapp/lib/OpenPNE/Img/Generator.php @ 6913

Last change on this file since 6913 was 6913, checked in by ebihara, 13 years ago

r6909で画像サイズ算出アルゴリズムに手を加えてしまったのを修正

File size: 8.9 KB
Line 
1<?php
2/**
3 * @copyright 2005-2008 OpenPNE Project
4 * @license   http://www.php.net/license/3_01.txt PHP License 3.01
5 */
6
7/**
8 * OpenPNEで画像処理をおこなうGeneratorのスーパークラス
9 *
10 * @package OpenPNE
11 * @author Kousuke Ebihara <ebihara@tejimaya.net>
12 */
13class OpenPNE_Img_Generator
14{
15    var $jpeg_quality = 75;
16    var $width = 0;
17    var $height = 0;
18
19    var $source_format;
20    var $output_format;
21
22    var $cache_dir;
23    var $cache_fullpath;
24
25    /**
26     * 変換を許可する画像サイズ
27     *
28     * この配列にあるサイズの画像のみ出力できる。
29     * 空の場合は無制限となる。
30     *
31     * @var array
32     */
33    var $allowed_size;
34
35    function OpenPNE_Img_Generator($options = array())
36    {
37        $this->allowed_size = (array)$GLOBALS['_OPENPNE_IMG_ALLOWED_SIZE'];
38        if (isset($options['allowed_size'])) {
39            $this->allowed_size = $options['allowed_size'];
40        }
41
42        if (!empty($options['jpeg_quality'])) {
43            $this->jpeg_quality = $options['jpeg_quality'];
44        }
45
46        if (!empty($options['cache_dir'])) {
47            $this->cache_dir = $options['cache_dir'];
48        }
49    }
50
51    function createImage($raw_img, $format)
52    {
53        if (!$this->isAllowedSize($this->width, $this->height)) {
54            return false;
55        }
56
57        // サイズ指定がなく、かつ、形式変換しない場合(GDに変換する必要なし)
58        if (!$this->width && !$this->height && ($this->getSourceFormat() == $this->getOutputFormat())) {
59            $this->createCacheFromRawImage($this->cache_fullpath, $this->cache_dir, $raw_img);
60            return true;
61        }
62
63        // create a GD image from raw_img
64        if (!$source_gdimg  = imagecreatefromstring($raw_img)) {
65            return false;
66        }
67
68        if ($format == 'jpg') {
69            // JPEGの場合、携帯対応
70            imageinterlace($source_gdimg, 0);
71        }
72
73        // リサイズ
74        $output_img = $this->resizeImage($source_gdimg);
75
76        // キャッシュを生成
77        if ($output_img) {
78            $this->createCache($this->cache_fullpath, $this->cache_dir, $output_img);
79        } else {
80            $this->createCacheFromRawImage($this->cache_fullpath, $this->cache_dir, $raw_img);
81        }
82
83        return true;
84    }
85
86    /**
87     * GDイメージのリサイズ+形式変換
88     *
89     * @param resource $gdimg source GD image
90     * @return resource output GD image
91     */
92    function resizeImage($source_gdimg)
93    {
94        $s_width  = imagesx($source_gdimg);
95        $s_height = imagesy($source_gdimg);
96
97        $o_width  = $this->width;
98        $o_height = $this->height;
99        if (!$o_width) {
100            $o_width = $s_width;
101        }
102        if (!$o_height) {
103            $o_height = $s_height;
104        }
105
106        // リサイズの必要がない場合
107        if ($s_width <= $o_width && $s_height <= $o_height) {
108            // 形式変換する場合はGDを通す
109            if ($this->source_format != $this->output_format) {
110                return $source_gdimg;
111            }
112            return false;
113        }
114
115        $h = $s_height;
116        if ($o_width < $s_width) {
117            $h = $s_height * $o_width / $s_width;
118        }
119        if ($o_height < $h && $o_height < $s_height) {
120            $o_width = $s_width * $o_height / $s_height;
121        }
122
123        if ($o_height < 1.) {
124            $o_height = 1;
125        }
126        if ($o_width < 1.) {
127            $o_width = 1;
128        }
129
130        $output_gdimg = imagecreatetruecolor($o_width, $o_height);
131
132        if (($this->output_format == 'gif') || ($this->output_format == 'png')) {
133            $trnprt_idx_s = imagecolortransparent($source_gdimg);
134            if ($trnprt_idx_s >= 0) { // 透過色が設定されている
135                imagetruecolortopalette($output_gdimg, true, 256);
136
137                // 入力画像から透明色取得
138                $trnprt_color = imagecolorsforindex($source_gdimg, $trnprt_idx_s);
139
140                // 出力画像に透明色設定
141                imagecolorset($source_gdimg, 0, $trnprt_color['red'], $trnprt_color['green'], $trnprt_color['blue']);
142                imagefill($output_gdimg, 0, 0, 0);
143                imagecolortransparent($output_gdimg, 0);
144            } elseif ($this->output_format == 'png') {  // PNG-24
145                // アルファチャンネル情報を保存するには、アルファブレンディングを解除する必要がある
146                imagealphablending($output_gdimg, false);
147                imagesavealpha($output_gdimg, true);
148
149                // 透過色設定
150                $color = imagecolorallocatealpha($output_gdimg, 0, 0, 0, 127);
151                imagefill($output_gdimg, 0, 0, $color);
152            }
153        }
154
155        imagecopyresampled($output_gdimg, $source_gdimg,
156                0, 0, 0, 0, $o_width, $o_height, $s_width, $s_height);
157        return $output_gdimg;
158    }
159
160    function createCacheFromRawImage($cache_fullpath, $cache_dir, $raw_img)
161    {
162        $this->createCacheSubdir($cache_fullpath, $cache_dir);
163
164        if ($this->getOutputFormat() == 'png') {
165            touch($cache_fullpath);
166            $output_gdimg = imagecreatefromstring($raw_img);
167            imagepng($output_gdimg, $cache_fullpath);
168        } else {
169            $handle = fopen($cache_fullpath, 'wb');
170            fwrite($handle, $raw_img);
171            fclose($handle);
172        }
173    }
174
175    function createCache($cache_fullpath, $cache_dir, $output_gdimg)
176    {
177        $this->createCacheSubdir($cache_fullpath, $cache_dir);
178
179        touch($cache_fullpath);
180        switch ($this->getOutputFormat()) {
181        case 'jpeg':
182        case 'jpg':
183        default:
184            imagejpeg($output_gdimg, $cache_fullpath, $this->jpeg_quality); break;
185        case 'gif':
186            imagegif($output_gdimg, $cache_fullpath);
187            break;
188        case 'png':
189            imagepng($output_gdimg, $cache_fullpath);
190            break;
191        }
192    }
193
194    function createCacheSubdir($cache_fullpath, $cache_dir)
195    {
196        $subdir = dirname($cache_fullpath);
197        if (!is_dir($subdir)) {
198            // mkdir recursive
199            $_dir = $cache_dir;
200            if (!is_dir($_dir) && !mkdir($_dir)) {
201                return false;
202            }
203            $relative_path = substr($subdir, strlen($cache_dir)+1);
204            $parts = explode('/', $relative_path);
205            foreach ($parts as $part) {
206                $_dir .=  '/' . $part;
207                if (!is_dir($_dir) && !mkdir($_dir)) {
208                    return false;
209                }
210            }
211        }
212    }
213
214    function checkFormatString($string)
215    {
216        $string = strtolower($string);
217
218        $format = 'jpg';
219        if ($string == 'gif' || $string == 'png') {
220            $format = $string;
221        }
222       
223        return $format;
224    }
225
226    function setCacheFileName($filename)
227    {
228        $pieces = explode('.', $filename);
229        $this->setSourceFormat($this->checkFormatString(array_pop($pieces)));
230
231        $f = $this->getOutputFormat();
232
233        $this->cache_fullpath =
234                 $this->cache_dir . '/' .
235                 $this->getCachePath($filename, $this->width, $this->height, $f);
236    }
237
238    function setOutputFormat($output_format = '')
239    {
240        if ($output_format) {
241            $this->output_format = $this->checkFormatString($output_format);
242        } else {
243            $this->output_format = $this->checkFormatString($this->getSourceFormat());
244        }
245    }
246
247    /**
248     * ファイルの高さ・幅をセット
249     *
250     * @param int $width
251     * @param int $height
252     */
253    function setImageSize($width = 0, $height = 0)
254    {
255        if (is_numeric($width)) {
256            $this->width = $width;
257        }
258
259        if (is_numeric($height)) {
260            $this->height = $height;
261        }
262    }
263
264    function setSourceFormat($source_format)
265    {
266        $this->source_format = $source_format;
267    }
268
269    function getOutputFormat()
270    {
271        return $this->output_format;
272    }
273
274    function getSourceFormat()
275    {
276        return $this->source_format;
277    }
278
279    function getCacheFullpath()
280    {
281        return $this->cache_fullpath;
282    }
283
284    function getCachePath($filename, $w, $h, $f)
285    {
286        $prefix = OPENPNE_IMG_CACHE_PREFIX;
287
288        if (!$w) $w = '';
289        if (!$h) $h = '';
290        $file = str_replace('.', '_', $filename) . '.' . $f;
291
292        $path = "{$f}/w{$w}_h{$h}/{$prefix}{$file}";
293        return $path;
294    }
295
296    function isCacheReadable()
297    {
298        return is_readable($this->cache_fullpath);
299    }
300
301    /**
302     * 変換可能な画像サイズかどうか
303     *
304     * @param int $width
305     * @param int $height
306     * @return bool
307     */
308    function isAllowedSize($width = 0, $height = 0)
309    {
310        if (!$width && !$height) {
311            return true;
312        }
313
314        $size = sprintf('%dx%d', $width, $height);
315        if ($this->allowed_size && !in_array($size, $this->allowed_size)) {
316            return false;
317        }
318
319        return true;
320    }
321}
322
323?>
Note: See TracBrowser for help on using the repository browser.