本文要讲述的是如何给一张图片加上水印然后保存起来,原理很简单,首先要从本地或者拍照获得一张图片的路径,然后根据路径获取图片的Bitmap,再对Bitmap进行处理保存就可以实现。
文章最后附有上传至github的源码,具体操作步骤如下:
一、获取图片路径,原理就是根据隐示intent跳转至图片处理的activity,根据处理结果的result进行操作,如跳转至选择图片
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent, SELECT_PIC_BY_PICK_PHOTO);
具体细节可以看源码
二、获取对应bitmap,在不改变原始图片宽高比的情况下获取对应的Bitmap
public Bitmap getImage(String srcPath, int width, int height) {
BitmapFactory.Options newOpts = new BitmapFactory.Options();
//开始读入图片,此时把options.inJustDecodeBounds 设回true了
newOpts.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);//此时返回bm为空
newOpts.inJustDecodeBounds = false;
int w = newOpts.outWidth;
int h = newOpts.outHeight;
//缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
int be = 1;//be=1表示不缩放
if (w > h && w > width) {//如果宽度大的话根据宽度固定大小缩放
be = (int) (newOpts.outWidth / width);
} else if (w < h && h > height) {//如果高度高的话根据宽度固定大小缩放
be = (int) (newOpts.outHeight / height);
}
if (be <= 0) {
be = 1;
}
newOpts.inSampleSize = be;//设置缩放比例
//重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
if (bitmap != null) {
// return compressImage(bitmap);//压缩好比例大小后再进行质量压缩
return bitmap;//压缩好比例大小后再进行质量压缩
} else {
return null;
}
}
对bitmap的占用空间有要求则可以对齐进行压缩,比如存储不大于300K
public Bitmap compressImage(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int options = 100;
while (baos.toByteArray().length / 1024 > 300) { //循环判断如果压缩后图片是否大于300kb,大于继续压缩
baos.reset();//重置baos即清空baos
options -= 15;//每次都减少15
image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
return BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片
}
三、最后就是加上文字水印保存新的bitmap,关键代码如下:
private boolean addWatermarkBitmap(Bitmap bitmap,String str) {
int destWidth = bitmap.getWidth(); //此处的bitmap已经限定好宽高
int destHeight = bitmap.getHeight();
Bitmap icon = Bitmap.createBitmap(destWidth, destHeight, Bitmap.Config.ARGB_8888); //定好宽高的全彩bitmap
Canvas canvas = new Canvas(icon);//初始化画布绘制的图像到icon上
Paint photoPaint = new Paint(); //建立画笔
photoPaint.setDither(true); //获取跟清晰的图像采样
photoPaint.setFilterBitmap(true);//过滤一些
Rect src = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());//创建一个指定的新矩形的坐标
Rect dst = new Rect(0, 0, destWidth, destHeight);//创建一个指定的新矩形的坐标
canvas.drawBitmap(bitmap, src, dst, photoPaint);//将photo 缩放或则扩大到 dst使用的填充区photoPaint
Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG);//设置画笔
textPaint.setTextSize(destWidth/20);//字体大小
textPaint.setTextAlign(Paint.Align.CENTER);
textPaint.setTypeface(Typeface.DEFAULT_BOLD);//采用默认的宽度
textPaint.setAntiAlias(true); //抗锯齿
textPaint.setStrokeWidth(3);
textPaint.setAlpha(15);
textPaint.setStyle(Paint.Style.STROKE); //空心
textPaint.setColor(Color.WHITE);//采用的颜色
textPaint.setShadowLayer(1f, 0f, 3f, Color.LTGRAY);
// textPaint.setShadowLayer(3f, 1, 1,getResources().getColor(android.R.color.white));//影音的设置
canvas.drawText(str, destWidth/2, destHeight-45, textPaint);//绘制上去字,开始未知x,y采用那只笔绘制
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.restore();
imageView.setImageBitmap(icon);
return FileUtil.getInstance().saveMyBitmap(icon); //保存至文件
}
保存至文件的代码比较简单
利用Bitmap的方法 compress(CompressFormat format, int quality, OutputStream stream) ,将bitmap资源数据指向文件流即可