/src/main/Silverlight/WallpaperCreatorForSamsungPhone/WallpaperCreatorForSamsungPhone/FJCore/Decoder/HuffmanTable.cs

http://s5230wallpapercreator.googlecode.com/ · C# · 487 lines · 372 code · 68 blank · 47 comment · 68 complexity · cf250d639269cda8367b0cfc79e6a950 MD5 · raw file

  1. /// Copyright (c) 2008 Jeffrey Powers for Fluxcapacity Open Source.
  2. /// Under the MIT License, details: License.txt.
  3. // Partially derives from a Java encoder, JpegEncoder.java by James R Weeks.
  4. // Implements Baseline JPEG Encoding http://www.opennet.ru/docs/formats/jpeg.txt
  5. using System;
  6. using FluxJpeg.Core.IO;
  7. using System.IO;
  8. using System.Collections.Generic;
  9. namespace FluxJpeg.Core
  10. {
  11. internal class HuffmanTable
  12. {
  13. public static int HUFFMAN_MAX_TABLES = 4;
  14. private short[] huffcode = new short[256];
  15. private short[] huffsize = new short[256];
  16. private short[] valptr = new short[16];
  17. private short[] mincode = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-1,-1};
  18. private short[] maxcode = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
  19. private short[] huffval;
  20. private short[] bits;
  21. int bufferPutBits, bufferPutBuffer;
  22. internal int ImageHeight;
  23. internal int ImageWidth;
  24. internal int[,] DC_matrix0;
  25. internal int[,] AC_matrix0;
  26. internal int[,] DC_matrix1;
  27. internal int[,] AC_matrix1;
  28. internal int[][,] DC_matrix;
  29. internal int[][,] AC_matrix;
  30. internal int NumOfDCTables;
  31. internal int NumOfACTables;
  32. public List<short[]> bitsList;
  33. public List<short[]> val;
  34. public static byte JPEG_DC_TABLE = 0;
  35. public static byte JPEG_AC_TABLE = 1;
  36. private short lastk = 0;
  37. internal HuffmanTable(JpegHuffmanTable table)
  38. {
  39. if (table != null)
  40. {
  41. huffval = table.Values;
  42. bits = table.Lengths;
  43. GenerateSizeTable();
  44. GenerateCodeTable();
  45. GenerateDecoderTables();
  46. }
  47. else
  48. {
  49. // Encode initialization
  50. bitsList = new List<short[]>();
  51. bitsList.Add(JpegHuffmanTable.StdDCLuminance.Lengths);
  52. bitsList.Add(JpegHuffmanTable.StdACLuminance.Lengths);
  53. bitsList.Add(JpegHuffmanTable.StdDCChrominance.Lengths);
  54. bitsList.Add(JpegHuffmanTable.StdACChrominance.Lengths);
  55. val = new List<short[]>();
  56. val.Add(JpegHuffmanTable.StdDCLuminance.Values);
  57. val.Add(JpegHuffmanTable.StdACLuminance.Values);
  58. val.Add(JpegHuffmanTable.StdDCChrominance.Values);
  59. val.Add(JpegHuffmanTable.StdACChrominance.Values);
  60. initHuf();
  61. }
  62. }
  63. /// <summary>See Figure C.1</summary>
  64. private void GenerateSizeTable()
  65. {
  66. short index = 0;
  67. for (short i = 0; i < bits.Length; i++)
  68. {
  69. for (short j = 0; j < bits[i]; j++)
  70. {
  71. huffsize[index] = (short)(i + 1);
  72. index++;
  73. }
  74. }
  75. lastk = index;
  76. }
  77. /// <summary>See Figure C.2</summary>
  78. private void GenerateCodeTable()
  79. {
  80. short k = 0;
  81. short si = huffsize[0];
  82. short code = 0;
  83. for (short i = 0; i < huffsize.Length; i++)
  84. {
  85. while (huffsize[k] == si)
  86. {
  87. huffcode[k] = code;
  88. code++;
  89. k++;
  90. }
  91. code <<= 1;
  92. si++;
  93. }
  94. }
  95. /// <summary>See figure F.15</summary>
  96. private void GenerateDecoderTables()
  97. {
  98. short bitcount = 0;
  99. for (int i = 0; i < 16; i++)
  100. {
  101. if (bits[i] != 0)
  102. valptr[i] = bitcount;
  103. for (int j = 0; j < bits[i]; j++)
  104. {
  105. if (huffcode[j + bitcount] < mincode[i] || mincode[i] == -1)
  106. mincode[i] = huffcode[j + bitcount];
  107. if (huffcode[j + bitcount] > maxcode[i])
  108. maxcode[i] = huffcode[j + bitcount];
  109. }
  110. if (mincode[i] != -1)
  111. valptr[i] = (short)(valptr[i] - mincode[i]);
  112. bitcount += bits[i];
  113. }
  114. }
  115. /// <summary>Figure F.12</summary>
  116. public static int Extend(int diff, int t)
  117. {
  118. // here we use bitshift to implement 2^ ...
  119. // NOTE: Math.Pow returns 0 for negative powers, which occassionally happen here!
  120. int Vt = 1 << t - 1;
  121. // WAS: int Vt = (int)Math.Pow(2, (t - 1));
  122. if (diff < Vt)
  123. {
  124. Vt = (-1 << t) + 1;
  125. diff = diff + Vt;
  126. }
  127. return diff;
  128. }
  129. /// <summary>Figure F.16 - Reads the huffman code bit-by-bit.</summary>
  130. public int Decode(JPEGBinaryReader JPEGStream)
  131. {
  132. int i = 0;
  133. short code = (short)JPEGStream.ReadBits(1);
  134. while (code > maxcode[i])
  135. {
  136. i++;
  137. code <<= 1;
  138. code |= (short)JPEGStream.ReadBits(1);
  139. }
  140. int val = huffval[code + (valptr[i])];
  141. if (val < 0)
  142. val = 256 + val;
  143. return val;
  144. }
  145. /// <summary>
  146. /// HuffmanBlockEncoder run length encodes and Huffman encodes the quantized data.
  147. /// </summary>
  148. internal void HuffmanBlockEncoder(Stream outStream, int[] zigzag, int prec, int DCcode, int ACcode)
  149. {
  150. int temp, temp2, nbits, k, r, i;
  151. NumOfDCTables = 2;
  152. NumOfACTables = 2;
  153. // The DC portion
  154. temp = temp2 = zigzag[0] - prec;
  155. if (temp < 0)
  156. {
  157. temp = -temp;
  158. temp2--;
  159. }
  160. nbits = 0;
  161. while (temp != 0)
  162. {
  163. nbits++;
  164. temp >>= 1;
  165. }
  166. // if (nbits > 11) nbits = 11;
  167. bufferIt(outStream,
  168. DC_matrix[DCcode][nbits, 0],
  169. DC_matrix[DCcode][nbits, 1]);
  170. // The arguments in bufferIt are code and size.
  171. if (nbits != 0)
  172. {
  173. bufferIt(outStream, temp2, nbits);
  174. }
  175. // The AC portion
  176. r = 0;
  177. for (k = 1; k < 64; k++)
  178. {
  179. if ((temp = zigzag[ ZigZag.ZigZagMap[k] ]) == 0)
  180. {
  181. r++;
  182. }
  183. else
  184. {
  185. while (r > 15)
  186. {
  187. bufferIt(outStream,
  188. AC_matrix[ACcode][0xF0, 0],
  189. AC_matrix[ACcode][0xF0, 1]);
  190. r -= 16;
  191. }
  192. temp2 = temp;
  193. if (temp < 0)
  194. {
  195. temp = -temp;
  196. temp2--;
  197. }
  198. nbits = 1;
  199. while ((temp >>= 1) != 0)
  200. {
  201. nbits++;
  202. }
  203. i = (r << 4) + nbits;
  204. bufferIt(outStream,
  205. AC_matrix[ACcode][i, 0],
  206. AC_matrix[ACcode][i, 1]);
  207. bufferIt(outStream, temp2, nbits);
  208. r = 0;
  209. }
  210. }
  211. if (r > 0)
  212. {
  213. bufferIt(outStream,
  214. AC_matrix[ACcode][0, 0],
  215. AC_matrix[ACcode][0, 1]);
  216. }
  217. }
  218. /// <summary>
  219. /// Uses an integer long (32 bits) buffer to store the Huffman encoded bits
  220. /// and sends them to outStream by the byte.
  221. /// </summary>
  222. void bufferIt(Stream outStream, int code, int size)
  223. {
  224. int PutBuffer = code;
  225. int PutBits = bufferPutBits;
  226. PutBuffer &= (1 << size) - 1;
  227. PutBits += size;
  228. PutBuffer <<= 24 - PutBits;
  229. PutBuffer |= bufferPutBuffer;
  230. while (PutBits >= 8)
  231. {
  232. int c = ((PutBuffer >> 16) & 0xFF);
  233. outStream.WriteByte((byte)c);
  234. // FF must be escaped
  235. if (c == 0xFF) outStream.WriteByte(0);
  236. PutBuffer <<= 8;
  237. PutBits -= 8;
  238. }
  239. bufferPutBuffer = PutBuffer;
  240. bufferPutBits = PutBits;
  241. }
  242. public void FlushBuffer(Stream outStream)
  243. {
  244. int PutBuffer = bufferPutBuffer;
  245. int PutBits = bufferPutBits;
  246. while (PutBits >= 8)
  247. {
  248. int c = ((PutBuffer >> 16) & 0xFF);
  249. outStream.WriteByte((byte)c);
  250. // FF must be escaped
  251. if (c == 0xFF) outStream.WriteByte(0);
  252. PutBuffer <<= 8;
  253. PutBits -= 8;
  254. }
  255. if (PutBits > 0)
  256. {
  257. int c = ((PutBuffer >> 16) & 0xFF);
  258. outStream.WriteByte((byte)c);
  259. }
  260. }
  261. /// <summary>
  262. /// Initialisation of the Huffman codes for Luminance and Chrominance.
  263. /// This code results in the same tables created in the IJG Jpeg-6a
  264. /// library.
  265. /// </summary>
  266. public void initHuf()
  267. {
  268. DC_matrix0 = new int[12, 2];
  269. DC_matrix1 = new int[12, 2];
  270. AC_matrix0 = new int[255, 2];
  271. AC_matrix1 = new int[255, 2];
  272. DC_matrix = new int[2][,];
  273. AC_matrix = new int[2][,];
  274. int p, l, i, lastp, si, code;
  275. int[] huffsize = new int[257];
  276. int[] huffcode = new int[257];
  277. short[] bitsDCchrominance = JpegHuffmanTable.StdDCChrominance.Lengths;
  278. short[] bitsACchrominance = JpegHuffmanTable.StdACChrominance.Lengths;
  279. short[] bitsDCluminance = JpegHuffmanTable.StdDCLuminance.Lengths;
  280. short[] bitsACluminance = JpegHuffmanTable.StdACLuminance.Lengths;
  281. short[] valDCchrominance = JpegHuffmanTable.StdDCChrominance.Values;
  282. short[] valACchrominance = JpegHuffmanTable.StdACChrominance.Values;
  283. short[] valDCluminance = JpegHuffmanTable.StdDCLuminance.Values;
  284. short[] valACluminance = JpegHuffmanTable.StdACLuminance.Values;
  285. /*
  286. * init of the DC values for the chrominance
  287. * [,0] is the code [,1] is the number of bit
  288. */
  289. p = 0;
  290. for (l = 0; l < 16; l++)
  291. {
  292. for (i = 1; i <= bitsDCchrominance[l]; i++)
  293. {
  294. huffsize[p++] = l+1;
  295. }
  296. }
  297. huffsize[p] = 0;
  298. lastp = p;
  299. code = 0;
  300. si = huffsize[0];
  301. p = 0;
  302. while (huffsize[p] != 0)
  303. {
  304. while (huffsize[p] == si)
  305. {
  306. huffcode[p++] = code;
  307. code++;
  308. }
  309. code <<= 1;
  310. si++;
  311. }
  312. for (p = 0; p < lastp; p++)
  313. {
  314. DC_matrix1[valDCchrominance[p], 0] = huffcode[p];
  315. DC_matrix1[valDCchrominance[p], 1] = huffsize[p];
  316. }
  317. /*
  318. * Init of the AC hufmann code for the chrominance
  319. * matrix [,,0] is the code & matrix[,,1] is the number of bit needed
  320. */
  321. p = 0;
  322. for (l = 0; l < 16; l++)
  323. {
  324. for (i = 1; i <= bitsACchrominance[l]; i++)
  325. {
  326. huffsize[p++] = l+1;
  327. }
  328. }
  329. huffsize[p] = 0;
  330. lastp = p;
  331. code = 0;
  332. si = huffsize[0];
  333. p = 0;
  334. while (huffsize[p] != 0)
  335. {
  336. while (huffsize[p] == si)
  337. {
  338. huffcode[p++] = code;
  339. code++;
  340. }
  341. code <<= 1;
  342. si++;
  343. }
  344. for (p = 0; p < lastp; p++)
  345. {
  346. AC_matrix1[valACchrominance[p], 0] = huffcode[p];
  347. AC_matrix1[valACchrominance[p], 1] = huffsize[p];
  348. }
  349. /*
  350. * init of the DC values for the luminance
  351. * [,0] is the code [,1] is the number of bit
  352. */
  353. p = 0;
  354. for (l = 0; l < 16; l++)
  355. {
  356. for (i = 1; i <= bitsDCluminance[l]; i++)
  357. {
  358. huffsize[p++] = l+1;
  359. }
  360. }
  361. huffsize[p] = 0;
  362. lastp = p;
  363. code = 0;
  364. si = huffsize[0];
  365. p = 0;
  366. while (huffsize[p] != 0)
  367. {
  368. while (huffsize[p] == si)
  369. {
  370. huffcode[p++] = code;
  371. code++;
  372. }
  373. code <<= 1;
  374. si++;
  375. }
  376. for (p = 0; p < lastp; p++)
  377. {
  378. DC_matrix0[valDCluminance[p], 0] = huffcode[p];
  379. DC_matrix0[valDCluminance[p], 1] = huffsize[p];
  380. }
  381. /*
  382. * Init of the AC hufmann code for luminance
  383. * matrix [,,0] is the code & matrix[,,1] is the number of bit
  384. */
  385. p = 0;
  386. for (l = 0; l < 16; l++)
  387. {
  388. for (i = 1; i <= bitsACluminance[l]; i++)
  389. {
  390. huffsize[p++] = l+1;
  391. }
  392. }
  393. huffsize[p] = 0;
  394. lastp = p;
  395. code = 0;
  396. si = huffsize[0];
  397. p = 0;
  398. while (huffsize[p] != 0)
  399. {
  400. while (huffsize[p] == si)
  401. {
  402. huffcode[p++] = code;
  403. code++;
  404. }
  405. code <<= 1;
  406. si++;
  407. }
  408. for (int q = 0; q < lastp; q++)
  409. {
  410. AC_matrix0[valACluminance[q], 0] = huffcode[q];
  411. AC_matrix0[valACluminance[q], 1] = huffsize[q];
  412. }
  413. DC_matrix[0] = DC_matrix0;
  414. DC_matrix[1] = DC_matrix1;
  415. AC_matrix[0] = AC_matrix0;
  416. AC_matrix[1] = AC_matrix1;
  417. }
  418. }
  419. }