TerrainCompressor.cs 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223
  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 unsafe 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 = stackalloc int[256];
  87. CompressPatch(patchData, header, 10, out wbits, patch);
  88. EncodePatchHeader(output, header, false, ref wbits);
  89. EncodePatch(output, patch, 0, wbits);
  90. }
  91. private static TerrainPatch.Header PrescanPatch(float[] patch)
  92. {
  93. TerrainPatch.Header header = new TerrainPatch.Header();
  94. float zmax = -99999999.0f;
  95. float zmin = 99999999.0f;
  96. for (int i = 0; i < 256; i++)
  97. {
  98. float val = patch[i];
  99. if (val > zmax) zmax = val;
  100. if (val < zmin) zmin = val;
  101. }
  102. header.DCOffset = zmin;
  103. header.Range = (int)((zmax - zmin) + 1.0f);
  104. return header;
  105. }
  106. private unsafe static void CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits, int* iout)
  107. {
  108. float* block = stackalloc float[256];
  109. float oozrange = 1.0f / header.Range;
  110. float range = (1 << prequant);
  111. float premult = oozrange * range;
  112. float sub = 0.5f * header.Range + header.DCOffset;
  113. int wordsize = (prequant - 2) & 0x0f;
  114. header.QuantWBits = wordsize;
  115. header.QuantWBits |= wordsize << 4;
  116. int k = 0;
  117. for (int j = 0; j < 16; j++)
  118. {
  119. for (int i = 0; i < 16; i++)
  120. block[k++] = (patchData[j * 16 + i] - sub) * premult;
  121. }
  122. wbits = (prequant >> 1);
  123. dct16x16(block, iout, ref wbits);
  124. }
  125. /*
  126. // new using terrain data and patchs indexes
  127. public static List<LayerDataPacket> CreateLayerDataPackets(TerrainData terrData, int[] map)
  128. {
  129. List<LayerDataPacket> ret = new List<LayerDataPacket>();
  130. int numberPatchs = map.Length / 2;
  131. byte[] data = new byte[numberPatchs * 256 * 2];
  132. //create packet and global header
  133. LayerDataPacket layer = new LayerDataPacket();
  134. byte landPacketType;
  135. if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
  136. landPacketType = (byte)TerrainPatch.LayerType.LandExtended;
  137. else
  138. landPacketType = (byte)TerrainPatch.LayerType.Land;
  139. layer.LayerID.Type = landPacketType;
  140. BitPack bitpack = new BitPack(data, 0);
  141. bitpack.PackBits(STRIDE, 16);
  142. bitpack.PackBitsFromByte(16);
  143. bitpack.PackBitsFromByte(landPacketType);
  144. int s;
  145. for (int i = 0; i < numberPatchs; i++)
  146. {
  147. s = 2 * i;
  148. CreatePatchFromTerrainData(bitpack, terrData, map[s], map[s + 1]);
  149. if (bitpack.BytePos > 950 && i != numberPatchs - 1)
  150. {
  151. //finish this packet
  152. bitpack.PackBitsFromByte(END_OF_PATCHES);
  153. layer.LayerData.Data = new byte[bitpack.BytePos + 1];
  154. Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
  155. ret.Add(layer);
  156. // start another
  157. layer = new LayerDataPacket();
  158. layer.LayerID.Type = landPacketType;
  159. bitpack = new BitPack(data, 0);
  160. bitpack.PackBits(STRIDE, 16);
  161. bitpack.PackBitsFromByte(16);
  162. bitpack.PackBitsFromByte(landPacketType);
  163. }
  164. }
  165. bitpack.PackBitsFromByte(END_OF_PATCHES);
  166. layer.LayerData.Data = new byte[bitpack.BytePos + 1];
  167. Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
  168. ret.Add(layer);
  169. return ret;
  170. }
  171. */
  172. public unsafe static void CreatePatchFromTerrainData(BitPack output, TerrainData terrData, int patchX, int patchY)
  173. {
  174. float frange;
  175. TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY, out frange);
  176. header.QuantWBits = 130;
  177. bool largeRegion = false;
  178. // If larger than legacy region size, pack patch X and Y info differently.
  179. if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
  180. {
  181. header.PatchIDs = (patchY & 0xFFFF);
  182. header.PatchIDs += (patchX << 16);
  183. largeRegion = true;
  184. }
  185. else
  186. {
  187. header.PatchIDs = (patchY & 0x1F);
  188. header.PatchIDs += (patchX << 5);
  189. }
  190. if (Math.Round(frange, 2) == 1.0)
  191. {
  192. // flat terrain speed up things
  193. output.PackBitsFromByte(0); //QuantWBits
  194. output.PackFloat(header.DCOffset - 0.5f);
  195. output.PackBitsFromByte(1); //range low
  196. output.PackBitsFromByte(0); //range high
  197. if (largeRegion)
  198. output.PackBits(header.PatchIDs, 32);
  199. else
  200. output.PackBits(header.PatchIDs, 10);
  201. // and thats all
  202. output.PackBits(ZERO_EOB, 2);
  203. return;
  204. }
  205. int wbits;
  206. int* patch = stackalloc int[256];
  207. CompressPatch(terrData, patchX, patchY, header, 10, out wbits, patch);
  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. if (lastZeroindx != 256)
  249. patch[lastZeroindx] = 0;
  250. int i = 0;
  251. while(i < 256)
  252. {
  253. int temp = patch[i];
  254. if (temp == 0)
  255. {
  256. int j = i + 1;
  257. while(j < lastZeroindx)
  258. {
  259. if (patch[j] != 0)
  260. break;
  261. ++j;
  262. }
  263. if (j == lastZeroindx)
  264. {
  265. output.PackBits(ZERO_EOB, 2);
  266. return;
  267. }
  268. i = j - i;
  269. while(i > 8)
  270. {
  271. output.PackBitsFromByte(ZERO_CODE);
  272. i -= 8;
  273. }
  274. if( i > 0)
  275. output.PackBitsFromByte(ZERO_CODE, i);
  276. i = j;
  277. continue;
  278. }
  279. if (temp < 0)
  280. {
  281. temp *= -1;
  282. if (temp > maxwbitssize)
  283. temp = maxwbitssize;
  284. output.PackBits(NEGATIVE_VALUE, 3);
  285. output.PackBits(temp, wbits);
  286. }
  287. else
  288. {
  289. if (temp > maxwbitssize)
  290. temp = maxwbitssize;
  291. output.PackBits(POSITIVE_VALUE, 3);
  292. output.PackBits(temp, wbits);
  293. }
  294. ++i;
  295. }
  296. }
  297. private unsafe static void CompressPatch(TerrainData terrData, int patchX, int patchY, TerrainPatch.Header header,
  298. int prequant, out int wbits, int* iout)
  299. {
  300. float* block = stackalloc float[256];
  301. float oozrange = 1.0f / header.Range;
  302. float invprequat = (1 << prequant);
  303. float premult = oozrange * invprequat;
  304. float sub = 0.5f * header.Range + header.DCOffset;
  305. int wordsize = (prequant - 2) & 0x0f;
  306. header.QuantWBits = wordsize;
  307. header.QuantWBits |= wordsize << 4;
  308. terrData.GetPatchBlock(block, patchX, patchY, sub, premult);
  309. wbits = (prequant >> 1);
  310. dct16x16(block, iout, ref wbits);
  311. }
  312. #region Initialization
  313. private static void BuildDequantizeTable16()
  314. {
  315. for (int j = 0; j < 16; j++)
  316. {
  317. int c = j * 16;
  318. for (int i = 0; i < 16; i++)
  319. {
  320. DequantizeTable16[c + i] = 1.0f + 2.0f * (i + j);
  321. }
  322. }
  323. }
  324. private unsafe static void BuildQuantizeTable16()
  325. {
  326. const float oosob = 2.0f / 16;
  327. fixed(float* fQuantizeTable16 = QuantizeTable16)
  328. {
  329. for (int j = 0; j < 16; j++)
  330. {
  331. int c = j * 16;
  332. for (int i = 0; i < 16; i++)
  333. {
  334. fQuantizeTable16[c + i] = oosob / (1.0f + 2.0f * (i + j));
  335. }
  336. }
  337. }
  338. }
  339. private unsafe static void BuildCopyMatrix16()
  340. {
  341. bool diag = false;
  342. bool right = true;
  343. int i = 0;
  344. int j = 0;
  345. int count = 0;
  346. fixed (int* fCopyMatrix16 = CopyMatrix16)
  347. {
  348. while (i < 16 && j < 16)
  349. {
  350. fCopyMatrix16[j * 16 + i] = count++;
  351. if (!diag)
  352. {
  353. if (right)
  354. {
  355. if (i < 15) i++;
  356. else j++;
  357. right = false;
  358. diag = true;
  359. }
  360. else
  361. {
  362. if (j < 15 ) j++;
  363. else i++;
  364. right = true;
  365. diag = true;
  366. }
  367. }
  368. else
  369. {
  370. if (right)
  371. {
  372. i++;
  373. j--;
  374. if (i == 15 || j == 0) diag = false;
  375. }
  376. else
  377. {
  378. i--;
  379. j++;
  380. if (j == 15 || i == 0) diag = false;
  381. }
  382. }
  383. }
  384. }
  385. }
  386. #endregion Initialization
  387. #region DCT
  388. /* DCT (Discrete Cosine Transform)
  389. adaptation from
  390. General Purpose 2D,3D FFT (Fast Fourier Transform) Package
  391. by Takuya OOURA (email: [email protected])
  392. -------- 16x16 DCT (Discrete Cosine Transform) / Inverse of DCT --------
  393. [definition]
  394. <case1> Normalized 16x16 IDCT
  395. C[k1 + k2] = (1/8) * sum_j1=0^15 sum_j2=0^15
  396. tmp[j1 + j2] * s[j1] * s[j2] *
  397. cos(pi*j1*(k1+1/2)/16) *
  398. cos(pi*j2*(k2+1/2)/16), 0<=k1<16, 0<=k2<16
  399. (s[0] = 1/sqrt(2), s[j] = 1, j > 0)
  400. <case2> Normalized 16x16 DCT
  401. C[k1 + k2] = (1/8) * s[k1] * s[k2] * sum_j1=0^15 sum_j2=0^15
  402. tmp[j1 + j2] *
  403. cos(pi*(j1+1/2)*k1/16) *
  404. cos(pi*(j2+1/2)*k2/16), 0<=k1<16, 0<=k2<16
  405. (s[0] = 1/sqrt(2), s[j] = 1, j > 0)
  406. */
  407. /* Cn_kR = sqrt(2.0/n) * cos(pi/2*k/n) */
  408. /* Cn_kI = sqrt(2.0/n) * sin(pi/2*k/n) */
  409. /* Wn_kR = cos(pi/2*k/n) */
  410. /* Wn_kI = sin(pi/2*k/n) */
  411. const float C16_1R = 0.35185093438159561476f * 2.82842712474619f;
  412. const float C16_1I = 0.03465429229977286565f * 2.82842712474619f;
  413. const float C16_2R = 0.34675996133053686546f * 2.82842712474619f;
  414. const float C16_2I = 0.06897484482073575308f * 2.82842712474619f;
  415. const float C16_3R = 0.33832950029358816957f * 2.82842712474619f;
  416. const float C16_3I = 0.10263113188058934529f * 2.82842712474619f;
  417. const float C16_4R = 0.32664074121909413196f * 2.82842712474619f;
  418. const float C16_4I = 0.13529902503654924610f * 2.82842712474619f;
  419. const float C16_5R = 0.31180625324666780814f * 2.82842712474619f;
  420. const float C16_5I = 0.16666391461943662432f * 2.82842712474619f;
  421. const float C16_6R = 0.29396890060483967924f * 2.82842712474619f;
  422. const float C16_6I = 0.19642373959677554532f * 2.82842712474619f;
  423. const float C16_7R = 0.27330046675043937206f * 2.82842712474619f;
  424. const float C16_7I = 0.22429189658565907106f * 2.82842712474619f;
  425. const float C16_8R = 0.25f * 2.82842712474619f;
  426. const float W16_4R = 0.92387953251128675613f;
  427. const float W16_4I = 0.38268343236508977173f;
  428. const float W16_8R = 0.70710678118654752440f;
  429. unsafe static void dct16x16(float* a, int* iout, ref int wbits)
  430. {
  431. float* tmp = stackalloc float[256];
  432. float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
  433. float x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;
  434. float xr, xi;
  435. float ftmp;
  436. int itmp;
  437. int j, k;
  438. int indx;
  439. const int maxwbits = 17; // per header encoding
  440. int wbitsMaxValue = 1 << wbits;
  441. bool dowbits = wbits < 17;
  442. fixed (float* fQuantizeTable16 = QuantizeTable16)
  443. fixed (int* fCopyMatrix16 = CopyMatrix16)
  444. {
  445. for (j = 0, k = 0; j < 256; j += 16, k++)
  446. {
  447. x4r = a[0 + j] - a[15 + j];
  448. xr = a[0 + j] + a[15 + j];
  449. x4i = a[8 + j] - a[7 + j];
  450. xi = a[8 + j] + a[7 + j];
  451. x0r = xr + xi;
  452. x0i = xr - xi;
  453. x5r = a[2 + j] - a[13 + j];
  454. xr = a[2 + j] + a[13 + j];
  455. x5i = a[10 + j] - a[5 + j];
  456. xi = a[10 + j] + a[5 + j];
  457. x1r = xr + xi;
  458. x1i = xr - xi;
  459. x6r = a[4 + j] - a[11 + j];
  460. xr = a[4 + j] + a[11 + j];
  461. x6i = a[12 + j] - a[3 + j];
  462. xi = a[12 + j] + a[3 + j];
  463. x2r = xr + xi;
  464. x2i = xr - xi;
  465. x7r = a[6 + j] - a[9 + j];
  466. xr = a[6 + j] + a[9 + j];
  467. x7i = a[14 + j] - a[1 + j];
  468. xi = a[14 + j] + a[1 + j];
  469. x3r = xr + xi;
  470. x3i = xr - xi;
  471. xr = x0r + x2r;
  472. xi = x1r + x3r;
  473. tmp[k] = C16_8R * (xr + xi); //
  474. tmp[8 * 16 + k] = C16_8R * (xr - xi); //
  475. xr = x0r - x2r;
  476. xi = x1r - x3r;
  477. tmp[4 * 16 + k] = C16_4R * xr - C16_4I * xi; //
  478. tmp[12 * 16 + k] = C16_4R * xi + C16_4I * xr; //
  479. x0r = W16_8R * (x1i - x3i);
  480. x2r = W16_8R * (x1i + x3i);
  481. xr = x0i + x0r;
  482. xi = x2r + x2i;
  483. tmp[2 * 16 + k] = C16_2R * xr - C16_2I * xi; //
  484. tmp[14 * 16 + k] = C16_2R * xi + C16_2I * xr; //
  485. xr = x0i - x0r;
  486. xi = x2r - x2i;
  487. tmp[6 * 16 + k] = C16_6R * xr - C16_6I * xi; //
  488. tmp[10 * 16 + k] = C16_6R * xi + C16_6I * xr; //
  489. xr = W16_8R * (x6r - x6i);
  490. xi = W16_8R * (x6i + x6r);
  491. x6r = x4r - xr;
  492. x6i = x4i - xi;
  493. x4r += xr;
  494. x4i += xi;
  495. xr = W16_4I * x7r - W16_4R * x7i;
  496. xi = W16_4I * x7i + W16_4R * x7r;
  497. x7r = W16_4R * x5r - W16_4I * x5i;
  498. x7i = W16_4R * x5i + W16_4I * x5r;
  499. x5r = x7r + xr;
  500. x5i = x7i + xi;
  501. x7r -= xr;
  502. x7i -= xi;
  503. xr = x4r + x5r;
  504. xi = x5i + x4i;
  505. tmp[16 + k] = C16_1R * xr - C16_1I * xi; //
  506. tmp[15 * 16 + k] = C16_1R * xi + C16_1I * xr; //
  507. xr = x4r - x5r;
  508. xi = x5i - x4i;
  509. tmp[7 * 16 + k] = C16_7R * xr - C16_7I * xi; //
  510. tmp[9 * 16 + k] = C16_7R * xi + C16_7I * xr; //
  511. xr = x6r - x7i;
  512. xi = x7r + x6i;
  513. tmp[5 * 16 + k] = C16_5R * xr - C16_5I * xi; //
  514. tmp[11 * 16 + k] = C16_5R * xi + C16_5I * xr; //
  515. xr = x6r + x7i;
  516. xi = x7r - x6i;
  517. tmp[3 * 16 + k] = C16_3R * xr - C16_3I * xi; //
  518. tmp[13 * 16 + k] = C16_3R * xi + C16_3I * xr; //
  519. }
  520. for (j = 0, k = 0; j < 256; j += 16, k++)
  521. {
  522. x4r = tmp[0 + j] - tmp[15 + j];
  523. xr = tmp[0 + j] + tmp[15 + j];
  524. x4i = tmp[8 + j] - tmp[7 + j];
  525. xi = tmp[8 + j] + tmp[7 + j];
  526. x0r = xr + xi;
  527. x0i = xr - xi;
  528. x5r = tmp[2 + j] - tmp[13 + j];
  529. xr = tmp[2 + j] + tmp[13 + j];
  530. x5i = tmp[10 + j] - tmp[5 + j];
  531. xi = tmp[10 + j] + tmp[5 + j];
  532. x1r = xr + xi;
  533. x1i = xr - xi;
  534. x6r = tmp[4 + j] - tmp[11 + j];
  535. xr = tmp[4 + j] + tmp[11 + j];
  536. x6i = tmp[12 + j] - tmp[3 + j];
  537. xi = tmp[12 + j] + tmp[3 + j];
  538. x2r = xr + xi;
  539. x2i = xr - xi;
  540. x7r = tmp[6 + j] - tmp[9 + j];
  541. xr = tmp[6 + j] + tmp[9 + j];
  542. x7i = tmp[14 + j] - tmp[1 + j];
  543. xi = tmp[14 + j] + tmp[1 + j];
  544. x3r = xr + xi;
  545. x3i = xr - xi;
  546. xr = x0r + x2r;
  547. xi = x1r + x3r;
  548. //tmp[0 + k] = C16_8R * (xr + xi); //
  549. ftmp = C16_8R * (xr + xi);
  550. itmp = (int)(ftmp * fQuantizeTable16[k]);
  551. iout[fCopyMatrix16[k]] = itmp;
  552. if (dowbits)
  553. {
  554. if (itmp < 0) itmp *= -1;
  555. while (itmp > wbitsMaxValue)
  556. {
  557. wbits++;
  558. wbitsMaxValue = 1 << wbits;
  559. if (wbits == maxwbits)
  560. {
  561. dowbits = false;
  562. break;
  563. }
  564. }
  565. }
  566. //tmp[8 * Constants.TerrainPatchSize + k] = C16_8R * (xr - xi); //
  567. ftmp = C16_8R * (xr - xi);
  568. indx = 8 * 16 + k;
  569. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  570. iout[fCopyMatrix16[indx]] = itmp;
  571. if (dowbits)
  572. {
  573. if (itmp < 0) itmp *= -1;
  574. while (itmp > wbitsMaxValue)
  575. {
  576. wbits++;
  577. wbitsMaxValue = 1 << wbits;
  578. if (wbits == maxwbits)
  579. {
  580. dowbits = false;
  581. break;
  582. }
  583. }
  584. }
  585. xr = x0r - x2r;
  586. xi = x1r - x3r;
  587. //tmp[4 * Constants.TerrainPatchSize + k] = C16_4R * xr - C16_4I * xi; //
  588. ftmp = C16_4R * xr - C16_4I * xi;
  589. indx = 4 * 16 + k;
  590. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  591. iout[fCopyMatrix16[indx]] = itmp;
  592. if (dowbits)
  593. {
  594. if (itmp < 0) itmp *= -1;
  595. while (itmp > wbitsMaxValue)
  596. {
  597. wbits++;
  598. wbitsMaxValue = 1 << wbits;
  599. if (wbits == maxwbits)
  600. {
  601. dowbits = false;
  602. break;
  603. }
  604. }
  605. }
  606. //tmp[12 * Constants.TerrainPatchSize + k] = C16_4R * xi + C16_4I * xr; //
  607. ftmp = C16_4R * xi + C16_4I * xr;
  608. indx = 12 * 16 + k;
  609. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  610. iout[fCopyMatrix16[indx]] = itmp;
  611. if (dowbits)
  612. {
  613. if (itmp < 0) itmp *= -1;
  614. while (itmp > wbitsMaxValue)
  615. {
  616. wbits++;
  617. wbitsMaxValue = 1 << wbits;
  618. if (wbits == maxwbits)
  619. {
  620. dowbits = false;
  621. break;
  622. }
  623. }
  624. }
  625. x0r = W16_8R * (x1i - x3i);
  626. x2r = W16_8R * (x1i + x3i);
  627. xr = x0i + x0r;
  628. xi = x2r + x2i;
  629. //tmp[2 * Constants.TerrainPatchSize + k] = C16_2R * xr - C16_2I * xi; //
  630. ftmp = C16_2R * xr - C16_2I * xi;
  631. indx = 2 * 16 + k;
  632. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  633. iout[fCopyMatrix16[indx]] = itmp;
  634. if (dowbits)
  635. {
  636. if (itmp < 0) itmp *= -1;
  637. while (itmp > wbitsMaxValue)
  638. {
  639. wbits++;
  640. wbitsMaxValue = 1 << wbits;
  641. if (wbits == maxwbits)
  642. {
  643. dowbits = false;
  644. break;
  645. }
  646. }
  647. }
  648. //tmp[14 * Constants.TerrainPatchSize + k] = C16_2R * xi + C16_2I * xr; //
  649. ftmp = C16_2R * xi + C16_2I * xr;
  650. indx = 14 * 16 + k;
  651. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  652. iout[fCopyMatrix16[indx]] = itmp;
  653. if (dowbits)
  654. {
  655. if (itmp < 0) itmp *= -1;
  656. while (itmp > wbitsMaxValue)
  657. {
  658. wbits++;
  659. wbitsMaxValue = 1 << wbits;
  660. if (wbits == maxwbits)
  661. {
  662. dowbits = false;
  663. break;
  664. }
  665. }
  666. }
  667. xr = x0i - x0r;
  668. xi = x2r - x2i;
  669. //tmp[6 * Constants.TerrainPatchSize + k] = C16_6R * xr - C16_6I * xi; //
  670. ftmp = C16_6R * xr - C16_6I * xi;
  671. indx = 6 * 16 + k;
  672. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  673. iout[fCopyMatrix16[indx]] = itmp;
  674. if (dowbits)
  675. {
  676. if (itmp < 0) itmp *= -1;
  677. while (itmp > wbitsMaxValue)
  678. {
  679. wbits++;
  680. wbitsMaxValue = 1 << wbits;
  681. if (wbits == maxwbits)
  682. {
  683. dowbits = false;
  684. break;
  685. }
  686. }
  687. }
  688. //tmp[10 * Constants.TerrainPatchSize + k] = C16_6R * xi + C16_6I * xr; //
  689. ftmp = C16_6R * xi + C16_6I * xr;
  690. indx = 10 * 16 + k;
  691. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  692. iout[fCopyMatrix16[indx]] = itmp;
  693. if (dowbits)
  694. {
  695. if (itmp < 0) itmp *= -1;
  696. while (itmp > wbitsMaxValue)
  697. {
  698. wbits++;
  699. wbitsMaxValue = 1 << wbits;
  700. if (wbits == maxwbits)
  701. {
  702. dowbits = false;
  703. break;
  704. }
  705. }
  706. }
  707. xr = W16_8R * (x6r - x6i);
  708. xi = W16_8R * (x6i + x6r);
  709. x6r = x4r - xr;
  710. x6i = x4i - xi;
  711. x4r += xr;
  712. x4i += xi;
  713. xr = W16_4I * x7r - W16_4R * x7i;
  714. xi = W16_4I * x7i + W16_4R * x7r;
  715. x7r = W16_4R * x5r - W16_4I * x5i;
  716. x7i = W16_4R * x5i + W16_4I * x5r;
  717. x5r = x7r + xr;
  718. x5i = x7i + xi;
  719. x7r -= xr;
  720. x7i -= xi;
  721. xr = x4r + x5r;
  722. xi = x5i + x4i;
  723. //tmp[1 * Constants.TerrainPatchSize + k] = C16_1R * xr - C16_1I * xi; //
  724. ftmp = C16_1R * xr - C16_1I * xi;
  725. indx = 16 + k;
  726. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  727. iout[fCopyMatrix16[indx]] = itmp;
  728. if (dowbits)
  729. {
  730. if (itmp < 0) itmp *= -1;
  731. while (itmp > wbitsMaxValue)
  732. {
  733. wbits++;
  734. wbitsMaxValue = 1 << wbits;
  735. if (wbits == maxwbits)
  736. {
  737. dowbits = false;
  738. break;
  739. }
  740. }
  741. }
  742. //tmp[15 * Constants.TerrainPatchSize + k] = C16_1R * xi + C16_1I * xr; //
  743. ftmp = C16_1R * xi + C16_1I * xr;
  744. indx = 15 * 16 + k;
  745. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  746. iout[fCopyMatrix16[indx]] = itmp;
  747. if (dowbits)
  748. {
  749. if (itmp < 0) itmp *= -1;
  750. while (itmp > wbitsMaxValue)
  751. {
  752. wbits++;
  753. wbitsMaxValue = 1 << wbits;
  754. if (wbits == maxwbits)
  755. {
  756. dowbits = false;
  757. break;
  758. }
  759. }
  760. }
  761. xr = x4r - x5r;
  762. xi = x5i - x4i;
  763. //tmp[7 * Constants.TerrainPatchSize + k] = C16_7R * xr - C16_7I * xi; //
  764. ftmp = C16_7R * xr - C16_7I * xi;
  765. indx = 7 * 16 + k;
  766. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  767. iout[fCopyMatrix16[indx]] = itmp;
  768. if (dowbits)
  769. {
  770. if (itmp < 0) itmp *= -1;
  771. while (itmp > wbitsMaxValue)
  772. {
  773. wbits++;
  774. wbitsMaxValue = 1 << wbits;
  775. if (wbits == maxwbits)
  776. {
  777. dowbits = false;
  778. break;
  779. }
  780. }
  781. }
  782. //tmp[9 * Constants.TerrainPatchSize + k] = C16_7R * xi + C16_7I * xr; //
  783. ftmp = C16_7R * xi + C16_7I * xr;
  784. indx = 9 * 16 + k;
  785. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  786. iout[fCopyMatrix16[indx]] = itmp;
  787. if (dowbits)
  788. {
  789. if (itmp < 0) itmp *= -1;
  790. while (itmp > wbitsMaxValue)
  791. {
  792. wbits++;
  793. wbitsMaxValue = 1 << wbits;
  794. if (wbits == maxwbits)
  795. {
  796. dowbits = false;
  797. break;
  798. }
  799. }
  800. }
  801. xr = x6r - x7i;
  802. xi = x7r + x6i;
  803. //tmp[5 * Constants.TerrainPatchSize + k] = C16_5R * xr - C16_5I * xi; //
  804. ftmp = C16_5R * xr - C16_5I * xi;
  805. indx = 5 * 16 + k;
  806. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  807. iout[fCopyMatrix16[indx]] = itmp;
  808. if (dowbits)
  809. {
  810. if (itmp < 0) itmp *= -1;
  811. while (itmp > wbitsMaxValue)
  812. {
  813. wbits++;
  814. wbitsMaxValue = 1 << wbits;
  815. if (wbits == maxwbits)
  816. {
  817. dowbits = false;
  818. break;
  819. }
  820. }
  821. }
  822. //tmp[11 * Constants.TerrainPatchSize + k] = C16_5R * xi + C16_5I * xr; //
  823. ftmp = C16_5R * xi + C16_5I * xr;
  824. indx = 11 * 16 + k;
  825. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  826. iout[fCopyMatrix16[indx]] = itmp;
  827. if (dowbits)
  828. {
  829. if (itmp < 0) itmp *= -1;
  830. while (itmp > wbitsMaxValue)
  831. {
  832. wbits++;
  833. wbitsMaxValue = 1 << wbits;
  834. if (wbits == maxwbits)
  835. {
  836. dowbits = false;
  837. break;
  838. }
  839. }
  840. }
  841. xr = x6r + x7i;
  842. xi = x7r - x6i;
  843. //tmp[3 * Constants.TerrainPatchSize + k] = C16_3R * xr - C16_3I * xi; //
  844. ftmp = C16_3R * xr - C16_3I * xi;
  845. indx = 3 * 16 + k;
  846. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  847. iout[fCopyMatrix16[indx]] = itmp;
  848. if (dowbits)
  849. {
  850. if (itmp < 0) itmp *= -1;
  851. while (itmp > wbitsMaxValue)
  852. {
  853. wbits++;
  854. wbitsMaxValue = 1 << wbits;
  855. if (wbits == maxwbits)
  856. {
  857. dowbits = false;
  858. break;
  859. }
  860. }
  861. }
  862. //tmp[13 * Constants.TerrainPatchSize + k] = C16_3R * xi + C16_3I * xr; //
  863. ftmp = C16_3R * xi + C16_3I * xr;
  864. indx = 13 * 16 + k;
  865. itmp = (int)(ftmp * fQuantizeTable16[indx]);
  866. iout[fCopyMatrix16[indx]] = itmp;
  867. if (dowbits)
  868. {
  869. if (itmp < 0) itmp *= -1;
  870. while (itmp > wbitsMaxValue)
  871. {
  872. wbits++;
  873. wbitsMaxValue = 1 << wbits;
  874. if (wbits == maxwbits)
  875. {
  876. dowbits = false;
  877. break;
  878. }
  879. }
  880. }
  881. }
  882. }
  883. }
  884. #endregion DCT
  885. #region IDCT
  886. /* not in use
  887. private static void IDCTColumn16(float[] linein, float[] lineout, int column)
  888. {
  889. for (int n = 0; n < Constants.TerrainPatchSize; n++)
  890. {
  891. float total = OO_SQRT2 * linein[column];
  892. for (int u = 1; u < Constants.TerrainPatchSize; u++)
  893. {
  894. int usize = u * Constants.TerrainPatchSize;
  895. total += linein[usize + column] * CosineTable16[usize + n];
  896. }
  897. lineout[Constants.TerrainPatchSize * n + column] = total;
  898. }
  899. }
  900. private static void IDCTLine16(float[] linein, float[] lineout, int line)
  901. {
  902. const float oosob = 2.0f / Constants.TerrainPatchSize;
  903. int lineSize = line * Constants.TerrainPatchSize;
  904. for (int n = 0; n < Constants.TerrainPatchSize; n++)
  905. {
  906. float total = OO_SQRT2 * linein[lineSize];
  907. for (int u = 1; u < Constants.TerrainPatchSize; u++)
  908. {
  909. total += linein[lineSize + u] * CosineTable16[u * Constants.TerrainPatchSize + n];
  910. }
  911. lineout[lineSize + n] = total * oosob;
  912. }
  913. }
  914. //not in use, and still not fixed
  915. /*
  916. static void idct16x16(float[] a)
  917. {
  918. int j;
  919. float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
  920. float x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;
  921. float xr, xi;
  922. int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
  923. for (j = 0; j < fullSize; j += Constants.TerrainPatchSize)
  924. {
  925. x5r = C16_1R * tmp[1 + j] + C16_1I * tmp[15 + j];
  926. x5i = C16_1R * tmp[15 + j] - C16_1I * tmp[1 + j];
  927. xr = C16_7R * tmp[7 + j] + C16_7I * tmp[9 + j];
  928. xi = C16_7R * tmp[9 + j] - C16_7I * tmp[7 + j];
  929. x4r = x5r + xr;
  930. x4i = x5i - xi;
  931. x5r -= xr;
  932. x5i += xi;
  933. x7r = C16_5R * tmp[5 + j] + C16_5I * tmp[11 + j];
  934. x7i = C16_5R * tmp[11 + j] - C16_5I * tmp[5 + j];
  935. xr = C16_3R * tmp[3 + j] + C16_3I * tmp[13 + j];
  936. xi = C16_3R * tmp[13 + j] - C16_3I * tmp[3 + j];
  937. x6r = x7r + xr;
  938. x6i = x7i - xi;
  939. x7r -= xr;
  940. x7i += xi;
  941. xr = x4r - x6r;
  942. xi = x4i - x6i;
  943. x4r += x6r;
  944. x4i += x6i;
  945. x6r = W16_8R * (xi + xr);
  946. x6i = W16_8R * (xi - xr);
  947. xr = x5r + x7i;
  948. xi = x5i - x7r;
  949. x5r -= x7i;
  950. x5i += x7r;
  951. x7r = W16_4I * x5r + W16_4R * x5i;
  952. x7i = W16_4I * x5i - W16_4R * x5r;
  953. x5r = W16_4R * xr + W16_4I * xi;
  954. x5i = W16_4R * xi - W16_4I * xr;
  955. xr = C16_4R * tmp[4 + j] + C16_4I * tmp[12 + j];
  956. xi = C16_4R * tmp[12 + j] - C16_4I * tmp[4 + j];
  957. x2r = C16_8R * (tmp[0 + j] + tmp[8 + j]);
  958. x3r = C16_8R * (tmp[0 + j] - tmp[8 + j]);
  959. x0r = x2r + xr;
  960. x1r = x3r + xi;
  961. x2r -= xr;
  962. x3r -= xi;
  963. x0i = C16_2R * tmp[2 + j] + C16_2I * tmp[14 + j];
  964. x2i = C16_2R * tmp[14 + j] - C16_2I * tmp[2 + j];
  965. x1i = C16_6R * tmp[6 + j] + C16_6I * tmp[10 + j];
  966. x3i = C16_6R * tmp[10 + j] - C16_6I * tmp[6 + j];
  967. xr = x0i - x1i;
  968. xi = x2i + x3i;
  969. x0i += x1i;
  970. x2i -= x3i;
  971. x1i = W16_8R * (xi + xr);
  972. x3i = W16_8R * (xi - xr);
  973. xr = x0r + x0i;
  974. xi = x0r - x0i;
  975. tmp[0 + j] = xr + x4r;
  976. tmp[15 + j] = xr - x4r;
  977. tmp[8 + j] = xi + x4i;
  978. tmp[7 + j] = xi - x4i;
  979. xr = x1r + x1i;
  980. xi = x1r - x1i;
  981. tmp[2 + j] = xr + x5r;
  982. tmp[13 + j] = xr - x5r;
  983. tmp[10 + j] = xi + x5i;
  984. tmp[5 + j] = xi - x5i;
  985. xr = x2r + x2i;
  986. xi = x2r - x2i;
  987. tmp[4 + j] = xr + x6r;
  988. tmp[11 + j] = xr - x6r;
  989. tmp[12 + j] = xi + x6i;
  990. tmp[3 + j] = xi - x6i;
  991. xr = x3r + x3i;
  992. xi = x3r - x3i;
  993. tmp[6 + j] = xr + x7r;
  994. tmp[9 + j] = xr - x7r;
  995. tmp[14 + j] = xi + x7i;
  996. tmp[1 + j] = xi - x7i;
  997. }
  998. for (j = 0; j < fullSize; j += Constants.TerrainPatchSize)
  999. {
  1000. x5r = C16_1R * tmp[j + 1] + C16_1I * tmp[j + 15];
  1001. x5i = C16_1R * tmp[j + 15] - C16_1I * tmp[j + 1];
  1002. xr = C16_7R * tmp[j + 7] + C16_7I * tmp[j + 9];
  1003. xi = C16_7R * tmp[j + 9] - C16_7I * tmp[j + 7];
  1004. x4r = x5r + xr;
  1005. x4i = x5i - xi;
  1006. x5r -= xr;
  1007. x5i += xi;
  1008. x7r = C16_5R * tmp[j + 5] + C16_5I * tmp[j + 11];
  1009. x7i = C16_5R * tmp[j + 11] - C16_5I * tmp[j + 5];
  1010. xr = C16_3R * tmp[j + 3] + C16_3I * tmp[j + 13];
  1011. xi = C16_3R * tmp[j + 13] - C16_3I * tmp[j + 3];
  1012. x6r = x7r + xr;
  1013. x6i = x7i - xi;
  1014. x7r -= xr;
  1015. x7i += xi;
  1016. xr = x4r - x6r;
  1017. xi = x4i - x6i;
  1018. x4r += x6r;
  1019. x4i += x6i;
  1020. x6r = W16_8R * (xi + xr);
  1021. x6i = W16_8R * (xi - xr);
  1022. xr = x5r + x7i;
  1023. xi = x5i - x7r;
  1024. x5r -= x7i;
  1025. x5i += x7r;
  1026. x7r = W16_4I * x5r + W16_4R * x5i;
  1027. x7i = W16_4I * x5i - W16_4R * x5r;
  1028. x5r = W16_4R * xr + W16_4I * xi;
  1029. x5i = W16_4R * xi - W16_4I * xr;
  1030. xr = C16_4R * tmp[j + 4] + C16_4I * tmp[j + 12];
  1031. xi = C16_4R * tmp[j + 12] - C16_4I * tmp[j + 4];
  1032. x2r = C16_8R * (tmp[j + 0] + tmp[j + 8]);
  1033. x3r = C16_8R * (tmp[j + 0] - tmp[j + 8]);
  1034. x0r = x2r + xr;
  1035. x1r = x3r + xi;
  1036. x2r -= xr;
  1037. x3r -= xi;
  1038. x0i = C16_2R * tmp[j + 2] + C16_2I * tmp[j + 14];
  1039. x2i = C16_2R * tmp[j + 14] - C16_2I * tmp[j + 2];
  1040. x1i = C16_6R * tmp[j + 6] + C16_6I * tmp[j + 10];
  1041. x3i = C16_6R * tmp[j + 10] - C16_6I * tmp[j + 6];
  1042. xr = x0i - x1i;
  1043. xi = x2i + x3i;
  1044. x0i += x1i;
  1045. x2i -= x3i;
  1046. x1i = W16_8R * (xi + xr);
  1047. x3i = W16_8R * (xi - xr);
  1048. xr = x0r + x0i;
  1049. xi = x0r - x0i;
  1050. tmp[j + 0] = xr + x4r;
  1051. tmp[j + 15] = xr - x4r;
  1052. tmp[j + 8] = xi + x4i;
  1053. tmp[j + 7] = xi - x4i;
  1054. xr = x1r + x1i;
  1055. xi = x1r - x1i;
  1056. tmp[j + 2] = xr + x5r;
  1057. tmp[j + 13] = xr - x5r;
  1058. tmp[j + 10] = xi + x5i;
  1059. tmp[j + 5] = xi - x5i;
  1060. xr = x2r + x2i;
  1061. xi = x2r - x2i;
  1062. tmp[j + 4] = xr + x6r;
  1063. tmp[j + 11] = xr - x6r;
  1064. tmp[j + 12] = xi + x6i;
  1065. tmp[j + 3] = xi - x6i;
  1066. xr = x3r + x3i;
  1067. xi = x3r - x3i;
  1068. tmp[j + 6] = xr + x7r;
  1069. tmp[j + 9] = xr - x7r;
  1070. tmp[j + 14] = xi + x7i;
  1071. tmp[j + 1] = xi - x7i;
  1072. }
  1073. }
  1074. */
  1075. #endregion IDCT
  1076. }
  1077. }