ccitt.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. #!/usr/bin/env python
  2. # CCITT Fax decoder
  3. #
  4. # Bugs: uncompressed mode untested.
  5. #
  6. # cf.
  7. # ITU-T Recommendation T.4
  8. # "Standardization of Group 3 facsimile terminals for document transmission"
  9. # ITU-T Recommendation T.6
  10. # "FACSIMILE CODING SCHEMES AND CODING CONTROL FUNCTIONS FOR GROUP 4 FACSIMILE APPARATUS"
  11. import sys
  12. import array
  13. ## BitParser
  14. ##
  15. class BitParser(object):
  16. def __init__(self):
  17. self._pos = 0
  18. return
  19. @classmethod
  20. def add(klass, root, v, bits):
  21. p = root
  22. b = None
  23. for i in xrange(len(bits)):
  24. if 0 < i:
  25. if p[b] is None:
  26. p[b] = [None, None]
  27. p = p[b]
  28. if bits[i] == '1':
  29. b = 1
  30. else:
  31. b = 0
  32. p[b] = v
  33. return
  34. def feedbytes(self, data):
  35. for c in data:
  36. b = ord(c)
  37. for m in (128, 64, 32, 16, 8, 4, 2, 1):
  38. self._parse_bit(b & m)
  39. return
  40. def _parse_bit(self, x):
  41. if x:
  42. v = self._state[1]
  43. else:
  44. v = self._state[0]
  45. self._pos += 1
  46. if isinstance(v, list):
  47. self._state = v
  48. else:
  49. self._state = self._accept(v)
  50. return
  51. ## CCITTG4Parser
  52. ##
  53. class CCITTG4Parser(BitParser):
  54. MODE = [None, None]
  55. BitParser.add(MODE, 0, '1')
  56. BitParser.add(MODE, +1, '011')
  57. BitParser.add(MODE, -1, '010')
  58. BitParser.add(MODE, 'h', '001')
  59. BitParser.add(MODE, 'p', '0001')
  60. BitParser.add(MODE, +2, '000011')
  61. BitParser.add(MODE, -2, '000010')
  62. BitParser.add(MODE, +3, '0000011')
  63. BitParser.add(MODE, -3, '0000010')
  64. BitParser.add(MODE, 'u', '0000001111')
  65. BitParser.add(MODE, 'x1', '0000001000')
  66. BitParser.add(MODE, 'x2', '0000001001')
  67. BitParser.add(MODE, 'x3', '0000001010')
  68. BitParser.add(MODE, 'x4', '0000001011')
  69. BitParser.add(MODE, 'x5', '0000001100')
  70. BitParser.add(MODE, 'x6', '0000001101')
  71. BitParser.add(MODE, 'x7', '0000001110')
  72. BitParser.add(MODE, 'e', '000000000001000000000001')
  73. WHITE = [None, None]
  74. BitParser.add(WHITE, 0 , '00110101')
  75. BitParser.add(WHITE, 1 , '000111')
  76. BitParser.add(WHITE, 2 , '0111')
  77. BitParser.add(WHITE, 3 , '1000')
  78. BitParser.add(WHITE, 4 , '1011')
  79. BitParser.add(WHITE, 5 , '1100')
  80. BitParser.add(WHITE, 6 , '1110')
  81. BitParser.add(WHITE, 7 , '1111')
  82. BitParser.add(WHITE, 8 , '10011')
  83. BitParser.add(WHITE, 9 , '10100')
  84. BitParser.add(WHITE, 10 , '00111')
  85. BitParser.add(WHITE, 11 , '01000')
  86. BitParser.add(WHITE, 12 , '001000')
  87. BitParser.add(WHITE, 13 , '000011')
  88. BitParser.add(WHITE, 14 , '110100')
  89. BitParser.add(WHITE, 15 , '110101')
  90. BitParser.add(WHITE, 16 , '101010')
  91. BitParser.add(WHITE, 17 , '101011')
  92. BitParser.add(WHITE, 18 , '0100111')
  93. BitParser.add(WHITE, 19 , '0001100')
  94. BitParser.add(WHITE, 20 , '0001000')
  95. BitParser.add(WHITE, 21 , '0010111')
  96. BitParser.add(WHITE, 22 , '0000011')
  97. BitParser.add(WHITE, 23 , '0000100')
  98. BitParser.add(WHITE, 24 , '0101000')
  99. BitParser.add(WHITE, 25 , '0101011')
  100. BitParser.add(WHITE, 26 , '0010011')
  101. BitParser.add(WHITE, 27 , '0100100')
  102. BitParser.add(WHITE, 28 , '0011000')
  103. BitParser.add(WHITE, 29 , '00000010')
  104. BitParser.add(WHITE, 30 , '00000011')
  105. BitParser.add(WHITE, 31 , '00011010')
  106. BitParser.add(WHITE, 32 , '00011011')
  107. BitParser.add(WHITE, 33 , '00010010')
  108. BitParser.add(WHITE, 34 , '00010011')
  109. BitParser.add(WHITE, 35 , '00010100')
  110. BitParser.add(WHITE, 36 , '00010101')
  111. BitParser.add(WHITE, 37 , '00010110')
  112. BitParser.add(WHITE, 38 , '00010111')
  113. BitParser.add(WHITE, 39 , '00101000')
  114. BitParser.add(WHITE, 40 , '00101001')
  115. BitParser.add(WHITE, 41 , '00101010')
  116. BitParser.add(WHITE, 42 , '00101011')
  117. BitParser.add(WHITE, 43 , '00101100')
  118. BitParser.add(WHITE, 44 , '00101101')
  119. BitParser.add(WHITE, 45 , '00000100')
  120. BitParser.add(WHITE, 46 , '00000101')
  121. BitParser.add(WHITE, 47 , '00001010')
  122. BitParser.add(WHITE, 48 , '00001011')
  123. BitParser.add(WHITE, 49 , '01010010')
  124. BitParser.add(WHITE, 50 , '01010011')
  125. BitParser.add(WHITE, 51 , '01010100')
  126. BitParser.add(WHITE, 52 , '01010101')
  127. BitParser.add(WHITE, 53 , '00100100')
  128. BitParser.add(WHITE, 54 , '00100101')
  129. BitParser.add(WHITE, 55 , '01011000')
  130. BitParser.add(WHITE, 56 , '01011001')
  131. BitParser.add(WHITE, 57 , '01011010')
  132. BitParser.add(WHITE, 58 , '01011011')
  133. BitParser.add(WHITE, 59 , '01001010')
  134. BitParser.add(WHITE, 60 , '01001011')
  135. BitParser.add(WHITE, 61 , '00110010')
  136. BitParser.add(WHITE, 62 , '00110011')
  137. BitParser.add(WHITE, 63 , '00110100')
  138. BitParser.add(WHITE, 64 , '11011')
  139. BitParser.add(WHITE, 128 , '10010')
  140. BitParser.add(WHITE, 192 , '010111')
  141. BitParser.add(WHITE, 256 , '0110111')
  142. BitParser.add(WHITE, 320 , '00110110')
  143. BitParser.add(WHITE, 384 , '00110111')
  144. BitParser.add(WHITE, 448 , '01100100')
  145. BitParser.add(WHITE, 512 , '01100101')
  146. BitParser.add(WHITE, 576 , '01101000')
  147. BitParser.add(WHITE, 640 , '01100111')
  148. BitParser.add(WHITE, 704 , '011001100')
  149. BitParser.add(WHITE, 768 , '011001101')
  150. BitParser.add(WHITE, 832 , '011010010')
  151. BitParser.add(WHITE, 896 , '011010011')
  152. BitParser.add(WHITE, 960 , '011010100')
  153. BitParser.add(WHITE, 1024, '011010101')
  154. BitParser.add(WHITE, 1088, '011010110')
  155. BitParser.add(WHITE, 1152, '011010111')
  156. BitParser.add(WHITE, 1216, '011011000')
  157. BitParser.add(WHITE, 1280, '011011001')
  158. BitParser.add(WHITE, 1344, '011011010')
  159. BitParser.add(WHITE, 1408, '011011011')
  160. BitParser.add(WHITE, 1472, '010011000')
  161. BitParser.add(WHITE, 1536, '010011001')
  162. BitParser.add(WHITE, 1600, '010011010')
  163. BitParser.add(WHITE, 1664, '011000')
  164. BitParser.add(WHITE, 1728, '010011011')
  165. BitParser.add(WHITE, 1792, '00000001000')
  166. BitParser.add(WHITE, 1856, '00000001100')
  167. BitParser.add(WHITE, 1920, '00000001101')
  168. BitParser.add(WHITE, 1984, '000000010010')
  169. BitParser.add(WHITE, 2048, '000000010011')
  170. BitParser.add(WHITE, 2112, '000000010100')
  171. BitParser.add(WHITE, 2176, '000000010101')
  172. BitParser.add(WHITE, 2240, '000000010110')
  173. BitParser.add(WHITE, 2304, '000000010111')
  174. BitParser.add(WHITE, 2368, '000000011100')
  175. BitParser.add(WHITE, 2432, '000000011101')
  176. BitParser.add(WHITE, 2496, '000000011110')
  177. BitParser.add(WHITE, 2560, '000000011111')
  178. BLACK = [None, None]
  179. BitParser.add(BLACK, 0 , '0000110111')
  180. BitParser.add(BLACK, 1 , '010')
  181. BitParser.add(BLACK, 2 , '11')
  182. BitParser.add(BLACK, 3 , '10')
  183. BitParser.add(BLACK, 4 , '011')
  184. BitParser.add(BLACK, 5 , '0011')
  185. BitParser.add(BLACK, 6 , '0010')
  186. BitParser.add(BLACK, 7 , '00011')
  187. BitParser.add(BLACK, 8 , '000101')
  188. BitParser.add(BLACK, 9 , '000100')
  189. BitParser.add(BLACK, 10 , '0000100')
  190. BitParser.add(BLACK, 11 , '0000101')
  191. BitParser.add(BLACK, 12 , '0000111')
  192. BitParser.add(BLACK, 13 , '00000100')
  193. BitParser.add(BLACK, 14 , '00000111')
  194. BitParser.add(BLACK, 15 , '000011000')
  195. BitParser.add(BLACK, 16 , '0000010111')
  196. BitParser.add(BLACK, 17 , '0000011000')
  197. BitParser.add(BLACK, 18 , '0000001000')
  198. BitParser.add(BLACK, 19 , '00001100111')
  199. BitParser.add(BLACK, 20 , '00001101000')
  200. BitParser.add(BLACK, 21 , '00001101100')
  201. BitParser.add(BLACK, 22 , '00000110111')
  202. BitParser.add(BLACK, 23 , '00000101000')
  203. BitParser.add(BLACK, 24 , '00000010111')
  204. BitParser.add(BLACK, 25 , '00000011000')
  205. BitParser.add(BLACK, 26 , '000011001010')
  206. BitParser.add(BLACK, 27 , '000011001011')
  207. BitParser.add(BLACK, 28 , '000011001100')
  208. BitParser.add(BLACK, 29 , '000011001101')
  209. BitParser.add(BLACK, 30 , '000001101000')
  210. BitParser.add(BLACK, 31 , '000001101001')
  211. BitParser.add(BLACK, 32 , '000001101010')
  212. BitParser.add(BLACK, 33 , '000001101011')
  213. BitParser.add(BLACK, 34 , '000011010010')
  214. BitParser.add(BLACK, 35 , '000011010011')
  215. BitParser.add(BLACK, 36 , '000011010100')
  216. BitParser.add(BLACK, 37 , '000011010101')
  217. BitParser.add(BLACK, 38 , '000011010110')
  218. BitParser.add(BLACK, 39 , '000011010111')
  219. BitParser.add(BLACK, 40 , '000001101100')
  220. BitParser.add(BLACK, 41 , '000001101101')
  221. BitParser.add(BLACK, 42 , '000011011010')
  222. BitParser.add(BLACK, 43 , '000011011011')
  223. BitParser.add(BLACK, 44 , '000001010100')
  224. BitParser.add(BLACK, 45 , '000001010101')
  225. BitParser.add(BLACK, 46 , '000001010110')
  226. BitParser.add(BLACK, 47 , '000001010111')
  227. BitParser.add(BLACK, 48 , '000001100100')
  228. BitParser.add(BLACK, 49 , '000001100101')
  229. BitParser.add(BLACK, 50 , '000001010010')
  230. BitParser.add(BLACK, 51 , '000001010011')
  231. BitParser.add(BLACK, 52 , '000000100100')
  232. BitParser.add(BLACK, 53 , '000000110111')
  233. BitParser.add(BLACK, 54 , '000000111000')
  234. BitParser.add(BLACK, 55 , '000000100111')
  235. BitParser.add(BLACK, 56 , '000000101000')
  236. BitParser.add(BLACK, 57 , '000001011000')
  237. BitParser.add(BLACK, 58 , '000001011001')
  238. BitParser.add(BLACK, 59 , '000000101011')
  239. BitParser.add(BLACK, 60 , '000000101100')
  240. BitParser.add(BLACK, 61 , '000001011010')
  241. BitParser.add(BLACK, 62 , '000001100110')
  242. BitParser.add(BLACK, 63 , '000001100111')
  243. BitParser.add(BLACK, 64 , '0000001111')
  244. BitParser.add(BLACK, 128 , '000011001000')
  245. BitParser.add(BLACK, 192 , '000011001001')
  246. BitParser.add(BLACK, 256 , '000001011011')
  247. BitParser.add(BLACK, 320 , '000000110011')
  248. BitParser.add(BLACK, 384 , '000000110100')
  249. BitParser.add(BLACK, 448 , '000000110101')
  250. BitParser.add(BLACK, 512 , '0000001101100')
  251. BitParser.add(BLACK, 576 , '0000001101101')
  252. BitParser.add(BLACK, 640 , '0000001001010')
  253. BitParser.add(BLACK, 704 , '0000001001011')
  254. BitParser.add(BLACK, 768 , '0000001001100')
  255. BitParser.add(BLACK, 832 , '0000001001101')
  256. BitParser.add(BLACK, 896 , '0000001110010')
  257. BitParser.add(BLACK, 960 , '0000001110011')
  258. BitParser.add(BLACK, 1024, '0000001110100')
  259. BitParser.add(BLACK, 1088, '0000001110101')
  260. BitParser.add(BLACK, 1152, '0000001110110')
  261. BitParser.add(BLACK, 1216, '0000001110111')
  262. BitParser.add(BLACK, 1280, '0000001010010')
  263. BitParser.add(BLACK, 1344, '0000001010011')
  264. BitParser.add(BLACK, 1408, '0000001010100')
  265. BitParser.add(BLACK, 1472, '0000001010101')
  266. BitParser.add(BLACK, 1536, '0000001011010')
  267. BitParser.add(BLACK, 1600, '0000001011011')
  268. BitParser.add(BLACK, 1664, '0000001100100')
  269. BitParser.add(BLACK, 1728, '0000001100101')
  270. BitParser.add(BLACK, 1792, '00000001000')
  271. BitParser.add(BLACK, 1856, '00000001100')
  272. BitParser.add(BLACK, 1920, '00000001101')
  273. BitParser.add(BLACK, 1984, '000000010010')
  274. BitParser.add(BLACK, 2048, '000000010011')
  275. BitParser.add(BLACK, 2112, '000000010100')
  276. BitParser.add(BLACK, 2176, '000000010101')
  277. BitParser.add(BLACK, 2240, '000000010110')
  278. BitParser.add(BLACK, 2304, '000000010111')
  279. BitParser.add(BLACK, 2368, '000000011100')
  280. BitParser.add(BLACK, 2432, '000000011101')
  281. BitParser.add(BLACK, 2496, '000000011110')
  282. BitParser.add(BLACK, 2560, '000000011111')
  283. UNCOMPRESSED = [None, None]
  284. BitParser.add(UNCOMPRESSED, '1', '1')
  285. BitParser.add(UNCOMPRESSED, '01', '01')
  286. BitParser.add(UNCOMPRESSED, '001', '001')
  287. BitParser.add(UNCOMPRESSED, '0001', '0001')
  288. BitParser.add(UNCOMPRESSED, '00001', '00001')
  289. BitParser.add(UNCOMPRESSED, '00000', '000001')
  290. BitParser.add(UNCOMPRESSED, 'T00', '00000011')
  291. BitParser.add(UNCOMPRESSED, 'T10', '00000010')
  292. BitParser.add(UNCOMPRESSED, 'T000', '000000011')
  293. BitParser.add(UNCOMPRESSED, 'T100', '000000010')
  294. BitParser.add(UNCOMPRESSED, 'T0000', '0000000011')
  295. BitParser.add(UNCOMPRESSED, 'T1000', '0000000010')
  296. BitParser.add(UNCOMPRESSED, 'T00000', '00000000011')
  297. BitParser.add(UNCOMPRESSED, 'T10000', '00000000010')
  298. class EOFB(Exception):
  299. pass
  300. class InvalidData(Exception):
  301. pass
  302. class ByteSkip(Exception):
  303. pass
  304. def __init__(self, width, bytealign=False):
  305. BitParser.__init__(self)
  306. self.width = width
  307. self.bytealign = bytealign
  308. self.reset()
  309. return
  310. def feedbytes(self, data):
  311. for c in data:
  312. b = ord(c)
  313. try:
  314. for m in (128, 64, 32, 16, 8, 4, 2, 1):
  315. self._parse_bit(b & m)
  316. except self.ByteSkip:
  317. self._accept = self._parse_mode
  318. self._state = self.MODE
  319. except self.EOFB:
  320. break
  321. return
  322. def _parse_mode(self, mode):
  323. if mode == 'p':
  324. self._do_pass()
  325. self._flush_line()
  326. return self.MODE
  327. elif mode == 'h':
  328. self._n1 = 0
  329. self._accept = self._parse_horiz1
  330. if self._color:
  331. return self.WHITE
  332. else:
  333. return self.BLACK
  334. elif mode == 'u':
  335. self._accept = self._parse_uncompressed
  336. return self.UNCOMPRESSED
  337. elif mode == 'e':
  338. raise self.EOFB
  339. elif isinstance(mode, int):
  340. self._do_vertical(mode)
  341. self._flush_line()
  342. return self.MODE
  343. else:
  344. raise self.InvalidData(mode)
  345. def _parse_horiz1(self, n):
  346. if n is None:
  347. raise self.InvalidData
  348. self._n1 += n
  349. if n < 64:
  350. self._n2 = 0
  351. self._color = 1-self._color
  352. self._accept = self._parse_horiz2
  353. if self._color:
  354. return self.WHITE
  355. else:
  356. return self.BLACK
  357. def _parse_horiz2(self, n):
  358. if n is None:
  359. raise self.InvalidData
  360. self._n2 += n
  361. if n < 64:
  362. self._color = 1-self._color
  363. self._accept = self._parse_mode
  364. self._do_horizontal(self._n1, self._n2)
  365. self._flush_line()
  366. return self.MODE
  367. elif self._color:
  368. return self.WHITE
  369. else:
  370. return self.BLACK
  371. def _parse_uncompressed(self, bits):
  372. if not bits:
  373. raise self.InvalidData
  374. if bits.startswith('T'):
  375. self._accept = self._parse_mode
  376. self._color = int(bits[1])
  377. self._do_uncompressed(bits[2:])
  378. return self.MODE
  379. else:
  380. self._do_uncompressed(bits)
  381. return self.UNCOMPRESSED
  382. def _get_bits(self):
  383. return ''.join(str(b) for b in self._curline[:self._curpos])
  384. def _get_refline(self, i):
  385. if i < 0:
  386. return '[]'+''.join(str(b) for b in self._refline)
  387. elif len(self._refline) <= i:
  388. return ''.join(str(b) for b in self._refline)+'[]'
  389. else:
  390. return (''.join(str(b) for b in self._refline[:i]) +
  391. '['+str(self._refline[i])+']' +
  392. ''.join(str(b) for b in self._refline[i+1:]))
  393. def reset(self):
  394. self._y = 0
  395. self._curline = array.array('b', [1]*self.width)
  396. self._reset_line()
  397. self._accept = self._parse_mode
  398. self._state = self.MODE
  399. return
  400. def output_line(self, y, bits):
  401. print y, ''.join(str(b) for b in bits)
  402. return
  403. def _reset_line(self):
  404. self._refline = self._curline
  405. self._curline = array.array('b', [1]*self.width)
  406. self._curpos = -1
  407. self._color = 1
  408. return
  409. def _flush_line(self):
  410. if self.width <= self._curpos:
  411. self.output_line(self._y, self._curline)
  412. self._y += 1
  413. self._reset_line()
  414. if self.bytealign:
  415. raise self.ByteSkip
  416. return
  417. def _do_vertical(self, dx):
  418. #print '* vertical(%d): curpos=%r, color=%r' % (dx, self._curpos, self._color)
  419. #print ' refline:', self._get_refline(self._curpos+1)
  420. x1 = self._curpos+1
  421. while 1:
  422. if x1 == 0:
  423. if (self._color == 1 and self._refline[x1] != self._color):
  424. break
  425. elif x1 == len(self._refline):
  426. break
  427. elif (self._refline[x1-1] == self._color and
  428. self._refline[x1] != self._color):
  429. break
  430. x1 += 1
  431. x1 += dx
  432. x0 = max(0, self._curpos)
  433. x1 = max(0, min(self.width, x1))
  434. if x1 < x0:
  435. for x in xrange(x1, x0):
  436. self._curline[x] = self._color
  437. elif x0 < x1:
  438. for x in xrange(x0, x1):
  439. self._curline[x] = self._color
  440. self._curpos = x1
  441. self._color = 1-self._color
  442. return
  443. def _do_pass(self):
  444. #print '* pass: curpos=%r, color=%r' % (self._curpos, self._color)
  445. #print ' refline:', self._get_refline(self._curpos+1)
  446. x1 = self._curpos+1
  447. while 1:
  448. if x1 == 0:
  449. if (self._color == 1 and self._refline[x1] != self._color):
  450. break
  451. elif x1 == len(self._refline):
  452. break
  453. elif (self._refline[x1-1] == self._color and
  454. self._refline[x1] != self._color):
  455. break
  456. x1 += 1
  457. while 1:
  458. if x1 == 0:
  459. if (self._color == 0 and self._refline[x1] == self._color):
  460. break
  461. elif x1 == len(self._refline):
  462. break
  463. elif (self._refline[x1-1] != self._color and
  464. self._refline[x1] == self._color):
  465. break
  466. x1 += 1
  467. for x in xrange(self._curpos, x1):
  468. self._curline[x] = self._color
  469. self._curpos = x1
  470. return
  471. def _do_horizontal(self, n1, n2):
  472. #print '* horizontal(%d,%d): curpos=%r, color=%r' % (n1, n2, self._curpos, self._color)
  473. if self._curpos < 0:
  474. self._curpos = 0
  475. x = self._curpos
  476. for _ in xrange(n1):
  477. if len(self._curline) <= x:
  478. break
  479. self._curline[x] = self._color
  480. x += 1
  481. for _ in xrange(n2):
  482. if len(self._curline) <= x:
  483. break
  484. self._curline[x] = 1-self._color
  485. x += 1
  486. self._curpos = x
  487. return
  488. def _do_uncompressed(self, bits):
  489. #print '* uncompressed(%r): curpos=%r' % (bits, self._curpos)
  490. for c in bits:
  491. self._curline[self._curpos] = int(c)
  492. self._curpos += 1
  493. self._flush_line()
  494. return
  495. import unittest
  496. ## Test cases
  497. ##
  498. class TestCCITTG4Parser(unittest.TestCase):
  499. def get_parser(self, bits):
  500. parser = CCITTG4Parser(len(bits))
  501. parser._curline = [int(c) for c in bits]
  502. parser._reset_line()
  503. return parser
  504. def test_b1(self):
  505. parser = self.get_parser('00000')
  506. parser._do_vertical(0)
  507. self.assertEqual(parser._curpos, 0)
  508. return
  509. def test_b2(self):
  510. parser = self.get_parser('10000')
  511. parser._do_vertical(-1)
  512. self.assertEqual(parser._curpos, 0)
  513. return
  514. def test_b3(self):
  515. parser = self.get_parser('000111')
  516. parser._do_pass()
  517. self.assertEqual(parser._curpos, 3)
  518. self.assertEqual(parser._get_bits(), '111')
  519. return
  520. def test_b4(self):
  521. parser = self.get_parser('00000')
  522. parser._do_vertical(+2)
  523. self.assertEqual(parser._curpos, 2)
  524. self.assertEqual(parser._get_bits(), '11')
  525. return
  526. def test_b5(self):
  527. parser = self.get_parser('11111111100')
  528. parser._do_horizontal(0, 3)
  529. self.assertEqual(parser._curpos, 3)
  530. parser._do_vertical(1)
  531. self.assertEqual(parser._curpos, 10)
  532. self.assertEqual(parser._get_bits(), '0001111111')
  533. return
  534. def test_e1(self):
  535. parser = self.get_parser('10000')
  536. parser._do_vertical(0)
  537. self.assertEqual(parser._curpos, 1)
  538. parser._do_vertical(0)
  539. self.assertEqual(parser._curpos, 5)
  540. self.assertEqual(parser._get_bits(), '10000')
  541. return
  542. def test_e2(self):
  543. parser = self.get_parser('10011')
  544. parser._do_vertical(0)
  545. self.assertEqual(parser._curpos, 1)
  546. parser._do_vertical(2)
  547. self.assertEqual(parser._curpos, 5)
  548. self.assertEqual(parser._get_bits(), '10000')
  549. return
  550. def test_e3(self):
  551. parser = self.get_parser('011111')
  552. parser._color = 0
  553. parser._do_vertical(0)
  554. self.assertEqual(parser._color, 1)
  555. self.assertEqual(parser._curpos, 1)
  556. parser._do_vertical(-2)
  557. self.assertEqual(parser._color, 0)
  558. self.assertEqual(parser._curpos, 4)
  559. parser._do_vertical(0)
  560. self.assertEqual(parser._curpos, 6)
  561. self.assertEqual(parser._get_bits(), '011100')
  562. return
  563. def test_e4(self):
  564. parser = self.get_parser('10000')
  565. parser._do_vertical(0)
  566. self.assertEqual(parser._curpos, 1)
  567. parser._do_vertical(-2)
  568. self.assertEqual(parser._curpos, 3)
  569. parser._do_vertical(0)
  570. self.assertEqual(parser._curpos, 5)
  571. self.assertEqual(parser._get_bits(), '10011')
  572. return
  573. def test_e5(self):
  574. parser = self.get_parser('011000')
  575. parser._color = 0
  576. parser._do_vertical(0)
  577. self.assertEqual(parser._curpos, 1)
  578. parser._do_vertical(3)
  579. self.assertEqual(parser._curpos, 6)
  580. self.assertEqual(parser._get_bits(), '011111')
  581. return
  582. def test_e6(self):
  583. parser = self.get_parser('11001')
  584. parser._do_pass()
  585. self.assertEqual(parser._curpos, 4)
  586. parser._do_vertical(0)
  587. self.assertEqual(parser._curpos, 5)
  588. self.assertEqual(parser._get_bits(), '11111')
  589. return
  590. def test_e7(self):
  591. parser = self.get_parser('0000000000')
  592. parser._curpos = 2
  593. parser._color = 1
  594. parser._do_horizontal(2, 6)
  595. self.assertEqual(parser._curpos, 10)
  596. self.assertEqual(parser._get_bits(), '1111000000')
  597. return
  598. def test_e8(self):
  599. parser = self.get_parser('001100000')
  600. parser._curpos = 1
  601. parser._color = 0
  602. parser._do_vertical(0)
  603. self.assertEqual(parser._curpos, 2)
  604. parser._do_horizontal(7, 0)
  605. self.assertEqual(parser._curpos, 9)
  606. self.assertEqual(parser._get_bits(), '101111111')
  607. return
  608. def test_m1(self):
  609. parser = self.get_parser('10101')
  610. parser._do_pass()
  611. self.assertEqual(parser._curpos, 2)
  612. parser._do_pass()
  613. self.assertEqual(parser._curpos, 4)
  614. self.assertEqual(parser._get_bits(), '1111')
  615. return
  616. def test_m2(self):
  617. parser = self.get_parser('101011')
  618. parser._do_vertical(-1)
  619. parser._do_vertical(-1)
  620. parser._do_vertical(1)
  621. parser._do_horizontal(1, 1)
  622. self.assertEqual(parser._get_bits(), '011101')
  623. return
  624. def test_m3(self):
  625. parser = self.get_parser('10111011')
  626. parser._do_vertical(-1)
  627. parser._do_pass()
  628. parser._do_vertical(1)
  629. parser._do_vertical(1)
  630. self.assertEqual(parser._get_bits(), '00000001')
  631. return
  632. ## CCITTFaxDecoder
  633. ##
  634. class CCITTFaxDecoder(CCITTG4Parser):
  635. def __init__(self, width, bytealign=False, reversed=False):
  636. CCITTG4Parser.__init__(self, width, bytealign=bytealign)
  637. self.reversed = reversed
  638. self._buf = ''
  639. return
  640. def close(self):
  641. return self._buf
  642. def output_line(self, y, bits):
  643. bytes = array.array('B', [0]*((len(bits)+7)//8))
  644. if self.reversed:
  645. bits = [1-b for b in bits]
  646. for (i, b) in enumerate(bits):
  647. if b:
  648. bytes[i//8] += (128, 64, 32, 16, 8, 4, 2, 1)[i % 8]
  649. self._buf += bytes.tostring()
  650. return
  651. def ccittfaxdecode(data, params):
  652. K = params.get('K')
  653. cols = params.get('Columns')
  654. bytealign = params.get('EncodedByteAlign')
  655. reversed = params.get('BlackIs1')
  656. if K == -1:
  657. parser = CCITTFaxDecoder(cols, bytealign=bytealign, reversed=reversed)
  658. else:
  659. raise ValueError(K)
  660. parser.feedbytes(data)
  661. return parser.close()
  662. # test
  663. def main(argv):
  664. import pygame
  665. if not argv[1:]:
  666. return unittest.main()
  667. class Parser(CCITTG4Parser):
  668. def __init__(self, width, bytealign=False):
  669. CCITTG4Parser.__init__(self, width, bytealign=bytealign)
  670. self.img = pygame.Surface((self.width, 1000))
  671. return
  672. def output_line(self, y, bits):
  673. for (x, b) in enumerate(bits):
  674. if b:
  675. self.img.set_at((x, y), (255, 255, 255))
  676. else:
  677. self.img.set_at((x, y), (0, 0, 0))
  678. return
  679. def close(self):
  680. pygame.image.save(self.img, 'out.bmp')
  681. return
  682. for path in argv[1:]:
  683. fp = file(path, 'rb')
  684. (_, _, k, w, h, _) = path.split('.')
  685. parser = Parser(int(w))
  686. parser.feedbytes(fp.read())
  687. parser.close()
  688. fp.close()
  689. return
  690. if __name__ == '__main__':
  691. sys.exit(main(sys.argv))