Android GrayScale然后反转位图问题的颜色

时间:2016-10-26 19:43:27

标签: java android bitmap colormatrixfilter

我正在为ImageView的Canvas绘制一些位图。资源位图是彩色的。我希望看到的结果是一个被反转的灰度位图图像。

这是我的方法,完全适用于我的三星Galaxy S3(版本4.3),但它不适用于我的S3 Mini(版本4.1.2)。

Overrided 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上我只得到黑色位图,为什么?

3 个答案:

答案 0 :(得分:2)

您确定您的矩阵设置正确吗?

根据ColorMatrix documentation,您的输入矩阵定义如下:

  

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'= k R + l G + m B + n A + o;

     

A'= p R + q G + r B + s A + 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});

答案 1 :(得分:1)

根据@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);

答案 2 :(得分:0)

这对我有用:

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);