/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

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