/*
 * $RCSfile: TIFFFaxDecoder.java,v $
 *
 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
 *
 * Use is subject to license terms.
 *
 * $Revision: 1.3 $
 * $Date: 2005/11/14 22:44:48 $
 * $State: Exp $
 */
package com.lightcrafts.media.jai.codecimpl;

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+1];
	this.currChangingElems = new int[w+1];
    }

    // 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 RuntimeException(JaiI18N.getString("TIFFFaxDecoder0"));
		} else if (bits == 15) {    // EOL
		    //throw new Error(JaiI18N.getString("TIFFFaxDecoder1"));
                    //
                    // Instead of throwing an error, assume that the EOL
                    // was premature. Rewind the pointers to the start
                    // of the EOL and return, thereby stopping decoding
                    // this line.
                    //
                    updatePointer(12);
                    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) {
		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"));
                        //
                        // Instead of throwing an error, assume that the EOL
                        // was premature. Rewind the pointers to the start
                        // of the EOL and return, thereby stopping decoding
                        // this line.
                        //
                        updatePointer(12);
                        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) {
		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.
	// TODO: Deal with uncompressedMode, aastha 03/03/1999

	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 RuntimeException(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 RuntimeException(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
	// extension. This code is when code == 11. aastha 03/03/1999
	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) {
                        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(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 RuntimeException(JaiI18N.getString("TIFFFaxDecoder5"));
		}
	    }

	    // Add the changing element beyond the current scanline for the
	    // other color too, if not already added
	    if (currIndex <= w)
		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 RuntimeException(JaiI18N.getString("TIFFFaxDecoder0"));
	    } else if (bits == 15) {    // EOL
		throw new RuntimeException(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 RuntimeException(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;
    }

    // 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;
    }

    private int readEOL(boolean isFirstEOL) {
        if(oneD == 0) {
            // Seek to the next EOL.
            if(!seekEOL()) {
                throw new RuntimeException(JaiI18N.getString("TIFFFaxDecoder9"));
            }
        }

	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 RuntimeException(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 RuntimeException(JaiI18N.getString("TIFFFaxDecoder8"));
	    }

	    // If the number of bitsLeft is less than 4, 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(JaiI18N.getString("TIFFFaxDecoder8"));
		}
	    }

            //
            // Some encoders under Group 3 Fax compression 1D writes TIFF
            // files without the fill bits, but say otherwise in T4Options.
            // 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 = 0;
                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(JaiI18N.getString("TIFFFaxDecoder8"));
                    }
                    next8 = nextNBits(8);
                }
            }
	}

	// 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 RuntimeException(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 RuntimeException(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) {
        if(bitsToMoveBack > 8) {
            bytePointer -= bitsToMoveBack/8;
            bitsToMoveBack %= 8;
        }

	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;
    }
}
