12

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

// 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()似乎对此不起作用。

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

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

4

4 回答 4

3

不久前我需要做类似的事情,我发现这篇关于颜色通道的帖子很有启发性。(但恐怕这与您在“PS”中描述的内容有关)

上面的链接 archive.org,感谢@1j01

于 2011-10-14T23:30:39.923 回答
3

我正在实现与我们的 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不是我的 - 在这里找到它:(来自鲁班的回答)

于 2015-01-06T11:01:14.217 回答
0

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

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;
}
于 2017-05-23T10:18:19.253 回答
0

我正在使用@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;
}
于 2021-03-31T17:06:38.967 回答