File indexing completed on 2025-01-19 05:21:21
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Pdf 0017 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0018 * @license http://framework.zend.com/license/new-bsd New BSD License 0019 * @version $Id$ 0020 */ 0021 0022 0023 /** Zend_Pdf_Filter_Interface */ 0024 // require_once 'Zend/Pdf/Filter/Interface.php'; 0025 0026 /** 0027 * ASCII85 stream filter 0028 * 0029 * @package Zend_Pdf 0030 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0031 * @license http://framework.zend.com/license/new-bsd New BSD License 0032 */ 0033 abstract class Zend_Pdf_Filter_Compression implements Zend_Pdf_Filter_Interface 0034 { 0035 /** 0036 * Paeth prediction function 0037 * 0038 * @param integer $a 0039 * @param integer $b 0040 * @param integer $c 0041 * @return integer 0042 */ 0043 private static function _paeth($a, $b, $c) 0044 { 0045 // $a - left, $b - above, $c - upper left 0046 $p = $a + $b - $c; // initial estimate 0047 $pa = abs($p - $a); // distances to a, b, c 0048 $pb = abs($p - $b); 0049 $pc = abs($p - $c); 0050 0051 // return nearest of a,b,c, 0052 // breaking ties in order a,b,c. 0053 if ($pa <= $pb && $pa <= $pc) { 0054 return $a; 0055 } else if ($pb <= $pc) { 0056 return $b; 0057 } else { 0058 return $c; 0059 } 0060 } 0061 0062 0063 /** 0064 * Get Predictor decode param value 0065 * 0066 * @param array $params 0067 * @return integer 0068 * @throws Zend_Pdf_Exception 0069 */ 0070 private static function _getPredictorValue(&$params) 0071 { 0072 if (isset($params['Predictor'])) { 0073 $predictor = $params['Predictor']; 0074 0075 if ($predictor != 1 && $predictor != 2 && 0076 $predictor != 10 && $predictor != 11 && $predictor != 12 && 0077 $predictor != 13 && $predictor != 14 && $predictor != 15) { 0078 // require_once 'Zend/Pdf/Exception.php'; 0079 throw new Zend_Pdf_Exception('Invalid value of \'Predictor\' decode param - ' . $predictor . '.' ); 0080 } 0081 return $predictor; 0082 } else { 0083 return 1; 0084 } 0085 } 0086 0087 /** 0088 * Get Colors decode param value 0089 * 0090 * @param array $params 0091 * @return integer 0092 * @throws Zend_Pdf_Exception 0093 */ 0094 private static function _getColorsValue(&$params) 0095 { 0096 if (isset($params['Colors'])) { 0097 $colors = $params['Colors']; 0098 0099 if ($colors != 1 && $colors != 2 && $colors != 3 && $colors != 4) { 0100 // require_once 'Zend/Pdf/Exception.php'; 0101 throw new Zend_Pdf_Exception('Invalid value of \'Color\' decode param - ' . $colors . '.' ); 0102 } 0103 return $colors; 0104 } else { 0105 return 1; 0106 } 0107 } 0108 0109 /** 0110 * Get BitsPerComponent decode param value 0111 * 0112 * @param array $params 0113 * @return integer 0114 * @throws Zend_Pdf_Exception 0115 */ 0116 private static function _getBitsPerComponentValue(&$params) 0117 { 0118 if (isset($params['BitsPerComponent'])) { 0119 $bitsPerComponent = $params['BitsPerComponent']; 0120 0121 if ($bitsPerComponent != 1 && $bitsPerComponent != 2 && 0122 $bitsPerComponent != 4 && $bitsPerComponent != 8 && 0123 $bitsPerComponent != 16 ) { 0124 // require_once 'Zend/Pdf/Exception.php'; 0125 throw new Zend_Pdf_Exception('Invalid value of \'BitsPerComponent\' decode param - ' . $bitsPerComponent . '.' ); 0126 } 0127 return $bitsPerComponent; 0128 } else { 0129 return 8; 0130 } 0131 } 0132 0133 /** 0134 * Get Columns decode param value 0135 * 0136 * @param array $params 0137 * @return integer 0138 */ 0139 private static function _getColumnsValue(&$params) 0140 { 0141 if (isset($params['Columns'])) { 0142 return $params['Columns']; 0143 } else { 0144 return 1; 0145 } 0146 } 0147 0148 0149 /** 0150 * Convert stream data according to the filter params set before encoding. 0151 * 0152 * @param string $data 0153 * @param array $params 0154 * @return string 0155 * @throws Zend_Pdf_Exception 0156 */ 0157 protected static function _applyEncodeParams($data, $params) { 0158 $predictor = self::_getPredictorValue($params); 0159 $colors = self::_getColorsValue($params); 0160 $bitsPerComponent = self::_getBitsPerComponentValue($params); 0161 $columns = self::_getColumnsValue($params); 0162 0163 /** None of prediction */ 0164 if ($predictor == 1) { 0165 return $data; 0166 } 0167 0168 /** TIFF Predictor 2 */ 0169 if ($predictor == 2) { 0170 // require_once 'Zend/Pdf/Exception.php'; 0171 throw new Zend_Pdf_Exception('Not implemented yet' ); 0172 } 0173 0174 /** Optimal PNG prediction */ 0175 if ($predictor == 15) { 0176 /** Use Paeth prediction as optimal */ 0177 $predictor = 14; 0178 } 0179 0180 /** PNG prediction */ 0181 if ($predictor == 10 || /** None of prediction */ 0182 $predictor == 11 || /** Sub prediction */ 0183 $predictor == 12 || /** Up prediction */ 0184 $predictor == 13 || /** Average prediction */ 0185 $predictor == 14 /** Paeth prediction */ 0186 ) { 0187 $predictor -= 10; 0188 0189 if($bitsPerComponent == 16) { 0190 // require_once 'Zend/Pdf/Exception.php'; 0191 throw new Zend_Pdf_Exception("PNG Prediction with bit depth greater than 8 not yet supported."); 0192 } 0193 0194 $bitsPerSample = $bitsPerComponent*$colors; 0195 $bytesPerSample = (int)(($bitsPerSample + 7)/8); // (int)ceil(...) emulation 0196 $bytesPerRow = (int)(($bitsPerSample*$columns + 7)/8); // (int)ceil(...) emulation 0197 $rows = strlen($data)/$bytesPerRow; 0198 $output = ''; 0199 $offset = 0; 0200 0201 if (!is_integer($rows)) { 0202 // require_once 'Zend/Pdf/Exception.php'; 0203 throw new Zend_Pdf_Exception('Wrong data length.'); 0204 } 0205 0206 switch ($predictor) { 0207 case 0: // None of prediction 0208 for ($count = 0; $count < $rows; $count++) { 0209 $output .= chr($predictor); 0210 $output .= substr($data, $offset, $bytesPerRow); 0211 $offset += $bytesPerRow; 0212 } 0213 break; 0214 0215 case 1: // Sub prediction 0216 for ($count = 0; $count < $rows; $count++) { 0217 $output .= chr($predictor); 0218 0219 $lastSample = array_fill(0, $bytesPerSample, 0); 0220 for ($count2 = 0; $count2 < $bytesPerRow; $count2++) { 0221 $newByte = ord($data[$offset++]); 0222 // Note. chr() automatically cuts input to 8 bit 0223 $output .= chr($newByte - $lastSample[$count2 % $bytesPerSample]); 0224 $lastSample[$count2 % $bytesPerSample] = $newByte; 0225 } 0226 } 0227 break; 0228 0229 case 2: // Up prediction 0230 $lastRow = array_fill(0, $bytesPerRow, 0); 0231 for ($count = 0; $count < $rows; $count++) { 0232 $output .= chr($predictor); 0233 0234 for ($count2 = 0; $count2 < $bytesPerRow; $count2++) { 0235 $newByte = ord($data[$offset++]); 0236 // Note. chr() automatically cuts input to 8 bit 0237 $output .= chr($newByte - $lastRow[$count2]); 0238 $lastRow[$count2] = $newByte; 0239 } 0240 } 0241 break; 0242 0243 case 3: // Average prediction 0244 $lastRow = array_fill(0, $bytesPerRow, 0); 0245 for ($count = 0; $count < $rows; $count++) { 0246 $output .= chr($predictor); 0247 0248 $lastSample = array_fill(0, $bytesPerSample, 0); 0249 for ($count2 = 0; $count2 < $bytesPerRow; $count2++) { 0250 $newByte = ord($data[$offset++]); 0251 // Note. chr() automatically cuts input to 8 bit 0252 $output .= chr($newByte - floor(( $lastSample[$count2 % $bytesPerSample] + $lastRow[$count2])/2)); 0253 $lastSample[$count2 % $bytesPerSample] = $lastRow[$count2] = $newByte; 0254 } 0255 } 0256 break; 0257 0258 case 4: // Paeth prediction 0259 $lastRow = array_fill(0, $bytesPerRow, 0); 0260 $currentRow = array(); 0261 for ($count = 0; $count < $rows; $count++) { 0262 $output .= chr($predictor); 0263 0264 $lastSample = array_fill(0, $bytesPerSample, 0); 0265 for ($count2 = 0; $count2 < $bytesPerRow; $count2++) { 0266 $newByte = ord($data[$offset++]); 0267 // Note. chr() automatically cuts input to 8 bit 0268 $output .= chr($newByte - self::_paeth( $lastSample[$count2 % $bytesPerSample], 0269 $lastRow[$count2], 0270 ($count2 - $bytesPerSample < 0)? 0271 0 : $lastRow[$count2 - $bytesPerSample] )); 0272 $lastSample[$count2 % $bytesPerSample] = $currentRow[$count2] = $newByte; 0273 } 0274 $lastRow = $currentRow; 0275 } 0276 break; 0277 } 0278 return $output; 0279 } 0280 0281 // require_once 'Zend/Pdf/Exception.php'; 0282 throw new Zend_Pdf_Exception('Unknown prediction algorithm - ' . $predictor . '.' ); 0283 } 0284 0285 /** 0286 * Convert stream data according to the filter params set after decoding. 0287 * 0288 * @param string $data 0289 * @param array $params 0290 * @return string 0291 */ 0292 protected static function _applyDecodeParams($data, $params) { 0293 $predictor = self::_getPredictorValue($params); 0294 $colors = self::_getColorsValue($params); 0295 $bitsPerComponent = self::_getBitsPerComponentValue($params); 0296 $columns = self::_getColumnsValue($params); 0297 0298 /** None of prediction */ 0299 if ($predictor == 1) { 0300 return $data; 0301 } 0302 0303 /** TIFF Predictor 2 */ 0304 if ($predictor == 2) { 0305 // require_once 'Zend/Pdf/Exception.php'; 0306 throw new Zend_Pdf_Exception('Not implemented yet' ); 0307 } 0308 0309 /** 0310 * PNG prediction 0311 * Prediction code is duplicated on each row. 0312 * Thus all cases can be brought to one 0313 */ 0314 if ($predictor == 10 || /** None of prediction */ 0315 $predictor == 11 || /** Sub prediction */ 0316 $predictor == 12 || /** Up prediction */ 0317 $predictor == 13 || /** Average prediction */ 0318 $predictor == 14 || /** Paeth prediction */ 0319 $predictor == 15 /** Optimal prediction */) { 0320 0321 $bitsPerSample = $bitsPerComponent*$colors; 0322 $bytesPerSample = ceil($bitsPerSample/8); 0323 $bytesPerRow = ceil($bitsPerSample*$columns/8); 0324 $rows = ceil(strlen($data)/($bytesPerRow + 1)); 0325 $output = ''; 0326 $offset = 0; 0327 0328 $lastRow = array_fill(0, $bytesPerRow, 0); 0329 for ($count = 0; $count < $rows; $count++) { 0330 $lastSample = array_fill(0, $bytesPerSample, 0); 0331 switch (ord($data[$offset++])) { 0332 case 0: // None of prediction 0333 $output .= substr($data, $offset, $bytesPerRow); 0334 for ($count2 = 0; $count2 < $bytesPerRow && $offset < strlen($data); $count2++) { 0335 $lastSample[$count2 % $bytesPerSample] = $lastRow[$count2] = ord($data[$offset++]); 0336 } 0337 break; 0338 0339 case 1: // Sub prediction 0340 for ($count2 = 0; $count2 < $bytesPerRow && $offset < strlen($data); $count2++) { 0341 $decodedByte = (ord($data[$offset++]) + $lastSample[$count2 % $bytesPerSample]) & 0xFF; 0342 $lastSample[$count2 % $bytesPerSample] = $lastRow[$count2] = $decodedByte; 0343 $output .= chr($decodedByte); 0344 } 0345 break; 0346 0347 case 2: // Up prediction 0348 for ($count2 = 0; $count2 < $bytesPerRow && $offset < strlen($data); $count2++) { 0349 $decodedByte = (ord($data[$offset++]) + $lastRow[$count2]) & 0xFF; 0350 $lastSample[$count2 % $bytesPerSample] = $lastRow[$count2] = $decodedByte; 0351 $output .= chr($decodedByte); 0352 } 0353 break; 0354 0355 case 3: // Average prediction 0356 for ($count2 = 0; $count2 < $bytesPerRow && $offset < strlen($data); $count2++) { 0357 $decodedByte = (ord($data[$offset++]) + 0358 floor(( $lastSample[$count2 % $bytesPerSample] + $lastRow[$count2])/2) 0359 ) & 0xFF; 0360 $lastSample[$count2 % $bytesPerSample] = $lastRow[$count2] = $decodedByte; 0361 $output .= chr($decodedByte); 0362 } 0363 break; 0364 0365 case 4: // Paeth prediction 0366 $currentRow = array(); 0367 for ($count2 = 0; $count2 < $bytesPerRow && $offset < strlen($data); $count2++) { 0368 $decodedByte = (ord($data[$offset++]) + 0369 self::_paeth($lastSample[$count2 % $bytesPerSample], 0370 $lastRow[$count2], 0371 ($count2 - $bytesPerSample < 0)? 0372 0 : $lastRow[$count2 - $bytesPerSample]) 0373 ) & 0xFF; 0374 $lastSample[$count2 % $bytesPerSample] = $currentRow[$count2] = $decodedByte; 0375 $output .= chr($decodedByte); 0376 } 0377 $lastRow = $currentRow; 0378 break; 0379 0380 default: 0381 // require_once 'Zend/Pdf/Exception.php'; 0382 throw new Zend_Pdf_Exception('Unknown prediction tag.'); 0383 } 0384 } 0385 return $output; 0386 } 0387 0388 // require_once 'Zend/Pdf/Exception.php'; 0389 throw new Zend_Pdf_Exception('Unknown prediction algorithm - ' . $predictor . '.' ); 0390 } 0391 }