From 4f3dac9f04b5663e5d210832cf03f139f6d570a7 Mon Sep 17 00:00:00 2001 From: enikey Date: Fri, 19 Dec 2008 07:45:53 +0000 Subject: [PATCH] [Developement] Added decode methods to ZRLE decoder class. git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@3430 3789f03b-4d11-0410-bbf8-ca57d06f2519 --- .../src/com/tightvnc/decoder/ZRLEDecoder.java | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) diff --git a/java/src/com/tightvnc/decoder/ZRLEDecoder.java b/java/src/com/tightvnc/decoder/ZRLEDecoder.java index 6c692708..ba4071ce 100644 --- a/java/src/com/tightvnc/decoder/ZRLEDecoder.java +++ b/java/src/com/tightvnc/decoder/ZRLEDecoder.java @@ -4,6 +4,11 @@ import com.tightvnc.vncviewer.InStream; import com.tightvnc.vncviewer.RfbInputStream; import com.tightvnc.vncviewer.ZlibInStream; import java.awt.Graphics; +import com.tightvnc.vncviewer.MemInStream; +import java.awt.Color; +import java.awt.Toolkit; +import java.awt.image.MemoryImageSource; +import java.io.IOException; // // Class that used for decoding ZRLE encoded data. @@ -20,6 +25,140 @@ public class ZRLEDecoder extends RawDecoder { super(g, is, frameBufferW, frameBufferH); } + // + // Handle a ZRLE-encoded rectangle. + // + // FIXME: Currently, session recording is not fully supported for ZRLE. + // + + public void handleRect(int x, int y, int w, int h) throws IOException, Exception { + if (zrleInStream == null) + zrleInStream = new ZlibInStream(); + + int nBytes = rfbis.readU32(); + if (nBytes > 64 * 1024 * 1024) + throw new Exception("ZRLE decoder: illegal compressed data size"); + + if (zrleBuf == null || zrleBufLen < nBytes) { + zrleBufLen = nBytes + 4096; + zrleBuf = new byte[zrleBufLen]; + } + + // FIXME: Do not wait for all the data before decompression. + rfbis.readFully(zrleBuf, 0, nBytes); + + // + // Override handleRect method to decode RRE encoded data insted of + // raw pixel data. + // + + if (rec.canWrite()) { + if (rec.isRecordFromBeginning()) { + rec.writeIntBE(nBytes); + rec.write(zrleBuf, 0, nBytes); + } else if (!zrleRecWarningShown) { + System.out.println("Warning: ZRLE session can be recorded" + + " only from the beginning"); + System.out.println("Warning: Recorded file may be corrupted"); + zrleRecWarningShown = true; + } + } + + zrleInStream.setUnderlying(new MemInStream(zrleBuf, 0, nBytes), nBytes); + + for (int ty = y; ty < y+h; ty += 64) { + + int th = Math.min(y+h-ty, 64); + + for (int tx = x; tx < x+w; tx += 64) { + + int tw = Math.min(x+w-tx, 64); + + int mode = zrleInStream.readU8(); + boolean rle = (mode & 128) != 0; + int palSize = mode & 127; + int[] palette = new int[128]; + + readZrlePalette(palette, palSize); + + if (palSize == 1) { + int pix = palette[0]; + Color c = (bytesPerPixel == 1) ? + getColor256()[pix] : new Color(0xFF000000 | pix); + graphics.setColor(c); + graphics.fillRect(tx, ty, tw, th); + continue; + } + + if (!rle) { + if (palSize == 0) { + readZrleRawPixels(tw, th); + } else { + readZrlePackedPixels(tw, th, palette, palSize); + } + } else { + if (palSize == 0) { + readZrlePlainRLEPixels(tw, th); + } else { + readZrlePackedRLEPixels(tw, th, palette); + } + } + handleUpdatedZrleTile(tx, ty, tw, th); + } + } + zrleInStream.reset(); + } + + // + // Override update() method cause we have own data that + // must be updated 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) { + RawDecoder.pixels24 = null; + RawDecoder.pixels8 = new byte[fbWidth * fbHeight]; + RawDecoder.pixelsSource = new MemoryImageSource(fbWidth, fbHeight, getColorModel8(), pixels8, 0, fbWidth); + zrleTilePixels24 = null; + zrleTilePixels8 = new byte[64 * 64]; + } else { + RawDecoder.pixels8 = null; + RawDecoder.pixels24 = new int[fbWidth * fbHeight]; + RawDecoder.pixelsSource = + new MemoryImageSource(fbWidth, fbHeight, getColorModel24(), pixels24, 0, fbWidth); + zrleTilePixels8 = null; + zrleTilePixels24 = new int[64 * 64]; + } + RawDecoder.pixelsSource.setAnimated(true); + RawDecoder.rawPixelsImage = Toolkit.getDefaultToolkit().createImage(pixelsSource); + } + + // + // Copy pixels from zrleTilePixels8 or zrleTilePixels24, then update. + // + + private void handleUpdatedZrleTile(int x, int y, int w, int h) { + Object src, dst; + if (bytesPerPixel == 1) { + src = zrleTilePixels8; dst = pixels8; + } else { + src = zrleTilePixels24; dst = pixels24; + } + int offsetSrc = 0; + int offsetDst = (y * framebufferWidth + x); + for (int j = 0; j < h; j++) { + System.arraycopy(src, offsetSrc, dst, offsetDst, w); + offsetSrc += w; + offsetDst += framebufferWidth; + } + handleUpdatedPixels(x, y, w, h); + } + // // Private methods for reading ZRLE data // -- 2.39.5