// constructs a neighborhood from a list of offsets public void construct(MultiDimFloatTexture t, accessor access, bool checkcrossing, int l, int i, int j) { //CLM this used to be static... s_OffsetTable = new OffsetTableInitializer(Globals.NeighborhoodSynth_NUM_NEIGHBORS); m_iI = (short)i; m_iJ = (short)j; m_bCrossing = false; int w = t.getWidth(); int h = t.getHeight(); int n = 0; for (int k = 0; k < T_iNumNeighbors; k++) { int offsi = s_OffsetTable.m_OffsetTable[k][0]; int offsj = s_OffsetTable.m_OffsetTable[k][1]; int ni = 0, nj = 0; access.neigh_ij(i, j, offsi, offsj, ref ni, ref nj); ni = ((ni % w) + w) % w; // FIXME TODO make this faster nj = ((nj % h) + h) % h; for (int c = 0; c < T_iC; c++) { float v = t.get(ni, nj, c); m_Values[n++] = v; } } // border detection // . if the neighborhood crosses the boundary of a non-toroidal texture, // it will not be used as a candidate. Therefore, synthesis will not use it. if (checkcrossing) //l < FIRST_LEVEL_WITH_BORDER) // FIXME TODO: how to choose this automatically ? { int hl = (1 << l); if (i < Globals.NeighborhoodSynth_SIZE / 2 * hl || i >= w - Globals.NeighborhoodSynth_SIZE / 2 * hl) { m_bCrossing = true; } if (j < Globals.NeighborhoodSynth_SIZE / 2 * hl || j >= h - Globals.NeighborhoodSynth_SIZE / 2 * hl) { m_bCrossing = true; } } Globals.Assert(n == e_numdim); }
// ----------------------------------------------------- MultiDimFloatTexture enlargeTexture(MultiDimFloatTexture ex, int type) { ScopeTimer tm = new ScopeTimer("[Exemplar::enlargeTexture]"); int w = ex.getWidth(); int h = ex.getHeight(); MultiDimFloatTexture large = new MultiDimFloatTexture(w * 2, h * 2, ex.numComp()); for (int j = 0; j < h * 2; j++) { for (int i = 0; i < w * 2; i++) { int ri, rj; // where to read ? if (type == 0) { // Toroidal // ri if (i < w / 2) { ri = (i + w / 2) % w; } else if (i < w + w / 2) { ri = i - w / 2; } else { ri = ((i - w / 2) % w); } // rj if (j < h / 2) { rj = (j + h / 2) % h; } else if (j < h + h / 2) { rj = j - h / 2; } else { rj = ((j - h / 2) % h); } } else { // Mirror // ri if (i < w / 2) { ri = (w / 2 - i); } else if (i < w + w / 2) { ri = i - w / 2; } else { ri = (w - 1 - (i - (w / 2 + w))); } // rj if (j < h / 2) { rj = (h / 2 - j); } else if (j < h + h / 2) { rj = j - h / 2; } else { rj = (h - 1 - (j - (h / 2 + h))); } } for (int c = 0; c < ex.numComp(); c++) { large.set(ex.get(ri, rj, c), i, j, c); } } } tm.destroy(); tm = null; return(large); }
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); }
void computeSynthNeighborhoods() { ScopeTimer tm = new ScopeTimer("[computeSynthNeighborhoods]"); m_SynthNeighborhoods = new NeighborhoodSynth[mNumLevels][]; // foreach level for (int level = 0; level < mNumLevels; level++) { MultiDimFloatTexture recolored_level = null; if (Globals.isDefined("4D")) { // . keep only 4 dimension from recolored exemplar MultiDimFloatTexture level_4D = new MultiDimFloatTexture(mOwner.recoloredStack(level).width(), mOwner.recoloredStack(level).height(), mOwner.recoloredStack(level).numComp()); int w = level_4D.getWidth(); int h = level_4D.getHeight(); Globals.Assert(w == mOwner.stack(level).getWidth() && h == mOwner.stack(level).height()); Globals.Assert(level_4D.numComp() == Globals.NUM_RECOLORED_PCA_COMPONENTS); for (int i = 0; i < w; i++) { for (int j = 0; j < h; j++) { // . copy first four channels for (int c = 0; c < 4; c++) { level_4D.set(mOwner.recoloredStack(level).get(i, j, c), i, j, c); } // . zero out all channels above 4 for (int c = 4; c < level_4D.numComp(); c++) { level_4D.set(0, i, j, c); } } } recolored_level = level_4D; } else { // . keep all dimensions recolored_level = mOwner.recoloredStack(level); } m_SynthNeighborhoods[level] = new NeighborhoodSynth[recolored_level.width() * recolored_level.height()]; stack_accessor_v2 access = new stack_accessor_v2(level); for (int j = 0; j < recolored_level.height(); j++) { for (int i = 0; i < recolored_level.width(); i++) { int index = i + j * recolored_level.width(); m_SynthNeighborhoods[level][index] = new NeighborhoodSynth(); m_SynthNeighborhoods[level][index].construct( recolored_level, access, (!mOwner.isToroidal()) && level < (mNumLevels - Globals.NUM_LEVELS_WITHOUT_BORDER), //(!m_bToroidal) && l < FIRST_LEVEL_WITH_BORDER, level, i, j); } } } tm.destroy(); tm = null; }