这就是我在 Android 应用程序中在
Bitmap
上绘制 Canvas
的方式:
canvas.save();
canvas.scale(scale, scale, x, y);
canvas.drawBitmap(bitmap, x, y, null);
canvas.restore();
但是,
Bitmap
缩放不平滑,未执行抗锯齿。如何启用抗锯齿功能?
试试这个:
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawBitmap(bitmap, x, y, paint);
Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG);
或paint.setFilterBitmap(true);
都对我有用,但要非常小心,在我的游戏中,它仅将FPS从30FPS
降低到17FPS
。因此,如果它是像游戏中那样的关键任务绘图,您最好在加载时缩放图像。我通过以下方式做到了:
public Bitmap getImage (int id, int width, int height) {
Bitmap bmp = BitmapFactory.decodeResource( getResources(), id );
Bitmap img = Bitmap.createScaledBitmap( bmp, width, height, true );
bmp.recycle();
return img;
}
您是否尝试过创建一个
Paint
对象,在其上调用 setAntiAlias(true)
并将其作为第四个参数传递给 drawBitmap
方法?如果这不起作用,我想你应该缩小 drawBitmap
调用而不是缩放画布,例如通过使用 drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)
。
API 33 中提供了行和列跳跃功能。共享源代码无法正常工作。平滑重新缩放对于动态游戏图形来说并不是一种实用的算法。该算法对于预定义图形很有用。如果有找到请分享一下。
编辑:马赛克重新缩放算法适用于
Bitmap
对象:
UnpackedColor.java
import java.util.Random;
import android.graphics.Color;
import java.lang.Math;
public class UnpackedColor {
public float A, R, G, B;
public UnpackedColor(
float A,
float R,
float G,
float B
) {
this.A = A;
this.R = R;
this.G = G;
this.B = B;
}
public UnpackedColor(int packedColor) {
A = Color.alpha(packedColor) / 255f;
R = Color.red(packedColor) / 255f;
G = Color.green(packedColor) / 255f;
B = Color.blue(packedColor) / 255f;
}
public void sum(UnpackedColor ref) {
if (ref == null) return;
A += ref.A;
R += ref.R;
G += ref.G;
B += ref.B;
}
public void div(float divider) {
A /= divider;
R /= divider;
G /= divider;
B /= divider;
}
public void pow(float value) {
A *= value;
R *= value;
G *= value;
B *= value;
}
public int pack() {
int Ar = Math.round(255 * A);
int Rr = Math.round(255 * R);
int Gr = Math.round(255 * G);
int Br = Math.round(255 * B);
if (Ar > 255) Ar = 255;
else if (Ar < 0) Ar = 0;
if (Rr > 255) Rr = 255;
else if (Rr < 0) Rr = 0;
if (Gr > 255) Gr = 255;
else if (Gr < 0) Gr = 0;
if (Br > 255) Br = 255;
else if (Br < 0) Br = 0;
return Color.argb(Ar, Rr, Gr, Br);
}
}
重新缩放.java
import android.graphics.Bitmap;
import java.lang.Math;
public class Rescale {
public static Bitmap filterBitmap(Bitmap refBitmap, float ratio) {
int newWidth = Math.round(refBitmap.getWidth() * ratio);
int newHeight = Math.round(refBitmap.getHeight() * ratio);
if (newWidth <= 0) {
newWidth = 1;
}
if (newHeight <= 0) {
newHeight = 1;
}
return Rescale.filterBitmap(refBitmap, newWidth, newHeight);
}
public static Bitmap filterBitmap(Bitmap refBitmap, float widthRatio, float heightRatio) {
int newWidth = Math.round(refBitmap.getWidth() * widthRatio);
int newHeight = Math.round(refBitmap.getHeight() * heightRatio);
if (newWidth <= 0) {
newWidth = 1;
}
if (newHeight <= 0) {
newHeight = 1;
}
return Rescale.filterBitmap(refBitmap, newWidth, newHeight);
}
public static Bitmap filterBitmap(Bitmap refBitmap, int newWidth, int newHeight) {
int width = refBitmap.getWidth();
int height = refBitmap.getHeight();
Bitmap ret = Bitmap.createBitmap(
newWidth,
newHeight,
Bitmap.Config.ARGB_8888
);
int gridXPointer = 0;
float gridXPointerF = 0.0f;
float gridXPointerF2 = 0.0f;
float gridYPointerF = 0.0f;
float gridYPointerF2 = 0.0f;
UnpackedColor loopTmpColor = null;
UnpackedColor unpackedRetPixel = null;
float retWeight = 0.0f;
float tmpYWeight = 0.0f;
float tmpWeight = 0.0f;
float refXF = 0.0f;
float refYF = 0.0f;
float loopF = 0.0f;
float loop2F = 0.0f;
float loopFMod = 0.0f;
float loop2FMod = 0.0f;
int refXFInt = 0;
int refYFInt = 0;
float refXFMod = 0.0f;
float refYFMod = 0.0f;
float refXFFirstMod = 0.0f;
float loopFInt = 0.0f;
float loop2FInt = 0.0f;
for (int gridYPointer = 0; gridYPointer < newHeight; gridYPointer++) {
gridYPointerF = (gridYPointer * (float)height) / (float)newHeight;
gridYPointerF2 = ((gridYPointer + 1) * (float)height) / (float)newHeight;
gridXPointer = 0;
for (; gridXPointer < newWidth; gridXPointer++) {
unpackedRetPixel = new UnpackedColor(
0.0f,
0.0f,
0.0f,
0.0f
);
gridXPointerF = (gridXPointer * (float)width) / (float)newWidth;
gridXPointerF2 = ((gridXPointer + 1) * (float)width) / (float)newWidth;
retWeight = 0.0f;
refYF = gridYPointerF;
refYFMod = refYF % 1.0f;
loopF = gridYPointerF2;
loop2F = gridXPointerF2;
loopFMod = loopF % 1.0f;
loop2FMod = loop2F % 1.0f;
loopFInt = (int)loopF;
loop2FInt = (int)loop2F;
retWeight = 0;
for (; refYF < loopF; refYF += 1.0f) {
refYFInt = (int)refYF;
if (refYFInt == loopFInt) {
tmpYWeight = loopFMod - refYFMod;
}
else if (refYFMod > 0.0f) {
tmpYWeight = 1.0f - refYFMod;
}
else {
tmpYWeight = 1.0f;
}
refXF = gridXPointerF;
refXFMod = refXFFirstMod;
for (; refXF < loop2F; refXF += 1.0f) {
refXFInt = (int)refXF;
loopTmpColor = new UnpackedColor(
refBitmap.getPixel(
refXFInt,
refYFInt
)
);
tmpWeight = tmpYWeight;
if (refXFInt == loop2FInt) {
tmpWeight *= loop2FMod - refXFMod;
}
else if (refXFMod > 0.0f) {
tmpWeight *= 1.0f - refXFMod;
}
else {
tmpWeight *= 1.0f;
}
loopTmpColor.pow(tmpWeight);
unpackedRetPixel.sum(loopTmpColor);
retWeight += tmpWeight;
if (refXFMod > 0.0f) {
refXF = refXFInt;
refXFMod = 0.0f;
}
}
if (refYFMod > 0.0f) {
refYF = refYFInt;
refYFMod = 0.0f;
}
}
unpackedRetPixel.div(retWeight);
ret.setPixel(
gridXPointer,
gridYPointer,
unpackedRetPixel.pack()
);
}
}
return ret;
}
}
使用过滤器:
Bitmap b = ((BitmapDrawable)getResources().getDrawable(R.mipmap.icon)).getBitmap();
b = Rescale.filterBitmap(b, 0.75f);
//Or
b = Rescale.filterBitmap(b, 0.75f, 1.25f);
//Or
b = Rescale.filterBitmap(b, 250, 500);
您只需要一行代码:
canvas.drawBitmap(bitmap, x, y, new Paint(Paint.ANTI_ALIAS_FLAG));
不是 5 行