skip to Main Content

I have made image compress long ago it was working well until android 10 but above android its not working.

public class ImageCompress {

private static final int IMAGE_QUALITY = 99;
private static final int MAX_SIZE_PIXELS = 1200;

public static Bitmap decodeFile(File file, int width, int height) {
    try {
        // decode image size
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(new FileInputStream(file), null, options);

        // the new size we want to scale to
        final int REQUIRED_WIDTH = width;
        final int REQUIRED_HIGHT = height;

        // find the correct scale value. It should be the power of 2.
        int scale = 1;
        while (options.outWidth / scale / 2 >= REQUIRED_WIDTH
                && options.outHeight / scale / 2 >= REQUIRED_HIGHT)
            scale *= 2;

        // decode with inSampleSize
        BitmapFactory.Options newOptions = new BitmapFactory.Options();
        newOptions.inSampleSize = scale;
        return BitmapFactory.decodeStream(new FileInputStream(file), null, newOptions);

    } catch (FileNotFoundException e) {
        return null;
    }
}

public static File compressImage(final File file, String outputDirectory, Context context) {
    String path = file.getPath();
    String format = path.substring(path.lastIndexOf(".")).substring(1);
    Bitmap source;
    try {
        source = decodeFile(file, MAX_SIZE_PIXELS, MAX_SIZE_PIXELS);
    } catch (Exception e) {
        Log.d(ImageCompress.class.toString(), e.toString() + " Something happened wrong");
        return null;
    }

    Bitmap.CompressFormat compressFormat;

    // if png pr webp have allowed resolution then not compress it
    if ("png".equals(format) || "webp".equals(format)) return file;

    // select format
    switch (format) {
        case "png":
            compressFormat = Bitmap.CompressFormat.PNG;
            break;
        case "webp":
            compressFormat = Bitmap.CompressFormat.WEBP;
            break;
        case "gif":
            return file;
        default:
            compressFormat = Bitmap.CompressFormat.JPEG;
    }

    // resize image
    Bitmap resizedBmp;
//getting error on source.getHeight() line
    if (source.getHeight() > MAX_SIZE_PIXELS || source.getWidth() > MAX_SIZE_PIXELS) {
        resizedBmp = resizeBitmap(source, MAX_SIZE_PIXELS);
    } else {
        resizedBmp = source;
    }
    File result = null;
    OutputStream fOut = null;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        ContentResolver resolver = BaseApplication.getInstance().getContentResolver();
        ContentValues contentValues = new ContentValues();
        contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, file.getName());
        contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/" + format);
        contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Constants.MULTIMEDIA_CHATROOM_11);
        Uri imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
        try {
            fOut = resolver.openOutputStream(imageUri);
            result = new File(Utils.getPath(BaseApplication.getInstance(), imageUri));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    } else {
        // create directory if not exist
        File directory = new File(outputDirectory);
        int code = context.getPackageManager().checkPermission(
                android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
                context.getPackageName());
        if (code == PackageManager.PERMISSION_GRANTED) {
            Log.i(ImageCompress.class.getSimpleName(), "creating directory");
            if (!directory.isDirectory() || !directory.exists()) {
                directory.mkdirs();
            }
        } else {
            Log.i(ImageCompress.class.getSimpleName(), "failed access");
        }

        // compress image
        result = new File(outputDirectory, file.getName());

        try {
            if (!result.exists()) {
                result.createNewFile();
                fOut = new FileOutputStream(result);
            } else {
                fOut = new FileOutputStream(result);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    try {
        resizedBmp.compress(compressFormat, IMAGE_QUALITY, fOut);
        fOut.flush();
        fOut.close();
        source.recycle();
        resizedBmp.recycle();

    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }

    // copy EXIF orientation from original image
    try {
        ExifInterface oldExif = new ExifInterface(file.getPath());
        String exifOrientation = oldExif.getAttribute(ExifInterface.TAG_ORIENTATION);
        if (exifOrientation != null) {
            ExifInterface newExif = new ExifInterface(result.getPath());
            newExif.setAttribute(ExifInterface.TAG_ORIENTATION, exifOrientation);
            newExif.saveAttributes();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    return result;
}

private static Bitmap resizeBitmap(Bitmap source, int maxSizePixels) {
    int targetWidth, targetHeight;
    double aspectRatio;

    if (source.getWidth() > source.getHeight()) {
        targetWidth = maxSizePixels;
        aspectRatio = (double) source.getHeight() / (double) source.getWidth();
        targetHeight = (int) (targetWidth * aspectRatio);
    } else {
        targetHeight = maxSizePixels;
        aspectRatio = (double) source.getWidth() / (double) source.getHeight();
        targetWidth = (int) (targetHeight * aspectRatio);
    }

    return Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
}
}

My app is made for social entertainment purpose so I don’t have storage access like before due to policies. so we can use only session scope way to access files. am getting error at line source.getHeight() and source.getWidth() as both are zero. Help me to fix this for all android versions this issue.

Update:
Getting error

Please note: I noticed this error comes in few pictures from gallery.

2

Answers


  1.  public File compressImage(File fileimage) {
            Bitmap icon = BitmapFactory.decodeFile(String.valueOf(fileimage));
            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
            icon.compress(Bitmap.CompressFormat.JPEG, 70, bytes);
            String folder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS + "/" + "Images") + "/";
            File directory = new File(folder);
            if (!directory.exists()) {
                directory.mkdirs();
            }
            File f = new File(folder + System.currentTimeMillis() + ".jpg");
            try {
                f.createNewFile();
                FileOutputStream fo = new FileOutputStream(f);
                fo.write(bytes.toByteArray());
            } catch (IOException e) {
                e.printStackTrace();
            }
            return f;
        }
    
    Login or Signup to reply.
  2. If you get a NullPointerException on source.getHeight() then this means source has been set to null.

    The only point where sourceis set is on the line

    source = decodeFile(file, MAX_SIZE_PIXELS, MAX_SIZE_PIXELS);
    

    This means the method decodeFile has to return a null value.

    Looking at the method decodeFile you can see tha there are only two different code paths that return a value. The first code path returns the value of BitmapFactory.decodeStream(..) which AFAIK should never return null.

    The it is most likely the other code path in the FileNotFoundException catch clause.

    public static Bitmap decodeFile(File file, int width, int height) {
        try {
            ....
            return BitmapFactory.decodeStream(new FileInputStream(file), null, newOptions);
    
        } catch (FileNotFoundException e) {
            return null;
        }
    }
    

    This leads to the conclusion that at some point you are trying to read a File that does not exist or on that you don’t have read permissions.

    As your app is older the chance is high that if it is a permission problem and the file is on the shared storage (/sdcard or subfolder) this is because the app does not make use of scoped storage system introduced with Android 10/11.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search