4 import iv
.glbinds
.utils
;
12 // ////////////////////////////////////////////////////////////////////////// //
14 just a 2d bitmap that keeps rgb colors.
15 there is also the code to find the biggest non-empty rectangle on the bitmap.
16 empty pixels are represented with zeroes.
18 the algorithm was taken from this SO topic: https://stackoverflow.com/questions/7245/
27 Pair
[] stack
; // stack
28 int top
; // top of stack
30 void push (int a
, int b
) {
36 void pop (int *a
, int *b
) {
43 int wdt
, hgt
; // dimension of input
48 void updateCache (int currY
) {
49 for (int m
= 0; m
< wdt
; ++m
) {
50 if (!grid
[currY
*wdt
+m
]) cache
[m
] = 0; else ++cache
[m
];
56 delete cache
; cache
= null;
57 delete stack
; stack
= null;
58 delete grid
; grid
= null;
59 wdt
= hgt
= dotCount
= 0;
63 void setSize (int awdt
, int ahgt
) {
64 if (awdt
< 1) awdt
= 0;
65 if (ahgt
< 1) ahgt
= 0;
68 if (grid
.length
< awdt
*ahgt
) grid
.length
= awdt
*ahgt
;
69 grid
[0..awdt
*ahgt
] = 0;
80 void setPixel (int x
, int y
, uint rgb
) nothrow @safe @nogc {
81 if (x
< 0 || y
< 0 || x
>= wdt || y
>= hgt
) return;
88 uint resetPixel (int x
, int y
) nothrow @trusted @nogc {
89 if (x
< 0 || y
< 0 || x
>= wdt || y
>= hgt
) return 0;
90 const uint addr
= y
*wdt
+x
;
91 const uint res
= grid
[addr
];
100 bool isDone () const nothrow @safe @nogc { pragma(inline
, true); return (dotCount
== 0); }
103 bool doOne (int *rx0
, int *ry0
, int *rx1
, int *ry1
) {
104 if (dotCount
== 0) return false;
106 if (cache
.length
< wdt
+1) cache
.length
= wdt
+1;
107 if (stack
.length
< wdt
+1) stack
.length
= wdt
+1;
113 best_ll
.one
= best_ll
.two
= 0;
114 best_ur
.one
= best_ur
.two
= -1;
119 for (int m
= 0; m
<= wdt
; ++m
) cache
[m
] = stack
[m
].one
= stack
[m
].two
= 0;
122 for (int n
= 0; n
< hgt
; ++n
) {
125 for (int m
= 0; m
<= wdt
; ++m
) {
126 if (cache
[m
] > openWidth
) {
127 // open new rectangle
129 openWidth
= cache
[m
];
130 } else if (cache
[m
] < openWidth
) {
131 // close rectangle(s)
135 area
= openWidth
*(m
-m0
);
136 if (area
> best_area
) {
138 best_ll
.one
= m0
; best_ll
.two
= n
;
139 best_ur
.one
= m
-1; best_ur
.two
= n
-openWidth
+1;
142 } while (cache
[m
] < openWidth
);
143 openWidth
= cache
[m
];
144 if (openWidth
!= 0) push(m0
, w0
);
149 *rx0
= (best_ll
.one
< best_ur
.one ? best_ll
.one
: best_ur
.one
);
150 *ry0
= (best_ll
.two
< best_ur
.two ? best_ll
.two
: best_ur
.two
);
151 *rx1
= (best_ll
.one
> best_ur
.one ? best_ll
.one
: best_ur
.one
);
152 *ry1
= (best_ll
.two
> best_ur
.two ? best_ll
.two
: best_ur
.two
);
156 for (int y = *ry0; y <= *ry1; ++y) {
157 for (int x = *rx0; x <= *rx1; ++x) {