com.sun.pdfview.decode.DCTDecode Maven / Gradle / Ivy
/*
* $Id: DCTDecode.java,v 1.2 2007/12/20 18:33:33 rbair Exp $
*
* Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* 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.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.awt.image.ImageObserver;
import java.io.IOException;
import java.nio.ByteBuffer;
import com.sun.pdfview.PDFObject;
import com.sun.pdfview.PDFParseException;
import com.sun.pdfview.colorspace.PDFColorSpace;
/**
* decode a DCT encoded array into a byte array. This class uses Java's
* built-in JPEG image class to do the decoding.
*
* @author Mike Wessler
*/
public class DCTDecode {
/**
* decode an array of bytes in DCT format.
*
* DCT is the format used by JPEG images, so this class simply
* loads the DCT-format bytes as an image, then reads the bytes out
* of the image to create the array. Unfortunately, their most
* likely use is to get turned BACK into an image, so this isn't
* terribly efficient... but is is general... don't hit, please.
*
* The DCT-encoded stream may have 1, 3 or 4 samples per pixel, depending
* on the colorspace of the image. In decoding, we look for the colorspace
* in the stream object's dictionary to decide how to decode this image.
* If no colorspace is present, we guess 3 samples per pixel.
*
* @param dict the stream dictionary
* @param buf the DCT-encoded buffer
* @param params the parameters to the decoder (ignored)
* @return the decoded buffer
*/
protected static ByteBuffer decode(PDFObject dict, ByteBuffer buf,
PDFObject params) throws PDFParseException
{
// System.out.println("DCTDecode image info: "+params);
buf.rewind();
// copy the data into a byte array required by createimage
byte[] ary = new byte[buf.remaining()];
buf.get(ary);
// wait for the image to get drawn
Image img= Toolkit.getDefaultToolkit().createImage(ary);
MyTracker mt= new MyTracker(img);
mt.waitForAll();
// the default components per pixel is 3
int numComponents = 3;
// see if we have a colorspace
try {
PDFObject csObj = dict.getDictRef("ColorSpace");
if (csObj != null) {
// we do, so get the number of components
PDFColorSpace cs = PDFColorSpace.getColorSpace(csObj, null);
numComponents = cs.getNumComponents();
}
} catch (IOException ioe) {
// oh well
}
// figure out the type
int type = BufferedImage.TYPE_INT_RGB;
if (numComponents == 1) {
type = BufferedImage.TYPE_BYTE_GRAY;
} else if (numComponents == 4) {
type = BufferedImage.TYPE_INT_ARGB;
}
// create a buffered image
BufferedImage bimg = new BufferedImage(img.getWidth(null),
img.getHeight(null),
type);
Graphics bg= bimg.getGraphics();
// draw the image onto it
bg.drawImage(img, 0, 0, null);
byte[] output = null;
if (type == BufferedImage.TYPE_INT_RGB) {
// read back the data
DataBufferInt db = (DataBufferInt) bimg.getData().getDataBuffer();
int[] data = db.getData();
output = new byte[data.length*3];
for (int i=0; i>16);
output[i*3+1]= (byte)(data[i]>>8);
output[i*3+2]= (byte)(data[i]);
}
} else if (type == BufferedImage.TYPE_BYTE_GRAY) {
DataBufferByte db = (DataBufferByte) bimg.getData().getDataBuffer();
output = db.getData();
} else if (type == BufferedImage.TYPE_INT_ARGB) {
// read back the data
DataBufferInt db = (DataBufferInt) bimg.getData().getDataBuffer();
int[] data = db.getData();
output = new byte[data.length*4];
for (int i=0; i>24);
output[i*4+1]= (byte)(data[i]>>16);
output[i*4+2]= (byte)(data[i]>>8);
output[i*4+3]= (byte)(data[i]);
}
}
// System.out.println("Translated data");
return ByteBuffer.wrap(output);
}
}
/**
* Image tracker. I'm not sure why I'm not using the default Java
* image tracker for this one.
*/
class MyTracker implements ImageObserver {
boolean done= false;
/**
* create a new MyTracker that watches this image. The image
* will start loading immediately.
*/
public MyTracker(Image img) {
img.getWidth(this);
}
/**
* More information has come in about the image.
*/
public boolean imageUpdate(Image img, int infoflags, int x, int y,
int width, int height) {
if ((infoflags & (ALLBITS | ERROR | ABORT))!=0) {
synchronized(this) {
done= true;
notifyAll();
}
return false;
}
return true;
}
/**
* Wait until the image is done, then return.
*/
public synchronized void waitForAll() {
if (!done) {
try {
wait();
} catch (InterruptedException ie) {}
}
}
}