天天看点

android上传图片压缩图片大小

现在手机拍照都是好几兆,直接把原图上传到服务器,对于用户来说,直接就崩溃了,在有WiFi的情况下还好。但当其他用户查看列表时,看一会估计手机都得欠费了。所以在上传图片的时候,要对图片进行压缩。

注意:这里的压缩是指质量压缩,不是尺寸压缩。

比如当我们拍一张照片,要上传到服务器。我们需要先把这个照片,读到内存中,然后进行压缩,最后把压缩后的文件输出。

关于图片的内存了,怎么加载节省内存了,这里就不说了

推荐读者看看这篇文章:http://www.jcodecraeer.com/plus/view.php?aid=3874

以下代码来自ImageLoader框架,我把它decoder图片的代码抽了出来,稍作了一下修改

使用代码

public class MainActivity extends AppCompatActivity {


    String imagePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "123.jpg";
    String outPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + "new.jpg";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final ImageDecoder decoder = new ImageDecoder();
        final ImageSize imageSize = new ImageSize(, );
        final File file = new File(imagePath);
        if (file.exists()) {
            new Thread() {
                @Override
                public void run() {
                    super.run();
                    try {
                        Bitmap bitmap = decoder.decode(file, imageSize);
                        ImageUtils.compressBmpToFile(bitmap, new File(outPath));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }.start();
        }
    }
}
           

ImageDecoder 类负责把图片decode成目标大小,然后ImageUtils.compressBmpToFile对图片进行压缩,压缩完之后(压缩到100K以内),输出文件

ImageDecoder.java

public class ImageDecoder {

    public Bitmap decode(File file, ImageSize targetSize) throws IOException {
        Bitmap decodedBitmap;
        ImageFileInfo imageInfo;

        InputStream imageStream = getImageStream(file);
        try {
            imageInfo = defineImageSizeAndRotation(imageStream, file);
            imageStream = resetStream(imageStream, file);
            BitmapFactory.Options decodingOptions = prepareDecodingOptions(imageInfo.imageSize, targetSize);
            decodedBitmap = BitmapFactory.decodeStream(imageStream, null, decodingOptions);
        } finally {
            closeSilently(imageStream);
        }

        if (decodedBitmap != null) {
            decodedBitmap = considerExactScaleAndOrientatiton(decodedBitmap, targetSize, imageInfo.exif.rotation,
                    imageInfo.exif.flipHorizontal);
        }
        return decodedBitmap;
    }

    private InputStream getImageStream(File res) throws IOException{
        return new FileInputStream(res);
    }

    /**
     * 定义image的大小和旋转的度
     */
    protected ImageFileInfo defineImageSizeAndRotation(InputStream imageStream, File file)
            throws IOException {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(imageStream, null, options);

        ExifInfo exif;
        if (canDefineExifParams(options.outMimeType)) {
            exif = defineExifOrientation(file);
        } else {
            exif = new ExifInfo();
        }
        return new ImageFileInfo(new ImageSize(options.outWidth, options.outHeight, exif.rotation), exif);
    }

    private boolean canDefineExifParams(String mimeType) {
        return "image/jpeg".equalsIgnoreCase(mimeType);
    }

    protected ExifInfo defineExifOrientation(File imageUri) {
        int rotation = ;
        boolean flip = false;
        try {
            ExifInterface exif = new ExifInterface(imageUri.getAbsolutePath());
            int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
            switch (exifOrientation) {
                case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
                    flip = true;
                case ExifInterface.ORIENTATION_NORMAL:
                    rotation = ;
                    break;
                case ExifInterface.ORIENTATION_TRANSVERSE:
                    flip = true;
                case ExifInterface.ORIENTATION_ROTATE_90:
                    rotation = ;
                    break;
                case ExifInterface.ORIENTATION_FLIP_VERTICAL:
                    flip = true;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    rotation = ;
                    break;
                case ExifInterface.ORIENTATION_TRANSPOSE:
                    flip = true;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    rotation = ;
                    break;
            }
        } catch (IOException e) {
            Log.w("decoder", "Can't read EXIF tags from file [%s]" + imageUri.getAbsolutePath());
        }
        return new ExifInfo(rotation, flip);
    }

    /**
     * 如果imageStream支持reset,则返回reset后的imageStream,否则返回 {@link #getImageStream(File)}
     */
    protected InputStream resetStream(InputStream imageStream, File res) throws IOException {
        //http://zhangbo-peipei-163-com.iteye.com/blog/2022460
        if (imageStream.markSupported()) {
            try {
                imageStream.reset();
                return imageStream;
            } catch (IOException ignored) {
            }
        }
        closeSilently(imageStream);
        return getImageStream(res);
    }

    /**
     * 返回计算好 simple size 的Option
     */
    protected BitmapFactory.Options prepareDecodingOptions(ImageSize imageSize, ImageSize targetSize) {
        int scale = ImageUtils.computeImageSampleSize(imageSize, targetSize);
        BitmapFactory.Options decodingOptions = new BitmapFactory.Options();
        decodingOptions.inSampleSize = scale;
        return decodingOptions;
    }

    protected Bitmap considerExactScaleAndOrientatiton(Bitmap subsampledBitmap, ImageSize targetSize,
                                                       int rotation, boolean flipHorizontal) {
        Matrix m = new Matrix();
        // 缩小到精确的大小,如果需要
        ImageSize srcSize = new ImageSize(subsampledBitmap.getWidth(), subsampledBitmap.getHeight(), rotation);
        float scale = ImageUtils.computeImageScale(srcSize, targetSize, false);
        if (Float.compare(scale, f) != ) {
            m.setScale(scale, scale);
        }
        // 翻转 bitmap 如果需要
        if (flipHorizontal) {
            m.postScale(-, );

        }
        // 选择 bitmap 如果需要
        if (rotation != ) {
            m.postRotate(rotation);
        }

        Bitmap finalBitmap = Bitmap.createBitmap(subsampledBitmap, , , subsampledBitmap.getWidth(), subsampledBitmap
                .getHeight(), m, true);
        if (finalBitmap != subsampledBitmap) {
            subsampledBitmap.recycle();
        }
        return finalBitmap;
    }

    protected static class ExifInfo {

        public final int rotation;
        public final boolean flipHorizontal;

        protected ExifInfo() {
            this.rotation = ;
            this.flipHorizontal = false;
        }

        protected ExifInfo(int rotation, boolean flipHorizontal) {
            this.rotation = rotation;
            this.flipHorizontal = flipHorizontal;
        }
    }

    protected static class ImageFileInfo {

        public final ImageSize imageSize;
        public final ExifInfo exif;

        protected ImageFileInfo(ImageSize imageSize, ExifInfo exif) {
            this.imageSize = imageSize;
            this.exif = exif;
        }
    }

    public static void closeSilently(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (Exception ignored) {
            }
        }
    }

}
           

ImageUtils .java

public class ImageUtils {
    private static final int DEFAULT_MAX_BITMAP_DIMENSION = ;

    private static ImageSize maxBitmapSize;

    static {
        int[] maxTextureSize = new int[];
        GLES10.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxTextureSize, );
        int maxBitmapDimension = Math.max(maxTextureSize[], DEFAULT_MAX_BITMAP_DIMENSION);
        maxBitmapSize = new ImageSize(maxBitmapDimension, maxBitmapDimension);
    }

    private ImageUtils() {
    }

    public static int computeImageSampleSize(ImageSize srcSize, ImageSize targetSize){
        final int srcWidth = srcSize.getWidth();
        final int srcHeight = srcSize.getHeight();
        final int targetWidth = targetSize.getWidth();
        final int targetHeight = targetSize.getHeight();

        int scale = ;
        scale = Math.min(srcWidth / targetWidth, srcHeight / targetHeight); // min
        if (scale < ) {
            scale = ;
        }
        scale = considerMaxTextureSize(srcWidth, srcHeight, scale, false);

        return scale;
    }

    /**
     * 如果宽度和高度/scale大于max texture size则继续缩小
     * @return sample size
     */
    private static int considerMaxTextureSize(int srcWidth, int srcHeight, int scale, boolean powerOf2) {
        final int maxWidth = maxBitmapSize.getWidth();
        final int maxHeight = maxBitmapSize.getHeight();
        while ((srcWidth / scale) > maxWidth || (srcHeight / scale) > maxHeight) {
            if (powerOf2) {
                scale *= ;
            } else {
                scale++;
            }
        }
        return scale;
    }

    public static float computeImageScale(ImageSize srcSize, ImageSize targetSize,
                                          boolean stretch) {
        final int srcWidth = srcSize.getWidth();
        final int srcHeight = srcSize.getHeight();
        final int targetWidth = targetSize.getWidth();
        final int targetHeight = targetSize.getHeight();

        final float widthScale = (float) srcWidth / targetWidth;
        final float heightScale = (float) srcHeight / targetHeight;

        final int destWidth;
        final int destHeight;
        if (widthScale < heightScale) {
            destWidth = targetWidth;
            destHeight = (int) (srcHeight / widthScale);
        } else {
            destWidth = (int) (srcWidth / heightScale);
            destHeight = targetHeight;
        }

        float scale = ;
        if ((!stretch && destWidth < srcWidth && destHeight < srcHeight) || (stretch && destWidth != srcWidth && destHeight != srcHeight)) {
            scale = (float) destWidth / srcWidth;
        }

        return scale;
    }

    public static void compressBmpToFile(Bitmap bmp, File file) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int options = ;
        bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
        while (baos.toByteArray().length /  > ) {
            options -= ;
            if (options > ) {
                baos.reset();
                bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
            } else {
                break;
            }
        }
        try {
            FileOutputStream fos = new FileOutputStream(file);
            byte[] bytes = baos.toByteArray();
            fos.write(bytes);
            fos.flush();
            fos.close();
            Log.i("tag", "file.length" + file.length());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
           

ImageSize.java

public class ImageSize {
    private final int width;
    private final int height;

    public ImageSize(int width, int height) {
        this.width = width;
        this.height = height;
    }
    public ImageSize(int width, int height, int rotation) {
        if (rotation %  == ) {
            this.width = width;
            this.height = height;
        } else {
            this.width = height;
            this.height = width;
        }
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }
}
           

github地址

https://github.com/wu-liao-de-ren-sheng/ImageCompress