package persist;
/* PcxReader: This is a class which provides a method for reading
* PCX-Files.
* The PCX-Format is a Image-File-Format which was developed by ZSoft.
*
* PcxReader, Version 1.00 [06/05/2000]
* Copyright (c) 2000 by Matthias Burg
* All rights reserved
* eMail: Matthias@burgsoft.de
* Internet: www.burgsoft.de
*
* The PcxReader is Freeware. You can use and copy it without any fee.
* The author is not responsible for any damages which are caused by
* this software.
* You find further information about the Java-Technology on the Sun-
* Website (Internet: www.sun.com).
*
* At the moment PcxReader supports the following File-Formats:
* - PCX Version 3.0 with 8 Bit (=256) Colors
* - PCX Version 3.0 with 24 Bit (=16.7 Mio) Colors
*
* The PcxReader needs an opened InputStream with the PCX-Data as
* Argument. The return-value is the loaded Image.
* You can use the PcxReader in a Java-Application as well as in a
* Java-Applet
*
* If you have questions or tips for the PcxReader, please write an
* eMail.
*/
import java.awt.*;
import java.awt.image.*;
import java.io.*;
/**
* This class reads PCX-Data from a stream and converts it into an Image-Class.
*
* @author Matthias Burg
*/
public class PCXReader {
public static final int NORMAL = 1;
public static final int RLE = 2;
public static BufferedImage loadImage(InputStream in) {
int pcxheight, pcxwidth;
Image picture = null;
//Header-Data
int manufacturer;
int version;
int encoding;
int bits_per_pixel;
int xmin,ymin;
int xmax,ymax;
int hres;
int vres;
byte[] palette16 = new byte[48];
int reserved;
int color_planes;
int bytes_per_line;
int palette_type;
byte[] filler = new byte[58];
boolean wasOdd = false; // Rafael: PCSx with odd width (ex: 7, 135, etc)
int imagebytes;
try {
/* In the beginning the Image-Data is read as in the PCX-
* specification.
*/
manufacturer = in.read();
version = in.read();
encoding = in.read();
bits_per_pixel = in.read();
xmin = in.read()+in.read()*256;
ymin = in.read()+in.read()*256;
xmax = in.read()+in.read()*256;
ymax = in.read()+in.read()*256;
hres = in.read()+in.read()*256;
vres = in.read()+in.read()*256;
in.read(palette16);
reserved = in.read();
color_planes = in.read();
bytes_per_line = in.read()+in.read()*256;
palette_type = (short)(in.read()+in.read()*256);
in.read(filler);
pcxwidth = 1+xmax-xmin;
pcxheight = 1+ymax-ymin;
if(pcxwidth % 2 == 1)
{
/* The width of an PCX-Image must be even. That is why the
* width is increased when it was odd before.
*/
pcxwidth++;
wasOdd = true;
}
if(bits_per_pixel == 8 && color_planes == 1)
{
/* If the PCX-file has 256 colors there is a color-palete
* at the end of the file. This is 768b bytes long and
* contains the red- green- and blue-values of the colors.
*/
byte[] pal = new byte[768];
int[] intPal = new int[768];
imagebytes = (pcxwidth*pcxheight);
int[] imageData = new int[imagebytes];
readRLECompressedData(imagebytes, imageData, in);
if(in.available() > 769)
{
while(in.available() > 769)
{
in.read();
}
}
if(in.available() != 769)
{
System.err.println("Error in the palette!");
}
if(in.read()!=12)
{
System.err.println("Error in the palette!");
}
in.read(pal);
in.close();
for(int y = 0; y <767;y++)
{
intPal[y] = (int)(pal[y]);
if(intPal[y] < 0)
{
intPal[y] += 256;
}
}
/* Now the PcxReader converts the imagedata into the format
* of a MemoryImageSource.
*/
int RGBImageData[] = new int[imagebytes];
for(int i = 0; i < imagebytes; i++)
{
int paletteEntry = (int)(imageData[i]);
if(paletteEntry < 0) paletteEntry += 256;
RGBImageData[i] = new Color(intPal[paletteEntry*3],
intPal[paletteEntry*3+1],
intPal[paletteEntry*3+2]).getRGB();
}
ImageProducer prod = new MemoryImageSource(pcxwidth, pcxheight, RGBImageData, 0, pcxwidth);
picture = Toolkit.getDefaultToolkit().createImage(prod);
}
else if(bits_per_pixel == 8 && color_planes == 3) {
/* If the picture has 24 bit colors, there are 3 times many
* bytes as many pixels.
*/
imagebytes = (pcxwidth*pcxheight*3);
int[] imageData = new int[imagebytes];
readRLECompressedData(imagebytes, imageData, in);
int RGBImageData[] = new int[imagebytes];
for(int i = 0; i < pcxheight; i++)
{
for(int j = 0; j < pcxwidth; j++)
{
int red = imageData[i*3*pcxwidth+j];
int green = imageData[((i*3)+1)*pcxwidth+j];
int blue = imageData[((i*3)+2)*pcxwidth+j];
RGBImageData[i*pcxwidth+j] = new Color(red,green,blue).getRGB();
}
}
ImageProducer prod = new MemoryImageSource(pcxwidth, pcxheight, RGBImageData, 0, pcxwidth);
picture = Toolkit.getDefaultToolkit().createImage(prod);
}
}
catch (IOException e) {
System.err.println("Error reading PCX-File!");
}
return bufferImage(picture, BufferedImage.TYPE_INT_ARGB, wasOdd);
}
/**
* Reads the compressed data-stream and decompresses it in the memory.
* @param imagebytes
* @param imageData
* @param in
* @throws java.io.IOException
*/
private static void readRLECompressedData( int imagebytes, int[] imageData, InputStream in)
throws IOException {
int i;
int mode=NORMAL,nbytes=0;
int abyte = 0;
for(i = 0; i<imagebytes;i++)
{
if (mode == NORMAL)
{
abyte = in.read();
if(abyte > 191)
{
nbytes=abyte-192;
abyte =(byte)(in.read());
if (--nbytes > 0)
{
mode = RLE;
}
}
}
else if(--nbytes == 0)
{
mode = NORMAL;
}
imageData[i] = (int)(abyte);
if(imageData[i] < 0) imageData[i] += 256;
}
}
public static BufferedImage bufferImage(Image image, int type, boolean odd) {
BufferedImage bufferedImage = new BufferedImage(image.getWidth(null) - (odd?1:0), image.getHeight(null), type);
Graphics2D g = bufferedImage.createGraphics();
g.drawImage(image, 0, 0, null);
//waitForImage(bufferedImage);
return bufferedImage;
}
}