BitmapFactory.decodeFile(path,options)返回options.outWidth等于0

时间:2016-11-16 13:18:15

标签: android android-bitmap bitmapfactory image-compression

下面是我用来压缩图片的代码片段:

    public static final List<Object> compressImage(String imagePath) {
        Bitmap scaledBitmap = null;

        BitmapFactory.Options options = new BitmapFactory.Options();

        options.inJustDecodeBounds = true;

        Bitmap bmp = BitmapFactory.decodeFile( imagePath, options );

        int actualHeight = options.outWidth;
        int actualWidth  = options.outWidth;

        float maxHeight = 816.0f;
        float maxWidth = 612.0f;
        float imgRatio = actualWidth / actualHeight;
        float maxRatio = maxWidth / maxHeight;

        ................

        return List<Object>
    }

我的问题是options.outWitdth等于 0 。我在第java.lang.ArithmeticException: divide by zero

上收到错误float imgRatio = actualWidth / actualHeight;

我已经看到了这个问题:java.lang.ArithmeticException: divide by zero when compres image from pick galery

并尝试使用答案,但它没有用。我不知道该尝试什么。如何修复???

我从Camera App获得了imagePath:

private void dispatchTakePictureIntent() {
    // Create an intent to capture an image and returns control to the caller.
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    fileImageUri = ProcessaImagens.getOutputMediaFileUri(ProcessaImagens.MEDIA_TYPE_IMAGE, getApplicationContext());
    intent.putExtra(MediaStore.EXTRA_OUTPUT, fileImageUri);
    // Starts the intent for image capture and wait for the result.
    startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
}

Class ProcessaImagens:

public static Uri getOutputMediaFileUri( int type, Context context ) {
    return Uri.fromFile( getOutputMediaFile( type, context ) );
}

private static File getOutputMediaFile( int type, Context context ) {
    // Obtem o nome do app para usar como o nome da pasta onde as imagens serao salvas dentro da pasta "Pictures"
    PackageManager packageManager = context.getPackageManager();
    ApplicationInfo applicationInfo = null;

    try {
        applicationInfo = packageManager.getApplicationInfo( context.getApplicationInfo().packageName, 0 );
    } catch ( final PackageManager.NameNotFoundException e ) {
    }
    String nomeApp = (String) (applicationInfo != null ? packageManager.getApplicationLabel( applicationInfo ) : "Desconhecido");

    if (nomeApp == null)
        nomeApp = context.getString(R.string.app_name);

    // To be safe, you should check that the SDCard is mounted
    // using Environment.getExternalStorageState() before doing this.

    // Esta localizacao trabalha melhor se voce quer criar imagens para ser compartilhada entre aplicacoes e persistir depois de seu app ter sido desinstalado.
    File mediaStorageDir = new File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), nomeApp );

    // Cria o diretorio se ele nao existe
    if ( !mediaStorageDir.exists() ) {
        if ( !mediaStorageDir.mkdirs() ) {
            Log.d( nomeApp, "Falha ao criar diretório ou diretório já existe!" );
            return null;
        }
    }

    // Cria o nome do arquivo de midia
    String timeStamp = new SimpleDateFormat( "yyyyMMdd_HHmmss" ).format( new Date() );
    File mediaFile;
    if ( type == MEDIA_TYPE_IMAGE ) {
        mediaFile = new File( mediaStorageDir.getPath() + File.separator +
                "IMG_" + timeStamp + ".jpg" );
    } else if ( type == MEDIA_TYPE_VIDEO ) {
        mediaFile = new File( mediaStorageDir.getPath() + File.separator +
                "VID_" + timeStamp + ".mp4" );
    } else {
        return null;
    }

    return mediaFile;
}

方法onActivityResult我将方法调用到processImage:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    // If finish Activity on startForActivityResult.
    if (resultCode == RESULT_OK) {
        if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
            processImageCaptured();
        } else if (requestCode == SELECT_IMAGE_ACTIVITY_REQUEST_CODE) {
            fileImageUri = data.getData();
            new ProcessesImageSelectedTask().execute();
        }
    }
    // If cancel Activity on startForActivityResult.
    else if (resultCode == RESULT_CANCELED) {
        if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
            // User cancel capture image.
        } else if (requestCode == SELECT_IMAGE_ACTIVITY_REQUEST_CODE) {}
    }
    // If an error occurred in the Activity on startForActivityResult.
    else {
        // Image capture fail, warning user.
        Toast.makeText(this, getString(R.string.fail_activity_take_image), Toast.LENGTH_SHORT).show();
    }
}

private void processImageCaptured() {
    galleryAddPic();
    List<Object> image = ProcessaImagens.compactarImagem(fileImageUri.getPath());

    .................
}

private void galleryAddPic() {
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    mediaScanIntent.setData(fileImageUri);
    this.sendBroadcast(mediaScanIntent);
}

2 个答案:

答案 0 :(得分:0)

我认为问题在于您正在尝试使用文件Uri创建图像。 您确定自己的应用获得了WRITE_EXTERNAL_STORAGE权限吗?因为没有它,相机应用程序无法存储您捕获的图像。

此外,这可能是一个好的开始: https://developer.android.com/training/camera/photobasics.html

答案 1 :(得分:-1)

首先,您需要选择图像

public void onClick(View v) {//does whatever code is in here when the button is clicked
                    try {
                        Intent intent = new Intent();
                        intent.setType("image/*");
                        intent.setAction(Intent.ACTION_GET_CONTENT);
                        startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_REQUEST);
                    } catch (ActivityNotFoundException e){
                        Toast.makeText(Seller_Home_Page.this,"No application available to select image",Toast.LENGTH_SHORT).show();
                    }
                }

然后你需要抓取图像数据

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    //For photo
    //so the if statement checks if the image came through, double checks if the result is okay and triple checks to see if the data is not null.
    if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {

        //File path to the photo that is selected.
        Uri ProductPhotoFilePath = data.getData();


        try {

            //Getting the Bitmap from Gallery
            productBitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), ProductPhotoFilePath);

            ImagePath = getPath(ProductPhotoFilePath);

            persistProductImage(productBitmap, ImagePath);

            getStringImage(productBitmap);
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(Seller_Home_Page.this,"Please pick a valid photo",Toast.LENGTH_SHORT).show();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }

然后压缩图像

public void getStringImage(Bitmap bitmap) {

    if (bitmap != null){
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 30, baos);//30 equals to the quality of the photo
        byte[] imageBytes = baos.toByteArray();

        int PhotoSize = imageBytes.length;

        if(PhotoSize <= 15000) {//Change this value to something more reasonable
            //Setting the Bitmap to ImageView
            ItemPhotoPreview.setImageBitmap(bitmap);

            encodedImage = Base64.encodeToString(imageBytes, Base64.DEFAULT);
        }else{
            //Setting the Bitmap to ImageView
            ItemPhotoPreview.setColorFilter(Color.TRANSPARENT);

            Toast.makeText(Seller_Home_Page.this,"Photo size is too large",Toast.LENGTH_SHORT).show();
        }
    }
}