]> source.dussan.org Git - tigervnc.git/commitdiff
[Developement] Added decode methods to ZRLE decoder class.
authorenikey <enikey@3789f03b-4d11-0410-bbf8-ca57d06f2519>
Fri, 19 Dec 2008 07:45:53 +0000 (07:45 +0000)
committerenikey <enikey@3789f03b-4d11-0410-bbf8-ca57d06f2519>
Fri, 19 Dec 2008 07:45:53 +0000 (07:45 +0000)
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@3430 3789f03b-4d11-0410-bbf8-ca57d06f2519

java/src/com/tightvnc/decoder/ZRLEDecoder.java

index 6c692708f29d199a1df4a7cbee5831f536eaf513..ba4071cea9f00e00b77255e491251f4944546e7e 100644 (file)
@@ -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
   //