com.sun.pdfview.decode.TIFFPredictor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of pdf-renderer Show documentation
Show all versions of pdf-renderer Show documentation
PDF renderer implementation supporting the subset of PDF 1.4 specification.
The newest version!
/*
* $Id: TIFFPredictor.java,v 1.1 2010-05-23 22:07:04 lujke Exp $
*
* Copyright 2010 Pirion Systems Pty Ltd, 139 Warry St,
* Fortitude Valley, Queensland, Australia
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.sun.pdfview.decode;
import java.io.IOException;
import java.nio.ByteBuffer;
/**
* Undo prediction based on the TIFF Predictor 2 algorithm
*/
public class TIFFPredictor extends Predictor {
public TIFFPredictor() {
super (TIFF);
}
/**
* Undo data based on the png algorithm
*/
public ByteBuffer unpredict(ByteBuffer imageData)
throws IOException
{
ByteBuffer out = ByteBuffer.allocate(imageData.limit());
final int numComponents = getColors();
final int pixelBits = numComponents * getBitsPerComponent();
int bytePerRow = (getColumns() * pixelBits + 7) / 8;
final byte[] row = new byte[bytePerRow];
while(imageData.remaining() > 0) {
imageData.get(row);
if (getBitsPerComponent() == 8) {
for (int i = numComponents; i < row.length; i += numComponents) {
for (int c = 0; c < numComponents; ++c) {
final int pos = i + c;
row[pos] += row[pos - numComponents];
}
}
} else if (getBitsPerComponent() == 16) {
final short[] prev = new short[numComponents];
for (int c = 0; c < numComponents; c += 1) {
final int pos = c * 2;
prev[c] = (short) ((row[pos] << 8 | (row[pos + 1]) & 0xFFFF));
}
for (int i = numComponents * 2; i < row.length; i += numComponents * 2) {
for (int c = 0; c < numComponents; c += 1) {
final int pos = i + c * 2;
short cur = (short) ((row[pos] << 8 | (row[pos + 1]) & 0xFFFF));
cur += prev[c];
row[pos] = (byte) (cur >>> 8 & 0xFF);
row[pos + 1] = (byte) (cur & 0xFF);
prev[c] = cur;
}
}
} else {
assert getBitsPerComponent() == 1 || getBitsPerComponent() == 2 || getBitsPerComponent() == 4 : "we don't want to grab components across pixel boundaries";
int bitsOnRow = pixelBits * getColumns(); // may be less than bytesOnRow * 8
byte prev[] = new byte[numComponents];
final int shiftWhenAligned = 8 - getBitsPerComponent();
final int mask = (1 << getBitsPerComponent()) - 1;
for (int c = 0; c < numComponents; ++c) {
prev[c] = getbits(row, c * getBitsPerComponent(), shiftWhenAligned, mask);
}
for (int i = pixelBits; i < bitsOnRow; i += pixelBits) {
for (int c = 0; c < numComponents; ++c) {
byte cur = getbits(row, i + c * getBitsPerComponent(), shiftWhenAligned, mask);
cur += prev[c];
prev[c] = cur;
setbits(row, i + c * getBitsPerComponent(), shiftWhenAligned, mask, cur);
}
}
}
out.put(row);
}
// reset start pointer
out.flip();
// return
return out;
}
private static byte getbits(byte[] data, int bitIndex, int shiftWhenByteAligned, int mask)
{
final int b = data[(bitIndex >> 3)];
final int bitIndexInB = bitIndex & 7;
final int shift = shiftWhenByteAligned - bitIndexInB;
return (byte) ((b >>> shift) & mask);
}
private static void setbits(byte[] data, int bitIndex, int shiftWhenByteAligned, int mask, byte bits)
{
final int b = data[(bitIndex >> 3)];
final int bitIndexInB = bitIndex & 7;
final int shift = shiftWhenByteAligned - bitIndexInB;
data[bitIndex >> 3] = (byte) ((b & ~(mask << shift)) | (bits << shift));
}
}