EditableImage(int width, int height); // void clear(int color); // void drawGradient(int x1, int y1, int color1, int x2, int y2, int color2); // BufferedImage getImage(); //
0xAARRGGBB AA - ( 32 ) RR - GG - BB -
package ru.idgdima.gradient; import javax.swing.*; public class Gradient { public static final int IMG_WIDTH = 640; public static final int IMG_HEIGHT = 480; private static GradientPanel panel; //, public static void main(String[] args) { // , // JFrame frame = new JFrame("Test"); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); frame.setResizable(false); // , , // , // panel = new GradientPanel(IMG_WIDTH, IMG_HEIGHT); frame.add(panel); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }
package ru.idgdima.gradient; import javax.swing.*; import java.awt.*; import java.awt.image.BufferedImage; public class GradientPanel extends JPanel { private BufferedImage image; public GradientPanel(int width, int height) { // super(); setPreferredSize(new Dimension(width, height)); // , , // BufferedImage // EditableImage gradientImage = new EditableImage(width, height); gradientImage.clear(0xff000000); gradientImage.drawGradient(55, 20, 0xff2e2e2e, 175, 180, 0xffb5b5b5); image = gradientImage.getImage(); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); // . // : g.drawImage(image, 0, 0, null); } }
package ru.idgdima.gradient; import java.awt.image.BufferedImage; public class EditableImage { private int width; private int height; private int[] rgb; // BufferedImage image; // getImage public EditableImage(int width, int height) { this.width = width; this.height = height; rgb = new int[width * height]; // // getImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); } /** * * @param color */ public void clear(int color) { for (int i = 0; i < rgb.length; i++) { rgb[i] = color; } } /** * * @return */ public BufferedImage getImage() { // rgb image image.setRGB(0, 0, width, height, rgb, 0, width); return image; } public void drawGradient(int x1, int y1, int color1, int x2, int y2, int color2) { // } }
public void drawGradient(int x1, int y1, int color1, int x2, int y2, int color2) { float dx = x1 - x2; // float dy = y1 - y2; float AB = (float) Math.sqrt(dx * dx + dy * dy); // // for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { dx = x1 - x; dy = y1 - y; float AE2 = dx * dx + dy * dy; float AE = (float) Math.sqrt(AE2); dx = x2 - x; dy = y2 - y; float EB2 = dx * dx + dy * dy; float EB = (float) Math.sqrt(EB2); float p = (AB + AE + EB) / 2f; float EF = 2 / AB * (float)Math.sqrt(Math.abs(p * (p - AB) * (p - AE) * (p - EB))) float EF2 = EF * EF; float AF = (float) Math.sqrt(Math.abs(AE2 - EF2)); float BF = (float) Math.sqrt(Math.abs(EB2 - EF2)); if (AF + BF - 0.1f > AB) { // rgb[y * width + x] = AF < BF ? color1 : color2; } else { // float progress = AF / AB; // interpolate rgb[y * width + x] = interpolate(color1, color2, progress); } } } } /** * @param num - * @return 0, num < 0; 255, num > 255; num */ private static int clip(int num) { return num <= 0 ? 0 : (num >= 255 ? 255 : num); }
- 0.1f
, it turns out just a terrible mess. Due to the error of calculations, we have to take a small number:
if (AF + BF - 0.1f > AB) {
private int interpolate(int color1, int color2, float progress) { // int a1 = (color1 & 0xff000000) >>> 24; int r1 = (color1 & 0x00ff0000) >>> 16; int g1 = (color1 & 0x0000ff00) >>> 8; int b1 = color1 & 0x000000ff; int a2 = (color2 & 0xff000000) >>> 24; int r2 = (color2 & 0x00ff0000) >>> 16; int g2 = (color2 & 0x0000ff00) >>> 8; int b2 = color2 & 0x000000ff; // float progress2 = (1 - progress); int newA = clip((int) (a1 * progress2 + a2 * progress)); int newR = clip((int) (r1 * progress2 + r2 * progress)); int newG = clip((int) (g1 * progress2 + g2 * progress)); int newB = clip((int) (b1 * progress2 + b2 * progress)); // return (newA << 24) + (newR << 16) + (newG << 8) + newB; }
public static final int INTERPOLATION_LINEAR = 0; public static final int INTERPOLATION_COS = 1;
private int interpolate(int color1, int color2, float progress, int interpolation) { // int a1 = (color1 & 0xff000000) >>> 24; int r1 = (color1 & 0x00ff0000) >>> 16; int g1 = (color1 & 0x0000ff00) >>> 8; int b1 = color1 & 0x000000ff; int a2 = (color2 & 0xff000000) >>> 24; int r2 = (color2 & 0x00ff0000) >>> 16; int g2 = (color2 & 0x0000ff00) >>> 8; int b2 = color2 & 0x000000ff; // float f; if (interpolation == INTERPOLATION_LINEAR) { f = progress; } else if (interpolation == INTERPOLATION_COS) { float ft = progress * 3.1415927f; f = (1 - (float) Math.cos(ft)) * 0.5f; } else { throw new IllegalArgumentException(); } int newA = clip((int) (a1 * (1 - f) + a2 * f)); int newR = clip((int) (r1 * (1 - f) + r2 * f)); int newG = clip((int) (g1 * (1 - f) + g2 * f)); int newB = clip((int) (b1 * (1 - f) + b2 * f)); // return (newA << 24) + (newR << 16) + (newG << 8) + newB; }
int interpolation
to the list of parameters of the drawGradient method and add this variable to the line calling the interpolate method:
rgb[y * width + x] = interpolate(color1, color2, progress , interpolation);
INTERPOLATION_COS_LINEAR = 2
} else if (interpolation == INTERPOLATION_COS_LINEAR) { float ft = progress * 3.1415927f; f = (progress + (1 - (float) Math.cos(ft)) * 0.5f) / 2f; }
Source: https://habr.com/ru/post/180839/