天天看點

Adnroid上的容易圖像合成類——PorterDuffXfermode

​​http://www.myexception.cn/image/1255520.html​​

Adnroid上的簡單圖像合成類——PorterDuffXfermode

圖像合成,是将兩幅退昂放在一起的動作,它使得我們能夠同時看到兩幅圖像的特征。

我們可以首先在Canvas對象上繪制一個位圖對象,然後再相同的Canvas對象上繪制第二個位圖對象的方式來實作合成。不過這裡在繪制第二幅圖像的時候,需要在Paint對象上指定一個過渡模式(Xfermode)。

可用作過渡模式的類集合都繼承自Xfermode基類,而其中包括一個成為PorterDuffXfermode的類。PorterDuffXfermode因Thomas Porter和Tom Duff而得名,他們于1984年在ACM SIGGRAPH計算機圖形學出版物上發表了題為“Compositing digital images”(合成數字圖像)的文章,詳細介紹了一系列不同的規則,用于彼此重疊的繪制圖像。

在Android的PorterDuff.Mode類中列舉了他們制定的規則:

android.graphics.PorterDuff.Mode.CLEAR: 所繪制不會送出到畫布上

android.graphics.PorterDuff.Mode.SRC:隻繪制源圖像

android.graphics.PorterDuff.Mode.DST:隻繪制目标圖像

android.graphics.PorterDuff.Mode.DST_OVER:在源圖像的頂部繪制目标圖像

android.graphics.PorterDuff.Mode.DST_IN:隻在源圖像和目标圖像相交的地方繪制目标圖像

android.graphics.PorterDuff.Mode.DST_OUT:隻在源圖像和目标圖像不相交的地方繪制目标圖像

android.graphics.PorterDuff.Mode.DST_ATOP:在源圖像和目标圖像相交的地方繪制目标圖像,在不相交的地方繪制源圖像

android.graphics.PorterDuff.Mode.SRC_OVER:在目标圖像的頂部繪制源圖像

android.graphics.PorterDuff.Mode.SRC_IN:隻在源圖像和目标圖像相交的地方繪制源圖像

android.graphics.PorterDuff.Mode.SRC_OUT:隻在源圖像和目标圖像不相交的地方繪制源圖像

android.graphics.PorterDuff.Mode.SRC_ATOP:在源圖像和目标圖像相交的地方繪制源圖像,在不相交的地方繪制目标圖像

android.graphics.PorterDuff.Mode.XOR:在源圖像和目标圖像重疊之外的任何地方繪制他們,而在不重疊的地方不繪制任何内容

android.graphics.PorterDuff.Mode.LIGHTEN:獲得每個位置上兩幅圖像中最亮的像素并顯示

android.graphics.PorterDuff.Mode.DARKEN:獲得每個位置上兩幅圖像中最暗的像素并顯示

android.graphics.PorterDuff.Mode.MULTIPLY:将每個位置的兩個像素相乘,除以255,然後使用該值建立一個新的像素進行顯示。結果顔色=頂部顔色*底部顔色/255

android.graphics.PorterDuff.Mode.SCREEN:反轉每個顔色,執行相同的操作(将他們相乘并除以255),然後再次反轉。結果顔色=255-(((255-頂部顔色)*(255-底部顔色))/255)

以下是使用的範例源碼:

public class MainActivity extends Activity implements OnClickListener
{
  static final int PICKED_ONE = 0;
  static final int PICKED_TWO = 1;
  boolean onePicked = false;
  boolean twoPicked = false;
  ImageView compositeImageView;
  Button choosePicture1, choosePicture2;
  Bitmap bmp1, bmp2;
  Canvas canvas;
  Paint paint;

  @Override
  protected void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    compositeImageView = (ImageView) findViewById(R.id.ChosenImageView);
    choosePicture1 = (Button) findViewById(R.id.ChoosePictureButton1);
    choosePicture2 = (Button) findViewById(R.id.ChoosePictureButton2);
    choosePicture1.setOnClickListener(this);
    choosePicture2.setOnClickListener(this);
  }

  @Override
  public void onClick(View v)
  {
    // TODO Auto-generated method stub
    int which = -1;
    if (v == choosePicture1)
    {
      which = PICKED_ONE;
    } else
    {
      which = PICKED_TWO;
    }
    Intent choosePictureIntent = new Intent(Intent.ACTION_PICK,
        Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(choosePictureIntent, which);
  }

  private Bitmap loadBitmap(Uri imageFileUri)
  {
    Display currentDisplay = getWindowManager().getDefaultDisplay();
    int dw = currentDisplay.getWidth();
    int dh = currentDisplay.getHeight();
    Bitmap returnBmp = Bitmap.createBitmap(dw, dh, Config.ARGB_4444);

    BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
    bmpFactoryOptions.inJustDecodeBounds = true;
    try
    {
      returnBmp = BitmapFactory.decodeStream(getContentResolver()
          .openInputStream(imageFileUri), null, bmpFactoryOptions);
    } catch (FileNotFoundException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    int heightRatio = (int) Math.ceil(bmpFactoryOptions.outHeight
        / (float) dh);
    int widthRatio = (int) Math.ceil(bmpFactoryOptions.outWidth
        / (float) dw);
    if (heightRatio > 1 && widthRatio > 1)
    {
      if (heightRatio > widthRatio)
      {
        bmpFactoryOptions.inSampleSize = heightRatio;
      } else
      {
        bmpFactoryOptions.inSampleSize = widthRatio;
      }
    }
    bmpFactoryOptions.inJustDecodeBounds = false;
    try
    {
      returnBmp = BitmapFactory.decodeStream(getContentResolver()
          .openInputStream(imageFileUri), null, bmpFactoryOptions);
    } catch (FileNotFoundException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    return returnBmp;
  }

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data)
  {
    // TODO Auto-generated method stub
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK)
    {
      Uri imageFileUri = data.getData();

      if (requestCode == PICKED_ONE)
      {
        bmp1 = loadBitmap(imageFileUri);
        onePicked = true;
      } else
      {
        bmp2 = loadBitmap(imageFileUri);
        twoPicked = true;
      }

      if (onePicked && twoPicked)
      {
        Bitmap drawingBitmap = Bitmap.createBitmap(bmp1.getWidth(),
            bmp1.getHeight(), bmp1.getConfig());
        canvas = new Canvas(drawingBitmap);
        paint = new Paint();
        canvas.drawBitmap(bmp1, 0, 0, paint);
        paint.setXfermode(new PorterDuffXfermode(
            android.graphics.PorterDuff.Mode.DARKEN));
        canvas.drawBitmap(bmp2, 0, 0, paint);
        compositeImageView.setImageBitmap(drawingBitmap);
      }
    }
  }

}