【问题标题】:How to compress image size?如何压缩图像大小?
【发布时间】:2013-09-03 21:52:42
【问题描述】:

我想使用 android camera api 以低分辨率捕获图像,但是当我捕获图像时,它将采用设备相机的默认分辨率。所以我想在捕获时以低分辨率或小尺寸捕获图像,或者我该如何压缩在android中将大图像变成小尺寸?

【问题讨论】:

标签: android android-camera android-camera-intent image-compression


【解决方案1】:

您可以使用捕获的图像创建位图,如下所示:

Bitmap bitmap = Bitmap.createScaledBitmap(capturedImage, width, height, true);

您可以在此处指定要设置为 ImageView 的位图的宽度和高度。您也可以根据设备的屏幕dpi设置高度和宽度,通过编程读取不同设备的屏幕dpi。

【讨论】:

  • 是的,但有没有不缩放的方法?它使图像看起来很奇怪
【解决方案2】:

使用 Compressor(图像压缩库)。 访问zetbaitsu/Compressor 获取代码和文档。

  1. 在 gradle 中添加依赖(应用级别)

    dependencies {
        implementation 'id.zelory:compressor:3.0.0'
    }
    
  2. 要压缩图像,请使用以下方法之一:

  • 压缩图像文件:

          val compressedImageFile = Compressor.compress(context, actualImageFile)
    
  • 将图像文件压缩为位图:

          val compressedImageFile = Compressor.compress(context, actualImageFile)
          val bitmap = BitmapFactory.decodeFile(compressedImageFile.path)
    

【讨论】:

  • 出现错误“原因:java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法'int android.graphics.Bitmap.getWidth()'”先生,请帮助我...
  • 我如何将这个库用于java?你能也写java的代码吗
  • 为 JAVA 实现 'id.zelory:compressor:2.1.1' github.com/zetbaitsu/Compressor/blob/master/README_v2.md
  • @ashishdhiman2007 - 异常显示为 Compressor 具有私有权限!
  • Bitmap 是浪费使用像 Google 的高级 WebP 这样的压缩格式。
【解决方案3】:

试试这个对我很有用。

private String decodeFile(String path) {
        String strMyImagePath = null;
        Bitmap scaledBitmap = null;

        try {
            // Part 1: Decode image
            Bitmap unscaledBitmap = ScalingUtilities.decodeFile(path, DESIREDWIDTH, DESIREDHEIGHT, ScalingLogic.FIT);

            if (!(unscaledBitmap.getWidth() <= 800 && unscaledBitmap.getHeight() <= 800)) {
                // Part 2: Scale image
                scaledBitmap = ScalingUtilities.createScaledBitmap(unscaledBitmap, DESIREDWIDTH, DESIREDHEIGHT, ScalingLogic.FIT);
            } else {
                unscaledBitmap.recycle();
                return path;
            }

            // Store to tmp file

            String extr = Environment.getExternalStorageDirectory().toString();
            File mFolder = new File(extr + "/myTmpDir");
            if (!mFolder.exists()) {
                mFolder.mkdir();
            }

            String s = "tmp.png";

            File f = new File(mFolder.getAbsolutePath(), s);

            strMyImagePath = f.getAbsolutePath();
            FileOutputStream fos = null;
            try {
                fos = new FileOutputStream(f);
                scaledBitmap.compress(Bitmap.CompressFormat.PNG, 70, fos);
                fos.flush();
                fos.close();
            } catch (FileNotFoundException e) {

                e.printStackTrace();
            } catch (Exception e) {

                e.printStackTrace();
            }

            scaledBitmap.recycle();
        } catch (Throwable e) {
        }

        if (strMyImagePath == null) {
            return path;
        }
        return strMyImagePath;

    }

实用类

public class ScalingUtilities {

    /**
     * Utility function for decoding an image resource. The decoded bitmap will
     * be optimized for further scaling to the requested destination dimensions
     * and scaling logic.
     *
     * @param res The resources object containing the image data
     * @param resId The resource id of the image data
     * @param dstWidth Width of destination area
     * @param dstHeight Height of destination area
     * @param scalingLogic Logic to use to avoid image stretching
     * @return Decoded bitmap
     */
    public static Bitmap decodeResource(Resources res, int resId, int dstWidth, int dstHeight,
            ScalingLogic scalingLogic) {
        Options options = new Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, options);
        options.inJustDecodeBounds = false;
        options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, dstWidth,
                dstHeight, scalingLogic);
        Bitmap unscaledBitmap = BitmapFactory.decodeResource(res, resId, options);

        return unscaledBitmap;
    }
    public static Bitmap decodeFile(String path, int dstWidth, int dstHeight,
            ScalingLogic scalingLogic) {
        Options options = new Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);
        options.inJustDecodeBounds = false;
        options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, dstWidth,
                dstHeight, scalingLogic);
        Bitmap unscaledBitmap = BitmapFactory.decodeFile(path, options);

        return unscaledBitmap;
    }

    /**
     * Utility function for creating a scaled version of an existing bitmap
     *
     * @param unscaledBitmap Bitmap to scale
     * @param dstWidth Wanted width of destination bitmap
     * @param dstHeight Wanted height of destination bitmap
     * @param scalingLogic Logic to use to avoid image stretching
     * @return New scaled bitmap object
     */
    public static Bitmap createScaledBitmap(Bitmap unscaledBitmap, int dstWidth, int dstHeight,
            ScalingLogic scalingLogic) {
        Rect srcRect = calculateSrcRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(),
                dstWidth, dstHeight, scalingLogic);
        Rect dstRect = calculateDstRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(),
                dstWidth, dstHeight, scalingLogic);
        Bitmap scaledBitmap = Bitmap.createBitmap(dstRect.width(), dstRect.height(),
                Config.ARGB_8888);
        Canvas canvas = new Canvas(scaledBitmap);
        canvas.drawBitmap(unscaledBitmap, srcRect, dstRect, new Paint(Paint.FILTER_BITMAP_FLAG));

        return scaledBitmap;
    }

    /**
     * ScalingLogic defines how scaling should be carried out if source and
     * destination image has different aspect ratio.
     *
     * CROP: Scales the image the minimum amount while making sure that at least
     * one of the two dimensions fit inside the requested destination area.
     * Parts of the source image will be cropped to realize this.
     *
     * FIT: Scales the image the minimum amount while making sure both
     * dimensions fit inside the requested destination area. The resulting
     * destination dimensions might be adjusted to a smaller size than
     * requested.
     */
    public static enum ScalingLogic {
        CROP, FIT
    }

    /**
     * Calculate optimal down-sampling factor given the dimensions of a source
     * image, the dimensions of a destination area and a scaling logic.
     *
     * @param srcWidth Width of source image
     * @param srcHeight Height of source image
     * @param dstWidth Width of destination area
     * @param dstHeight Height of destination area
     * @param scalingLogic Logic to use to avoid image stretching
     * @return Optimal down scaling sample size for decoding
     */
    public static int calculateSampleSize(int srcWidth, int srcHeight, int dstWidth, int dstHeight,
            ScalingLogic scalingLogic) {
        if (scalingLogic == ScalingLogic.FIT) {
            final float srcAspect = (float)srcWidth / (float)srcHeight;
            final float dstAspect = (float)dstWidth / (float)dstHeight;

            if (srcAspect > dstAspect) {
                return srcWidth / dstWidth;
            } else {
                return srcHeight / dstHeight;
            }
        } else {
            final float srcAspect = (float)srcWidth / (float)srcHeight;
            final float dstAspect = (float)dstWidth / (float)dstHeight;

            if (srcAspect > dstAspect) {
                return srcHeight / dstHeight;
            } else {
                return srcWidth / dstWidth;
            }
        }
    }

    /**
     * Calculates source rectangle for scaling bitmap
     *
     * @param srcWidth Width of source image
     * @param srcHeight Height of source image
     * @param dstWidth Width of destination area
     * @param dstHeight Height of destination area
     * @param scalingLogic Logic to use to avoid image stretching
     * @return Optimal source rectangle
     */
    public static Rect calculateSrcRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight,
            ScalingLogic scalingLogic) {
        if (scalingLogic == ScalingLogic.CROP) {
            final float srcAspect = (float)srcWidth / (float)srcHeight;
            final float dstAspect = (float)dstWidth / (float)dstHeight;

            if (srcAspect > dstAspect) {
                final int srcRectWidth = (int)(srcHeight * dstAspect);
                final int srcRectLeft = (srcWidth - srcRectWidth) / 2;
                return new Rect(srcRectLeft, 0, srcRectLeft + srcRectWidth, srcHeight);
            } else {
                final int srcRectHeight = (int)(srcWidth / dstAspect);
                final int scrRectTop = (int)(srcHeight - srcRectHeight) / 2;
                return new Rect(0, scrRectTop, srcWidth, scrRectTop + srcRectHeight);
            }
        } else {
            return new Rect(0, 0, srcWidth, srcHeight);
        }
    }

    /**
     * Calculates destination rectangle for scaling bitmap
     *
     * @param srcWidth Width of source image
     * @param srcHeight Height of source image
     * @param dstWidth Width of destination area
     * @param dstHeight Height of destination area
     * @param scalingLogic Logic to use to avoid image stretching
     * @return Optimal destination rectangle
     */
    public static Rect calculateDstRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight,
            ScalingLogic scalingLogic) {
        if (scalingLogic == ScalingLogic.FIT) {
            final float srcAspect = (float)srcWidth / (float)srcHeight;
            final float dstAspect = (float)dstWidth / (float)dstHeight;

            if (srcAspect > dstAspect) {
                return new Rect(0, 0, dstWidth, (int)(dstWidth / srcAspect));
            } else {
                return new Rect(0, 0, (int)(dstHeight * srcAspect), dstHeight);
            }
        } else {
            return new Rect(0, 0, dstWidth, dstHeight);
        }
    }

}

【讨论】:

  • 这里Scalling逻辑是什么意思?
  • 两种类型:FIX 用于拉伸图像以适合给定尺寸。 CROP 是因为它会从中心裁剪图像而不拉伸图像以适应给定的大小
  • @BirajZalavadia 这工作得很好,只是当我将图像保存在临时文件夹中时它会旋转。我怎样才能让它不旋转?
【解决方案4】:

你可以像这样压缩图像位图。

ByteArrayOutputStream out = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);

这里 100 是图像质量,您可以更改图像格式以获得低分辨率图像。

【讨论】:

  • 但是这种压缩方法对我不起作用..我正在以 JPEG 格式保存图像。是格式问题吗?
  • thnx..但我想要小尺寸的图片,我可以上传到服务器
  • 您可以根据@mAndroid 的回答设置高度和宽度。
  • 这对我也不起作用,你找到解决办法了吗?
  • 位图是浪费使用像谷歌的高级WebP这样的压缩格式,而不是。质量相同,但空间更小。
【解决方案5】:

我想你是在问关于缩小图像大小的问题:

    public Bitmap ShrinkBitmap(String file, int width, int height)
{
    BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
    bmpFactoryOptions.inJustDecodeBounds = true;
    Bitmap bitmap = BitmapFactory.decodeFile(file, bmpFactoryOptions);

    int heightRatio = (int) Math.ceil(bmpFactoryOptions.outHeight / (float) height);
    int widthRatio = (int) Math.ceil(bmpFactoryOptions.outWidth / (float) width);

    if(heightRatio > 1 || widthRatio > 1)
    {
        if(heightRatio > widthRatio)
        {
            bmpFactoryOptions.inSampleSize = heightRatio;
        }
        else
        {
            bmpFactoryOptions.inSampleSize = widthRatio;
        }
    }

    bmpFactoryOptions.inJustDecodeBounds = false;
    bitmap = BitmapFactory.decodeFile(file, bmpFactoryOptions);
    return bitmap;
}

【讨论】:

  • (方法名应该是驼峰式)
  • 位图是浪费使用像谷歌的高级WebP这样的压缩格式,而不是。质量相同,但空间更小。
【解决方案6】:

请查看我用于压缩图像的 compressImage 方法。

public static String compressImage(String imageUri, Activity activity) {
    String filename = "";
    try {
        String filePath = getRealPathFromURI(imageUri, activity);
        Bitmap scaledBitmap = null;

        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        Bitmap bmp = BitmapFactory.decodeFile(filePath, options);

        int actualHeight = options.outHeight;
        int actualWidth = options.outWidth;
        float maxHeight = 816.0f;
        float maxWidth = 612.0f;
        float imgRatio = actualWidth / actualHeight;
        float maxRatio = maxWidth / maxHeight;

        if (actualHeight > maxHeight || actualWidth > maxWidth) {
            if (imgRatio < maxRatio) {
                imgRatio = maxHeight / actualHeight;
                actualWidth = (int) (imgRatio * actualWidth);
                actualHeight = (int) maxHeight;
            } else if (imgRatio > maxRatio) {
                imgRatio = maxWidth / actualWidth;
                actualHeight = (int) (imgRatio * actualHeight);
                actualWidth = (int) maxWidth;
            } else {
                actualHeight = (int) maxHeight;
                actualWidth = (int) maxWidth;

            }
        }

        options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight);
        options.inJustDecodeBounds = false;
        options.inDither = false;
        options.inPurgeable = true;
        options.inInputShareable = true;
        options.inTempStorage = new byte[16 * 1024];

        try {
            bmp = BitmapFactory.decodeFile(filePath, options);
        } catch (OutOfMemoryError exception) {
            exception.printStackTrace();

        }
        try {
            scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888);
        } catch (OutOfMemoryError exception) {
            exception.printStackTrace();
        }

        float ratioX = actualWidth / (float) options.outWidth;
        float ratioY = actualHeight / (float) options.outHeight;
        float middleX = actualWidth / 2.0f;
        float middleY = actualHeight / 2.0f;

        Matrix scaleMatrix = new Matrix();
        scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);

        Canvas canvas;
        if (scaledBitmap != null) {
            canvas = new Canvas(scaledBitmap);
            canvas.setMatrix(scaleMatrix);
            canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));
        }


        ExifInterface exif;
        try {
            exif = new ExifInterface(filePath);

            int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);

            Matrix matrix = new Matrix();
            if (orientation == 6) {
                matrix.postRotate(90);

            } else if (orientation == 3) {
                matrix.postRotate(180);

            } else if (orientation == 8) {
                matrix.postRotate(270);

            }
            if (scaledBitmap != null) {
                scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        FileOutputStream out;
        filename = getFilename(activity);
        try {
            out = new FileOutputStream(filename);
            if (scaledBitmap != null) {
                scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

    return filename;
}

private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {
        final int heightRatio = Math.round((float) height / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }
    final float totalPixels = width * height;
    final float totalReqPixelsCap = reqWidth * reqHeight * 2;

    while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
        inSampleSize++;
    }

    return inSampleSize;
}

private static String getRealPathFromURI(String contentURI, Activity activity) {
    Uri contentUri = Uri.parse(contentURI);
    Cursor cursor = activity.getContentResolver().query(contentUri, null, null, null, null);
    if (cursor == null) {
        return contentUri.getPath();
    } else {
        cursor.moveToFirst();
        int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
        return cursor.getString(idx);
    }
}

【讨论】:

  • 你能简单解释一下你的代码吗@Neelesh Atale
  • 位图是浪费使用像谷歌的高级WebP这样的压缩格式,而不是。质量相同,但空间更小。
【解决方案7】:

您可以使用this awesome 库进行压缩。 在应用级gradel中添加依赖:

    dependencies {
    implementation 'id.zelory:compressor:3.0.0'
}

然后像这样压缩实际的图像文件:

val compressedImageFile = Compressor.compress(context, actualImageFile)

【讨论】:

  • 我可以在 Java 中使用它吗??
【解决方案8】:

你应该使用谷歌的原生图片格式WebP,它会shrink the image without losing quality。您可以在不损失质量的情况下压缩 80% 的图片。

您可以使用CompressFormat.WEBP 将任何位图编码为 WEBP 格式。

文件示例:

const int quality = 100; 
FileOutputStream out = new FileOutputStream(path); 
bitmap.compress(Bitmap.CompressFormat.WEBP, quality, out);
out.close(); 

【讨论】:

    【解决方案9】:

    试试这个:

    byte[] data = null;
    
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    bi.compress(Bitmap.CompressFormat.JPEG, 100, baos);
    
    data = baos.toByteArray();
    

    【讨论】:

      【解决方案10】:

      我就是这样解决这个问题的,以后我会改进代码

      protected Void doInBackground(byte[]... data) {
              FileOutputStream outStream = null;
      
              // Write to Internal Storage
              try {
                  File dir = new File (context.getFilesDir());
                  dir.mkdirs();
      
                  String fileName ="image.jpg";
                  File outFile = new File(dir, fileName);
                  outFile.setExecutable(true, false);
                  outFile.setWritable(true, false);
                  outStream = new FileOutputStream(outFile);
                  outStream.write(data[0]);
                  outStream.flush();
                  outStream.close();
                  InputStream in = new FileInputStream(context.getFilesDir()+"image.jpg");
                  Bitmap bm2 = BitmapFactory.decodeStream(in);
                  OutputStream stream = new FileOutputStream(String.valueOf(context.getFilesDir()+pathImage+"/"+idPicture+".jpg"));
                  bm2.compress(Bitmap.CompressFormat.JPEG, 50, stream);
                  stream.close();
                  in.close();
      
              } catch (FileNotFoundException e) {
                  e.printStackTrace();
              } catch (IOException e) {
                  e.printStackTrace();
              } finally {
              }
              return null;
          }
      

      【讨论】:

        【解决方案11】:

        使用这个类来压缩图片

        import android.content.Context
        import android.graphics.Bitmap
        import android.graphics.BitmapFactory
        import android.graphics.Canvas
        import android.graphics.Matrix
        import android.graphics.Paint
        import android.net.Uri
        import android.os.Environment
        import java.io.*
        
        
        class ImageFile(val uri: Uri, name: String) {
        
            val filename: String
        
            init {
                val file = File(Environment.getExternalStorageDirectory().toString() + "/Documents")
                if (!file.exists()) {
                    file.mkdirs()
                }
                val fileNoMedia = File(file.absolutePath + "/.nomedia")
                if (!fileNoMedia.exists())
                    fileNoMedia.createNewFile()
                if (name.toLowerCase().endsWith(".pdf")) {
                    filename = file.absolutePath + "/" + System.currentTimeMillis() + ".pdf"
                } else {
                    filename = file.absolutePath + "/" + System.currentTimeMillis() + ".jpg"
                }
            }
        
            @Throws(IOException::class)
            fun copyFileStream(context: Context, uri: Uri): String {
                if (filename.endsWith(".pdf") || filename.endsWith(".PDF")) {
                    var ins: InputStream? = null
                    var os: OutputStream? = null
                    try {
                        ins = context.getContentResolver().openInputStream(uri)
                        os = FileOutputStream(filename)
                        val buffer = ByteArray(1024)
                        var length: Int = ins.read(buffer)
                        while (length > 0) {
                            os.write(buffer, 0, length);
                            length = ins.read(buffer)
                        }
                    } catch (e: Exception) {
                        e.printStackTrace();
                    } finally {
                        ins?.close()
                        os?.close()
                    }
                } else {
                    var ins: InputStream? = null
                    var os: OutputStream? = null
                    try {
                        ins = context.getContentResolver().openInputStream(uri)
                        var scaledBitmap: Bitmap? = null
                        val options = BitmapFactory.Options()
                        options.inJustDecodeBounds = true
                        var bmp = BitmapFactory.decodeStream(ins, null, options)
                        var actualHeight = options.outHeight
                        var actualWidth = options.outWidth
        
                        //      max Height and width values of the compressed image is taken as 816x612
                        val maxHeight = 816.0f
                        val maxWidth = 612.0f
                        var imgRatio = (actualWidth / actualHeight).toFloat()
                        val maxRatio = maxWidth / maxHeight
        
                        //      width and height values are set maintaining the aspect ratio of the image
                        if (actualHeight > maxHeight || actualWidth > maxWidth) {
                            if (imgRatio < maxRatio) {
                                imgRatio = maxHeight / actualHeight
                                actualWidth = (imgRatio * actualWidth).toInt()
                                actualHeight = maxHeight.toInt()
                            } else if (imgRatio > maxRatio) {
                                imgRatio = maxWidth / actualWidth
                                actualHeight = (imgRatio * actualHeight).toInt()
                                actualWidth = maxWidth.toInt()
                            } else {
                                actualHeight = maxHeight.toInt()
                                actualWidth = maxWidth.toInt()
        
                            }
                        }
        
                        //      setting inSampleSize value allows to load a scaled down version of the original image
                        options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight)
        
                        //      inJustDecodeBounds set to false to load the actual bitmap
                        options.inJustDecodeBounds = false
        
                        //      this options allow android to claim the bitmap memory if it runs low on memory
                        options.inPurgeable = true
                        options.inInputShareable = true
                        options.inTempStorage = ByteArray(16 * 1024)
        
        
                        try {
                            //          load the bitmap from its path
                            ins.close()
                            ins = context.getContentResolver().openInputStream(uri)
                            bmp = BitmapFactory.decodeStream(ins, null, options)
                        } catch (exception: OutOfMemoryError) {
                            exception.printStackTrace()
        
                        }
        
                        try {
                            scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888)
                        } catch (exception: OutOfMemoryError) {
                            exception.printStackTrace()
                        }
        
                        val ratioX = actualWidth / options.outWidth.toFloat()
                        val ratioY = actualHeight / options.outHeight.toFloat()
                        val middleX = actualWidth / 2.0f
                        val middleY = actualHeight / 2.0f
        
                        val scaleMatrix = Matrix()
                        scaleMatrix.setScale(ratioX, ratioY, middleX, middleY)
        
                        val canvas = Canvas(scaledBitmap!!)
                        canvas.matrix = scaleMatrix
                        canvas.drawBitmap(bmp, middleX - bmp.width / 2, middleY - bmp.height / 2, Paint(Paint.FILTER_BITMAP_FLAG))
        
                        os = FileOutputStream(filename)
                        scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, os)
                        val buffer = ByteArray(1024)
                        var length: Int = ins.read(buffer)
                        while (length > 0) {
                            os.write(buffer, 0, length);
                            length = ins.read(buffer)
                        }
                    } catch (e: Exception) {
                        e.printStackTrace();
                    } finally {
                        ins?.close()
                        os?.close()
                    }
                }
                return filename
            }
        
            fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {
                val height = options.outHeight
                val width = options.outWidth
                var inSampleSize = 1
                if (height > reqHeight || width > reqWidth) {
                    val heightRatio = Math.round(height.toFloat() / reqHeight.toFloat())
                    val widthRatio = Math.round(width.toFloat() / reqWidth.toFloat())
                    inSampleSize = if (heightRatio < widthRatio) heightRatio else widthRatio
                }
                val totalPixels = (width * height).toFloat()
                val totalReqPixelsCap = (reqWidth * reqHeight * 2).toFloat()
                while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
                    inSampleSize++
                }
        
                return inSampleSize
            }
        }
        

        https://lalitjadav007.blogspot.in/2017/08/compress-image-in-android.html

        【讨论】:

          【解决方案12】:

          你可以试试这个代码

              public class ScalingUtilities {
          
              /**
               * Utility function for decoding an image resource. The decoded bitmap will
               * be optimized for further scaling to the requested destination dimensions
               * and scaling logic.
               *
               * @param res The resources object containing the image data
               * @param resId The resource id of the image data
               * @param dstWidth Width of destination area
               * @param dstHeight Height of destination area
               * @param scalingLogic Logic to use to avoid image stretching
               * @return Decoded bitmap
               */
              public static Bitmap decodeResource(Resources res, int resId, int dstWidth, int dstHeight,
                      ScalingLogic scalingLogic) {
                  Options options = new Options();
                  options.inJustDecodeBounds = true;
                  BitmapFactory.decodeResource(res, resId, options);
                  options.inJustDecodeBounds = false;
                  options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, dstWidth,
                          dstHeight, scalingLogic);
                  Bitmap unscaledBitmap = BitmapFactory.decodeResource(res, resId, options);
          
                  return unscaledBitmap;
              }
              public static Bitmap decodeFile(String path, int dstWidth, int dstHeight,
                      ScalingLogic scalingLogic) {
                  Options options = new Options();
                  options.inJustDecodeBounds = true;
                  BitmapFactory.decodeFile(path, options);
                  options.inJustDecodeBounds = false;
                  options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, dstWidth,
                          dstHeight, scalingLogic);
                  Bitmap unscaledBitmap = BitmapFactory.decodeFile(path, options);
          
                  return unscaledBitmap;
              }
          
              /**
               * Utility function for creating a scaled version of an existing bitmap
               *
               * @param unscaledBitmap Bitmap to scale
               * @param dstWidth Wanted width of destination bitmap
               * @param dstHeight Wanted height of destination bitmap
               * @param scalingLogic Logic to use to avoid image stretching
               * @return New scaled bitmap object
               */
              public static Bitmap createScaledBitmap(Bitmap unscaledBitmap, int dstWidth, int dstHeight,
                      ScalingLogic scalingLogic) {
                  Rect srcRect = calculateSrcRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(),
                          dstWidth, dstHeight, scalingLogic);
                  Rect dstRect = calculateDstRect(unscaledBitmap.getWidth(), unscaledBitmap.getHeight(),
                          dstWidth, dstHeight, scalingLogic);
                  Bitmap scaledBitmap = Bitmap.createBitmap(dstRect.width(), dstRect.height(),
                          Config.ARGB_8888);
                  Canvas canvas = new Canvas(scaledBitmap);
                  canvas.drawBitmap(unscaledBitmap, srcRect, dstRect, new Paint(Paint.FILTER_BITMAP_FLAG));
          
                  return scaledBitmap;
              }
          
              /**
               * ScalingLogic defines how scaling should be carried out if source and
               * destination image has different aspect ratio.
               *
               * CROP: Scales the image the minimum amount while making sure that at least
               * one of the two dimensions fit inside the requested destination area.
               * Parts of the source image will be cropped to realize this.
               *
               * FIT: Scales the image the minimum amount while making sure both
               * dimensions fit inside the requested destination area. The resulting
               * destination dimensions might be adjusted to a smaller size than
               * requested.
               */
              public static enum ScalingLogic {
                  CROP, FIT
              }
          
              /**
               * Calculate optimal down-sampling factor given the dimensions of a source
               * image, the dimensions of a destination area and a scaling logic.
               *
               * @param srcWidth Width of source image
               * @param srcHeight Height of source image
               * @param dstWidth Width of destination area
               * @param dstHeight Height of destination area
               * @param scalingLogic Logic to use to avoid image stretching
               * @return Optimal down scaling sample size for decoding
               */
              public static int calculateSampleSize(int srcWidth, int srcHeight, int dstWidth, int dstHeight,
                      ScalingLogic scalingLogic) {
                  if (scalingLogic == ScalingLogic.FIT) {
                      final float srcAspect = (float)srcWidth / (float)srcHeight;
                      final float dstAspect = (float)dstWidth / (float)dstHeight;
          
                      if (srcAspect > dstAspect) {
                          return srcWidth / dstWidth;
                      } else {
                          return srcHeight / dstHeight;
                      }
                  } else {
                      final float srcAspect = (float)srcWidth / (float)srcHeight;
                      final float dstAspect = (float)dstWidth / (float)dstHeight;
          
                      if (srcAspect > dstAspect) {
                          return srcHeight / dstHeight;
                      } else {
                          return srcWidth / dstWidth;
                      }
                  }
              }
          
              /**
               * Calculates source rectangle for scaling bitmap
               *
               * @param srcWidth Width of source image
               * @param srcHeight Height of source image
               * @param dstWidth Width of destination area
               * @param dstHeight Height of destination area
               * @param scalingLogic Logic to use to avoid image stretching
               * @return Optimal source rectangle
               */
              public static Rect calculateSrcRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight,
                      ScalingLogic scalingLogic) {
                  if (scalingLogic == ScalingLogic.CROP) {
                      final float srcAspect = (float)srcWidth / (float)srcHeight;
                      final float dstAspect = (float)dstWidth / (float)dstHeight;
          
                      if (srcAspect > dstAspect) {
                          final int srcRectWidth = (int)(srcHeight * dstAspect);
                          final int srcRectLeft = (srcWidth - srcRectWidth) / 2;
                          return new Rect(srcRectLeft, 0, srcRectLeft + srcRectWidth, srcHeight);
                      } else {
                          final int srcRectHeight = (int)(srcWidth / dstAspect);
                          final int scrRectTop = (int)(srcHeight - srcRectHeight) / 2;
                          return new Rect(0, scrRectTop, srcWidth, scrRectTop + srcRectHeight);
                      }
                  } else {
                      return new Rect(0, 0, srcWidth, srcHeight);
                  }
              }
          
              /**
               * Calculates destination rectangle for scaling bitmap
               *
               * @param srcWidth Width of source image
               * @param srcHeight Height of source image
               * @param dstWidth Width of destination area
               * @param dstHeight Height of destination area
               * @param scalingLogic Logic to use to avoid image stretching
               * @return Optimal destination rectangle
               */
              public static Rect calculateDstRect(int srcWidth, int srcHeight, int dstWidth, int dstHeight,
                      ScalingLogic scalingLogic) {
                  if (scalingLogic == ScalingLogic.FIT) {
                      final float srcAspect = (float)srcWidth / (float)srcHeight;
                      final float dstAspect = (float)dstWidth / (float)dstHeight;
          
                      if (srcAspect > dstAspect) {
                          return new Rect(0, 0, dstWidth, (int)(dstWidth / srcAspect));
                      } else {
                          return new Rect(0, 0, (int)(dstHeight * srcAspect), dstHeight);
                      }
                  } else {
                      return new Rect(0, 0, dstWidth, dstHeight);
                  }
              }
          
          
              public static String decodeFile(String path,int DESIREDWIDTH, int DESIREDHEIGHT, int type) {
                  String strMyImagePath = null;
                  Bitmap scaledBitmap = null;
                  Bitmap rotated = null;
          
                  try {
                      // Part 1: Decode image
                      Bitmap unscaledBitmap = ScalingUtilities.decodeFile(path, DESIREDWIDTH, DESIREDHEIGHT, ScalingLogic.FIT);
          
          //            if (!(unscaledBitmap.getWidth() <= DESIREDWIDTH && unscaledBitmap.getHeight() <= DESIREDHEIGHT)) {
          //                // Part 2: Scale image
          //                scaledBitmap = ScalingUtilities.createScaledBitmap(unscaledBitmap, DESIREDWIDTH, DESIREDHEIGHT, ScalingLogic.FIT);
          //            } else {
          //                unscaledBitmap.recycle();
          //                return path;
          //            }
          
                      // Store to tmp file
                      scaledBitmap = ScalingUtilities.createScaledBitmap(unscaledBitmap, DESIREDWIDTH, DESIREDHEIGHT, ScalingLogic.FIT);
          
                      String extr = Environment.getExternalStorageDirectory().toString();
                      File mFolder = new File(extr + com.vt.vsmart.utils.Config.SD_PATH+"/image");
                      if (!mFolder.exists()) {
                          mFolder.mkdir();
                      }
          
                      String s = type+"temp.jpg";
          
                      File f = new File(mFolder.getAbsolutePath(), s);
          
                      strMyImagePath = f.getAbsolutePath();
                      FileOutputStream fos = null;
                      try {
                          fos = new FileOutputStream(f);
          //                scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 95, fos);
          
                          // quay anh 90 do
                          Matrix matrix = new Matrix();
          
                          matrix.postRotate(90);
          
                          rotated = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
          
                          rotated.compress(Bitmap.CompressFormat.JPEG, 95, fos);
          
                          fos.flush();
                          fos.close();
                      } catch (FileNotFoundException e) {
          
                          e.printStackTrace();
                      } catch (Exception e) {
          
                          e.printStackTrace();
                      }
          
          //            scaledBitmap.recycle();
                      rotated.recycle();
                  } catch (Throwable e) {
                  }
          
                  if (strMyImagePath == null) {
                      return path;
                  }
                  return strMyImagePath;
          
              }
          
              // check anh bi quay
              public int getCameraPhotoOrientation(Context context, Uri imageUri, String imagePath){
                  int rotate = 0;
                  try {
                      context.getContentResolver().notifyChange(imageUri, null);
                      File imageFile = new File(imagePath);
          
                      ExifInterface exif = new ExifInterface(imageFile.getAbsolutePath());
                      int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
          
                      switch (orientation) {
                      case ExifInterface.ORIENTATION_ROTATE_270:
                          rotate = 270;
                          break;
                      case ExifInterface.ORIENTATION_ROTATE_180:
                          rotate = 180;
                          break;
                      case ExifInterface.ORIENTATION_ROTATE_90:
                          rotate = 90;
                          break;
                      }
          
          //            Log.i("RotateImage", "Exif orientation: " + orientation);
          //            Log.i("RotateImage", "Rotate value: " + rotate);
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
                  return rotate;
              }
          
          }
          

          它对我有用。希望能帮到你!

          【讨论】:

            【解决方案13】:

            试试这个方法,这会将你的图像文件转换为压缩格式,你可以通过改变代码中x和y的值来自定义压缩级别(在注释行中注明)

                  File mImageFile = saveBitmapToFile(ImageFile);
            
                  public File saveBitmapToFile(File file){
            
                  try {
            
                    // BitmapFactory options to downsize the image
                    BitmapFactory.Options o = new BitmapFactory.Options();
                    o.inJustDecodeBounds = true;
                    o.inSampleSize = 6;
                    // factor of downsizing the image
            
                    FileInputStream inputStream = new FileInputStream(file);
                    //Bitmap selectedBitmap = null;
                    BitmapFactory.decodeStream(inputStream, null, o);
                    inputStream.close();
            
                    // The new size we want to scale to
                    final int REQUIRED_SIZE=200;        // x............
            
                    // Find the correct scale value. It should be the power of 2.
                    int scale = 1;
                    while(o.outWidth / scale / 2 >= REQUIRED_SIZE &&
                            o.outHeight / scale / 2 >= REQUIRED_SIZE) {
                        scale *= 2;
                    }
            
                    BitmapFactory.Options o2 = new BitmapFactory.Options();
                    o2.inSampleSize = scale;
                    inputStream = new FileInputStream(file);
            
                    Bitmap selectedBitmap = BitmapFactory.decodeStream(inputStream, null, o2);
                    inputStream.close();
            
                    // here i override the original image file
                    File outPutFile = File.createTempFile("abc","image");
                    FileOutputStream outputStream = new FileOutputStream(outPutFile);
                                                              // y.......
                    selectedBitmap.compress(Bitmap.CompressFormat.JPEG, 95 , outputStream);
            
                    return outPutFile;
                } catch (Exception e) {
                    return null;
                }
            }
            

            谢谢

            【讨论】: