PageRenderTime 38ms CodeModel.GetById 1ms app.highlight 31ms RepoModel.GetById 1ms app.codeStats 0ms

/src/main/java/com/wet/wired/jrc/frame/compression/RunLengthThenGZCompressor.java

http://java-remote-control.googlecode.com/
Java | 410 lines | 340 code | 63 blank | 7 comment | 65 complexity | e2351a06f00b003307c42a746e860251 MD5 | raw file
  1package com.wet.wired.jrc.frame.compression;
  2
  3import java.io.ByteArrayInputStream;
  4import java.io.IOException;
  5import java.io.InputStream;
  6import java.io.OutputStream;
  7import java.util.zip.GZIPInputStream;
  8import java.util.zip.GZIPOutputStream;
  9
 10import com.wet.wired.jrc.frame.Frame;
 11
 12public class RunLengthThenGZCompressor implements Compressor,Decompressor{
 13	private static final int ALPHA = 0xFF000000;
 14	private static final int READ_BLOCK_SIZE = 10000;
 15
 16	private class OutputStreamMonitor extends OutputStream {
 17		private OutputStream delegate;
 18		private int writeCount = 0;
 19
 20		public OutputStreamMonitor(OutputStream out) {
 21			delegate = out;
 22		}
 23		
 24		public void close() throws IOException {
 25			delegate.close();
 26		}
 27
 28		public boolean equals(Object obj) {
 29			return delegate.equals(obj);
 30		}
 31
 32		public void flush() throws IOException {
 33			delegate.flush();
 34		}
 35
 36		public int hashCode() {
 37			return delegate.hashCode();
 38		}
 39
 40		public String toString() {
 41			return delegate.toString();
 42		}
 43
 44		public void write(byte[] b, int off, int len) throws IOException {
 45			delegate.write(b, off, len);
 46			writeCount+=len;
 47		}
 48
 49		public void write(byte[] b) throws IOException {
 50			delegate.write(b);
 51			writeCount+=b.length;
 52		}
 53
 54		public void write(int b) throws IOException {
 55			delegate.write(b);
 56			writeCount++;
 57		}
 58		
 59		private int getWriteCount() {
 60			return writeCount;
 61		}
 62	}
 63	
 64	@Override
 65	public int compressFrame(Frame lastFrame,Frame currentFrame, OutputStream out) throws IOException {
 66		int inCursor = 0;
 67		int outCursor = 0;
 68		int blocks = 0;
 69
 70		boolean inBlock = true;
 71		int blockSize = 0;
 72		byte blockRed = 0;
 73		byte blockGreen = 0;
 74		byte blockBlue = 0;
 75		
 76		int blankBlocks = 0;
 77		
 78		int uncompressedCursor = -1;
 79		
 80		byte red;
 81		byte green;
 82		byte blue;
 83		
 84		boolean hasChanges = false;
 85		boolean lastEntry = false;
 86		
 87		int[] currFrame = currentFrame.getData();
 88		int[] prevFrame = lastFrame.getData();
 89		byte[] compFrame = new byte[lastFrame.getData().length];
 90		
 91		int dataSize = lastFrame.getData().length;
 92		
 93		OutputStreamMonitor outMonitor = new OutputStreamMonitor(out); 
 94		
 95		while(inCursor < dataSize)
 96		{
 97			if(inCursor == dataSize - 1)
 98			{
 99				lastEntry = true;
100			}
101			
102			if(currFrame[inCursor] == prevFrame[inCursor])
103			{
104				red=0;
105				green=0;
106				blue=0;
107			}
108			else
109			{
110				red = (byte) ((currFrame[inCursor] & 0x00FF0000) >>> 16);
111				green = (byte) ((currFrame[inCursor] & 0x0000FF00) >>> 8);
112				blue = (byte) ((currFrame[inCursor] & 0x000000FF));
113				
114				if(red==0 && green==0 && blue==0)
115				{
116					blue = 1;
117				}
118			}
119			
120			if(
121				blockRed == red &&
122				blockGreen == green &&
123				blockBlue == blue
124			)
125			{
126				if(inBlock == false)
127				{
128					if(uncompressedCursor > -1)
129					{
130						blocks++;
131						hasChanges = true;
132						compFrame[uncompressedCursor] = (byte)(blockSize + 0x80);
133					}
134					inBlock = true;
135					blockSize = 0;
136					blankBlocks = 0;
137				}
138				else if(blockSize == 126 || lastEntry == true)
139				{
140					if (
141						blockRed == 0 &&
142						blockGreen == 0 &&
143						blockBlue == 0
144					)
145					{
146						if (blankBlocks > 0)
147						{
148							blankBlocks++;
149							compFrame[outCursor-1] = (byte) blankBlocks;
150						}
151						else
152						{
153							blocks++;
154							blankBlocks++;
155							compFrame[outCursor] = (byte)0xFF;
156							outCursor++;
157							compFrame[outCursor] = (byte)blankBlocks;
158							outCursor++;
159						}
160						if(blankBlocks == 255)
161						{
162							blankBlocks = 0;
163						}
164					}
165					else
166					{
167						blocks++;
168						hasChanges = true;
169						compFrame[outCursor] = (byte)blockSize;
170						outCursor++;
171						compFrame[outCursor] = blockRed;
172						outCursor++;
173						compFrame[outCursor] = blockGreen;
174						outCursor++;
175						compFrame[outCursor] = blockBlue;
176						outCursor++;
177						
178						blankBlocks = 0;
179					}			
180					inBlock = true;
181					blockSize = 0;
182				}
183			}
184			else
185			{
186				if(inBlock == true)
187				{
188					if(blockSize > 0)
189					{
190						blocks++;
191						hasChanges = true;
192						compFrame[outCursor] = (byte) blockSize;
193						outCursor++;
194						compFrame[outCursor] = blockRed;
195						outCursor++;
196						compFrame[outCursor] = blockGreen;
197						outCursor++;
198						compFrame[outCursor] = blockBlue;
199						outCursor++;
200					}
201
202					uncompressedCursor = -1;
203					inBlock = false;
204					blockSize = 0;
205					
206					blankBlocks = 0;
207				}
208				else if(blockSize == 126 || lastEntry == true)
209				{
210					if(uncompressedCursor>-1)
211					{
212						blocks++;
213						hasChanges = true;
214						compFrame[uncompressedCursor] = (byte)(blockSize + 0x80);
215					}
216					
217					uncompressedCursor = -1;
218					inBlock = false;
219					blockSize = 0;
220					
221					blankBlocks = 0;					
222				}
223
224
225				if(uncompressedCursor == -1)
226				{
227					uncompressedCursor = outCursor;
228					outCursor++;
229				}
230				
231				compFrame[outCursor] = red;
232				outCursor++;
233				compFrame[outCursor] = green;
234				outCursor++;
235				compFrame[outCursor] = blue;
236				outCursor++;
237				
238				blockRed = red;
239				blockGreen = green;
240				blockBlue = blue;
241			}
242			inCursor++;
243			blockSize++;
244		}
245		
246		if(hasChanges==false) {
247			return -1;
248		}
249		
250		GZIPOutputStream zO = new GZIPOutputStream(outMonitor);
251		zO.write(compFrame,0,outCursor);
252		zO.close();
253		
254		return outMonitor.getWriteCount();
255	}
256	
257	public void decompressFrame(InputStream in,int framePacketSize,Frame lastFrame,Frame currentFrame) throws IOException {
258		
259		int[] prevFrame = lastFrame.getData();
260		int[] currFrame = currentFrame.getData();
261		int currFrameSize = currFrame.length;
262		
263		byte[] compFrame = new byte[currFrameSize*4];
264		int compFrameSize = 0;
265		
266		byte[] zData = new byte[framePacketSize];
267		
268		int maxBlockSize = READ_BLOCK_SIZE;
269		if(maxBlockSize>framePacketSize) {
270			maxBlockSize = framePacketSize;
271		}
272		int sizeRead=in.read(zData,0,maxBlockSize);
273		int cursor=sizeRead;
274		while(sizeRead!=-1 && cursor<framePacketSize) {
275			if(maxBlockSize+cursor>framePacketSize) {
276				maxBlockSize = framePacketSize-cursor;
277			}
278			sizeRead=in.read(zData,cursor,maxBlockSize);
279			if(sizeRead>0) {
280				cursor+=sizeRead;
281			}
282		}
283		
284		ByteArrayInputStream biStream = new ByteArrayInputStream( zData,0,zData.length );
285		GZIPInputStream gzipInputStream = new GZIPInputStream( biStream );
286		
287		sizeRead = gzipInputStream.read(compFrame,0,READ_BLOCK_SIZE);
288		if(sizeRead>0) {
289			cursor+=sizeRead;
290		}
291		cursor=sizeRead;
292
293		while(sizeRead>-1)
294		{
295			sizeRead = gzipInputStream.read(compFrame,cursor,READ_BLOCK_SIZE);
296			if(sizeRead>0) {
297				cursor += sizeRead;
298			}
299		}
300		
301		compFrameSize = cursor;
302		
303		int inCursor = 0;
304		int outCursor = 0;
305		
306		int blockSize = 0;
307		
308		int rgb = 0xFF000000;
309		
310		//System.out.println("Combining old:"+frame.previousData+" with new:"+frame.newData);
311		
312		while(inCursor < compFrameSize && outCursor < currFrameSize)
313		{
314			if(compFrame[inCursor] == -1)
315			{
316				inCursor++;
317				
318				int count = (compFrame[inCursor] & 0xFF);
319				inCursor++;
320				
321				int size = count*126;
322				if( size > currFrameSize)
323				{
324					size = currFrameSize;
325				}
326				//System.arraycopy(frame.previousData,0,frame.newData,0,size);
327				//outCursor+=size;
328				
329				for(int loop=0; loop < (126 * count); loop++)
330				{
331					//frame.newData[outCursor]=blue;//frame.previousData[outCursor];
332					currFrame[outCursor] = prevFrame[outCursor];
333					//newRawData[outCursor]=blue;
334					outCursor++;
335					if(outCursor == currFrameSize)
336					{
337						break;
338					}
339				}
340				
341			}
342			else if (compFrame[inCursor] < 0) // uncomp
343			{
344				blockSize = compFrame[inCursor] & 0x7F;//(128+packed[inCursor]);
345				inCursor++;
346				
347				for(int loop=0; loop < blockSize; loop++)
348				{
349					rgb = ((compFrame[inCursor] & 0xFF)<<16) 
350						| ((compFrame[inCursor+1] & 0xFF) << 8)
351						| (compFrame[inCursor+2] & 0xFF)
352						| ALPHA;
353					
354					if(rgb == ALPHA)
355					{
356						rgb = prevFrame[outCursor];
357					}
358					//rgb = green;
359					inCursor += 3;
360					currFrame[outCursor] = rgb;
361					outCursor++;
362					if (outCursor == currFrame.length)
363					{
364						break;
365					}
366				}
367			}
368			else
369			{
370				blockSize = compFrame[inCursor];
371				inCursor++;
372				rgb = ((compFrame[inCursor] & 0xFF) << 16)
373					| ((compFrame[inCursor+1] & 0xFF) << 8)
374					| (compFrame[inCursor+2] & 0xFF)
375					| ALPHA;
376				
377				boolean transparent = false;
378				if(rgb == ALPHA)
379				{
380					transparent = true;
381				}
382				//rgb = red;
383				inCursor += 3;
384				
385				for (int loop = 0; loop < blockSize; loop++)
386				{
387					if (transparent)
388					{
389						currFrame[outCursor] = prevFrame[outCursor];						
390					}
391					else
392					{
393						currFrame[outCursor] = rgb;	
394					}
395					outCursor++;
396					if (outCursor == currFrameSize)
397					{
398						break;
399					}
400				}
401			}
402		}
403		if(outCursor<currFrameSize) {
404			currFrame[outCursor]=rgb;
405		}
406		
407		currentFrame.setData(currFrame);
408	}
409
410}