// pixels may contain any float number (e.g. for a distance map) static final class FloatBWImage is IBWImage { int width, height; float[] pixels; // 0 to 1 usually // color returned when getPixel is called with a position outside the actual image float borderColor = 0.0f; // for unstructure() *() {} // BLACK! *(int *width, int *height) { pixels = new float[width*height]; } *(int *width, int *height, float brightness) { pixels = new float[width*height]; fillArrayUnlessZero(pixels, brightness); } *(int *width, int *height, float[] *pixels) {} public float getPixel aka getFloatPixel(int x, int y) { ret inRange(x, y) ? getPixel_noRangeCheck(x, y) : borderColor; } public float getFloatPixel(int index) { ret pixels[index]; } float getPixel(Pt p) { ret getPixel(p.x, p.y); } private boolean inRange(int x, int y) { return x >= 0 && x < width && y >= 0 && y < height; } public int getWidth() { return width; } public int getHeight() { return height; } public void setPixel(int x, int y, float brightness) { pixels[y*width+x] = brightness; } float getPixel_noRangeCheck(int x, int y) { return pixels[y*width+x]; } public byte getByte(int x, int y) { return inRange(x, y) ? getByte_noRangeCheck(x, y) : _toByte(borderColor); } byte getByte_noRangeCheck(int x, int y) { ret _toByte(pixels[y*width+x]); } static byte _toByte(float pixel) { return (byte) (Math.max(0, Math.min(1, pixel))*255f); } // TODO: optimize public BufferedImage getBufferedImage() { BufferedImage img = bufferedImage(width, height); for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) { int b = ((int) getByte(x, y) & 0xFF); img.setRGB(x, y, b*0x010101); } ret img; } public double averageBrightness() { ret floatSumAsDouble(pixels)/(width*height); } }