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

154
LINES

< > BotCompany Repo | #1035707 // SSI (Simple Scanline Image) backup

JavaX fragment (include)

1  
// SSI - Simple Scanline Image
2  
// A partial image consisting of exactly one horizontal line per row.
3  
// All pixels are of the same color.
4  
5  
// The important values are y1 and data
6  
persistable sclass SSI is HasBounds, G2Drawable, ByteIO {
7  
  replace X with short.
8  
  replace Y with short.
9  
  replace toX with toShort_enforce.
10  
  replace toY with toShort_enforce.
11  
  replace newXArray with newShortArrayOrNull.
12  
  
13  
  // core value (mandatory): first row occupied
14  
  settable Y y1;
15  
  
16  
  // core value (mandatory): x coordinates per row
17  
  // x_left is inclusive, x_right is exclusive
18  
  //
19  
  // Order in array:
20  
  //   x_left at y1, x_right at y1,
21  
  //   x_left at y1+1, x_right at y1+1, ,,,
22  
  settable X[] data;
23  
24  
  // Color in 15 bit
25  
  settable short hi15color;
26  
  
27  
  *(int y1, int y2) {
28  
    init(y1, y2);
29  
  }
30  
  
31  
  void init(int y1, int y2) {
32  
    this.y1 = toY(y1);
33  
    data = newXArray((y2-y1)*2);
34  
  }
35  
  
36  
  void set(int y, int xLeft, int xRight) {
37  
    data[(y-y1)*2] = toX(xLeft);
38  
    data[(y-y1)*2+1] = toX(xRight);
39  
  }
40  
  
41  
  // bounds can be calculated quickly from core values & are then cached
42  
  public simplyCached Rect bounds() {
43  
    int x1 = Int.MAX_VALUE, x2 = 0;
44  
    for (int i = 0; i < l(data); i += 2) {
45  
      x1 = min(x1, data[i]);
46  
      x2 = max(x2, data[i+1]);
47  
    }
48  
    ret rectFromPoints(x1, y1, x2, y2());
49  
  }
50  
  
51  
  // same with number of pixels
52  
  int numberOfPixels_cache = -1;
53  
  public int numberOfPixels() {
54  
    if (numberOfPixels_cache < 0) {
55  
      int n = 0;
56  
      for (int i = 0; i < l(data); i += 2)
57  
        n += max(0, data[i+1]-data[i]);
58  
      numberOfPixels_cache = n;
59  
    }
60  
    ret numberOfPixels_cache;
61  
  }
62  
  
63  
  public int getHeight() { ret l(data)/2; }
64  
  int y2() { ret y1+height(); }
65  
  
66  
  bool contains(Pt p) { ret contains(p.x, p.y); }
67  
  bool contains(int x, int y) {
68  
    if (y < y1) false;
69  
    int i = (y-y1)*2;
70  
    if (i >= l(data)) false;
71  
    ret x >= data[i] && x < data[i+1];
72  
  }
73  
  
74  
  Color color() {
75  
    ret main hi15color(hi15color);
76  
  }
77  
  
78  
  selfType color(RGB color) {
79  
    ret hi15color(rgbToHi15(color));
80  
  }
81  
  
82  
  public void drawOn(Graphics2D g) {
83  
    g.setColor(color());
84  
    int h = height();
85  
    for y to h: {
86  
      int x1 = data[y*2], x2 = data[y*2+1];
87  
      if (x1 < x2)
88  
        g.drawLine(x1, y1+y, x2-1, y1+y);
89  
    }
90  
  }
91  
  
92  
  // doesn't set a color
93  
  // TODO
94  
  public void drawOutline(Graphics2D g) {
95  
    int h = height();
96  
    IntRange last = intRange(0, 0);
97  
    for y to h: {
98  
      IntRange r = intRange(data[y*2], data[y*2+1]);
99  
      
100  
      // anything to draw in this line?
101  
      if (nempty(r)) {
102  
        if (empty(last))
103  
          // draw full line if just starting
104  
          g.drawLine(r.start, y1+y, r.end-1, y1+y);
105  
        else {
106  
          // We make a line from the left boundary that if possible goes only to last.start but is at least 1 pixel wide
107  
          int xleft = max(r.start, last.start-1);
108  
          
109  
          // Same from the right boundary
110  
          int xright = min(r.end-1, last.end);
111  
          
112  
          g.drawLine(r.start, y1+y, xleft, y1+y);
113  
          g.drawLine(xright, y1+y, r.end-1, y1+y);
114  
        }
115  
      }
116  
      
117  
      last = r;
118  
    }
119  
  }
120  
  
121  
  SSI topPart(int nLines) {
122  
    SSI ssi = new SSI(y1, toShort_enforce(y1+nLines)).hi15color(hi15color);
123  
    arrayCopy(data, ssi.data, 0, l(ssi.data));
124  
    ret ssi;
125  
  }
126  
  
127  
  // an SSI is coherent if all scanlines are non-empty
128  
  // and the SSI is one region
129  
  bool coherent(bool withDiagonals default false) {
130  
    int h = height();
131  
    for y to h: {
132  
      int i = y*2;
133  
      int x1 = data[i], x2 = data[i+1];
134  
      if (x1 >= x2) false;
135  
      if (y > 0) {
136  
        int lastx1 = data[i-2], lastx2 = data[i-1];
137  
        if (withDiagonals) { lastx1--; lastx2++; }
138  
        if (!intRangesOverlap(x1, x2, lastx1, lastx2))
139  
          false;
140  
      }
141  
    }
142  
    true;
143  
  }
144  
  
145  
  public void readWrite(ByteHead head) {
146  
    head.exchangeShort(-> hi15color, color -> hi15color = color);
147  
    head.exchangeShort(-> y1, y1 -> this.y1 = y1);
148  
    head.exchangeShort(-> toShort_enforce(y2()), y2 -> init(y1, y2));
149  
    for i over data: {
150  
      reMutable i;
151  
      head.exchangeShort(-> data[i], x -> data[i] = x);
152  
    }
153  
  }
154  
}

Author comment

Began life as a copy of #1035561

download  show line numbers  debug dex  old transpilations   

Travelled to 1 computer(s): mqqgnosmbjvj

No comments. add comment

Snippet ID: #1035707
Snippet name: SSI (Simple Scanline Image) backup
Eternal ID of this version: #1035707/1
Text MD5: c73eb78aa1bfafffbe1dbfdd683dab3f
Author: stefan
Category: javax / imaging
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-07-09 23:59:29
Source code size: 4259 bytes / 154 lines
Pitched / IR pitched: No / No
Views / Downloads: 64 / 67
Referenced in: [show references]