/*
* Created on 2005-10-04 by Piotrm
*
*/
package org.getopt.pcl5.PCL5Interpreter;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import org.getopt.pcl5.PrinterState;
public class RasterGraphics {
private final static int BUFFER_INCREMENT = 128;
private int _height;
private int _width;
private int _position;
private BufferedImage _image;
// private Graphics2D _graphics;
private Point _start;
private Point _end;
public RasterGraphics(int width, int height) {
_width = width;
_height = height;
createImage();
}
protected void createImage() {
_image = new BufferedImage(_width, _height, BufferedImage.TYPE_BYTE_GRAY);
Graphics2D graphics = _image.createGraphics();
// _graphics.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
// RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
// Clear image with transparent alpha by drawing a rectangle
// _graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR,
// 0.0f));
Rectangle2D.Double rect = new Rectangle2D.Double(0, 0, _width, _height);
graphics.setColor(Color.WHITE);
graphics.fill(rect);
// _graphics.setComposite(AlphaComposite.SrcOver);
graphics.setColor(Color.BLACK);
_start = new Point(_width, _height);
_end = new Point(0, 0);
}
public int decodeImage(byte[] data, int compressionMethod, int x, int y,
int w, int h) {
byte[] decodedData;
if (compressionMethod == PrinterState.CompressionMode.TIFF)
decodedData = decompressTIFF(data);
else
decodedData = data;
if (h == 0)
h = 1;
if (w == 0)
w = decodedData.length * 8;
// calculate 'real' side of image, for cropping
if (x < _start.x)
_start.x = x;
if (y < _start.y)
_start.y = y;
if (x + w > _end.x)
_end.x = x + w;
if (y + h > _end.y)
_end.y = y + h;
fillPattern(decodedData, x, y, w, h);
return h;
}
// -3 Literal Pattern Values
// # of Bytes Binary value Decimal value
// 1 0000 0000 1
// to to to
// 127 0111 1111 127
//
// No Operation Value
// NOP value Binary value Decimal value
// 128 (-128) 1000 000 128
//
// Repeated Pattern Values
// # of Repetitions Binary value Decimal value
// 1 (-1) 1111 1111 255
// to to to
// 127 (-127) 1000 0001 129
private byte[] decompressTIFF(byte[] data) {
int offset = 0;
byte[] decodedData = new byte[BUFFER_INCREMENT];
_position = 0;
while (offset < data.length) {
offset = decompress(decodedData, offset, data);
if (_position + 128 > decodedData.length) {
byte[] newData = new byte[decodedData.length + BUFFER_INCREMENT];
System.arraycopy(decodedData, 0, newData, 0, _position);
decodedData = newData;
}
}
byte[] newData = new byte[_position];
System.arraycopy(decodedData, 0, newData, 0, _position);
decodedData = newData;
return decodedData;
}
private int decompress(byte[] dest, int offset, byte[] src) {
int n = src[offset++];
if (n >= 0 && n < 128) {
n++;
copyData(dest, src, offset, n);
offset += n;
} else if (n < 0 && n != 128) {
n = Math.abs(n);
n++;
repeatByte(dest, src[offset], n);
offset++;
}
return offset;
}
private void repeatByte(byte[] dest, byte b, int n) {
while (n > 0) {
dest[_position] = b;
n--;
_position++;
}
}
private void copyData(byte[] dest, byte[] src, int offset, int n) {
while (n > 0) {
dest[_position] = src[offset++];
n--;
_position++;
}
}
protected void fillPattern(byte[] src, int dx, int dy, int w, int h) {
int bytesInRow = (w / 8) + 1;
for (int y = 0; y < _height; y++) {
for (int i = 0; i < bytesInRow; i++) {
int offset = y * bytesInRow + i;
if (offset < src.length) {
byte b = src[offset];
if (b != 0x00)
draw8bits(b, i * 8 + dx, y + dy);
}
}
}
}
protected void draw8bits(byte bits, int x, int y) {
// if (bits == -1)
// _graphics.fillRect(x, y, 8, 1);
// else
{
px(bits & 0x01, x + 7, y);
px(bits & 0x02, x + 6, y);
px(bits & 0x04, x + 5, y);
px(bits & 0x08, x + 4, y);
px(bits & 0x10, x + 3, y);
px(bits & 0x20, x + 2, y);
px(bits & 0x40, x + 1, y);
px(bits & 0x80, x + 0, y);
}
}
private void px(int bit, int x, int y) {
if (bit != 0)
_image.setRGB(x, y, 0xFF000000);
// _graphics.fillRect(x, y, 1, 1 );
}
/**
* @return Returns the image.
*/
public BufferedImage getImage() {
int w = _end.x - _start.x;
int h = _end.y - _start.y;
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY);
Graphics2D graphics = image.createGraphics();
graphics.drawImage(_image, -_start.x, -_start.y, null);
return image;
}
public Point getStart() {
return _start;
}
}