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?>