Замаскировка рисунок / растровое изображение на Android

StackOverflow https://stackoverflow.com/questions/2623888

  •  26-09-2019
  •  | 
  •  

Вопрос

В настоящее время я ищу способ использовать черно-белое растровое изображение, чтобы замаскировать альфа-канал другого растрового изображения или на Android. Мне интересно, как это сделать лучший способ сделать это. У меня, безусловно, у меня есть пара идей для того, как это сделать, но они не являются оптимальными.

Мне нужно иметь возможность применить новую маску на изображение каждый так часто (черно-белое растровое изображение изменится каждые несколько секунд).

Любая отзыва о том, как добиться этого было бы очень оценено.

Это было полезно?

Решение

Я получил это работать, так что это что-то подобное

    // we first same the layer, rectF is the area of interest we plan on drawing
    // this will create an offscreen bitmap
    canvas.saveLayer(rectF, null, Canvas.MATRIX_SAVE_FLAG
            | Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
            | Canvas.FULL_COLOR_LAYER_SAVE_FLAG
            | Canvas.CLIP_TO_LAYER_SAVE_FLAG);

    // draw our unmasked stuff
    super.draw(canvas);
    // We same a layer again but this time we pass a paint object to mask
    // the above layer
    maskPaint = new Paint()
    maskPaint.setColor(0xFFFFFFFF);
    maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));

    canvas.saveLayer(rectF, maskPaint,
            Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG
                    | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
                    | Canvas.FULL_COLOR_LAYER_SAVE_FLAG
                    | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
    // we draw the mask which is black and white. In my case
    // I have a path, and I use a blurPaint which blurs the mask slightly
    // You can do anti aliasing or whatever you which. Just black & white
    canvas.drawPath(path, blurPaint);
    // We restore twice, this merges the results upward
    // as each saveLayer() allocates a new drawing bitmap
    canvas.restore();
    canvas.restore();

Другие советы

Мое решение близко к решению @ Over_Optimistic, меньше одного Savelayer () вызова. Я использую черную маску вместо пути, в моем случае это был диск.

Я объявил эти переменные как поля (это хорошая практика для выделения памяти за пределами метода Ondraw):

private Paint maskingPaint = new Paint();
private Drawable mask = <insert your drawable here>

Затем, где-то за пределами OnDraw (), установить объекты:

// Xfermode won't work if hardware accelerated
setLayerType(View.LAYER_TYPE_SOFTWARE, null);

// Using destination shape as a mask
// For a good explanation of PorterDuff transfer modes : http://ssp.impulsetrain.com/porterduff.html
maskingPaint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
maskingPaint.setAntiAlias(true);

// Position the mask
mask.setBounds(<insert your mask bounds here>);

Затем, наконец, метод Ondraw () применяет маску:

@Override
protected synchronized void onDraw(Canvas canvas)
{
    // Draw the mask first, making it the PorterDuff destination
    mask.draw(canvas);

    // Save the layer with the masking paint, that will be applied on restore()
    // Using CLIP_TO_LAYER_SAVE_FLAG to avoid any overflow of the masked image outside the mask bounds.
    Rect bounds = mask.getBounds();
    canvas.saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, maskingPaint, 
            Canvas.CLIP_TO_LAYER_SAVE_FLAG);

    // Draw the shape offscreen, making it the PorterDuff source
    super.onDraw(canvas);

    // Apply the source to the destination, using SRC_IN transfer mode
    canvas.restore();
}

Для лучшего понимания режимов передачи я упоминал http://ssp.impulsetrain.com/porterduff.html.Отказ Эта страница довольно интересная для чтения. После этого, с тем же типом кода вы сможете достичь гораздо больше, чем простой маски!

Я сделал маскируемый макет. Это чердак, где вы можете специфизировать Xporterduffmode и маску. Вы можете найти это здесь: https://github.com/christophesmet/android_maskable_layout.

Я не совсем понятно о том, что вы идете, но я считаю, что комбинация BitmapDrawable а также LayerDrawable может работать. Bitmapdrawable позволит вам использовать ваши растровые изображения в качестве Doeskables, а затем вы можете использовать SaleDrawable для слоя маски поверх другого нанесения.

Используя пример Xfermodes в демонстрационной основе API, я смог использовать PorterDuffxfermode, примененный к объекту краски, чтобы объединить два растровых изображения на холсте. Это работает именно, как мне это нужно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top