1: <?php
2: /**
3: ##DOC-SIGNATURE##
4:
5: This file is part of WideImage.
6:
7: WideImage is free software; you can redistribute it and/or modify
8: it under the terms of the GNU Lesser General Public License as published by
9: the Free Software Foundation; either version 2.1 of the License, or
10: (at your option) any later version.
11:
12: WideImage is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU Lesser General Public License for more details.
16:
17: You should have received a copy of the GNU Lesser General Public License
18: along with WideImage; if not, write to the Free Software
19: Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20:
21: * @package Internal/Mappers
22: **/
23:
24: /**
25: * External code for TGA
26: *
27: * Adapted for use in WideImage. Code used with permission from the original author de77.
28: * http://de77.com/php/open-tga-with-php-imagecreatefromtga
29: *
30: * @author de77
31: * @license MIT
32: * @version 24.08.2010
33: * @url http://de77.com
34: *
35: * @package Internal/Mappers
36: */
37:
38: namespace WideImage\vendor\de77;
39:
40: class TGA
41: {
42: public static function rle_decode($data, $datalen)
43: {
44: $len = strlen($data);
45:
46: $out = '';
47:
48: $i = 0;
49: $k = 0;
50:
51: while ($i < $len) {
52: static::dec_bits(ord($data[$i]), $type, $value);
53:
54: if ($k >= $datalen) {
55: break;
56: }
57:
58: $i++;
59:
60: if ($type == 0) { //raw
61: for ($j = 0; $j < (3 * $value); $j++) {
62: $out .= $data[$j+$i];
63: $k++;
64: }
65:
66: $i += $value * 3;
67: } else { //rle
68: for ($j = 0; $j < $value; $j++) {
69: $out .= $data[$i] . $data[$i+1] . $data[$i+2];
70: $k++;
71: }
72:
73: $i += 3;
74: }
75: }
76:
77: return $out;
78: }
79:
80: public static function dec_bits($byte, &$type, &$value)
81: {
82: $type = ($byte & 0x80) >> 7;
83: $value = 1 + ($byte & 0x7F);
84: }
85:
86: public static function imagecreatefromstring($bin_data)
87: {
88: if (!trim($bin_data)) {
89: return false;
90: }
91:
92: $bin_pos = 0;
93: $header = substr($bin_data, $bin_pos, 18);
94: $bin_pos += 18;
95: $header = unpack( "cimage_id_len/ccolor_map_type/cimage_type/vcolor_map_origin/vcolor_map_len/" .
96: "ccolor_map_entry_size/vx_origin/vy_origin/vwidth/vheight/" .
97: "cpixel_size/cdescriptor", $header);
98:
99: switch ($header['image_type']) {
100: case 2: //no palette, uncompressed
101: case 10: //no palette, rle
102: break;
103: default: return false;
104: }
105:
106: if ($header['pixel_size'] != 24) {
107: return false;
108: //die('Unsupported TGA color depth');
109: }
110:
111: $bytes = $header['pixel_size'] / 8;
112:
113: if ($header['image_id_len'] > 0) {
114: $header['image_id'] = substr($bin_data, $bin_pos, $header['image_id_len']);
115: $bin_pos += $header['image_id_len'];
116: } else {
117: $header['image_id'] = '';
118: }
119:
120: $im = imagecreatetruecolor($header['width'], $header['height']);
121:
122: $size = $header['width'] * $header['height'] * 3;
123:
124: //-- check whether this is NEW TGA or not
125: $pos = $bin_pos;
126: $bin_pos = strlen($bin_data) - 26;
127: $newtga = substr($bin_data, $bin_pos, 26);
128:
129: if (substr($newtga, 8, 16) != 'TRUEVISION-XFILE') {
130: $newtga = false;
131: }
132:
133: $bin_pos = strlen($bin_data);
134: $datasize = $bin_pos - $pos;
135:
136: if ($newtga) {
137: $datasize -= 26;
138: }
139:
140: $bin_pos = $pos;
141:
142: //-- end of check
143: $data = substr($bin_data, $bin_pos, $datasize);
144: $bin_pos += $datasize;
145:
146: if ($header['image_type'] == 10) {
147: $data = self::rle_decode($data, $size);
148: }
149:
150: $reverse = self::bit5($header['descriptor']) == 1;
151: $pixels = str_split($data, 3);
152:
153: $i = 0;
154:
155: //read pixels
156: if ($reverse) {
157: for ($y = 0; $y < $header['height']; $y++) {
158: for ($x = 0; $x < $header['width']; $x++) {
159: imagesetpixel($im, $x, $y, self::dwordize($pixels[$i]));
160: $i++;
161: }
162: }
163: } else {
164: for ($y = $header['height']-1; $y >= 0; $y--) {
165: for ($x=0; $x<$header['width']; $x++) {
166: imagesetpixel($im, $x, $y, self::dwordize($pixels[$i]));
167: $i++;
168: }
169: }
170: }
171:
172: return $im;
173: }
174:
175: public static function imagecreatefromtga($filename)
176: {
177: return self::imagecreatefromstring(file_get_contents($filename));
178: }
179:
180: public static function dwordize($str)
181: {
182: $a = ord($str[0]);
183: $b = ord($str[1]);
184: $c = ord($str[2]);
185:
186: return $c*256*256 + $b*256 + $a;
187: }
188:
189: public static function bit5($x)
190: {
191: return ($x & 32) >> 5;
192: }
193: }
194: