TerrainCompressor.cs 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSimulator Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. /* Freely adapted from the Aurora version of the terrain compressor.
  28. * Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/
  29. * Aurora version created from libOpenMetaverse Library terrain compressor
  30. */
  31. // terrain patchs must be 16mx16m
  32. using System;
  33. using System.Collections.Generic;
  34. using log4net;
  35. using OpenSim.Framework;
  36. using OpenMetaverse;
  37. using OpenMetaverse.Packets;
  38. namespace OpenSim.Region.ClientStack.LindenUDP
  39. {
  40. public static class OpenSimTerrainCompressor
  41. {
  42. private const float OO_SQRT2 = 0.7071068f;
  43. private const int END_OF_PATCHES = 97;
  44. private const int STRIDE = 264;
  45. private const int ZERO_CODE = 0x0;
  46. private const int ZERO_EOB = 0x2;
  47. private const int POSITIVE_VALUE = 0x6;
  48. private const int NEGATIVE_VALUE = 0x7;
  49. private static readonly int[] CopyMatrix16 = new int[256];
  50. private static readonly float[] QuantizeTable16 = new float[256];
  51. private static readonly float[] DequantizeTable16 = new float[256];
  52. static OpenSimTerrainCompressor()
  53. {
  54. if(Constants.TerrainPatchSize != 16)
  55. throw new Exception("Terrain patch size must be 16m x 16m");
  56. // Initialize the decompression tables
  57. BuildDequantizeTable16();
  58. BuildCopyMatrix16();
  59. BuildQuantizeTable16();
  60. }
  61. // Used to send cloud and wind patches
  62. public static LayerDataPacket CreateLayerDataPacketStandardSize(TerrainPatch[] patches, byte type)
  63. {
  64. LayerDataPacket layer = new LayerDataPacket { LayerID = { Type = type } };
  65. TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader { Stride = STRIDE, PatchSize = 16 };
  66. // Should be enough to fit even the most poorly packed data
  67. byte[] data = new byte[patches.Length * 256 * 2];
  68. BitPack bitpack = new BitPack(data, 0);
  69. bitpack.PackBits(header.Stride, 16);
  70. bitpack.PackBits(header.PatchSize, 8);
  71. bitpack.PackBits(type, 8);
  72. foreach (TerrainPatch t in patches)
  73. CreatePatchtStandardSize(bitpack, t.Data, t.X, t.Y);
  74. bitpack.PackBits(END_OF_PATCHES, 8);
  75. layer.LayerData.Data = new byte[bitpack.BytePos + 1];
  76. Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
  77. return layer;
  78. }
  79. public static void CreatePatchtStandardSize(BitPack output, float[] patchData, int x, int y)
  80. {
  81. TerrainPatch.Header header = PrescanPatch(patchData);
  82. header.QuantWBits = 136;
  83. header.PatchIDs = (y & 0x1F);
  84. header.PatchIDs += (x << 5);
  85. int wbits;
  86. int[] patch = CompressPatch(patchData, header, 10, out wbits);
  87. EncodePatchHeader(output, header, false, ref wbits);
  88. EncodePatch(output, patch, 0, wbits);
  89. }
  90. private static TerrainPatch.Header PrescanPatch(float[] patch)
  91. {
  92. TerrainPatch.Header header = new TerrainPatch.Header();
  93. float zmax = -99999999.0f;
  94. float zmin = 99999999.0f;
  95. for (int i = 0; i < 256; i++)
  96. {
  97. float val = patch[i];
  98. if (val > zmax) zmax = val;
  99. if (val < zmin) zmin = val;
  100. }
  101. header.DCOffset = zmin;
  102. header.Range = (int)((zmax - zmin) + 1.0f);
  103. return header;
  104. }
  105. private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits)
  106. {
  107. float[] block = new float[256];
  108. float oozrange = 1.0f / header.Range;
  109. float range = (1 << prequant);
  110. float premult = oozrange * range;
  111. float sub = 0.5f * header.Range + header.DCOffset;
  112. int wordsize = (prequant - 2) & 0x0f;
  113. header.QuantWBits = wordsize;
  114. header.QuantWBits |= wordsize << 4;
  115. int k = 0;
  116. for (int j = 0; j < 16; j++)
  117. {
  118. for (int i = 0; i < 16; i++)
  119. block[k++] = (patchData[j * 16 + i] - sub) * premult;
  120. }
  121. wbits = (prequant >> 1);
  122. int[] iout = new int[256];
  123. dct16x16(block, iout, ref wbits);
  124. return iout;
  125. }
  126. /*
  127. // new using terrain data and patchs indexes
  128. public static List<LayerDataPacket> CreateLayerDataPackets(TerrainData terrData, int[] map)
  129. {
  130. List<LayerDataPacket> ret = new List<LayerDataPacket>();
  131. int numberPatchs = map.Length / 2;
  132. byte[] data = new byte[numberPatchs * 256 * 2];
  133. //create packet and global header
  134. LayerDataPacket layer = new LayerDataPacket();
  135. byte landPacketType;
  136. if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
  137. landPacketType = (byte)TerrainPatch.LayerType.LandExtended;
  138. else
  139. landPacketType = (byte)TerrainPatch.LayerType.Land;
  140. layer.LayerID.Type = landPacketType;
  141. BitPack bitpack = new BitPack(data, 0);
  142. bitpack.PackBits(STRIDE, 16);
  143. bitpack.PackBitsFromByte(16);
  144. bitpack.PackBitsFromByte(landPacketType);
  145. int s;
  146. for (int i = 0; i < numberPatchs; i++)
  147. {
  148. s = 2 * i;
  149. CreatePatchFromTerrainData(bitpack, terrData, map[s], map[s + 1]);
  150. if (bitpack.BytePos > 950 && i != numberPatchs - 1)
  151. {
  152. //finish this packet
  153. bitpack.PackBitsFromByte(END_OF_PATCHES);
  154. layer.LayerData.Data = new byte[bitpack.BytePos + 1];
  155. Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
  156. ret.Add(layer);
  157. // start another
  158. layer = new LayerDataPacket();
  159. layer.LayerID.Type = landPacketType;
  160. bitpack = new BitPack(data, 0);
  161. bitpack.PackBits(STRIDE, 16);
  162. bitpack.PackBitsFromByte(16);
  163. bitpack.PackBitsFromByte(landPacketType);
  164. }
  165. }
  166. bitpack.PackBitsFromByte(END_OF_PATCHES);
  167. layer.LayerData.Data = new byte[bitpack.BytePos + 1];
  168. Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
  169. ret.Add(layer);
  170. return ret;
  171. }
  172. */
  173. public static void CreatePatchFromTerrainData(BitPack output, TerrainData terrData, int patchX, int patchY)
  174. {
  175. float frange;
  176. TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY, out frange);
  177. header.QuantWBits = 130;
  178. bool largeRegion = false;
  179. // If larger than legacy region size, pack patch X and Y info differently.
  180. if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
  181. {
  182. header.PatchIDs = (patchY & 0xFFFF);
  183. header.PatchIDs += (patchX << 16);
  184. largeRegion = true;
  185. }
  186. else
  187. {
  188. header.PatchIDs = (patchY & 0x1F);
  189. header.PatchIDs += (patchX << 5);
  190. }
  191. if (Math.Round(frange, 2) == 1.0)
  192. {
  193. // flat terrain speed up things
  194. output.PackBitsFromByte(0); //QuantWBits
  195. output.PackFloat(header.DCOffset - 0.5f);
  196. output.PackBitsFromByte(1); //range low
  197. output.PackBitsFromByte(0); //range high
  198. if (largeRegion)
  199. output.PackBits(header.PatchIDs, 32);
  200. else
  201. output.PackBits(header.PatchIDs, 10);
  202. // and thats all
  203. output.PackBits(ZERO_EOB, 2);
  204. return;
  205. }
  206. int wbits;
  207. int[] patch = CompressPatch(terrData, patchX, patchY, header, 10, out wbits);
  208. EncodePatchHeader(output, header, largeRegion, ref wbits);
  209. EncodePatch(output, patch, 0, wbits);
  210. }
  211. // Scan the height info we're returning and return a patch packet header for this patch.
  212. private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY, out float frange)
  213. {
  214. TerrainPatch.Header header = new TerrainPatch.Header();
  215. float zmax = float.MinValue;
  216. float zmin = float.MaxValue;
  217. terrData.GetPatchMinMax(patchX, patchY, out zmin, out zmax);
  218. header.DCOffset = zmin;
  219. frange = ((zmax - zmin) + 1.0f);
  220. header.Range = (int)frange;
  221. return header;
  222. }
  223. private static void EncodePatchHeader(BitPack output, TerrainPatch.Header header, bool largeRegion, ref int wbits)
  224. {
  225. if (wbits > 17)
  226. wbits = 17;
  227. else if (wbits < 2)
  228. wbits = 2;
  229. header.QuantWBits &= 0xf0;
  230. header.QuantWBits |= (wbits - 2);
  231. output.PackBitsFromByte((byte)header.QuantWBits);
  232. output.PackFloat(header.DCOffset);
  233. output.PackBits(header.Range, 16);
  234. if (largeRegion)
  235. output.PackBits(header.PatchIDs, 32);
  236. else
  237. output.PackBits(header.PatchIDs, 10);
  238. }
  239. private unsafe static void EncodePatch(BitPack output, int[] _patch, int postquant, int wbits)
  240. {
  241. int maxwbitssize = (1 << wbits) - 1;
  242. if (postquant > 256 || postquant < 0)
  243. {
  244. Logger.Log("Postquant is outside the range of allowed values in EncodePatch()", Helpers.LogLevel.Error);
  245. return;
  246. }
  247. int lastZeroindx = 256 - postquant;
  248. fixed(int * patch = _patch)
  249. {
  250. if (lastZeroindx != 256)
  251. patch[lastZeroindx] = 0;
  252. int i = 0;
  253. while(i < 256)
  254. {
  255. int temp = patch[i];
  256. if (temp == 0)
  257. {
  258. int j = i + 1;
  259. while(j < lastZeroindx)
  260. {
  261. if (patch[j] != 0)
  262. break;
  263. ++j;
  264. }
  265. if (j == lastZeroindx)
  266. {
  267. output.PackBits(ZERO_EOB, 2);
  268. return;
  269. }
  270. i = j - i;
  271. while(i > 8)
  272. {
  273. output.PackBitsFromByte(ZERO_CODE);
  274. i -= 8;
  275. }
  276. if( i > 0)
  277. output.PackBitsFromByte(ZERO_CODE, i);
  278. i = j;
  279. continue;
  280. }
  281. if (temp < 0)
  282. {
  283. temp *= -1;
  284. if (temp > maxwbitssize)
  285. temp = maxwbitssize;
  286. output.PackBits(NEGATIVE_VALUE, 3);
  287. output.PackBits(temp, wbits);
  288. }
  289. else
  290. {
  291. if (temp > maxwbitssize)
  292. temp = maxwbitssize;
  293. output.PackBits(POSITIVE_VALUE, 3);
  294. output.PackBits(temp, wbits);
  295. }
  296. ++i;
  297. }
  298. }
  299. }
  300. private static int[] CompressPatch(TerrainData terrData, int patchX, int patchY, TerrainPatch.Header header,
  301. int prequant, out int wbits)
  302. {
  303. float[] block = new float[256];
  304. int[] iout = new int[256];
  305. float oozrange = 1.0f / header.Range;
  306. float invprequat = (1 << prequant);
  307. float premult = oozrange * invprequat;
  308. float sub = 0.5f * header.Range + header.DCOffset;
  309. int wordsize = (prequant - 2) & 0x0f;
  310. header.QuantWBits = wordsize;
  311. header.QuantWBits |= wordsize << 4;
  312. terrData.GetPatchBlock(block, patchX, patchY, sub, premult);
  313. wbits = (prequant >> 1);
  314. dct16x16(block, iout, ref wbits);
  315. return iout;
  316. }
  317. #region Initialization
  318. private static void BuildDequantizeTable16()
  319. {
  320. for (int j = 0; j < 16; j++)
  321. {
  322. int c = j * 16;
  323. for (int i = 0; i < 16; i++)
  324. {
  325. DequantizeTable16[c + i] = 1.0f + 2.0f * (i + j);
  326. }
  327. }
  328. }
  329. private unsafe static void BuildQuantizeTable16()
  330. {
  331. const float oosob = 2.0f / 16;
  332. fixed(float* fQuantizeTable16 = QuantizeTable16)
  333. {
  334. for (int j = 0; j < 16; j++)
  335. {
  336. int c = j * 16;
  337. for (int i = 0; i < 16; i++)
  338. {
  339. fQuantizeTable16[c + i] = oosob / (1.0f + 2.0f * (i + j));
  340. }
  341. }
  342. }
  343. }
  344. private unsafe static void BuildCopyMatrix16()
  345. {
  346. bool diag = false;
  347. bool right = true;
  348. int i = 0;
  349. int j = 0;
  350. int count = 0;
  351. fixed (int* fCopyMatrix16 = CopyMatrix16)
  352. {
  353. while (i < 16 && j < 16)
  354. {
  355. fCopyMatrix16[j * 16 + i] = count++;
  356. if (!diag)
  357. {
  358. if (right)
  359. {
  360. if (i < 15) i++;
  361. else j++;
  362. right = false;
  363. diag = true;
  364. }
  365. else
  366. {
  367. if (j < 15 ) j++;
  368. else i++;
  369. right = true;
  370. diag = true;
  371. }
  372. }
  373. else
  374. {
  375. if (right)
  376. {
  377. i++;
  378. j--;
  379. if (i == 15 || j == 0) diag = false;
  380. }
  381. else
  382. {
  383. i--;
  384. j++;
  385. if (j == 15 || i == 0) diag = false;
  386. }
  387. }
  388. }
  389. }
  390. }
  391. #endregion Initialization
  392. #region DCT
  393. /* DCT (Discrete Cosine Transform)
  394. adaptation from
  395. General Purpose 2D,3D FFT (Fast Fourier Transform) Package
  396. by Takuya OOURA (email: [email protected])
  397. -------- 16x16 DCT (Discrete Cosine Transform) / Inverse of DCT --------
  398. [definition]
  399. <case1> Normalized 16x16 IDCT
  400. C[k1 + k2] = (1/8) * sum_j1=0^15 sum_j2=0^15
  401. tmp[j1 + j2] * s[j1] * s[j2] *
  402. cos(pi*j1*(k1+1/2)/16) *
  403. cos(pi*j2*(k2+1/2)/16), 0<=k1<16, 0<=k2<16
  404. (s[0] = 1/sqrt(2), s[j] = 1, j > 0)
  405. <case2> Normalized 16x16 DCT
  406. C[k1 + k2] = (1/8) * s[k1] * s[k2] * sum_j1=0^15 sum_j2=0^15
  407. tmp[j1 + j2] *
  408. cos(pi*(j1+1/2)*k1/16) *
  409. cos(pi*(j2+1/2)*k2/16), 0<=k1<16, 0<=k2<16
  410. (s[0] = 1/sqrt(2), s[j] = 1, j > 0)
  411. */
  412. /* Cn_kR = sqrt(2.0/n) * cos(pi/2*k/n) */
  413. /* Cn_kI = sqrt(2.0/n) * sin(pi/2*k/n) */
  414. /* Wn_kR = cos(pi/2*k/n) */
  415. /* Wn_kI = sin(pi/2*k/n) */
  416. const float C16_1R = 0.35185093438159561476f * 2.82842712474619f;
  417. const float C16_1I = 0.03465429229977286565f * 2.82842712474619f;
  418. const float C16_2R = 0.34675996133053686546f * 2.82842712474619f;
  419. const float C16_2I = 0.06897484482073575308f * 2.82842712474619f;
  420. const float C16_3R = 0.33832950029358816957f * 2.82842712474619f;
  421. const float C16_3I = 0.10263113188058934529f * 2.82842712474619f;
  422. const float C16_4R = 0.32664074121909413196f * 2.82842712474619f;
  423. const float C16_4I = 0.13529902503654924610f * 2.82842712474619f;
  424. const float C16_5R = 0.31180625324666780814f * 2.82842712474619f;
  425. const float C16_5I = 0.16666391461943662432f * 2.82842712474619f;
  426. const float C16_6R = 0.29396890060483967924f * 2.82842712474619f;
  427. const float C16_6I = 0.19642373959677554532f * 2.82842712474619f;
  428. const float C16_7R = 0.27330046675043937206f * 2.82842712474619f;
  429. const float C16_7I = 0.22429189658565907106f * 2.82842712474619f;
  430. const float C16_8R = 0.25f * 2.82842712474619f;
  431. const float W16_4R = 0.92387953251128675613f;
  432. const float W16_4I = 0.38268343236508977173f;
  433. const float W16_8R = 0.70710678118654752440f;
  434. unsafe static void dct16x16(float[] _a, int[] _iout, ref int wbits)
  435. {
  436. float[] _tmp = new float[256];
  437. float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
  438. float x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;
  439. float xr, xi;
  440. float ftmp;
  441. int itmp;
  442. int j, k;
  443. int indx;
  444. const int maxwbits = 17; // per header encoding
  445. int wbitsMaxValue = 1 << wbits;
  446. bool dowbits = wbits < 17;
  447. fixed (float* a = _a, tmp = _tmp, fQuantizeTable16 = QuantizeTable16)
  448. fixed (int* iout = _iout, fCopyMatrix16 = CopyMatrix16)
  449. {
  450. for (j = 0, k = 0; j < 256; j += 16, k++)
  451. {
  452. x4r = a[0 + j] - a[15 + j];
  453. xr = a[0 + j] + a[15 + j];
  454. x4i = a[8 + j] - a[7 + j];
  455. xi = a[8 + j] + a[7 + j];
  456. x0r = xr + xi;
  457. x0i = xr - xi;
  458. x5r = a[2 + j] - a[13 + j];
  459. xr = a[2 + j] + a[13 + j];
  460. x5i = a[10 + j] - a[5 + j];
  461. xi = a[10 + j] + a[5 + j];
  462. x1r = xr + xi;
  463. x1i = xr - xi;
  464. x6r = a[4 + j] - a[11 + j];
  465. xr = a[4 + j] + a[11 + j];
  466. x6i = a[12 + j] - a[3 + j];
  467. xi = a[12 + j] + a[3 + j];
  468. x2r = xr + xi;
  469. x2i = xr - xi;
  470. x7r = a[6 + j] - a[9 + j];
  471. xr = a[6 + j] + a[9 + j];
  472. x7i = a[14 + j] - a[1 + j];
  473. xi = a[14 + j] + a[1 + j];
  474. x3r = xr + xi;
  475. x3i = xr - xi;
  476. xr = x0r + x2r;
  477. xi = x1r + x3r;
  478. tmp[k] = C16_8R * (xr + xi); //
  479. tmp[8 * 16 + k] = C16_8R * (xr - xi); //
  480. xr = x0r - x2r;
  481. xi = x1r - x3r;
  482. tmp[4 * 16 + k] = C16_4R * xr - C16_4I * xi; //
  483. tmp[12 * 16 + k] = C16_4R * xi + C16_4I * xr; //
  484. x0r = W16_8R * (x1i - x3i);
  485. x2r = W16_8R * (x1i + x3i);
  486. xr = x0i + x0r;
  487. xi = x2r + x2i;
  488. tmp[2 * 16 + k] = C16_2R * xr - C16_2I * xi; //
  489. tmp[14 * 16 + k] = C16_2R * xi + C16_2I * xr; //
  490. xr = x0i - x0r;
  491. xi = x2r - x2i;
  492. tmp[6 * 16 + k] = C16_6R * xr - C16_6I * xi; //
  493. tmp[10 * 16 + k] = C16_6R * xi + C16_6I * xr; //
  494. xr = W16_8R * (x6r - x6i);
  495. xi = W16_8R * (x6i + x6r);
  496. x6r = x4r - xr;
  497. x6i = x4i - xi;
  498. x4r += xr;
  499. x4i += xi;
  500. xr = W16_4I * x7r - W16_4R * x7i;
  501. xi = W16_4I * x7i + W16_4R * x7r;
  502. x7r = W16_4R * x5r - W16_4I * x5i;
  503. x7i = W16_4R * x5i + W16_4I * x5r;
  504. x5r = x7r + xr;
  505. x5i = x7i + xi;
  506. x7r -= xr;
  507. x7i -= xi;
  508. xr = x4r + x5r;
  509. xi = x5i + x4i;
  510. tmp[16 + k] = C16_1R * xr - C16_1I * xi; //
  511. tmp[15 * 16 + k] = C16_1R * xi + C16_1I * xr; //
  512. xr = x4r - x5r;
  513. xi = x5i - x4i;
  514. tmp[7 * 16 + k] = C16_7R * xr - C16_7I * xi; //
  515. tmp[9 * 16 + k] = C16_7R * xi + C16_7I * xr; //
  516. xr = x6r - x7i;
  517. xi = x7r + x6i;
  518. tmp[5 * 16 + k] = C16_5R * xr - C16_5I * xi; //
  519. tmp[11 * 16 + k] = C16_5R * xi + C16_5I * xr; //
  520. xr = x6r + x7i;
  521. xi = x7r - x6i;
  522. tmp[3 * 16 + k] = C16_3R * xr - C16_3I * xi; //
  523. tmp[13 * 16 + k] = C16_3R * xi + C16_3I * xr; //
  524. }
  525. for (j = 0, k = 0; j < 256; j += 16, k++)
  526. {
  527. x4r = tmp[0 + j] - tmp[15 + j];
  528. xr = tmp[0 + j] + tmp[15 + j];
  529. x4i = tmp[8 + j] - tmp[7 + j];
  530. xi = tmp[8 + j] + tmp[7 + j];
  531. x0r = xr + xi;
  532. x0i = xr - xi;
  533. x5r = tmp[2 + j] - tmp[13 + j];
  534. xr = tmp[2 + j] + tmp[13 + j];
  535. x5i = tmp[10 + j] - tmp[5 + j];
  536. xi = tmp[10 + j] + tmp[5 + j];
  537. x1r = xr + xi;
  538. x1i = xr - xi;
  539. x6r = tmp[4 + j] - tmp[11 + j];
  540. xr = tmp[4 + j] + tmp[11 + j];
  541. x6i = tmp[12 + j] - tmp[3 + j];
  542. xi = tmp[12 + j] + tmp[3 + j];
  543. x2r = xr + xi;
  544. x2i = xr - xi;
  545. x7r = tmp[6 + j] - tmp[9 + j];
  546. xr = tmp[6 + j] + tmp[9 + j];
  547. x7i = tmp[14 + j] - tmp[1 + j];
  548. xi = tmp[14 + j] + tmp[1 + j];
  549. x3r = xr + xi;
  550. x3i = xr - xi;
  551. xr = x0r + x2r;
  552. xi = x1r + x3r;
  553. //tmp[0 + k] = C16_8R * (xr + xi); //
  554. ftmp = C16_8R * (xr + xi);
  555. itmp = (int)(ftmp * fQuantizeTable16[k]);
  556. iout[fCopyMatrix16[k]] = itmp;
  557. if (dowbits)
  558. {
  559. if (itmp < 0) itmp *= -1;
  560. while (itmp > wbitsMaxValue)
  561. {
  562. wbits++;
  563. wbitsMaxValue = 1 << wbits;
  564. if (wbits == maxwbits)
  565. {
  566. dowbits = false;
  567. break;
  568. }
  569. }
  570. }
  571. //tmp[8 * Constants.TerrainPatchSize + k] = C16_8R * (xr - xi); //
  572. ftmp = C16_8R * (xr - xi);
  573. indx = 8 * 16 + k;
  574. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  575. iout[fCopyMatrix16[indx]] = itmp;
  576. if (dowbits)
  577. {
  578. if (itmp < 0) itmp *= -1;
  579. while (itmp > wbitsMaxValue)
  580. {
  581. wbits++;
  582. wbitsMaxValue = 1 << wbits;
  583. if (wbits == maxwbits)
  584. {
  585. dowbits = false;
  586. break;
  587. }
  588. }
  589. }
  590. xr = x0r - x2r;
  591. xi = x1r - x3r;
  592. //tmp[4 * Constants.TerrainPatchSize + k] = C16_4R * xr - C16_4I * xi; //
  593. ftmp = C16_4R * xr - C16_4I * xi;
  594. indx = 4 * 16 + k;
  595. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  596. iout[fCopyMatrix16[indx]] = itmp;
  597. if (dowbits)
  598. {
  599. if (itmp < 0) itmp *= -1;
  600. while (itmp > wbitsMaxValue)
  601. {
  602. wbits++;
  603. wbitsMaxValue = 1 << wbits;
  604. if (wbits == maxwbits)
  605. {
  606. dowbits = false;
  607. break;
  608. }
  609. }
  610. }
  611. //tmp[12 * Constants.TerrainPatchSize + k] = C16_4R * xi + C16_4I * xr; //
  612. ftmp = C16_4R * xi + C16_4I * xr;
  613. indx = 12 * 16 + k;
  614. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  615. iout[fCopyMatrix16[indx]] = itmp;
  616. if (dowbits)
  617. {
  618. if (itmp < 0) itmp *= -1;
  619. while (itmp > wbitsMaxValue)
  620. {
  621. wbits++;
  622. wbitsMaxValue = 1 << wbits;
  623. if (wbits == maxwbits)
  624. {
  625. dowbits = false;
  626. break;
  627. }
  628. }
  629. }
  630. x0r = W16_8R * (x1i - x3i);
  631. x2r = W16_8R * (x1i + x3i);
  632. xr = x0i + x0r;
  633. xi = x2r + x2i;
  634. //tmp[2 * Constants.TerrainPatchSize + k] = C16_2R * xr - C16_2I * xi; //
  635. ftmp = C16_2R * xr - C16_2I * xi;
  636. indx = 2 * 16 + k;
  637. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  638. iout[fCopyMatrix16[indx]] = itmp;
  639. if (dowbits)
  640. {
  641. if (itmp < 0) itmp *= -1;
  642. while (itmp > wbitsMaxValue)
  643. {
  644. wbits++;
  645. wbitsMaxValue = 1 << wbits;
  646. if (wbits == maxwbits)
  647. {
  648. dowbits = false;
  649. break;
  650. }
  651. }
  652. }
  653. //tmp[14 * Constants.TerrainPatchSize + k] = C16_2R * xi + C16_2I * xr; //
  654. ftmp = C16_2R * xi + C16_2I * xr;
  655. indx = 14 * 16 + k;
  656. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  657. iout[fCopyMatrix16[indx]] = itmp;
  658. if (dowbits)
  659. {
  660. if (itmp < 0) itmp *= -1;
  661. while (itmp > wbitsMaxValue)
  662. {
  663. wbits++;
  664. wbitsMaxValue = 1 << wbits;
  665. if (wbits == maxwbits)
  666. {
  667. dowbits = false;
  668. break;
  669. }
  670. }
  671. }
  672. xr = x0i - x0r;
  673. xi = x2r - x2i;
  674. //tmp[6 * Constants.TerrainPatchSize + k] = C16_6R * xr - C16_6I * xi; //
  675. ftmp = C16_6R * xr - C16_6I * xi;
  676. indx = 6 * 16 + k;
  677. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  678. iout[fCopyMatrix16[indx]] = itmp;
  679. if (dowbits)
  680. {
  681. if (itmp < 0) itmp *= -1;
  682. while (itmp > wbitsMaxValue)
  683. {
  684. wbits++;
  685. wbitsMaxValue = 1 << wbits;
  686. if (wbits == maxwbits)
  687. {
  688. dowbits = false;
  689. break;
  690. }
  691. }
  692. }
  693. //tmp[10 * Constants.TerrainPatchSize + k] = C16_6R * xi + C16_6I * xr; //
  694. ftmp = C16_6R * xi + C16_6I * xr;
  695. indx = 10 * 16 + k;
  696. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  697. iout[fCopyMatrix16[indx]] = itmp;
  698. if (dowbits)
  699. {
  700. if (itmp < 0) itmp *= -1;
  701. while (itmp > wbitsMaxValue)
  702. {
  703. wbits++;
  704. wbitsMaxValue = 1 << wbits;
  705. if (wbits == maxwbits)
  706. {
  707. dowbits = false;
  708. break;
  709. }
  710. }
  711. }
  712. xr = W16_8R * (x6r - x6i);
  713. xi = W16_8R * (x6i + x6r);
  714. x6r = x4r - xr;
  715. x6i = x4i - xi;
  716. x4r += xr;
  717. x4i += xi;
  718. xr = W16_4I * x7r - W16_4R * x7i;
  719. xi = W16_4I * x7i + W16_4R * x7r;
  720. x7r = W16_4R * x5r - W16_4I * x5i;
  721. x7i = W16_4R * x5i + W16_4I * x5r;
  722. x5r = x7r + xr;
  723. x5i = x7i + xi;
  724. x7r -= xr;
  725. x7i -= xi;
  726. xr = x4r + x5r;
  727. xi = x5i + x4i;
  728. //tmp[1 * Constants.TerrainPatchSize + k] = C16_1R * xr - C16_1I * xi; //
  729. ftmp = C16_1R * xr - C16_1I * xi;
  730. indx = 16 + k;
  731. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  732. iout[fCopyMatrix16[indx]] = itmp;
  733. if (dowbits)
  734. {
  735. if (itmp < 0) itmp *= -1;
  736. while (itmp > wbitsMaxValue)
  737. {
  738. wbits++;
  739. wbitsMaxValue = 1 << wbits;
  740. if (wbits == maxwbits)
  741. {
  742. dowbits = false;
  743. break;
  744. }
  745. }
  746. }
  747. //tmp[15 * Constants.TerrainPatchSize + k] = C16_1R * xi + C16_1I * xr; //
  748. ftmp = C16_1R * xi + C16_1I * xr;
  749. indx = 15 * 16 + k;
  750. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  751. iout[fCopyMatrix16[indx]] = itmp;
  752. if (dowbits)
  753. {
  754. if (itmp < 0) itmp *= -1;
  755. while (itmp > wbitsMaxValue)
  756. {
  757. wbits++;
  758. wbitsMaxValue = 1 << wbits;
  759. if (wbits == maxwbits)
  760. {
  761. dowbits = false;
  762. break;
  763. }
  764. }
  765. }
  766. xr = x4r - x5r;
  767. xi = x5i - x4i;
  768. //tmp[7 * Constants.TerrainPatchSize + k] = C16_7R * xr - C16_7I * xi; //
  769. ftmp = C16_7R * xr - C16_7I * xi;
  770. indx = 7 * 16 + k;
  771. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  772. iout[fCopyMatrix16[indx]] = itmp;
  773. if (dowbits)
  774. {
  775. if (itmp < 0) itmp *= -1;
  776. while (itmp > wbitsMaxValue)
  777. {
  778. wbits++;
  779. wbitsMaxValue = 1 << wbits;
  780. if (wbits == maxwbits)
  781. {
  782. dowbits = false;
  783. break;
  784. }
  785. }
  786. }
  787. //tmp[9 * Constants.TerrainPatchSize + k] = C16_7R * xi + C16_7I * xr; //
  788. ftmp = C16_7R * xi + C16_7I * xr;
  789. indx = 9 * 16 + k;
  790. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  791. iout[fCopyMatrix16[indx]] = itmp;
  792. if (dowbits)
  793. {
  794. if (itmp < 0) itmp *= -1;
  795. while (itmp > wbitsMaxValue)
  796. {
  797. wbits++;
  798. wbitsMaxValue = 1 << wbits;
  799. if (wbits == maxwbits)
  800. {
  801. dowbits = false;
  802. break;
  803. }
  804. }
  805. }
  806. xr = x6r - x7i;
  807. xi = x7r + x6i;
  808. //tmp[5 * Constants.TerrainPatchSize + k] = C16_5R * xr - C16_5I * xi; //
  809. ftmp = C16_5R * xr - C16_5I * xi;
  810. indx = 5 * 16 + k;
  811. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  812. iout[fCopyMatrix16[indx]] = itmp;
  813. if (dowbits)
  814. {
  815. if (itmp < 0) itmp *= -1;
  816. while (itmp > wbitsMaxValue)
  817. {
  818. wbits++;
  819. wbitsMaxValue = 1 << wbits;
  820. if (wbits == maxwbits)
  821. {
  822. dowbits = false;
  823. break;
  824. }
  825. }
  826. }
  827. //tmp[11 * Constants.TerrainPatchSize + k] = C16_5R * xi + C16_5I * xr; //
  828. ftmp = C16_5R * xi + C16_5I * xr;
  829. indx = 11 * 16 + k;
  830. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  831. iout[fCopyMatrix16[indx]] = itmp;
  832. if (dowbits)
  833. {
  834. if (itmp < 0) itmp *= -1;
  835. while (itmp > wbitsMaxValue)
  836. {
  837. wbits++;
  838. wbitsMaxValue = 1 << wbits;
  839. if (wbits == maxwbits)
  840. {
  841. dowbits = false;
  842. break;
  843. }
  844. }
  845. }
  846. xr = x6r + x7i;
  847. xi = x7r - x6i;
  848. //tmp[3 * Constants.TerrainPatchSize + k] = C16_3R * xr - C16_3I * xi; //
  849. ftmp = C16_3R * xr - C16_3I * xi;
  850. indx = 3 * 16 + k;
  851. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  852. iout[fCopyMatrix16[indx]] = itmp;
  853. if (dowbits)
  854. {
  855. if (itmp < 0) itmp *= -1;
  856. while (itmp > wbitsMaxValue)
  857. {
  858. wbits++;
  859. wbitsMaxValue = 1 << wbits;
  860. if (wbits == maxwbits)
  861. {
  862. dowbits = false;
  863. break;
  864. }
  865. }
  866. }
  867. //tmp[13 * Constants.TerrainPatchSize + k] = C16_3R * xi + C16_3I * xr; //
  868. ftmp = C16_3R * xi + C16_3I * xr;
  869. indx = 13 * 16 + k;
  870. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  871. iout[fCopyMatrix16[indx]] = itmp;
  872. if (dowbits)
  873. {
  874. if (itmp < 0) itmp *= -1;
  875. while (itmp > wbitsMaxValue)
  876. {
  877. wbits++;
  878. wbitsMaxValue = 1 << wbits;
  879. if (wbits == maxwbits)
  880. {
  881. dowbits = false;
  882. break;
  883. }
  884. }
  885. }
  886. }
  887. }
  888. }
  889. #endregion DCT
  890. #region IDCT
  891. /* not in use
  892. private static void IDCTColumn16(float[] linein, float[] lineout, int column)
  893. {
  894. for (int n = 0; n < Constants.TerrainPatchSize; n++)
  895. {
  896. float total = OO_SQRT2 * linein[column];
  897. for (int u = 1; u < Constants.TerrainPatchSize; u++)
  898. {
  899. int usize = u * Constants.TerrainPatchSize;
  900. total += linein[usize + column] * CosineTable16[usize + n];
  901. }
  902. lineout[Constants.TerrainPatchSize * n + column] = total;
  903. }
  904. }
  905. private static void IDCTLine16(float[] linein, float[] lineout, int line)
  906. {
  907. const float oosob = 2.0f / Constants.TerrainPatchSize;
  908. int lineSize = line * Constants.TerrainPatchSize;
  909. for (int n = 0; n < Constants.TerrainPatchSize; n++)
  910. {
  911. float total = OO_SQRT2 * linein[lineSize];
  912. for (int u = 1; u < Constants.TerrainPatchSize; u++)
  913. {
  914. total += linein[lineSize + u] * CosineTable16[u * Constants.TerrainPatchSize + n];
  915. }
  916. lineout[lineSize + n] = total * oosob;
  917. }
  918. }
  919. //not in use, and still not fixed
  920. /*
  921. static void idct16x16(float[] a)
  922. {
  923. int j;
  924. float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
  925. float x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;
  926. float xr, xi;
  927. int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
  928. for (j = 0; j < fullSize; j += Constants.TerrainPatchSize)
  929. {
  930. x5r = C16_1R * tmp[1 + j] + C16_1I * tmp[15 + j];
  931. x5i = C16_1R * tmp[15 + j] - C16_1I * tmp[1 + j];
  932. xr = C16_7R * tmp[7 + j] + C16_7I * tmp[9 + j];
  933. xi = C16_7R * tmp[9 + j] - C16_7I * tmp[7 + j];
  934. x4r = x5r + xr;
  935. x4i = x5i - xi;
  936. x5r -= xr;
  937. x5i += xi;
  938. x7r = C16_5R * tmp[5 + j] + C16_5I * tmp[11 + j];
  939. x7i = C16_5R * tmp[11 + j] - C16_5I * tmp[5 + j];
  940. xr = C16_3R * tmp[3 + j] + C16_3I * tmp[13 + j];
  941. xi = C16_3R * tmp[13 + j] - C16_3I * tmp[3 + j];
  942. x6r = x7r + xr;
  943. x6i = x7i - xi;
  944. x7r -= xr;
  945. x7i += xi;
  946. xr = x4r - x6r;
  947. xi = x4i - x6i;
  948. x4r += x6r;
  949. x4i += x6i;
  950. x6r = W16_8R * (xi + xr);
  951. x6i = W16_8R * (xi - xr);
  952. xr = x5r + x7i;
  953. xi = x5i - x7r;
  954. x5r -= x7i;
  955. x5i += x7r;
  956. x7r = W16_4I * x5r + W16_4R * x5i;
  957. x7i = W16_4I * x5i - W16_4R * x5r;
  958. x5r = W16_4R * xr + W16_4I * xi;
  959. x5i = W16_4R * xi - W16_4I * xr;
  960. xr = C16_4R * tmp[4 + j] + C16_4I * tmp[12 + j];
  961. xi = C16_4R * tmp[12 + j] - C16_4I * tmp[4 + j];
  962. x2r = C16_8R * (tmp[0 + j] + tmp[8 + j]);
  963. x3r = C16_8R * (tmp[0 + j] - tmp[8 + j]);
  964. x0r = x2r + xr;
  965. x1r = x3r + xi;
  966. x2r -= xr;
  967. x3r -= xi;
  968. x0i = C16_2R * tmp[2 + j] + C16_2I * tmp[14 + j];
  969. x2i = C16_2R * tmp[14 + j] - C16_2I * tmp[2 + j];
  970. x1i = C16_6R * tmp[6 + j] + C16_6I * tmp[10 + j];
  971. x3i = C16_6R * tmp[10 + j] - C16_6I * tmp[6 + j];
  972. xr = x0i - x1i;
  973. xi = x2i + x3i;
  974. x0i += x1i;
  975. x2i -= x3i;
  976. x1i = W16_8R * (xi + xr);
  977. x3i = W16_8R * (xi - xr);
  978. xr = x0r + x0i;
  979. xi = x0r - x0i;
  980. tmp[0 + j] = xr + x4r;
  981. tmp[15 + j] = xr - x4r;
  982. tmp[8 + j] = xi + x4i;
  983. tmp[7 + j] = xi - x4i;
  984. xr = x1r + x1i;
  985. xi = x1r - x1i;
  986. tmp[2 + j] = xr + x5r;
  987. tmp[13 + j] = xr - x5r;
  988. tmp[10 + j] = xi + x5i;
  989. tmp[5 + j] = xi - x5i;
  990. xr = x2r + x2i;
  991. xi = x2r - x2i;
  992. tmp[4 + j] = xr + x6r;
  993. tmp[11 + j] = xr - x6r;
  994. tmp[12 + j] = xi + x6i;
  995. tmp[3 + j] = xi - x6i;
  996. xr = x3r + x3i;
  997. xi = x3r - x3i;
  998. tmp[6 + j] = xr + x7r;
  999. tmp[9 + j] = xr - x7r;
  1000. tmp[14 + j] = xi + x7i;
  1001. tmp[1 + j] = xi - x7i;
  1002. }
  1003. for (j = 0; j < fullSize; j += Constants.TerrainPatchSize)
  1004. {
  1005. x5r = C16_1R * tmp[j + 1] + C16_1I * tmp[j + 15];
  1006. x5i = C16_1R * tmp[j + 15] - C16_1I * tmp[j + 1];
  1007. xr = C16_7R * tmp[j + 7] + C16_7I * tmp[j + 9];
  1008. xi = C16_7R * tmp[j + 9] - C16_7I * tmp[j + 7];
  1009. x4r = x5r + xr;
  1010. x4i = x5i - xi;
  1011. x5r -= xr;
  1012. x5i += xi;
  1013. x7r = C16_5R * tmp[j + 5] + C16_5I * tmp[j + 11];
  1014. x7i = C16_5R * tmp[j + 11] - C16_5I * tmp[j + 5];
  1015. xr = C16_3R * tmp[j + 3] + C16_3I * tmp[j + 13];
  1016. xi = C16_3R * tmp[j + 13] - C16_3I * tmp[j + 3];
  1017. x6r = x7r + xr;
  1018. x6i = x7i - xi;
  1019. x7r -= xr;
  1020. x7i += xi;
  1021. xr = x4r - x6r;
  1022. xi = x4i - x6i;
  1023. x4r += x6r;
  1024. x4i += x6i;
  1025. x6r = W16_8R * (xi + xr);
  1026. x6i = W16_8R * (xi - xr);
  1027. xr = x5r + x7i;
  1028. xi = x5i - x7r;
  1029. x5r -= x7i;
  1030. x5i += x7r;
  1031. x7r = W16_4I * x5r + W16_4R * x5i;
  1032. x7i = W16_4I * x5i - W16_4R * x5r;
  1033. x5r = W16_4R * xr + W16_4I * xi;
  1034. x5i = W16_4R * xi - W16_4I * xr;
  1035. xr = C16_4R * tmp[j + 4] + C16_4I * tmp[j + 12];
  1036. xi = C16_4R * tmp[j + 12] - C16_4I * tmp[j + 4];
  1037. x2r = C16_8R * (tmp[j + 0] + tmp[j + 8]);
  1038. x3r = C16_8R * (tmp[j + 0] - tmp[j + 8]);
  1039. x0r = x2r + xr;
  1040. x1r = x3r + xi;
  1041. x2r -= xr;
  1042. x3r -= xi;
  1043. x0i = C16_2R * tmp[j + 2] + C16_2I * tmp[j + 14];
  1044. x2i = C16_2R * tmp[j + 14] - C16_2I * tmp[j + 2];
  1045. x1i = C16_6R * tmp[j + 6] + C16_6I * tmp[j + 10];
  1046. x3i = C16_6R * tmp[j + 10] - C16_6I * tmp[j + 6];
  1047. xr = x0i - x1i;
  1048. xi = x2i + x3i;
  1049. x0i += x1i;
  1050. x2i -= x3i;
  1051. x1i = W16_8R * (xi + xr);
  1052. x3i = W16_8R * (xi - xr);
  1053. xr = x0r + x0i;
  1054. xi = x0r - x0i;
  1055. tmp[j + 0] = xr + x4r;
  1056. tmp[j + 15] = xr - x4r;
  1057. tmp[j + 8] = xi + x4i;
  1058. tmp[j + 7] = xi - x4i;
  1059. xr = x1r + x1i;
  1060. xi = x1r - x1i;
  1061. tmp[j + 2] = xr + x5r;
  1062. tmp[j + 13] = xr - x5r;
  1063. tmp[j + 10] = xi + x5i;
  1064. tmp[j + 5] = xi - x5i;
  1065. xr = x2r + x2i;
  1066. xi = x2r - x2i;
  1067. tmp[j + 4] = xr + x6r;
  1068. tmp[j + 11] = xr - x6r;
  1069. tmp[j + 12] = xi + x6i;
  1070. tmp[j + 3] = xi - x6i;
  1071. xr = x3r + x3i;
  1072. xi = x3r - x3i;
  1073. tmp[j + 6] = xr + x7r;
  1074. tmp[j + 9] = xr - x7r;
  1075. tmp[j + 14] = xi + x7i;
  1076. tmp[j + 1] = xi - x7i;
  1077. }
  1078. }
  1079. */
  1080. #endregion IDCT
  1081. }
  1082. }