001: /*
002: * $RCSfile: TIFFPackBitsCompressor.java,v $
003: *
004: *
005: * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * - Redistribution of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: *
014: * - Redistribution in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * Neither the name of Sun Microsystems, Inc. or the names of
020: * contributors may be used to endorse or promote products derived
021: * from this software without specific prior written permission.
022: *
023: * This software is provided "AS IS," without a warranty of any
024: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
025: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
026: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
027: * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
028: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
029: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
030: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
031: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
032: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
033: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
034: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
035: * POSSIBILITY OF SUCH DAMAGES.
036: *
037: * You acknowledge that this software is not designed or intended for
038: * use in the design, construction, operation or maintenance of any
039: * nuclear facility.
040: *
041: * $Revision: 1.1 $
042: * $Date: 2005/02/11 05:01:49 $
043: * $State: Exp $
044: */
045: package com.sun.media.imageioimpl.plugins.tiff;
046:
047: import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet;
048: import com.sun.media.imageio.plugins.tiff.TIFFCompressor;
049: import java.io.IOException;
050:
051: /**
052: *
053: */
054: public class TIFFPackBitsCompressor extends TIFFCompressor {
055:
056: public TIFFPackBitsCompressor() {
057: super ("PackBits", BaselineTIFFTagSet.COMPRESSION_PACKBITS, true);
058: }
059:
060: /**
061: * Performs PackBits compression for a single buffer of data.
062: * This should be called for each row of each tile. The returned
063: * value is the offset into the output buffer after compression.
064: */
065: private static int packBits(byte[] input, int inOffset,
066: int inCount, byte[] output, int outOffset) {
067: int inMax = inOffset + inCount - 1;
068: int inMaxMinus1 = inMax - 1;
069:
070: while (inOffset <= inMax) {
071: int run = 1;
072: byte replicate = input[inOffset];
073: while (run < 127 && inOffset < inMax
074: && input[inOffset] == input[inOffset + 1]) {
075: run++;
076: inOffset++;
077: }
078: if (run > 1) {
079: inOffset++;
080: output[outOffset++] = (byte) (-(run - 1));
081: output[outOffset++] = replicate;
082: }
083:
084: run = 0;
085: int saveOffset = outOffset;
086: while (run < 128
087: && ((inOffset < inMax && input[inOffset] != input[inOffset + 1]) || (inOffset < inMaxMinus1 && input[inOffset] != input[inOffset + 2]))) {
088: run++;
089: output[++outOffset] = input[inOffset++];
090: }
091: if (run > 0) {
092: output[saveOffset] = (byte) (run - 1);
093: outOffset++;
094: }
095:
096: if (inOffset == inMax) {
097: if (run > 0 && run < 128) {
098: output[saveOffset]++;
099: output[outOffset++] = input[inOffset++];
100: } else {
101: output[outOffset++] = (byte) 0;
102: output[outOffset++] = input[inOffset++];
103: }
104: }
105: }
106:
107: return outOffset;
108: }
109:
110: public int encode(byte[] b, int off, int width, int height,
111: int[] bitsPerSample, int scanlineStride) throws IOException {
112: int bitsPerPixel = 0;
113: for (int i = 0; i < bitsPerSample.length; i++) {
114: bitsPerPixel += bitsPerSample[i];
115: }
116: int bytesPerRow = (bitsPerPixel * width + 7) / 8;
117: int bufSize = (int) (bytesPerRow + (bytesPerRow + 127) / 128);
118: byte[] compData = new byte[bufSize];
119:
120: int bytesWritten = 0;
121:
122: for (int i = 0; i < height; i++) {
123: int bytes = packBits(b, off, scanlineStride, compData, 0);
124: off += scanlineStride;
125: bytesWritten += bytes;
126: stream.write(compData, 0, bytes);
127: }
128:
129: return bytesWritten;
130: }
131: }
|