// 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); }
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; }