1

我正在尝试从特定 uri 打开图像,检查该图像是否太大而无法调整大小,并将其返回为 Base64。我的问题是我必须调整图像大小的代码从不调整图像大小(从不表示图像太大)。我寻找其他类似的问题,但我没有得到任何答案。我不知道为什么这两个代码行中的值总是-1:

        final int height = options.outHeight; // Always -1 WHY?
    final int width = options.outWidth; // Always -1 WHY?

我附上我的代码:

private class WriteImage extends AsyncTask<Object, Void, String>{
            private static Bitmap decodeSampledBitmapFromStream(InputStream is,
                                                    int reqWidth,
                                                    int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    InputStream aux = inputStreamCopy(is);
    BitmapFactory.decodeStream(is, null, options);  // SkImageDecoder::Factory returned null
    try {
        is.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeStream(aux, null, options);
}

private static InputStream inputStreamCopy(InputStream is) {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    int len;
    byte[] buffer = new byte[1024];

    try {
        while ((len = is.read(buffer)) > -1) baos.write(buffer, 0, len);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return new ByteArrayInputStream(baos.toByteArray());
}

private static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight; // Always -1 WHY?
    final int width = options.outWidth; // Always -1 WHY?
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {
        if (width > height)
            inSampleSize = Math.round((float)height / (float)reqHeight);
        else
            inSampleSize = Math.round((float)width / (float)reqWidth);

        // This offers some additional logic in case the image has a strange
        // aspect ratio. For example, a panorama may have a much larger
        // width than height. In these cases the total pixels might still
        // end up being too large to fit comfortably in memory, so we should
        // be more aggressive with sample down the image (=larger
        // inSampleSize).
        final float totalPixels = width * height;

        // Anything more than 2x the requested pixels we'll sample down
        // further.
        final float totalReqPixelsCap = reqWidth * reqHeight * 2;

        while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap)
            inSampleSize++;
    }
    for (int i=5; i>0; i--){
        if (Math.pow(2, i)<=inSampleSize){
            inSampleSize = (int) Math.pow(2, i);
            break;
        }
    }
    return inSampleSize;
}


    @Override
    protected void onPreExecute(){  
    }

    @Override
    protected void onProgressUpdate(Void... values){
    }

    @Override
    protected String doInBackground(Object... params) {
        try {
            InputStream is = ((android.app.Activity) params[1]).getContentResolver().openInputStream((Uri) params[0]);

            Bitmap bitmap = decodeSampledBitmapFromStream(is, 300, 300);
            int bytes = bitmap.getWidth()*bitmap.getHeight()*4;
            ByteBuffer buffer = ByteBuffer.allocate(bytes);
            bitmap.copyPixelsToBuffer(buffer);
            return Base64.encodeToString(buffer.array(), Base64.DEFAULT);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(String result){
    }
}
4

1 回答 1

0

解决方案是这样的!替换以下内容:

decodeSampledBitmapFromStream函数中:

    private Bitmap decodeSampledBitmapFromStream(InputStream is,
                                                    int reqWidth,
                                                    int reqHeight) {

    // First decode with inJustDecodeBounds=true to check dimensions
    final BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;

    InputStream aux = inputStreamCopy(is);
    BitmapFactory.decodeStream(aux, null, options);  // SkImageDecoder::Factory returned null
    try {
        aux.reset();
    } catch (IOException e) {
        e.printStackTrace();
    }

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

    // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;
    return BitmapFactory.decodeStream(aux, null, options);
}

doInBackground方法中:

        @Override
    protected String doInBackground(Object... params) {
        try {
            InputStream is = ((android.app.Activity) params[1]).getContentResolver().openInputStream((Uri) params[0]);
            Bitmap bitmap = decodeSampledBitmapFromStream(is, 300, 300);
            System.gc();
            int bytes = bitmap.getWidth()*bitmap.getHeight()*2;
            ByteBuffer buffer = ByteBuffer.allocate(bytes);
            bitmap.copyPixelsToBuffer(buffer);
            return Base64.encodeToString(buffer.array(), Base64.DEFAULT);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

:)

于 2012-11-14T22:02:39.887 回答