blob: 478a668e056e3ca81fa1a867a2b5efe17856dae7 [file] [log] [blame]
Adam Tkacf53e62a2009-03-13 13:20:26 +00001package com.tigervnc.decoder;
enikey00e0dbf2008-12-08 10:59:59 +00002
Adam Tkacf53e62a2009-03-13 13:20:26 +00003import com.tigervnc.vncviewer.RfbInputStream;
enikey4f92da42008-12-19 05:28:12 +00004import java.io.IOException;
enikeyc6f6bab2008-12-24 03:41:00 +00005import java.io.DataOutput;
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 {
enikey6558a302008-12-24 05:14:30 +000020 final static int EncodingRaw = 0;
enikey00e0dbf2008-12-08 10:59:59 +000021
enikey2f811b82008-12-19 04:45:15 +000022 public RawDecoder(Graphics g, RfbInputStream is) {
23 setGraphics(g);
24 setRfbInputStream(is);
enikey2f811b82008-12-19 04:45:15 +000025 }
26
27 public RawDecoder(Graphics g, RfbInputStream is, int frameBufferW,
28 int frameBufferH) {
29 setGraphics(g);
30 setRfbInputStream(is);
31 setFrameBufferSize(frameBufferW, frameBufferH);
enikeyb3e19f72008-12-19 04:54:49 +000032 // FIXME: cm24 created in getColorModel24.
33 // Remove if no bugs
enikey2f811b82008-12-19 04:45:15 +000034 cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
35 }
36
enikey2c23ba12008-12-19 05:34:17 +000037 //
38 // Set methods to set value of non-static protected members of class
39 //
40
enikey2f811b82008-12-19 04:45:15 +000041 public void setRfbInputStream(RfbInputStream is) {
42 rfbis = is;
43 }
44
45 public void setGraphics(Graphics g) {
46 graphics = g;
47 }
48
49 public void setBPP(int bpp) {
50 bytesPerPixel = bpp;
51 }
52
enikey2c23ba12008-12-19 05:34:17 +000053 public void setFrameBufferSize(int w, int h) {
54 framebufferWidth = w;
55 framebufferHeight = h;
56 }
57
enikeyb3e19f72008-12-19 04:54:49 +000058 //
enikey3e9ff9f2008-12-24 03:30:29 +000059 // FIXME: Rename this method after we don't need RecordInterface
60 // in RawDecoder class to record session
61 //
62
enikeyc6f6bab2008-12-24 03:41:00 +000063 public void setDataOutputStream(DataOutput os) {
enikey3e9ff9f2008-12-24 03:30:29 +000064 dos = os;
65 }
66
67 //
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 {
enikey2f0294e2008-12-24 08:18:54 +000072
73 //
74 // Write encoding ID to record output stream
75 //
76
77 if ((dos != null) && (enableEncodingRecordWritting)) {
78 dos.writeInt(RawDecoder.EncodingRaw);
79 }
80
enikey4f92da42008-12-19 05:28:12 +000081 if (bytesPerPixel == 1) {
82 for (int dy = y; dy < y + h; dy++) {
83 if (pixels8 != null) {
84 rfbis.readFully(pixels8, dy * framebufferWidth + x, w);
85 }
enikey2c23ba12008-12-19 05:34:17 +000086 //
enikey5276d792008-12-24 04:12:34 +000087 // Save decoded data to record output stream
enikey2c23ba12008-12-19 05:34:17 +000088 //
enikey5276d792008-12-24 04:12:34 +000089 if (dos != null) {
90 dos.write(pixels8, dy * framebufferWidth + x, w);
enikey4f92da42008-12-19 05:28:12 +000091 }
92 }
93 } else {
94 byte[] buf = new byte[w * 4];
95 int i, offset;
96 for (int dy = y; dy < y + h; dy++) {
97 rfbis.readFully(buf);
98 //
enikey5276d792008-12-24 04:12:34 +000099 // Save decoded data to record output stream
enikey4f92da42008-12-19 05:28:12 +0000100 //
enikey5276d792008-12-24 04:12:34 +0000101 if (dos != null) {
102 dos.write(buf);
enikey4f92da42008-12-19 05:28:12 +0000103 }
104 offset = dy * framebufferWidth + x;
105 if (pixels24 != null) {
106 for (i = 0; i < w; i++) {
107 pixels24[offset + i] =
108 (buf[i * 4 + 2] & 0xFF) << 16 |
109 (buf[i * 4 + 1] & 0xFF) << 8 |
110 (buf[i * 4] & 0xFF);
111 } //for
112 } // if
113 } // for
114 } // else
115 handleUpdatedPixels(x, y, w, h);
116 } // void
enikey3e9ff9f2008-12-24 03:30:29 +0000117
enikey4f92da42008-12-19 05:28:12 +0000118 //
119 // Display newly updated area of pixels.
120 //
enikey2c23ba12008-12-19 05:34:17 +0000121
enikey4f92da42008-12-19 05:28:12 +0000122 protected void handleUpdatedPixels(int x, int y, int w, int h) {
123 // Draw updated pixels of the off-screen image.
124 pixelsSource.newPixels(x, y, w, h);
125 graphics.setClip(x, y, w, h);
126 graphics.drawImage(rawPixelsImage, 0, 0, null);
127 graphics.setClip(0, 0, framebufferWidth, framebufferHeight);
128 }
129
130 //
enikey663025d2008-12-19 05:14:15 +0000131 // Updates pixels data.
enikey4f92da42008-12-19 05:28:12 +0000132 // This method must be called when framebuffer is resized
enikey663025d2008-12-19 05:14:15 +0000133 // or BPP is changed.
134 //
135
136 public void update() {
137 // Images with raw pixels should be re-allocated on every change
138 // of geometry or pixel format.
139 int fbWidth = framebufferWidth;
140 int fbHeight = framebufferHeight;
141
142 if (bytesPerPixel == 1) {
143 pixels24 = null;
144 pixels8 = new byte[fbWidth * fbHeight];
145 pixelsSource = new MemoryImageSource(fbWidth, fbHeight, getColorModel8(),
146 pixels8, 0, fbWidth);
147 } else {
148 pixels8 = null;
149 pixels24 = new int[fbWidth * fbHeight];
150 pixelsSource =
151 new MemoryImageSource(fbWidth, fbHeight, cm24, pixels24, 0, fbWidth);
152 }
153 pixelsSource.setAnimated(true);
154 rawPixelsImage = Toolkit.getDefaultToolkit().createImage(pixelsSource);
155 }
156
157 //
enikey1924c442008-12-19 05:36:36 +0000158 // Private static members access methods
enikeyb3e19f72008-12-19 04:54:49 +0000159 //
160
161 protected ColorModel getColorModel8() {
162 if (cm8 == null) {
163 cm8 = cm8 = new DirectColorModel(8, 7, (7 << 3), (3 << 6));
164 }
165 return cm8;
166 }
167
168 protected ColorModel getColorModel24() {
169 if (cm24 == null) {
170 cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);
171 }
172 return cm24;
173 }
174
175 protected Color[]getColor256() {
176 if (color256 == null) {
177 color256 = new Color[256];
178 for (int i = 0; i < 256; i++)
179 color256[i] = new Color(cm8.getRGB(i));
180 }
181 return color256;
182 }
183
184 //
enikey2f0294e2008-12-24 08:18:54 +0000185 // This method will be used by HextileDecoder to disable
186 // double writting encoding id to record stream.
187 //
188 // FIXME: Try to find better solution than this.
189 //
190
191 protected void enableEncodingRecordWritting(boolean enable) {
192 enableEncodingRecordWritting = enable;
193 }
194
195 //
enikeyb3e19f72008-12-19 04:54:49 +0000196 // Unique data for every decoder (? maybe not ?)
197 //
enikey2c23ba12008-12-19 05:34:17 +0000198
enikey2f811b82008-12-19 04:45:15 +0000199 protected int bytesPerPixel = 4;
200 protected int framebufferWidth = 0;
201 protected int framebufferHeight = 0;
202 protected RfbInputStream rfbis = null;
203 protected Graphics graphics = null;
enikeyc6f6bab2008-12-24 03:41:00 +0000204 protected DataOutput dos = null;
enikey2f0294e2008-12-24 08:18:54 +0000205 protected boolean enableEncodingRecordWritting = true;
enikey2f811b82008-12-19 04:45:15 +0000206
enikeyb3e19f72008-12-19 04:54:49 +0000207 //
208 // This data must be shared between decoders
209 //
enikey2c23ba12008-12-19 05:34:17 +0000210
enikey2f811b82008-12-19 04:45:15 +0000211 protected static byte []pixels8 = null;
212 protected static int []pixels24 = null;
213 protected static MemoryImageSource pixelsSource = null;
214 protected static Image rawPixelsImage = null;
215
enikeyb3e19f72008-12-19 04:54:49 +0000216 //
217 // Access to this static members only though protected methods
218 //
enikey2c23ba12008-12-19 05:34:17 +0000219
enikey2f811b82008-12-19 04:45:15 +0000220 private static ColorModel cm8 = null;
221 private static ColorModel cm24 = null;
222 private static Color []color256 = null;
enikey00e0dbf2008-12-08 10:59:59 +0000223}