You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1479 lines
46 KiB
1479 lines
46 KiB
/* |
|
* Copyright (c) 2001 Sun Microsystems, Inc. All Rights Reserved. |
|
* |
|
* Redistribution and use in source and binary forms, with or without |
|
* modification, are permitted provided that the following conditions are met: |
|
* |
|
* -Redistributions of source code must retain the above copyright notice, this |
|
* list of conditions and the following disclaimer. |
|
* |
|
* -Redistribution in binary form must reproduct the above copyright notice, |
|
* this list of conditions and the following disclaimer in the documentation |
|
* and/or other materials provided with the distribution. |
|
* |
|
* Neither the name of Sun Microsystems, Inc. or the names of contributors may |
|
* be used to endorse or promote products derived from this software without |
|
* specific prior written permission. |
|
* |
|
* This software is provided "AS IS," without a warranty of any kind. ALL |
|
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY |
|
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR |
|
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE |
|
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING |
|
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS |
|
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, |
|
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER |
|
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF |
|
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE |
|
* POSSIBILITY OF SUCH DAMAGES. |
|
* |
|
* You acknowledge that Software is not designed,licensed or intended for use in |
|
* the design, construction, operation or maintenance of any nuclear facility. |
|
*/ |
|
package com.fr.third.JAI; |
|
|
|
class TIFFFaxDecoder { |
|
|
|
private int bitPointer, bytePointer; |
|
private byte[] data; |
|
private int w, h; |
|
private int fillOrder; |
|
|
|
// Data structures needed to store changing elements for the previous |
|
// and the current scanline |
|
private int changingElemSize = 0; |
|
private int prevChangingElems[]; |
|
private int currChangingElems[]; |
|
|
|
// Element at which to start search in getNextChangingElement |
|
private int lastChangingElement = 0; |
|
|
|
private int compression = 2; |
|
|
|
// Variables set by T4Options |
|
private int uncompressedMode = 0; |
|
private int fillBits = 0; |
|
private int oneD; |
|
|
|
static int table1[] = { |
|
0x00, // 0 bits are left in first byte - SHOULD NOT HAPPEN |
|
0x01, // 1 bits are left in first byte |
|
0x03, // 2 bits are left in first byte |
|
0x07, // 3 bits are left in first byte |
|
0x0f, // 4 bits are left in first byte |
|
0x1f, // 5 bits are left in first byte |
|
0x3f, // 6 bits are left in first byte |
|
0x7f, // 7 bits are left in first byte |
|
0xff // 8 bits are left in first byte |
|
}; |
|
|
|
static int table2[] = { |
|
0x00, // 0 |
|
0x80, // 1 |
|
0xc0, // 2 |
|
0xe0, // 3 |
|
0xf0, // 4 |
|
0xf8, // 5 |
|
0xfc, // 6 |
|
0xfe, // 7 |
|
0xff // 8 |
|
}; |
|
|
|
// Table to be used when fillOrder = 2, for flipping bytes. |
|
static byte flipTable[] = { |
|
0, -128, 64, -64, 32, -96, 96, -32, |
|
16, -112, 80, -48, 48, -80, 112, -16, |
|
8, -120, 72, -56, 40, -88, 104, -24, |
|
24, -104, 88, -40, 56, -72, 120, -8, |
|
4, -124, 68, -60, 36, -92, 100, -28, |
|
20, -108, 84, -44, 52, -76, 116, -12, |
|
12, -116, 76, -52, 44, -84, 108, -20, |
|
28, -100, 92, -36, 60, -68, 124, -4, |
|
2, -126, 66, -62, 34, -94, 98, -30, |
|
18, -110, 82, -46, 50, -78, 114, -14, |
|
10, -118, 74, -54, 42, -86, 106, -22, |
|
26, -102, 90, -38, 58, -70, 122, -6, |
|
6, -122, 70, -58, 38, -90, 102, -26, |
|
22, -106, 86, -42, 54, -74, 118, -10, |
|
14, -114, 78, -50, 46, -82, 110, -18, |
|
30, -98, 94, -34, 62, -66, 126, -2, |
|
1, -127, 65, -63, 33, -95, 97, -31, |
|
17, -111, 81, -47, 49, -79, 113, -15, |
|
9, -119, 73, -55, 41, -87, 105, -23, |
|
25, -103, 89, -39, 57, -71, 121, -7, |
|
5, -123, 69, -59, 37, -91, 101, -27, |
|
21, -107, 85, -43, 53, -75, 117, -11, |
|
13, -115, 77, -51, 45, -83, 109, -19, |
|
29, -99, 93, -35, 61, -67, 125, -3, |
|
3, -125, 67, -61, 35, -93, 99, -29, |
|
19, -109, 83, -45, 51, -77, 115, -13, |
|
11, -117, 75, -53, 43, -85, 107, -21, |
|
27, -101, 91, -37, 59, -69, 123, -5, |
|
7, -121, 71, -57, 39, -89, 103, -25, |
|
23, -105, 87, -41, 55, -73, 119, -9, |
|
15, -113, 79, -49, 47, -81, 111, -17, |
|
31, -97, 95, -33, 63, -65, 127, -1, |
|
}; |
|
|
|
// The main 10 bit white runs lookup table |
|
static short white[] = { |
|
// 0 - 7 |
|
6430, 6400, 6400, 6400, 3225, 3225, 3225, 3225, |
|
// 8 - 15 |
|
944, 944, 944, 944, 976, 976, 976, 976, |
|
// 16 - 23 |
|
1456, 1456, 1456, 1456, 1488, 1488, 1488, 1488, |
|
// 24 - 31 |
|
718, 718, 718, 718, 718, 718, 718, 718, |
|
// 32 - 39 |
|
750, 750, 750, 750, 750, 750, 750, 750, |
|
// 40 - 47 |
|
1520, 1520, 1520, 1520, 1552, 1552, 1552, 1552, |
|
// 48 - 55 |
|
428, 428, 428, 428, 428, 428, 428, 428, |
|
// 56 - 63 |
|
428, 428, 428, 428, 428, 428, 428, 428, |
|
// 64 - 71 |
|
654, 654, 654, 654, 654, 654, 654, 654, |
|
// 72 - 79 |
|
1072, 1072, 1072, 1072, 1104, 1104, 1104, 1104, |
|
// 80 - 87 |
|
1136, 1136, 1136, 1136, 1168, 1168, 1168, 1168, |
|
// 88 - 95 |
|
1200, 1200, 1200, 1200, 1232, 1232, 1232, 1232, |
|
// 96 - 103 |
|
622, 622, 622, 622, 622, 622, 622, 622, |
|
// 104 - 111 |
|
1008, 1008, 1008, 1008, 1040, 1040, 1040, 1040, |
|
// 112 - 119 |
|
44, 44, 44, 44, 44, 44, 44, 44, |
|
// 120 - 127 |
|
44, 44, 44, 44, 44, 44, 44, 44, |
|
// 128 - 135 |
|
396, 396, 396, 396, 396, 396, 396, 396, |
|
// 136 - 143 |
|
396, 396, 396, 396, 396, 396, 396, 396, |
|
// 144 - 151 |
|
1712, 1712, 1712, 1712, 1744, 1744, 1744, 1744, |
|
// 152 - 159 |
|
846, 846, 846, 846, 846, 846, 846, 846, |
|
// 160 - 167 |
|
1264, 1264, 1264, 1264, 1296, 1296, 1296, 1296, |
|
// 168 - 175 |
|
1328, 1328, 1328, 1328, 1360, 1360, 1360, 1360, |
|
// 176 - 183 |
|
1392, 1392, 1392, 1392, 1424, 1424, 1424, 1424, |
|
// 184 - 191 |
|
686, 686, 686, 686, 686, 686, 686, 686, |
|
// 192 - 199 |
|
910, 910, 910, 910, 910, 910, 910, 910, |
|
// 200 - 207 |
|
1968, 1968, 1968, 1968, 2000, 2000, 2000, 2000, |
|
// 208 - 215 |
|
2032, 2032, 2032, 2032, 16, 16, 16, 16, |
|
// 216 - 223 |
|
10257, 10257, 10257, 10257, 12305, 12305, 12305, 12305, |
|
// 224 - 231 |
|
330, 330, 330, 330, 330, 330, 330, 330, |
|
// 232 - 239 |
|
330, 330, 330, 330, 330, 330, 330, 330, |
|
// 240 - 247 |
|
330, 330, 330, 330, 330, 330, 330, 330, |
|
// 248 - 255 |
|
330, 330, 330, 330, 330, 330, 330, 330, |
|
// 256 - 263 |
|
362, 362, 362, 362, 362, 362, 362, 362, |
|
// 264 - 271 |
|
362, 362, 362, 362, 362, 362, 362, 362, |
|
// 272 - 279 |
|
362, 362, 362, 362, 362, 362, 362, 362, |
|
// 280 - 287 |
|
362, 362, 362, 362, 362, 362, 362, 362, |
|
// 288 - 295 |
|
878, 878, 878, 878, 878, 878, 878, 878, |
|
// 296 - 303 |
|
1904, 1904, 1904, 1904, 1936, 1936, 1936, 1936, |
|
// 304 - 311 |
|
-18413, -18413, -16365, -16365, -14317, -14317, -10221, -10221, |
|
// 312 - 319 |
|
590, 590, 590, 590, 590, 590, 590, 590, |
|
// 320 - 327 |
|
782, 782, 782, 782, 782, 782, 782, 782, |
|
// 328 - 335 |
|
1584, 1584, 1584, 1584, 1616, 1616, 1616, 1616, |
|
// 336 - 343 |
|
1648, 1648, 1648, 1648, 1680, 1680, 1680, 1680, |
|
// 344 - 351 |
|
814, 814, 814, 814, 814, 814, 814, 814, |
|
// 352 - 359 |
|
1776, 1776, 1776, 1776, 1808, 1808, 1808, 1808, |
|
// 360 - 367 |
|
1840, 1840, 1840, 1840, 1872, 1872, 1872, 1872, |
|
// 368 - 375 |
|
6157, 6157, 6157, 6157, 6157, 6157, 6157, 6157, |
|
// 376 - 383 |
|
6157, 6157, 6157, 6157, 6157, 6157, 6157, 6157, |
|
// 384 - 391 |
|
-12275, -12275, -12275, -12275, -12275, -12275, -12275, -12275, |
|
// 392 - 399 |
|
-12275, -12275, -12275, -12275, -12275, -12275, -12275, -12275, |
|
// 400 - 407 |
|
14353, 14353, 14353, 14353, 16401, 16401, 16401, 16401, |
|
// 408 - 415 |
|
22547, 22547, 24595, 24595, 20497, 20497, 20497, 20497, |
|
// 416 - 423 |
|
18449, 18449, 18449, 18449, 26643, 26643, 28691, 28691, |
|
// 424 - 431 |
|
30739, 30739, -32749, -32749, -30701, -30701, -28653, -28653, |
|
// 432 - 439 |
|
-26605, -26605, -24557, -24557, -22509, -22509, -20461, -20461, |
|
// 440 - 447 |
|
8207, 8207, 8207, 8207, 8207, 8207, 8207, 8207, |
|
// 448 - 455 |
|
72, 72, 72, 72, 72, 72, 72, 72, |
|
// 456 - 463 |
|
72, 72, 72, 72, 72, 72, 72, 72, |
|
// 464 - 471 |
|
72, 72, 72, 72, 72, 72, 72, 72, |
|
// 472 - 479 |
|
72, 72, 72, 72, 72, 72, 72, 72, |
|
// 480 - 487 |
|
72, 72, 72, 72, 72, 72, 72, 72, |
|
// 488 - 495 |
|
72, 72, 72, 72, 72, 72, 72, 72, |
|
// 496 - 503 |
|
72, 72, 72, 72, 72, 72, 72, 72, |
|
// 504 - 511 |
|
72, 72, 72, 72, 72, 72, 72, 72, |
|
// 512 - 519 |
|
104, 104, 104, 104, 104, 104, 104, 104, |
|
// 520 - 527 |
|
104, 104, 104, 104, 104, 104, 104, 104, |
|
// 528 - 535 |
|
104, 104, 104, 104, 104, 104, 104, 104, |
|
// 536 - 543 |
|
104, 104, 104, 104, 104, 104, 104, 104, |
|
// 544 - 551 |
|
104, 104, 104, 104, 104, 104, 104, 104, |
|
// 552 - 559 |
|
104, 104, 104, 104, 104, 104, 104, 104, |
|
// 560 - 567 |
|
104, 104, 104, 104, 104, 104, 104, 104, |
|
// 568 - 575 |
|
104, 104, 104, 104, 104, 104, 104, 104, |
|
// 576 - 583 |
|
4107, 4107, 4107, 4107, 4107, 4107, 4107, 4107, |
|
// 584 - 591 |
|
4107, 4107, 4107, 4107, 4107, 4107, 4107, 4107, |
|
// 592 - 599 |
|
4107, 4107, 4107, 4107, 4107, 4107, 4107, 4107, |
|
// 600 - 607 |
|
4107, 4107, 4107, 4107, 4107, 4107, 4107, 4107, |
|
// 608 - 615 |
|
266, 266, 266, 266, 266, 266, 266, 266, |
|
// 616 - 623 |
|
266, 266, 266, 266, 266, 266, 266, 266, |
|
// 624 - 631 |
|
266, 266, 266, 266, 266, 266, 266, 266, |
|
// 632 - 639 |
|
266, 266, 266, 266, 266, 266, 266, 266, |
|
// 640 - 647 |
|
298, 298, 298, 298, 298, 298, 298, 298, |
|
// 648 - 655 |
|
298, 298, 298, 298, 298, 298, 298, 298, |
|
// 656 - 663 |
|
298, 298, 298, 298, 298, 298, 298, 298, |
|
// 664 - 671 |
|
298, 298, 298, 298, 298, 298, 298, 298, |
|
// 672 - 679 |
|
524, 524, 524, 524, 524, 524, 524, 524, |
|
// 680 - 687 |
|
524, 524, 524, 524, 524, 524, 524, 524, |
|
// 688 - 695 |
|
556, 556, 556, 556, 556, 556, 556, 556, |
|
// 696 - 703 |
|
556, 556, 556, 556, 556, 556, 556, 556, |
|
// 704 - 711 |
|
136, 136, 136, 136, 136, 136, 136, 136, |
|
// 712 - 719 |
|
136, 136, 136, 136, 136, 136, 136, 136, |
|
// 720 - 727 |
|
136, 136, 136, 136, 136, 136, 136, 136, |
|
// 728 - 735 |
|
136, 136, 136, 136, 136, 136, 136, 136, |
|
// 736 - 743 |
|
136, 136, 136, 136, 136, 136, 136, 136, |
|
// 744 - 751 |
|
136, 136, 136, 136, 136, 136, 136, 136, |
|
// 752 - 759 |
|
136, 136, 136, 136, 136, 136, 136, 136, |
|
// 760 - 767 |
|
136, 136, 136, 136, 136, 136, 136, 136, |
|
// 768 - 775 |
|
168, 168, 168, 168, 168, 168, 168, 168, |
|
// 776 - 783 |
|
168, 168, 168, 168, 168, 168, 168, 168, |
|
// 784 - 791 |
|
168, 168, 168, 168, 168, 168, 168, 168, |
|
// 792 - 799 |
|
168, 168, 168, 168, 168, 168, 168, 168, |
|
// 800 - 807 |
|
168, 168, 168, 168, 168, 168, 168, 168, |
|
// 808 - 815 |
|
168, 168, 168, 168, 168, 168, 168, 168, |
|
// 816 - 823 |
|
168, 168, 168, 168, 168, 168, 168, 168, |
|
// 824 - 831 |
|
168, 168, 168, 168, 168, 168, 168, 168, |
|
// 832 - 839 |
|
460, 460, 460, 460, 460, 460, 460, 460, |
|
// 840 - 847 |
|
460, 460, 460, 460, 460, 460, 460, 460, |
|
// 848 - 855 |
|
492, 492, 492, 492, 492, 492, 492, 492, |
|
// 856 - 863 |
|
492, 492, 492, 492, 492, 492, 492, 492, |
|
// 864 - 871 |
|
2059, 2059, 2059, 2059, 2059, 2059, 2059, 2059, |
|
// 872 - 879 |
|
2059, 2059, 2059, 2059, 2059, 2059, 2059, 2059, |
|
// 880 - 887 |
|
2059, 2059, 2059, 2059, 2059, 2059, 2059, 2059, |
|
// 888 - 895 |
|
2059, 2059, 2059, 2059, 2059, 2059, 2059, 2059, |
|
// 896 - 903 |
|
200, 200, 200, 200, 200, 200, 200, 200, |
|
// 904 - 911 |
|
200, 200, 200, 200, 200, 200, 200, 200, |
|
// 912 - 919 |
|
200, 200, 200, 200, 200, 200, 200, 200, |
|
// 920 - 927 |
|
200, 200, 200, 200, 200, 200, 200, 200, |
|
// 928 - 935 |
|
200, 200, 200, 200, 200, 200, 200, 200, |
|
// 936 - 943 |
|
200, 200, 200, 200, 200, 200, 200, 200, |
|
// 944 - 951 |
|
200, 200, 200, 200, 200, 200, 200, 200, |
|
// 952 - 959 |
|
200, 200, 200, 200, 200, 200, 200, 200, |
|
// 960 - 967 |
|
232, 232, 232, 232, 232, 232, 232, 232, |
|
// 968 - 975 |
|
232, 232, 232, 232, 232, 232, 232, 232, |
|
// 976 - 983 |
|
232, 232, 232, 232, 232, 232, 232, 232, |
|
// 984 - 991 |
|
232, 232, 232, 232, 232, 232, 232, 232, |
|
// 992 - 999 |
|
232, 232, 232, 232, 232, 232, 232, 232, |
|
// 1000 - 1007 |
|
232, 232, 232, 232, 232, 232, 232, 232, |
|
// 1008 - 1015 |
|
232, 232, 232, 232, 232, 232, 232, 232, |
|
// 1016 - 1023 |
|
232, 232, 232, 232, 232, 232, 232, 232, |
|
}; |
|
|
|
// Additional make up codes for both White and Black runs |
|
static short additionalMakeup[] = { |
|
28679, 28679, 31752, (short)32777, |
|
(short)33801, (short)34825, (short)35849, (short)36873, |
|
(short)29703, (short)29703, (short)30727, (short)30727, |
|
(short)37897, (short)38921, (short)39945, (short)40969 |
|
}; |
|
|
|
// Initial black run look up table, uses the first 4 bits of a code |
|
static short initBlack[] = { |
|
// 0 - 7 |
|
3226, 6412, 200, 168, 38, 38, 134, 134, |
|
// 8 - 15 |
|
100, 100, 100, 100, 68, 68, 68, 68 |
|
}; |
|
|
|
// |
|
static short twoBitBlack[] = {292, 260, 226, 226}; // 0 - 3 |
|
|
|
// Main black run table, using the last 9 bits of possible 13 bit code |
|
static short black[] = { |
|
// 0 - 7 |
|
62, 62, 30, 30, 0, 0, 0, 0, |
|
// 8 - 15 |
|
0, 0, 0, 0, 0, 0, 0, 0, |
|
// 16 - 23 |
|
0, 0, 0, 0, 0, 0, 0, 0, |
|
// 24 - 31 |
|
0, 0, 0, 0, 0, 0, 0, 0, |
|
// 32 - 39 |
|
3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225, |
|
// 40 - 47 |
|
3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225, |
|
// 48 - 55 |
|
3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225, |
|
// 56 - 63 |
|
3225, 3225, 3225, 3225, 3225, 3225, 3225, 3225, |
|
// 64 - 71 |
|
588, 588, 588, 588, 588, 588, 588, 588, |
|
// 72 - 79 |
|
1680, 1680, 20499, 22547, 24595, 26643, 1776, 1776, |
|
// 80 - 87 |
|
1808, 1808, -24557, -22509, -20461, -18413, 1904, 1904, |
|
// 88 - 95 |
|
1936, 1936, -16365, -14317, 782, 782, 782, 782, |
|
// 96 - 103 |
|
814, 814, 814, 814, -12269, -10221, 10257, 10257, |
|
// 104 - 111 |
|
12305, 12305, 14353, 14353, 16403, 18451, 1712, 1712, |
|
// 112 - 119 |
|
1744, 1744, 28691, 30739, -32749, -30701, -28653, -26605, |
|
// 120 - 127 |
|
2061, 2061, 2061, 2061, 2061, 2061, 2061, 2061, |
|
// 128 - 135 |
|
424, 424, 424, 424, 424, 424, 424, 424, |
|
// 136 - 143 |
|
424, 424, 424, 424, 424, 424, 424, 424, |
|
// 144 - 151 |
|
424, 424, 424, 424, 424, 424, 424, 424, |
|
// 152 - 159 |
|
424, 424, 424, 424, 424, 424, 424, 424, |
|
// 160 - 167 |
|
750, 750, 750, 750, 1616, 1616, 1648, 1648, |
|
// 168 - 175 |
|
1424, 1424, 1456, 1456, 1488, 1488, 1520, 1520, |
|
// 176 - 183 |
|
1840, 1840, 1872, 1872, 1968, 1968, 8209, 8209, |
|
// 184 - 191 |
|
524, 524, 524, 524, 524, 524, 524, 524, |
|
// 192 - 199 |
|
556, 556, 556, 556, 556, 556, 556, 556, |
|
// 200 - 207 |
|
1552, 1552, 1584, 1584, 2000, 2000, 2032, 2032, |
|
// 208 - 215 |
|
976, 976, 1008, 1008, 1040, 1040, 1072, 1072, |
|
// 216 - 223 |
|
1296, 1296, 1328, 1328, 718, 718, 718, 718, |
|
// 224 - 231 |
|
456, 456, 456, 456, 456, 456, 456, 456, |
|
// 232 - 239 |
|
456, 456, 456, 456, 456, 456, 456, 456, |
|
// 240 - 247 |
|
456, 456, 456, 456, 456, 456, 456, 456, |
|
// 248 - 255 |
|
456, 456, 456, 456, 456, 456, 456, 456, |
|
// 256 - 263 |
|
326, 326, 326, 326, 326, 326, 326, 326, |
|
// 264 - 271 |
|
326, 326, 326, 326, 326, 326, 326, 326, |
|
// 272 - 279 |
|
326, 326, 326, 326, 326, 326, 326, 326, |
|
// 280 - 287 |
|
326, 326, 326, 326, 326, 326, 326, 326, |
|
// 288 - 295 |
|
326, 326, 326, 326, 326, 326, 326, 326, |
|
// 296 - 303 |
|
326, 326, 326, 326, 326, 326, 326, 326, |
|
// 304 - 311 |
|
326, 326, 326, 326, 326, 326, 326, 326, |
|
// 312 - 319 |
|
326, 326, 326, 326, 326, 326, 326, 326, |
|
// 320 - 327 |
|
358, 358, 358, 358, 358, 358, 358, 358, |
|
// 328 - 335 |
|
358, 358, 358, 358, 358, 358, 358, 358, |
|
// 336 - 343 |
|
358, 358, 358, 358, 358, 358, 358, 358, |
|
// 344 - 351 |
|
358, 358, 358, 358, 358, 358, 358, 358, |
|
// 352 - 359 |
|
358, 358, 358, 358, 358, 358, 358, 358, |
|
// 360 - 367 |
|
358, 358, 358, 358, 358, 358, 358, 358, |
|
// 368 - 375 |
|
358, 358, 358, 358, 358, 358, 358, 358, |
|
// 376 - 383 |
|
358, 358, 358, 358, 358, 358, 358, 358, |
|
// 384 - 391 |
|
490, 490, 490, 490, 490, 490, 490, 490, |
|
// 392 - 399 |
|
490, 490, 490, 490, 490, 490, 490, 490, |
|
// 400 - 407 |
|
4113, 4113, 6161, 6161, 848, 848, 880, 880, |
|
// 408 - 415 |
|
912, 912, 944, 944, 622, 622, 622, 622, |
|
// 416 - 423 |
|
654, 654, 654, 654, 1104, 1104, 1136, 1136, |
|
// 424 - 431 |
|
1168, 1168, 1200, 1200, 1232, 1232, 1264, 1264, |
|
// 432 - 439 |
|
686, 686, 686, 686, 1360, 1360, 1392, 1392, |
|
// 440 - 447 |
|
12, 12, 12, 12, 12, 12, 12, 12, |
|
// 448 - 455 |
|
390, 390, 390, 390, 390, 390, 390, 390, |
|
// 456 - 463 |
|
390, 390, 390, 390, 390, 390, 390, 390, |
|
// 464 - 471 |
|
390, 390, 390, 390, 390, 390, 390, 390, |
|
// 472 - 479 |
|
390, 390, 390, 390, 390, 390, 390, 390, |
|
// 480 - 487 |
|
390, 390, 390, 390, 390, 390, 390, 390, |
|
// 488 - 495 |
|
390, 390, 390, 390, 390, 390, 390, 390, |
|
// 496 - 503 |
|
390, 390, 390, 390, 390, 390, 390, 390, |
|
// 504 - 511 |
|
390, 390, 390, 390, 390, 390, 390, 390, |
|
}; |
|
|
|
static byte twoDCodes[] = { |
|
// 0 - 7 |
|
80, 88, 23, 71, 30, 30, 62, 62, |
|
// 8 - 15 |
|
4, 4, 4, 4, 4, 4, 4, 4, |
|
// 16 - 23 |
|
11, 11, 11, 11, 11, 11, 11, 11, |
|
// 24 - 31 |
|
11, 11, 11, 11, 11, 11, 11, 11, |
|
// 32 - 39 |
|
35, 35, 35, 35, 35, 35, 35, 35, |
|
// 40 - 47 |
|
35, 35, 35, 35, 35, 35, 35, 35, |
|
// 48 - 55 |
|
51, 51, 51, 51, 51, 51, 51, 51, |
|
// 56 - 63 |
|
51, 51, 51, 51, 51, 51, 51, 51, |
|
// 64 - 71 |
|
41, 41, 41, 41, 41, 41, 41, 41, |
|
// 72 - 79 |
|
41, 41, 41, 41, 41, 41, 41, 41, |
|
// 80 - 87 |
|
41, 41, 41, 41, 41, 41, 41, 41, |
|
// 88 - 95 |
|
41, 41, 41, 41, 41, 41, 41, 41, |
|
// 96 - 103 |
|
41, 41, 41, 41, 41, 41, 41, 41, |
|
// 104 - 111 |
|
41, 41, 41, 41, 41, 41, 41, 41, |
|
// 112 - 119 |
|
41, 41, 41, 41, 41, 41, 41, 41, |
|
// 120 - 127 |
|
41, 41, 41, 41, 41, 41, 41, 41, |
|
}; |
|
|
|
/** |
|
* @param fillOrder The fill order of the compressed data bytes. |
|
* @param compData Array containing compressed data. |
|
* @param w |
|
* @param h |
|
*/ |
|
public TIFFFaxDecoder(int fillOrder, int w, int h) { |
|
this.fillOrder = fillOrder; |
|
this.w = w; |
|
this.h = h; |
|
|
|
this.bitPointer = 0; |
|
this.bytePointer = 0; |
|
this.prevChangingElems = new int[w]; |
|
this.currChangingElems = new int[w]; |
|
} |
|
|
|
// One-dimensional decoding methods |
|
|
|
public void decode1D(byte[] buffer, byte[] compData, |
|
int startX, int height) { |
|
this.data = compData; |
|
|
|
int lineOffset = 0; |
|
int scanlineStride = (w + 7)/8; |
|
|
|
bitPointer = 0; |
|
bytePointer = 0; |
|
|
|
for (int i = 0; i < height; i++) { |
|
decodeNextScanline(buffer, lineOffset, startX); |
|
lineOffset += scanlineStride; |
|
} |
|
} |
|
|
|
public void decodeNextScanline(byte[] buffer, |
|
int lineOffset, int bitOffset) { |
|
int bits = 0, code = 0, isT = 0; |
|
int current, entry, twoBits; |
|
boolean isWhite = true; |
|
int dstEnd = 0; |
|
|
|
// Initialize starting of the changing elements array |
|
changingElemSize = 0; |
|
|
|
// While scanline not complete |
|
while (bitOffset < w) { |
|
while (isWhite) { |
|
// White run |
|
current = nextNBits(10); |
|
entry = white[current]; |
|
|
|
// Get the 3 fields from the entry |
|
isT = entry & 0x0001; |
|
bits = (entry >>> 1) & 0x0f; |
|
|
|
if (bits == 12) { // Additional Make up code |
|
// Get the next 2 bits |
|
twoBits = nextLesserThan8Bits(2); |
|
// Consolidate the 2 new bits and last 2 bits into 4 bits |
|
current = ((current << 2) & 0x000c) | twoBits; |
|
entry = additionalMakeup[current]; |
|
bits = (entry >>> 1) & 0x07; // 3 bits 0000 0111 |
|
code = (entry >>> 4) & 0x0fff; // 12 bits |
|
bitOffset += code; // Skip white run |
|
|
|
updatePointer(4 - bits); |
|
} else if (bits == 0) { // ERROR |
|
throw new Error(JaiI18N.getString("TIFFFaxDecoder0")); |
|
} else if (bits == 15) { // EOL |
|
throw new Error(JaiI18N.getString("TIFFFaxDecoder1")); |
|
} else { |
|
// 11 bits - 0000 0111 1111 1111 = 0x07ff |
|
code = (entry >>> 5) & 0x07ff; |
|
bitOffset += code; |
|
|
|
updatePointer(10 - bits); |
|
if (isT == 0) { |
|
isWhite = false; |
|
currChangingElems[changingElemSize++] = bitOffset; |
|
} |
|
} |
|
} |
|
|
|
// Check whether this run completed one width, if so |
|
// advance to next byte boundary for compression = 2. |
|
if (bitOffset == w) { |
|
if (compression == 2) { |
|
advancePointer(); |
|
} |
|
break; |
|
} |
|
|
|
while (isWhite == false) { |
|
// Black run |
|
current = nextLesserThan8Bits(4); |
|
entry = initBlack[current]; |
|
|
|
// Get the 3 fields from the entry |
|
isT = entry & 0x0001; |
|
bits = (entry >>> 1) & 0x000f; |
|
code = (entry >>> 5) & 0x07ff; |
|
|
|
if (code == 100) { |
|
current = nextNBits(9); |
|
entry = black[current]; |
|
|
|
// Get the 3 fields from the entry |
|
isT = entry & 0x0001; |
|
bits = (entry >>> 1) & 0x000f; |
|
code = (entry >>> 5) & 0x07ff; |
|
|
|
if (bits == 12) { |
|
// Additional makeup codes |
|
updatePointer(5); |
|
current = nextLesserThan8Bits(4); |
|
entry = additionalMakeup[current]; |
|
bits = (entry >>> 1) & 0x07; // 3 bits 0000 0111 |
|
code = (entry >>> 4) & 0x0fff; // 12 bits |
|
|
|
setToBlack(buffer, lineOffset, bitOffset, code); |
|
bitOffset += code; |
|
|
|
updatePointer(4 - bits); |
|
} else if (bits == 15) { |
|
// EOL code |
|
throw new Error(JaiI18N.getString("TIFFFaxDecoder2")); |
|
} else { |
|
setToBlack(buffer, lineOffset, bitOffset, code); |
|
bitOffset += code; |
|
|
|
updatePointer(9 - bits); |
|
if (isT == 0) { |
|
isWhite = true; |
|
currChangingElems[changingElemSize++] = bitOffset; |
|
} |
|
} |
|
} else if (code == 200) { |
|
// Is a Terminating code |
|
current = nextLesserThan8Bits(2); |
|
entry = twoBitBlack[current]; |
|
code = (entry >>> 5) & 0x07ff; |
|
bits = (entry >>> 1) & 0x0f; |
|
|
|
setToBlack(buffer, lineOffset, bitOffset, code); |
|
bitOffset += code; |
|
|
|
updatePointer(2 - bits); |
|
isWhite = true; |
|
currChangingElems[changingElemSize++] = bitOffset; |
|
} else { |
|
// Is a Terminating code |
|
setToBlack(buffer, lineOffset, bitOffset, code); |
|
bitOffset += code; |
|
|
|
updatePointer(4 - bits); |
|
isWhite = true; |
|
currChangingElems[changingElemSize++] = bitOffset; |
|
} |
|
} |
|
|
|
// Check whether this run completed one width |
|
if (bitOffset == w) { |
|
if (compression == 2) { |
|
advancePointer(); |
|
} |
|
break; |
|
} |
|
} |
|
|
|
currChangingElems[changingElemSize++] = bitOffset; |
|
} |
|
|
|
// Two-dimensional decoding methods |
|
|
|
public void decode2D(byte[] buffer, |
|
byte compData[], |
|
int startX, |
|
int height, |
|
long tiffT4Options) { |
|
this.data = compData; |
|
compression = 3; |
|
|
|
bitPointer = 0; |
|
bytePointer = 0; |
|
|
|
int scanlineStride = (w + 7)/8; |
|
|
|
int a0, a1, b1, b2; |
|
int[] b = new int[2]; |
|
int entry, code, bits, color; |
|
boolean isWhite; |
|
int currIndex = 0; |
|
int temp[]; |
|
|
|
// fillBits - dealt with this in readEOL |
|
// 1D/2D encoding - dealt with this in readEOL |
|
|
|
// uncompressedMode - haven't dealt with this yet. |
|
|
|
|
|
oneD = (int)(tiffT4Options & 0x01); |
|
uncompressedMode = (int)((tiffT4Options & 0x02) >> 1); |
|
fillBits = (int)((tiffT4Options & 0x04) >> 2); |
|
|
|
// The data must start with an EOL code |
|
if (readEOL(true) != 1) { |
|
throw new Error(JaiI18N.getString("TIFFFaxDecoder3")); |
|
} |
|
|
|
int lineOffset = 0; |
|
int bitOffset; |
|
|
|
// Then the 1D encoded scanline data will occur, changing elements |
|
// array gets set. |
|
decodeNextScanline(buffer, lineOffset, startX); |
|
lineOffset += scanlineStride; |
|
|
|
for (int lines = 1; lines < height; lines++) { |
|
|
|
// Every line must begin with an EOL followed by a bit which |
|
// indicates whether the following scanline is 1D or 2D encoded. |
|
if (readEOL(false) == 0) { |
|
// 2D encoded scanline follows |
|
|
|
// Initialize previous scanlines changing elements, and |
|
// initialize current scanline's changing elements array |
|
temp = prevChangingElems; |
|
prevChangingElems = currChangingElems; |
|
currChangingElems = temp; |
|
currIndex = 0; |
|
|
|
// a0 has to be set just before the start of this scanline. |
|
a0 = -1; |
|
isWhite = true; |
|
bitOffset = startX; |
|
|
|
lastChangingElement = 0; |
|
|
|
while (bitOffset < w) { |
|
// Get the next changing element |
|
getNextChangingElement(a0, isWhite, b); |
|
|
|
b1 = b[0]; |
|
b2 = b[1]; |
|
|
|
// Get the next seven bits |
|
entry = nextLesserThan8Bits(7); |
|
|
|
// Run these through the 2DCodes table |
|
entry = (int)(twoDCodes[entry] & 0xff); |
|
|
|
// Get the code and the number of bits used up |
|
code = (entry & 0x78) >>> 3; |
|
bits = entry & 0x07; |
|
|
|
if (code == 0) { |
|
if (!isWhite) { |
|
setToBlack(buffer, lineOffset, bitOffset, |
|
b2 - bitOffset); |
|
} |
|
bitOffset = a0 = b2; |
|
|
|
// Set pointer to consume the correct number of bits. |
|
updatePointer(7 - bits); |
|
} else if (code == 1) { |
|
// Horizontal |
|
updatePointer(7 - bits); |
|
|
|
// identify the next 2 codes. |
|
int number; |
|
if (isWhite) { |
|
number = decodeWhiteCodeWord(); |
|
bitOffset += number; |
|
currChangingElems[currIndex++] = bitOffset; |
|
|
|
number = decodeBlackCodeWord(); |
|
setToBlack(buffer, lineOffset, bitOffset, number); |
|
bitOffset += number; |
|
currChangingElems[currIndex++] = bitOffset; |
|
} else { |
|
number = decodeBlackCodeWord(); |
|
setToBlack(buffer, lineOffset, bitOffset, number); |
|
bitOffset += number; |
|
currChangingElems[currIndex++] = bitOffset; |
|
|
|
number = decodeWhiteCodeWord(); |
|
bitOffset += number; |
|
currChangingElems[currIndex++] = bitOffset; |
|
} |
|
|
|
a0 = bitOffset; |
|
} else if (code <= 8) { |
|
// Vertical |
|
a1 = b1 + (code - 5); |
|
|
|
currChangingElems[currIndex++] = a1; |
|
|
|
// We write the current color till a1 - 1 pos, |
|
// since a1 is where the next color starts |
|
if (!isWhite) { |
|
setToBlack(buffer, lineOffset, bitOffset, |
|
a1 - bitOffset); |
|
} |
|
bitOffset = a0 = a1; |
|
isWhite = !isWhite; |
|
|
|
updatePointer(7 - bits); |
|
} else { |
|
throw new Error(JaiI18N.getString("TIFFFaxDecoder4")); |
|
} |
|
} |
|
|
|
// Add the changing element beyond the current scanline for the |
|
// other color too |
|
currChangingElems[currIndex++] = bitOffset; |
|
changingElemSize = currIndex; |
|
} else { |
|
// 1D encoded scanline follows |
|
decodeNextScanline(buffer, lineOffset, startX); |
|
} |
|
|
|
lineOffset += scanlineStride; |
|
} |
|
} |
|
|
|
public synchronized void decodeT6(byte[] buffer, |
|
byte[] compData, |
|
int startX, |
|
int height, |
|
long tiffT6Options) { |
|
this.data = compData; |
|
compression = 4; |
|
|
|
bitPointer = 0; |
|
bytePointer = 0; |
|
|
|
int scanlineStride = (w + 7)/8; |
|
int bufferOffset = 0; |
|
|
|
int a0, a1, b1, b2; |
|
int entry, code, bits; |
|
byte color; |
|
boolean isWhite; |
|
int currIndex; |
|
int temp[]; |
|
|
|
// Return values from getNextChangingElement |
|
int[] b = new int[2]; |
|
|
|
// uncompressedMode - have written some code for this, but this |
|
// has not been tested due to lack of test images using this optional |
|
|
|
uncompressedMode = (int)((tiffT6Options & 0x02) >> 1); |
|
|
|
// Local cached reference |
|
int[] cce = currChangingElems; |
|
|
|
// Assume invisible preceding row of all white pixels and insert |
|
// both black and white changing elements beyond the end of this |
|
// imaginary scanline. |
|
changingElemSize = 0; |
|
cce[changingElemSize++] = w; |
|
cce[changingElemSize++] = w; |
|
|
|
int lineOffset = 0; |
|
int bitOffset; |
|
|
|
for (int lines = 0; lines < height; lines++) { |
|
// a0 has to be set just before the start of the scanline. |
|
a0 = -1; |
|
isWhite = true; |
|
|
|
// Assign the changing elements of the previous scanline to |
|
// prevChangingElems and start putting this new scanline's |
|
// changing elements into the currChangingElems. |
|
temp = prevChangingElems; |
|
prevChangingElems = currChangingElems; |
|
cce = currChangingElems = temp; |
|
currIndex = 0; |
|
|
|
// Start decoding the scanline at startX in the raster |
|
bitOffset = startX; |
|
|
|
// Reset search start position for getNextChangingElement |
|
lastChangingElement = 0; |
|
|
|
// Till one whole scanline is decoded |
|
while (bitOffset < w) { |
|
// Get the next changing element |
|
getNextChangingElement(a0, isWhite, b); |
|
b1 = b[0]; |
|
b2 = b[1]; |
|
|
|
// Get the next seven bits |
|
entry = nextLesserThan8Bits(7); |
|
// Run these through the 2DCodes table |
|
entry = (int)(twoDCodes[entry] & 0xff); |
|
|
|
// Get the code and the number of bits used up |
|
code = (entry & 0x78) >>> 3; |
|
bits = entry & 0x07; |
|
|
|
if (code == 0) { // Pass |
|
// We always assume WhiteIsZero format for fax. |
|
if (!isWhite) { |
|
setToBlack(buffer, lineOffset, bitOffset, |
|
b2 - bitOffset); |
|
} |
|
bitOffset = a0 = b2; |
|
|
|
// Set pointer to only consume the correct number of bits. |
|
updatePointer(7 - bits); |
|
} else if (code == 1) { // Horizontal |
|
// Set pointer to only consume the correct number of bits. |
|
updatePointer(7 - bits); |
|
|
|
// identify the next 2 alternating color codes. |
|
int number; |
|
if (isWhite) { |
|
// Following are white and black runs |
|
number = decodeWhiteCodeWord(); |
|
bitOffset += number; |
|
cce[currIndex++] = bitOffset; |
|
|
|
number = decodeBlackCodeWord(); |
|
setToBlack(buffer, lineOffset, bitOffset, number); |
|
bitOffset += number; |
|
cce[currIndex++] = bitOffset; |
|
} else { |
|
// First a black run and then a white run follows |
|
number = decodeBlackCodeWord(); |
|
setToBlack(buffer, lineOffset, bitOffset, number); |
|
bitOffset += number; |
|
cce[currIndex++] = bitOffset; |
|
|
|
number = decodeWhiteCodeWord(); |
|
bitOffset += number; |
|
cce[currIndex++] = bitOffset; |
|
} |
|
|
|
a0 = bitOffset; |
|
} else if (code <= 8) { // Vertical |
|
a1 = b1 + (code - 5); |
|
cce[currIndex++] = a1; |
|
|
|
// We write the current color till a1 - 1 pos, |
|
// since a1 is where the next color starts |
|
if (!isWhite) { |
|
setToBlack(buffer, lineOffset, bitOffset, |
|
a1 - bitOffset); |
|
} |
|
bitOffset = a0 = a1; |
|
isWhite = !isWhite; |
|
|
|
updatePointer(7 - bits); |
|
} else if (code == 11) { |
|
if (nextLesserThan8Bits(3) != 7) { |
|
throw new Error(JaiI18N.getString("TIFFFaxDecoder5")); |
|
} |
|
|
|
int zeros = 0; |
|
boolean exit = false; |
|
|
|
while (!exit) { |
|
while (nextLesserThan8Bits(1) != 1) { |
|
zeros++; |
|
} |
|
|
|
if (zeros > 5) { |
|
// Exit code |
|
|
|
// Zeros before exit code |
|
zeros = zeros - 6; |
|
|
|
if (!isWhite && (zeros > 0)) { |
|
cce[currIndex++] = bitOffset; |
|
} |
|
|
|
// Zeros before the exit code |
|
bitOffset += zeros; |
|
if (zeros > 0) { |
|
// Some zeros have been written |
|
isWhite = true; |
|
} |
|
|
|
// Read in the bit which specifies the color of |
|
// the following run |
|
if (nextLesserThan8Bits(1) == 0) { |
|
if (!isWhite) { |
|
cce[currIndex++] = bitOffset; |
|
} |
|
isWhite = true; |
|
} else { |
|
if (isWhite) { |
|
cce[currIndex++] = bitOffset; |
|
} |
|
isWhite = false; |
|
} |
|
|
|
exit = true; |
|
} |
|
|
|
if (zeros == 5) { |
|
if (!isWhite) { |
|
cce[currIndex++] = bitOffset; |
|
} |
|
bitOffset += zeros; |
|
|
|
// Last thing written was white |
|
isWhite = true; |
|
} else { |
|
bitOffset += zeros; |
|
|
|
cce[currIndex++] = bitOffset; |
|
setToBlack(buffer, lineOffset, bitOffset, 1); |
|
++bitOffset; |
|
|
|
// Last thing written was black |
|
isWhite = false; |
|
} |
|
|
|
} |
|
} else { |
|
throw new Error(JaiI18N.getString("TIFFFaxDecoder5")); |
|
} |
|
} |
|
|
|
// Add the changing element beyond the current scanline for the |
|
// other color too |
|
cce[currIndex++] = bitOffset; |
|
|
|
// Number of changing elements in this scanline. |
|
changingElemSize = currIndex; |
|
|
|
lineOffset += scanlineStride; |
|
} |
|
} |
|
|
|
private void setToBlack(byte[] buffer, |
|
int lineOffset, int bitOffset, |
|
int numBits) { |
|
int bitNum = 8*lineOffset + bitOffset; |
|
int lastBit = bitNum + numBits; |
|
|
|
int byteNum = bitNum >> 3; |
|
|
|
// Handle bits in first byte |
|
int shift = bitNum & 0x7; |
|
if (shift > 0) { |
|
int maskVal = 1 << (7 - shift); |
|
byte val = buffer[byteNum]; |
|
while (maskVal > 0 && bitNum < lastBit) { |
|
val |= maskVal; |
|
maskVal >>= 1; |
|
++bitNum; |
|
} |
|
buffer[byteNum] = val; |
|
} |
|
|
|
// Fill in 8 bits at a time |
|
byteNum = bitNum >> 3; |
|
while (bitNum < lastBit - 7) { |
|
buffer[byteNum++] = (byte)255; |
|
bitNum += 8; |
|
} |
|
|
|
// Fill in remaining bits |
|
while (bitNum < lastBit) { |
|
byteNum = bitNum >> 3; |
|
buffer[byteNum] |= 1 << (7 - (bitNum & 0x7)); |
|
++bitNum; |
|
} |
|
} |
|
|
|
// Returns run length |
|
private int decodeWhiteCodeWord() { |
|
int current, entry, bits, isT, twoBits, code = -1; |
|
int runLength = 0; |
|
boolean isWhite = true; |
|
|
|
while (isWhite) { |
|
current = nextNBits(10); |
|
entry = white[current]; |
|
|
|
// Get the 3 fields from the entry |
|
isT = entry & 0x0001; |
|
bits = (entry >>> 1) & 0x0f; |
|
|
|
if (bits == 12) { // Additional Make up code |
|
// Get the next 2 bits |
|
twoBits = nextLesserThan8Bits(2); |
|
// Consolidate the 2 new bits and last 2 bits into 4 bits |
|
current = ((current << 2) & 0x000c) | twoBits; |
|
entry = additionalMakeup[current]; |
|
bits = (entry >>> 1) & 0x07; // 3 bits 0000 0111 |
|
code = (entry >>> 4) & 0x0fff; // 12 bits |
|
runLength += code; |
|
updatePointer(4 - bits); |
|
} else if (bits == 0) { // ERROR |
|
throw new Error(JaiI18N.getString("TIFFFaxDecoder0")); |
|
} else if (bits == 15) { // EOL |
|
throw new Error(JaiI18N.getString("TIFFFaxDecoder1")); |
|
} else { |
|
// 11 bits - 0000 0111 1111 1111 = 0x07ff |
|
code = (entry >>> 5) & 0x07ff; |
|
runLength += code; |
|
updatePointer(10 - bits); |
|
if (isT == 0) { |
|
isWhite = false; |
|
} |
|
} |
|
} |
|
|
|
return runLength; |
|
} |
|
|
|
// Returns run length |
|
private int decodeBlackCodeWord() { |
|
int current, entry, bits, isT, twoBits, code = -1; |
|
int runLength = 0; |
|
boolean isWhite = false; |
|
|
|
while (!isWhite) { |
|
current = nextLesserThan8Bits(4); |
|
entry = initBlack[current]; |
|
|
|
// Get the 3 fields from the entry |
|
isT = entry & 0x0001; |
|
bits = (entry >>> 1) & 0x000f; |
|
code = (entry >>> 5) & 0x07ff; |
|
|
|
if (code == 100) { |
|
current = nextNBits(9); |
|
entry = black[current]; |
|
|
|
// Get the 3 fields from the entry |
|
isT = entry & 0x0001; |
|
bits = (entry >>> 1) & 0x000f; |
|
code = (entry >>> 5) & 0x07ff; |
|
|
|
if (bits == 12) { |
|
// Additional makeup codes |
|
updatePointer(5); |
|
current = nextLesserThan8Bits(4); |
|
entry = additionalMakeup[current]; |
|
bits = (entry >>> 1) & 0x07; // 3 bits 0000 0111 |
|
code = (entry >>> 4) & 0x0fff; // 12 bits |
|
runLength += code; |
|
|
|
updatePointer(4 - bits); |
|
} else if (bits == 15) { |
|
// EOL code |
|
throw new Error(JaiI18N.getString("TIFFFaxDecoder2")); |
|
} else { |
|
runLength += code; |
|
updatePointer(9 - bits); |
|
if (isT == 0) { |
|
isWhite = true; |
|
} |
|
} |
|
} else if (code == 200) { |
|
// Is a Terminating code |
|
current = nextLesserThan8Bits(2); |
|
entry = twoBitBlack[current]; |
|
code = (entry >>> 5) & 0x07ff; |
|
runLength += code; |
|
bits = (entry >>> 1) & 0x0f; |
|
updatePointer(2 - bits); |
|
isWhite = true; |
|
} else { |
|
// Is a Terminating code |
|
runLength += code; |
|
updatePointer(4 - bits); |
|
isWhite = true; |
|
} |
|
} |
|
|
|
return runLength; |
|
} |
|
|
|
private int readEOL(boolean isFirstEOL) { |
|
if (fillBits == 0) { |
|
int next12Bits = nextNBits(12); |
|
if (isFirstEOL && next12Bits == 0) { |
|
|
|
// Might have the case of EOL padding being used even |
|
// though it was not flagged in the T4Options field. |
|
// This was observed to be the case in TIFFs produced |
|
// by a well known vendor who shall remain nameless. |
|
|
|
if(nextNBits(4) == 1) { |
|
|
|
// EOL must be padded: reset the fillBits flag. |
|
|
|
fillBits = 1; |
|
return 1; |
|
} |
|
} |
|
if(next12Bits != 1) { |
|
throw new Error(JaiI18N.getString("TIFFFaxDecoder6")); |
|
} |
|
} else if (fillBits == 1) { |
|
|
|
// First EOL code word xxxx 0000 0000 0001 will occur |
|
// As many fill bits will be present as required to make |
|
// the EOL code of 12 bits end on a byte boundary. |
|
|
|
int bitsLeft = 8 - bitPointer; |
|
|
|
if (nextNBits(bitsLeft) != 0) { |
|
throw new Error(JaiI18N.getString("TIFFFaxDecoder8")); |
|
} |
|
|
|
// If the number of bitsLeft is less than 8, then to have a 12 |
|
// bit EOL sequence, two more bytes are certainly going to be |
|
// required. The first of them has to be all zeros, so ensure |
|
// that. |
|
if (bitsLeft < 4) { |
|
if (nextNBits(8) != 0) { |
|
throw new Error(JaiI18N.getString("TIFFFaxDecoder8")); |
|
} |
|
} |
|
|
|
// There might be a random number of fill bytes with 0s, so |
|
// loop till the EOL of 0000 0001 is found, as long as all |
|
// the bytes preceding it are 0's. |
|
int n; |
|
while ((n = nextNBits(8)) != 1) { |
|
|
|
// If not all zeros |
|
if (n != 0) { |
|
throw new Error(JaiI18N.getString("TIFFFaxDecoder8")); |
|
} |
|
} |
|
} |
|
|
|
// If one dimensional encoding mode, then always return 1 |
|
if (oneD == 0) { |
|
return 1; |
|
} else { |
|
// Otherwise for 2D encoding mode, |
|
// The next one bit signifies 1D/2D encoding of next line. |
|
return nextLesserThan8Bits(1); |
|
} |
|
} |
|
|
|
private void getNextChangingElement(int a0, boolean isWhite, int[] ret) { |
|
// Local copies of instance variables |
|
int[] pce = this.prevChangingElems; |
|
int ces = this.changingElemSize; |
|
|
|
// If the previous match was at an odd element, we still |
|
// have to search the preceeding element. |
|
// int start = lastChangingElement & ~0x1; |
|
int start = lastChangingElement > 0 ? lastChangingElement - 1 : 0; |
|
if (isWhite) { |
|
start &= ~0x1; // Search even numbered elements |
|
} else { |
|
start |= 0x1; // Search odd numbered elements |
|
} |
|
|
|
int i = start; |
|
for (; i < ces; i += 2) { |
|
int temp = pce[i]; |
|
if (temp > a0) { |
|
lastChangingElement = i; |
|
ret[0] = temp; |
|
break; |
|
} |
|
} |
|
|
|
if (i + 1 < ces) { |
|
ret[1] = pce[i + 1]; |
|
} |
|
} |
|
|
|
private int nextNBits(int bitsToGet) { |
|
byte b, next, next2next; |
|
int l = data.length - 1; |
|
int bp = this.bytePointer; |
|
|
|
if (fillOrder == 1) { |
|
b = data[bp]; |
|
|
|
if (bp == l) { |
|
next = 0x00; |
|
next2next = 0x00; |
|
} else if ((bp + 1) == l) { |
|
next = data[bp + 1]; |
|
next2next = 0x00; |
|
} else { |
|
next = data[bp + 1]; |
|
next2next = data[bp + 2]; |
|
} |
|
} else if (fillOrder == 2) { |
|
b = flipTable[data[bp] & 0xff]; |
|
|
|
if (bp == l) { |
|
next = 0x00; |
|
next2next = 0x00; |
|
} else if ((bp + 1) == l) { |
|
next = flipTable[data[bp + 1] & 0xff]; |
|
next2next = 0x00; |
|
} else { |
|
next = flipTable[data[bp + 1] & 0xff]; |
|
next2next = flipTable[data[bp + 2] & 0xff]; |
|
} |
|
} else { |
|
throw new Error(JaiI18N.getString("TIFFFaxDecoder7")); |
|
} |
|
|
|
int bitsLeft = 8 - bitPointer; |
|
int bitsFromNextByte = bitsToGet - bitsLeft; |
|
int bitsFromNext2NextByte = 0; |
|
if (bitsFromNextByte > 8) { |
|
bitsFromNext2NextByte = bitsFromNextByte - 8; |
|
bitsFromNextByte = 8; |
|
} |
|
|
|
bytePointer++; |
|
|
|
int i1 = (b & table1[bitsLeft]) << (bitsToGet - bitsLeft); |
|
int i2 = (next & table2[bitsFromNextByte]) >>> (8 - bitsFromNextByte); |
|
|
|
int i3 = 0; |
|
if (bitsFromNext2NextByte != 0) { |
|
i2 <<= bitsFromNext2NextByte; |
|
i3 = (next2next & table2[bitsFromNext2NextByte]) >>> |
|
(8 - bitsFromNext2NextByte); |
|
i2 |= i3; |
|
bytePointer++; |
|
bitPointer = bitsFromNext2NextByte; |
|
} else { |
|
if (bitsFromNextByte == 8) { |
|
bitPointer = 0; |
|
bytePointer++; |
|
} else { |
|
bitPointer = bitsFromNextByte; |
|
} |
|
} |
|
|
|
int i = i1 | i2; |
|
return i; |
|
} |
|
|
|
private int nextLesserThan8Bits(int bitsToGet) { |
|
byte b, next; |
|
int l = data.length - 1; |
|
int bp = this.bytePointer; |
|
|
|
if (fillOrder == 1) { |
|
b = data[bp]; |
|
if (bp == l) { |
|
next = 0x00; |
|
} else { |
|
next = data[bp + 1]; |
|
} |
|
} else if (fillOrder == 2) { |
|
b = flipTable[data[bp] & 0xff]; |
|
if (bp == l) { |
|
next = 0x00; |
|
} else { |
|
next = flipTable[data[bp + 1] & 0xff]; |
|
} |
|
} else { |
|
throw new Error(JaiI18N.getString("TIFFFaxDecoder7")); |
|
} |
|
|
|
int bitsLeft = 8 - bitPointer; |
|
int bitsFromNextByte = bitsToGet - bitsLeft; |
|
|
|
int shift = bitsLeft - bitsToGet; |
|
int i1, i2; |
|
if (shift >= 0) { |
|
i1 = (b & table1[bitsLeft]) >>> shift; |
|
bitPointer += bitsToGet; |
|
if (bitPointer == 8) { |
|
bitPointer = 0; |
|
bytePointer++; |
|
} |
|
} else { |
|
i1 = (b & table1[bitsLeft]) << (-shift); |
|
i2 = (next & table2[bitsFromNextByte]) >>> (8 - bitsFromNextByte); |
|
|
|
i1 |= i2; |
|
bytePointer++; |
|
bitPointer = bitsFromNextByte; |
|
} |
|
|
|
return i1; |
|
} |
|
|
|
// Move pointer backwards by given amount of bits |
|
private void updatePointer(int bitsToMoveBack) { |
|
int i = bitPointer - bitsToMoveBack; |
|
|
|
if (i < 0) { |
|
bytePointer--; |
|
bitPointer = 8 + i; |
|
} else { |
|
bitPointer = i; |
|
} |
|
} |
|
|
|
// Move to the next byte boundary |
|
private boolean advancePointer() { |
|
if (bitPointer != 0) { |
|
bytePointer++; |
|
bitPointer = 0; |
|
} |
|
|
|
return true; |
|
} |
|
} |
|
|
|
|