Android 使用Glide4.9 压缩并保存图片(jpg/png/gif)到本地


前言

项目中遇到,需要用户上传图片的场景。结果用户上传的、特别是拍摄后的图片,分辨率很大,长宽2000多3000甚至更高,一个图片5MB以上。 造成之后,从网络上加载这些图片,比较慢。
所以,不得不在上传前进行压缩后,再上传。


FileUtils 文件写入

/**
 * desc   : 
 * author : stone
 * email  : [email protected]
 * time   : 2019/5/29 9:19
 */
public class FileUtils {
  
    //获取指定文件目录的内部文件(路径)
    public static File getAlbumStorageDir(Context context, String directory) {
        File file;
        //有sdcard
        if (TextUtils.equals(Environment.getExternalStorageState(), Environment.MEDIA_MOUNTED)) {
            file = new File(Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_PICTURES), directory);
        } else {
            file = new File(context.getCacheDir(), directory);
        }

        if (!file.mkdirs()) {
            LogUtils.e("ExtensionSignActivity", "Directory not created");
        }
        return file;
    }

	//保存 jpg/png的 Bitmap
    public static String saveBmp2Local(Context context, Bitmap bmp, String picName, boolean isPng) {
        // 声明文件对象
        File file = null;
        // 声明输出流
        FileOutputStream outStream = null;

        try {
            file = new File(getAlbumStorageDir(context, LFConfig.IMG_DIRECTORY_NAME), picName + (isPng ? ".png" : ".jpg"));

            // 获得输出流,如果文件中有内容,追加内容
            outStream = new FileOutputStream(file);
            bmp.compress(isPng ? Bitmap.CompressFormat.PNG : Bitmap.CompressFormat.JPEG, 90, outStream);
        } catch (Exception e) {
            e.getStackTrace();
        } finally {
            try {
                if (outStream != null) {
                    outStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (file != null) {
            return file.getPath();
        }
        return null;
    }

   //保存gif。使用nio写入
    public static String saveGif2Local(Context context, ByteBuffer byteBuffer, String picName) throws FileNotFoundException {
        // 声明文件对象
        File file = null;
        // 声明输出流
        FileOutputStream outStream = null;
        FileChannel channel = null;
        try {
            file = new File(getAlbumStorageDir(context, LFConfig.IMG_DIRECTORY_NAME), picName + ".gif");

            // 获得输出流,如果文件中有内容,追加内容
            outStream = new FileOutputStream(file);
            channel = outStream.getChannel();
            //不能确定channel.write()能一次性写入buffer的所有数据
            //所以通过判断是否有余留循环写入
            while (byteBuffer.hasRemaining()) {
                channel.write(byteBuffer);
            }
        } catch (Exception e) {
            e.getStackTrace();
        } finally {
            try {
                if (outStream != null) {
                    outStream.close();
                }
                if (channel != null) {
                    channel.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if (file != null) {
            return file.getPath();
        }
        return null;
    }

    public static void deleteTempImages(Context context) {
        com.blankj.utilcode.util.FileUtils.deleteDir(getAlbumStorageDir(context, LFConfig.IMG_DIRECTORY_NAME));
    }
}


Glide加载并压缩

结合rxjava#Obserable,在子线程中, 对图片路径做map变换。
用glide加载图片变换为 Bitmap 或 GifDrawable。
订阅后,进行压缩并保存到本地。
关于gif压缩,暂未考虑。

/**
 * 存储到本地
 * @param item      原始图片路径
 */
private void compressAndSaveItem(final String item) {
     String[] strArray = item.split("\\.");
     if (strArray.length > 0 && strArray[strArray.length - 1].toLowerCase().equals("gif")) {//判断后缀名是否是gif
         Observable.just(item)
                 .observeOn(Schedulers.io()) //整体运行行在子线程
                 .compose(RxJavaUtil.rxLife(PublishProductActivity.this)) //结合了rxlifecycle库
                 .map(s -> GlideApp.with(PublishProductActivity.this)
                         .asGif()
                         .load(s)
                         .fitCenter()
                         .submit()//原始分辨率
//                            .submit(720, 1080) //自定义分辨率
                         .get())
                 .subscribe(result -> {
                     int pointIndex = item.lastIndexOf(".");
                     int nameStartIndex = item.lastIndexOf("/") + 1;
                     int end;
                     if (pointIndex < nameStartIndex) {
                         end = item.length();
                     } else {
                         end = pointIndex;
                     }
                     String fileName = item.substring(nameStartIndex, end);

                     String path = FileUtils.saveGif2Local(PublishProductActivity.this,
                             result.getBuffer(),  fileName + "_copy");
                     /*
                      * 有了保存的压缩图片路径 path
                      * do other thing
                      */
                 }, error -> {
                     error.printStackTrace();
                 });
     } else {
         Observable.just(item)
                 .observeOn(Schedulers.io())//整体运行行在子线程
                 .compose(RxJavaUtil.rxLife(PublishProductActivity.this)) //结合了rxlifecycle库
                 .map(s -> GlideApp.with(PublishProductActivity.this)
                         .asBitmap()
                         .load(s)
                         .fitCenter()
                         .submit()//原始分辨率
//                            .submit(720, 1080) //自定义分辨率
                         .get())
                 .subscribe(result -> {
                     int pointIndex = item.lastIndexOf(".");
                     int nameStartIndex = item.lastIndexOf("/") + 1;
                     int end;
                     if (pointIndex < nameStartIndex) {
                         end = item.length();
                     } else {
                         end = pointIndex;
                     }
                     String fileName = item.substring(nameStartIndex, end);
					
					//缩放bitmap都为原宽高的1/2
                     Bitmap scaleBitmap = Bitmap.createScaledBitmap(result,
                             result.getWidth() / 2, result.getHeight() / 2, true);

                     String path = FileUtils.saveBmp2Local(PublishProductActivity.this, scaleBitmap
                             , fileName + "_copy",
                             strArray[strArray.length - 1].toLowerCase().equals("png"));
                     /*
                      * 有了保存的压缩图片路径 path
                      * do other thing
                      */
                 }, error -> {
                     error.printStackTrace();
                 });
     }

遇到了gif图片不显示的问题

太坑了,GifDrawable # getBuffer(),用nio保存的逻辑是没问题的。结果保存后的图片,无法展示了,貌似可能是Glide的bug,只能 删除掉 gif相关的代码,不使用glide处理了。


发布了400 篇原创文章 · 获赞 364 · 访问量 162万+

猜你喜欢

转载自blog.csdn.net/jjwwmlp456/article/details/90668395