Смешивание двух изображений вместе с умножением и% непрозрачности

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

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

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

Solutions Collecting From Web of "Смешивание двух изображений вместе с умножением и% непрозрачности"

Мне нужно было сделать что-то подобное раньше, и я нашел этот пост о Color Channels многополезным. (Но я боюсь, что это связано с тем, что вы описали в своем «PS»)

Я выполнял фото фильтры, похожие на то, что делает наше приложение 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 не является моим – нашел его здесь : (ответ от Ruban )

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

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