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; }