jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxCompressor.java
changeset 34416 68c0d866db5d
child 36448 a07e108d5722
equal deleted inserted replaced
34415:098d54b4051d 34416:68c0d866db5d
       
     1 /*
       
     2  * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 package com.sun.imageio.plugins.tiff;
       
    26 
       
    27 import javax.imageio.metadata.IIOMetadata;
       
    28 import javax.imageio.plugins.tiff.BaselineTIFFTagSet;
       
    29 import javax.imageio.plugins.tiff.TIFFField;
       
    30 
       
    31 /**
       
    32  *
       
    33  */
       
    34 abstract class TIFFFaxCompressor extends TIFFCompressor {
       
    35 
       
    36      /**
       
    37      * The CCITT numerical definition of white.
       
    38      */
       
    39     protected static final int WHITE = 0;
       
    40 
       
    41     /**
       
    42      * The CCITT numerical definition of black.
       
    43      */
       
    44     protected static final int BLACK = 1;
       
    45 
       
    46     // --- Begin tables for CCITT compression ---
       
    47 
       
    48     protected static final byte[] byteTable = new byte[] {
       
    49         8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,     // 0 to 15
       
    50         3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,     // 16 to 31
       
    51         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,     // 32 to 47
       
    52         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,     // 48 to 63
       
    53         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     // 64 to 79
       
    54         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     // 80 to 95
       
    55         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     // 96 to 111
       
    56         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,     // 112 to 127
       
    57         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     // 128 to 143
       
    58         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     // 144 to 159
       
    59         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     // 160 to 175
       
    60         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     // 176 to 191
       
    61         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     // 192 to 207
       
    62         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     // 208 to 223
       
    63         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     // 224 to 239
       
    64         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0      // 240 to 255
       
    65     };
       
    66 
       
    67     /**
       
    68      * Terminating codes for black runs.
       
    69      */
       
    70     protected static final int[] termCodesBlack = new int[] {
       
    71         /*     0 0x0000 */     0x0dc0000a, 0x40000003, 0xc0000002, 0x80000002,
       
    72         /*     4 0x0004 */     0x60000003, 0x30000004, 0x20000004, 0x18000005,
       
    73         /*     8 0x0008 */     0x14000006, 0x10000006, 0x08000007, 0x0a000007,
       
    74         /*    12 0x000c */     0x0e000007, 0x04000008, 0x07000008, 0x0c000009,
       
    75         /*    16 0x0010 */     0x05c0000a, 0x0600000a, 0x0200000a, 0x0ce0000b,
       
    76         /*    20 0x0014 */     0x0d00000b, 0x0d80000b, 0x06e0000b, 0x0500000b,
       
    77         /*    24 0x0018 */     0x02e0000b, 0x0300000b, 0x0ca0000c, 0x0cb0000c,
       
    78         /*    28 0x001c */     0x0cc0000c, 0x0cd0000c, 0x0680000c, 0x0690000c,
       
    79         /*    32 0x0020 */     0x06a0000c, 0x06b0000c, 0x0d20000c, 0x0d30000c,
       
    80         /*    36 0x0024 */     0x0d40000c, 0x0d50000c, 0x0d60000c, 0x0d70000c,
       
    81         /*    40 0x0028 */     0x06c0000c, 0x06d0000c, 0x0da0000c, 0x0db0000c,
       
    82         /*    44 0x002c */     0x0540000c, 0x0550000c, 0x0560000c, 0x0570000c,
       
    83         /*    48 0x0030 */     0x0640000c, 0x0650000c, 0x0520000c, 0x0530000c,
       
    84         /*    52 0x0034 */     0x0240000c, 0x0370000c, 0x0380000c, 0x0270000c,
       
    85         /*    56 0x0038 */     0x0280000c, 0x0580000c, 0x0590000c, 0x02b0000c,
       
    86         /*    60 0x003c */     0x02c0000c, 0x05a0000c, 0x0660000c, 0x0670000c
       
    87     };
       
    88 
       
    89     /**
       
    90      * Terminating codes for white runs.
       
    91      */
       
    92     protected static final int[] termCodesWhite = new int[] {
       
    93         /*     0 0x0000 */     0x35000008, 0x1c000006, 0x70000004, 0x80000004,
       
    94         /*     4 0x0004 */     0xb0000004, 0xc0000004, 0xe0000004, 0xf0000004,
       
    95         /*     8 0x0008 */     0x98000005, 0xa0000005, 0x38000005, 0x40000005,
       
    96         /*    12 0x000c */     0x20000006, 0x0c000006, 0xd0000006, 0xd4000006,
       
    97         /*    16 0x0010 */     0xa8000006, 0xac000006, 0x4e000007, 0x18000007,
       
    98         /*    20 0x0014 */     0x10000007, 0x2e000007, 0x06000007, 0x08000007,
       
    99         /*    24 0x0018 */     0x50000007, 0x56000007, 0x26000007, 0x48000007,
       
   100         /*    28 0x001c */     0x30000007, 0x02000008, 0x03000008, 0x1a000008,
       
   101         /*    32 0x0020 */     0x1b000008, 0x12000008, 0x13000008, 0x14000008,
       
   102         /*    36 0x0024 */     0x15000008, 0x16000008, 0x17000008, 0x28000008,
       
   103         /*    40 0x0028 */     0x29000008, 0x2a000008, 0x2b000008, 0x2c000008,
       
   104         /*    44 0x002c */     0x2d000008, 0x04000008, 0x05000008, 0x0a000008,
       
   105         /*    48 0x0030 */     0x0b000008, 0x52000008, 0x53000008, 0x54000008,
       
   106         /*    52 0x0034 */     0x55000008, 0x24000008, 0x25000008, 0x58000008,
       
   107         /*    56 0x0038 */     0x59000008, 0x5a000008, 0x5b000008, 0x4a000008,
       
   108         /*    60 0x003c */     0x4b000008, 0x32000008, 0x33000008, 0x34000008
       
   109     };
       
   110 
       
   111     /**
       
   112      * Make-up codes for black runs.
       
   113      */
       
   114     protected static final int[] makeupCodesBlack = new int[] {
       
   115         /*     0 0x0000 */     0x00000000, 0x03c0000a, 0x0c80000c, 0x0c90000c,
       
   116         /*     4 0x0004 */     0x05b0000c, 0x0330000c, 0x0340000c, 0x0350000c,
       
   117         /*     8 0x0008 */     0x0360000d, 0x0368000d, 0x0250000d, 0x0258000d,
       
   118         /*    12 0x000c */     0x0260000d, 0x0268000d, 0x0390000d, 0x0398000d,
       
   119         /*    16 0x0010 */     0x03a0000d, 0x03a8000d, 0x03b0000d, 0x03b8000d,
       
   120         /*    20 0x0014 */     0x0290000d, 0x0298000d, 0x02a0000d, 0x02a8000d,
       
   121         /*    24 0x0018 */     0x02d0000d, 0x02d8000d, 0x0320000d, 0x0328000d,
       
   122         /*    28 0x001c */     0x0100000b, 0x0180000b, 0x01a0000b, 0x0120000c,
       
   123         /*    32 0x0020 */     0x0130000c, 0x0140000c, 0x0150000c, 0x0160000c,
       
   124         /*    36 0x0024 */     0x0170000c, 0x01c0000c, 0x01d0000c, 0x01e0000c,
       
   125         /*    40 0x0028 */     0x01f0000c, 0x00000000, 0x00000000, 0x00000000,
       
   126         /*    44 0x002c */     0x00000000, 0x00000000, 0x00000000, 0x00000000,
       
   127         /*    48 0x0030 */     0x00000000, 0x00000000, 0x00000000, 0x00000000,
       
   128         /*    52 0x0034 */     0x00000000, 0x00000000, 0x00000000, 0x00000000,
       
   129         /*    56 0x0038 */     0x00000000, 0x00000000, 0x00000000, 0x00000000
       
   130     };
       
   131 
       
   132     /**
       
   133      * Make-up codes for white runs.
       
   134      */
       
   135     protected static final int[] makeupCodesWhite = new int[] {
       
   136         /*     0 0x0000 */     0x00000000, 0xd8000005, 0x90000005, 0x5c000006,
       
   137         /*     4 0x0004 */     0x6e000007, 0x36000008, 0x37000008, 0x64000008,
       
   138         /*     8 0x0008 */     0x65000008, 0x68000008, 0x67000008, 0x66000009,
       
   139         /*    12 0x000c */     0x66800009, 0x69000009, 0x69800009, 0x6a000009,
       
   140         /*    16 0x0010 */     0x6a800009, 0x6b000009, 0x6b800009, 0x6c000009,
       
   141         /*    20 0x0014 */     0x6c800009, 0x6d000009, 0x6d800009, 0x4c000009,
       
   142         /*    24 0x0018 */     0x4c800009, 0x4d000009, 0x60000006, 0x4d800009,
       
   143         /*    28 0x001c */     0x0100000b, 0x0180000b, 0x01a0000b, 0x0120000c,
       
   144         /*    32 0x0020 */     0x0130000c, 0x0140000c, 0x0150000c, 0x0160000c,
       
   145         /*    36 0x0024 */     0x0170000c, 0x01c0000c, 0x01d0000c, 0x01e0000c,
       
   146         /*    40 0x0028 */     0x01f0000c, 0x00000000, 0x00000000, 0x00000000,
       
   147         /*    44 0x002c */     0x00000000, 0x00000000, 0x00000000, 0x00000000,
       
   148         /*    48 0x0030 */     0x00000000, 0x00000000, 0x00000000, 0x00000000,
       
   149         /*    52 0x0034 */     0x00000000, 0x00000000, 0x00000000, 0x00000000,
       
   150         /*    56 0x0038 */     0x00000000, 0x00000000, 0x00000000, 0x00000000
       
   151     };
       
   152 
       
   153     /**
       
   154      * Pass mode table.
       
   155      */
       
   156     protected static final int[] passMode = new int[] {
       
   157         0x10000004            // 0001
       
   158     };
       
   159 
       
   160     /**
       
   161      * Vertical mode table.
       
   162      */
       
   163     protected static final int[] vertMode = new int[] {
       
   164         0x06000007,            // 0000011
       
   165         0x0c000006,            // 000011
       
   166         0x60000003,            // 011
       
   167         0x80000001,            // 1
       
   168         0x40000003,            // 010
       
   169         0x08000006,            // 000010
       
   170         0x04000007            // 0000010
       
   171     };
       
   172 
       
   173     /**
       
   174      * Horizontal mode table.
       
   175      */
       
   176     protected static final int[] horzMode = new int[] {
       
   177         0x20000003            // 001
       
   178     };
       
   179 
       
   180     /**
       
   181      * Black and white terminating code table.
       
   182      */
       
   183     protected static final int[][] termCodes =
       
   184         new int[][] {termCodesWhite, termCodesBlack};
       
   185 
       
   186     /**
       
   187      * Black and white make-up code table.
       
   188      */
       
   189     protected static final int[][] makeupCodes =
       
   190         new int[][] {makeupCodesWhite, makeupCodesBlack};
       
   191 
       
   192     /**
       
   193      * Black and white pass mode table.
       
   194      */
       
   195     protected static final int[][] pass = new int[][] {passMode, passMode};
       
   196 
       
   197     /**
       
   198      * Black and white vertical mode table.
       
   199      */
       
   200     protected static final int[][] vert = new int[][] {vertMode, vertMode};
       
   201 
       
   202     /**
       
   203      * Black and white horizontal mode table.
       
   204      */
       
   205     protected static final int[][] horz = new int[][] {horzMode, horzMode};
       
   206 
       
   207     // --- End tables for CCITT compression ---
       
   208 
       
   209     /**
       
   210      * Whether bits are inserted in reverse order (TIFF FillOrder 2).
       
   211      */
       
   212     protected boolean inverseFill = false;
       
   213 
       
   214     /**
       
   215      * Output bit buffer.
       
   216      */
       
   217     protected int bits;
       
   218 
       
   219     /**
       
   220      * Number of bits in the output bit buffer.
       
   221      */
       
   222     protected int ndex;
       
   223 
       
   224     /**
       
   225      * Constructor. The superclass constructor is merely invoked with the
       
   226      * same parameters.
       
   227      */
       
   228     protected TIFFFaxCompressor(String compressionType,
       
   229                                 int compressionTagValue,
       
   230                                 boolean isCompressionLossless) {
       
   231         super(compressionType, compressionTagValue, isCompressionLossless);
       
   232     }
       
   233 
       
   234     /**
       
   235      * Sets the value of the <code>metadata</code> field.
       
   236      *
       
   237      * <p> The implementation in this class also sets local options
       
   238      * from the FILL_ORDER field if it exists.</p>
       
   239      *
       
   240      * @param metadata the <code>IIOMetadata</code> object for the
       
   241      * image being written.
       
   242      *
       
   243      * @see #getMetadata()
       
   244      */
       
   245     public void setMetadata(IIOMetadata metadata) {
       
   246         super.setMetadata(metadata);
       
   247 
       
   248         if (metadata instanceof TIFFImageMetadata) {
       
   249             TIFFImageMetadata tim = (TIFFImageMetadata)metadata;
       
   250             TIFFField f = tim.getTIFFField(BaselineTIFFTagSet.TAG_FILL_ORDER);
       
   251             inverseFill = (f != null && f.getAsInt(0) == 2);
       
   252         }
       
   253     }
       
   254 
       
   255     /**
       
   256      * Return min of <code>maxOffset</code> or offset of first pixel
       
   257      * different from pixel at <code>bitOffset</code>.
       
   258      */
       
   259     public int nextState(byte[] data,
       
   260                           int    base,
       
   261                           int    bitOffset,
       
   262                           int    maxOffset)
       
   263     {
       
   264         if(data == null) {
       
   265             return maxOffset;
       
   266         }
       
   267 
       
   268         int next  = base + (bitOffset>>>3);
       
   269         // If the offset is beyond the data already then the minimum of the
       
   270         // current offset and maxOffset must be maxOffset.
       
   271         if(next >= data.length) {
       
   272             return maxOffset;
       
   273         }
       
   274         int end   = base + (maxOffset>>>3);
       
   275         if(end == data.length) { // Prevents out of bounds exception below
       
   276             end--;
       
   277         }
       
   278         int extra = bitOffset & 0x7;
       
   279 
       
   280         int  testbyte;
       
   281 
       
   282         if((data[next] & (0x80 >>> extra)) != 0) {    // look for "0"
       
   283             testbyte = ~(data[next]) & (0xff >>> extra);
       
   284             while (next < end) {
       
   285                 if (testbyte != 0) {
       
   286                     break;
       
   287                 }
       
   288                 testbyte = ~(data[++next]) & 0xff;
       
   289             }
       
   290         } else {                // look for "1"
       
   291             if ((testbyte = (data[next] & (0xff >>> extra))) != 0) {
       
   292                 bitOffset = (next-base)*8 + byteTable[testbyte];
       
   293                 return ((bitOffset < maxOffset) ? bitOffset : maxOffset);
       
   294             }
       
   295             while (next < end) {
       
   296                 if ((testbyte = data[++next]&0xff) != 0) {
       
   297                     // "1" is in current byte
       
   298                     bitOffset = (next-base)*8 + byteTable[testbyte];
       
   299                     return ((bitOffset < maxOffset) ? bitOffset : maxOffset);
       
   300                 }
       
   301             }
       
   302         }
       
   303         bitOffset = (next-base)*8 + byteTable[testbyte];
       
   304         return ((bitOffset < maxOffset) ? bitOffset : maxOffset);
       
   305     }
       
   306 
       
   307     /**
       
   308      * Initialize bit buffer machinery.
       
   309      */
       
   310     public void initBitBuf()
       
   311     {
       
   312         ndex = 0;
       
   313         bits = 0x00000000;
       
   314     }
       
   315 
       
   316     /**
       
   317      * Get code for run and add to compressed bitstream.
       
   318      */
       
   319     public int add1DBits(byte[] buf,
       
   320                           int    where, // byte offs
       
   321                           int    count, // #pixels in run
       
   322                           int    color) // color of run
       
   323     {
       
   324         int                 sixtyfours;
       
   325         int        mask;
       
   326         int len = where;
       
   327 
       
   328         sixtyfours = count >>> 6;    // count / 64;
       
   329         count = count & 0x3f;       // count % 64
       
   330         if (sixtyfours != 0) {
       
   331             for ( ; sixtyfours > 40; sixtyfours -= 40) {
       
   332                 mask = makeupCodes[color][40];
       
   333                 bits |= (mask & 0xfff80000) >>> ndex;
       
   334                 ndex += (mask & 0x0000ffff);
       
   335                 while (ndex > 7) {
       
   336                     buf[len++] = (byte)(bits >>> 24);
       
   337                     bits <<= 8;
       
   338                     ndex -= 8;
       
   339                 }
       
   340             }
       
   341 
       
   342             mask = makeupCodes[color][sixtyfours];
       
   343             bits |= (mask & 0xfff80000) >>> ndex;
       
   344             ndex += (mask & 0x0000ffff);
       
   345             while (ndex > 7) {
       
   346                 buf[len++] = (byte)(bits >>> 24);
       
   347                 bits <<= 8;
       
   348                 ndex -= 8;
       
   349             }
       
   350         }
       
   351 
       
   352         mask = termCodes[color][count];
       
   353         bits |= (mask & 0xfff80000) >>> ndex;
       
   354         ndex += (mask & 0x0000ffff);
       
   355         while (ndex > 7) {
       
   356             buf[len++] = (byte)(bits >>> 24);
       
   357             bits <<= 8;
       
   358             ndex -= 8;
       
   359         }
       
   360 
       
   361         return(len - where);
       
   362     }
       
   363 
       
   364     /**
       
   365      * Place entry from mode table into compressed bitstream.
       
   366      */
       
   367     public int add2DBits(byte[]  buf,   // compressed buffer
       
   368                           int     where, // byte offset into compressed buffer
       
   369                           int[][] mode,  // 2-D mode to be encoded
       
   370                           int     entry) // mode entry (0 unless vertical)
       
   371     {
       
   372         int        mask;
       
   373         int len = where;
       
   374         int                 color = 0;
       
   375 
       
   376         mask = mode[color][entry];
       
   377         bits |= (mask & 0xfff80000) >>> ndex;
       
   378         ndex += (mask & 0x0000ffff);
       
   379         while (ndex > 7) {
       
   380             buf[len++] = (byte)(bits >>> 24);
       
   381             bits <<= 8;
       
   382             ndex -= 8;
       
   383         }
       
   384 
       
   385         return(len - where);
       
   386     }
       
   387 
       
   388     /**
       
   389      * Add an End-of-Line (EOL == 0x001) to the compressed bitstream
       
   390      * with optional byte alignment.
       
   391      */
       
   392     public int addEOL(boolean is1DMode,// 1D encoding
       
   393                        boolean addFill, // byte aligned EOLs
       
   394                        boolean add1,    // add1 ? EOL+1 : EOL+0
       
   395                        byte[]  buf,     // compressed buffer address
       
   396                        int     where)   // current byte offset into buffer
       
   397     {
       
   398         int len = where;
       
   399 
       
   400         //
       
   401         // Add zero-valued fill bits such that the EOL is aligned as
       
   402         //
       
   403         //     xxxx 0000 0000 0001
       
   404         //
       
   405         if(addFill) {
       
   406             //
       
   407             // Simply increment the bit count. No need to feed bits into
       
   408             // the output buffer at this point as there are at most 7 bits
       
   409             // in the bit buffer, at most 7 are added here, and at most
       
   410             // 13 below making the total 7+7+13 = 27 before the bit feed
       
   411             // at the end of this routine.
       
   412             //
       
   413             ndex += ((ndex <= 4) ? 4 - ndex : 12 - ndex);
       
   414         }
       
   415 
       
   416         //
       
   417         // Write EOL into buffer
       
   418         //
       
   419         if(is1DMode) {
       
   420             bits |= 0x00100000 >>> ndex;
       
   421             ndex += 12;
       
   422         } else {
       
   423             bits |= (add1 ? 0x00180000 : 0x00100000) >>> ndex;
       
   424             ndex += 13;
       
   425         }
       
   426 
       
   427         while (ndex > 7) {
       
   428             buf[len++] = (byte)(bits >>> 24);
       
   429             bits <<= 8;
       
   430             ndex -= 8;
       
   431         }
       
   432 
       
   433         return(len - where);
       
   434     }
       
   435 
       
   436     /**
       
   437      * Add an End-of-Facsimile-Block (EOFB == 0x001001) to the compressed
       
   438      * bitstream.
       
   439      */
       
   440     public int addEOFB(byte[] buf,    // compressed buffer
       
   441                          int    where) // byte offset into compressed buffer
       
   442     {
       
   443         int len = where;
       
   444 
       
   445         //
       
   446         // eofb code
       
   447         //
       
   448         bits |= 0x00100100 >>> ndex;
       
   449 
       
   450         //
       
   451         // eofb code length
       
   452         //
       
   453         ndex += 24;
       
   454 
       
   455         //
       
   456         // flush all pending bits
       
   457         //
       
   458         while(ndex > 0) {
       
   459             buf[len++] = (byte)(bits >>> 24);
       
   460             bits <<= 8;
       
   461             ndex -= 8;
       
   462         }
       
   463 
       
   464         return(len - where);
       
   465     }
       
   466 
       
   467     /**
       
   468      * One-dimensionally encode a row of data using CCITT Huffman compression.
       
   469      * The bit buffer should be initialized as required before invoking this
       
   470      * method and should be flushed after the method returns. The fill order
       
   471      * is always highest-order to lowest-order bit so the calling routine
       
   472      * should handle bit inversion.
       
   473      */
       
   474     public int encode1D(byte[] data,
       
   475                          int rowOffset,
       
   476                          int colOffset,
       
   477                          int rowLength,
       
   478                          byte[] compData,
       
   479                          int compOffset) {
       
   480         int lineAddr = rowOffset;
       
   481         int bitIndex = colOffset;
       
   482 
       
   483         int last     = bitIndex + rowLength;
       
   484         int outIndex = compOffset;
       
   485 
       
   486         //
       
   487         // Is first pixel black
       
   488         //
       
   489         int testbit =
       
   490             ((data[lineAddr + (bitIndex>>>3)]&0xff) >>>
       
   491              (7-(bitIndex & 0x7))) & 0x1;
       
   492         int currentColor = BLACK;
       
   493         if (testbit != 0) {
       
   494             outIndex += add1DBits(compData, outIndex, 0, WHITE);
       
   495         } else {
       
   496             currentColor = WHITE;
       
   497         }
       
   498 
       
   499         //
       
   500         // Run-length encode line
       
   501         //
       
   502         while (bitIndex < last) {
       
   503             int bitCount =
       
   504                 nextState(data, lineAddr, bitIndex, last) - bitIndex;
       
   505             outIndex +=
       
   506                 add1DBits(compData, outIndex, bitCount, currentColor);
       
   507             bitIndex += bitCount;
       
   508             currentColor ^= 0x00000001;
       
   509         }
       
   510 
       
   511         return outIndex - compOffset;
       
   512     }
       
   513 }