BZZ.pm 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. #------------------------------------------------------------------------------
  2. # File: BZZ.pm
  3. #
  4. # Description: Utility to decode BZZ compressed data
  5. #
  6. # Revisions: 09/22/2008 - P. Harvey Created
  7. #
  8. # References: 1) http://djvu.sourceforge.net/
  9. # 2) http://www.djvu.org/
  10. #
  11. # Notes: This code based on ZPCodec and BSByteStream of DjVuLibre 3.5.21
  12. # (see NOTES documentation below for license/copyright details)
  13. #------------------------------------------------------------------------------
  14. package Image::ExifTool::BZZ;
  15. use strict;
  16. use integer; # IMPORTANT!! use integer arithmetic throughout
  17. require Exporter;
  18. use vars qw($VERSION @ISA @EXPORT_OK);
  19. $VERSION = '1.00';
  20. @ISA = qw(Exporter);
  21. @EXPORT_OK = qw(Decode);
  22. # constants
  23. sub FREQMAX { 4 }
  24. sub CTXIDS { 3 }
  25. sub MAXBLOCK { 4096 }
  26. # This table has been designed for the ZPCoder
  27. # by running the following command in file 'zptable.sn':
  28. # (fast-crude (steady-mat 0.0035 0.0002) 260)))
  29. my @default_ztable_p = (
  30. 0x8000, 0x8000, 0x8000, 0x6bbd, 0x6bbd, 0x5d45, 0x5d45, 0x51b9, 0x51b9, 0x4813,
  31. 0x4813, 0x3fd5, 0x3fd5, 0x38b1, 0x38b1, 0x3275, 0x3275, 0x2cfd, 0x2cfd, 0x2825,
  32. 0x2825, 0x23ab, 0x23ab, 0x1f87, 0x1f87, 0x1bbb, 0x1bbb, 0x1845, 0x1845, 0x1523,
  33. 0x1523, 0x1253, 0x1253, 0x0fcf, 0x0fcf, 0x0d95, 0x0d95, 0x0b9d, 0x0b9d, 0x09e3,
  34. 0x09e3, 0x0861, 0x0861, 0x0711, 0x0711, 0x05f1, 0x05f1, 0x04f9, 0x04f9, 0x0425,
  35. 0x0425, 0x0371, 0x0371, 0x02d9, 0x02d9, 0x0259, 0x0259, 0x01ed, 0x01ed, 0x0193,
  36. 0x0193, 0x0149, 0x0149, 0x010b, 0x010b, 0x00d5, 0x00d5, 0x00a5, 0x00a5, 0x007b,
  37. 0x007b, 0x0057, 0x0057, 0x003b, 0x003b, 0x0023, 0x0023, 0x0013, 0x0013, 0x0007,
  38. 0x0007, 0x0001, 0x0001, 0x5695, 0x24ee, 0x8000, 0x0d30, 0x481a, 0x0481, 0x3579,
  39. 0x017a, 0x24ef, 0x007b, 0x1978, 0x0028, 0x10ca, 0x000d, 0x0b5d, 0x0034, 0x078a,
  40. 0x00a0, 0x050f, 0x0117, 0x0358, 0x01ea, 0x0234, 0x0144, 0x0173, 0x0234, 0x00f5,
  41. 0x0353, 0x00a1, 0x05c5, 0x011a, 0x03cf, 0x01aa, 0x0285, 0x0286, 0x01ab, 0x03d3,
  42. 0x011a, 0x05c5, 0x00ba, 0x08ad, 0x007a, 0x0ccc, 0x01eb, 0x1302, 0x02e6, 0x1b81,
  43. 0x045e, 0x24ef, 0x0690, 0x2865, 0x09de, 0x3987, 0x0dc8, 0x2c99, 0x10ca, 0x3b5f,
  44. 0x0b5d, 0x5695, 0x078a, 0x8000, 0x050f, 0x24ee, 0x0358, 0x0d30, 0x0234, 0x0481,
  45. 0x0173, 0x017a, 0x00f5, 0x007b, 0x00a1, 0x0028, 0x011a, 0x000d, 0x01aa, 0x0034,
  46. 0x0286, 0x00a0, 0x03d3, 0x0117, 0x05c5, 0x01ea, 0x08ad, 0x0144, 0x0ccc, 0x0234,
  47. 0x1302, 0x0353, 0x1b81, 0x05c5, 0x24ef, 0x03cf, 0x2b74, 0x0285, 0x201d, 0x01ab,
  48. 0x1715, 0x011a, 0x0fb7, 0x00ba, 0x0a67, 0x01eb, 0x06e7, 0x02e6, 0x0496, 0x045e,
  49. 0x030d, 0x0690, 0x0206, 0x09de, 0x0155, 0x0dc8, 0x00e1, 0x2b74, 0x0094, 0x201d,
  50. 0x0188, 0x1715, 0x0252, 0x0fb7, 0x0383, 0x0a67, 0x0547, 0x06e7, 0x07e2, 0x0496,
  51. 0x0bc0, 0x030d, 0x1178, 0x0206, 0x19da, 0x0155, 0x24ef, 0x00e1, 0x320e, 0x0094,
  52. 0x432a, 0x0188, 0x447d, 0x0252, 0x5ece, 0x0383, 0x8000, 0x0547, 0x481a, 0x07e2,
  53. 0x3579, 0x0bc0, 0x24ef, 0x1178, 0x1978, 0x19da, 0x2865, 0x24ef, 0x3987, 0x320e,
  54. 0x2c99, 0x432a, 0x3b5f, 0x447d, 0x5695, 0x5ece, 0x8000, 0x8000, 0x5695, 0x481a,
  55. 0x481a, 0, 0, 0, 0, 0
  56. );
  57. my @default_ztable_m = (
  58. 0x0000, 0x0000, 0x0000, 0x10a5, 0x10a5, 0x1f28, 0x1f28, 0x2bd3, 0x2bd3, 0x36e3,
  59. 0x36e3, 0x408c, 0x408c, 0x48fd, 0x48fd, 0x505d, 0x505d, 0x56d0, 0x56d0, 0x5c71,
  60. 0x5c71, 0x615b, 0x615b, 0x65a5, 0x65a5, 0x6962, 0x6962, 0x6ca2, 0x6ca2, 0x6f74,
  61. 0x6f74, 0x71e6, 0x71e6, 0x7404, 0x7404, 0x75d6, 0x75d6, 0x7768, 0x7768, 0x78c2,
  62. 0x78c2, 0x79ea, 0x79ea, 0x7ae7, 0x7ae7, 0x7bbe, 0x7bbe, 0x7c75, 0x7c75, 0x7d0f,
  63. 0x7d0f, 0x7d91, 0x7d91, 0x7dfe, 0x7dfe, 0x7e5a, 0x7e5a, 0x7ea6, 0x7ea6, 0x7ee6,
  64. 0x7ee6, 0x7f1a, 0x7f1a, 0x7f45, 0x7f45, 0x7f6b, 0x7f6b, 0x7f8d, 0x7f8d, 0x7faa,
  65. 0x7faa, 0x7fc3, 0x7fc3, 0x7fd7, 0x7fd7, 0x7fe7, 0x7fe7, 0x7ff2, 0x7ff2, 0x7ffa,
  66. 0x7ffa, 0x7fff, 0x7fff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  67. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  68. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  69. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  70. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  71. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  72. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  73. );
  74. my @default_ztable_up = (
  75. 84, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
  76. 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
  77. 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
  78. 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
  79. 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
  80. 82, 81, 82, 9, 86, 5, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
  81. 82, 99, 76, 101, 70, 103, 66, 105, 106, 107, 66, 109, 60, 111, 56, 69,
  82. 114, 65, 116, 61, 118, 57, 120, 53, 122, 49, 124, 43, 72, 39, 60, 33,
  83. 56, 29, 52, 23, 48, 23, 42, 137, 38, 21, 140, 15, 142, 9, 144, 141,
  84. 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 70, 157, 66, 81, 62, 75,
  85. 58, 69, 54, 65, 50, 167, 44, 65, 40, 59, 34, 55, 30, 175, 24, 177,
  86. 178, 179, 180, 181, 182, 183, 184, 69, 186, 59, 188, 55, 190, 51, 192, 47,
  87. 194, 41, 196, 37, 198, 199, 72, 201, 62, 203, 58, 205, 54, 207, 50, 209,
  88. 46, 211, 40, 213, 36, 215, 30, 217, 26, 219, 20, 71, 14, 61, 14, 57,
  89. 8, 53, 228, 49, 230, 45, 232, 39, 234, 35, 138, 29, 24, 25, 240, 19,
  90. 22, 13, 16, 13, 10, 7, 244, 249, 10, 89, 230, 0, 0, 0, 0, 0
  91. );
  92. my @default_ztable_dn = (
  93. 145, 4, 3, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
  94. 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
  95. 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
  96. 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
  97. 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
  98. 78, 79, 80, 85, 226, 6, 176, 143, 138, 141, 112, 135, 104, 133, 100, 129,
  99. 98, 127, 72, 125, 102, 123, 60, 121, 110, 119, 108, 117, 54, 115, 48, 113,
  100. 134, 59, 132, 55, 130, 51, 128, 47, 126, 41, 62, 37, 66, 31, 54, 25,
  101. 50, 131, 46, 17, 40, 15, 136, 7, 32, 139, 172, 9, 170, 85, 168, 248,
  102. 166, 247, 164, 197, 162, 95, 160, 173, 158, 165, 156, 161, 60, 159, 56, 71,
  103. 52, 163, 48, 59, 42, 171, 38, 169, 32, 53, 26, 47, 174, 193, 18, 191,
  104. 222, 189, 218, 187, 216, 185, 214, 61, 212, 53, 210, 49, 208, 45, 206, 39,
  105. 204, 195, 202, 31, 200, 243, 64, 239, 56, 237, 52, 235, 48, 233, 44, 231,
  106. 38, 229, 34, 227, 28, 225, 22, 223, 16, 221, 220, 63, 8, 55, 224, 51,
  107. 2, 47, 87, 43, 246, 37, 244, 33, 238, 27, 236, 21, 16, 15, 8, 241,
  108. 242, 7, 10, 245, 2, 1, 83, 250, 2, 143, 246, 0, 0, 0, 0, 0
  109. );
  110. #------------------------------------------------------------------------------
  111. # New - create new BZZ object
  112. # Inputs: 0) reference to BZZ object or BZZ class name
  113. # Returns: blessed BZZ object ref
  114. sub new
  115. {
  116. local $_;
  117. my $that = shift;
  118. my $class = ref($that) || $that || 'Image::ExifTool::BZZ';
  119. return bless {}, $class;
  120. }
  121. #------------------------------------------------------------------------------
  122. # Initialize BZZ object
  123. # Inputs: 0) BZZ object ref, 1) data ref, 2) true for DjVu compatibility
  124. sub Init($$)
  125. {
  126. my ($self, $dataPt, $djvucompat) = @_;
  127. # Create machine independent ffz table
  128. my $ffzt = $$self{ffzt} = [ ];
  129. my ($i, $j);
  130. for ($i=0; $i<256; $i++) {
  131. $$ffzt[$i] = 0;
  132. for ($j=$i; $j&0x80; $j<<=1) {
  133. $$ffzt[$i] += 1;
  134. }
  135. }
  136. # Initialize table
  137. $$self{p} = [ @default_ztable_p ];
  138. $$self{'m'} = [ @default_ztable_m ];
  139. $$self{up} = [ @default_ztable_up ];
  140. $$self{dn} = [ @default_ztable_dn ];
  141. # Patch table (and lose DjVu compatibility)
  142. unless ($djvucompat) {
  143. my ($p, $m, $dn) = ($$self{p}, $$self{'m'}, $$self{dn});
  144. for ($j=0; $j<256; $j++) {
  145. my $a = (0x10000 - $$p[$j]) & 0xffff;
  146. while ($a >= 0x8000) { $a = ($a<<1) & 0xffff }
  147. if ($$m[$j]>0 && $a+$$p[$j]>=0x8000 && $a>=$$m[$j]) {
  148. $$dn[$j] = $default_ztable_dn[$default_ztable_dn[$j]];
  149. }
  150. }
  151. }
  152. $$self{ctx} = [ (0) x 300 ];
  153. $$self{DataPt} = $dataPt;
  154. $$self{Pos} = 0;
  155. $$self{DataLen} = length $$dataPt;
  156. $$self{a} = 0;
  157. $$self{buffer} = 0;
  158. $$self{fence} = 0;
  159. $$self{blocksize} = 0;
  160. # Read first 16 bits of code
  161. if (length($$dataPt) >= 2) {
  162. $$self{code} = unpack('n', $$dataPt);
  163. $$self{Pos} += 2;
  164. } elsif (length($$dataPt) >= 1) {
  165. $$self{code} = (unpack('C', $$dataPt) << 8) | 0xff;
  166. $$self{Pos}++;
  167. } else {
  168. $$self{code} = 0xffff;
  169. }
  170. $$self{byte} = $$self{code} & 0xff;
  171. # Preload buffer
  172. $$self{delay} = 25;
  173. $$self{scount} = 0;
  174. # Compute initial fence
  175. $$self{fence} = $$self{code} >= 0x8000 ? 0x7fff : $$self{code};
  176. }
  177. #------------------------------------------------------------------------------
  178. # Decode data block
  179. # Inputs: 0) optional BZZ object ref, 1) optional data ref
  180. # Returns: decoded data or undefined on error
  181. # Notes: If called without a data ref, an input BZZ object ref must be given and
  182. # the BZZ object must have been initialized by a previous call to Init()
  183. sub Decode($;$)
  184. {
  185. # Decode input stream
  186. local $_;
  187. my $self;
  188. if (ref $_[0] and UNIVERSAL::isa($_[0],'Image::ExifTool::BZZ')) {
  189. $self = shift;
  190. } else {
  191. $self = new Image::ExifTool::BZZ;
  192. }
  193. my $dataPt = shift;
  194. if ($dataPt) {
  195. $self->Init($dataPt, 1);
  196. } else {
  197. $dataPt = $$self{DataPt} or return undef;
  198. }
  199. # Decode block size
  200. my $n = 1;
  201. my $m = (1 << 24);
  202. while ($n < $m) {
  203. my $b = $self->decode_sub(0x8000 + ($$self{a}>>1));
  204. $n = ($n<<1) | $b;
  205. }
  206. $$self{size} = $n - $m;
  207. return '' unless $$self{size};
  208. return undef if $$self{size} > MAXBLOCK()*1024;
  209. # Allocate
  210. if ($$self{blocksize} < $$self{size}) {
  211. $$self{blocksize} = $$self{size};
  212. }
  213. # Decode Estimation Speed
  214. my $fshift = 0;
  215. if ($self->decode_sub(0x8000 + ($$self{a}>>1))) {
  216. $fshift += 1;
  217. $fshift += 1 if $self->decode_sub(0x8000 + ($$self{a}>>1));
  218. }
  219. # Prepare Quasi MTF
  220. my @mtf = (0..255);
  221. my @freq = (0) x FREQMAX();
  222. my $fadd = 4;
  223. # Decode
  224. my $mtfno = 3;
  225. my $markerpos = -1;
  226. my $cx = $$self{ctx};
  227. my ($i, @dat);
  228. byte: for ($i=0; $i<$$self{size}; $i++) {
  229. # dummy loop avoids use of "goto" statement
  230. dummy: for (;;) {
  231. my $ctxid = CTXIDS() - 1;
  232. $ctxid = $mtfno if $ctxid > $mtfno;
  233. my $cp = 0;
  234. my ($imtf, $bits);
  235. for ($imtf=0; $imtf<2; ++$imtf) {
  236. if ($self->decoder($$cx[$cp+$ctxid])) {
  237. $mtfno = $imtf;
  238. $dat[$i] = $mtf[$mtfno];
  239. # (a "goto" here could give a segfault due to a Perl bug)
  240. last dummy; # do rotation
  241. }
  242. $cp += CTXIDS();
  243. }
  244. for ($bits=1; $bits<8; ++$bits, $imtf<<=1) {
  245. if ($self->decoder($$cx[$cp])) {
  246. my $n = 1;
  247. my $m = (1 << $bits);
  248. while ($n < $m) {
  249. my $b = $self->decoder($$cx[$cp+$n]);
  250. $n = ($n<<1) | $b;
  251. }
  252. $mtfno = $imtf + $n - $m;
  253. $dat[$i] = $mtf[$mtfno];
  254. last dummy; # do rotation
  255. }
  256. $cp += $imtf;
  257. }
  258. $mtfno=256;
  259. $dat[$i] = 0;
  260. $markerpos=$i;
  261. next byte; # no rotation necessary
  262. }
  263. # Rotate mtf according to empirical frequencies (new!)
  264. # Adjust frequencies for overflow
  265. $fadd = $fadd + ($fadd >> $fshift);
  266. if ($fadd > 0x10000000) {
  267. $fadd >>= 24;
  268. $_ >>= 24 foreach @freq;
  269. }
  270. # Relocate new char according to new freq
  271. my $fc = $fadd;
  272. $fc += $freq[$mtfno] if $mtfno < FREQMAX();
  273. my $k;
  274. for ($k=$mtfno; $k>=FREQMAX(); $k--) {
  275. $mtf[$k] = $mtf[$k-1];
  276. }
  277. for (; $k>0 && $fc>=$freq[$k-1]; $k--) {
  278. $mtf[$k] = $mtf[$k-1];
  279. $freq[$k] = $freq[$k-1];
  280. }
  281. $mtf[$k] = $dat[$i];
  282. $freq[$k] = $fc;
  283. # when "goto" was used, Perl 5.8.6 could segfault here
  284. # unless "next" was explicitly stated
  285. }
  286. #
  287. # Reconstruct the string
  288. #
  289. return undef if $markerpos<1 || $markerpos>=$$self{size};
  290. # Allocate pointers
  291. # Prepare count buffer
  292. my @count = (0) x 256;
  293. my @posn;
  294. # Fill count buffer
  295. no integer;
  296. for ($i=0; $i<$markerpos; $i++) {
  297. my $c = $dat[$i];
  298. $posn[$i] = ($c<<24) | ($count[$c]++ & 0xffffff);
  299. }
  300. $posn[$i++] = 0; # (initialize marker entry just to be safe)
  301. for ( ; $i<$$self{size}; $i++) {
  302. my $c = $dat[$i];
  303. $posn[$i] = ($c<<24) | ($count[$c]++ & 0xffffff);
  304. }
  305. use integer;
  306. # Compute sorted char positions
  307. my $last = 1;
  308. for ($i=0; $i<256; $i++) {
  309. my $tmp = $count[$i];
  310. $count[$i] = $last;
  311. $last += $tmp;
  312. }
  313. # Undo the sort transform
  314. $i = 0;
  315. $last = $$self{size}-1;
  316. while ($last > 0) {
  317. my $n = $posn[$i];
  318. no integer;
  319. my $c = $n >> 24;
  320. use integer;
  321. $dat[--$last] = $c;
  322. $i = $count[$c] + ($n & 0xffffff);
  323. }
  324. # Final check and return decoded data
  325. return undef if $i != $markerpos;
  326. pop @dat; # (last byte isn't real)
  327. return pack 'C*', @dat;
  328. }
  329. #------------------------------------------------------------------------------
  330. # Inputs: 0) BZZ object ref, 1) ctx
  331. # Returns: decoded bit
  332. sub decoder($$)
  333. {
  334. my ($self, $ctx) = @_;
  335. my $z = $$self{a} + $self->{p}[$ctx];
  336. if ($z <= $$self{fence}) {
  337. $$self{a} = $z;
  338. return ($ctx & 1);
  339. }
  340. # must pass $_[1] so subroutine can modify value (darned C++ pass-by-reference!)
  341. return $self->decode_sub($z, $_[1]);
  342. }
  343. #------------------------------------------------------------------------------
  344. # Inputs: 0) BZZ object ref, 1) z, 2) ctx (or undef)
  345. # Returns: decoded bit
  346. sub decode_sub($$;$)
  347. {
  348. my ($self, $z, $ctx) = @_;
  349. # ensure that we have at least 16 bits of encoded data available
  350. if ($$self{scount} < 16) {
  351. # preload byte by byte until we have at least 24 bits
  352. while ($$self{scount} <= 24) {
  353. if ($$self{Pos} < $$self{DataLen}) {
  354. $$self{byte} = ord(substr(${$$self{DataPt}}, $$self{Pos}, 1));
  355. ++$$self{Pos};
  356. } else {
  357. $$self{byte} = 0xff;
  358. if (--$$self{delay} < 1) {
  359. # setting size to zero forces error return from Decode()
  360. $$self{size} = 0;
  361. return 0;
  362. }
  363. }
  364. $$self{buffer} = ($$self{buffer}<<8) | $$self{byte};
  365. $$self{scount} += 8;
  366. }
  367. }
  368. # Save bit
  369. my $a = $$self{a};
  370. my ($bit, $code);
  371. if (defined $ctx) {
  372. $bit = ($ctx & 1);
  373. # Avoid interval reversion
  374. my $d = 0x6000 + (($z+$a)>>2);
  375. $z = $d if $z > $d;
  376. } else {
  377. $bit = 0;
  378. }
  379. # Test MPS/LPS
  380. if ($z > ($code = $$self{code})) {
  381. $bit ^= 1;
  382. # LPS branch
  383. $z = 0x10000 - $z;
  384. $a += $z;
  385. $code += $z;
  386. # LPS adaptation
  387. $_[2] = $self->{dn}[$ctx] if defined $ctx;
  388. # LPS renormalization
  389. my $sft = $a>=0xff00 ? $self->{ffzt}[$a&0xff] + 8 : $self->{ffzt}[($a>>8)&0xff];
  390. $$self{scount} -= $sft;
  391. $$self{a} = ($a<<$sft) & 0xffff;
  392. $code = (($code<<$sft) & 0xffff) | (($$self{buffer}>>$$self{scount}) & ((1<<$sft)-1));
  393. } else {
  394. # MPS adaptation
  395. $_[2] = $self->{up}[$ctx] if defined $ctx and $a >= $self->{'m'}[$ctx];
  396. # MPS renormalization
  397. $$self{scount} -= 1;
  398. $$self{a} = ($z<<1) & 0xffff;
  399. $code = (($code<<1) & 0xffff) | (($$self{buffer}>>$$self{scount}) & 1);
  400. }
  401. # Adjust fence and save new code
  402. $$self{fence} = $code >= 0x8000 ? 0x7fff : $code;
  403. $$self{code} = $code;
  404. return $bit;
  405. }
  406. 1; # end
  407. __END__
  408. =head1 NAME
  409. Image::ExifTool::BZZ - Utility to decode BZZ compressed data
  410. =head1 SYNOPSIS
  411. This module is used by Image::ExifTool
  412. =head1 DESCRIPTION
  413. This module contains definitions required by Image::ExifTool to decode BZZ
  414. compressed data in DjVu images.
  415. =head1 NOTES
  416. This code is based on ZPCodec and BSByteStream of DjVuLibre 3.5.21 (see
  417. additional copyrights and the first reference below), which are covered
  418. under the GNU GPL license.
  419. This is implemented as Image::ExifTool::BZZ instead of Compress::BZZ because
  420. I am hoping that someone else will write a proper Compress::BZZ module (with
  421. compression ability).
  422. =head1 AUTHOR
  423. Copyright 2003-2016, Phil Harvey (phil at owl.phy.queensu.ca)
  424. Copyright 2002, Leon Bottou and Yann Le Cun
  425. Copyright 2001, AT&T
  426. Copyright 1999-2001, LizardTech Inc.
  427. This library is free software; you can redistribute it and/or modify it
  428. under the same terms as Perl itself.
  429. =head1 REFERENCES
  430. =over 4
  431. =item L<http://djvu.sourceforge.net/>
  432. =item L<http://www.djvu.org/>
  433. =back
  434. =head1 SEE ALSO
  435. L<Image::ExifTool::DjVu(3pm)|Image::ExifTool::DjVu>,
  436. L<Image::ExifTool(3pm)|Image::ExifTool>
  437. =cut