Android仿微信图片编辑处理:文字,马赛克,裁剪,涂鸦,旋转图片等

如图:

这个项目实现了微信图片编辑处理的关键功能,如给一张图片添加文字,打上马赛克,裁剪图片,在图片上手势涂鸦。引用了kareluo的Imaging库,但是kareluo的Imaging库示例代码有两个遗留问题需要重新解决:

1,它是用kotlin写的,我重新把kotlin代码部分用Java写了一遍。

2,kareluo的Imaging库中,编辑图片的IMGEditActivity接受两种传入的资源路径类型:asset和file。Android 4.4以下可以直接获取再拼装。但在高版本(大于4.4,API19)就不好办,且在大于4.4版本的机器上,用相册选择器选中的图片资源是以content://开头表示的,这需要把content://这样的路径重新转为file传过去。

我把上述两个问题解决后写了简单的测试:

package zhangphil.app;import android.annotation.TargetApi;import android.content.ContentResolver;import android.content.ContentUris;import android.content.Context;import android.content.Intent;import android.database.Cursor;import android.graphics.Bitmap;import android.net.Uri;import android.os.Build;import android.os.Environment;import android.provider.DocumentsContract;import android.provider.MediaStore;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import java.io.File;import me.kareluo.imaging.IMGEditActivity;public class MainActivity extends AppCompatActivity {    public static final int REQ_SELECT_PHOTO = 0xf0a;    private Bitmap avatarBitMap = null;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                seleteImg();            }        });    }    private void seleteImg() {        Intent intent = new Intent();        intent.setType("image/*");        intent.setAction(Intent.ACTION_GET_CONTENT);        startActivityForResult(intent, REQ_SELECT_PHOTO);    }    @Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        switch (requestCode) {            case REQ_SELECT_PHOTO: {                // 选取照片。                if (resultCode == RESULT_OK && data != null) {                    try {                        avatarBitMap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), data.getData());                        //此处获得了Bitmap图片,可以用作设置头像等等。                    } catch (Exception e) {                        e.printStackTrace();                    }                    Intent intent = new Intent(this, IMGEditActivity.class);                    try {                        String uri_path = getFilePathByUri(this, data.getData());                        Uri uri = Uri.fromFile(new File(uri_path));                        System.out.println(uri.toString());                        intent.putExtra(IMGEditActivity.EXTRA_IMAGE_URI, uri);                        //intent.putExtra(IMGEditActivity.EXTRA_IMAGE_SAVE_PATH,);                        startActivity(intent);                    } catch (Exception e) {                        e.printStackTrace();                    }                }                break;            }            default:                break;        }    }    @TargetApi(19)    public static String getFilePathByUri(Context context, Uri uri) {        String path = null;        // 以 file:// 开头的        if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {            path = uri.getPath();            return path;        }        // 以 content:// 开头的,比如 content://media/extenral/images/media/17766        if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme()) && Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {            Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.Media.DATA}, null, null, null);            if (cursor != null) {                if (cursor.moveToFirst()) {                    int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);                    if (columnIndex > -1) {                        path = cursor.getString(columnIndex);                    }                }                cursor.close();            }            return path;        }        // 4.4及之后的 是以 content:// 开头的,比如 content://com.android.providers.media.documents/document/image%3A235700        if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme()) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {            if (DocumentsContract.isDocumentUri(context, uri)) {                if (isExternalStorageDocument(uri)) {                    // ExternalStorageProvider                    final String docId = DocumentsContract.getDocumentId(uri);                    final String[] split = docId.split(":");                    final String type = split[0];                    if ("primary".equalsIgnoreCase(type)) {                        path = Environment.getExternalStorageDirectory() + "/" + split[1];                        return path;                    }                } else if (isDownloadsDocument(uri)) {                    // DownloadsProvider                    final String id = DocumentsContract.getDocumentId(uri);                    final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"),                            Long.valueOf(id));                    path = getDataColumn(context, contentUri, null, null);                    return path;                } else if (isMediaDocument(uri)) {                    // MediaProvider                    final String docId = DocumentsContract.getDocumentId(uri);                    final String[] split = docId.split(":");                    final String type = split[0];                    Uri contentUri = null;                    if ("image".equals(type)) {                        contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;                    } else if ("video".equals(type)) {                        contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;                    } else if ("audio".equals(type)) {                        contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;                    }                    final String selection = "_id=?";                    final String[] selectionArgs = new String[]{split[1]};                    path = getDataColumn(context, contentUri, selection, selectionArgs);                    return path;                }            }        }        return null;    }    public static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {        Cursor cursor = null;        String column = MediaStore.Images.Media.DATA;        String[] projection = {column};        try {            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs, null);            if (cursor != null && cursor.moveToFirst()) {                int index = cursor.getColumnIndexOrThrow(column);                return cursor.getString(index);            }        } finally {            if (cursor != null)                cursor.close();        }        return null;    }    /**     * @param uri The Uri to check.     * @return Whether the Uri authority is ExternalStorageProvider.     */    public static boolean isExternalStorageDocument(Uri uri) {        return "com.android.externalstorage.documents".equals(uri.getAuthority());    }    /**     * @param uri The Uri to check.     * @return Whether the Uri authority is DownloadsProvider.     */    public static boolean isDownloadsDocument(Uri uri) {        return "com.android.providers.downloads.documents".equals(uri.getAuthority());    }    /**     * @param uri The Uri to check.     * @return Whether the Uri authority is MediaProvider.     */    public static boolean isMediaDocument(Uri uri) {        return "com.android.providers.media.documents".equals(uri.getAuthority());    }    /**     * @param uri The Uri to check.     * @return Whether the Uri authority is Google Photos.     */    public static boolean isGooglePhotosUri(Uri uri) {        return "com.google.android.apps.photos.content".equals(uri.getAuthority());    }}

亲测在Android8.0上正常。

完整可运行的项目已经整理出来,上传到github:https://github.com/zhangphil/WeiXinPictureTool

更多相关文章

  1. android 背景图片滚动
  2. android加载大图推荐框架LargeImageView及所遇问题——部分机型
  3. TextView(文本框)详解
  4. Android(安卓)OOM 排查与解决——图片加载优化
  5. APP瘦身这一篇就够了
  6. 【Android】Android实现自定义带文字和图片的Button
  7. [置顶] 我的Android进阶之旅------>Android疯狂连连看游戏的实现
  8. ffmpeg 移植到 android 并使用
  9. Android(安卓)图片Bitmap保存到内存卡

随机推荐

  1. SQL Server 2012 安全概述
  2. SQL数据库存储过程示例解析
  3. sqlserver还原数据库的时候出现提示无法
  4. SQL Server评估期已过问题的解决方法
  5. SQL附加数据库失败问题的解决方法
  6. SQL(MSSQLSERVER)服务启动错误代码3414的
  7. SQL语句性能优化(续)
  8. SQL Server数据类型转换方法
  9. 实例讲解sql server排名函数DENSE_RANK的
  10. sql server如何利用开窗函数over()进行分