David Toth David Toth - 1 month ago 22
Android Question

Android GrayScale then Invert colors for a bitmap issue

I am drawing some bitmaps to an ImageView's Canvas. 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).

Inside of the Overrided OnDraw(Canvas canvas) method:

// 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?

Answer

Are you sure your matrix is set properly?

According to the ColorMatrix documentation your input matrix is defined like this:

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;

In your matrix r equals 1.0f while the rest are 0f. According to this, only the alpha channel will be non zero and hence black seems like the expected output.

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