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: | 1160 / 5829 |
Version history: | 39 change(s) |
Referenced in: | [show references] |