【问题标题】:How whatsapp/Instagram or other compresses the image before uploading it to server?whatsapp/Instagram 或其他如何在将图像上传到服务器之前对其进行压缩?
【发布时间】:2016-04-12 07:22:08
【问题描述】:

我使用以下方法在将图像上传到服务器之前对其进行压缩。

总结以下代码,最初我从手机/SD卡中获取图像,将其转换为位图并在位图上进行缩放和压缩。然后我将磁盘上的压缩位图保存为新位置的图像。

此方法确实将图像从 3mb - 5mb 压缩到 30-100kb。 (当我检查 sdcard 上的压缩图像大小时)

然后我通过将其转换为位图字符串(通过 Base64.encodeToString())将 30-100kb 的新压缩图像发送到服务器

我认为它会正常工作。但是当我在服务器上检查上传的图像时,图像的大小与原始图像大小(压缩前的原始大小)相同,而不是压缩后的 30-100kb 大小的图像。

代码如下:

public String compressImage(String imageUri)
  {
    String filePath = getRealPathFromURI(imageUri);
    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.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 = 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);
        Log.d("EXIF", "Exif: " + orientation);
        Matrix matrix = new Matrix();
        if (orientation == 6) {
            matrix.postRotate(90);
            Log.d("EXIF", "Exif: " + orientation);
        } else if (orientation == 3) {
            matrix.postRotate(180);
            Log.d("EXIF", "Exif: " + orientation);
        } else if (orientation == 8) {
            matrix.postRotate(270);
            Log.d("EXIF", "Exif: " + orientation);
        }
        scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
                scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix,
                true);
    } catch (IOException e) {
        e.printStackTrace();
    }

    FileOutputStream out = null;
    String filename = getFilename();
    try {
        out = new FileOutputStream(filename);
        scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
return filename;
}

public String getFilename() {
File file = new File(Environment.getExternalStorageDirectory().getPath(), "MyFolder/Images");
if (!file.exists()) {
    file.mkdirs();
}
String uriSting = (file.getAbsolutePath() + "/" +  System.currentTimeMillis() + ".jpg");
    return uriSting;}

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

public 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;

}

我在上面的代码中的某个地方出错了吗?有没有更好的方法来压缩图像。我想知道如何上传未压缩的图像(位图)而不是压缩的。

whatsapp/instagram/facebook 在上传到服务器之前如何压缩图像。有没有它的图书馆。谢谢。

【问题讨论】:

    标签: android image bitmap compression


    【解决方案1】:

    试试这个

    private String decodeFile(String path,int DESIREDWIDTH, int DESIREDHEIGHT) {
        String strMyImagePath = null;
        Bitmap scaledBitmap = 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
    
            String extr = Environment.getExternalStorageDirectory().toString();
            File mFolder = new File(extr + "/TMMFOLDER");
            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.JPEG, 75, 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;
    
    }
    


    ScalingUtilities.java

    import android.content.res.Resources;
    import android.graphics.Bitmap;
    import android.graphics.Bitmap.Config;
    import android.graphics.BitmapFactory;
    import android.graphics.BitmapFactory.Options;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.Rect;
    
    /**
     * Class containing static utility methods for bitmap decoding and scaling
     *
     * @author 
     */
    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);
            }
        }
    
    }
    

    【讨论】:

    • 您的答案完美无缺。但是,如果您对我的方法出错的地方有所了解,那会更合适。
    猜你喜欢
    • 2022-01-18
    • 2017-03-15
    • 1970-01-01
    • 1970-01-01
    • 2020-09-15
    • 2017-05-17
    • 1970-01-01
    • 2017-02-01
    相关资源
    最近更新 更多