Bitmap: Allow pixel-based access (#1855)

This commit is contained in:
Constantin Piber
2026-01-11 22:48:07 +01:00
committed by GitHub
parent b979db9acb
commit c4d8bba5ca
3 changed files with 70 additions and 3 deletions
@@ -315,6 +315,23 @@ public final class Bitmap {
}
}
/**
* Shared code to check for illegal arguments passed to getPixel()
* or setPixel()
*
* @param x x coordinate of the pixel
* @param y y coordinate of the pixel
*/
private void checkPixelAccess(int x, int y) {
checkXYSign(x, y);
if (x >= getWidth()) {
throw new IllegalArgumentException("x must be < bitmap.width()");
}
if (y >= getHeight()) {
throw new IllegalArgumentException("y must be < bitmap.height()");
}
}
public void getPixels(@ColorInt int[] pixels, int offset, int stride,
int x, int y, int width, int height) {
checkPixelsAccess(x, y, width, height, offset, stride, pixels);
@@ -322,6 +339,12 @@ public final class Bitmap {
image.getRGB(x, y, width, height, pixels, offset, stride);
}
@ColorInt
public int getPixel(int x, int y) {
checkPixelAccess(x, y);
return image.getRGB(x, y);
}
public void eraseColor(int c) {
java.awt.Color color = Color.valueOf(c).toJavaColor();
Graphics2D graphics = image.createGraphics();
@@ -13,6 +13,7 @@ import java.awt.Shape;
import java.awt.font.TextAttribute;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.text.AttributedString;
import java.util.ArrayList;
@@ -182,11 +183,21 @@ public final class Canvas {
canvas.fillRect(0, 0, canvasImage.getWidth(), canvasImage.getHeight());
}
public void drawPoint(float x, float y, Paint paint) {
applyPaint(paint);
Shape shape = paintToShape(paint, x, y);
if (paint.getStyle() == Paint.Style.FILL) {
canvas.fill(shape);
} else {
canvas.draw(shape);
}
}
private void applyPaint(Paint paint) {
canvas.setFont(paint.getTypeface().getFont());
java.awt.Color color = Color.valueOf(paint.getColorLong()).toJavaColor();
canvas.setColor(color);
canvas.setStroke(new BasicStroke(paint.getStrokeWidth(), BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
canvas.setStroke(new BasicStroke(paint.getStrokeWidth(), paintToStrokeCap(paint), BasicStroke.JOIN_ROUND));
if (paint.isAntiAlias()) {
canvas.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
} else {
@@ -199,4 +210,34 @@ public final class Canvas {
}
// TODO: use more from paint?
}
private static int paintToStrokeCap(Paint paint) {
switch (paint.getStrokeCap()) {
case BUTT:
return BasicStroke.CAP_BUTT;
case SQUARE:
return BasicStroke.CAP_SQUARE;
case ROUND:
return BasicStroke.CAP_ROUND;
default:
throw new UnsupportedOperationException("Stroke cap " + paint.getStrokeCap() + " not supported");
}
}
private static Shape paintToShape(Paint paint, float x, float y) {
int width = (int)(paint.getStrokeWidth() * 2);
if (width <= 0) width = 1;
int upLeftX = (int) (x - (float) width / 2);
int upLeftY = (int) (y - (float) width / 2);
switch (paint.getStrokeCap()) {
case BUTT:
return new Rectangle((int)x, (int)y, 1, 1);
case SQUARE:
return new Rectangle(upLeftX, upLeftY, width, width);
case ROUND:
return new Ellipse2D.Float(upLeftX, upLeftY, width, width);
default:
throw new UnsupportedOperationException("Stroke cap " + paint.getStrokeCap() + " not supported");
}
}
}
@@ -67,6 +67,7 @@ public class Paint {
private int mFlags;
private Style mStyle = Style.FILL;
private float mStrokeWidth = 1.0f;
private Cap mStrokeCap = Cap.BUTT;
private Typeface mTypeface = Typeface.DEFAULT;
private static final Object sCacheLock = new Object();
@@ -280,6 +281,7 @@ public class Paint {
mStyle = Style.FILL;
mStrokeWidth = 1.0f;
mStrokeCap = Cap.BUTT;
mTypeface = Typeface.DEFAULT;
setFlags(ANTI_ALIAS_FLAG);
}
@@ -316,6 +318,7 @@ public class Paint {
mFlags = paint.mFlags;
mStyle = paint.mStyle;
mStrokeWidth = paint.mStrokeWidth;
mStrokeCap = paint.mStrokeCap;
mTypeface = paint.mTypeface;
}
@@ -526,11 +529,11 @@ public class Paint {
}
public Cap getStrokeCap() {
throw new RuntimeException("Stub!");
return mStrokeCap;
}
public void setStrokeCap(Cap cap) {
throw new RuntimeException("Stub!");
mStrokeCap = cap;
}
public Join getStrokeJoin() {