【问题标题】:Android GrayScale then Invert colors for a bitmap issueAndroid GrayScale 然后为位图问题反转颜色
【发布时间】:2016-10-26 19:43:27
【问题描述】:

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

这是我的方法,它在我的三星 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 上我只能看到黑色位图,为什么?

【问题讨论】:

    标签: java android bitmap colormatrixfilter


    【解决方案1】:

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

    根据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' = 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});

    【讨论】:

    • 太好了,它的工作原理(代码在我下面的答案中,我接受这个 ofc)。是的,我会将这些颜色设置移到 OnDraw 方法之外。谢谢!
    • 这绝对适用于 drawBitmap() 方法。谢谢:)
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      这对我有用:

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

      【讨论】:

        猜你喜欢
        • 2011-06-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-07
        相关资源
        最近更新 更多