blob: ad0cfac7cd2f3fd0db5ae3a2dd8882ea18490b25 [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//
enikey00e0dbf2008-12-08 10:59:59 +000018public class RawDecoder {
19
enikey2f811b82008-12-19 04:45:15 +000020 public RawDecoder(Graphics g, RfbInputStream is) {
21 setGraphics(g);
22 setRfbInputStream(is);
enikeyb3e19f72008-12-19 04:54:49 +000023 // FIXME: cm24 created in getColorModel24.
24 // Remove if no bugs
enikey2f811b82008-12-19 04:45:15 +000025 cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
26 }
27
28 public RawDecoder(Graphics g, RfbInputStream is, int frameBufferW,
29 int frameBufferH) {
30 setGraphics(g);
31 setRfbInputStream(is);
32 setFrameBufferSize(frameBufferW, frameBufferH);
enikeyb3e19f72008-12-19 04:54:49 +000033 // FIXME: cm24 created in getColorModel24.
34 // Remove if no bugs
enikey2f811b82008-12-19 04:45:15 +000035 cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
36 }
37
enikey2c23ba12008-12-19 05:34:17 +000038 //
39 // Set methods to set value of non-static protected members of class
40 //
41
enikey2f811b82008-12-19 04:45:15 +000042 public void setRfbInputStream(RfbInputStream is) {
43 rfbis = is;
44 }
45
46 public void setGraphics(Graphics g) {
47 graphics = g;
48 }
49
50 public void setBPP(int bpp) {
51 bytesPerPixel = bpp;
52 }
53
enikey2c23ba12008-12-19 05:34:17 +000054 public void setFrameBufferSize(int w, int h) {
55 framebufferWidth = w;
56 framebufferHeight = h;
57 }
58
enikey292cf9d2008-12-19 05:30:11 +000059 public void setSessionRecorder(RecordInterface ri) {
60 rec = ri;
61 }
62
enikeyb3e19f72008-12-19 04:54:49 +000063 //
64 // FIXME: This method may be useless in future, remove if so
65 //
66
enikey2f811b82008-12-19 04:45:15 +000067 public int getBPP() {
68 return bytesPerPixel;
69 }
70
enikeyb3e19f72008-12-19 04:54:49 +000071 //
enikey4f92da42008-12-19 05:28:12 +000072 // Decodes Raw Pixels data and draw it into graphics
73 //
74
75 public void handleRect(int x, int y, int w, int h) throws IOException, Exception {
76 if (bytesPerPixel == 1) {
77 for (int dy = y; dy < y + h; dy++) {
78 if (pixels8 != null) {
79 rfbis.readFully(pixels8, dy * framebufferWidth + x, w);
80 }
enikey2c23ba12008-12-19 05:34:17 +000081 //
82 // Save decoded data to RecordInterface
83 //
enikey4f92da42008-12-19 05:28:12 +000084 if (rec.canWrite()) {
85 rec.write(pixels8, dy * framebufferWidth + x, w);
86 }
87 }
88 } else {
89 byte[] buf = new byte[w * 4];
90 int i, offset;
91 for (int dy = y; dy < y + h; dy++) {
92 rfbis.readFully(buf);
93 //
94 // Save decoded data to RecordInterface
95 //
96 if (rec.canWrite()) {
97 rec.write(buf);
98 }
99 offset = dy * framebufferWidth + x;
100 if (pixels24 != null) {
101 for (i = 0; i < w; i++) {
102 pixels24[offset + i] =
103 (buf[i * 4 + 2] & 0xFF) << 16 |
104 (buf[i * 4 + 1] & 0xFF) << 8 |
105 (buf[i * 4] & 0xFF);
106 } //for
107 } // if
108 } // for
109 } // else
110 handleUpdatedPixels(x, y, w, h);
111 } // void
112
113 //
114 // Display newly updated area of pixels.
115 //
enikey2c23ba12008-12-19 05:34:17 +0000116
enikey4f92da42008-12-19 05:28:12 +0000117 protected void handleUpdatedPixels(int x, int y, int w, int h) {
118 // Draw updated pixels of the off-screen image.
119 pixelsSource.newPixels(x, y, w, h);
120 graphics.setClip(x, y, w, h);
121 graphics.drawImage(rawPixelsImage, 0, 0, null);
122 graphics.setClip(0, 0, framebufferWidth, framebufferHeight);
123 }
124
125 //
enikey663025d2008-12-19 05:14:15 +0000126 // Updates pixels data.
enikey4f92da42008-12-19 05:28:12 +0000127 // This method must be called when framebuffer is resized
enikey663025d2008-12-19 05:14:15 +0000128 // or BPP is changed.
129 //
130
131 public void update() {
132 // Images with raw pixels should be re-allocated on every change
133 // of geometry or pixel format.
134 int fbWidth = framebufferWidth;
135 int fbHeight = framebufferHeight;
136
137 if (bytesPerPixel == 1) {
138 pixels24 = null;
139 pixels8 = new byte[fbWidth * fbHeight];
140 pixelsSource = new MemoryImageSource(fbWidth, fbHeight, getColorModel8(),
141 pixels8, 0, fbWidth);
142 } else {
143 pixels8 = null;
144 pixels24 = new int[fbWidth * fbHeight];
145 pixelsSource =
146 new MemoryImageSource(fbWidth, fbHeight, cm24, pixels24, 0, fbWidth);
147 }
148 pixelsSource.setAnimated(true);
149 rawPixelsImage = Toolkit.getDefaultToolkit().createImage(pixelsSource);
150 }
151
152 //
enikey1924c442008-12-19 05:36:36 +0000153 // Private static members access methods
enikeyb3e19f72008-12-19 04:54:49 +0000154 //
155
156 protected ColorModel getColorModel8() {
157 if (cm8 == null) {
158 cm8 = cm8 = new DirectColorModel(8, 7, (7 << 3), (3 << 6));
159 }
160 return cm8;
161 }
162
163 protected ColorModel getColorModel24() {
164 if (cm24 == null) {
165 cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
166 }
167 return cm24;
168 }
169
170 protected Color[]getColor256() {
171 if (color256 == null) {
172 color256 = new Color[256];
173 for (int i = 0; i < 256; i++)
174 color256[i] = new Color(cm8.getRGB(i));
175 }
176 return color256;
177 }
178
179 //
180 // Unique data for every decoder (? maybe not ?)
181 //
enikey2c23ba12008-12-19 05:34:17 +0000182
enikey2f811b82008-12-19 04:45:15 +0000183 protected int bytesPerPixel = 4;
184 protected int framebufferWidth = 0;
185 protected int framebufferHeight = 0;
186 protected RfbInputStream rfbis = null;
187 protected Graphics graphics = null;
188 protected RecordInterface rec = null;
189
enikeyb3e19f72008-12-19 04:54:49 +0000190 //
191 // This data must be shared between decoders
192 //
enikey2c23ba12008-12-19 05:34:17 +0000193
enikey2f811b82008-12-19 04:45:15 +0000194 protected static byte []pixels8 = null;
195 protected static int []pixels24 = null;
196 protected static MemoryImageSource pixelsSource = null;
197 protected static Image rawPixelsImage = null;
198
enikeyb3e19f72008-12-19 04:54:49 +0000199 //
200 // Access to this static members only though protected methods
201 //
enikey2c23ba12008-12-19 05:34:17 +0000202
enikey2f811b82008-12-19 04:45:15 +0000203 private static ColorModel cm8 = null;
204 private static ColorModel cm24 = null;
205 private static Color []color256 = null;
enikey00e0dbf2008-12-08 10:59:59 +0000206}