blob: affdc67925049d713df11eed2551359d5e8ee076 [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;
enikeyc6f6bab2008-12-24 03:41:00 +00006import java.io.DataOutput;
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 {
enikey6558a302008-12-24 05:14:30 +000021 final static int EncodingRaw = 0;
enikey00e0dbf2008-12-08 10:59:59 +000022
enikey2f811b82008-12-19 04:45:15 +000023 public RawDecoder(Graphics g, RfbInputStream is) {
24 setGraphics(g);
25 setRfbInputStream(is);
enikeyb3e19f72008-12-19 04:54:49 +000026 // FIXME: cm24 created in getColorModel24.
27 // Remove if no bugs
enikey2f811b82008-12-19 04:45:15 +000028 cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
29 }
30
31 public RawDecoder(Graphics g, RfbInputStream is, int frameBufferW,
32 int frameBufferH) {
33 setGraphics(g);
34 setRfbInputStream(is);
35 setFrameBufferSize(frameBufferW, frameBufferH);
enikeyb3e19f72008-12-19 04:54:49 +000036 // FIXME: cm24 created in getColorModel24.
37 // Remove if no bugs
enikey2f811b82008-12-19 04:45:15 +000038 cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
39 }
40
enikey2c23ba12008-12-19 05:34:17 +000041 //
42 // Set methods to set value of non-static protected members of class
43 //
44
enikey2f811b82008-12-19 04:45:15 +000045 public void setRfbInputStream(RfbInputStream is) {
46 rfbis = is;
47 }
48
49 public void setGraphics(Graphics g) {
50 graphics = g;
51 }
52
53 public void setBPP(int bpp) {
54 bytesPerPixel = bpp;
55 }
56
enikey2c23ba12008-12-19 05:34:17 +000057 public void setFrameBufferSize(int w, int h) {
58 framebufferWidth = w;
59 framebufferHeight = h;
60 }
61
enikey292cf9d2008-12-19 05:30:11 +000062 public void setSessionRecorder(RecordInterface ri) {
63 rec = ri;
64 }
65
enikeyb3e19f72008-12-19 04:54:49 +000066 //
enikey3e9ff9f2008-12-24 03:30:29 +000067 // FIXME: Rename this method after we don't need RecordInterface
68 // in RawDecoder class to record session
69 //
70
enikeyc6f6bab2008-12-24 03:41:00 +000071 public void setDataOutputStream(DataOutput os) {
enikey3e9ff9f2008-12-24 03:30:29 +000072 dos = os;
73 }
74
75 //
enikeyb3e19f72008-12-19 04:54:49 +000076 // FIXME: This method may be useless in future, remove if so
77 //
78
enikey2f811b82008-12-19 04:45:15 +000079 public int getBPP() {
80 return bytesPerPixel;
81 }
82
enikeyb3e19f72008-12-19 04:54:49 +000083 //
enikey4f92da42008-12-19 05:28:12 +000084 // Decodes Raw Pixels data and draw it into graphics
85 //
86
87 public void handleRect(int x, int y, int w, int h) throws IOException, Exception {
enikey2f0294e2008-12-24 08:18:54 +000088
89 //
90 // Write encoding ID to record output stream
91 //
92
93 if ((dos != null) && (enableEncodingRecordWritting)) {
94 dos.writeInt(RawDecoder.EncodingRaw);
95 }
96
enikey4f92da42008-12-19 05:28:12 +000097 if (bytesPerPixel == 1) {
98 for (int dy = y; dy < y + h; dy++) {
99 if (pixels8 != null) {
100 rfbis.readFully(pixels8, dy * framebufferWidth + x, w);
101 }
enikey2c23ba12008-12-19 05:34:17 +0000102 //
enikey5276d792008-12-24 04:12:34 +0000103 // Save decoded data to record output stream
enikey2c23ba12008-12-19 05:34:17 +0000104 //
enikey5276d792008-12-24 04:12:34 +0000105 if (dos != null) {
106 dos.write(pixels8, dy * framebufferWidth + x, w);
enikey4f92da42008-12-19 05:28:12 +0000107 }
108 }
109 } else {
110 byte[] buf = new byte[w * 4];
111 int i, offset;
112 for (int dy = y; dy < y + h; dy++) {
113 rfbis.readFully(buf);
114 //
enikey5276d792008-12-24 04:12:34 +0000115 // Save decoded data to record output stream
enikey4f92da42008-12-19 05:28:12 +0000116 //
enikey5276d792008-12-24 04:12:34 +0000117 if (dos != null) {
118 dos.write(buf);
enikey4f92da42008-12-19 05:28:12 +0000119 }
120 offset = dy * framebufferWidth + x;
121 if (pixels24 != null) {
122 for (i = 0; i < w; i++) {
123 pixels24[offset + i] =
124 (buf[i * 4 + 2] & 0xFF) << 16 |
125 (buf[i * 4 + 1] & 0xFF) << 8 |
126 (buf[i * 4] & 0xFF);
127 } //for
128 } // if
129 } // for
130 } // else
131 handleUpdatedPixels(x, y, w, h);
132 } // void
enikey3e9ff9f2008-12-24 03:30:29 +0000133
enikey4f92da42008-12-19 05:28:12 +0000134 //
135 // Display newly updated area of pixels.
136 //
enikey2c23ba12008-12-19 05:34:17 +0000137
enikey4f92da42008-12-19 05:28:12 +0000138 protected void handleUpdatedPixels(int x, int y, int w, int h) {
139 // Draw updated pixels of the off-screen image.
140 pixelsSource.newPixels(x, y, w, h);
141 graphics.setClip(x, y, w, h);
142 graphics.drawImage(rawPixelsImage, 0, 0, null);
143 graphics.setClip(0, 0, framebufferWidth, framebufferHeight);
144 }
145
146 //
enikey663025d2008-12-19 05:14:15 +0000147 // Updates pixels data.
enikey4f92da42008-12-19 05:28:12 +0000148 // This method must be called when framebuffer is resized
enikey663025d2008-12-19 05:14:15 +0000149 // or BPP is changed.
150 //
151
152 public void update() {
153 // Images with raw pixels should be re-allocated on every change
154 // of geometry or pixel format.
155 int fbWidth = framebufferWidth;
156 int fbHeight = framebufferHeight;
157
158 if (bytesPerPixel == 1) {
159 pixels24 = null;
160 pixels8 = new byte[fbWidth * fbHeight];
161 pixelsSource = new MemoryImageSource(fbWidth, fbHeight, getColorModel8(),
162 pixels8, 0, fbWidth);
163 } else {
164 pixels8 = null;
165 pixels24 = new int[fbWidth * fbHeight];
166 pixelsSource =
167 new MemoryImageSource(fbWidth, fbHeight, cm24, pixels24, 0, fbWidth);
168 }
169 pixelsSource.setAnimated(true);
170 rawPixelsImage = Toolkit.getDefaultToolkit().createImage(pixelsSource);
171 }
172
173 //
enikey1924c442008-12-19 05:36:36 +0000174 // Private static members access methods
enikeyb3e19f72008-12-19 04:54:49 +0000175 //
176
177 protected ColorModel getColorModel8() {
178 if (cm8 == null) {
179 cm8 = cm8 = new DirectColorModel(8, 7, (7 << 3), (3 << 6));
180 }
181 return cm8;
182 }
183
184 protected ColorModel getColorModel24() {
185 if (cm24 == null) {
186 cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
187 }
188 return cm24;
189 }
190
191 protected Color[]getColor256() {
192 if (color256 == null) {
193 color256 = new Color[256];
194 for (int i = 0; i < 256; i++)
195 color256[i] = new Color(cm8.getRGB(i));
196 }
197 return color256;
198 }
199
200 //
enikey2f0294e2008-12-24 08:18:54 +0000201 // This method will be used by HextileDecoder to disable
202 // double writting encoding id to record stream.
203 //
204 // FIXME: Try to find better solution than this.
205 //
206
207 protected void enableEncodingRecordWritting(boolean enable) {
208 enableEncodingRecordWritting = enable;
209 }
210
211 //
enikeyb3e19f72008-12-19 04:54:49 +0000212 // Unique data for every decoder (? maybe not ?)
213 //
enikey2c23ba12008-12-19 05:34:17 +0000214
enikey2f811b82008-12-19 04:45:15 +0000215 protected int bytesPerPixel = 4;
216 protected int framebufferWidth = 0;
217 protected int framebufferHeight = 0;
218 protected RfbInputStream rfbis = null;
219 protected Graphics graphics = null;
220 protected RecordInterface rec = null;
enikeyc6f6bab2008-12-24 03:41:00 +0000221 protected DataOutput dos = null;
enikey2f0294e2008-12-24 08:18:54 +0000222 protected boolean enableEncodingRecordWritting = true;
enikey2f811b82008-12-19 04:45:15 +0000223
enikeyb3e19f72008-12-19 04:54:49 +0000224 //
225 // This data must be shared between decoders
226 //
enikey2c23ba12008-12-19 05:34:17 +0000227
enikey2f811b82008-12-19 04:45:15 +0000228 protected static byte []pixels8 = null;
229 protected static int []pixels24 = null;
230 protected static MemoryImageSource pixelsSource = null;
231 protected static Image rawPixelsImage = null;
232
enikeyb3e19f72008-12-19 04:54:49 +0000233 //
234 // Access to this static members only though protected methods
235 //
enikey2c23ba12008-12-19 05:34:17 +0000236
enikey2f811b82008-12-19 04:45:15 +0000237 private static ColorModel cm8 = null;
238 private static ColorModel cm24 = null;
239 private static Color []color256 = null;
enikey00e0dbf2008-12-08 10:59:59 +0000240}