1<?php
2
3require_once(HTML2PS_DIR.'ps.image.encoder.stream.inc.php');
4
5class PSL3ImageEncoderStream extends PSImageEncoderStream {
6  function PSL3ImageEncoderStream() {
7    $this->last_image_id = 0;
8  }
9
10  function auto(&$psdata, $src_img, &$size_x, &$size_y, &$tcolor, &$image, &$mask) {
11    if (imagecolortransparent($src_img->get_handle()) == -1) {
12      $id = $this->solid($psdata, $src_img->get_handle(), $size_x, $size_y, $image->get_handle(), $mask);
13      $tcolor = 0;
14      return $id;
15    } else {
16      $id = $this->transparent($psdata, $src_img->get_handle(), $size_x, $size_y, $image->get_handle(), $mask);
17      $tcolor = 1;
18
19      return $id;
20    };
21  }
22
23  // Encodes "solid" image without any transparent parts
24  //
25  // @param $psdata (in) Postscript file "writer" object
26  // @param $src_img (in) PHP image resource
27  // @param $size_x (out) size of image in pixels
28  // @param $size_y (out) size of image in pixels
29  // @returns identifier if encoded image to use in postscript file
30  //
31  function solid(&$psdata, $src_img, &$size_x, &$size_y, &$image, &$mask) {
32    // Generate an unique image id
33    $id = $this->generate_id();
34
35    // Determine image size and create a truecolor copy of this image
36    // (as we don't want to work with palette-based images manually)
37    $size_x      = imagesx($src_img);
38    $size_y      = imagesy($src_img);
39    $dest_img    = imagecreatetruecolor($size_x, $size_y);
40    imagecopymerge($dest_img, $src_img, 0, 0, 0, 0, $size_x, $size_y, 100);
41
42    // write stread header to the postscript file
43    $psdata->write("/image-{$id}-init { image-{$id}-data 0 setfileposition } def\n");
44    $psdata->write("/image-{$id}-data currentfile << /Filter /ASCIIHexDecode >> /ReusableStreamDecode filter\n");
45
46    // initialize line length counter
47    $ctr = 0;
48
49    for ($y = 0; $y < $size_y; $y++) {
50      for ($x = 0; $x < $size_x; $x++) {
51        // Save image pixel to the stream data
52        $rgb = ImageColorAt($dest_img, $x, $y);
53        $r = ($rgb >> 16) & 0xFF;
54        $g = ($rgb >> 8) & 0xFF;
55        $b = $rgb & 0xFF;
56        $psdata->write(sprintf("%02X%02X%02X",min(max($r,0),255),min(max($g,0),255),min(max($b,0),255)));
57
58        // Increate the line length counter; check if stream line needs to be terminated
59        $ctr += 6;
60        if ($ctr > MAX_LINE_LENGTH) {
61          $psdata->write("\n");
62          $ctr = 0;
63        }
64      };
65    };
66
67    // terminate the stream data
68    $psdata->write(">\ndef\n");
69
70    // return image and mask data references
71    $image = "image-{$id}-data";
72    $mask  = "";
73
74    return $id;
75  }
76
77  // Encodes image containing 100% transparent color (1-bit alpha channel)
78  //
79  // @param $psdata (in) Postscript file "writer" object
80  // @param $src_img (in) PHP image resource
81  // @param $size_x (out) size of image in pixels
82  // @param $size_y (out) size of image in pixels
83  // @returns identifier if encoded image to use in postscript file
84  //
85  function transparent(&$psdata, $src_img, &$size_x, &$size_y, &$image, &$mask) {
86    // Generate an unique image id
87    $id = $this->generate_id();
88
89    // Store transparent color for further reference
90    $transparent = imagecolortransparent($src_img);
91
92    // Determine image size and create a truecolor copy of this image
93    // (as we don't want to work with palette-based images manually)
94    $size_x      = imagesx($src_img);
95    $size_y      = imagesy($src_img);
96    $dest_img    = imagecreatetruecolor($size_x, $size_y);
97    imagecopymerge($dest_img, $src_img, 0, 0, 0, 0, $size_x, $size_y, 100);
98
99    // write stread header to the postscript file
100    $psdata->write("/image-{$id}-init { image-{$id}-data 0 setfileposition mask-{$id}-data 0 setfileposition } def\n");
101
102    // Create IMAGE data stream
103    $psdata->write("/image-{$id}-data currentfile << /Filter /ASCIIHexDecode >> /ReusableStreamDecode filter\n");
104
105    // initialize line length counter
106    $ctr = 0;
107
108    for ($y = 0; $y < $size_y; $y++) {
109      for ($x = 0; $x < $size_x; $x++) {
110        // Save image pixel to the stream data
111        $rgb = ImageColorAt($dest_img, $x, $y);
112        $r = ($rgb >> 16) & 0xFF;
113        $g = ($rgb >> 8) & 0xFF;
114        $b = $rgb & 0xFF;
115
116        $psdata->write(sprintf("%02X%02X%02X",$r,$g,$b));
117
118        // Increate the line length counter; check if stream line needs to be terminated
119        $ctr += 6;
120        if ($ctr > MAX_LINE_LENGTH) {
121          $psdata->write("\n");
122          $ctr = 0;
123        }
124      };
125    };
126
127    // terminate the stream data
128    $psdata->write(">\ndef\n");
129
130    // Create MASK data stream
131    $psdata->write("/mask-{$id}-data currentfile << /Filter /ASCIIHexDecode >> /ReusableStreamDecode filter\n");
132
133    // initialize line length counter
134    $ctr = 0;
135
136    // initialize mask bit counter
137    $bit_ctr = 0;
138    $mask_data = 0xff;
139
140    for ($y = 0; $y < $size_y; $y++) {
141      for ($x = 0; $x < $size_x; $x++) {
142        // Check if this pixel should be transparent
143        if (ImageColorAt($src_img, $x, $y) == $transparent) {
144          $mask_data = ($mask_data << 1) | 0x1;
145        } else {
146          $mask_data = ($mask_data << 1);
147        };
148        $bit_ctr ++;
149
150        // If we've filled the whole byte,  write it into the mask data stream
151        if ($bit_ctr >= 8 || $x + 1 == $size_x) {
152          // Pad mask data, in case we have completed the image row
153          while ($bit_ctr < 8) {
154            $mask_data = ($mask_data << 1) | 0x01;
155            $bit_ctr ++;
156          };
157
158          $psdata->write(sprintf("%02X", $mask_data & 0xff));
159
160          // Clear mask data after writing
161          $mask_data = 0xff;
162          $bit_ctr = 0;
163
164          // Increate the line length counter; check if stream line needs to be terminated
165          $ctr += 1;
166          if ($ctr > MAX_LINE_LENGTH) {
167            $psdata->write("\n");
168            $ctr = 0;
169          }
170        };
171      };
172    };
173
174    // terminate the stream data
175    // Write any incomplete mask byte to the mask data stream
176    if ($bit_ctr != 0) {
177      while ($bit_ctr < 8) {
178        $mask_data <<= 1;
179        $mask_data |= 1;
180        $bit_ctr ++;
181      }
182      $psdata->write(sprintf("%02X", $mask_data));
183    };
184    $psdata->write(">\ndef\n");
185
186    // return image and mask data references
187    $image = "image-{$id}-data";
188    $mask  = "mask-{$id}-data";
189
190    return $id;
191  }
192
193  function alpha(&$psdata, $src_img, &$size_x, &$size_y, &$image, &$mask) {
194    // Generate an unique image id
195    $id = $this->generate_id();
196
197    // Determine image size
198    $size_x      = imagesx($src_img);
199    $size_y      = imagesy($src_img);
200
201    // write stread header to the postscript file
202    $psdata->write("/image-{$id}-init { image-{$id}-data 0 setfileposition } def\n");
203    $psdata->write("/image-{$id}-data currentfile << /Filter /ASCIIHexDecode >> /ReusableStreamDecode filter\n");
204
205    // initialize line length counter
206    $ctr = 0;
207
208    // Save visible background color
209    $handler =& CSS::get_handler(CSS_BACKGROUND_COLOR);
210    $bg = $handler->get_visible_background_color();
211
212    for ($y = 0; $y < $size_y; $y++) {
213      for ($x = 0; $x < $size_x; $x++) {
214        // Check color/alpha of current pixels
215        $colors = imagecolorsforindex($src_img, imagecolorat($src_img, $x, $y));
216
217        $a = $colors['alpha'];
218        $r = $colors['red'];
219        $g = $colors['green'];
220        $b = $colors['blue'];
221
222        // Calculate approximate color
223        $r = (int)($r + ($bg[0] - $r)*$a/127);
224        $g = (int)($g + ($bg[1] - $g)*$a/127);
225        $b = (int)($b + ($bg[2] - $b)*$a/127);
226
227        // Save image pixel to the stream data
228        $psdata->write(sprintf("%02X%02X%02X",$r,$g,$b));
229
230        // Increate the line length counter; check if stream line needs to be terminated
231        $ctr += 6;
232        if ($ctr > MAX_LINE_LENGTH) {
233          $psdata->write("\n");
234          $ctr = 0;
235        }
236      };
237    };
238
239    // terminate the stream data
240    $psdata->write(">\ndef\n");
241
242    // return image and mask data references
243    $image = "image-{$id}-data";
244    $mask  = "";
245
246    return $id;
247  }
248
249}
250?>