【问题标题】:Blending two images together with multiply and % opacity将两个图像与乘法和不透明度混合在一起
【发布时间】:2011-12-06 12:31:55
【问题描述】:

我正在尝试将两个图像与 Android 混合在一起,使用类似 Multiply 的混合模式。

// Prepare -------------------------------

// Create source images
Bitmap img1 = ...
Bitmap img2 = ...

// Create result image
Bitmap result = ...
Canvas canvas = new Canvas();
canvas.setBitmap(result);

// Get proper display reference
BitmapDrawable drawable = new BitmapDrawable(getResources(), result);
ImageView imageView = (ImageView)findViewById(R.id.imageBlend1);
imageView.setImageDrawable(drawable);


// Apply -------------------------------

// Draw base
canvas.drawBitmap(img1, 0, 0, null);

// Draw overlay
Paint paint = new Paint();
paint.setXfermode(new PorterDuffXfermode(Mode.MULTIPLY));
paint.setShader(new BitmapShader(img2, TileMode.CLAMP, TileMode.CLAMP));

canvas.drawRect(0, 0, img2.getWidth(), img2.getHeight(), paint);

这可行,但我无法控制完成的乘法“数量” - 它始终是完整的乘法传输。理想情况下,0% 的乘法将与基本图像 (img1) 相同,没有任何更改,但 100% 的乘法将是我使用上述代码得到的结果。

paint.setAlpha() 似乎对此不起作用。

还有其他方法可以设置新“层”的不透明度百分比吗?

附:我猜有一些方法可以通过预乘并将颜色偏移为白色来使乘法工作(使用LightingColorFilter),但它非常特定于乘法模式..我正在尝试找到一种方法来应用opacity/% 也适用于所有其他传输模式。

【问题讨论】:

    标签: android blending porter-duff


    【解决方案1】:

    不久前我需要做类似的事情,我发现this post about Color Channels 很有启发性。 (但我担心这与你在“PS”中描述的内容有关)

    Link above in archive.org,感谢@1j01

    【讨论】:

    • Valeu rapaz。但是,是的,这篇文章很棒,但更多的是关于附加具有不同模式的图层,而不是有一种方法可以更改每种模式的输入值百分比。从图像中读取像素后,它确实显示了对像素的一些直接操作,所以也许它是一种替代方法。我需要对此进行调查。现在,谢谢!
    【解决方案2】:

    我正在实现与我们的 iOS 应用类似的照片过滤器。他们这样做就像source bitmap + mask bitmap + blend mode + alpha value。为了实现相同的行为,我只是增加了掩码的 alpha。这是我的代码最终的样子:

    public static Bitmap blend(Bitmap back, Bitmap front, BlendMethod method, float alpha) {
        if (alpha != 1.0F) {
            front = makeTransparent(front, Math.round(alpha * 255));
        }
    
        Bitmap.Config config = back.getConfig();
        int width = back.getWidth();
        int height = back.getHeight();
    
        if (width != front.getWidth() || height != front.getHeight()) {
            Log.e(TAG, "Arrays must be of identical size! Do bitmap scaling prior to blending.");
            return null;
        }
    
        int[] frontArr = new int[height * width], backArr = new int[height * width], resultArr;
    
        back.getPixels(backArr, 0, width, 0, 0, width, height);
        front.getPixels(frontArr, 0, width, 0, 0, width, height);
    
        resultArr = jniBlend(frontArr, backArr, alpha, method.toInt());
        return Bitmap.createBitmap(resultArr, width, height, config);
    }
    
    public static Bitmap blend(Bitmap back, Bitmap front, BlendMethod method) {
        return blend(back, front, method, 1F);
    }
    
    public static Bitmap makeTransparent(Bitmap src, int value) {
        int width = src.getWidth();
        int height = src.getHeight();
        Bitmap transBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(transBitmap);
        canvas.drawARGB(0, 0, 0, 0);
        // config paint
        final Paint paint = new Paint();
        paint.setAlpha(value);
        canvas.drawBitmap(src, 0, 0, paint);
        return transBitmap;
    }
    

    请注意,jniBlend 是我自己编写的一些方法,它的行为类似于 Java 中的普通 PorterDuff 模式。

    方法makeTransparent 不是我的 - 找到它here:(来自Ruban 的回答)

    【讨论】:

    • 什么是 BlendMethod???请分享完整的,否则没用。
    • @Mohsin 如果我没记错这背后的问题,我认为这现在是在 AndroidSDK 中实现的。早在 2015 年,它就缺少一些混合模式
    【解决方案3】:

    代码不完整。它只是给您一个想法,以便您可以使用渲染脚本来混合图像

    public Bitmap blend(Bitmap image)
    {
        final float BLUR_RADIUS = 25f;
        Bitmap outbitmap = Bitmap.createBitmap(image);
        final RenderScript renderScript = RenderScript.create(this);
    
        Allocation tmpin = Allocation.createFromBitmap(renderScript,image);
        Allocation tmpout = Allocation.createFromBitmap(renderScript,outbitmap);
        ScriptIntrinsicBlend blend = ScriptIntrinsicBlend.create(renderScript,
        Element.U8_4(renderScript));
    
        blend.forEachMultiply(tmpin,tmpout);
        return outbitmap;
    }
    

    【讨论】:

      【解决方案4】:

      我正在使用来自@Den Drobiazko 答案的这些代码行,它非常适合混合位图

      // 将您的位图和可见性百分比作为整数值传递

          public static Bitmap makeTransparent(Bitmap src, int value) {
          int width = src.getWidth();
          int height = src.getHeight();
          Bitmap transBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
          Canvas canvas = new Canvas(transBitmap);
          canvas.drawARGB(0, 0, 0, 0);
          // config paint
          Log.e("test","value "+value);
          final Paint paint = new Paint();
          paint.setAlpha(value);
          canvas.drawBitmap(src, 0, 0, paint);
          return transBitmap;
      }
      

      【讨论】:

        猜你喜欢
        • 2015-02-03
        • 1970-01-01
        • 1970-01-01
        • 2017-03-31
        • 1970-01-01
        • 2016-05-02
        • 1970-01-01
        • 1970-01-01
        • 2011-02-22
        相关资源
        最近更新 更多