PageRenderTime 46ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/Zend/Pdf/Filter/Compression.php

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