图片加水印

我尝试了两种实现水印的方式

1、一个轻量级是我文字和图片水印框架

2、通过Canvas绘制水印

轻量级的我就不做笔记了,因为很简单就能实现你想要的水印,留意内存溢出就好。

下面主要记录下第二种方式加水印。
效果图如下:
图片加水印

图片加水印

正文

   //打开相机
    openCamera(this);
   /**
     * 打开相机
     */
    private void openCamera(Activity activity) {
        //獲取系統版本
        int currentapiVersion = android.os.Build.VERSION.SDK_INT;
        if (tvResult.getText().toString().length() > 0) {
            //执行拍照前,应该先判断SD卡是否存在
            String SDState = Environment.getExternalStorageState();
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);//"android.media.action.IMAGE_CAPTURE"
            if (SDState.equals(Environment.MEDIA_MOUNTED)) {

                File file = new File(FileUtil.getInstance().getImageFile( tvResult.getText().toString()));
                if (!file.exists()) {
                    file.mkdirs();
                }
                // 从文件中创建uri
                imageUri = Uri.fromFile(file);
                if (currentapiVersion < 24) {
                    intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                    intent.putExtra(FILE_PATH, file.getAbsoluteFile());
                } else {
                    //兼容android7.0 使用共享文件的形式
                    ContentValues contentValues = new ContentValues(1);
                    contentValues.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());
                    imageUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
                    intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                }
                startActivityForResult(intent, TAKE_PICTURE);
                Log.d("tag", "filepath = " + file.getAbsoluteFile());

            } else {
                Toast.makeText(this, getString(R.string.no_sd_card), Toast.LENGTH_LONG).show();
            }

        } else {

            Toast.makeText(this, "请先进行扫描或输入条形码", Toast.LENGTH_SHORT).show();
        }

    }

有人会说打开相机需要这么繁琐的代码吗?其实不需要,只是我的业务需要获取图片的路径,安卓碎片重,高版本的注重用户隐私的保护,相片就是用户隐私,所以需要区别对待。

获取图片路径:

 /**
     * 选择图片后,获取图片的路径
     *
     * @param requestCode
     * @param data
     */
    private void doPhoto(int requestCode, Intent data) {

        /**
         * 获取到的图片路径
         */
        String picPath = null;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");// HH:mm:ss
        // 获取当前时间
        Date date = new Date(System.currentTimeMillis());
        String dateStr = simpleDateFormat.format(date).toString();

        if (requestCode == TAKE_PICTURE) {
            String[] pojo = {MediaStore.Images.Media.DATA};
            Cursor cursor = getContentResolver().query(imageUri, pojo, null, null, null);
            if (cursor != null) {
                int columnIndex = cursor.getColumnIndexOrThrow(pojo[0]);
                cursor.moveToFirst();
                picPath = cursor.getString(columnIndex);
                cursor.close();
            } else {   //小米4上取不到图片路径
                try {
                    String[] strPaths = imageUri.toString().split("//");
                    picPath = strPaths[1];
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (picPath != null && (picPath.toLowerCase().endsWith(".png") || picPath.toLowerCase().endsWith(".jpg"))) {
                if (picPath == null || picPath.equals("")) {
                    Toast.makeText(this, "请重新拍照", Toast.LENGTH_SHORT).show();
                    return;
                }
                Toast.makeText(this, "pic = " + picPath, Toast.LENGTH_SHORT).show();
                Bitmap bm = null;
                try {
                    bm = FileUtil.getInstance().getImage(picPath, btnOpenCamera.getWidth(), btnOpenCamera.getHeight()); //获取限定宽高的bitmap,不限定则容易占用内存过大及OOM
                    if (bm == null) {
                        Toast.makeText(this, "请重新拍照", Toast.LENGTH_SHORT).show();
                    } else {
                        if (addWatermarkBitmap(bm, dateStr, btnOpenCamera.getWidth(), btnOpenCamera.getHeight())) {
                            Toast.makeText(this, "水印生成成功,文件已保存在 " + FileUtil.getInstance().IMAGE_PATH, Toast.LENGTH_SHORT).show();
                        }
                    }
                } catch (OutOfMemoryError e) {
                    e.printStackTrace();
                    if (bm != null) {
                        bm.recycle();
                    }
                    System.gc();
                }
            } else {
                Toast.makeText(this, "请重新拍照", Toast.LENGTH_LONG).show();
            }

        }
    }

然后调用加水印并保存

 private boolean addWatermarkBitmap(Bitmap bitmap, String str, int w, int h) {
        int destWidth = w;   //此处的bitmap已经限定好宽高
        int destHeight = h;
        Log.v("tag", "width = " + destWidth + " height = " + destHeight);

        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(1);
        textPaint.setAlpha(30);
//        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.save();
        canvas.restore();
        bitmap.recycle();
        btnOpenCamera.setImageBitmap(icon);
        return FileUtil.getInstance().saveMyBitmap(icon, tvResult.getText().toString()); //保存至文件
//        return true;
    }

我在这个重点是实现功能。over,完成。返回显示不难,难在难在加水印,然后保存,代码中也可以看出,添加的水印是自己在控件上方画中来的,然后更具控件的大小新生成一张图保存。主要是其中的一句话:

  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

那样先拍照的图片就在Canvas上面了,然后通过画笔Paint 在上面写字,保存图片:

   Bitmap icon = Bitmap.createBitmap(destWidth, destHeight, Bitmap.Config.ARGB_8888); //定好宽高的全彩bitmap
   Canvas canvas = new Canvas(icon);//初始化画布绘制的图像到icon上
        

文章中若有侵犯他*益,请及时通知我,我也只是做作笔记。