[英]Android GrayScale then Invert colors for a bitmap issue
我正在向ImageView的画布绘制一些位图。 资源位图是彩色的。 我想看到的结果是一个反转的灰度位图图像。
这是我的方法在我的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文档,您的输入矩阵的定义如下:
4x5矩阵,用于转换位图的颜色和alpha分量。 矩阵可以作为单个数组传递,并按以下方式处理:
[a,b,c,d,e,
f,g,h,i,j,
k,l,m,n,o,
p,q,r,s,t]
当应用于颜色[R,G,B,A]时,所得颜色计算为:
R'= a R + b G + c B + d A + e;
G'= f R + g G + h B + i A + j;
B′= kR + 1G + mB + nA + o;
A'= p R + q G + r B + s A + t;
在您的矩阵中,r等于1.0f,其余均为0f。 据此,只有Alpha通道将为非零,因此黑色看起来像是预期的输出。
相反,您可以执行以下操作:
ColorMatrix matrix = new ColorMatrix(); matrix.setSaturation(0);
顺便说一句,在执行onDraw()时分配对象(如矩阵)不利于性能。 如果可以,请将分配移动到构造函数或其他地方。
更新:对于反转部分可以申请额外的基质(无论是作为描述乘以矩阵这里 。或者只是绘制位图的两倍(这是低效率)的逆矩阵应该是-
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);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.