Bitmap图片压缩、图片副本及特效处理、画板功能(保存相册刷新)、刮刮奖

图片压缩:

原理:

1、获取图片宽高 和 手机屏幕宽高

2、获取图片宽与手机宽 ,图片高与手机高比值中较大的作为缩放比例,对图片进行压缩

代码如下:

public class BitmapUtil {

    public static Bitmap ratio(Resources res, int id, int pixelW, int pixelH) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true; //只加载图片宽高,不加载真正图片
        options.inPreferredConfig = Bitmap.Config.RGB_565;      //设置像素位数
        //预加载
//        Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);
        Bitmap bitmap = BitmapFactory.decodeResource(res, id, options);

        //取出原图宽高
        int originalW = options.outWidth;
        int originalH = options.outHeight;

        //采样inSampleSize :缩放比例 ==1 则原图 ==4 则 变为1/4
        options.inSampleSize = getSampleSize(originalW, originalH, pixelW, pixelH);
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeResource(res, id, options);      //真正进行加载
    }

    public static Bitmap ratio2(Resources res, int id) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true; //只加载图片宽高,不加载真正图片
        options.inPreferredConfig = Bitmap.Config.RGB_565;      //设置像素位数
        //预加载
//        Bitmap bitmap = BitmapFactory.decodeFile(filePath, options);
        Bitmap bitmap = BitmapFactory.decodeResource(res, id, options);

        //取出原图宽高
        int imgWidth = options.outWidth;
        int imgHeight = options.outHeight;

         //获取屏幕宽高
        Display dsp = getWindowManager().getDefaultDisplay();
        int screanWidth = dsp.getWidth();
        int screanHeight = dsp.getHeight();
        //计算缩放比例
        int scaleWidth = imgWidth / screanWidth;
        int scaleHeight = imgHeight / screanHeight;
        int scale = scaleHeight >= scaleWidth ? scaleHeight:scaleWidth;
        if(scale < 1)
            scale = 1;
        //设置缩放比例(scale应大于1缩放才能其作用)
        options.inSampleSize = scale;

        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeResource(res, id, options);      //真正进行加载
    }

    /**
     * 计算采样值
     * @param originalW
     * @param originalH
     * @param pixelW:屏幕宽度
     * @param pixelH:屏幕高度
     * @return
     */
    private static int getSampleSize(int originalW, int originalH, int pixelW, int pixelH) {
        int sampleSize = 1;    //默认原图比例
        //图片宽度大于图片高度,同时图片宽度大于屏幕宽度
        if (originalW > originalH && originalW > pixelW) {
            sampleSize = originalW / pixelW;
        } else if (originalW < originalH && originalH > pixelH) {
        //图片高度大于图片宽度,同时图片高度大于屏幕高度
            sampleSize = originalH / pixelH;
        }
        if (sampleSize <= 0) {
            sampleSize = 1;
        }
        return sampleSize;
    }
}

ublic class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ImageView imageView = (ImageView) findViewById(R.id.image_view);

        //需要捕获异常,防止OOM
        try {
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ico_smile);
            Log.i("TAG", "未裁剪前图片大小:" + bitmap.getByteCount());
            bitmap = BitmapUtil.ratio(getResources(), R.drawable.ico_smile, 2, 1);
//        bitmap = BitmapUtil.ratio(getResources(), R.drawable.ico_smile, imageView.getWidth(), imageView.getHeight());
            Log.i("TAG", "裁剪后图片大小:" + bitmap.getByteCount());

            //及时释放bitmap资源
            if (!bitmap.isRecycled()) {
                bitmap.recycle();
                bitmap = null;
            }
        } catch (OutOfMemoryError e) {
            e.printStackTrace();
        }
    }
}

图片副本: 

原理:

1、通过Paint 和 Canvas 重新绘制一个 Bitmap

2、通过Matrix类进行特效编辑

代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


   <ImageView
       android:id="@+id/original"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content" />

   <TextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:textSize="20sp"
       android:text="我是图片原图"/>

   <ImageView
       android:id="@+id/copy"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content" />

   <TextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:textSize="20sp"
       android:text="我是图片副本,并且做了处理"/>
</LinearLayout>

public class MainActivity extends AppCompatActivity {

	@BindView(R.id.original)
	ImageView mOriginal;
	@BindView(R.id.copy)
	ImageView mCopy;


	@Override
	protected void onCreate(@Nullable Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		ButterKnife.bind(this);

		//加载原图
		Bitmap btOriginal = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
		Log.e("MainActivity", "btCopy.getByteCount():" + btOriginal.getByteCount());

		//创建图片副本
		//创建一个和原图bitmap  相当于大小一样的白纸,没有内容
		Bitmap btCopy = Bitmap.createBitmap(btOriginal.getWidth(), btOriginal.getHeight(), btOriginal.getConfig());
		Log.e("MainActivity", "btCopy.getByteCount():" + btCopy.getByteCount());
		//创建画笔
		Paint paint = new Paint();
		//创建画板,并把btCopy铺到画板上
		Canvas canvas = new Canvas(btCopy);

		//作画,单纯复制未做修改
//		canvas.drawBitmap(btOriginal, new Matrix(), paint);

		//作画 ,并且修改
		Matrix matrix = new Matrix();
		
		//图片平移,不是控件平移
//		matrix.setTranslate(20,10);
		
		//缩放
//		matrix.setScale(2, 0.5f);
		
		//旋转
//		matrix.setRotate(45, btCopy.getWidth() / 2, btCopy.getHeight() / 2);
		
		//镜面效果(x轴翻转)
//		matrix.setScale(-1, 1);		// -1 表示方向改变  1 表示方向不变  2 的话是放大两倍
//		matrix.postTranslate(btCopy.getWidth(), 0);		//翻转后移动回来
		
		//倒影效果(y轴翻转)
		matrix.setScale(1,-1);
		matrix.postTranslate(0, btCopy.getHeight());		//翻转后移动回来
		
		canvas.drawBitmap(btOriginal, matrix, paint);

		mOriginal.setImageBitmap(btOriginal);
		mCopy.setImageBitmap(btCopy);
    }
}

 画板:

原理:

1、构建一个bitmap,里面什么都没有,只设置了大小和config

2、设置好 Paint 和Canva,设置好画板背景

3、对要添加bitmap的IamgeView设置 触摸监听,ACTION_MOVE 时进行作画即可

4、图片压缩保存,要手动刷新媒体广播,相册才有图片

 代码如下:

public class MainActivity extends AppCompatActivity {

	@BindView(R.id.iv)
	ImageView mIv;
	@BindView(R.id.cloroBlue)
	Button mCloroBlue;
	@BindView(R.id.cloroRed)
	Button mCloroRed;
	@BindView(R.id.overstriking)
	Button mOverstriking;
	@BindView(R.id.save)
	Button mSave;

	private PermissionListener mListener;

	private float mStartX;    //起始点
	private float mStartY;    //起始点

	private Paint mPaint;        //画笔
	private Canvas mCanvas;        //画板
	private Bitmap mBitmap;


	@Override
	protected void onCreate(@Nullable Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		ButterKnife.bind(this);

		Bitmap.Config config = Bitmap.Config.ARGB_8888;        //设置像素位

		//设置Bitmap 大小
		mBitmap = Bitmap.createBitmap(DisplayUtils.dip2px(getApplicationContext(), 300),    //设置Bitmap 大小
				DisplayUtils.dip2px(getApplicationContext(), 400), config);
		//必须要先设置一下,否则ImageView 没有宽高
		mIv.setImageBitmap(mBitmap);
		mPaint = new Paint();
		mCanvas = new Canvas(mBitmap);
		mCanvas.drawRGB(255,255,255);		//设置背景为白色

		mIv.setOnTouchListener(new View.OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch (event.getAction()) {
					case MotionEvent.ACTION_DOWN:
						//获取作画起始坐标
						mStartX = event.getX();
						mStartY = event.getY();
						break;
					case MotionEvent.ACTION_MOVE:
						//得到结束坐标
						float endX = event.getX();
						float endY = event.getY();
						mCanvas.drawLine(mStartX, mStartY, endX, endY, mPaint);
						mIv.setImageBitmap(mBitmap);

						//将上次的结束坐标作为下次的开始坐标
						mStartX = endX;
						mStartY = endY;
						break;
					case MotionEvent.ACTION_UP:
						break;
				}
				return true;
			}
		});
	}

	/**
	 * 权限请求
	 */
	public void requestRunTimePermission(String[] permissions, PermissionListener listener) {
		mListener = listener;
		List<String> permissionList = new ArrayList<>();
		for (String permission : permissions) {
			if (ActivityCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {//检测当前权限是否已经被允许
				permissionList.add(permission);//没有则添加进集合
			}
		}
		if (!permissionList.isEmpty()) {//检测权限集合中是否有未申请的权限
			ActivityCompat.requestPermissions(this, permissionList.toArray(new String[permissionList.size()]), 1);
		} else {
			//所有权限都通过了
			mListener.onGranted();
		}
	}

	@Override
	public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
		super.onRequestPermissionsResult(requestCode, permissions, grantResults);
		switch (requestCode) {
			case 1:
				if (grantResults.length > 0) {
					List<String> deniedPermission = new ArrayList<>();
					for (int i = 0; i < grantResults.length; i++) {
						int grantResult = grantResults[i];
						String permission = permissions[i];
						if (grantResult != PackageManager.PERMISSION_GRANTED) {
							deniedPermission.add(permission);
						}
					}

					if (!deniedPermission.isEmpty()) {
						mListener.onDenied(deniedPermission);
					} else
						mListener.onGranted();
				}
				break;
			default:
				break;
		}
	}

	@OnClick({R.id.cloroBlue, R.id.cloroRed, R.id.overstriking, R.id.save})
	public void onViewClicked(View view) {
		switch (view.getId()) {
			case R.id.cloroBlue:
				mPaint.setColor(Color.BLUE);
				break;
			case R.id.cloroRed:
				mPaint.setColor(Color.RED);
				break;
			case R.id.overstriking:
				mPaint.setStrokeWidth(20);        //设置画笔粗细
				break;
			case R.id.save:
				requestRunTimePermission(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}, new PermissionListener() {
					@Override
					public void onGranted() {
						save();
					}

					@Override
					public void onDenied(List<String> deniedPermission) {
						Toast.makeText(MainActivity.this, "need permission", Toast.LENGTH_SHORT).show();
					}
				});
				break;
		}
	}

	private void save() {
		File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "test");
		if (!dir.exists()) {
			dir.mkdirs();
		}
		File file = new File(dir, "my_draw.png");        //PNG:图片质量高 jpg:图片质量一般
		try {
			FileOutputStream fos = new FileOutputStream(file);
			//把图片压缩到本地
			mBitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);			//CompressFormat:图片格式 quality:图片质量0-100
			Toast.makeText(MainActivity.this, "保存成功", Toast.LENGTH_SHORT).show();

			//手动发送广播通知相册刷新
			Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
			Uri uri = Uri.fromFile(file);
			intent.setData(uri);
			sendBroadcast(intent);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity"
    android:background="#000000">

   <ImageView
       android:id="@+id/iv"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_gravity="center_horizontal"/>

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="horizontal">

      <Button
          android:id="@+id/cloroBlue"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="蓝色"/>

      <Button
          android:id="@+id/cloroRed"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="红色"/>


      <Button
          android:id="@+id/overstriking"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="加粗"/>

      <Button
          android:id="@+id/save"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="保存"/>
   </LinearLayout>
</LinearLayout>

刮刮奖:

原理:

1、 两张图片重叠

2、为表面的图片设置副本,并且监听触摸响应,然后将用户触摸位置像素设为透明

代码如下:

public class MainActivity extends AppCompatActivity {

	@BindView(R.id.ivCover)
	ImageView mIvCover;

	private Paint mPaint;
	private Canvas mCanvas;
	private int r = 5;

	@Override
	protected void onCreate(@Nullable Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		ButterKnife.bind(this);

		//创建图片副本
		final Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
		final Bitmap bitmapCopy = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());

		//画出图片副本
		mPaint = new Paint();
		mCanvas = new Canvas(bitmapCopy);
		mCanvas.drawBitmap(bitmap, new Matrix(), mPaint);
		mIvCover.setImageBitmap(bitmap);

		mIvCover.setOnTouchListener(new View.OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				switch (event.getAction()) {
					case MotionEvent.ACTION_MOVE:
						int x = (int) event.getX();
						int y = (int) event.getY();
						//已 r 为半径,透明圆内像素
						for (int i = -r; i < r; i++) {
							for (int j = -r; j < r; j++) {
								//判断范围是否在圆外,三角函数
								if (Math.sqrt(i * i + j * j) <= r) {
									//是否超图图片边界
									if (x + i < bitmapCopy.getWidth() && y + j < bitmapCopy.getHeight() && x + i >= 0 && y + j >= 0) {
										//将对应坐标像素,设置为透明
										bitmapCopy.setPixel(x + i, y + j, Color.TRANSPARENT);
									}
								}
							}
						}
						mIvCover.setImageBitmap(bitmapCopy);
						break;
				}
				return true;
			}
		});
	}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

   <TextView
       android:layout_width="40dp"
       android:layout_height="40dp"
       android:layout_gravity="center_horizontal"
       android:background="#000000"
       android:layout_centerInParent="true"
       android:text="谢谢惠顾"
       android:textColor="#ffffffff"
       android:gravity="center"/>

   <ImageView
       android:id="@+id/ivCover"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_gravity="center_horizontal"
       android:layout_centerInParent="true"/>

</RelativeLayout>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值