最近工作上遇到了一个将一个图片按照相框进行裁剪的问题,花了一个下午研究了下,在此整理一下,以便后用。
+ =
(相片) (相框) (结果图)
一个按照边框裁剪的类,因为相框通体为蓝色,只是不同区域的透明度不同,所以,选用了根据透明度来筛选边界上的点的方法。
另外,这个类也提供了判断一个点是否是在相框内部的方法:
和当前像素点同一水平线上的各点,假如左右两侧均有相框蓝色边界上的点的话,并且当前点不在边框上则认为当前点在相框的内部。
反之,则认为当前点在相框的外部。
- package com.example.test_filter;
- import android.graphics.Bitmap;
- import android.graphics.Color;
- import android.graphics.Matrix;
- import android.graphics.Bitmap.Config;
- public class AlphaFilter implements Filter{
- public static final int INSIDE_MODE = 0;
- public static final int EDGE_MODE = 1;
- public static final int OUTSIDE_MODE = 2;
- public int findNonOpaque(int x, int y, int width, int height, int[] srcPixels) {
- if(width < height) {
- return findNonOpaqueByX(x, y, width, height, srcPixels);
- } else {
- return findNonOpaqueByY(x, y, width, height, srcPixels);
- }
- }
- /*
- * 横向检测左右两侧边界
- */
- public int findNonOpaqueByX(int x, int y, int width, int height, int[] srcPixels) {
- int mode = OUTSIDE_MODE;
- //当前点左右两侧均有边界点出现,则认为当前点在内部或者边框中
- if(findNonOpaqueByXLeft(x, y, width, height, srcPixels) && findNonOpaqueByXRight(x, y, width, height, srcPixels)) {
- mode = INSIDE_MODE;
- }
- int pos = y*width+x;
- if(isMatch(pos, srcPixels)) {
- mode = EDGE_MODE;
- }
- return mode;
- }
- /*
- * 检测与当前点y坐标相同的左侧各点是否有边界存在
- */
- public boolean findNonOpaqueByXLeft(int x, int y, int width, int height, int[] srcPixels) {
- for(int i=0; i < x; i++) {
- int pos = y*width + i;
- if(isMatch(pos, srcPixels)) {
- return true;
- }
- }
- return false;
- }
- /*
- * 检测与当前点y坐标相同的右侧各点是否有边界存在
- */
- public boolean findNonOpaqueByXRight(int x, int y, int width, int height, int[] srcPixels) {
- for(int i= x+1; i < width; i++) {
- int pos = y*width + i;
- if(isMatch(pos, srcPixels)) {
- return true;
- }
- }
- return false;
- }
- /*
- * 纵向检测上下两侧的边界
- */
- public int findNonOpaqueByY(int x, int y, int width, int height, int[] srcPixels) {
- int mode = OUTSIDE_MODE;
- //当前点上下两侧均有边界点出现,则认为当前点在内部或者边框中
- if(findNonOpaqueByYTop(x, y, width, height, srcPixels) && findNonOpaqueByYBottom(x, y, width, height, srcPixels)) {
- mode = INSIDE_MODE;
- }
- int pos = y*width+x;
- if(isMatch(pos, srcPixels)) {
- mode = EDGE_MODE;
- }
- return mode;
- }
- /*
- * 检测与当前点x坐标相同的上方各点是否有边界存在
- */
- public boolean findNonOpaqueByYTop(int x, int y, int width, int height, int[] srcPixels) {
- for(int i=0; i < y; i++) {
- int pos = i*width + x;
- if(isMatch(pos, srcPixels)) {
- return true;
- }
- }
- return false;
- }
- /*
- * 检测与当前点x坐标相同的下方各点是否有边界存在
- */
- public boolean findNonOpaqueByYBottom(int x, int y, int width, int height, int[] srcPixels) {
- for(int i=y+1; i < height; i++) {
- int pos = i*width + x;
- if(isMatch(pos, srcPixels)) {
- return true;
- }
- }
- return false;
- }
- public boolean isMatch(int pos, int[]srcPixels) {
- int color = srcPixels[pos];
- int alpha = Color.alpha(color);
- //检测是否是边界,针对背景图片选用透明度进行过滤
- if(alpha >= 94 && alpha < 255) {
- return true;
- }
- return false;
- }
- /**
- * 图片效果叠加
- * @param bmp 要裁剪的图片
- * @param filter 边框
- * @return
- */
- public Bitmap overlay(Bitmap bmp, Bitmap filter)
- {
- int width = bmp.getWidth();
- int height = bmp.getHeight();
- Bitmap overlay = filter;
- Bitmap bitmap = Bitmap.createBitmap(width, height, Config.ARGB_4444);
- bitmap.setHasAlpha(true);
- // 对边框图片进行缩放
- int w = overlay.getWidth();
- int h = overlay.getHeight();
- float scaleX = width * 1F / w;
- float scaleY = height * 1F / h;
- Matrix matrix = new Matrix();
- matrix.postScale(scaleX, scaleY);
- Bitmap overlayCopy = Bitmap.createBitmap(overlay, 0, 0, w, h, matrix, true);
- int[] srcPixels = new int[width * height];
- int[] layPixels = new int[width * height];
- bmp.getPixels(srcPixels, 0, width, 0, 0, width, height);
- overlayCopy.getPixels(layPixels, 0, width, 0, 0, width, height);
- int pos = 0;
- for (int i = 0; i < height; i++)
- {
- for (int k = 0; k < width; k++)
- {
- pos = i * width + k;
- int mode = findNonOpaque(k, i, width, height, layPixels);
- if(mode == INSIDE_MODE) {
- srcPixels[pos] = srcPixels[pos];
- continue;
- } else if(mode == EDGE_MODE){
- srcPixels[pos] = layPixels[pos];
- } else{
- srcPixels[pos] = 0;
- continue;
- }
- }
- }
- bitmap.setPixels(srcPixels, 0, width, 0, 0, width, height);
- return bitmap;
- }
- }
- package com.example.test_filter;
- import android.os.AsyncTask;
- import android.os.Bundle;
- import android.app.Activity;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.widget.ImageView;
- public class MainActivity extends Activity {
- ImageView filter;
- AlphaFilter alphaFilter;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- filter = (ImageView) findViewById(R.id.filter);
- alphaFilter = new AlphaFilter();
- }
- @Override
- protected void onResume() {
- Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.album_photo_0);
- Bitmap frame = BitmapFactory.decodeResource(getResources(), R.drawable.first_album_frame);
- new BitmapFilter().execute(bitmap, frame);
- super.onResume();
- }
- class BitmapFilter extends AsyncTask<Bitmap, Bitmap, Bitmap> {
- @Override
- protected Bitmap doInBackground(Bitmap... params) {
- Bitmap bitmap = alphaFilter.overlay(params[0], params[1]);
- return bitmap;
- }
- @Override
- protected void onPostExecute(Bitmap result) {
- filter.setImageBitmap(result);
- super.onPostExecute(result);
- }
- }
- }