Android 图片拼接

under Android  tag     Published on October 8th , 2021 at 05:49 pm

  • 确定两张图测试。(直接看 获取文件字节输入流
  • 利用 PictureSelector 选两张以上的图(本篇讲的是两张图)。这里不详细讲 PictureSelector ,附上链接里讲的很清楚。主要是在 onActivityResult 获取 List<LocalMedia> result。

写的工具类是操作重要的地方,如何获取文件字节输入流不限。


获取图片 URI

在不裁剪、不压缩,单纯将两张图拼一起的情况下,只需要获取原始路径。LocalMedia 类下的 path 为原始路径,path 返回的是包含 content:// scheme 的字符串。

Uri.parse(result.get(0).getPath());

获取文件字节输入流

在读取文件之前需要获取文件的绝对路径,文件不存在或是路径为文件夹路径或是因为其他原因无法打开文件,都会抛出 FileNotFoundException 异常。

new FileInputStream(PictureUtils.uriToFilePath(this, Uri.parse(result.get(0).getPath())))

// 如果只是想测试两张图拼接不去选择
new FileInputStream(PictureUtils.uriToFilePath(new File("图片文件的绝对路径")) // 文件路径
getApplicationContext().getResources().openRawResource(R.drawable.ic_launcher) // 资源文件

PictureUtils 类

// 图片Uri 转 FilePath
public static String uriToFilePath(Context context, Uri uri) {
        if (uri == null) return null;
        final String scheme = uri.getScheme();
        String filePath = null;
        if (scheme == null) {
            filePath = uri.getPath();
        } else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
            filePath = uri.getPath();
        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
            Cursor cursor = null;
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null);
            }
            if (cursor != null) {
                if (cursor.moveToFirst()) {
                    int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
                    if (index > -1) {
                        filePath = cursor.getString(index);
                    }
                }
                cursor.close();
            }
        }
        return filePath;
    }

创建 Bitmap

将输入流传递给 BitmapFactory.decodeStream(InputStream is) 方法,创建 Bitmap。

Bitmap bitmap1 = BitmapFactory.decodeStream(new FileInputStream(PictureUtils.uriToFilePath(this, Uri.parse(result.get(0).getPath()))));
Bitmap bitmap2 = BitmapFactory.decodeStream(new FileInputStream(PictureUtils.uriToFilePath(this, Uri.parse(result.get(1).getPath()))));

合成新的 Bitmap

PictureUtils 类

// 合成一张照片
public static Bitmap newBitmap(Bitmap bmp1, Bitmap bmp2) {
    Bitmap bitmap;
    int width = bmp1.getWidth();
    if (bmp2.getWidth() != width) {
        int h2 = bmp2.getHeight() * width / bmp2.getWidth();
        bitmap = Bitmap.createBitmap(width, bmp1.getHeight() + h2, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Bitmap newSizeBmp2 = resizeBitmap(bmp2, width, h2);
        canvas.drawBitmap(bmp1, 0, 0, null);
        canvas.drawBitmap(newSizeBmp2, 0, bmp1.getHeight(), null);
    } else {
        bitmap = Bitmap.createBitmap(width, bmp1.getHeight() + bmp2.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        canvas.drawBitmap(bmp1, 0, 0, null);
        canvas.drawBitmap(bmp2, 0, bmp1.getHeight(), null);
    }
    return bitmap;
}

// 规范两张照片尺寸
private static Bitmap resizeBitmap(Bitmap bitmap, int newWidth, int newHeight) {
    float scaleWidth = ((float) newWidth) / bitmap.getWidth();
    float scaleHeight = ((float) newHeight) / bitmap.getHeight();
    Matrix matrix = new Matrix();
    matrix.postScale(scaleWidth, scaleHeight);
    return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}

保存 Bitmap

PictureUtils 类

public static void saveBitmap(Context context, Bitmap bitmap) {
        String filePath = context.getFilesDir().getAbsolutePath() + "/longPicture";
        String fileName = System.currentTimeMillis() + ".jpg";
        File file = new File(filePath);
        boolean is = true;
        if (!file.exists()) is = file.mkdirs();
        if (!is) return;
        File f = new File(filePath, fileName);
        Log.e("TAG", "路径: " + f.getAbsolutePath());
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(f);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
        try {
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            // 将图片保存到系统相册
            MediaStore.Images.Media.insertImage(context.getContentResolver(), f.getAbsolutePath(), fileName, null);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

使用

我利用了 PictureSelector ,所以这部分代码 resultonActivityResult 返回的数据,为的是获取文件字节输入流,可以使用不需要 result 的方法。

try {
    Bitmap bitmap1 = BitmapFactory.decodeStream(new FileInputStream(PictureUtils.uriToFilePath(this, Uri.parse(result.get(0).getPath()))));
    Bitmap bitmap2 = BitmapFactory.decodeStream(new FileInputStream(PictureUtils.uriToFilePath(this, Uri.parse(result.get(1).getPath()))));
    Bitmap newBmp = PictureUtils.newBitmap(bitmap1, bitmap2);
    binding.iv.setImageBitmap(newBmp);
    PictureUtils.saveBitmap(this, newBmp);
} catch (FileNotFoundException e) {
    e.printStackTrace();
}

本文由 surface 创作,采用 知识共享署名4.0 国际许可协议进行许可,转载前请务必署名
  文章最后更新时间为:October 9th , 2021 at 11:29 am
分享到:Twitter  Weibo  Facebook