1/* 2 * Copyright (c) 2005, 2016, 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 */ 25package com.sun.imageio.plugins.tiff; 26 27import javax.imageio.plugins.tiff.BaselineTIFFTagSet; 28import java.io.IOException; 29import javax.imageio.IIOException; 30 31/** 32 * 33 */ 34public class TIFFRLECompressor extends TIFFFaxCompressor { 35 36 public TIFFRLECompressor() { 37 super("CCITT RLE", BaselineTIFFTagSet.COMPRESSION_CCITT_RLE, true); 38 } 39 40 /** 41 * Encode a row of data using Modified Huffman Compression also known as 42 * CCITT RLE (Run Lenth Encoding). 43 * 44 * @param data The row of data to compress. 45 * @param rowOffset Starting index in {@code data}. 46 * @param colOffset Bit offset within first {@code data[rowOffset]}. 47 * @param rowLength Number of bits in the row. 48 * @param compData The compressed data. 49 * 50 * @return The number of bytes saved in the compressed data array. 51 */ 52 public int encodeRLE(byte[] data, 53 int rowOffset, 54 int colOffset, 55 int rowLength, 56 byte[] compData) { 57 // 58 // Initialize bit buffer machinery. 59 // 60 initBitBuf(); 61 62 // 63 // Run-length encode line. 64 // 65 int outIndex = 66 encode1D(data, rowOffset, colOffset, rowLength, compData, 0); 67 68 // 69 // Flush pending bits 70 // 71 while (ndex > 0) { 72 compData[outIndex++] = (byte)(bits >>> 24); 73 bits <<= 8; 74 ndex -= 8; 75 } 76 77 // 78 // Flip the bytes if inverse fill was requested. 79 // 80 if (inverseFill) { 81 byte[] flipTable = TIFFFaxDecompressor.flipTable; 82 for(int i = 0; i < outIndex; i++) { 83 compData[i] = flipTable[compData[i] & 0xff]; 84 } 85 } 86 87 return outIndex; 88 } 89 90 public int encode(byte[] b, int off, 91 int width, int height, 92 int[] bitsPerSample, 93 int scanlineStride) throws IOException { 94 if (bitsPerSample.length != 1 || bitsPerSample[0] != 1) { 95 throw new IIOException( 96 "Bits per sample must be 1 for RLE compression!"); 97 } 98 99 // In the worst case, 2 bits of input will result in 9 bits of output, 100 // plus 2 extra bits if the row starts with black. 101 int maxBits = 9*((width + 1)/2) + 2; 102 byte[] compData = new byte[(maxBits + 7)/8]; 103 104 int bytes = 0; 105 int rowOffset = off; 106 107 for (int i = 0; i < height; i++) { 108 int rowBytes = encodeRLE(b, rowOffset, 0, width, compData); 109 stream.write(compData, 0, rowBytes); 110 111 rowOffset += scanlineStride; 112 bytes += rowBytes; 113 } 114 115 return bytes; 116 } 117} 118