public Quantizer(MultiDimFloatTexture tex, int qbits, float percent) { Globals.Assert(percent > 0.0f && percent <= 100.0f); ScopeTimer tm = new ScopeTimer("[Quantizer]"); m_Texture = tex; m_Quantized = new MultiDimIntTexture(tex.width(), tex.height(), tex.numComp()); m_iQBits = qbits; m_Mean = new float[tex.numComp()]; m_StdDev = new float[tex.numComp()]; m_Center = new float[tex.numComp()]; m_Radius = new float[tex.numComp()]; // . compute std dev and mean of every components float [] sum = new float[tex.numComp()]; float [] sumsq = new float[tex.numComp()]; for (int j = 0; j < tex.height(); j++) { for (int i = 0; i < tex.width(); i++) { for (int c = 0; c < tex.numComp(); c++) { float f = tex.get(i, j, c); sum[c] += f; sumsq[c] += f * f; } } } float num = (float)(tex.width() * tex.height()); for (int c = 0; c < tex.numComp(); c++) { m_Mean[c] = sum[c] / num; float sqstddev = (sumsq[c] - sum[c] * sum[c] / num) / (num - 1.0f); if (sqstddev > BMathLib.cFloatCompareEpsilon) { m_StdDev[c] = (float)Math.Sqrt(sqstddev); } else { m_StdDev[c] = 0.0f; } } // . for every component // compute center and radius so that 'percent' samples are within quantization space for (int c = 0; c < tex.numComp(); c++) { float [] samples = new float[tex.width() * tex.height()]; // add samples to array for (int j = 0; j < tex.height(); j++) { for (int i = 0; i < tex.width(); i++) { samples[i + j * tex.width()] = tex.get(i, j, c); } } // sort array Sort.RadixSort rs = new Sort.RadixSort(); rs.Sort(samples);//sort(samples.begin(),samples.end()); // find left and right elements so that 'percent' elements are inside float pout = ((100.0f - percent) / 2) / 100.0f; int left = (int)((samples.Length - 1) * pout); int right = (int)((samples.Length - 1) * (1.0f - pout)); m_Center[c] = (samples[right] + samples[left]) / 2.0f; m_Radius[c] = samples[right] - samples[left]; } // . quantize int num_outside = 0; for (int j = 0; j < tex.height(); j++) { for (int i = 0; i < tex.width(); i++) { if (!quantizePixel(tex.numComp(), tex, tex.getpixIndex(i, j), m_Quantized.getpixIndex(i, j))) { num_outside++; } } } float percent_out = num_outside * 100.0f / (tex.width() * tex.height()); if (Globals.PRINT_DEBUG_MSG) { Debug.Print("-----------.>> Quantizer: num outside = " + percent_out + "%"); } tm.destroy(); tm = null; }
int computeStackLevels_Box(MultiDimFloatTexture tex, ref MultiDimFloatTexture[] _lvls) { List <MultiDimFloatTexture> tmplvls = new List <MultiDimFloatTexture>(); // compute stack of averages on large texture // . add unmodifed finest level tmplvls.Clear(); tmplvls.Add(tex); int l = 0; MultiDimFloatTexture lvl = tex; float [] lvlDat = lvl.getData(); int num = (int)(0.01 + BMathLib.log2((float)lvl.getWidth())); do // TODO: speed this up - extremely unefficient !!! (not critical though) { stack_accessor_v2 access = new stack_accessor_v2(l); // l is destination level for children // (children *are* at level l) MultiDimFloatTexture stackl = new MultiDimFloatTexture(lvl.getWidth(), lvl.getHeight(), lvl.numComp()); List <float> avg = new List <float>(); for (int q = 0; q < lvl.numComp(); q++) { avg.Add(0); } for (int i = 0; i < stackl.getWidth(); i++) { for (int j = 0; j < stackl.getHeight(); j++) { for (int q = 0; q < avg.Count; q++) { avg[q] = 0; } for (int li = 0; li < 2; li++) { for (int lj = 0; lj < 2; lj++) { int ci = 0, cj = 0; access.child_ij(i, j, li, lj, ref ci, ref cj); //CLM large amount of modification here.. check back w/ origional if problems occur if (ci < 0 || ci >= lvl.getWidth() || cj < 0 || cj >= lvl.getHeight()) { continue; } int idx = lvl.getpixmodIndex(ci, cj); for (int c = 0; c < stackl.numComp(); c++) { avg[c] += lvlDat[idx + c]; } } } int opix = stackl.getpixIndex(i, j); for (int c = 0; c < stackl.numComp(); c++) { stackl.getData()[opix + c] = avg[c] / 4.0f; } } } lvl = stackl; tmplvls.Add(lvl); l++; } while ((1 << l) <= lvl.getWidth()); // clamp stack int w = tex.getWidth() / 2; int h = tex.getHeight() / 2; _lvls = new MultiDimFloatTexture[m_iNbLevels]; l = 0; int sz = w; for (int i = 0; i < tmplvls.Count; i++) { MultiDimFloatTexture ktex = tmplvls[i]; MultiDimFloatTexture clamped = ktex.extract(w / 2, h / 2, w, h); _lvls[i] = clamped; l++; sz >>= 1; if (sz < 1) { break; } } for (int i = 0; i < tmplvls.Count; i++) { tmplvls[i] = null; } tmplvls.Clear(); return((int)_lvls.Length); }