blob: f2442107b6de419c46a91e952a6548c534d7976e [file] [log] [blame]
enikey00e0dbf2008-12-08 10:59:59 +00001package com.tightvnc.decoder;
2
enikey2f811b82008-12-19 04:45:15 +00003import com.tightvnc.vncviewer.RecordInterface;
4import com.tightvnc.vncviewer.RfbInputStream;
enikey4f92da42008-12-19 05:28:12 +00005import java.io.IOException;
enikey2f811b82008-12-19 04:45:15 +00006import java.awt.Graphics;
7import java.awt.Image;
8import java.awt.image.ColorModel;
9import java.awt.image.DirectColorModel;
10import java.awt.image.MemoryImageSource;
11import java.awt.Color;
enikey663025d2008-12-19 05:14:15 +000012import java.awt.Toolkit;
enikey2f811b82008-12-19 04:45:15 +000013
enikeyb3e19f72008-12-19 04:54:49 +000014//
15// This is base decoder class.
16// Other classes will be childs of RawDecoder.
17//
enikeyccf6e7c2008-12-19 06:00:18 +000018
enikey00e0dbf2008-12-08 10:59:59 +000019public class RawDecoder {
20
enikey2f811b82008-12-19 04:45:15 +000021 public RawDecoder(Graphics g, RfbInputStream is) {
22 setGraphics(g);
23 setRfbInputStream(is);
enikeyb3e19f72008-12-19 04:54:49 +000024 // FIXME: cm24 created in getColorModel24.
25 // Remove if no bugs
enikey2f811b82008-12-19 04:45:15 +000026 cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
27 }
28
29 public RawDecoder(Graphics g, RfbInputStream is, int frameBufferW,
30 int frameBufferH) {
31 setGraphics(g);
32 setRfbInputStream(is);
33 setFrameBufferSize(frameBufferW, frameBufferH);
enikeyb3e19f72008-12-19 04:54:49 +000034 // FIXME: cm24 created in getColorModel24.
35 // Remove if no bugs
enikey2f811b82008-12-19 04:45:15 +000036 cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
37 }
38
enikey2c23ba12008-12-19 05:34:17 +000039 //
40 // Set methods to set value of non-static protected members of class
41 //
42
enikey2f811b82008-12-19 04:45:15 +000043 public void setRfbInputStream(RfbInputStream is) {
44 rfbis = is;
45 }
46
47 public void setGraphics(Graphics g) {
48 graphics = g;
49 }
50
51 public void setBPP(int bpp) {
52 bytesPerPixel = bpp;
53 }
54
enikey2c23ba12008-12-19 05:34:17 +000055 public void setFrameBufferSize(int w, int h) {
56 framebufferWidth = w;
57 framebufferHeight = h;
58 }
59
enikey292cf9d2008-12-19 05:30:11 +000060 public void setSessionRecorder(RecordInterface ri) {
61 rec = ri;
62 }
63
enikeyb3e19f72008-12-19 04:54:49 +000064 //
65 // FIXME: This method may be useless in future, remove if so
66 //
67
enikey2f811b82008-12-19 04:45:15 +000068 public int getBPP() {
69 return bytesPerPixel;
70 }
71
enikeyb3e19f72008-12-19 04:54:49 +000072 //
enikey4f92da42008-12-19 05:28:12 +000073 // Decodes Raw Pixels data and draw it into graphics
74 //
75
76 public void handleRect(int x, int y, int w, int h) throws IOException, Exception {
77 if (bytesPerPixel == 1) {
78 for (int dy = y; dy < y + h; dy++) {
79 if (pixels8 != null) {
80 rfbis.readFully(pixels8, dy * framebufferWidth + x, w);
81 }
enikey2c23ba12008-12-19 05:34:17 +000082 //
83 // Save decoded data to RecordInterface
84 //
enikey4f92da42008-12-19 05:28:12 +000085 if (rec.canWrite()) {
86 rec.write(pixels8, dy * framebufferWidth + x, w);
87 }
88 }
89 } else {
90 byte[] buf = new byte[w * 4];
91 int i, offset;
92 for (int dy = y; dy < y + h; dy++) {
93 rfbis.readFully(buf);
94 //
95 // Save decoded data to RecordInterface
96 //
97 if (rec.canWrite()) {
98 rec.write(buf);
99 }
100 offset = dy * framebufferWidth + x;
101 if (pixels24 != null) {
102 for (i = 0; i < w; i++) {
103 pixels24[offset + i] =
104 (buf[i * 4 + 2] & 0xFF) << 16 |
105 (buf[i * 4 + 1] & 0xFF) << 8 |
106 (buf[i * 4] & 0xFF);
107 } //for
108 } // if
109 } // for
110 } // else
111 handleUpdatedPixels(x, y, w, h);
112 } // void
113
114 //
115 // Display newly updated area of pixels.
116 //
enikey2c23ba12008-12-19 05:34:17 +0000117
enikey4f92da42008-12-19 05:28:12 +0000118 protected void handleUpdatedPixels(int x, int y, int w, int h) {
119 // Draw updated pixels of the off-screen image.
120 pixelsSource.newPixels(x, y, w, h);
121 graphics.setClip(x, y, w, h);
122 graphics.drawImage(rawPixelsImage, 0, 0, null);
123 graphics.setClip(0, 0, framebufferWidth, framebufferHeight);
124 }
125
126 //
enikey663025d2008-12-19 05:14:15 +0000127 // Updates pixels data.
enikey4f92da42008-12-19 05:28:12 +0000128 // This method must be called when framebuffer is resized
enikey663025d2008-12-19 05:14:15 +0000129 // or BPP is changed.
130 //
131
132 public void update() {
133 // Images with raw pixels should be re-allocated on every change
134 // of geometry or pixel format.
135 int fbWidth = framebufferWidth;
136 int fbHeight = framebufferHeight;
137
138 if (bytesPerPixel == 1) {
139 pixels24 = null;
140 pixels8 = new byte[fbWidth * fbHeight];
141 pixelsSource = new MemoryImageSource(fbWidth, fbHeight, getColorModel8(),
142 pixels8, 0, fbWidth);
143 } else {
144 pixels8 = null;
145 pixels24 = new int[fbWidth * fbHeight];
146 pixelsSource =
147 new MemoryImageSource(fbWidth, fbHeight, cm24, pixels24, 0, fbWidth);
148 }
149 pixelsSource.setAnimated(true);
150 rawPixelsImage = Toolkit.getDefaultToolkit().createImage(pixelsSource);
151 }
152
153 //
enikey1924c442008-12-19 05:36:36 +0000154 // Private static members access methods
enikeyb3e19f72008-12-19 04:54:49 +0000155 //
156
157 protected ColorModel getColorModel8() {
158 if (cm8 == null) {
159 cm8 = cm8 = new DirectColorModel(8, 7, (7 << 3), (3 << 6));
160 }
161 return cm8;
162 }
163
164 protected ColorModel getColorModel24() {
165 if (cm24 == null) {
166 cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
167 }
168 return cm24;
169 }
170
171 protected Color[]getColor256() {
172 if (color256 == null) {
173 color256 = new Color[256];
174 for (int i = 0; i < 256; i++)
175 color256[i] = new Color(cm8.getRGB(i));
176 }
177 return color256;
178 }
179
180 //
181 // Unique data for every decoder (? maybe not ?)
182 //
enikey2c23ba12008-12-19 05:34:17 +0000183
enikey2f811b82008-12-19 04:45:15 +0000184 protected int bytesPerPixel = 4;
185 protected int framebufferWidth = 0;
186 protected int framebufferHeight = 0;
187 protected RfbInputStream rfbis = null;
188 protected Graphics graphics = null;
189 protected RecordInterface rec = null;
190
enikeyb3e19f72008-12-19 04:54:49 +0000191 //
192 // This data must be shared between decoders
193 //
enikey2c23ba12008-12-19 05:34:17 +0000194
enikey2f811b82008-12-19 04:45:15 +0000195 protected static byte []pixels8 = null;
196 protected static int []pixels24 = null;
197 protected static MemoryImageSource pixelsSource = null;
198 protected static Image rawPixelsImage = null;
199
enikeyb3e19f72008-12-19 04:54:49 +0000200 //
201 // Access to this static members only though protected methods
202 //
enikey2c23ba12008-12-19 05:34:17 +0000203
enikey2f811b82008-12-19 04:45:15 +0000204 private static ColorModel cm8 = null;
205 private static ColorModel cm24 = null;
206 private static Color []color256 = null;
enikey00e0dbf2008-12-08 10:59:59 +0000207}