简体   繁体   English

Android GrayScale然后反转颜色以解决位图问题

[英]Android GrayScale then Invert colors for a bitmap issue

I am drawing some bitmaps to an ImageView's Canvas. 我正在向ImageView的画布绘制一些位图。 The resource bitmaps are colored. 资源位图是彩色的。 The result what I would like to see is a grayscaled bitmap image that is inverted. 我想看到的结果是一个反转的灰度位图图像。

Here is my approach that is perfectly working on my Samsung Galaxy S3 (Version 4.3) but its not working on my S3 Mini (Version 4.1.2). 这是我的方法在我的Samsung Galaxy S3(版本4.3)上可以正常使用,但在我的S3 Mini(版本4.1.2)上却无法使用。

Inside of the Overrided OnDraw(Canvas canvas) method: 覆盖的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);

On S3 Mini I get only black bitmaps, why? 在S3 Mini上,我只能得到黑色位图,为什么呢?

Are you sure your matrix is set properly? 您确定矩阵设置正确吗?

According to the ColorMatrix documentation your input matrix is defined like this: 根据ColorMatrix文档,您的输入矩阵的定义如下:

4x5 matrix for transforming the color and alpha components of a Bitmap. 4x5矩阵,用于转换位图的颜色和alpha分量。 The matrix can be passed as single array, and is treated as follows: 矩阵可以作为单个数组传递,并按以下方式处理:

[ a, b, c, d, e, [a,b,c,d,e,

f, g, h, i, j, f,g,h,i,j,

k, l, m, n, o, k,l,m,n,o,

p, q, r, s, t ] p,q,r,s,t]

When applied to a color [R, G, B, A], the resulting color is computed as: 当应用于颜色[R,G,B,A]时,所得颜色计算为:

R' = a R + b G + c B + d A + e; R'= a R + b G + c B + d A + e;

G' = f R + g G + h B + i A + j; G'= f R + g G + h B + i A + j;

B' = k R + l G + m B + n A + o; B′= kR + 1G + mB + nA + o;

A' = p R + q G + r B + s A + t; A'= p R + q G + r B + s A + t;

In your matrix r equals 1.0f while the rest are 0f. 在您的矩阵中,r等于1.0f,其余均为0f。 According to this, only the alpha channel will be non zero and hence black seems like the expected output. 据此,只有Alpha通道将为非零,因此黑色看起来像是预期的输出。

Instead you can do the following: 相反,您可以执行以下操作:

ColorMatrix matrix = new ColorMatrix(); matrix.setSaturation(0);

BTW, allocating objects (like the matrix) when you are performing onDraw() is bad for performance. 顺便说一句,在执行onDraw()时分配对象(如矩阵)不利于性能。 If you can, move the allocation to the constructor or somewhere else. 如果可以,请将分配移动到构造函数或其他地方。

Update: For the inversion part you can apply an extra matrix (either multiply the matrices as described in here or just draw the bitmap twice (which is less efficient). The inversion matrix should be - 更新:对于反转部分可以申请额外的基质(无论是作为描述乘以矩阵这里 。或者只是绘制位图的两倍(这是低效率)的逆矩阵应该是-

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

According to @Doron Yakovlev-Golani suggestion I have edited my code, this one is now working on both devices: 根据@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);

This works for me: 这对我有用:

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

It might be useful to note that your bitmap must be mutable to manipulate it. 注意,位图必须可变才能操作它,这可能会很有用。 If it is not, you can do this to create a mutable copy: 如果不是,则可以执行以下操作来创建可变副本:

bm = bm.copy(bm.getConfig(), true);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM