blob: 2095220aba20bfe7301c2bc7e942ef6006e94002 [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;
enikey3e9ff9f2008-12-24 03:30:29 +00006import java.io.DataOutputStream;
enikey2f811b82008-12-19 04:45:15 +00007import java.awt.Graphics;
8import java.awt.Image;
9import java.awt.image.ColorModel;
10import java.awt.image.DirectColorModel;
11import java.awt.image.MemoryImageSource;
12import java.awt.Color;
enikey663025d2008-12-19 05:14:15 +000013import java.awt.Toolkit;
enikey2f811b82008-12-19 04:45:15 +000014
enikeyb3e19f72008-12-19 04:54:49 +000015//
16// This is base decoder class.
17// Other classes will be childs of RawDecoder.
18//
enikeyccf6e7c2008-12-19 06:00:18 +000019
enikey00e0dbf2008-12-08 10:59:59 +000020public class RawDecoder {
21
enikey2f811b82008-12-19 04:45:15 +000022 public RawDecoder(Graphics g, RfbInputStream is) {
23 setGraphics(g);
24 setRfbInputStream(is);
enikeyb3e19f72008-12-19 04:54:49 +000025 // FIXME: cm24 created in getColorModel24.
26 // Remove if no bugs
enikey2f811b82008-12-19 04:45:15 +000027 cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
28 }
29
30 public RawDecoder(Graphics g, RfbInputStream is, int frameBufferW,
31 int frameBufferH) {
32 setGraphics(g);
33 setRfbInputStream(is);
34 setFrameBufferSize(frameBufferW, frameBufferH);
enikeyb3e19f72008-12-19 04:54:49 +000035 // FIXME: cm24 created in getColorModel24.
36 // Remove if no bugs
enikey2f811b82008-12-19 04:45:15 +000037 cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
38 }
39
enikey2c23ba12008-12-19 05:34:17 +000040 //
41 // Set methods to set value of non-static protected members of class
42 //
43
enikey2f811b82008-12-19 04:45:15 +000044 public void setRfbInputStream(RfbInputStream is) {
45 rfbis = is;
46 }
47
48 public void setGraphics(Graphics g) {
49 graphics = g;
50 }
51
52 public void setBPP(int bpp) {
53 bytesPerPixel = bpp;
54 }
55
enikey2c23ba12008-12-19 05:34:17 +000056 public void setFrameBufferSize(int w, int h) {
57 framebufferWidth = w;
58 framebufferHeight = h;
59 }
60
enikey292cf9d2008-12-19 05:30:11 +000061 public void setSessionRecorder(RecordInterface ri) {
62 rec = ri;
63 }
64
enikeyb3e19f72008-12-19 04:54:49 +000065 //
enikey3e9ff9f2008-12-24 03:30:29 +000066 // FIXME: Rename this method after we don't need RecordInterface
67 // in RawDecoder class to record session
68 //
69
70 public void setDataOutputStream(DataOutputStream os) {
71 dos = os;
72 }
73
74 //
enikeyb3e19f72008-12-19 04:54:49 +000075 // FIXME: This method may be useless in future, remove if so
76 //
77
enikey2f811b82008-12-19 04:45:15 +000078 public int getBPP() {
79 return bytesPerPixel;
80 }
81
enikeyb3e19f72008-12-19 04:54:49 +000082 //
enikey4f92da42008-12-19 05:28:12 +000083 // Decodes Raw Pixels data and draw it into graphics
84 //
85
86 public void handleRect(int x, int y, int w, int h) throws IOException, Exception {
87 if (bytesPerPixel == 1) {
88 for (int dy = y; dy < y + h; dy++) {
89 if (pixels8 != null) {
90 rfbis.readFully(pixels8, dy * framebufferWidth + x, w);
91 }
enikey2c23ba12008-12-19 05:34:17 +000092 //
93 // Save decoded data to RecordInterface
94 //
enikey4f92da42008-12-19 05:28:12 +000095 if (rec.canWrite()) {
96 rec.write(pixels8, dy * framebufferWidth + x, w);
97 }
98 }
99 } else {
100 byte[] buf = new byte[w * 4];
101 int i, offset;
102 for (int dy = y; dy < y + h; dy++) {
103 rfbis.readFully(buf);
104 //
105 // Save decoded data to RecordInterface
106 //
107 if (rec.canWrite()) {
108 rec.write(buf);
109 }
110 offset = dy * framebufferWidth + x;
111 if (pixels24 != null) {
112 for (i = 0; i < w; i++) {
113 pixels24[offset + i] =
114 (buf[i * 4 + 2] & 0xFF) << 16 |
115 (buf[i * 4 + 1] & 0xFF) << 8 |
116 (buf[i * 4] & 0xFF);
117 } //for
118 } // if
119 } // for
120 } // else
121 handleUpdatedPixels(x, y, w, h);
122 } // void
enikey3e9ff9f2008-12-24 03:30:29 +0000123
enikey4f92da42008-12-19 05:28:12 +0000124 //
125 // Display newly updated area of pixels.
126 //
enikey2c23ba12008-12-19 05:34:17 +0000127
enikey4f92da42008-12-19 05:28:12 +0000128 protected void handleUpdatedPixels(int x, int y, int w, int h) {
129 // Draw updated pixels of the off-screen image.
130 pixelsSource.newPixels(x, y, w, h);
131 graphics.setClip(x, y, w, h);
132 graphics.drawImage(rawPixelsImage, 0, 0, null);
133 graphics.setClip(0, 0, framebufferWidth, framebufferHeight);
134 }
135
136 //
enikey663025d2008-12-19 05:14:15 +0000137 // Updates pixels data.
enikey4f92da42008-12-19 05:28:12 +0000138 // This method must be called when framebuffer is resized
enikey663025d2008-12-19 05:14:15 +0000139 // or BPP is changed.
140 //
141
142 public void update() {
143 // Images with raw pixels should be re-allocated on every change
144 // of geometry or pixel format.
145 int fbWidth = framebufferWidth;
146 int fbHeight = framebufferHeight;
147
148 if (bytesPerPixel == 1) {
149 pixels24 = null;
150 pixels8 = new byte[fbWidth * fbHeight];
151 pixelsSource = new MemoryImageSource(fbWidth, fbHeight, getColorModel8(),
152 pixels8, 0, fbWidth);
153 } else {
154 pixels8 = null;
155 pixels24 = new int[fbWidth * fbHeight];
156 pixelsSource =
157 new MemoryImageSource(fbWidth, fbHeight, cm24, pixels24, 0, fbWidth);
158 }
159 pixelsSource.setAnimated(true);
160 rawPixelsImage = Toolkit.getDefaultToolkit().createImage(pixelsSource);
161 }
162
163 //
enikey1924c442008-12-19 05:36:36 +0000164 // Private static members access methods
enikeyb3e19f72008-12-19 04:54:49 +0000165 //
166
167 protected ColorModel getColorModel8() {
168 if (cm8 == null) {
169 cm8 = cm8 = new DirectColorModel(8, 7, (7 << 3), (3 << 6));
170 }
171 return cm8;
172 }
173
174 protected ColorModel getColorModel24() {
175 if (cm24 == null) {
176 cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
177 }
178 return cm24;
179 }
180
181 protected Color[]getColor256() {
182 if (color256 == null) {
183 color256 = new Color[256];
184 for (int i = 0; i < 256; i++)
185 color256[i] = new Color(cm8.getRGB(i));
186 }
187 return color256;
188 }
189
190 //
191 // Unique data for every decoder (? maybe not ?)
192 //
enikey2c23ba12008-12-19 05:34:17 +0000193
enikey2f811b82008-12-19 04:45:15 +0000194 protected int bytesPerPixel = 4;
195 protected int framebufferWidth = 0;
196 protected int framebufferHeight = 0;
197 protected RfbInputStream rfbis = null;
198 protected Graphics graphics = null;
199 protected RecordInterface rec = null;
enikey3e9ff9f2008-12-24 03:30:29 +0000200 protected DataOutputStream dos = null;
enikey2f811b82008-12-19 04:45:15 +0000201
enikeyb3e19f72008-12-19 04:54:49 +0000202 //
203 // This data must be shared between decoders
204 //
enikey2c23ba12008-12-19 05:34:17 +0000205
enikey2f811b82008-12-19 04:45:15 +0000206 protected static byte []pixels8 = null;
207 protected static int []pixels24 = null;
208 protected static MemoryImageSource pixelsSource = null;
209 protected static Image rawPixelsImage = null;
210
enikeyb3e19f72008-12-19 04:54:49 +0000211 //
212 // Access to this static members only though protected methods
213 //
enikey2c23ba12008-12-19 05:34:17 +0000214
enikey2f811b82008-12-19 04:45:15 +0000215 private static ColorModel cm8 = null;
216 private static ColorModel cm24 = null;
217 private static Color []color256 = null;
enikey00e0dbf2008-12-08 10:59:59 +0000218}