Libraryless. Click here for Pure Java version (10724L/61K).
1 | static final class BWImage extends Meta implements MakesBufferedImage, IBWImage {
|
2 | int width, height; |
3 | byte[] pixels; |
4 | |
5 | // color returned when getPixel is called with a position outside the actual image |
6 | float borderColor = 0.0f; |
7 | |
8 | // for unstructure() |
9 | *() {}
|
10 | |
11 | // BLACK! |
12 | *(int *width, int *height) {
|
13 | pixels = new byte[width*height]; |
14 | } |
15 | |
16 | *(int *width, int *height, float brightness) {
|
17 | pixels = new byte[width*height]; |
18 | fillArrayUnlessZero(pixels, _toByte(brightness)); |
19 | } |
20 | |
21 | *(int *width, int *height, float[] pixels) {
|
22 | this.pixels = new byte[pixels.length]; |
23 | for (int i = 0; i < pixels.length; i++) |
24 | this.pixels[i] = _toByte(pixels[i]); |
25 | } |
26 | |
27 | public BWImage(int width, int height, byte[] pixels) {
|
28 | this.height = height; |
29 | this.width = width; |
30 | this.pixels = pixels; |
31 | } |
32 | |
33 | public BWImage(BWImage image) {
|
34 | width = image.getWidth(); |
35 | height = image.getHeight(); |
36 | byte[] pixels = this.pixels = new byte[width*height]; |
37 | for (int y = 0; y < height; y++) |
38 | for (int x = 0; x < width; x++) |
39 | pixels[y*width+x] = image.getByte(x, y); |
40 | } |
41 | |
42 | // TODO: optimize! |
43 | *(RGBImage image) {
|
44 | width = image.getWidth(); |
45 | height = image.getHeight(); |
46 | byte[] pixels = this.pixels = new byte[height*width]; |
47 | for (int y = 0; y < height; y++) |
48 | for (int x = 0; x < width; x++) {
|
49 | RGB rgb = image.getRGB(x, y); |
50 | pixels[y*width+x] = BWImage._toByte(rgb.getBrightness()); |
51 | } |
52 | } |
53 | |
54 | /*public BWImage(BufferedImage image) {
|
55 | this(new RGBImage(image)); |
56 | }*/ |
57 | |
58 | *(BufferedImage image) ctex {
|
59 | width = image.getWidth(); |
60 | height = image.getHeight(); |
61 | int[] pixels = new int[width*height]; |
62 | byte[] bytePixels = this.pixels = new byte[width*height]; |
63 | PixelGrabber pixelGrabber = new PixelGrabber(image, 0, 0, width, height, pixels, 0, width); |
64 | if (!pixelGrabber.grabPixels()) |
65 | fail("Could not grab pixels");
|
66 | int n = width*height; |
67 | |
68 | for (int i = 0; i < n; i++) {
|
69 | //bytePixels[i] = pixelToByte(pixels[i]); |
70 | int packed = pixels[i]; |
71 | /*float r = ((packed >> 16) & 0xFF)/255f; |
72 | float g = ((packed >> 8) & 0xFF)/255f; |
73 | float b = (packed & 0xFF)/255f; |
74 | bytePixels[i] = (byte) iround((r+g+b)/3.0f*255f);*/ |
75 | int r = ((packed >> 16) & 0xFF); |
76 | int g = ((packed >> 8) & 0xFF); |
77 | int b = (packed & 0xFF); |
78 | bytePixels[i] = (byte) ((r+g+b+1)/3); |
79 | } |
80 | } |
81 | |
82 | // TODO: does it exactly match the other method? (asRGB+getBrightness+_toByte) |
83 | static byte pixelToByte(int packed) {
|
84 | /*int r = (packed >> 16) & 0xFF; |
85 | int g = (packed >> 8) & 0xFF; |
86 | int b = packed & 0xFF; |
87 | ret (byte) ((r+g+b)/3.0f);*/ |
88 | float r = ((packed >> 16) & 0xFF)/255f; |
89 | float g = ((packed >> 8) & 0xFF)/255f; |
90 | float b = (packed & 0xFF)/255f; |
91 | ret (byte) ((r+g+b)/3.0f*255f); |
92 | } |
93 | |
94 | public byte getByte(int x, int y) {
|
95 | return inRange(x, y) ? getByte_noRangeCheck(x, y) : _toByte(borderColor); |
96 | } |
97 | |
98 | // pretty bad function name |
99 | // gets brightness (0 to 255) at pixel |
100 | public int getInt(int x, int y) {
|
101 | ret ubyteToInt(getByte(x, y)); |
102 | } |
103 | |
104 | // idx = index in pixel array |
105 | public int getInt_noRangeCheck(int idx) {
|
106 | ret ubyteToInt(pixels[idx]); |
107 | } |
108 | |
109 | // gets brightness (0 to 255) at pixel with default if out of image |
110 | public int getInt(int x, int y, int defaultValue) {
|
111 | ret inRange(x, y) ? getInt(x, y) : defaultValue; |
112 | } |
113 | |
114 | public double averageBrightness() {
|
115 | double sum = 0; |
116 | int n = width*height; |
117 | for i to n: |
118 | sum += getInt_noRangeCheck(i); |
119 | ret sum/n; |
120 | } |
121 | |
122 | public float minimumBrightness() {
|
123 | float min = 1; |
124 | for (int y = 0; y < height; y++) |
125 | for (int x = 0; x < width; x++) |
126 | min = Math.min(min, getPixel(x, y)); |
127 | return min; |
128 | } |
129 | |
130 | public float maximumBrightness() {
|
131 | float max = 0; |
132 | for (int y = 0; y < height; y++) |
133 | for (int x = 0; x < width; x++) |
134 | max = Math.max(max, getPixel(x, y)); |
135 | return max; |
136 | } |
137 | |
138 | float getPixel(int x, int y) {
|
139 | return inRange(x, y) ? _toFloat(getByte(x,y )) : borderColor; |
140 | } |
141 | |
142 | public float getFloatPixel(int x, int y) { ret getPixel(x, y); }
|
143 | |
144 | float getPixel(Pt p) { ret getPixel(p.x, p.y); }
|
145 | |
146 | static byte _toByte(float pixel) {
|
147 | return (byte) (pixel*255f); |
148 | } |
149 | |
150 | static float _toFloat(byte pixel) {
|
151 | return (((int) pixel) & 255)/255f; |
152 | } |
153 | |
154 | private boolean inRange(int x, int y) {
|
155 | return x >= 0 && x < width && y >= 0 && y < height; |
156 | } |
157 | |
158 | public int getWidth() { return width; }
|
159 | public int getHeight() { return height; }
|
160 | |
161 | public RGBImage toRGB() {
|
162 | int[] rgbs = new int[width*height]; |
163 | for (int y = 0; y < height; y++) |
164 | for (int x = 0; x < width; x++) {
|
165 | int b = getByte(x, y) & 0xFF; |
166 | rgbs[y*width+x] = 0xFF000000 | b*0x010101; |
167 | } |
168 | return new RGBImage(width, height, rgbs); |
169 | } |
170 | |
171 | public RGBImage toRGB_slow() {
|
172 | RGB[] rgbs = new RGB[width*height]; |
173 | for (int y = 0; y < height; y++) |
174 | for (int x = 0; x < width; x++) {
|
175 | float p = getPixel(x, y); |
176 | rgbs[y*width+x] = new RGB(p, p, p); |
177 | } |
178 | return new RGBImage(width, height, rgbs); |
179 | } |
180 | |
181 | |
182 | public BWImage clip(int x, int y, int w, int h) {
|
183 | return clip(new Rectangle(x, y, w, h)); |
184 | } |
185 | |
186 | private Rectangle fixClipRect(Rectangle r) {
|
187 | return r.intersection(new Rectangle(0, 0, width, height)); |
188 | } |
189 | |
190 | BWImage clip(Rect r) {
|
191 | ret clip(r.getRectangle()); |
192 | } |
193 | |
194 | /** this should be multithread-safe */ |
195 | public BWImage clip(Rectangle r) {
|
196 | r = fixClipRect(r); |
197 | byte[] newPixels = new byte[r.height*r.width]; |
198 | for (int y = 0; y < r.height; y++) |
199 | for (int x = 0; x < r.width; x++) |
200 | newPixels[y*r.width+x] = getByte(r.x+x, r.y+y); |
201 | return new BWImage(r.width, r.height, newPixels); |
202 | } |
203 | |
204 | public void setPixel(int x, int y, float brightness) {
|
205 | setByte(x, y, _toByte(fixPixel(brightness))); |
206 | } |
207 | |
208 | // i = 0 to 255 |
209 | public void setInt(int x, int y, int i) {
|
210 | setByte(x, y, (byte) limitToUByte(i)); |
211 | } |
212 | |
213 | public void setInt(Pt p, int i) {
|
214 | setInt(p.x, p.y, i); |
215 | } |
216 | |
217 | public void setByte(int x, int y, byte b) {
|
218 | if (x >= 0 && x < width && y >= 0 && y < height) |
219 | pixels[y*width+x] = b; |
220 | } |
221 | |
222 | byte getByte_noRangeCheck(int x, int y) {
|
223 | return pixels[y*width+x]; |
224 | } |
225 | |
226 | public void setByte(int x, int y, int brightness) {
|
227 | setByte(x, y, (byte) brightness); |
228 | } |
229 | |
230 | private float fixPixel(float pixel) {
|
231 | return Math.max(0, Math.min(1, pixel)); |
232 | } |
233 | |
234 | public float getBorderColor() {
|
235 | return borderColor; |
236 | } |
237 | |
238 | public void setBorderColor(float borderColor) {
|
239 | this.borderColor = borderColor; |
240 | } |
241 | |
242 | public boolean anyPixelBrighterThan(double threshold) {
|
243 | for (int y = 0; y < height; y++) |
244 | for (int x = 0; x < width; x++) |
245 | if (getPixel(x, y) > threshold) |
246 | return true; |
247 | return false; |
248 | } |
249 | |
250 | int[] getRGBPixels() {
|
251 | int n = width*height; |
252 | int[] out = new[n]; |
253 | for i to n: {
|
254 | var b = ubyteToInt(pixels[i]); |
255 | b |= (b << 8) | (b << 16); |
256 | out[i] = b | 0xFF000000; |
257 | } |
258 | ret out; |
259 | } |
260 | |
261 | public BufferedImage getBufferedImage() {
|
262 | ret bufferedImage(getRGBPixels(), width, height); |
263 | } |
264 | |
265 | byte[] getBytes() {
|
266 | ret pixels; |
267 | } |
268 | } |
download show line numbers debug dex old transpilations
Travelled to 20 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, ddnzoavkxhuk, gwrvuhgaqvyk, irmadwmeruwu, ishqpsrjomds, lpdgvwnxivlt, mowyntqkapby, mqqgnosmbjvj, ofpaelxlmzfo, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, sawdedvomwva, tslmcundralx, tvejysmllsmz, vouqrxazstgt, xrpafgyirdlv
No comments. add comment
| Snippet ID: | #1004247 |
| Snippet name: | BWImage (8 bit grayscale) |
| Eternal ID of this version: | #1004247/40 |
| Text MD5: | bec097e59aadd3a79597341d9837dc8e |
| Transpilation MD5: | 64916b5bedf5faa1a3393fbced4fb2a5 |
| Author: | stefan |
| Category: | javax / imaging |
| Type: | JavaX fragment (include) |
| Public (visible to everyone): | Yes |
| Archived (hidden from active list): | No |
| Created/modified: | 2022-07-21 19:02:58 |
| Source code size: | 7431 bytes / 268 lines |
| Pitched / IR pitched: | No / No |
| Views / Downloads: | 1564 / 6304 |
| Version history: | 39 change(s) |
| Referenced in: | [show references] |