1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15: class Horde_Image_Png extends Horde_Image_Base {
16:
17: 18: 19: 20: 21:
22: var $_img = array();
23:
24: 25: 26: 27: 28:
29: var $_colorDepth = 8;
30:
31: 32: 33: 34: 35:
36: var $_colorType = 2;
37:
38: 39: 40: 41: 42:
43: var $_compressionMethod = 0;
44:
45: 46: 47: 48: 49:
50: var $_filterMethod = 0;
51:
52: 53: 54: 55: 56:
57: var $_interlaceMethod = 0;
58:
59: 60: 61:
62: public function __construct($params, $context = array())
63: {
64: parent::__construct($params, $context);
65:
66: if (!empty($params['width'])) {
67: $this->rectangle(0, 0, $params['width'], $params['height'], $this->_background, $this->_background);
68: }
69: }
70:
71: function getContentType()
72: {
73: return 'image/png';
74: }
75:
76: 77: 78: 79: 80:
81: function raw()
82: {
83: return
84: $this->_header() .
85: $this->_IHDR() .
86:
87:
88: $this->_tEXt('Software', 'Horde Framework Image_png Class') .
89:
90:
91: $this->_tIME() .
92:
93: $this->_IDAT() .
94: $this->_IEND();
95: }
96:
97: 98: 99:
100: function reset()
101: {
102: parent::reset();
103: $this->_img = array();
104: }
105:
106: 107: 108: 109: 110: 111: 112: 113: 114: 115:
116: function rectangle($x, $y, $width, $height, $color = 'black', $fill = 'none')
117: {
118: list($r, $g, $b) = Horde_Image::getRGB($color);
119: if ($fill != 'none') {
120: list($fR, $fG, $fB) = Horde_Image::getRGB($fill);
121: }
122:
123: $x2 = $x + $width;
124: $y2 = $y + $height;
125:
126: for ($h = $y; $h <= $y2; $h++) {
127: for ($w = $x; $w <= $x2; $w++) {
128:
129: if ($w == $x || $h == $y || $w == $x2 || $h == $y2) {
130: $this->_img[$h][$w] = array('r' => $r, 'g' => $g, 'b' => $b);
131: } elseif ($fill != 'none') {
132: $this->_img[$h][$w] = array('r' => $fR, 'g' => $fG, 'b' => $fB);
133: }
134: }
135: }
136: }
137:
138: 139: 140:
141: function ()
142: {
143: return pack('CCCCCCCC', 137, 80, 78, 71, 13, 10, 26, 10);
144: }
145:
146: 147: 148:
149: function _IHDR()
150: {
151: $data = pack('a4NNCCCCC', 'IHDR', $this->_width, $this->_height, $this->_colorDepth, $this->_colorType, $this->_compressionMethod, $this->_filterMethod, $this->_interlaceMethod);
152: return pack('Na' . strlen($data) . 'N', strlen($data) - 4, $data, crc32($data));
153: }
154:
155: 156: 157:
158: function _IEND()
159: {
160: $data = 'IEND';
161: return pack('Na' . strlen($data) . 'N', strlen($data) - 4, $data, crc32($data));
162: }
163:
164: 165: 166:
167: function _IDAT()
168: {
169: $data = '';
170: $prevscanline = null;
171: $filter = 0;
172: for ($i = 0; $i < $this->_height; $i++) {
173: $scanline = array();
174: $data .= chr($filter);
175: for ($j = 0; $j < $this->_width; $j++) {
176: if ($this->_colorDepth == 8) {
177: $scanline[$j] = pack('CCC', $this->_img[$i][$j]['r'], $this->_img[$i][$j]['g'], $this->_img[$i][$j]['b']);
178: } elseif ($this->_colorDepth == 16) {
179: $scanline[$j] = pack('nnn', $this->_img[$i][$j]['r'] << 8, $this->_img[$i][$j]['g'] << 8, $this->_img[$i][$j]['b'] << 8);
180: }
181:
182: if ($filter == 0) {
183:
184: $data .= $scanline[$j];
185: } elseif ($filter == 2) {
186:
187: $pixel = $scanline[$j] - $prevscanline[$j];
188: if ($this->_colorDepth == 8) {
189: $data .= pack('CCC', $pixel >> 16, ($pixel >> 8) & 0xFF, $pixel & 0xFF);
190: } elseif ($this->_colorDepth == 16) {
191: $data .= pack('nnn', ($pixel >> 32), ($pixel >> 16) & 0xFFFF, $pixel & 0xFFFF);
192: }
193: }
194: }
195: $prevscanline = $scanline;
196: }
197: $compressed = gzdeflate($data, 9);
198:
199: $data = 'IDAT' . pack('CCa' . strlen($compressed) . 'a4', 0x78, 0x01, $compressed, $this->_Adler32($data));
200: return pack('Na' . strlen($data) . 'N', strlen($data) - 4, $data, crc32($data));
201: }
202:
203: 204: 205:
206: function _tEXt($keyword, $text)
207: {
208: $data = 'tEXt' . $keyword . "\0" . $text;
209: return pack('Na' . strlen($data) . 'N', strlen($data) - 4, $data, crc32($data));
210: }
211:
212: 213: 214:
215: function _tIME($date = null)
216: {
217: if (is_null($date)) {
218: $date = time();
219: }
220:
221: $data = 'tIME' . pack('nCCCCC', intval(date('Y', $date)), intval(date('m', $date)), intval(date('j', $date)), intval(date('G', $date)), intval(date('i', $date)), intval(date('s', $date)));
222: return pack('Na' . strlen($data) . 'N', strlen($data) - 4, $data, crc32($data));
223: }
224:
225: 226: 227:
228: function _Adler32($input)
229: {
230: $s1 = 1;
231: $s2 = 0;
232: $iMax = strlen($input);
233: for ($i = 0; $i < $iMax; $i++) {
234: $s1 = ($s1 + ord($input[$i])) % 0xFFF1;
235: $s2 = ($s2 + $s1) % 0xFFF1;
236: }
237: return pack('N', (($s2 << 16) | $s1));
238: }
239:
240: 241: 242: 243: 244: 245: 246: 247:
248: public function getImageAtIndex($index)
249: {
250: if ($index > 0) {
251: throw new Horde_Image_Exception('Image index out of bounds.');
252: }
253:
254: return clone($this);
255: }
256:
257: 258: 259: 260: 261:
262: public function getImagePageCount()
263: {
264: return 1;
265: }
266:
267: }
268: