diff options
Diffstat (limited to 'java/src/com/tigervnc/decoder/RawDecoder.java')
-rw-r--r-- | java/src/com/tigervnc/decoder/RawDecoder.java | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/java/src/com/tigervnc/decoder/RawDecoder.java b/java/src/com/tigervnc/decoder/RawDecoder.java new file mode 100644 index 00000000..9ef167a7 --- /dev/null +++ b/java/src/com/tigervnc/decoder/RawDecoder.java @@ -0,0 +1,223 @@ +package com.tightvnc.decoder; + +import com.tightvnc.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; +} |