OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
TerrainCompressor.cs
Go to the documentation of this file.
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 
28 /* Freely adapted from the Aurora version of the terrain compressor.
29  * Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/
30  * Aurora version created from libOpenMetaverse Library terrain compressor
31  */
32 
33 using System;
34 using System.Collections.Generic;
35 using System.Reflection;
36 using System.Diagnostics;
37 
38 using log4net;
39 
40 using OpenSim.Framework;
41 using OpenSim.Region.Framework;
42 using OpenSim.Region.Framework.Scenes;
43 
44 using OpenMetaverse;
45 using OpenMetaverse.Packets;
46 
47 namespace OpenSim.Region.ClientStack.LindenUDP
48 {
49  public static class OpenSimTerrainCompressor
50  {
51  // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 
53 #pragma warning disable 414
54  private static string LogHeader = "[TERRAIN COMPRESSOR]";
55 #pragma warning restore 414
56 
57  public const int END_OF_PATCHES = 97;
58 
59  private const float OO_SQRT2 = 0.7071067811865475244008443621049f;
60  private const int STRIDE = 264;
61 
62  private const int ZERO_CODE = 0x0;
63  private const int ZERO_EOB = 0x2;
64  private const int POSITIVE_VALUE = 0x6;
65  private const int NEGATIVE_VALUE = 0x7;
66 
67 
68 // private static readonly float[] CosineTable16 = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
69  private static readonly int[] CopyMatrix16 = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
70 
71  private static readonly float[] QuantizeTable16 =
72  new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
73  private static readonly float[] DequantizeTable16 =
74  new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
75 
76  static OpenSimTerrainCompressor()
77  {
78  // Initialize the decompression tables
79  BuildDequantizeTable16();
80 // SetupCosines16();
81  BuildCopyMatrix16();
82  BuildQuantizeTable16();
83  }
84 
85  // Used to send cloud and wind patches
86  public static LayerDataPacket CreateLayerDataPacketStandardSize(TerrainPatch[] patches, byte type)
87  {
88  LayerDataPacket layer = new LayerDataPacket { LayerID = { Type = type } };
89 
90  TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader
91  { Stride = STRIDE, PatchSize = Constants.TerrainPatchSize };
92 
93  // Should be enough to fit even the most poorly packed data
94  byte[] data = new byte[patches.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2];
95  BitPack bitpack = new BitPack(data, 0);
96  bitpack.PackBits(header.Stride, 16);
97  bitpack.PackBits(header.PatchSize, 8);
98  bitpack.PackBits(type, 8);
99 
100  foreach (TerrainPatch t in patches)
101  CreatePatchtStandardSize(bitpack, t.Data, t.X, t.Y);
102 
103  bitpack.PackBits(END_OF_PATCHES, 8);
104 
105  layer.LayerData.Data = new byte[bitpack.BytePos + 1];
106  Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
107 
108  return layer;
109  }
110 
111  public static void CreatePatchtStandardSize(BitPack output, float[] patchData, int x, int y)
112  {
113  TerrainPatch.Header header = PrescanPatch(patchData);
114  header.QuantWBits = 136;
115 
116  header.PatchIDs = (y & 0x1F);
117  header.PatchIDs += (x << 5);
118 
119  int wbits;
120  int[] patch = CompressPatch(patchData, header, 10, out wbits);
121  EncodePatchHeader(output, header, patch, false, ref wbits);
122  EncodePatch(output, patch, 0, wbits);
123  }
124 
125  private static TerrainPatch.Header PrescanPatch(float[] patch)
126  {
127  TerrainPatch.Header header = new TerrainPatch.Header();
128  float zmax = -99999999.0f;
129  float zmin = 99999999.0f;
130 
131  for (int i = 0; i < Constants.TerrainPatchSize * Constants.TerrainPatchSize; i++)
132  {
133  float val = patch[i];
134  if (val > zmax) zmax = val;
135  if (val < zmin) zmin = val;
136  }
137 
138  header.DCOffset = zmin;
139  header.Range = (int)((zmax - zmin) + 1.0f);
140 
141  return header;
142  }
143 
144  private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits)
145  {
146  float[] block = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
147  float oozrange = 1.0f / header.Range;
148  float range = (1 << prequant);
149  float premult = oozrange * range;
150 
151 
152  float sub = 0.5f * header.Range + header.DCOffset;
153 
154  int wordsize = (prequant - 2) & 0x0f;
155  header.QuantWBits = wordsize;
156  header.QuantWBits |= wordsize << 4;
157 
158  int k = 0;
159  for (int j = 0; j < Constants.TerrainPatchSize; j++)
160  {
161  for (int i = 0; i < Constants.TerrainPatchSize; i++)
162  block[k++] = (patchData[j * Constants.TerrainPatchSize + i] - sub) * premult;
163  }
164 
165  float[] ftemp = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
166  int[] iout = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
167 
168  wbits = (prequant >> 1);
169 
170  dct16x16(block, iout, ref wbits);
171 
172  return iout;
173  }
174 
175  // new using terrain data and patchs indexes
176  public static List<LayerDataPacket> CreateLayerDataPackets(TerrainData terrData, int[] x, int[] y, byte landPacketType)
177  {
178  List<LayerDataPacket> ret = new List<LayerDataPacket>();
179 
180  //create packet and global header
181  LayerDataPacket layer = new LayerDataPacket();
182 
183  layer.LayerID.Type = landPacketType;
184 
185  byte[] data = new byte[x.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2];
186  BitPack bitpack = new BitPack(data, 0);
187  bitpack.PackBits(STRIDE, 16);
188  bitpack.PackBits(Constants.TerrainPatchSize, 8);
189  bitpack.PackBits(landPacketType, 8);
190 
191  for (int i = 0; i < x.Length; i++)
192  {
193  CreatePatchFromTerrainData(bitpack, terrData, x[i], y[i]);
194  if (bitpack.BytePos > 980 && i != x.Length - 1)
195  {
196  //finish this packet
197  bitpack.PackBits(END_OF_PATCHES, 8);
198 
199  layer.LayerData.Data = new byte[bitpack.BytePos + 1];
200  Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
201  ret.Add(layer);
202 
203  // start another
204  layer = new LayerDataPacket();
205  layer.LayerID.Type = landPacketType;
206 
207  bitpack = new BitPack(data, 0);
208  bitpack.PackBits(STRIDE, 16);
209  bitpack.PackBits(Constants.TerrainPatchSize, 8);
210  bitpack.PackBits(landPacketType, 8);
211  }
212  }
213 
214  bitpack.PackBits(END_OF_PATCHES, 8);
215 
216  layer.LayerData.Data = new byte[bitpack.BytePos + 1];
217  Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
218  ret.Add(layer);
219 
220  return ret;
221  }
222 
223  public static void CreatePatchFromTerrainData(BitPack output, TerrainData terrData, int patchX, int patchY)
224  {
225  float frange;
226  TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY, out frange);
227  header.QuantWBits = 130;
228 
229  bool largeRegion = false;
230  // If larger than legacy region size, pack patch X and Y info differently.
231  if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
232  {
233  header.PatchIDs = (patchY & 0xFFFF);
234  header.PatchIDs += (patchX << 16);
235  largeRegion = true;
236  }
237  else
238  {
239  header.PatchIDs = (patchY & 0x1F);
240  header.PatchIDs += (patchX << 5);
241  }
242 
243  if (Math.Round((double)frange, 2) == 1.0)
244  {
245  // flat terrain speed up things
246 
247  header.DCOffset -= 0.5f;
248 
249  header.QuantWBits = 0x00;
250  output.PackBits(header.QuantWBits, 8);
251  output.PackFloat(header.DCOffset);
252  output.PackBits(1, 16);
253  if (largeRegion)
254  output.PackBits(header.PatchIDs, 32);
255  else
256  output.PackBits(header.PatchIDs, 10);
257 
258  // and thats all
259  output.PackBits(ZERO_EOB, 2);
260  return;
261  }
262 
263  int wbits;
264  int[] patch = CompressPatch(terrData, patchX, patchY, header, 10, out wbits);
265  EncodePatchHeader(output, header, patch, largeRegion, ref wbits);
266  EncodePatch(output, patch, 0, wbits);
267  }
268 
269  // Scan the height info we're returning and return a patch packet header for this patch.
270  private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY, out float frange)
271  {
272  TerrainPatch.Header header = new TerrainPatch.Header();
273  float zmax = float.MinValue;
274  float zmin = float.MaxValue;
275 
276  int startx = patchX * Constants.TerrainPatchSize;
277  int starty = patchY * Constants.TerrainPatchSize;
278 
279  for (int j = starty; j < starty + Constants.TerrainPatchSize; j++)
280  {
281  for (int i = startx; i < startx + Constants.TerrainPatchSize; i++)
282  {
283  float val = terrData[i, j];
284  if (val > zmax) zmax = val;
285  if (val < zmin) zmin = val;
286  }
287  }
288 
289  header.DCOffset = zmin;
290  frange = ((zmax - zmin) + 1.0f);
291  header.Range = (int)frange;
292 
293  return header;
294  }
295 
296  private static void EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, bool largeRegion, ref int wbits)
297  {
298  if (wbits > 17)
299  wbits = 17;
300  else if (wbits < 2)
301  wbits = 2;
302 
303  header.QuantWBits &= 0xf0;
304  header.QuantWBits |= (wbits - 2);
305 
306  output.PackBits(header.QuantWBits, 8);
307  output.PackFloat(header.DCOffset);
308  output.PackBits(header.Range, 16);
309  if (largeRegion)
310  output.PackBits(header.PatchIDs, 32);
311  else
312  output.PackBits(header.PatchIDs, 10);
313  }
314 
315  private static void EncodePatch(BitPack output, int[] patch, int postquant, int wbits)
316  {
317  int maxwbitssize = (1 << wbits) - 1;
318  int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
319 
320  if (postquant > fullSize || postquant < 0)
321  {
322  Logger.Log("Postquant is outside the range of allowed values in EncodePatch()", Helpers.LogLevel.Error);
323  return;
324  }
325 
326  if (postquant != 0)
327  patch[fullSize - postquant] = 0;
328 
329  int lastZeroindx = fullSize - postquant;
330 
331  for (int i = 0; i < fullSize; i++)
332  {
333  int temp = patch[i];
334 
335  if (temp == 0)
336  {
337  bool eob = true;
338 
339  for (int j = i; j < lastZeroindx; j++)
340  {
341  if (patch[j] != 0)
342  {
343  eob = false;
344  break;
345  }
346  }
347 
348  if (eob)
349  {
350  output.PackBits(ZERO_EOB, 2);
351  return;
352  }
353  output.PackBits(ZERO_CODE, 1);
354  }
355  else
356  {
357  if (temp < 0)
358  {
359  temp *= -1;
360 
361  if (temp > maxwbitssize) temp = maxwbitssize;
362 
363  output.PackBits(NEGATIVE_VALUE, 3);
364  output.PackBits(temp, wbits);
365  }
366  else
367  {
368  if (temp > maxwbitssize) temp = maxwbitssize;
369 
370  output.PackBits(POSITIVE_VALUE, 3);
371  output.PackBits(temp, wbits);
372  }
373  }
374  }
375  }
376 
377  private static int[] CompressPatch(TerrainData terrData, int patchX, int patchY, TerrainPatch.Header header,
378  int prequant, out int wbits)
379  {
380  float[] block = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
381  int[] iout = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
382 
383  float oozrange = 1.0f / header.Range;
384  float invprequat = (1 << prequant);
385  float premult = oozrange * invprequat;
386 
387  float sub = 0.5f * header.Range + header.DCOffset;
388 
389  int wordsize = (prequant - 2) & 0x0f;
390  header.QuantWBits = wordsize;
391  header.QuantWBits |= wordsize << 4;
392 
393  int k = 0;
394  int startX = patchX * Constants.TerrainPatchSize;
395  int startY = patchY * Constants.TerrainPatchSize;
396  for (int y = startY; y < startY + Constants.TerrainPatchSize; y++)
397  {
398  for (int x = startX; x < startX + Constants.TerrainPatchSize; x++)
399  {
400  block[k++] = (terrData[x, y] - sub) * premult;
401  }
402  }
403 
404  wbits = (prequant >> 1);
405 
406  dct16x16(block, iout, ref wbits);
407 
408  return iout;
409  }
410 
411  #region Initialization
412 
413  private static void BuildDequantizeTable16()
414  {
415  for (int j = 0; j < Constants.TerrainPatchSize; j++)
416  {
417  for (int i = 0; i < Constants.TerrainPatchSize; i++)
418  {
419  DequantizeTable16[j * Constants.TerrainPatchSize + i] = 1.0f + 2.0f * (i + j);
420  }
421  }
422  }
423 
424  private static void BuildQuantizeTable16()
425  {
426  const float oosob = 2.0f / Constants.TerrainPatchSize;
427  for (int j = 0; j < Constants.TerrainPatchSize; j++)
428  {
429  for (int i = 0; i < Constants.TerrainPatchSize; i++)
430  {
431  QuantizeTable16[j * Constants.TerrainPatchSize + i] = oosob / (1.0f + 2.0f * (i + (float)j));
432  }
433  }
434  }
435 
436  private static void BuildCopyMatrix16()
437  {
438  bool diag = false;
439  bool right = true;
440  int i = 0;
441  int j = 0;
442  int count = 0;
443 
445  {
446  CopyMatrix16[j * Constants.TerrainPatchSize + i] = count++;
447 
448  if (!diag)
449  {
450  if (right)
451  {
452  if (i < Constants.TerrainPatchSize - 1) i++;
453  else j++;
454 
455  right = false;
456  diag = true;
457  }
458  else
459  {
460  if (j < Constants.TerrainPatchSize - 1) j++;
461  else i++;
462 
463  right = true;
464  diag = true;
465  }
466  }
467  else
468  {
469  if (right)
470  {
471  i++;
472  j--;
473  if (i == Constants.TerrainPatchSize - 1 || j == 0) diag = false;
474  }
475  else
476  {
477  i--;
478  j++;
479  if (j == Constants.TerrainPatchSize - 1 || i == 0) diag = false;
480  }
481  }
482  }
483  }
484 
485  #endregion Initialization
486 
487 
488 
489 
490  #region DCT
491 
492  /* DCT (Discrete Cosine Transform)
493  adaptation from
494  General Purpose 2D,3D FFT (Fast Fourier Transform) Package
495  by Takuya OOURA (email: ooura@kurims.kyoto-u.ac.jp)
496 
497  -------- 16x16 DCT (Discrete Cosine Transform) / Inverse of DCT --------
498  [definition]
499  <case1> Normalized 16x16 IDCT
500  C[k1 + k2] = (1/8) * sum_j1=0^15 sum_j2=0^15
501  tmp[j1 + j2] * s[j1] * s[j2] *
502  cos(pi*j1*(k1+1/2)/16) *
503  cos(pi*j2*(k2+1/2)/16), 0<=k1<16, 0<=k2<16
504  (s[0] = 1/sqrt(2), s[j] = 1, j > 0)
505  <case2> Normalized 16x16 DCT
506  C[k1 + k2] = (1/8) * s[k1] * s[k2] * sum_j1=0^15 sum_j2=0^15
507  tmp[j1 + j2] *
508  cos(pi*(j1+1/2)*k1/16) *
509  cos(pi*(j2+1/2)*k2/16), 0<=k1<16, 0<=k2<16
510  (s[0] = 1/sqrt(2), s[j] = 1, j > 0)
511  */
512 
513  /* Cn_kR = sqrt(2.0/n) * cos(pi/2*k/n) */
514  /* Cn_kI = sqrt(2.0/n) * sin(pi/2*k/n) */
515  /* Wn_kR = cos(pi/2*k/n) */
516  /* Wn_kI = sin(pi/2*k/n) */
517 
518  const float C16_1R = 0.35185093438159561476f * 2.82842712474619f;
519  const float C16_1I = 0.03465429229977286565f * 2.82842712474619f;
520  const float C16_2R = 0.34675996133053686546f * 2.82842712474619f;
521  const float C16_2I = 0.06897484482073575308f * 2.82842712474619f;
522  const float C16_3R = 0.33832950029358816957f * 2.82842712474619f;
523  const float C16_3I = 0.10263113188058934529f * 2.82842712474619f;
524  const float C16_4R = 0.32664074121909413196f * 2.82842712474619f;
525  const float C16_4I = 0.13529902503654924610f * 2.82842712474619f;
526  const float C16_5R = 0.31180625324666780814f * 2.82842712474619f;
527  const float C16_5I = 0.16666391461943662432f * 2.82842712474619f;
528  const float C16_6R = 0.29396890060483967924f * 2.82842712474619f;
529  const float C16_6I = 0.19642373959677554532f * 2.82842712474619f;
530  const float C16_7R = 0.27330046675043937206f * 2.82842712474619f;
531  const float C16_7I = 0.22429189658565907106f * 2.82842712474619f;
532  const float C16_8R = 0.25f * 2.82842712474619f;
533  const float W16_4R = 0.92387953251128675613f;
534  const float W16_4I = 0.38268343236508977173f;
535  const float W16_8R = 0.70710678118654752440f;
536 
537  static void dct16x16(float[] a, int[] iout, ref int wbits)
538  {
539  float[] tmp = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
540 
541  float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
542  float x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;
543  float xr, xi;
544  float ftmp;
545 
546  int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
547  int itmp;
548  int j, k;
549  int indx;
550 
551  const int maxwbits = 17; // per header encoding
552  int wbitsMaxValue = 1 << wbits;
553  bool dowbits = wbits < 17;
554 
555  for (j = 0, k = 0; j < fullSize; j += Constants.TerrainPatchSize, k++)
556  {
557  x4r = a[0 + j] - a[15 + j];
558  xr = a[0 + j] + a[15 + j];
559  x4i = a[8 + j] - a[7 + j];
560  xi = a[8 + j] + a[7 + j];
561  x0r = xr + xi;
562  x0i = xr - xi;
563  x5r = a[2 + j] - a[13 + j];
564  xr = a[2 + j] + a[13 + j];
565  x5i = a[10 + j] - a[5 + j];
566  xi = a[10 + j] + a[5 + j];
567  x1r = xr + xi;
568  x1i = xr - xi;
569  x6r = a[4 + j] - a[11 + j];
570  xr = a[4 + j] + a[11 + j];
571  x6i = a[12 + j] - a[3 + j];
572  xi = a[12 + j] + a[3 + j];
573  x2r = xr + xi;
574  x2i = xr - xi;
575  x7r = a[6 + j] - a[9 + j];
576  xr = a[6 + j] + a[9 + j];
577  x7i = a[14 + j] - a[1 + j];
578  xi = a[14 + j] + a[1 + j];
579  x3r = xr + xi;
580  x3i = xr - xi;
581  xr = x0r + x2r;
582  xi = x1r + x3r;
583  tmp[k] = C16_8R * (xr + xi); //
584  tmp[8 * Constants.TerrainPatchSize + k] = C16_8R * (xr - xi); //
585  xr = x0r - x2r;
586  xi = x1r - x3r;
587  tmp[4 * Constants.TerrainPatchSize + k] = C16_4R * xr - C16_4I * xi; //
588  tmp[12 * Constants.TerrainPatchSize + k] = C16_4R * xi + C16_4I * xr; //
589  x0r = W16_8R * (x1i - x3i);
590  x2r = W16_8R * (x1i + x3i);
591  xr = x0i + x0r;
592  xi = x2r + x2i;
593  tmp[2 * Constants.TerrainPatchSize + k] = C16_2R * xr - C16_2I * xi; //
594  tmp[14 * Constants.TerrainPatchSize + k] = C16_2R * xi + C16_2I * xr; //
595  xr = x0i - x0r;
596  xi = x2r - x2i;
597  tmp[6 * Constants.TerrainPatchSize + k] = C16_6R * xr - C16_6I * xi; //
598  tmp[10 * Constants.TerrainPatchSize + k] = C16_6R * xi + C16_6I * xr; //
599  xr = W16_8R * (x6r - x6i);
600  xi = W16_8R * (x6i + x6r);
601  x6r = x4r - xr;
602  x6i = x4i - xi;
603  x4r += xr;
604  x4i += xi;
605  xr = W16_4I * x7r - W16_4R * x7i;
606  xi = W16_4I * x7i + W16_4R * x7r;
607  x7r = W16_4R * x5r - W16_4I * x5i;
608  x7i = W16_4R * x5i + W16_4I * x5r;
609  x5r = x7r + xr;
610  x5i = x7i + xi;
611  x7r -= xr;
612  x7i -= xi;
613  xr = x4r + x5r;
614  xi = x5i + x4i;
615  tmp[Constants.TerrainPatchSize + k] = C16_1R * xr - C16_1I * xi; //
616  tmp[15 * Constants.TerrainPatchSize + k] = C16_1R * xi + C16_1I * xr; //
617  xr = x4r - x5r;
618  xi = x5i - x4i;
619  tmp[7 * Constants.TerrainPatchSize + k] = C16_7R * xr - C16_7I * xi; //
620  tmp[9 * Constants.TerrainPatchSize + k] = C16_7R * xi + C16_7I * xr; //
621  xr = x6r - x7i;
622  xi = x7r + x6i;
623  tmp[5 * Constants.TerrainPatchSize + k] = C16_5R * xr - C16_5I * xi; //
624  tmp[11 * Constants.TerrainPatchSize + k] = C16_5R * xi + C16_5I * xr; //
625  xr = x6r + x7i;
626  xi = x7r - x6i;
627  tmp[3 * Constants.TerrainPatchSize + k] = C16_3R * xr - C16_3I * xi; //
628  tmp[13 * Constants.TerrainPatchSize + k] = C16_3R * xi + C16_3I * xr; //
629  }
630 
631  for (j = 0, k = 0; j < fullSize; j += Constants.TerrainPatchSize, k++)
632  {
633  x4r = tmp[0 + j] - tmp[15 + j];
634  xr = tmp[0 + j] + tmp[15 + j];
635  x4i = tmp[8 + j] - tmp[7 + j];
636  xi = tmp[8 + j] + tmp[7 + j];
637  x0r = xr + xi;
638  x0i = xr - xi;
639  x5r = tmp[2 + j] - tmp[13 + j];
640  xr = tmp[2 + j] + tmp[13 + j];
641  x5i = tmp[10 + j] - tmp[5 + j];
642  xi = tmp[10 + j] + tmp[5 + j];
643  x1r = xr + xi;
644  x1i = xr - xi;
645  x6r = tmp[4 + j] - tmp[11 + j];
646  xr = tmp[4 + j] + tmp[11 + j];
647  x6i = tmp[12 + j] - tmp[3 + j];
648  xi = tmp[12 + j] + tmp[3 + j];
649  x2r = xr + xi;
650  x2i = xr - xi;
651  x7r = tmp[6 + j] - tmp[9 + j];
652  xr = tmp[6 + j] + tmp[9 + j];
653  x7i = tmp[14 + j] - tmp[1 + j];
654  xi = tmp[14 + j] + tmp[1 + j];
655  x3r = xr + xi;
656  x3i = xr - xi;
657  xr = x0r + x2r;
658  xi = x1r + x3r;
659 
660  //tmp[0 + k] = C16_8R * (xr + xi); //
661  ftmp = C16_8R * (xr + xi);
662  itmp = (int)(ftmp * QuantizeTable16[k]);
663  iout[CopyMatrix16[k]] = itmp;
664 
665  if (dowbits)
666  {
667  if (itmp < 0) itmp *= -1;
668  while (itmp > wbitsMaxValue)
669  {
670  wbits++;
671  wbitsMaxValue = 1 << wbits;
672  if (wbits == maxwbits)
673  {
674  dowbits = false;
675  break;
676  }
677  }
678  }
679 
680  //tmp[8 * Constants.TerrainPatchSize + k] = C16_8R * (xr - xi); //
681  ftmp = C16_8R * (xr - xi);
682  indx = 8 * Constants.TerrainPatchSize + k;
683  itmp = (int)(ftmp * QuantizeTable16[indx]);
684  iout[CopyMatrix16[indx]] = itmp;
685 
686  if (dowbits)
687  {
688  if (itmp < 0) itmp *= -1;
689  while (itmp > wbitsMaxValue)
690  {
691  wbits++;
692  wbitsMaxValue = 1 << wbits;
693  if (wbits == maxwbits)
694  {
695  dowbits = false;
696  break;
697  }
698  }
699  }
700 
701  xr = x0r - x2r;
702  xi = x1r - x3r;
703 
704  //tmp[4 * Constants.TerrainPatchSize + k] = C16_4R * xr - C16_4I * xi; //
705  ftmp = C16_4R * xr - C16_4I * xi;
706  indx = 4 * Constants.TerrainPatchSize + k;
707  itmp = (int)(ftmp * QuantizeTable16[indx]);
708  iout[CopyMatrix16[indx]] = itmp;
709 
710  if (dowbits)
711  {
712  if (itmp < 0) itmp *= -1;
713  while (itmp > wbitsMaxValue)
714  {
715  wbits++;
716  wbitsMaxValue = 1 << wbits;
717  if (wbits == maxwbits)
718  {
719  dowbits = false;
720  break;
721  }
722  }
723  }
724 
725  //tmp[12 * Constants.TerrainPatchSize + k] = C16_4R * xi + C16_4I * xr; //
726  ftmp = C16_4R * xi + C16_4I * xr;
727  indx = 12 * Constants.TerrainPatchSize + k;
728  itmp = (int)(ftmp * QuantizeTable16[indx]);
729  iout[CopyMatrix16[indx]] = itmp;
730 
731  if (dowbits)
732  {
733  if (itmp < 0) itmp *= -1;
734  while (itmp > wbitsMaxValue)
735  {
736  wbits++;
737  wbitsMaxValue = 1 << wbits;
738  if (wbits == maxwbits)
739  {
740  dowbits = false;
741  break;
742  }
743  }
744  }
745 
746  x0r = W16_8R * (x1i - x3i);
747  x2r = W16_8R * (x1i + x3i);
748  xr = x0i + x0r;
749  xi = x2r + x2i;
750 
751  //tmp[2 * Constants.TerrainPatchSize + k] = C16_2R * xr - C16_2I * xi; //
752  ftmp = C16_2R * xr - C16_2I * xi;
753  indx = 2 * Constants.TerrainPatchSize + k;
754  itmp = (int)(ftmp * QuantizeTable16[indx]);
755  iout[CopyMatrix16[indx]] = itmp;
756 
757  if (dowbits)
758  {
759  if (itmp < 0) itmp *= -1;
760  while (itmp > wbitsMaxValue)
761  {
762  wbits++;
763  wbitsMaxValue = 1 << wbits;
764  if (wbits == maxwbits)
765  {
766  dowbits = false;
767  break;
768  }
769  }
770  }
771 
772  //tmp[14 * Constants.TerrainPatchSize + k] = C16_2R * xi + C16_2I * xr; //
773  ftmp = C16_2R * xi + C16_2I * xr;
774  indx = 14 * Constants.TerrainPatchSize + k;
775  itmp = (int)(ftmp * QuantizeTable16[indx]);
776  iout[CopyMatrix16[indx]] = itmp;
777 
778  if (dowbits)
779  {
780  if (itmp < 0) itmp *= -1;
781  while (itmp > wbitsMaxValue)
782  {
783  wbits++;
784  wbitsMaxValue = 1 << wbits;
785  if (wbits == maxwbits)
786  {
787  dowbits = false;
788  break;
789  }
790  }
791  }
792 
793  xr = x0i - x0r;
794  xi = x2r - x2i;
795 
796  //tmp[6 * Constants.TerrainPatchSize + k] = C16_6R * xr - C16_6I * xi; //
797  ftmp = C16_6R * xr - C16_6I * xi;
798  indx = 6 * Constants.TerrainPatchSize + k;
799  itmp = (int)(ftmp * QuantizeTable16[indx]);
800  iout[CopyMatrix16[indx]] = itmp;
801 
802  if (dowbits)
803  {
804  if (itmp < 0) itmp *= -1;
805  while (itmp > wbitsMaxValue)
806  {
807  wbits++;
808  wbitsMaxValue = 1 << wbits;
809  if (wbits == maxwbits)
810  {
811  dowbits = false;
812  break;
813  }
814  }
815  }
816 
817  //tmp[10 * Constants.TerrainPatchSize + k] = C16_6R * xi + C16_6I * xr; //
818  ftmp = C16_6R * xi + C16_6I * xr;
819  indx = 10 * Constants.TerrainPatchSize + k;
820  itmp = (int)(ftmp * QuantizeTable16[indx]);
821  iout[CopyMatrix16[indx]] = itmp;
822 
823  if (dowbits)
824  {
825  if (itmp < 0) itmp *= -1;
826  while (itmp > wbitsMaxValue)
827  {
828  wbits++;
829  wbitsMaxValue = 1 << wbits;
830  if (wbits == maxwbits)
831  {
832  dowbits = false;
833  break;
834  }
835  }
836  }
837 
838  xr = W16_8R * (x6r - x6i);
839  xi = W16_8R * (x6i + x6r);
840  x6r = x4r - xr;
841  x6i = x4i - xi;
842  x4r += xr;
843  x4i += xi;
844  xr = W16_4I * x7r - W16_4R * x7i;
845  xi = W16_4I * x7i + W16_4R * x7r;
846  x7r = W16_4R * x5r - W16_4I * x5i;
847  x7i = W16_4R * x5i + W16_4I * x5r;
848  x5r = x7r + xr;
849  x5i = x7i + xi;
850  x7r -= xr;
851  x7i -= xi;
852  xr = x4r + x5r;
853  xi = x5i + x4i;
854 
855  //tmp[1 * Constants.TerrainPatchSize + k] = C16_1R * xr - C16_1I * xi; //
856  ftmp = C16_1R * xr - C16_1I * xi;
857  indx = Constants.TerrainPatchSize + k;
858  itmp = (int)(ftmp * QuantizeTable16[indx]);
859  iout[CopyMatrix16[indx]] = itmp;
860 
861  if (dowbits)
862  {
863  if (itmp < 0) itmp *= -1;
864  while (itmp > wbitsMaxValue)
865  {
866  wbits++;
867  wbitsMaxValue = 1 << wbits;
868  if (wbits == maxwbits)
869  {
870  dowbits = false;
871  break;
872  }
873  }
874  }
875 
876  //tmp[15 * Constants.TerrainPatchSize + k] = C16_1R * xi + C16_1I * xr; //
877  ftmp = C16_1R * xi + C16_1I * xr;
878  indx = 15 * Constants.TerrainPatchSize + k;
879  itmp = (int)(ftmp * QuantizeTable16[indx]);
880  iout[CopyMatrix16[indx]] = itmp;
881 
882  if (dowbits)
883  {
884  if (itmp < 0) itmp *= -1;
885  while (itmp > wbitsMaxValue)
886  {
887  wbits++;
888  wbitsMaxValue = 1 << wbits;
889  if (wbits == maxwbits)
890  {
891  dowbits = false;
892  break;
893  }
894  }
895  }
896 
897  xr = x4r - x5r;
898  xi = x5i - x4i;
899 
900  //tmp[7 * Constants.TerrainPatchSize + k] = C16_7R * xr - C16_7I * xi; //
901  ftmp = C16_7R * xr - C16_7I * xi;
902  indx = 7 * Constants.TerrainPatchSize + k;
903  itmp = (int)(ftmp * QuantizeTable16[indx]);
904  iout[CopyMatrix16[indx]] = itmp;
905 
906  if (dowbits)
907  {
908  if (itmp < 0) itmp *= -1;
909  while (itmp > wbitsMaxValue)
910  {
911  wbits++;
912  wbitsMaxValue = 1 << wbits;
913  if (wbits == maxwbits)
914  {
915  dowbits = false;
916  break;
917  }
918  }
919  }
920 
921  //tmp[9 * Constants.TerrainPatchSize + k] = C16_7R * xi + C16_7I * xr; //
922  ftmp = C16_7R * xi + C16_7I * xr;
923  indx = 9 * Constants.TerrainPatchSize + k;
924  itmp = (int)(ftmp * QuantizeTable16[indx]);
925  iout[CopyMatrix16[indx]] = itmp;
926 
927  if (dowbits)
928  {
929  if (itmp < 0) itmp *= -1;
930  while (itmp > wbitsMaxValue)
931  {
932  wbits++;
933  wbitsMaxValue = 1 << wbits;
934  if (wbits == maxwbits)
935  {
936  dowbits = false;
937  break;
938  }
939  }
940  }
941 
942  xr = x6r - x7i;
943  xi = x7r + x6i;
944 
945  //tmp[5 * Constants.TerrainPatchSize + k] = C16_5R * xr - C16_5I * xi; //
946  ftmp = C16_5R * xr - C16_5I * xi;
947  indx = 5 * Constants.TerrainPatchSize + k;
948  itmp = (int)(ftmp * QuantizeTable16[indx]);
949  iout[CopyMatrix16[indx]] = itmp;
950 
951  if (dowbits)
952  {
953  if (itmp < 0) itmp *= -1;
954  while (itmp > wbitsMaxValue)
955  {
956  wbits++;
957  wbitsMaxValue = 1 << wbits;
958  if (wbits == maxwbits)
959  {
960  dowbits = false;
961  break;
962  }
963  }
964  }
965 
966  //tmp[11 * Constants.TerrainPatchSize + k] = C16_5R * xi + C16_5I * xr; //
967  ftmp = C16_5R * xi + C16_5I * xr;
968  indx = 11 * Constants.TerrainPatchSize + k;
969  itmp = (int)(ftmp * QuantizeTable16[indx]);
970  iout[CopyMatrix16[indx]] = itmp;
971 
972  if (dowbits)
973  {
974  if (itmp < 0) itmp *= -1;
975  while (itmp > wbitsMaxValue)
976  {
977  wbits++;
978  wbitsMaxValue = 1 << wbits;
979  if (wbits == maxwbits)
980  {
981  dowbits = false;
982  break;
983  }
984  }
985  }
986 
987  xr = x6r + x7i;
988  xi = x7r - x6i;
989 
990  //tmp[3 * Constants.TerrainPatchSize + k] = C16_3R * xr - C16_3I * xi; //
991  ftmp = C16_3R * xr - C16_3I * xi;
992  indx = 3 * Constants.TerrainPatchSize + k;
993  itmp = (int)(ftmp * QuantizeTable16[indx]);
994  iout[CopyMatrix16[indx]] = itmp;
995 
996  if (dowbits)
997  {
998  if (itmp < 0) itmp *= -1;
999  while (itmp > wbitsMaxValue)
1000  {
1001  wbits++;
1002  wbitsMaxValue = 1 << wbits;
1003  if (wbits == maxwbits)
1004  {
1005  dowbits = false;
1006  break;
1007  }
1008  }
1009  }
1010 
1011  //tmp[13 * Constants.TerrainPatchSize + k] = C16_3R * xi + C16_3I * xr; //
1012  ftmp = C16_3R * xi + C16_3I * xr;
1013  indx = 13 * Constants.TerrainPatchSize + k;
1014  itmp = (int)(ftmp * QuantizeTable16[indx]);
1015  iout[CopyMatrix16[indx]] = itmp;
1016 
1017  if (dowbits)
1018  {
1019  if (itmp < 0) itmp *= -1;
1020  while (itmp > wbitsMaxValue)
1021  {
1022  wbits++;
1023  wbitsMaxValue = 1 << wbits;
1024  if (wbits == maxwbits)
1025  {
1026  dowbits = false;
1027  break;
1028  }
1029  }
1030  }
1031  }
1032  }
1033 
1034  #endregion DCT
1035 
1036  #region Decode
1037  /*
1038  public static TerrainPatch.Header DecodePatchHeader(BitPack bitpack)
1039  {
1040  TerrainPatch.Header header = new TerrainPatch.Header { QuantWBits = bitpack.UnpackBits(8) };
1041 
1042  // Quantized word bits
1043  if (header.QuantWBits == END_OF_PATCHES)
1044  return header;
1045 
1046  // DC offset
1047  header.DCOffset = bitpack.UnpackFloat();
1048 
1049  // Range
1050  header.Range = bitpack.UnpackBits(16);
1051 
1052  // Patch IDs (10 bits)
1053  header.PatchIDs = bitpack.UnpackBits(10);
1054 
1055  // Word bits
1056  header.WordBits = (uint)((header.QuantWBits & 0x0f) + 2);
1057 
1058  return header;
1059  }
1060  */
1061 
1062  /*
1063  public static void DecodePatch(int[] patches, BitPack bitpack, TerrainPatch.Header header, int size)
1064  {
1065  for (int n = 0; n < size * size; n++)
1066  {
1067  // ?
1068  int temp = bitpack.UnpackBits(1);
1069  if (temp != 0)
1070  {
1071  // Value or EOB
1072  temp = bitpack.UnpackBits(1);
1073  if (temp != 0)
1074  {
1075  // Value
1076  temp = bitpack.UnpackBits(1);
1077  if (temp != 0)
1078  {
1079  // Negative
1080  temp = bitpack.UnpackBits((int)header.WordBits);
1081  patches[n] = temp * -1;
1082  }
1083  else
1084  {
1085  // Positive
1086  temp = bitpack.UnpackBits((int)header.WordBits);
1087  patches[n] = temp;
1088  }
1089  }
1090  else
1091  {
1092  // Set the rest to zero
1093  // TODO: This might not be necessary
1094  for (int o = n; o < size * size; o++)
1095  {
1096  patches[o] = 0;
1097  }
1098  break;
1099  }
1100  }
1101  else
1102  {
1103  patches[n] = 0;
1104  }
1105  }
1106  }
1107  */
1108  #region IDCT
1109  /* not in use
1110  private static void IDCTColumn16(float[] linein, float[] lineout, int column)
1111  {
1112  for (int n = 0; n < Constants.TerrainPatchSize; n++)
1113  {
1114  float total = OO_SQRT2 * linein[column];
1115 
1116  for (int u = 1; u < Constants.TerrainPatchSize; u++)
1117  {
1118  int usize = u * Constants.TerrainPatchSize;
1119  total += linein[usize + column] * CosineTable16[usize + n];
1120  }
1121 
1122  lineout[Constants.TerrainPatchSize * n + column] = total;
1123  }
1124  }
1125 
1126  private static void IDCTLine16(float[] linein, float[] lineout, int line)
1127  {
1128  const float oosob = 2.0f / Constants.TerrainPatchSize;
1129  int lineSize = line * Constants.TerrainPatchSize;
1130 
1131  for (int n = 0; n < Constants.TerrainPatchSize; n++)
1132  {
1133  float total = OO_SQRT2 * linein[lineSize];
1134 
1135  for (int u = 1; u < Constants.TerrainPatchSize; u++)
1136  {
1137  total += linein[lineSize + u] * CosineTable16[u * Constants.TerrainPatchSize + n];
1138  }
1139 
1140  lineout[lineSize + n] = total * oosob;
1141  }
1142  }
1143 
1144 /*
1145  private static void SetupCosines16()
1146  {
1147  const float hposz = (float)Math.PI * 0.5f / Constants.TerrainPatchSize;
1148 
1149  for (int u = 0; u < Constants.TerrainPatchSize; u++)
1150  {
1151  for (int n = 0; n < Constants.TerrainPatchSize; n++)
1152  {
1153  CosineTable16[u * Constants.TerrainPatchSize + n] = (float)Math.Cos((2.0f * n + 1.0f) * u * hposz);
1154  }
1155  }
1156  }
1157 */
1158  //not in use, and still not fixed
1159  /*
1160  static void idct16x16(float[] a)
1161  {
1162  int j;
1163  float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
1164  float x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;
1165  float xr, xi;
1166 
1167  int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
1168 
1169  for (j = 0; j < fullSize; j += Constants.TerrainPatchSize)
1170  {
1171  x5r = C16_1R * tmp[1 + j] + C16_1I * tmp[15 + j];
1172  x5i = C16_1R * tmp[15 + j] - C16_1I * tmp[1 + j];
1173  xr = C16_7R * tmp[7 + j] + C16_7I * tmp[9 + j];
1174  xi = C16_7R * tmp[9 + j] - C16_7I * tmp[7 + j];
1175  x4r = x5r + xr;
1176  x4i = x5i - xi;
1177  x5r -= xr;
1178  x5i += xi;
1179  x7r = C16_5R * tmp[5 + j] + C16_5I * tmp[11 + j];
1180  x7i = C16_5R * tmp[11 + j] - C16_5I * tmp[5 + j];
1181  xr = C16_3R * tmp[3 + j] + C16_3I * tmp[13 + j];
1182  xi = C16_3R * tmp[13 + j] - C16_3I * tmp[3 + j];
1183  x6r = x7r + xr;
1184  x6i = x7i - xi;
1185  x7r -= xr;
1186  x7i += xi;
1187  xr = x4r - x6r;
1188  xi = x4i - x6i;
1189  x4r += x6r;
1190  x4i += x6i;
1191  x6r = W16_8R * (xi + xr);
1192  x6i = W16_8R * (xi - xr);
1193  xr = x5r + x7i;
1194  xi = x5i - x7r;
1195  x5r -= x7i;
1196  x5i += x7r;
1197  x7r = W16_4I * x5r + W16_4R * x5i;
1198  x7i = W16_4I * x5i - W16_4R * x5r;
1199  x5r = W16_4R * xr + W16_4I * xi;
1200  x5i = W16_4R * xi - W16_4I * xr;
1201  xr = C16_4R * tmp[4 + j] + C16_4I * tmp[12 + j];
1202  xi = C16_4R * tmp[12 + j] - C16_4I * tmp[4 + j];
1203  x2r = C16_8R * (tmp[0 + j] + tmp[8 + j]);
1204  x3r = C16_8R * (tmp[0 + j] - tmp[8 + j]);
1205  x0r = x2r + xr;
1206  x1r = x3r + xi;
1207  x2r -= xr;
1208  x3r -= xi;
1209  x0i = C16_2R * tmp[2 + j] + C16_2I * tmp[14 + j];
1210  x2i = C16_2R * tmp[14 + j] - C16_2I * tmp[2 + j];
1211  x1i = C16_6R * tmp[6 + j] + C16_6I * tmp[10 + j];
1212  x3i = C16_6R * tmp[10 + j] - C16_6I * tmp[6 + j];
1213  xr = x0i - x1i;
1214  xi = x2i + x3i;
1215  x0i += x1i;
1216  x2i -= x3i;
1217  x1i = W16_8R * (xi + xr);
1218  x3i = W16_8R * (xi - xr);
1219  xr = x0r + x0i;
1220  xi = x0r - x0i;
1221  tmp[0 + j] = xr + x4r;
1222  tmp[15 + j] = xr - x4r;
1223  tmp[8 + j] = xi + x4i;
1224  tmp[7 + j] = xi - x4i;
1225  xr = x1r + x1i;
1226  xi = x1r - x1i;
1227  tmp[2 + j] = xr + x5r;
1228  tmp[13 + j] = xr - x5r;
1229  tmp[10 + j] = xi + x5i;
1230  tmp[5 + j] = xi - x5i;
1231  xr = x2r + x2i;
1232  xi = x2r - x2i;
1233  tmp[4 + j] = xr + x6r;
1234  tmp[11 + j] = xr - x6r;
1235  tmp[12 + j] = xi + x6i;
1236  tmp[3 + j] = xi - x6i;
1237  xr = x3r + x3i;
1238  xi = x3r - x3i;
1239  tmp[6 + j] = xr + x7r;
1240  tmp[9 + j] = xr - x7r;
1241  tmp[14 + j] = xi + x7i;
1242  tmp[1 + j] = xi - x7i;
1243  }
1244  for (j = 0; j < fullSize; j += Constants.TerrainPatchSize)
1245  {
1246  x5r = C16_1R * tmp[j + 1] + C16_1I * tmp[j + 15];
1247  x5i = C16_1R * tmp[j + 15] - C16_1I * tmp[j + 1];
1248  xr = C16_7R * tmp[j + 7] + C16_7I * tmp[j + 9];
1249  xi = C16_7R * tmp[j + 9] - C16_7I * tmp[j + 7];
1250  x4r = x5r + xr;
1251  x4i = x5i - xi;
1252  x5r -= xr;
1253  x5i += xi;
1254  x7r = C16_5R * tmp[j + 5] + C16_5I * tmp[j + 11];
1255  x7i = C16_5R * tmp[j + 11] - C16_5I * tmp[j + 5];
1256  xr = C16_3R * tmp[j + 3] + C16_3I * tmp[j + 13];
1257  xi = C16_3R * tmp[j + 13] - C16_3I * tmp[j + 3];
1258  x6r = x7r + xr;
1259  x6i = x7i - xi;
1260  x7r -= xr;
1261  x7i += xi;
1262  xr = x4r - x6r;
1263  xi = x4i - x6i;
1264  x4r += x6r;
1265  x4i += x6i;
1266  x6r = W16_8R * (xi + xr);
1267  x6i = W16_8R * (xi - xr);
1268  xr = x5r + x7i;
1269  xi = x5i - x7r;
1270  x5r -= x7i;
1271  x5i += x7r;
1272  x7r = W16_4I * x5r + W16_4R * x5i;
1273  x7i = W16_4I * x5i - W16_4R * x5r;
1274  x5r = W16_4R * xr + W16_4I * xi;
1275  x5i = W16_4R * xi - W16_4I * xr;
1276  xr = C16_4R * tmp[j + 4] + C16_4I * tmp[j + 12];
1277  xi = C16_4R * tmp[j + 12] - C16_4I * tmp[j + 4];
1278  x2r = C16_8R * (tmp[j + 0] + tmp[j + 8]);
1279  x3r = C16_8R * (tmp[j + 0] - tmp[j + 8]);
1280  x0r = x2r + xr;
1281  x1r = x3r + xi;
1282  x2r -= xr;
1283  x3r -= xi;
1284  x0i = C16_2R * tmp[j + 2] + C16_2I * tmp[j + 14];
1285  x2i = C16_2R * tmp[j + 14] - C16_2I * tmp[j + 2];
1286  x1i = C16_6R * tmp[j + 6] + C16_6I * tmp[j + 10];
1287  x3i = C16_6R * tmp[j + 10] - C16_6I * tmp[j + 6];
1288  xr = x0i - x1i;
1289  xi = x2i + x3i;
1290  x0i += x1i;
1291  x2i -= x3i;
1292  x1i = W16_8R * (xi + xr);
1293  x3i = W16_8R * (xi - xr);
1294  xr = x0r + x0i;
1295  xi = x0r - x0i;
1296  tmp[j + 0] = xr + x4r;
1297  tmp[j + 15] = xr - x4r;
1298  tmp[j + 8] = xi + x4i;
1299  tmp[j + 7] = xi - x4i;
1300  xr = x1r + x1i;
1301  xi = x1r - x1i;
1302  tmp[j + 2] = xr + x5r;
1303  tmp[j + 13] = xr - x5r;
1304  tmp[j + 10] = xi + x5i;
1305  tmp[j + 5] = xi - x5i;
1306  xr = x2r + x2i;
1307  xi = x2r - x2i;
1308  tmp[j + 4] = xr + x6r;
1309  tmp[j + 11] = xr - x6r;
1310  tmp[j + 12] = xi + x6i;
1311  tmp[j + 3] = xi - x6i;
1312  xr = x3r + x3i;
1313  xi = x3r - x3i;
1314  tmp[j + 6] = xr + x7r;
1315  tmp[j + 9] = xr - x7r;
1316  tmp[j + 14] = xi + x7i;
1317  tmp[j + 1] = xi - x7i;
1318  }
1319  }
1320  */
1321  #endregion IDCT
1322  #endregion Decode
1323  }
1324 
1325 }