2013-06-21 36 views
5

Tôi có hai bitmap. Dưới đây là Bitmap 1:Android - Mặt nạ một Bitmap bằng cách sử dụng một Bitmap khác

Bitmap 1: Background

Và đây là Bitmap 2:

Bitmap 2: frame

gì kết quả cuối cùng sẽ là:

Bitmap Final

tôi sẽ đánh giá cao một mã số Tuy nhiên, tôi muốn đánh giá cao hơn một tham chiếu đến tài liệu hoặc hướng dẫn. Tôi muốn hiểu mã hoàn toàn và tôi đã tìm kiếm trên developer.android.com quá lâu mà không có may mắn. Cảm ơn.

+0

Điều này có thể được thực hiện và tôi chắc chắn ai đó sẽ ghé qua bằng một số thông tin chi tiết. Nhưng tôi có thể hỏi tại sao bạn không chỉ sử dụng một bitmap hoặc .png của kết quả cuối cùng mà bạn muốn? –

+1

@JadeByfield có lẽ đó là đầu vào và đầu ra động, trong trường hợp này, tốt, bạn không thể làm điều đó – fge

+0

@fge Ahh, điểm tốt :) –

Trả lời

1

Trong 3 năm và không có câu trả lời? Tôi có thể sửa nó.

Như đã nêu trong các chú thích, Bitmap 2 là trong suốt xung quanh các cạnh và ở giữa (chỉ có đường viền ở đó) nên bước đầu tiên là điền vào giữa màu trắng. Có rất nhiều thuật toán lấp đầy lũ lụt có sẵn. Tôi đã sử dụng https://stackoverflow.com/a/8925653/852795 vì nó dễ dàng, mặc dù có những người khác chắc chắn nhanh hơn. Điều này là cần thiết vì nó cho phép bước tiếp theo.

Bước thứ hai là kết hợp Bitmap 2 được lấp đầy với Bitmap 1 bằng cách sử dụng Porter/Duff Composting. PorterDuff.Mode.SRC_ATOP sẽ sơn Bitmap 1 hiệu quả vào khu vực màu trắng hiện tại của Bitmap 2 trong khi rời khỏi khu vực bên ngoài đường viền trong suốt.

Đây là mã:

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

Khi chạy, đầu ra (sau khi thêm một màu xanh nhạt để nền để 'nhìn thấy' các vùng trong suốt của hình ảnh) nên trông như thế này, với những hình ảnh, tương ứng, là Bitmap 2, Bitmap 2 điền, Bitmap 1 và cuối cùng là sự kết hợp của Bitmap 2 điền và Bitmap 1:

enter image description here

có vẻ như một chút 'mờ' chỉ bên trong đường viền , nhưng đó có lẽ một tạo phẩm tràn ngập lũ lụt, hoặc có lẽ là bản gốc Bitmap 2. Chơi xung quanh với cả hai người trong số đó có thể rõ ràng rằng lên.