1576 lines
45 KiB
Java
1576 lines
45 KiB
Java
/*
|
|
* Based on the SUN code (see license beyond) changes are made to handle CCITTFax encoded
|
|
* data in a PDF image. This may or may not apply to real world CCITT documents.
|
|
*
|
|
* Copyright (c) 2007, intarsys consulting GmbH
|
|
*
|
|
* 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.
|
|
*
|
|
* - Redistributions in binary form must reproduce 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 intarsys nor the names of its contributors may be used
|
|
* to endorse or promote products derived from this software without specific
|
|
* prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
/*
|
|
* 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.sun.pdfview.decode;
|
|
|
|
public class CCITTFaxDecoder {
|
|
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, };
|
|
|
|
private int bitPointer;
|
|
|
|
private int bytePointer;
|
|
|
|
private byte[] data;
|
|
|
|
private int w;
|
|
|
|
private boolean align = false;
|
|
|
|
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 boolean fillBits = false;
|
|
|
|
/**
|
|
* @param fillOrder
|
|
* The fill order of the compressed data bytes.
|
|
* @param w
|
|
* @param h
|
|
*/
|
|
public CCITTFaxDecoder(int fillOrder, int w, int h) {
|
|
this.fillOrder = fillOrder;
|
|
this.w = w;
|
|
|
|
this.bitPointer = 0;
|
|
this.bytePointer = 0;
|
|
this.prevChangingElems = new int[w];
|
|
this.currChangingElems = new int[w];
|
|
}
|
|
|
|
private boolean align() {
|
|
if (align && bitPointer != 0) {
|
|
bytePointer++;
|
|
bitPointer = 0;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
protected boolean consumeEOL() {
|
|
// Get the next 12 bits.
|
|
int next12Bits = nextNBits(12);
|
|
if (next12Bits == 1) {
|
|
// EOL found & consumed
|
|
return true;
|
|
}
|
|
// no EOL - unread and return
|
|
updatePointer(12);
|
|
return false;
|
|
}
|
|
|
|
// Returns run length
|
|
private int decodeBlackCodeWord() {
|
|
int current;
|
|
int entry;
|
|
int bits;
|
|
int isT;
|
|
int 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 RuntimeException(
|
|
"EOL code word encountered in Black run."); //$NON-NLS-1$
|
|
} 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;
|
|
}
|
|
|
|
protected void decodeNextScanline(byte[] buffer, int lineOffset,
|
|
int bitOffset) {
|
|
int bits = 0;
|
|
int code = 0;
|
|
int isT = 0;
|
|
int current;
|
|
int entry;
|
|
int twoBits;
|
|
boolean isWhite = true;
|
|
|
|
// 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 RuntimeException("Invalid code encountered.");
|
|
} else if (bits == 15) {
|
|
// EOL recover
|
|
// move bits back...
|
|
updatePointer(10);
|
|
return;
|
|
} 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) {
|
|
align();
|
|
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 recover
|
|
// unread bits ???
|
|
updatePointer(9);
|
|
return;
|
|
} 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) {
|
|
align();
|
|
break;
|
|
}
|
|
}
|
|
|
|
currChangingElems[changingElemSize++] = bitOffset;
|
|
}
|
|
|
|
// One-dimensional decoding methods
|
|
public void decodeT41D(byte[] buffer, byte[] compData, int startX,
|
|
int height) {
|
|
this.data = compData;
|
|
int scanlineStride = (w + 7) / 8;
|
|
bitPointer = 0;
|
|
bytePointer = 0;
|
|
|
|
int lineOffset = 0;
|
|
for (int i = 0; i < height; i++) {
|
|
consumeEOL();
|
|
decodeNextScanline(buffer, lineOffset, startX);
|
|
lineOffset += scanlineStride;
|
|
}
|
|
}
|
|
|
|
// Two-dimensional decoding methods
|
|
public void decodeT42D(byte[] buffer, byte[] compData, int startX,
|
|
int height) {
|
|
this.data = compData;
|
|
int scanlineStride = (w + 7) / 8;
|
|
bitPointer = 0;
|
|
bytePointer = 0;
|
|
|
|
int a0;
|
|
int a1;
|
|
int b1;
|
|
int b2;
|
|
int[] b = new int[2];
|
|
int entry;
|
|
int code;
|
|
int bits;
|
|
boolean isWhite;
|
|
int currIndex = 0;
|
|
int[] temp;
|
|
|
|
// The data must start with an EOL code
|
|
if (readEOL(true) != 1) {
|
|
throw new RuntimeException("First scanline must be 1D encoded."); //$NON-NLS-1$
|
|
}
|
|
|
|
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 = (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 RuntimeException(
|
|
"Invalid code encountered while decoding 2D group 3 compressed data."); //$NON-NLS-1$
|
|
}
|
|
}
|
|
|
|
// 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) {
|
|
this.data = compData;
|
|
int scanlineStride = (w + 7) / 8;
|
|
bitPointer = 0;
|
|
bytePointer = 0;
|
|
|
|
int a0;
|
|
int a1;
|
|
int b1;
|
|
int b2;
|
|
int entry;
|
|
int code;
|
|
int bits;
|
|
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
|
|
|
|
// 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 = (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) {
|
|
if (b2 > w) {
|
|
b2 = w;
|
|
}
|
|
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();
|
|
if (number > w - bitOffset) {
|
|
number = w - bitOffset;
|
|
}
|
|
setToBlack(buffer, lineOffset, bitOffset, number);
|
|
bitOffset += number;
|
|
cce[currIndex++] = bitOffset;
|
|
} else {
|
|
// First a black run and then a white run follows
|
|
number = decodeBlackCodeWord();
|
|
if (number > w - bitOffset) {
|
|
number = w - bitOffset;
|
|
}
|
|
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) {
|
|
if (a1 > w) {
|
|
a1 = w;
|
|
}
|
|
setToBlack(buffer, lineOffset, bitOffset, a1
|
|
- bitOffset);
|
|
}
|
|
bitOffset = a0 = a1;
|
|
isWhite = !isWhite;
|
|
|
|
updatePointer(7 - bits);
|
|
} else if (code == 11) {
|
|
if (nextLesserThan8Bits(3) != 7) {
|
|
throw new RuntimeException(
|
|
"Invalid code encountered while decoding 2D group 4 compressed data."); //$NON-NLS-1$
|
|
}
|
|
|
|
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 {
|
|
// break line - seems to be a common failure
|
|
// unread
|
|
updatePointer(7 - bits);
|
|
// and mark lines as complete
|
|
bitOffset = w;
|
|
// throw new RuntimeException(
|
|
// "Invalid code encountered while decoding 2D group 4
|
|
// compressed data."); //$NON-NLS-1$
|
|
}
|
|
}
|
|
|
|
align();
|
|
|
|
// Add the changing element beyond the current scanline for the
|
|
// other color too
|
|
// make sure that the index does not exceed the bounds of the array
|
|
if (currIndex <= w) {
|
|
cce[currIndex++] = bitOffset;
|
|
}
|
|
|
|
// Number of changing elements in this scanline.
|
|
changingElemSize = currIndex;
|
|
|
|
lineOffset += scanlineStride;
|
|
}
|
|
}
|
|
|
|
// Returns run length
|
|
private int decodeWhiteCodeWord() {
|
|
int current;
|
|
int entry;
|
|
int bits;
|
|
int isT;
|
|
int twoBits;
|
|
int 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 RuntimeException("Invalid code encountered."); //$NON-NLS-1$
|
|
} else if (bits == 15) { // EOL
|
|
throw new RuntimeException(
|
|
"EOL code word encountered in White run."); //$NON-NLS-1$
|
|
} else {
|
|
// 11 bits - 0000 0111 1111 1111 = 0x07ff
|
|
code = (entry >>> 5) & 0x07ff;
|
|
runLength += code;
|
|
updatePointer(10 - bits);
|
|
if (isT == 0) {
|
|
isWhite = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return runLength;
|
|
}
|
|
|
|
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];
|
|
}
|
|
}
|
|
|
|
public boolean isAlign() {
|
|
return align;
|
|
}
|
|
|
|
public boolean isFillBits() {
|
|
return fillBits;
|
|
}
|
|
|
|
private int nextLesserThan8Bits(int bitsToGet) {
|
|
byte b;
|
|
byte 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 RuntimeException("tag must be either 1 or 2."); //$NON-NLS-1$
|
|
}
|
|
|
|
int bitsLeft = 8 - bitPointer;
|
|
int bitsFromNextByte = bitsToGet - bitsLeft;
|
|
|
|
int shift = bitsLeft - bitsToGet;
|
|
int i1;
|
|
int 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;
|
|
}
|
|
|
|
private int nextNBits(int bitsToGet) {
|
|
byte b;
|
|
byte next;
|
|
byte 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 RuntimeException("tag must be either 1 or 2."); //$NON-NLS-1$
|
|
}
|
|
|
|
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 readEOL(boolean isFirstEOL) {
|
|
// Seek to the next EOL.
|
|
if (!seekEOL()) {
|
|
throw new RuntimeException("EOL not found");
|
|
}
|
|
|
|
if (!fillBits) {
|
|
int next12Bits = nextNBits(12);
|
|
if (isFirstEOL && (next12Bits == 0)) {
|
|
// Might have the case of EOL padding being used even
|
|
// though it was not flagged.
|
|
// 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 = true;
|
|
return 1;
|
|
}
|
|
}
|
|
if (next12Bits != 1) {
|
|
throw new RuntimeException(
|
|
"Scanline must begin with EOL code word."); //$NON-NLS-1$
|
|
}
|
|
} else {
|
|
// 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 RuntimeException(
|
|
"All fill bits preceding EOL code must be 0."); //$NON-NLS-1$
|
|
}
|
|
|
|
// 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 RuntimeException(
|
|
"All fill bits preceding EOL code must be 0."); //$NON-NLS-1$
|
|
}
|
|
}
|
|
|
|
//
|
|
// Some encoders under Group 3 Fax compression 1D writes TIFF
|
|
// files without the fill bits, but say otherwise.
|
|
// Need to check for this here.
|
|
//
|
|
int next8 = nextNBits(8);
|
|
|
|
if (isFirstEOL && (next8 & 0xf0) == 0x10) {
|
|
//
|
|
// Fill bits are not actually used despite what the flag
|
|
// says. So switch fillBits off and then rewind so that
|
|
// only 12 bits have effectively been read.
|
|
//
|
|
fillBits = false;
|
|
updatePointer(4);
|
|
} else {
|
|
//
|
|
// This is the normal case.
|
|
// 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.
|
|
//
|
|
while (next8 != 1) {
|
|
// If not all zeros
|
|
if (next8 != 0) {
|
|
throw new RuntimeException("0 bits expected before EOL");
|
|
}
|
|
next8 = nextNBits(8);
|
|
}
|
|
}
|
|
}
|
|
// The next one bit signifies 1D/2D encoding of next line.
|
|
return nextLesserThan8Bits(1);
|
|
}
|
|
|
|
// Seeks to the next EOL in the compressed bitstream.
|
|
// Returns 'true' if and only if an EOL is found; if 'false'
|
|
// is returned it may be inferred that the EOF was reached first.
|
|
private boolean seekEOL() {
|
|
// Set maximum and current bit index into the compressed data.
|
|
int bitIndexMax = data.length * 8 - 1;
|
|
int bitIndex = bytePointer * 8 + bitPointer;
|
|
|
|
// Loop while at least 12 bits are available.
|
|
while (bitIndex <= bitIndexMax - 12) {
|
|
// Get the next 12 bits.
|
|
int next12Bits = nextNBits(12);
|
|
bitIndex += 12;
|
|
|
|
// Loop while the 12 bits are not unity, i.e., while the EOL
|
|
// has not been reached, and there is at least one bit left.
|
|
while (next12Bits != 1 && bitIndex < bitIndexMax) {
|
|
next12Bits = ((next12Bits & 0x000007ff) << 1)
|
|
| (nextLesserThan8Bits(1) & 0x00000001);
|
|
bitIndex++;
|
|
}
|
|
|
|
// If EOL reached, rewind the pointers and return 'true'.
|
|
if (next12Bits == 1) {
|
|
updatePointer(12);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// EOL not found: return 'false'.
|
|
return false;
|
|
}
|
|
|
|
public void setAlign(boolean align) {
|
|
this.align = align;
|
|
}
|
|
|
|
public void setFillBits(boolean fillBits) {
|
|
this.fillBits = fillBits;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
// Move pointer backwards by given amount of bits
|
|
private void updatePointer(int bitsToMoveBack) {
|
|
if (bitsToMoveBack > 8) {
|
|
bytePointer -= bitsToMoveBack / 8;
|
|
bitsToMoveBack %= 8;
|
|
}
|
|
|
|
int i = bitPointer - bitsToMoveBack;
|
|
|
|
if (i < 0) {
|
|
bytePointer--;
|
|
bitPointer = 8 + i;
|
|
} else {
|
|
bitPointer = i;
|
|
}
|
|
}
|
|
}
|