Пример заливки с "жесткостью".
Использование:
В форме FillToleranceExample нажмите на единственную кнопку для генерации тестовой сцены.
В единственном текстовом поле укажите параметр "жесткости" от 0 до 1, затем нажимайте мышью на панели в разных участках сцены. Для очистки сцены повторно нажмите на кнопку.
Участок из кода формы jForm FillToleranceExample.java, где:
jPanel1 - панель с абстрактной графикой java.awt.Graphics
jButton1 - кнопка, начинающая отрисовку тестовой сцены
jTextField1 - текстовое поле с параметром заливки
(Автоматически сгенерированный код и код формы опущен)
//вызываем отрисовку тестовой сцены private void jButton1MousePressed(java.awt.event.MouseEvent evt) { drawer.Clear(Color.WHITE, false); DrawCircles(16, 245, 16, new Dot(400, 280), 30, 280); drawer.Update(); } //начинаем заливку в точке нажатия на панель private void jPanel1MousePressed(java.awt.event.MouseEvent evt) { drawer.SetColor(Color.RED); drawer.Fill(evt.getX(), evt.getY(), new Float(jTextField1.getText())); drawer.Update(); } //функция отрисовки тестовой сцены из окружностей void DrawCircles(int count, int fromColor, int toColor, Dot atPosition, int fromRadius, int toRadius) { int curColor = fromColor; int stepColor = (toColor - fromColor) / count; int curRadius = fromRadius; int stepRadius = (toRadius - fromRadius) / count; for(int i = 0; i < count; i++) { Random rand = new Random(); drawer.SetColor(new Color(Rand(curColor, 255), Rand(curColor, 255), Rand(curColor, 255))); drawer.Circle(atPosition.x, atPosition.y, curRadius, false); curColor += stepColor; curRadius += stepRadius; } } //функция случайного числа в диапазоне public static int Rand(int min, int max) { return new Random().nextInt((max - min) + 1) + min; }
Примитивный дроувер Drawer.java, рисующий на сгенерированном буфферизированном изображении BufferedImage по абстрактной графике (в данном примере, она захватывается из jPanel из формы выше)
Наиболее значимыми являются методы Fill для заливки и ColorCompatible для проверки, удовлетворяет ли выбранный цвет параметру заливки.
import java.awt.Graphics; import java.awt.Color; import java.awt.image.BufferedImage; import java.util.Stack; public class Drawer { private final BufferedImage bi; private final Graphics g; private final int w; private final int h; private Dot lineBuffer; private int c; public Drawer(Graphics graphics, int width, int height, Color color) { g = graphics; c = color.getRGB(); w = width - 1; h = height - 1; bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); } public void SetColor(Color color) { c = color.getRGB(); } public void Point(Dot d) { bi.setRGB(d.x, d.y, c); } public void Point(int x, int y) { bi.setRGB(x, y, c); } public void Rect(Dot s, Dot e) { Rect(s.x, s.y, e.x, e.y, false); } public void Rect(Dot s, Dot e, boolean isFilled) { Rect(s.x, s.y, e.x, e.y, isFilled); } public void Rect(int x, int y, int w, int h, boolean isFilled) { if (isFilled) { for (int i = 0; i <= w; i++) { for (int j = 0; j <= h; j++) { Point (x + i, y + j); } } } else { for (int i = 0; i <= w; i++) { Point (x + i, y); Point (x + i, y + h); } for (int j = 0; j <= h; j++) { Point (x, y + j); Point (x + w, y + j); } } } public void SetLine(int x, int y) { lineBuffer = new Dot(x, y); } public void SetLine(Dot d) { lineBuffer = d; } public void MoveLine(int x, int y) { MoveLine(new Dot(x, y)); } public void MoveLine(Dot d) { if (lineBuffer != null) { Line (lineBuffer, d); lineBuffer = d; } } public void Line(Dot s, Dot e) { Line(s.x, s.y, e.x, e.y); } public void Line(int x1, int y1, int x2, int y2) { int x = x1, y = y1; int dx = Math.abs(x2 - x1), dy = Math.abs(y2 - y1); int sx = (x2 - x1) > 0 ? 1 : ((x2 - x1) == 0 ? 0 : -1); int sy = (y2 - y1) > 0 ? 1 : ((y2 - y1) == 0 ? 0 : -1); int e = 2 * dy - dx; Point(x, y); if (dy > dx) { int swap = dx; dx = dy; dy = swap; for (int k = 1; k <= (dx + dy); k++) { if (e < dx) { y += sy; e += 2 * dy; } else { x += sx; e -= 2 * dx; } Point(x, y); } } else { for (int k = 1; k <= (dx + dy); k++) { if (e < dx) { x += sx; e += 2 * dy; } else { y = y + sy; e -= 2 * dx; } Point(x, y); } } } public void LinePolygon(Dot[] points) { LinePolygon(points, false); } public void LinePolygon(Dot[] points, boolean isClosed) { for (int i = 0; i < points.length - 1; i++) { Line (points[i], points[i + 1]); } if (isClosed) { Line (points[points.length - 1], points[0]); } } public void Fill(int x, int y) { Fill(new Dot(x, y), 0); } public void Fill(int x, int y, float power) { Fill(new Dot(x, y), power); } public void Fill(Dot d) { Fill(d, 0); } public void Fill(Dot d, float power) { int targetColor = bi.getRGB(d.x, d.y); if(targetColor == c) { return; } Stack<Dot> dots = new Stack<>(); dots.add(d); while(!dots.isEmpty()) { Dot cur = dots.pop(); int x = cur.x; int y = cur.y; Point(cur); if (x < w && ColorCompatible(bi.getRGB(x + 1, y), targetColor, c, power)) { dots.add(new Dot(x + 1, y)); } if (x > 0 && ColorCompatible(bi.getRGB(x - 1, y), targetColor, c, power)) { dots.add(new Dot(x - 1, y)); } if (y < h && ColorCompatible(bi.getRGB(x, y + 1), targetColor, c, power)) { dots.add(new Dot(x, y + 1)); } if (y > 0 && ColorCompatible(bi.getRGB(x, y - 1), targetColor, c, power)) { dots.add(new Dot(x, y - 1)); } } } boolean ColorCompatible(int pickedColor, int tagetColor, int fillColor, float maxPower) { if(pickedColor == fillColor) { return false; } float[] ac = new Color(pickedColor).getRGBComponents(new float[4]); float[] bc = new Color(tagetColor).getRGBComponents(new float[4]); float maxDiff = 0; for(int i = 0; i < 3; i++) { maxDiff = Math.max(Math.abs(ac[i] - bc[i]), maxDiff); } return maxDiff <= maxPower; } public void Circle(Dot d, int r) { Circle(d.x, d.y, r, false); } public void Circle(Dot d, int r, boolean isFilled) { Circle(d.x, d.y, r, isFilled); } public void Circle(int x, int y, int r, boolean isFilled) { int sx = 0; int sy = r; int d = 3 - 2 * r; while(sx <= sy) { Point (x + sx, y - sy); Point (x + sx, y + sy); Point (x - sx, y - sy); Point (x - sx, y + sy); Point (x + sy, y + sx); Point (x - sy, y + sx); Point (x + sy, y - sx); Point (x - sy, y - sx); if (d < 0) { d += 4 * sx + 6; } else { d += 4 * (sx - sy) + 10; sy--; } sx += 1; } if (isFilled) { Fill(x, y); } } public void Clear() { Clear(Color.WHITE, true); } public void Clear(Color bg) { Clear(bg, true); } public void Clear(Color bg, boolean isUpdate) { SetColor(bg); Rect(0, 0, w, h, true); if (isUpdate) { Update(); } } public void Update() { g.drawImage(bi, 0, 0, null); } }
Утилитный класс точки Dot.java
public class Dot { int x, y; public Dot(int _x, int _y) { x = _x; y = _y; } }
Прикрепленный файл | Размер |
---|---|
Собранный проект для NetBeans 8.2 | 51.11 кб |