blob: 478a668e056e3ca81fa1a867a2b5efe17856dae7 [file] [log] [blame]
package com.tigervnc.decoder;
import com.tigervnc.vncviewer.RfbInputStream;
import java.io.IOException;
import java.io.DataOutput;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.ColorModel;
import java.awt.image.DirectColorModel;
import java.awt.image.MemoryImageSource;
import java.awt.Color;
import java.awt.Toolkit;
//
// This is base decoder class.
// Other classes will be childs of RawDecoder.
//
public class RawDecoder {
final static int EncodingRaw = 0;
public RawDecoder(Graphics g, RfbInputStream is) {
setGraphics(g);
setRfbInputStream(is);
}
public RawDecoder(Graphics g, RfbInputStream is, int frameBufferW,
int frameBufferH) {
setGraphics(g);
setRfbInputStream(is);
setFrameBufferSize(frameBufferW, frameBufferH);
// FIXME: cm24 created in getColorModel24.
// Remove if no bugs
cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
}
//
// Set methods to set value of non-static protected members of class
//
public void setRfbInputStream(RfbInputStream is) {
rfbis = is;
}
public void setGraphics(Graphics g) {
graphics = g;
}
public void setBPP(int bpp) {
bytesPerPixel = bpp;
}
public void setFrameBufferSize(int w, int h) {
framebufferWidth = w;
framebufferHeight = h;
}
//
// FIXME: Rename this method after we don't need RecordInterface
// in RawDecoder class to record session
//
public void setDataOutputStream(DataOutput os) {
dos = os;
}
//
// Decodes Raw Pixels data and draw it into graphics
//
public void handleRect(int x, int y, int w, int h) throws IOException, Exception {
//
// Write encoding ID to record output stream
//
if ((dos != null) && (enableEncodingRecordWritting)) {
dos.writeInt(RawDecoder.EncodingRaw);
}
if (bytesPerPixel == 1) {
for (int dy = y; dy < y + h; dy++) {
if (pixels8 != null) {
rfbis.readFully(pixels8, dy * framebufferWidth + x, w);
}
//
// Save decoded data to record output stream
//
if (dos != null) {
dos.write(pixels8, dy * framebufferWidth + x, w);
}
}
} else {
byte[] buf = new byte[w * 4];
int i, offset;
for (int dy = y; dy < y + h; dy++) {
rfbis.readFully(buf);
//
// Save decoded data to record output stream
//
if (dos != null) {
dos.write(buf);
}
offset = dy * framebufferWidth + x;
if (pixels24 != null) {
for (i = 0; i < w; i++) {
pixels24[offset + i] =
(buf[i * 4 + 2] & 0xFF) << 16 |
(buf[i * 4 + 1] & 0xFF) << 8 |
(buf[i * 4] & 0xFF);
} //for
} // if
} // for
} // else
handleUpdatedPixels(x, y, w, h);
} // void
//
// Display newly updated area of pixels.
//
protected void handleUpdatedPixels(int x, int y, int w, int h) {
// Draw updated pixels of the off-screen image.
pixelsSource.newPixels(x, y, w, h);
graphics.setClip(x, y, w, h);
graphics.drawImage(rawPixelsImage, 0, 0, null);
graphics.setClip(0, 0, framebufferWidth, framebufferHeight);
}
//
// Updates pixels data.
// This method must be called when framebuffer is resized
// or BPP is changed.
//
public void update() {
// Images with raw pixels should be re-allocated on every change
// of geometry or pixel format.
int fbWidth = framebufferWidth;
int fbHeight = framebufferHeight;
if (bytesPerPixel == 1) {
pixels24 = null;
pixels8 = new byte[fbWidth * fbHeight];
pixelsSource = new MemoryImageSource(fbWidth, fbHeight, getColorModel8(),
pixels8, 0, fbWidth);
} else {
pixels8 = null;
pixels24 = new int[fbWidth * fbHeight];
pixelsSource =
new MemoryImageSource(fbWidth, fbHeight, cm24, pixels24, 0, fbWidth);
}
pixelsSource.setAnimated(true);
rawPixelsImage = Toolkit.getDefaultToolkit().createImage(pixelsSource);
}
//
// Private static members access methods
//
protected ColorModel getColorModel8() {
if (cm8 == null) {
cm8 = cm8 = new DirectColorModel(8, 7, (7 << 3), (3 << 6));
}
return cm8;
}
protected ColorModel getColorModel24() {
if (cm24 == null) {
cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
}
return cm24;
}
protected Color[]getColor256() {
if (color256 == null) {
color256 = new Color[256];
for (int i = 0; i < 256; i++)
color256[i] = new Color(cm8.getRGB(i));
}
return color256;
}
//
// This method will be used by HextileDecoder to disable
// double writting encoding id to record stream.
//
// FIXME: Try to find better solution than this.
//
protected void enableEncodingRecordWritting(boolean enable) {
enableEncodingRecordWritting = enable;
}
//
// Unique data for every decoder (? maybe not ?)
//
protected int bytesPerPixel = 4;
protected int framebufferWidth = 0;
protected int framebufferHeight = 0;
protected RfbInputStream rfbis = null;
protected Graphics graphics = null;
protected DataOutput dos = null;
protected boolean enableEncodingRecordWritting = true;
//
// This data must be shared between decoders
//
protected static byte []pixels8 = null;
protected static int []pixels24 = null;
protected static MemoryImageSource pixelsSource = null;
protected static Image rawPixelsImage = null;
//
// Access to this static members only though protected methods
//
private static ColorModel cm8 = null;
private static ColorModel cm24 = null;
private static Color []color256 = null;
}