PageRenderTime 43ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Zend/Pdf/Filter/Compression.php

https://bitbucket.org/baruffaldi/website-2008-computer-shopping-3
PHP | 380 lines | 242 code | 44 blank | 94 comment | 100 complexity | e50b94299c2c5be230499660abcd0c6f MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @package Zend_Pdf
  16. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  17. * @license http://framework.zend.com/license/new-bsd New BSD License
  18. */
  19. /** Zend_Pdf_Filter_Interface */
  20. require_once 'Zend/Pdf/Filter/Interface.php';
  21. /**
  22. * ASCII85 stream filter
  23. *
  24. * @package Zend_Pdf
  25. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  26. * @license http://framework.zend.com/license/new-bsd New BSD License
  27. */
  28. abstract class Zend_Pdf_Filter_Compression implements Zend_Pdf_Filter_Interface
  29. {
  30. /**
  31. * Paeth prediction function
  32. *
  33. * @param integer $a
  34. * @param integer $b
  35. * @param integer $c
  36. * @return integer
  37. */
  38. private static function _paeth($a, $b, $c)
  39. {
  40. // $a - left, $b - above, $c - upper left
  41. $p = $a + $b - $c; // initial estimate
  42. $pa = abs($p - $a); // distances to a, b, c
  43. $pb = abs($p - $b);
  44. $pc = abs($p - $c);
  45. // return nearest of a,b,c,
  46. // breaking ties in order a,b,c.
  47. if ($pa <= $pb && $pa <= $pc) {
  48. return $a;
  49. } else if ($pb <= $pc) {
  50. return $b;
  51. } else {
  52. return $c;
  53. }
  54. }
  55. /**
  56. * Get Predictor decode param value
  57. *
  58. * @param array $params
  59. * @return integer
  60. * @throws Zend_Pdf_Exception
  61. */
  62. private static function _getPredictorValue(&$params)
  63. {
  64. if (isset($params['Predictor'])) {
  65. $predictor = $params['Predictor'];
  66. if ($predictor != 1 && $predictor != 2 &&
  67. $predictor != 10 && $predictor != 11 && $predictor != 12 &&
  68. $predictor != 13 && $predictor != 14 && $predictor != 15) {
  69. throw new Zend_Pdf_Exception('Invalid value of \'Predictor\' decode param - ' . $predictor . '.' );
  70. }
  71. return $predictor;
  72. } else {
  73. return 1;
  74. }
  75. }
  76. /**
  77. * Get Colors decode param value
  78. *
  79. * @param array $params
  80. * @return integer
  81. * @throws Zend_Pdf_Exception
  82. */
  83. private static function _getColorsValue(&$params)
  84. {
  85. if (isset($params['Colors'])) {
  86. $colors = $params['Colors'];
  87. if ($colors != 1 && $colors != 2 && $colors != 3 && $colors != 4) {
  88. throw new Zend_Pdf_Exception('Invalid value of \'Color\' decode param - ' . $colors . '.' );
  89. }
  90. return $colors;
  91. } else {
  92. return 1;
  93. }
  94. }
  95. /**
  96. * Get BitsPerComponent decode param value
  97. *
  98. * @param array $params
  99. * @return integer
  100. * @throws Zend_Pdf_Exception
  101. */
  102. private static function _getBitsPerComponentValue(&$params)
  103. {
  104. if (isset($params['BitsPerComponent'])) {
  105. $bitsPerComponent = $params['BitsPerComponent'];
  106. if ($bitsPerComponent != 1 && $bitsPerComponent != 2 &&
  107. $bitsPerComponent != 4 && $bitsPerComponent != 8 &&
  108. $bitsPerComponent != 16 ) {
  109. throw new Zend_Pdf_Exception('Invalid value of \'BitsPerComponent\' decode param - ' . $bitsPerComponent . '.' );
  110. }
  111. return $bitsPerComponent;
  112. } else {
  113. return 8;
  114. }
  115. }
  116. /**
  117. * Get Columns decode param value
  118. *
  119. * @param array $params
  120. * @return integer
  121. */
  122. private static function _getColumnsValue(&$params)
  123. {
  124. if (isset($params['Columns'])) {
  125. return $params['Columns'];
  126. } else {
  127. return 1;
  128. }
  129. }
  130. /**
  131. * Convert stream data according to the filter params set before encoding.
  132. *
  133. * @param string $data
  134. * @param array $params
  135. * @return string
  136. * @throws Zend_Pdf_Exception
  137. */
  138. protected static function _applyEncodeParams($data, $params) {
  139. $predictor = self::_getPredictorValue($params);
  140. $colors = self::_getColorsValue($params);
  141. $bitsPerComponent = self::_getBitsPerComponentValue($params);
  142. $columns = self::_getColumnsValue($params);
  143. /** None of prediction */
  144. if ($predictor == 1) {
  145. return $data;
  146. }
  147. /** TIFF Predictor 2 */
  148. if ($predictor == 2) {
  149. throw new Zend_Pdf_Exception('Not implemented yet' );
  150. }
  151. /** Optimal PNG prediction */
  152. if ($predictor == 15) {
  153. /** Use Paeth prediction as optimal */
  154. $predictor = 14;
  155. }
  156. /** PNG prediction */
  157. if ($predictor == 10 || /** None of prediction */
  158. $predictor == 11 || /** Sub prediction */
  159. $predictor == 12 || /** Up prediction */
  160. $predictor == 13 || /** Average prediction */
  161. $predictor == 14 /** Paeth prediction */
  162. ) {
  163. $predictor -= 10;
  164. if($bitsPerComponent == 16) {
  165. throw new Zend_Pdf_Exception("PNG Prediction with bit depth greater than 8 not yet supported.");
  166. }
  167. $bitsPerSample = $bitsPerComponent*$colors;
  168. $bytesPerSample = (int)(($bitsPerSample + 7)/8); // (int)ceil(...) emulation
  169. $bytesPerRow = (int)(($bitsPerSample*$columns + 7)/8); // (int)ceil(...) emulation
  170. $rows = strlen($data)/$bytesPerRow;
  171. $output = '';
  172. $offset = 0;
  173. if (!is_integer($rows)) {
  174. throw new Zend_Pdf_Exception('Wrong data length.');
  175. }
  176. switch ($predictor) {
  177. case 0: // None of prediction
  178. for ($count = 0; $count < $rows; $count++) {
  179. $output .= chr($predictor);
  180. $output .= substr($data, $offset, $bytesPerRow);
  181. $offset += $bytesPerRow;
  182. }
  183. break;
  184. case 1: // Sub prediction
  185. for ($count = 0; $count < $rows; $count++) {
  186. $output .= chr($predictor);
  187. $lastSample = array_fill(0, $bytesPerSample, 0);
  188. for ($count2 = 0; $count2 < $bytesPerRow; $count2++) {
  189. $newByte = ord($data[$offset++]);
  190. // Note. chr() automatically cuts input to 8 bit
  191. $output .= chr($newByte - $lastSample[$count2 % $bytesPerSample]);
  192. $lastSample[$count2 % $bytesPerSample] = $newByte;
  193. }
  194. }
  195. break;
  196. case 2: // Up prediction
  197. $lastRow = array_fill(0, $bytesPerRow, 0);
  198. for ($count = 0; $count < $rows; $count++) {
  199. $output .= chr($predictor);
  200. for ($count2 = 0; $count2 < $bytesPerRow; $count2++) {
  201. $newByte = ord($data[$offset++]);
  202. // Note. chr() automatically cuts input to 8 bit
  203. $output .= chr($newByte - $lastRow[$count2]);
  204. $lastRow[$count2] = $newByte;
  205. }
  206. }
  207. break;
  208. case 3: // Average prediction
  209. $lastRow = array_fill(0, $bytesPerRow, 0);
  210. for ($count = 0; $count < $rows; $count++) {
  211. $output .= chr($predictor);
  212. $lastSample = array_fill(0, $bytesPerSample, 0);
  213. for ($count2 = 0; $count2 < $bytesPerRow; $count2++) {
  214. $newByte = ord($data[$offset++]);
  215. // Note. chr() automatically cuts input to 8 bit
  216. $output .= chr($newByte - floor(( $lastSample[$count2 % $bytesPerSample] + $lastRow[$count2])/2));
  217. $lastSample[$count2 % $bytesPerSample] = $lastRow[$count2] = $newByte;
  218. }
  219. }
  220. break;
  221. case 4: // Paeth prediction
  222. $lastRow = array_fill(0, $bytesPerRow, 0);
  223. $currentRow = array();
  224. for ($count = 0; $count < $rows; $count++) {
  225. $output .= chr($predictor);
  226. $lastSample = array_fill(0, $bytesPerSample, 0);
  227. for ($count2 = 0; $count2 < $bytesPerRow; $count2++) {
  228. $newByte = ord($data[$offset++]);
  229. // Note. chr() automatically cuts input to 8 bit
  230. $output .= chr($newByte - self::_paeth( $lastSample[$count2 % $bytesPerSample],
  231. $lastRow[$count2],
  232. ($count2 - $bytesPerSample < 0)?
  233. 0 : $lastRow[$count2 - $bytesPerSample] ));
  234. $lastSample[$count2 % $bytesPerSample] = $currentRow[$count2] = $newByte;
  235. }
  236. $lastRow = $currentRow;
  237. }
  238. break;
  239. }
  240. return $output;
  241. }
  242. throw new Zend_Pdf_Exception('Unknown prediction algorithm - ' . $predictor . '.' );
  243. }
  244. /**
  245. * Convert stream data according to the filter params set after decoding.
  246. *
  247. * @param string $data
  248. * @param array $params
  249. * @return string
  250. */
  251. protected static function _applyDecodeParams($data, $params) {
  252. $predictor = self::_getPredictorValue($params);
  253. $colors = self::_getColorsValue($params);
  254. $bitsPerComponent = self::_getBitsPerComponentValue($params);
  255. $columns = self::_getColumnsValue($params);
  256. /** None of prediction */
  257. if ($predictor == 1) {
  258. return $data;
  259. }
  260. /** TIFF Predictor 2 */
  261. if ($predictor == 2) {
  262. throw new Zend_Pdf_Exception('Not implemented yet' );
  263. }
  264. /**
  265. * PNG prediction
  266. * Prediction code is duplicated on each row.
  267. * Thus all cases can be brought to one
  268. */
  269. if ($predictor == 10 || /** None of prediction */
  270. $predictor == 11 || /** Sub prediction */
  271. $predictor == 12 || /** Up prediction */
  272. $predictor == 13 || /** Average prediction */
  273. $predictor == 14 || /** Paeth prediction */
  274. $predictor == 15 /** Optimal prediction */) {
  275. $bitsPerSample = $bitsPerComponent*$colors;
  276. $bytesPerSample = ceil($bitsPerSample/8);
  277. $bytesPerRow = ceil($bitsPerSample*$columns/8);
  278. $rows = ceil(strlen($data)/($bytesPerRow + 1));
  279. $output = '';
  280. $offset = 0;
  281. $lastRow = array_fill(0, $bytesPerRow, 0);
  282. for ($count = 0; $count < $rows; $count++) {
  283. $lastSample = array_fill(0, $bytesPerSample, 0);
  284. switch (ord($data[$offset++])) {
  285. case 0: // None of prediction
  286. $output .= substr($data, $offset, $bytesPerRow);
  287. for ($count2 = 0; $count2 < $bytesPerRow && $offset < strlen($data); $count2++) {
  288. $lastSample[$count2 % $bytesPerSample] = $lastRow[$count2] = ord($data[$offset++]);
  289. }
  290. break;
  291. case 1: // Sub prediction
  292. for ($count2 = 0; $count2 < $bytesPerRow && $offset < strlen($data); $count2++) {
  293. $decodedByte = (ord($data[$offset++]) + $lastSample[$count2 % $bytesPerSample]) & 0xFF;
  294. $lastSample[$count2 % $bytesPerSample] = $lastRow[$count2] = $decodedByte;
  295. $output .= chr($decodedByte);
  296. }
  297. break;
  298. case 2: // Up prediction
  299. for ($count2 = 0; $count2 < $bytesPerRow && $offset < strlen($data); $count2++) {
  300. $decodedByte = (ord($data[$offset++]) + $lastRow[$count2]) & 0xFF;
  301. $lastSample[$count2 % $bytesPerSample] = $lastRow[$count2] = $decodedByte;
  302. $output .= chr($decodedByte);
  303. }
  304. break;
  305. case 3: // Average prediction
  306. for ($count2 = 0; $count2 < $bytesPerRow && $offset < strlen($data); $count2++) {
  307. $decodedByte = (ord($data[$offset++]) +
  308. floor(( $lastSample[$count2 % $bytesPerSample] + $lastRow[$count2])/2)
  309. ) & 0xFF;
  310. $lastSample[$count2 % $bytesPerSample] = $lastRow[$count2] = $decodedByte;
  311. $output .= chr($decodedByte);
  312. }
  313. break;
  314. case 4: // Paeth prediction
  315. $currentRow = array();
  316. for ($count2 = 0; $count2 < $bytesPerRow && $offset < strlen($data); $count2++) {
  317. $decodedByte = (ord($data[$offset++]) +
  318. self::_paeth($lastSample[$count2 % $bytesPerSample],
  319. $lastRow[$count2],
  320. ($count2 - $bytesPerSample < 0)?
  321. 0 : $lastRow[$count2 - $bytesPerSample])
  322. ) & 0xFF;
  323. $lastSample[$count2 % $bytesPerSample] = $currentRow[$count2] = $decodedByte;
  324. $output .= chr($decodedByte);
  325. }
  326. $lastRow = $currentRow;
  327. break;
  328. default:
  329. throw new Zend_Pdf_Exception('Unknown prediction tag.');
  330. }
  331. }
  332. return $output;
  333. }
  334. throw new Zend_Pdf_Exception('Unknown prediction algorithm - ' . $predictor . '.' );
  335. }
  336. }