我有兩個位圖。下面是位圖1:Android - 使用另一個位圖掩蓋位圖
這裏是位圖2:
什麼的最終結果應爲:
我將不勝感激代碼但是,我希望更多地參考文檔或教程。我想完全理解代碼,並且我一直在搜索developer.android.com很長時間沒有運氣。謝謝。
我有兩個位圖。下面是位圖1:Android - 使用另一個位圖掩蓋位圖
這裏是位圖2:
什麼的最終結果應爲:
我將不勝感激代碼但是,我希望更多地參考文檔或教程。我想完全理解代碼,並且我一直在搜索developer.android.com很長時間沒有運氣。謝謝。
3年多沒有回答?我可以解決這個問題。
正如評論中所述,位圖2在邊緣和中間是透明的(只有輪廓在那裏),所以第一步是用白色填充中心。有很多洪水填充算法可用。我用https://stackoverflow.com/a/8925653/852795,因爲它很容易,但也有其他人肯定更快。這是必要的,因爲它可以啓動下一步。
第二步是使用Porter/Duff Composting將填充的位圖2與位圖1相結合。 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++;
}
}
}
}
運行時,將輸出(在順序添加淺藍色色調的背景「看見」的圖像的透明區域之後)應該是這樣的,以圖像分別是位圖2,填充位圖2,位圖1和位圖2填充的最後的組合和Bitmap 1:
似乎有一個比特的「模糊性」只是在輪廓內部,但那很可能一個洪水填充的神器,或者也許是原始的位圖2.與這兩個玩弄可能會清除。
這可以完成,我相信有人會有一些洞察力。但是,我可以問爲什麼你不只是使用你想要的最終結果的單個位圖或.png? –
@JadeByfield也許這些是動態的輸入和輸出,在這種情況下,你不能這樣做 – fge
@fge啊,好點:) –