Android GrayScale 然后 Invert colors 解决位图问题
Android GrayScale then Invert colors for a bitmap issue
我正在将一些位图绘制到 ImageView 的 Canvas。资源位图是彩色的。我希望看到的结果是反转的灰度位图图像。
这是我的方法,在我的 Samsung Galaxy S3(版本 4.3)上运行良好,但在我的 S3 Mini(版本 4.1.2)上运行不正常。
重写的 OnDraw(Canvas canvas) 方法内部:
// Night mode color:
Paint colorBMPPaint = new Paint();
if (((EzPdfActivityPageView) mContext).bIsNightMode) {
float invertMX[] = {
0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f
};
ColorMatrix invertCM = new ColorMatrix(invertMX);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(invertCM);
colorBMPPaint.setColorFilter(filter);
}
canvas.drawBitmap(bitmap,
new Rect(0, 0, (int)((bbox.right - bbox.left) * zoom), (int)((bbox.top - bbox.bottom) * zoom)),
pageDrawRect,
colorBMPPaint);
在 S3 Mini 上我只能得到黑色位图,为什么?
你确定你的矩阵设置正确吗?
根据 ColorMatrix documentation 你的输入矩阵定义如下:
4x5 matrix for transforming the color and alpha components of a Bitmap. The matrix can be passed as single array, and is treated as follows:
[ a, b, c, d, e,
f, g, h, i, j,
k, l, m, n, o,
p, q, r, s, t ]
When applied to a color [R, G, B, A], the resulting color is computed as:
R’ = aR + bG + cB + dA + e;
G’ = fR + gG + hB + iA + j;
B’ = kR + lG + mB + nA + o;
A’ = pR + qG + rB + sA + t;
在你的矩阵中,r 等于 1.0f,而其余的都是 0f。据此,只有 alpha 通道将是非零的,因此黑色似乎是预期的输出。
相反,您可以执行以下操作:
ColorMatrix matrix = new ColorMatrix();
matrix.setSaturation(0);
顺便说一句,在执行 onDraw() 时分配对象(如矩阵)不利于性能。如果可以,请将分配移至构造函数或其他位置。
更新:
对于反转部分,您可以应用一个额外的矩阵(按照 here 中所述乘以矩阵,或者只绘制两次位图(效率较低)。反转矩阵应该是 -
ColorMatrix colorMatrix_Inverted =
new ColorMatrix(new float[] {
-1, 0, 0, 0, 255,
0, -1, 0, 0, 255,
0, 0, -1, 0, 255,
0, 0, 0, 1, 0});
根据@Doron Yakovlev-Golani 的建议,我已经编辑了我的代码,该代码现在可以在两种设备上运行:
float invertMX[] = {
-1.0f, 0.0f, 0.0f, 0.0f, 255f,
0.0f, -1.0f, 0.0f, 0.0f, 255f,
0.0f, 0.0f, -1.0f, 0.0f, 255f,
0.0f, 0.0f, 0.0f, 1.0f, 0.0f
};
ColorMatrix saturationZero = new ColorMatrix();
saturationZero.setSaturation(0);
ColorMatrix finalCM = new ColorMatrix(saturationZero);
ColorMatrix invertCM = new ColorMatrix(invertMX);
finalCM.postConcat(invertCM);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(finalCM);
colorBMPPaint.setColorFilter(filter);
这对我有用:
for (int x = 0; x < bm.getWidth(); ++x) {
for (int y = 0; y < bm.getHeight(); ++y) {
int color = bm.getPixel(x, y);
int r = Color.red(color);
int g = Color.green(color);
int b = Color.blue(color);
int avg = (r + g + b) / 3;
int newColor = Color.argb(255, 255 - avg, 255 - avg, 255 - avg);
bm.setPixel(x, y, newColor);
}
}
注意您的位图必须是可变的才能对其进行操作可能会很有用。如果不是,您可以这样做来创建一个可变副本:
bm = bm.copy(bm.getConfig(), true);
我正在将一些位图绘制到 ImageView 的 Canvas。资源位图是彩色的。我希望看到的结果是反转的灰度位图图像。
这是我的方法,在我的 Samsung Galaxy S3(版本 4.3)上运行良好,但在我的 S3 Mini(版本 4.1.2)上运行不正常。
重写的 OnDraw(Canvas canvas) 方法内部:
// Night mode color:
Paint colorBMPPaint = new Paint();
if (((EzPdfActivityPageView) mContext).bIsNightMode) {
float invertMX[] = {
0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f, 0.0f
};
ColorMatrix invertCM = new ColorMatrix(invertMX);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(invertCM);
colorBMPPaint.setColorFilter(filter);
}
canvas.drawBitmap(bitmap,
new Rect(0, 0, (int)((bbox.right - bbox.left) * zoom), (int)((bbox.top - bbox.bottom) * zoom)),
pageDrawRect,
colorBMPPaint);
在 S3 Mini 上我只能得到黑色位图,为什么?
你确定你的矩阵设置正确吗?
根据 ColorMatrix documentation 你的输入矩阵定义如下:
4x5 matrix for transforming the color and alpha components of a Bitmap. The matrix can be passed as single array, and is treated as follows:
[ a, b, c, d, e,
f, g, h, i, j,
k, l, m, n, o,
p, q, r, s, t ]
When applied to a color [R, G, B, A], the resulting color is computed as:
R’ = aR + bG + cB + dA + e;
G’ = fR + gG + hB + iA + j;
B’ = kR + lG + mB + nA + o;
A’ = pR + qG + rB + sA + t;
在你的矩阵中,r 等于 1.0f,而其余的都是 0f。据此,只有 alpha 通道将是非零的,因此黑色似乎是预期的输出。
相反,您可以执行以下操作:
ColorMatrix matrix = new ColorMatrix();
matrix.setSaturation(0);
顺便说一句,在执行 onDraw() 时分配对象(如矩阵)不利于性能。如果可以,请将分配移至构造函数或其他位置。
更新: 对于反转部分,您可以应用一个额外的矩阵(按照 here 中所述乘以矩阵,或者只绘制两次位图(效率较低)。反转矩阵应该是 -
ColorMatrix colorMatrix_Inverted =
new ColorMatrix(new float[] {
-1, 0, 0, 0, 255,
0, -1, 0, 0, 255,
0, 0, -1, 0, 255,
0, 0, 0, 1, 0});
根据@Doron Yakovlev-Golani 的建议,我已经编辑了我的代码,该代码现在可以在两种设备上运行:
float invertMX[] = {
-1.0f, 0.0f, 0.0f, 0.0f, 255f,
0.0f, -1.0f, 0.0f, 0.0f, 255f,
0.0f, 0.0f, -1.0f, 0.0f, 255f,
0.0f, 0.0f, 0.0f, 1.0f, 0.0f
};
ColorMatrix saturationZero = new ColorMatrix();
saturationZero.setSaturation(0);
ColorMatrix finalCM = new ColorMatrix(saturationZero);
ColorMatrix invertCM = new ColorMatrix(invertMX);
finalCM.postConcat(invertCM);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(finalCM);
colorBMPPaint.setColorFilter(filter);
这对我有用:
for (int x = 0; x < bm.getWidth(); ++x) {
for (int y = 0; y < bm.getHeight(); ++y) {
int color = bm.getPixel(x, y);
int r = Color.red(color);
int g = Color.green(color);
int b = Color.blue(color);
int avg = (r + g + b) / 3;
int newColor = Color.argb(255, 255 - avg, 255 - avg, 255 - avg);
bm.setPixel(x, y, newColor);
}
}
注意您的位图必须是可变的才能对其进行操作可能会很有用。如果不是,您可以这样做来创建一个可变副本:
bm = bm.copy(bm.getConfig(), true);