从我的自定义图库android中选择图像时出错

时间:2016-05-17 17:06:50

标签: java android bitmap

如果我选择了一些图像,它会起作用,但是当我选择其他可能在尺寸上更重的图像时,它会给我这个错误:

java.lang.OutOfMemoryError: Failed to allocate a 79629324 byte allocation with 16777120 free bytes and 46MB until OOM

我有这个课程:

我点击进入自定义图库活动的主要活动:

public class gallerygridselect extends BaseNavegationActivity implements View.OnClickListener{

private LinearLayout lnrImages;
private Button btnAddPhots,btnSaveImages;
private ArrayList<String> imagesPathList;
private Bitmap yourbitmap;
private final int PICK_IMAGE_MULTIPLE = 1;
ArrayList<String> a = new ArrayList<String>();
long imageSize = 0; // kb
ImageView imageView;
private String[] imagesPath;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.gallery_picker);
    lnrImages = (LinearLayout) findViewById(R.id.lnrImages);
    btnAddPhots = (Button) findViewById(R.id.btnAddPhots);
    btnSaveImages = (Button) findViewById(R.id.btnSaveImages);
    btnAddPhots.setOnClickListener(this);
    btnSaveImages.setOnClickListener(this);

}


@Override
public void onClick(View view) {
    switch (view.getId()) {
        case R.id.btnAddPhots:
            Intent intent = new Intent(gallerygridselect.this, gallerygrid.class);
            startActivityForResult(intent, PICK_IMAGE_MULTIPLE);
            break;
        case R.id.btnSaveImages:
            if (imagesPathList != null) {
                if (imagesPathList.size() > 0) {
                    Toast.makeText(gallerygridselect.this, imagesPathList.size() + " fotos selecionadas", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(gallerygridselect.this, imagesPathList.size() + " fotos selecionadas", Toast.LENGTH_SHORT).show();
                }
            } else {
                Toast.makeText(gallerygridselect.this, "Selecione as fotos", Toast.LENGTH_SHORT).show();
            }
            break;
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK) {
        if (requestCode == PICK_IMAGE_MULTIPLE) {
            imagesPathList = new ArrayList<String>();
            imagesPath = data.getStringExtra("data").split("\\|");

            for (int i = 0; i < imagesPath.length; i++) {
                System.out.println("imagesPath   "+imagesPath[i]);
            }

            imageSize = this.getFileSize(String.valueOf(imagesPath));

            Log.d("PATH", "" + imagesPath);
            try {
                lnrImages.removeAllViews();
            } catch (Throwable e) {
                e.printStackTrace();
            }
            for (int i = 0; i < imagesPath.length; i++) {
                imagesPathList.add(imagesPath[i]);
                Log.e("Pathlist", "" + imagesPathList);
                yourbitmap = BitmapFactory.decodeFile(imagesPath[i]);
                Log.i("BITMAP", "" + yourbitmap);

                imageView = new ImageView(this);
                LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
                        ViewGroup.LayoutParams.WRAP_CONTENT);
                params.setMargins(5, 5, 5, 5);
                imageView.setLayoutParams(params);

                imageView.setImageBitmap(BitmapHelper.decodeFile(imagesPath[i], 320, 480, true));
                imageView.setAdjustViewBounds(true);
                lnrImages.addView(imageView);
            }
        }
    }
}

private long getFileSize(String imagesPath) {
    long length = 0;
    try {
        File file = new File(imagesPath);
        length = file.length();
        length = length / 1024;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return length;
}

private String getPath(Uri uri) {
    String[] projection = {MediaStore.Images.Media.DATA};
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);
}
}

我的位图帮助类:

public class BitmapHelper {
//decodes image and scales it to reduce memory consumption
public static Bitmap decodeFile(String bitmapFile, int requiredWidth, int requiredHeight, boolean quickAndDirty)
{
    try
    {
        //Decode image size
        BitmapFactory.Options bitmapSizeOptions = new BitmapFactory.Options();
        bitmapSizeOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(new FileInputStream(bitmapFile), null, bitmapSizeOptions);

        // load image using inSampleSize adapted to required image size
        BitmapFactory.Options bitmapDecodeOptions = new BitmapFactory.Options();
        bitmapDecodeOptions.inTempStorage = new byte[16 * 1024];
        bitmapDecodeOptions.inSampleSize = computeInSampleSize(bitmapSizeOptions, requiredWidth, requiredHeight, false);
        bitmapDecodeOptions.inPurgeable = true;
        bitmapDecodeOptions.inDither = !quickAndDirty;
        bitmapDecodeOptions.inPreferredConfig = quickAndDirty ? Bitmap.Config.RGB_565 : Bitmap.Config.ARGB_8888;

        Bitmap decodedBitmap = BitmapFactory.decodeStream(new FileInputStream(bitmapFile), null, bitmapDecodeOptions);

        // scale bitmap to mathc required size (and keep aspect ratio)

        float srcWidth = (float) bitmapDecodeOptions.outWidth;
        float srcHeight = (float) bitmapDecodeOptions.outHeight;

        float dstWidth = (float) requiredWidth;
        float dstHeight = (float) requiredHeight;

        float srcAspectRatio = srcWidth / srcHeight;
        float dstAspectRatio = dstWidth / dstHeight;

        // recycleDecodedBitmap is used to know if we must recycle intermediary 'decodedBitmap'
        // (DO NOT recycle it right away: wait for end of bitmap manipulation process to avoid
        // java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@416ee7d8
        // I do not excatly understand why, but this way it's OK

        boolean recycleDecodedBitmap = false;

        Bitmap scaledBitmap = decodedBitmap;
        if (srcAspectRatio < dstAspectRatio)
        {
            scaledBitmap = getScaledBitmap(decodedBitmap, (int) dstWidth, (int) (srcHeight * (dstWidth / srcWidth)));
            // will recycle recycleDecodedBitmap
            recycleDecodedBitmap = true;
        }
        else if (srcAspectRatio > dstAspectRatio)
        {
            scaledBitmap = getScaledBitmap(decodedBitmap, (int) (srcWidth * (dstHeight / srcHeight)), (int) dstHeight);
            recycleDecodedBitmap = true;
        }

        // crop image to match required image size

        int scaledBitmapWidth = scaledBitmap.getWidth();
        int scaledBitmapHeight = scaledBitmap.getHeight();

        Bitmap croppedBitmap = scaledBitmap;

        if (scaledBitmapWidth > requiredWidth)
        {
            int xOffset = (scaledBitmapWidth - requiredWidth) / 2;
            croppedBitmap = Bitmap.createBitmap(scaledBitmap, xOffset, 0, requiredWidth, requiredHeight);
            scaledBitmap.recycle();
        }
        else if (scaledBitmapHeight > requiredHeight)
        {
            int yOffset = (scaledBitmapHeight - requiredHeight) / 2;
            croppedBitmap = Bitmap.createBitmap(scaledBitmap, 0, yOffset, requiredWidth, requiredHeight);
            scaledBitmap.recycle();
        }

        if (recycleDecodedBitmap)
        {
            decodedBitmap.recycle();
        }
        decodedBitmap = null;

        scaledBitmap = null;
        return croppedBitmap;
    }
    catch (Exception ex)
    {
        ex.printStackTrace();
    }
    return null;
}

/**
 * compute powerOf2 or exact scale to be used as {@link BitmapFactory.Options#inSampleSize} value (for subSampling)
 *
 // @param requiredWidth
 // @param requiredHeight
 * @param powerOf2
 *            weither we want a power of 2 sclae or not
 * @return
 */
public static int computeInSampleSize(BitmapFactory.Options options, int dstWidth, int dstHeight, boolean powerOf2)
{
    int inSampleSize = 1;

    // Raw height and width of image
    final int srcHeight = options.outHeight;
    final int srcWidth = options.outWidth;

    if (powerOf2)
    {
        //Find the correct scale value. It should be the power of 2.

        int tmpWidth = srcWidth, tmpHeight = srcHeight;
        while (true)
        {
            if (tmpWidth / 2 < dstWidth || tmpHeight / 2 < dstHeight)
                break;
            tmpWidth /= 2;
            tmpHeight /= 2;
            inSampleSize *= 2;
        }
    }
    else
    {
        // Calculate ratios of height and width to requested height and width
        final int heightRatio = Math.round((float) srcHeight / (float) dstHeight);
        final int widthRatio = Math.round((float) srcWidth / (float) dstWidth);

        // Choose the smallest ratio as inSampleSize value, this will guarantee
        // a final image with both dimensions larger than or equal to the
        // requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }

    return inSampleSize;
}

public static Bitmap drawableToBitmap(Drawable drawable)
{
    if (drawable instanceof BitmapDrawable)
    {
        return ((BitmapDrawable) drawable).getBitmap();
    }

    Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    drawable.draw(canvas);

    return bitmap;
}

public static Bitmap getScaledBitmap(Bitmap bitmap, int newWidth, int newHeight)
{
    int width = bitmap.getWidth();
    int height = bitmap.getHeight();
    float scaleWidth = ((float) newWidth) / width;
    float scaleHeight = ((float) newHeight) / height;

    // CREATE A MATRIX FOR THE MANIPULATION
    Matrix matrix = new Matrix();
    // RESIZE THE BIT MAP
    matrix.postScale(scaleWidth, scaleHeight);

    // RECREATE THE NEW BITMAP
    Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, false);
    return resizedBitmap;
}
}

我在Android开发中的新手我能做些什么来解决这个问题。提前谢谢。

1 个答案:

答案 0 :(得分:1)

您需要传递高度和宽度的文件路径。所以它会给你一个小图像: -

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

了解更多信息,请参阅链接: -

http://voidcanvas.com/whatsapp-like-image-compression-in-android/