2013-06-21 1 views
5

У меня есть два растровых изображения. Вот Bitmap 1:Android - Маскирование растрового изображения с использованием другого растрового изображения

Bitmap 1: Background

А вот Bitmap 2:

Bitmap 2: frame

Что окончательные результаты должны быть:

Bitmap Final

Я был бы признателен код , однако, я был бы признателен за дополнительную ссылку на документацию или учебник. Я хотел бы полностью понять код, и я долгое время искал на сайте developer.android.com без везения. Благодарю.

+0

Это можно сделать, и я уверен, что кто-то зайдет с некоторым пониманием. Но могу ли я спросить, почему вы не используете только одно растровое изображение или .png конечного результата, который вы хотите? –

+1

@JadeByfield может быть, это динамические входы и выходы, и в этом случае вы не можете этого сделать – fge

+0

@fge Ahh, хорошая точка :) –

ответ

1

Более 3 лет и ответа нет? Я могу это исправить.

Как указано в комментариях, битмап 2 прозрачен по краям и посередине (только контур), поэтому первым шагом будет заполнение центра белым. Существует множество доступных алгоритмов заливки. Я использовал https://stackoverflow.com/a/8925653/852795, потому что это было легко, хотя есть и другие, которые, безусловно, быстрее. Это необходимо, поскольку это позволяет сделать следующий шаг.

Второй этап заключается в объединении заполненного растрового изображения 2 с растровым изображением 1 с использованием Porter/Duff Composting. PorterDuff.Mode.SRC_ATOP эффективно рисует битмап 1 в теперь белую область растрового изображения 2, оставляя область за пределами контура прозрачной.

Вот код:

package test.testapplication; 

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.Point; 
import android.graphics.PorterDuff; 
import android.graphics.PorterDuffXfermode; 
import android.os.Bundle; 
import android.support.v7.app.AppCompatActivity; 
import android.view.View; 
import android.graphics.Bitmap.Config; 

import java.util.LinkedList; 
import java.util.Queue; 

public class MainActivity extends AppCompatActivity { 

    Bitmap mask, background, filledMask, overlay; 
    Canvas c; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     mask = BitmapFactory.decodeResource(getResources(), R.drawable.mask); 
     background = BitmapFactory.decodeResource(getResources(), R.drawable.background); 

     // get the mask, copy it to filledMask and then flood from the center with CYAN 
     filledMask = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(), Config.ARGB_8888); 
     c = new Canvas(filledMask); 
     c.drawBitmap(mask, 0, 0, new Paint()); 
     Point center = new Point(filledMask.getWidth()/2, filledMask.getHeight()/2); 
     floodFill(filledMask, center, Color.TRANSPARENT, Color.WHITE); 


     // create new overlay Bitmap, draw the filledMask and then add the background using PorterDuff 
     overlay = Bitmap.createBitmap(filledMask.getWidth(), filledMask.getHeight(), Config.ARGB_8888); 
     c = new Canvas(overlay); 
     Paint p = new Paint(); 
     p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP)); 
     c.drawBitmap(filledMask, 0, 0, new Paint()); 
     c.drawBitmap(background, 0, 0, p); 

     DrawView drawView = new DrawView(this); 
     // set background to light blue in order to see transparent areas 
     drawView.setBackgroundColor(0xffd2d7fe); 
     setContentView(drawView); 
     drawView.requestFocus(); 
    } 

    public class DrawView extends View { 
     Paint p = new Paint(); 
     int top = 0; 

     public DrawView(Context context) { 
      super(context); 
     } 

     protected void onDraw(Canvas canvas) { 
      super.onDraw(canvas); 
      canvas.drawBitmap(mask, 0, 0, p); 
      top += mask.getHeight(); 

      canvas.drawBitmap(filledMask, 0, top, p); 
      top += filledMask.getHeight(); 

      canvas.drawBitmap(background, 0, top, p); 
      top += background.getHeight(); 

      canvas.drawBitmap(overlay, 0, top, p); 
     } 
    } 

    // method from https://stackoverflow.com/a/8925653/852795 
    public void floodFill(Bitmap bmp, Point pt, int targetColor, int replacementColor) { 

     Queue<Point> q = new LinkedList<>(); 
     q.add(pt); 
     while (q.size() > 0) { 
      Point n = q.poll(); 
      if (bmp.getPixel(n.x, n.y) != targetColor) continue; 

      Point w = n, e = new Point(n.x + 1, n.y); 
      while ((w.x > 0) && (bmp.getPixel(w.x, w.y) == targetColor)) { 
       bmp.setPixel(w.x, w.y, replacementColor); 
       if ((w.y > 0) && (bmp.getPixel(w.x, w.y - 1) == targetColor)) q.add(new Point(w.x, w.y - 1)); 
       if ((w.y < bmp.getHeight() - 1) && (bmp.getPixel(w.x, w.y + 1) == targetColor)) q.add(new Point(w.x, w.y + 1)); 
       w.x--; 
      } 
      while ((e.x < bmp.getWidth() - 1) && (bmp.getPixel(e.x, e.y) == targetColor)) { 
       bmp.setPixel(e.x, e.y, replacementColor); 

       if ((e.y > 0) && (bmp.getPixel(e.x, e.y - 1) == targetColor)) q.add(new Point(e.x, e.y - 1)); 
       if ((e.y < bmp.getHeight() - 1) && (bmp.getPixel(e.x, e.y + 1) == targetColor)) q.add(new Point(e.x, e.y + 1)); 
       e.x++; 
      } 
     } 
    } 
} 

При запуске выход (после добавления светло-голубой оттенок на фоне того, чтобы «видеть» прозрачные области изображений) должен выглядеть следующим образом, с изображения, соответственно, будучи Bitmap 2, Bitmap 2 заполнены, Bitmap 1 и, наконец, сочетание Bitmap 2 заполнены и Bitmap 1:

enter image description here

Там, кажется, немного «размытости» только внутри контура , но это, вероятно, артефакт заливки заливки или, возможно, оригинальный битмап 2. Игра с обоими из них может прояснить это.

 Смежные вопросы

  • Нет связанных вопросов^_^