Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

214
LINES

< > BotCompany Repo | #1035226 // G22AbstractTiler - make G22Tiling / cover image by growing rectangles [seems to work]

JavaX fragment (include) [tags: use-pretranspiled]

Libraryless. Click here for Pure Java version (10264L/59K).

1  
// Abstract base class for tiling an image (G22Tiling)
2  
3  
abstract srecord noeq G22AbstractTiler<Img extends WidthAndHeight>(Img image) is Runnable, Steppable {
4  
  delegate Tile to G22Tiling.
5  
  
6  
  int w, h, runner;
7  
  gettable int size; // =w*h
8  
  
9  
  event tileStarted(GrowingTile tile);
10  
  event tileDone(GrowingTile tile);
11  
  
12  
  // iterator that provides points to be looked at
13  
  // (e.g. a WeightlessShuffledIterator)
14  
  IndexIterator pointIterator;
15  
  
16  
  // Temporary stack of points to be looked at
17  
  // (e.g. neighbors of a tile just discovered).
18  
  // May or may not be used.
19  
  new IntBuffer stack;
20  
21  
  G22Tiling<Img> tiling; // the tiling we are making
22  
  
23  
  int tileCounter;
24  
  GrowingTile growingTile; // tile currently being grown
25  
  
26  
  bool verbose;
27  
  
28  
  // The one method subclasses need to override.
29  
  // The exact meaning of a "color" is not defined,
30  
  // the tiler just treats different int value as different colors.
31  
  abstract int getColor(int pos);
32  
  
33  
  // calculations for positions (pixel index)
34  
  int x(int pos) { ret pos % w; }
35  
  int y(int pos) { ret pos / w; }
36  
  int pos(int x, int y) { ret y*w+x; }
37  
  Pt pt(int pos) { ret Pt(x(pos), y(pos)); }
38  
  bool validPos(int x, int y) { ret x >= 0 && y >= 0 && x < w && y < h; }
39  
  
40  
  int getColor(int x, int y) { ret getColor(pos(x, y)); }
41  
  
42  
  class GrowingTile is Steppable {
43  
    Tile tile;
44  
    int color;
45  
    
46  
    // Still growing in any of the 4 directions?
47  
    bool growingN = true;
48  
    bool growingE = true;
49  
    bool growingS = true;
50  
    bool growingW = true;
51  
    
52  
    *(int pos) {
53  
      int x = x(pos), y = y(pos);
54  
      color = getColor(x, y);
55  
      int iTile = tileCounter++;
56  
      tile = tiling.new Tile(iTile, color, rect(x, y, 1, 1));
57  
      tiling.tiles.add(tile);
58  
    }
59  
    
60  
    // put tile into tileMatrix
61  
    void finish {
62  
      Rect r = tile.position();
63  
      int rx = r.x, ry = r.y, rw = r.w, rh = r.h;
64  
      int[] matrix = tiling.tileMatrix;
65  
      int iTile = tile.index;
66  
      for y to rh:
67  
        for x to rw: {
68  
          int pos = (ry+y)*w+(rx+x);
69  
          if (matrix[pos] != 0)
70  
            fail("Overlapping tiles!");
71  
          matrix[pos] = iTile+1;
72  
        }
73  
      tiling.pixelsCovered += rw*rh;
74  
    }
75  
    
76  
    public bool step() {
77  
      Rect r = nextRect();
78  
      if (r == null) {
79  
        finish();
80  
        false;
81  
      }
82  
      
83  
      tile.position(r);
84  
      true;
85  
    }
86  
    
87  
    // Is this pixel in the image and the tile's color
88  
    // and not in a tile?
89  
    bool isContinuation(int x, int y) {
90  
      ret validPos(x, y) && isContinuation_impl(x, y);
91  
    }
92  
    
93  
    bool isContinuation_impl(int x, int y) {
94  
      ret tiling.tileMatrix[pos(x, y)] == 0 && getColor(x, y) == color;
95  
    }
96  
    
97  
    // Is this rectangle completely in the image and the tile's color
98  
    // and not in a tile?
99  
    bool isContinuation(int x1, int y1, int w, int h) {
100  
      if (!validPos(x1, y1) || !validPos(x1+w-1, y1+h-1)) false;
101  
      for y to h:
102  
        for x to w:
103  
          if (!isContinuation_impl(x1+x, y1+y))
104  
            false;
105  
      true;
106  
    }
107  
    
108  
    Rect nextRect() {
109  
      Rect r = tile.position();
110  
      
111  
      // Check the 4 sides for possible growth
112  
      growingN = growingN && isContinuation(r.x, r.y-1, r.w, 1);
113  
      growingS = growingS && isContinuation(r.x, r.y2(), r.w, 1);
114  
      growingW = growingW && isContinuation(r.x-1, r.y, 1, r.h);
115  
      growingE = growingE && isContinuation(r.x2(), r.y, 1, r.h);
116  
      
117  
      // Check the corners too (including the adjacent sides)
118  
      bool cornerNW = growingN && growingW && isContinuation(r.x-1, r.y-1);
119  
      bool cornerNE = growingN && growingE && isContinuation(r.x2(), r.y-1);
120  
      bool cornerSW = growingS && growingW && isContinuation(r.x-1, r.y2());
121  
      bool cornerSE = growingS && growingE && isContinuation(r.x2(), r.y2());
122  
      
123  
      // Corners are the best case, so try those first
124  
      if (cornerNW) {
125  
        int x2 = r.x2(), y2 = r.y2(); // Default case: Grow to NE only
126  
        
127  
        if (cornerSW && cornerNE && cornerSE) {
128  
          // Best case - grow in all 4 directions
129  
          x2++; y2++;
130  
        } else if (cornerNE)
131  
          // At least grow to the right too
132  
          x2++;
133  
        else if (cornerSW)
134  
          // At least grow to the south too
135  
          y2++;
136  
137  
        ret rectFromPoints(r.x-1, r.y-1, x2, y2);
138  
      } else if (cornerNE) {
139  
        // Can't grow NW but will grow NE. So only south growth to decide
140  
        int y2 = r.y2();
141  
        
142  
        if (cornerSE)
143  
          // Grow south too
144  
          y2++;
145  
          
146  
        ret rectFromPoints(r.x, r.y-1, r.x2()+1, y2);
147  
      } else if (cornerSW) {
148  
        // Can't grow NW or NE but will grow SW. So only east growth to decide
149  
        int x2 = r.x2();
150  
        
151  
        if (cornerSE)
152  
          // Grow east too
153  
          x2++;
154  
          
155  
        ret rectFromPoints(r.x-1, r.y, x2, r.y2()+1);
156  
      } else if (cornerSE) {
157  
        // Only growable corner is SE, so just do it
158  
        ret rectFromPoints(r.x, r.y, r.x2()+1, r.y2()+1);
159  
      } else {
160  
        // No growable corners. Try growing west/east or north/south
161  
        
162  
        if (growingW || growingE)
163  
          ret rectFromPoints(r.x-(growingW ? 1 : 0), r.y,
164  
            r.x2()+(growingE ? 1 : 0), r.y2());
165  
        else if (growingN || growingS)
166  
          ret rectFromPoints(r.x, r.y-(growingN ? 1 : 0),
167  
            r.x2(), r.y2()+(growingS ? 1 : 0));
168  
      }
169  
      
170  
      // No more growth possible
171  
      null;
172  
    }
173  
  }
174  
  
175  
  run { stepAll(this); }
176  
  
177  
  public bool step() {
178  
    init();
179  
    
180  
    // Currently growing a tile? Continue that
181  
    if (growingTile != null) {
182  
      if (growingTile.step()) true;
183  
      tileDone(growingTile);
184  
      growingTile = null; // Done growing this tile
185  
    }
186  
    
187  
    int pos = pointIterator.nextIndex();
188  
    if (pos < 0) false;
189  
    
190  
    // Is point already covered by a tile?
191  
    if (tiling.tileMatrix[pos] != 0) true;
192  
    
193  
    // Create new tile
194  
    growingTile = new GrowingTile(pos);
195  
    tileStarted(growingTile);
196  
    
197  
    true;
198  
  }
199  
  
200  
  void init {
201  
    if (tiling != null) ret;
202  
    w = image.getWidth(); h = image.getHeight();
203  
    size = w*h;
204  
    tiling = new G22Tiling(image);
205  
    tiling.initTileMatrix();
206  
    
207  
    pointIterator = WeightlessShuffledIterator(size);
208  
  }
209  
  
210  
  G22Tiling<Img> get() {
211  
    if (tiling == null) run();
212  
    ret tiling;
213  
  }
214  
}

Author comment

Began life as a copy of #1034520

download  show line numbers  debug dex  old transpilations   

Travelled to 4 computer(s): bhatertpkbcr, ekrmjmnbrukm, mowyntqkapby, mqqgnosmbjvj

No comments. add comment

Snippet ID: #1035226
Snippet name: G22AbstractTiler - make G22Tiling / cover image by growing rectangles [seems to work]
Eternal ID of this version: #1035226/26
Text MD5: 7f2c059c0bbd46d87c65d99a3c386a53
Transpilation MD5: 8b36b920457c2377520de1b133161d27
Author: stefan
Category: javax / imaging
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-06-23 23:57:09
Source code size: 6479 bytes / 214 lines
Pitched / IR pitched: No / No
Views / Downloads: 175 / 384
Version history: 25 change(s)
Referenced in: [show references]