图片压缩:
原理:
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>