blob: efa69d1328d0530e703da7fc3b9a3a02aaa07cbc [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
38 public void setRfbInputStream(RfbInputStream is) {
39 rfbis = is;
40 }
41
42 public void setGraphics(Graphics g) {
43 graphics = g;
44 }
45
46 public void setBPP(int bpp) {
47 bytesPerPixel = bpp;
48 }
49
enikey292cf9d2008-12-19 05:30:11 +000050 public void setSessionRecorder(RecordInterface ri) {
51 rec = ri;
52 }
53
enikeyb3e19f72008-12-19 04:54:49 +000054 //
55 // FIXME: This method may be useless in future, remove if so
56 //
57
enikey2f811b82008-12-19 04:45:15 +000058 public int getBPP() {
59 return bytesPerPixel;
60 }
61
62 public void setFrameBufferSize(int w, int h) {
63 framebufferWidth = w;
64 framebufferHeight = h;
65 }
66
enikeyb3e19f72008-12-19 04:54:49 +000067 //
enikey4f92da42008-12-19 05:28:12 +000068 // Decodes Raw Pixels data and draw it into graphics
69 //
70
71 public void handleRect(int x, int y, int w, int h) throws IOException, Exception {
72 if (bytesPerPixel == 1) {
73 for (int dy = y; dy < y + h; dy++) {
74 if (pixels8 != null) {
75 rfbis.readFully(pixels8, dy * framebufferWidth + x, w);
76 }
77 if (rec.canWrite()) {
78 rec.write(pixels8, dy * framebufferWidth + x, w);
79 }
80 }
81 } else {
82 byte[] buf = new byte[w * 4];
83 int i, offset;
84 for (int dy = y; dy < y + h; dy++) {
85 rfbis.readFully(buf);
86 //
87 // Save decoded data to RecordInterface
88 //
89 if (rec.canWrite()) {
90 rec.write(buf);
91 }
92 offset = dy * framebufferWidth + x;
93 if (pixels24 != null) {
94 for (i = 0; i < w; i++) {
95 pixels24[offset + i] =
96 (buf[i * 4 + 2] & 0xFF) << 16 |
97 (buf[i * 4 + 1] & 0xFF) << 8 |
98 (buf[i * 4] & 0xFF);
99 } //for
100 } // if
101 } // for
102 } // else
103 handleUpdatedPixels(x, y, w, h);
104 } // void
105
106 //
107 // Display newly updated area of pixels.
108 //
109 protected void handleUpdatedPixels(int x, int y, int w, int h) {
110 // Draw updated pixels of the off-screen image.
111 pixelsSource.newPixels(x, y, w, h);
112 graphics.setClip(x, y, w, h);
113 graphics.drawImage(rawPixelsImage, 0, 0, null);
114 graphics.setClip(0, 0, framebufferWidth, framebufferHeight);
115 }
116
117 //
enikey663025d2008-12-19 05:14:15 +0000118 // Updates pixels data.
enikey4f92da42008-12-19 05:28:12 +0000119 // This method must be called when framebuffer is resized
enikey663025d2008-12-19 05:14:15 +0000120 // or BPP is changed.
121 //
122
123 public void update() {
124 // Images with raw pixels should be re-allocated on every change
125 // of geometry or pixel format.
126 int fbWidth = framebufferWidth;
127 int fbHeight = framebufferHeight;
128
129 if (bytesPerPixel == 1) {
130 pixels24 = null;
131 pixels8 = new byte[fbWidth * fbHeight];
132 pixelsSource = new MemoryImageSource(fbWidth, fbHeight, getColorModel8(),
133 pixels8, 0, fbWidth);
134 } else {
135 pixels8 = null;
136 pixels24 = new int[fbWidth * fbHeight];
137 pixelsSource =
138 new MemoryImageSource(fbWidth, fbHeight, cm24, pixels24, 0, fbWidth);
139 }
140 pixelsSource.setAnimated(true);
141 rawPixelsImage = Toolkit.getDefaultToolkit().createImage(pixelsSource);
142 }
143
144 //
enikeyb3e19f72008-12-19 04:54:49 +0000145 // Private static members access methdos
146 //
147
148 protected ColorModel getColorModel8() {
149 if (cm8 == null) {
150 cm8 = cm8 = new DirectColorModel(8, 7, (7 << 3), (3 << 6));
151 }
152 return cm8;
153 }
154
155 protected ColorModel getColorModel24() {
156 if (cm24 == null) {
157 cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
158 }
159 return cm24;
160 }
161
162 protected Color[]getColor256() {
163 if (color256 == null) {
164 color256 = new Color[256];
165 for (int i = 0; i < 256; i++)
166 color256[i] = new Color(cm8.getRGB(i));
167 }
168 return color256;
169 }
170
171 //
172 // Unique data for every decoder (? maybe not ?)
173 //
enikey2f811b82008-12-19 04:45:15 +0000174 protected int bytesPerPixel = 4;
175 protected int framebufferWidth = 0;
176 protected int framebufferHeight = 0;
177 protected RfbInputStream rfbis = null;
178 protected Graphics graphics = null;
179 protected RecordInterface rec = null;
180
enikeyb3e19f72008-12-19 04:54:49 +0000181 //
182 // This data must be shared between decoders
183 //
enikey2f811b82008-12-19 04:45:15 +0000184 protected static byte []pixels8 = null;
185 protected static int []pixels24 = null;
186 protected static MemoryImageSource pixelsSource = null;
187 protected static Image rawPixelsImage = null;
188
enikeyb3e19f72008-12-19 04:54:49 +0000189 //
190 // Access to this static members only though protected methods
191 //
enikey2f811b82008-12-19 04:45:15 +0000192 private static ColorModel cm8 = null;
193 private static ColorModel cm24 = null;
194 private static Color []color256 = null;
enikey00e0dbf2008-12-08 10:59:59 +0000195}