Смешивание двух изображений вместе с кратностью и% непрозрачности - PullRequest
9 голосов
/ 13 октября 2011

Я пытаюсь смешать два изображения вместе с 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() не похоже на это.

Есть ли другой способ установить% непрозрачности нового «слоя»?

P.S. Я предполагаю, что есть несколько способов заставить умножение работать с этим (используя LightingColorFilter) путем предварительного умножения и смещения цвета к белому, но это очень специфично для множителя ... Я пытаюсь найти способ применить Непрозрачность /% вещь также для всех других режимов передачи.

Ответы [ 3 ]

3 голосов
/ 15 октября 2011

Мне нужно было сделать что-то подобное некоторое время назад, и я нашел этот пост о цветных каналах очень поучительным. (Но я боюсь, что это связано с тем, что вы описали в своем "PS")

Ссылка выше на archive.org , спасибо @ 1j01

2 голосов
/ 06 января 2015

Я реализовывал фотофильтры, похожие на то, что делает наше приложение для iOS.Они делают что-то вроде source bitmap + mask bitmap + blend mode + alpha value.Чтобы добиться идентичного поведения, я просто увеличил альфа маски.Вот как наконец-то выглядит мой код:

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 - это некоторый метод, который я написал самостоятельно, он ведет себя как стандартные режимы PorterDuff в Java.

Метод makeTransparent не мой- нашел его здесь : (ответ от Рубан )

0 голосов
/ 23 мая 2017

Код не полный. это просто дать вам представление о том, что вы можете использовать скрипт рендеринга для смешивания изображения

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