source: branches/version-2_11-dev/data/include/image_converter.inc @ 20973

Revision 20973, 8.4 KB checked in by Seasoft, 10 years ago (diff)

#597 (画像サイズ変更で透過GIFが扱えない)

  • Property svn:eol-style set to LF
  • Property svn:keywords set to Id
Line 
1<?php
2/**
3 * 画像ファイルの変換を行う
4 */
5class ImageConverter {
6    var $outputImageDir;         // 変換後の画像の保存先
7    var $outputImageType;        // 変換後の画像の形式
8    var $outputImageWidth;       // 変換後の画像の横幅
9    var $outputImageHeight;      // 変換後の画像の高さ
10    var $outputImageFileSize;    // 変換後の画像のファイルサイズ
11
12    // コンストラクタ
13    function ImageConverter() {
14        $this->outputImageDir    = realpath(realpath(dirname(__FILE__)));
15        $this->outputImageType   = 'jpg';
16        $this->outputImageWidth  = 320;
17        $this->outputImageHeight = NULL;
18        $this->outputFileSize    = 20000;
19    }
20
21    // 変換実行
22    function execute($inputImagePath) {
23        // 前処理
24        $filestat         = @stat($inputImagePath);
25        $imagesize        = getimagesize($inputImagePath);
26        $inputImageWidth  = $imagesize[0];
27        $inputImageHeight = $imagesize[1];
28        $inputImageType   = $imagesize[2];
29
30        // GIF 画像は縮小後も GIF 画像で出力する。旧機種対応などで、機種用の画像形式に変換したい場合、この処理は削除する。
31        if ($inputImageType == IMAGETYPE_GIF) {
32            $this->outputImageType = 'gif';
33        }
34
35        $outputImageName  = sha1($inputImagePath . '_' . $this->outputImageWidth . '_' . $this->outputFileSize . '_' . $filestat['mtime']) . '.' . $this->outputImageType;
36        $outputImagePath  = $this->outputImageDir . '/' . $outputImageName;
37
38        if (is_null($this->outputImageHeight)) {
39            $height_was_null = TRUE;
40            $this->outputImageHeight = $inputImageHeight * ($this->outputImageWidth / $inputImageWidth);
41        } else {
42            $height_was_null = FALSE;
43        }
44        if ($inputImageWidth <= $this->outputImageWidth) {
45            if ($inputImageHeight <= $this->outputImageHeight) {
46                $this->outputImageWidth  = $inputImageWidth;
47                $this->outputImageHeight = $inputImageHeight;
48            } else {
49                $this->outputImageWidth = $inputImageWidth * ($this->outputImageHeight / $inputImageHeight);
50            }
51        } else {
52            if ($inputImageHeight <= $this->outputImageHeight) {
53                $this->outputImageHeight = $inputImageHeight * ($this->outputImageWidth / $inputImageWidth);
54            } else {
55                if ($this->outputImageWidth / $inputImageWidth < $this->outputImageHeight / $inputImageHeight) {
56                    $this->outputImageHeight = $inputImageHeight * ($this->outputImageWidth / $inputImageWidth);
57                } else {
58                    $this->outputImageWidth = $inputImageWidth * ($this->outputImageHeight / $inputImageHeight);
59                }
60            }
61        }
62
63        // ファイルが存在するか確認し、存在しない場合のみ作成する
64        if (file_exists($outputImagePath)) {
65            $info['convert'] = FALSE;
66        } else {
67            // 元ファイル作成
68            switch($inputImageType) {
69                case IMAGETYPE_GIF:
70                    $tempImage = imagecreatefromgif($inputImagePath);
71                    $arrTransparentColor = $this->getTransparentColor($tempImage);
72                    if (!empty($arrTransparentColor)) {
73                        imagecolortransparent($tempImage, $arrTransparentColor);
74                    }
75                    break;
76
77                case IMAGETYPE_JPEG:
78                    $tempImage = imagecreatefromjpeg($inputImagePath);
79                    break;
80
81                case IMAGETYPE_PNG:
82                    $tempImage = imagecreatefrompng($inputImagePath);
83                    break;
84
85                case IMAGETYPE_WBMP:
86                    $tempImage = imagecreatefromwbmp($inputImagePath);
87                    break;
88            }
89
90            if (!$tempImage) {
91                return false;
92            }
93
94            $scale = 1.0;
95            $outputImagePathTemp = $outputImagePath . '.tmp-' . rand();
96            do {
97                // 空ファイル作成
98                if ($this->outputImageType == 'gif') {
99                    // 縮小時のノイズ防止のためインデックスカラーで処理する。特に透過色を扱う上で重要。
100                    $outputImage = ImageCreate($this->outputImageWidth * $scale, $this->outputImageHeight * $scale);
101                } else {
102                    $outputImage = ImageCreateTruecolor($this->outputImageWidth * $scale, $this->outputImageHeight * $scale);
103                }
104
105                ImageCopyResampled($outputImage, $tempImage, 0, 0, 0, 0, $this->outputImageWidth * $scale, $this->outputImageHeight * $scale, $inputImageWidth, $inputImageHeight);
106
107                // ファイル出力
108
109                @unlink($outputImagePathTemp);
110
111                switch ($this->outputImageType) {
112                    case 'gif':
113                        if (!empty($arrTransparentColor)) {
114                            $transparent_color_id = imagecolorexact($outputImage, $arrTransparentColor['red'], $arrTransparentColor['green'], $arrTransparentColor['blue']);
115                            imagecolortransparent($outputImage, $transparent_color_id);
116                        }
117                        imagegif($outputImage, $outputImagePathTemp);
118                        break;
119
120                    case 'jpg':
121                        $quality = 75;
122                        // 表示可能なファイルサイズ以下になるまで、10%ずつクオリティを調整する
123                        do {
124                            @unlink($outputImagePathTemp);
125                            imagejpeg($outputImage, $outputImagePathTemp, $quality);
126                            $quality -= 10;
127                            clearstatcache();
128                        } while (filesize($outputImagePathTemp) > $this->outputFileSize && $quality > 0);
129                        break;
130
131                    case 'png':
132                        imagepng($outputImage, $outputImagePathTemp);
133                        break;
134
135                    case 'bmp':
136                        imagewbmp($outputImage, $outputImagePathTemp);
137                        break;
138
139                    default:
140                        GC_Utils_Ex::gfPrintLog('不正な画像タイプ: ');
141                        break;
142                }
143
144                // メモリ開放
145                imagedestroy($outputImage);
146
147                $scale -= 0.1;
148                clearstatcache();
149            } while (filesize($outputImagePathTemp) > $this->outputFileSize && $scale >= 0.5);
150
151            rename($outputImagePathTemp, $outputImagePath);
152
153            // メモリ開放
154            imagedestroy($tempImage);
155
156            $info['convert'] = TRUE;
157        }
158
159        if ($height_was_null) {
160            $this->outputImageHeigh = NULL;
161        }
162
163        $info['outputImagePath']  = $outputImagePath;
164        $info['outputImageName']  = $outputImageName;
165        return $info;
166
167    }
168
169    // Setter
170    function setOutputDir($outputDir)   { $this->outputImageDir   = $outputDir;  }
171    function setImageType($imageType)   { $this->outputImageType  = $imageType;  }
172    function setImageWidth($imageWidth) { $this->outputImageWidth = $imageWidth; }
173    function setImageHeight($imageHeight) { $this->outputImageHeight = $imageHeight; }
174    function setFileSize($fileSize)     { $this->outputFileSize   = $fileSize;   }
175
176    // Getter
177    function getOutputDir()   { return $this->outputDir;         }
178    function getImageType()   { return $this->outputImageType;   }
179    function getImageWidth()  { return $this->outputImageWidth;  }
180    function getImageHeight() { return $this->outputImageHeight; }
181
182    /*
183     * PrivateMethod
184     */
185    function beforeExecute() {
186    }
187
188    /**
189     * 透過GIFの色情報を返す
190     *
191     * @access private
192     * @param resource $image imagecreatetruecolor() のような画像作成関数が返す画像リソース。
193     * @return array 色情報
194     */
195    function getTransparentColor($image) {
196        $max_x = imagesx($image) - 1;
197        $max_y = imagesy($image) - 1;
198        for ($x = 0; $x <= $max_x; $x++) {
199            for ($y = 0; $y <= $max_y; $y++) {
200                $color_index = imagecolorat($image, $x, $y);
201                $arrColors = imagecolorsforindex($image, $color_index);
202                if ($arrColors['alpha'] !== 0){
203                    return $arrColors;
204                }
205            }
206        }
207        return array();
208    }
209}
210?>
Note: See TracBrowser for help on using the repository browser.