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

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

Last change on this file since 6925 was 6925, checked in by ebihara, 12 years ago

r6924でRAW画像が出力されなくなったのを修正

File size: 9.7 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 = 'jpg';
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)
52    {
53        if (!$this->isAllowedSize($this->width, $this->height)) {
54            return false;
55        }
56
57        if (!$this->isResizeImage($this->width, $this->height) && !$this->isConvertFormat()) {
58            $this->createCacheFromRawImage($raw_img);
59            return true;
60        }
61
62        // create a GD image from raw_img
63        if (!$source_gdimg  = imagecreatefromstring($raw_img)) {
64            return false;
65        }
66
67        if ($this->getOutputFormat() == 'jpg') {
68            // JPEGの場合、携帯対応
69            imageinterlace($source_gdimg, 0);
70        }
71
72        // リサイズ
73        $output_img = $this->resizeImage($source_gdimg);
74
75        // キャッシュを生成
76        if ($output_img) {
77            $this->createCache($output_img);
78        } else {
79            $this->createCacheFromRawImage($raw_img);
80        }
81
82        return true;
83    }
84
85    /**
86     * GDイメージのリサイズ+形式変換
87     *
88     * @param resource $gdimg source GD image
89     * @return resource output GD image
90     */
91    function resizeImage($source_gdimg)
92    {
93        $s_width  = imagesx($source_gdimg);
94        $s_height = imagesy($source_gdimg);
95
96        $o_width  = $this->width;
97        $o_height = $this->height;
98        if (!$o_width) {
99            $o_width = $s_width;
100        }
101        if (!$o_height) {
102            $o_height = $s_height;
103        }
104
105        $this->calcResizedImageSize($o_width, $o_height, $s_width, $s_height);
106
107        if (!$this->isResizeImage($o_width, $o_height, $s_width, $s_height)) {
108            if ($this->isConvertFormat()) {
109                return $source_gdimg;
110            }
111            return false;
112        }
113
114        $output_gdimg = imagecreatetruecolor($o_width, $o_height);
115        $this->setTransparentToOutputImage($output_gdimg, $source_gdimg);
116        imagecopyresampled($output_gdimg, $source_gdimg,
117                0, 0, 0, 0, $o_width, $o_height, $s_width, $s_height);
118
119        return $output_gdimg;
120    }
121
122    function createCacheFromRawImage($raw_img)
123    {
124        $this->createCacheSubdir($this->cache_dir);
125
126        if ($this->getOutputFormat() == 'png') {
127            touch($this->cache_fullpath);
128            $output_gdimg = imagecreatefromstring($raw_img);
129            imagepng($output_gdimg, $this->cache_fullpath);
130        } else {
131            $handle = fopen($this->cache_fullpath, 'wb');
132            fwrite($handle, $raw_img);
133            fclose($handle);
134        }
135    }
136
137    function createCache($output_gdimg)
138    {
139        $this->createCacheSubdir($this->cache_dir);
140
141        touch($this->cache_fullpath);
142        switch ($this->getOutputFormat()) {
143        case 'jpeg':
144        case 'jpg':
145        default:
146            imagejpeg($output_gdimg, $this->cache_fullpath, $this->jpeg_quality); break;
147        case 'gif':
148            imagegif($output_gdimg, $this->cache_fullpath);
149            break;
150        case 'png':
151            imagepng($output_gdimg, $this->cache_fullpath);
152            break;
153        }
154    }
155
156    function createCacheSubdir($cache_dir)
157    {
158        $subdir = dirname($this->cache_fullpath);
159        if (!is_dir($subdir)) {
160            // mkdir recursive
161            $_dir = $cache_dir;
162            if (!is_dir($_dir) && !mkdir($_dir)) {
163                return false;
164            }
165            $relative_path = substr($subdir, strlen($cache_dir)+1);
166            $parts = explode('/', $relative_path);
167            foreach ($parts as $part) {
168                $_dir .=  '/' . $part;
169                if (!is_dir($_dir) && !mkdir($_dir)) {
170                    return false;
171                }
172            }
173        }
174    }
175
176    function checkFormatString($string)
177    {
178        $string = strtolower($string);
179
180        $format = 'jpg';
181        if ($string == 'gif' || $string == 'png') {
182            $format = $string;
183        }
184       
185        return $format;
186    }
187
188    function setCacheFileName($filename)
189    {
190        $pieces = explode('.', $filename);
191        $this->setSourceFormat($this->checkFormatString(array_pop($pieces)));
192
193        $this->cache_fullpath =
194                 $this->cache_dir . '/' .
195                 $this->getCachePath($filename, $this->width, $this->height, $this->getOutputFormat());
196    }
197
198    function setOutputFormat($output_format = '')
199    {
200        if ($output_format) {
201            $this->output_format = $this->checkFormatString($output_format);
202        } else {
203            $this->output_format = $this->checkFormatString($this->getSourceFormat());
204        }
205    }
206
207    /**
208     * ファイルの高さ・幅をセット
209     *
210     * @param int $width
211     * @param int $height
212     */
213    function setImageSize($width = 0, $height = 0)
214    {
215        if (is_numeric($width)) {
216            $this->width = $width;
217        }
218
219        if (is_numeric($height)) {
220            $this->height = $height;
221        }
222    }
223
224    function setSourceFormat($source_format)
225    {
226        $this->source_format = $source_format;
227    }
228
229    function getOutputFormat()
230    {
231        return $this->output_format;
232    }
233
234    function getSourceFormat()
235    {
236        return $this->source_format;
237    }
238
239    function getCacheFullpath()
240    {
241        return $this->cache_fullpath;
242    }
243
244    function getCachePath($filename, $w, $h, $f)
245    {
246        $prefix = OPENPNE_IMG_CACHE_PREFIX;
247
248        if (!$w) $w = '';
249        if (!$h) $h = '';
250        $file = str_replace('.', '_', $filename) . '.' . $f;
251
252        $path = "{$f}/w{$w}_h{$h}/{$prefix}{$file}";
253        return $path;
254    }
255
256    function isCacheReadable()
257    {
258        return is_readable($this->cache_fullpath);
259    }
260
261    /**
262     * 変換可能な画像サイズかどうか
263     *
264     * @param int $width
265     * @param int $height
266     * @return bool
267     */
268    function isAllowedSize($width = 0, $height = 0)
269    {
270        if (!$width && !$height) {
271            return true;
272        }
273
274        $size = sprintf('%dx%d', $width, $height);
275        if ($this->allowed_size && !in_array($size, $this->allowed_size)) {
276            return false;
277        }
278
279        return true;
280    }
281
282    /**
283     * 画像フォーマットの変換をおこなうかどうか
284     *
285     * @return bool
286     */
287    function isConvertFormat()
288    {
289        if ($this->getSourceFormat() != $this->getOutputFormat()) {
290            return true;
291        }
292
293        return false;
294    }
295
296    /**
297     * 画像のリサイズをおこなうかどうか
298     *
299     * @return bool
300     */
301    function isResizeImage($o_width = 0, $o_height = 0, $s_width = 0, $s_height = 0)
302    {
303        if (!$o_width && !$o_height) {
304            return false;
305        }
306
307        if (!$s_width || !$s_height) {
308            return true;
309        }
310
311        if ($s_width <= $o_width && $s_height <= $o_height) {
312            return false;
313        }
314
315        return true;
316    }
317
318    /**
319     * リサイズ後の画像サイズを算出する
320     */
321    function calcResizedImageSize(&$o_width, &$o_height, $s_width, $s_height)
322    {
323        $h = $s_height;
324        if ($o_width < $s_width) {
325            $h = $s_height * $o_width / $s_width;
326        }
327        if ($o_height < $h && $o_height < $s_height) {
328            $o_width = $s_width * $o_height / $s_height;
329        }
330
331        if ($o_height < 1.) {
332            $o_height = 1;
333        }
334        if ($o_width < 1.) {
335            $o_width = 1;
336        }
337    }
338
339    /**
340     * 入力画像から取得した透過情報を出力画像に適用する
341     */
342    function setTransparentToOutputImage(&$output_gdimg, &$source_gdimg)
343    {
344        if ($this->getOutputFormat() != 'gif' && $this->getOutputFormat() != 'png') {
345            return null;
346        }
347
348        $trnprt_idx_s = imagecolortransparent($source_gdimg);
349        if ($trnprt_idx_s >= 0) { // 透過色が設定されている
350            imagetruecolortopalette($output_gdimg, true, 256);
351
352            // 入力画像から透明色取得
353            $trnprt_color = imagecolorsforindex($source_gdimg, $trnprt_idx_s);
354
355            // 出力画像に透明色設定
356            imagecolorset($source_gdimg, 0, $trnprt_color['red'], $trnprt_color['green'], $trnprt_color['blue']);
357            imagefill($output_gdimg, 0, 0, 0);
358            imagecolortransparent($output_gdimg, 0);
359        } elseif ($this->getOutputFormat() == 'png') {  // PNG-24
360            // アルファチャンネル情報を保存するには、アルファブレンディングを解除する必要がある
361            imagealphablending($output_gdimg, false);
362            imagesavealpha($output_gdimg, true);
363
364            // 透過色設定
365            $color = imagecolorallocatealpha($output_gdimg, 0, 0, 0, 127);
366            imagefill($output_gdimg, 0, 0, $color);
367        }
368    }
369}
370
371?>
Note: See TracBrowser for help on using the repository browser.