发布之前减少图片的大小

时间:2017-04-11 10:24:15

标签: android android-studio

我有一个函数将文件(来自相机或图库的图片)发送到WebService。 我希望在发布之前减少fileUri的图像大小(每个示例50%)。 该文件是图库或相机图像。

这是我的postFile功能:

public static void postFile(Context context, String url, String fileUri, AsyncHttpResponseHandler responseHandler) {
    if (myCookieStore == null)
    {
        myCookieStore = new PersistentCookieStore(context);
        client.setCookieStore(myCookieStore);
    }

    File myFile = new File(Uri.parse(fileUri).getPath());

    RequestParams params = new RequestParams();
    try {
        params.put("profile_picture", myFile);
    } catch(FileNotFoundException e) {
        Log.d("error", "error catch");
    }
    Log.d("absolute url", "" + "*" + getAbsoluteUrl(url) + "*");
    client.post(context, getAbsoluteUrl(url), params, responseHandler);
}

我该怎么做?

6 个答案:

答案 0 :(得分:5)

有这个库,可以将你的图像从mb压缩到kb,它非常强大,我已经使用了很多次,它的工作文件上传是超高速的。 link

代码段:compressedImageFile = Compressor.getDefault(this).compressToFile(actualImageFile);

它内部使用google webp格式,WebP是一种现代图像格式,可为网络上的图像提供卓越的无损和有损压缩。使用WebP,网站管理员和网络开发人员可以创建更小,更丰富的图像,使网络更快。

该库非常适合大小压缩,它做得非常好,基于我的观察的大型文件,如2mb up,但是有一些内存泄漏需要解决,我通过使用泄漏解决了我的问题金丝雀,虽然每个开发人员都应该使用它。总的来说,它非常棒,可以随心所欲地使用它。

答案 1 :(得分:1)

我在很多项目中都使用了这个代码,并且它总能给我带来好的结果,我记得如果我选择尺寸为5-7MB的图像(来自12/13 MP相机的图像),此代码将返回1MB或更小的图像超过2MB。

public static boolean validateUri(Uri uri) {
        if (uri == null)
            return false;
        else {
            String path = uri.getPath();
            return !(uri.equals(Uri.EMPTY) || path == null || path.equals("null"));
        }
    }

首先,我们需要一个完整的图像并根据需要旋转。

public static Bitmap getFullSizeImage(Context context, Uri uri) {
        String filePath;
        if (validateUri(uri) && uri.toString().contains("file"))
            filePath = uri.getPath();
        else
            filePath = getRealPathFromURI(context, uri, MediaStore.Images.Media.DATA);
        if (filePath == null)
            return null;
        try {
            int rotation = 0;
            ExifInterface exifInterface = new ExifInterface(filePath);
            int exifRotation = exifInterface.getAttributeInt(
                    ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_UNDEFINED);
            if (exifRotation != ExifInterface.ORIENTATION_UNDEFINED) {
                switch (exifRotation) {
                    case ExifInterface.ORIENTATION_ROTATE_180:
                        rotation = 180;
                        break;
                    case ExifInterface.ORIENTATION_ROTATE_270:
                        rotation = 270;
                        break;
                    case ExifInterface.ORIENTATION_ROTATE_90:
                        rotation = 90;
                        break;
                }
            }
            Matrix matrix = new Matrix();
            matrix.setRotate(rotation);
            // you can use other than 400 as required width/height
            Bitmap sourceBitmap = getBitmapFromPath(400, filePath);
            if (sourceBitmap == null)
                return null;
            return Bitmap.createBitmap(sourceBitmap, 0, 0, sourceBitmap.getWidth(),
                    sourceBitmap.getHeight(), matrix, true);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

现在我们需要一个来自URI

的真实路径
public static String getRealPathFromURI(Context context, Uri contentUri, String type) {
        Cursor cursor = null;
        String path = null;
        try {
            // String[] proj = { MediaStore.Images.Media.DATA };
            String[] projection = {type};
            cursor = context.getContentResolver().query(contentUri, projection, null, null, null);
            if (cursor == null)
                return null;
            int columnIndex = cursor.getColumnIndexOrThrow(type);
            cursor.moveToFirst();
            path = cursor.getString(columnIndex);
            // we choose image from drive etc.
            if (path == null)
                path = getDocumentRealPathFromUri(context, contentUri);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return path;
    }

如果我们从驱动器等选择图片,我们仍然需要一个给定URI的真实路径

public static String getDocumentRealPathFromUri(Context context, Uri contentUri) {
        Cursor cursor = context.getContentResolver().query(contentUri, null,
                null, null, null);
        if (cursor == null)
            return null;
        cursor.moveToFirst();
        String documentId = cursor.getString(0);
        documentId = documentId.substring(documentId.lastIndexOf(":") + 1);
        cursor.close();
        cursor = context.getContentResolver().query(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                null, MediaStore.Images.Media._ID + " = ? ",
                new String[]{documentId}, null);
        if (cursor == null)
            return null;
        cursor.moveToFirst();
        String path = cursor.getString(cursor
                .getColumnIndex(MediaStore.Images.Media.DATA));
        cursor.close();
        return path;
    }

现在我们已经选择了一个真实的所选图像路径,因此我们可以使用样本大小从此路径获取位图

public static Bitmap getBitmapFromPath(int size, String realPathFromURI) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(realPathFromURI, options);
        options.inSampleSize = calculateInSampleSizeUsingPower2(options, size, size);
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(realPathFromURI, options);
    }

    public static int calculateInSampleSizeUsingPower2(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        // raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
            final int halfHeight = height / 2;
            final int halfWidth = width / 2;
            // calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / inSampleSize) > reqHeight
                    && (halfWidth / inSampleSize) > reqWidth)
                inSampleSize *= 2;
        }
        return inSampleSize;
    }

此时我们已经压缩了位图,如果我们对给定的位图执行Base64操作,我们还可以再次压缩这个位图。

public static String convertToBase64(Bitmap bitmap) {
        if (bitmap == null)
            return null;
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream)) {
            String base64 = encodeToString(byteArrayOutputStream.toByteArray(), DEFAULT);
            try {
                byteArrayOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return base64;
        }
        return null;
    }

在服务器端,您可以解码Base64并转换回文件流并保存图像。

示例

Bitmap bitmap = getFullSizeImage(context, selectedPhotoUri);
if(bitmap != null){
    String base64Image = convertToBase64(bitmap);
    if (base64Image != null) {
        RequestParams params = new RequestParams();
        try {
            params.put("title", "your_image_name");
            params.put("profile_picture", base64Image);
        } catch(FileNotFoundException e) {
            Log.d("error", "error catch");
        }
    }
}

注意 如果您不想执行Base64,可以使用位图转换为流并将其发送到您的服务器。

答案 2 :(得分:0)

尝试此功能。如果位图的宽度或高度大于512,它会将位图的大小减小到512

public static Bitmap resizeBitmap(Bitmap bm) {
        if (bm.getWidth() > maxSize || bm.getHeight() > maxSize) {
            if (bm.getWidth() > bm.getHeight()) {
                newWidth = maxSize;
                newHeight = (bm.getHeight() * maxSize) / bm.getWidth();

                bm = Bitmap.createScaledBitmap(bm, newHeight, newWidth, true);
                return bm;
            } else {
                newHeight = maxSize;
                newWidth = (bm.getWidth() * maxSize) / bm.getHeight();
                bm = Bitmap.createScaledBitmap(bm, newHeight, newWidth, true);
                return bm;
            }
        }
        return bm;
    }

您只需将位图传递给此方法。

从URI获取位图的方法是

BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 8;
        bitmap = BitmapFactory.decodeFile(fileUri.getPath(),
                options);

答案 3 :(得分:0)

使用此图片更改图像宽度和高度

public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
    int width = bm.getWidth();
    int height = bm.getHeight();
    float scaleWidth = ((float) newWidth) / width;
    float scaleHeight = ((float) newHeight) / height;
    Matrix matrix = new Matrix();
    matrix.postScale(scaleWidth, scaleHeight);
    Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height,
            matrix, false);

    return resizedBitmap;
}

你可以用这个来改变大小...这是最好的例子......

  private Bitmap decodeFile(File f){
   try {
    //Decode image size
    BitmapFactory.Options o = new BitmapFactory.Options();
    o.inJustDecodeBounds = true;
    BitmapFactory.decodeStream(new FileInputStream(f),null,o);

    //The new size we want to scale to
    final int REQUIRED_SIZE=70;

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

    //Decode with inSampleSize
    BitmapFactory.Options o2 = new BitmapFactory.Options();
    o2.inSampleSize=scale;
    return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
  } catch (FileNotFoundException e) {}
  return null;
  }

答案 4 :(得分:0)

如果摄像机图像是JPEG,则可以使用位图压缩方法,如:

Bitmap bitmap = BitmapFactory.decodeStream(...uri);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
            try {
                int compression_factor = 50;    // represents 50% compression
                bitmap.compress(Bitmap.CompressFormat.JPEG, compression_factor, baos);

                byte[] image = baos.toByteArray();

               // now update web service asynchronously...
               ...
            } finally {
                baos.close();
            }

答案 5 :(得分:0)

将图像转换为位图,然后使用以下方法

     public static Bitmap scaleBitmap(Bitmap bitmap, int newWidth, int newHeight) {
        Bitmap scaledBitmap = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);

        float scaleX = newWidth / (float) bitmap.getWidth();
        float scaleY = newHeight / (float) bitmap.getHeight();
        float pivotX = 0;
        float pivotY = 0;

        Matrix scaleMatrix = new Matrix();
        scaleMatrix.setScale(scaleX, scaleY, pivotX, pivotY);

        Canvas canvas = new Canvas(scaledBitmap);
        canvas.setMatrix(scaleMatrix);
        canvas.drawBitmap(bitmap, 0, 0, new Paint(Paint.FILTER_BITMAP_FLAG));

        return scaledBitmap;
    }