Source for file PelConvert.php

Documentation is available at PelConvert.php

  1. <?php
  2.  
  3. /* PEL: PHP EXIF Library. A library with support for reading and
  4. * writing all EXIF headers in JPEG and TIFF images using PHP.
  5. *
  6. * Copyright (C) 2004 Martin Geisler.
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program in the file COPYING; if not, write to the
  20. * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  21. * Boston, MA 02111-1307 USA
  22. */
  23.  
  24. /* PelConvert.php,v 1.16 2005/02/10 21:22:24 gimpster Exp */
  25.  
  26.  
  27. /**
  28. * Routines for converting back and forth between bytes and integers.
  29. *
  30. * @author Martin Geisler <gimpster@users.sourceforge.net>
  31. * @version 1.16
  32. * @date 2005/02/10 21:22:24
  33. * @license http://www.gnu.org/licenses/gpl.html GNU General Public
  34. * License (GPL)
  35. * @package PEL
  36. */
  37.  
  38. /**
  39. * Conversion functions to and from bytes and integers.
  40. *
  41. * The functions found in this class are used to convert bytes into
  42. * integers of several sizes ({@link bytesToShort}, {@link }
  43. * bytesToLong}, and {@link bytesToRational}) and convert integers of
  44. * several sizes into bytes ({@link shortToBytes} and {@link }
  45. * longToBytes}).
  46. *
  47. * All the methods are static and they all rely on an argument that
  48. * specifies the byte order to be used, this must be one of the class
  49. * constants {@link LITTLE_ENDIAN} or {@link BIG_ENDIAN}. These
  50. * constants will be referred to as the pseudo type PelByteOrder
  51. * throughout the documentation.
  52. *
  53. * @author Martin Geisler <gimpster@users.sourceforge.net>
  54. * @package PEL
  55. */
  56. class PelConvert {
  57.  
  58. /**
  59. * Little-endian (Intel) byte order.
  60. *
  61. * Data stored in little-endian byte order store the least
  62. * significant byte first, so the number 0x12345678 becomes 0x78
  63. * 0x56 0x34 0x12 when stored with little-endian byte order.
  64. */
  65. const LITTLE_ENDIAN = true;
  66.  
  67. /**
  68. * Big-endian (Motorola) byte order.
  69. *
  70. * Data stored in big-endian byte order store the most significant
  71. * byte first, so the number 0x12345678 becomes 0x12 0x34 0x56 0x78
  72. * when stored with big-endian byte order.
  73. */
  74. const BIG_ENDIAN = false;
  75.  
  76.  
  77. /**
  78. * Convert an unsigned short into two bytes.
  79. *
  80. * @param int the unsigned short that will be converted. The lower
  81. * two bytes will be extracted regardless of the actual size passed.
  82. *
  83. * @param PelByteOrder one of {@link LITTLE_ENDIAN} and {@link }
  84. * BIG_ENDIAN}.
  85. *
  86. * @return string the bytes representing the unsigned short.
  87. */
  88. static function shortToBytes($value, $endian) {
  89. if ($endian == self::LITTLE_ENDIAN)
  90. return chr($value) . chr($value >> 8);
  91. else
  92. return chr($value >> 8) . chr($value);
  93. }
  94.  
  95.  
  96. /**
  97. * Convert a signed short into two bytes.
  98. *
  99. * @param int the signed short that will be converted. The lower
  100. * two bytes will be extracted regardless of the actual size passed.
  101. *
  102. * @param PelByteOrder one of {@link LITTLE_ENDIAN} and {@link }
  103. * BIG_ENDIAN}.
  104. *
  105. * @return string the bytes representing the signed short.
  106. */
  107. static function sShortToBytes($value, $endian) {
  108. /* We can just use shortToBytes, since signed shorts fits well
  109. * within the 32 bit signed integers used in PHP. */
  110. return self::shortToBytes($value, $endian);
  111. }
  112.  
  113. /**
  114. * Convert an unsigned long into four bytes.
  115. *
  116. * Because PHP limits the size of integers to 32 bit signed, one
  117. * cannot really have an unsigned integer in PHP. But integers
  118. * larger than 2^31-1 will be promoted to 64 bit signed floating
  119. * point numbers, and so such large numbers can be handled too.
  120. *
  121. * @param int the unsigned long that will be converted. The
  122. * argument will be treated as an unsigned 32 bit integer and the
  123. * lower four bytes will be extracted. Treating the argument as an
  124. * unsigned integer means that the absolute value will be used. Use
  125. * {@link sLongToBytes} to convert signed integers.
  126. *
  127. * @param PelByteOrder one of {@link LITTLE_ENDIAN} and {@link }
  128. * BIG_ENDIAN}.
  129. *
  130. * @return string the bytes representing the unsigned long.
  131. */
  132. static function longToBytes($value, $endian) {
  133. /* We cannot convert the number to bytes in the normal way (using
  134. * shifts and modulo calculations) because the PHP operator >> and
  135. * function chr() clip their arguments to 2^31-1, which is the
  136. * largest signed integer known to PHP. But luckily base_convert
  137. * handles such big numbers. */
  138. $hex = str_pad(base_convert($value, 10, 16), 8, '0', STR_PAD_LEFT);
  139. if ($endian == self::LITTLE_ENDIAN)
  140. return (chr(hexdec($hex{6} . $hex{7})) .
  141. chr(hexdec($hex{4} . $hex{5})) .
  142. chr(hexdec($hex{2} . $hex{3})) .
  143. chr(hexdec($hex{0} . $hex{1})));
  144. else
  145. return (chr(hexdec($hex{0} . $hex{1})) .
  146. chr(hexdec($hex{2} . $hex{3})) .
  147. chr(hexdec($hex{4} . $hex{5})) .
  148. chr(hexdec($hex{6} . $hex{7})));
  149. }
  150.  
  151.  
  152. /**
  153. * Convert a signed long into four bytes.
  154. *
  155. * @param int the signed long that will be converted. The argument
  156. * will be treated as a signed 32 bit integer, from which the lower
  157. * four bytes will be extracted.
  158. *
  159. * @param PelByteOrder one of {@link LITTLE_ENDIAN} and {@link }
  160. * BIG_ENDIAN}.
  161. *
  162. * @return string the bytes representing the signed long.
  163. */
  164. static function sLongToBytes($value, $endian) {
  165. /* We can convert the number into bytes in the normal way using
  166. * shifts and modulo calculations here (in contrast with
  167. * longToBytes) because PHP automatically handles 32 bit signed
  168. * integers for us. */
  169. if ($endian == self::LITTLE_ENDIAN)
  170. return (chr($value) .
  171. chr($value >> 8) .
  172. chr($value >> 16) .
  173. chr($value >> 24));
  174. else
  175. return (chr($value >> 24) .
  176. chr($value >> 16) .
  177. chr($value >> 8) .
  178. chr($value));
  179. }
  180.  
  181.  
  182. /**
  183. * Extract an unsigned byte from a string of bytes.
  184. *
  185. * @param string the bytes.
  186. *
  187. * @param int the offset. The byte found at the offset will be
  188. * returned as an integer. The must be at least one byte available
  189. * at offset.
  190. *
  191. * @return int the unsigned byte found at offset, e.g., an integer
  192. * in the range 0 to 255.
  193. */
  194. static function bytesToByte(&$bytes, $offset) {
  195. return ord($bytes{$offset});
  196. }
  197.  
  198.  
  199. /**
  200. * Extract a signed byte from bytes.
  201. *
  202. * @param string the bytes.
  203. *
  204. * @param int the offset. The byte found at the offset will be
  205. * returned as an integer. The must be at least one byte available
  206. * at offset.
  207. *
  208. * @return int the signed byte found at offset, e.g., an integer in
  209. * the range -128 to 127.
  210. */
  211. static function bytesToSByte(&$bytes, $offset) {
  212. $n = self::bytesToByte($bytes, $offset);
  213. if ($n > 127)
  214. return $n - 256;
  215. else
  216. return $n;
  217. }
  218.  
  219.  
  220. /**
  221. * Extract an unsigned short from bytes.
  222. *
  223. * @param string the bytes.
  224. *
  225. * @param int the offset. The short found at the offset will be
  226. * returned as an integer. There must be at least two bytes
  227. * available beginning at the offset given.
  228. *
  229. * @return int the unsigned short found at offset, e.g., an integer
  230. * in the range 0 to 65535.
  231. *
  232. * @param PelByteOrder one of {@link LITTLE_ENDIAN} and {@link }
  233. * BIG_ENDIAN}.
  234. */
  235. static function bytesToShort(&$bytes, $offset, $endian) {
  236. if ($endian == self::LITTLE_ENDIAN)
  237. return (ord($bytes{$offset+1}) << 8 |
  238. ord($bytes{$offset}));
  239. else
  240. return (ord($bytes{$offset}) << 8 |
  241. ord($bytes{$offset+1}));
  242. }
  243.  
  244.  
  245. /**
  246. * Extract a signed short from bytes.
  247. *
  248. * @param string the bytes.
  249. *
  250. * @param int the offset. The short found at offset will be returned
  251. * as an integer. There must be at least two bytes available
  252. * beginning at the offset given.
  253. *
  254. * @return int the signed byte found at offset, e.g., an integer in
  255. * the range -32768 to 32767.
  256. *
  257. * @param PelByteOrder one of {@link LITTLE_ENDIAN} and {@link }
  258. * BIG_ENDIAN}.
  259. */
  260. static function bytesToSShort(&$bytes, $offset, $endian) {
  261. $n = self::bytesToShort($bytes, $offset, $endian);
  262. if ($n > 32767)
  263. return $n - 65536;
  264. else
  265. return $n;
  266. }
  267.  
  268.  
  269. /**
  270. * Extract an unsigned long from bytes.
  271. *
  272. * @param string the bytes.
  273. *
  274. * @param int the offset. The long found at offset will be returned
  275. * as an integer. There must be at least four bytes available
  276. * beginning at the offset given.
  277. *
  278. * @return int the unsigned long found at offset, e.g., an integer
  279. * in the range 0 to 4294967295.
  280. *
  281. * @param PelByteOrder one of {@link LITTLE_ENDIAN} and {@link }
  282. * BIG_ENDIAN}.
  283. */
  284. static function bytesToLong(&$bytes, $offset, $endian) {
  285. if ($endian == self::LITTLE_ENDIAN)
  286. return (ord($bytes{$offset+3}) * 16777216 +
  287. ord($bytes{$offset+2}) * 65536 +
  288. ord($bytes{$offset+1}) * 256 +
  289. ord($bytes{$offset}));
  290. else
  291. return (ord($bytes{$offset}) * 16777216 +
  292. ord($bytes{$offset+1}) * 65536 +
  293. ord($bytes{$offset+2}) * 256 +
  294. ord($bytes{$offset+3}));
  295. }
  296.  
  297.  
  298. /**
  299. * Extract a signed long from bytes.
  300. *
  301. * @param string the bytes.
  302. *
  303. * @param int the offset. The long found at offset will be returned
  304. * as an integer. There must be at least four bytes available
  305. * beginning at the offset given.
  306. *
  307. * @return int the signed long found at offset, e.g., an integer in
  308. * the range -2147483648 to 2147483647.
  309. *
  310. * @param PelByteOrder one of {@link LITTLE_ENDIAN} and {@link }
  311. * BIG_ENDIAN}.
  312. */
  313. static function bytesToSLong(&$bytes, $offset, $endian) {
  314. $n = self::bytesToLong($bytes, $offset, $endian);
  315. if ($n > 2147483647)
  316. return $n - 4294967296;
  317. else
  318. return $n;
  319. }
  320.  
  321.  
  322. /**
  323. * Extract an unsigned rational from bytes.
  324. *
  325. * @param string the bytes.
  326. *
  327. * @param int the offset. The rational found at offset will be
  328. * returned as an array. There must be at least eight bytes
  329. * available beginning at the offset given.
  330. *
  331. * @return array the unsigned rational found at offset, e.g., an
  332. * array with two integers in the range 0 to 4294967295.
  333. *
  334. * @param PelByteOrder one of {@link LITTLE_ENDIAN} and {@link }
  335. * BIG_ENDIAN}.
  336. */
  337. static function bytesToRational(&$bytes, $offset, $endian) {
  338. return array(self::bytesToLong($bytes, $offset, $endian),
  339. self::bytesToLong($bytes, $offset+4, $endian));
  340. }
  341.  
  342.  
  343. /**
  344. * Extract a signed rational from bytes.
  345. *
  346. * @param string the bytes.
  347. *
  348. * @param int the offset. The rational found at offset will be
  349. * returned as an array. There must be at least eight bytes
  350. * available beginning at the offset given.
  351. *
  352. * @return array the signed rational found at offset, e.g., an array
  353. * with two integers in the range -2147483648 to 2147483647.
  354. *
  355. * @param PelByteOrder one of {@link LITTLE_ENDIAN} and {@link }
  356. * BIG_ENDIAN}.
  357. */
  358. static function bytesToSRational(&$bytes, $offset, $endian) {
  359. return array(self::bytesToSLong($bytes, $offset, $endian),
  360. self::bytesToSLong($bytes, $offset+4, $endian));
  361. }
  362.  
  363.  
  364. /**
  365. * Format bytes for dumping.
  366. *
  367. * This method is for debug output, it will format a string as a
  368. * hexadecimal dump suitable for display on a terminal. The output
  369. * is printed directly to standard out.
  370. *
  371. * @param string the bytes that will be dumped.
  372. *
  373. * @param int the maximum number of bytes to dump. If this is left
  374. * out (or left to the default of 0), then the entire string will be
  375. * dumped.
  376. */
  377. static function bytesToDump($bytes, $max = 0) {
  378. $s = strlen($bytes);
  379.  
  380. if ($max > 0)
  381. $s = min($max, $s);
  382.  
  383. $line = 24;
  384.  
  385. for ($i = 0; $i < $s; $i++) {
  386. printf('%02X ', ord($bytes{$i}));
  387. if (($i+1) % $line == 0)
  388. print("\n");
  389. }
  390. print("\n");
  391. }
  392.  
  393. }
  394.  
  395. ?>

SourceForge.net Logo Documentation generated on Fri, 18 Feb 2005 01:43:10 +0100 by phpDocumentor 1.3.0RC3