Resized Image File not overwriting existing?

The following code is a part of an image resize function. The resize function works fine if the output file is different to the target file. However if I try to overwrite the target file.....

try (final FileOutputStream stream = new FileOutputStream(output,false)) {
        Bitmap bitmap = BitmapFactory.decodeFile(target);
        Bitmap rBitmap = resizeBitmap(bitmap,size);
        rBitmap.compress(format, quality, (OutputStream) stream);
        stream.close();
      }

It should happily overwrite the "target" file if the "output" = "target", but it fails with the following error:

Attempt to invoke virtual method 'boolean android.graphics.Bitmap.compress(android.graphics.Bitmap$CompressFormat, int, java.io.OutputStream)' on a null object reference

which I presume relates to this line

rBitmap.compress(format, quality, (OutputStream) stream);

Something is happening to the "target" file because it is reduced to 0 bytes !!

What am I missing ?

Maybe you should try deleting the file first if it exists.

That had crossed my mind, but should not be necessary......

1 Like

Does the problem occur on all Android versions? So also on Android 5 or 9, for example?

Seems so, tested in companion on 10 and 13

You should test it on Android < 10.

Also fails on 7

What is the definition of the resizeBitmap function? Since you're getting a NPE when caling compress, it indicates rBitmap is null. It would be good to understand when resizeBitmap could return null and address that issue.

1 Like

It is a function that carries out the resizing and retains the aspect ratio. As I have said this works just fine when the target does not equal the output filename.

public static Bitmap resizeBitmap(Bitmap source, int maxLength) {
    try {
      if (source.getHeight() >= source.getWidth()) {
        int targetHeight = maxLength;
        if (source.getHeight() <= targetHeight) { // if image already smaller than the required height
          return source;
        }

        double aspectRatio = (double) source.getWidth() / (double) source.getHeight();
        int targetWidth = (int) (targetHeight * aspectRatio);

        Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
        return result;
      } else {
        int targetWidth = maxLength;

        if (source.getWidth() <= targetWidth) { // if image already smaller than the required height
          return source;
        }

        double aspectRatio = ((double) source.getHeight()) / ((double) source.getWidth());
        int targetHeight = (int) (targetWidth * aspectRatio);

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

      }

What catch clauses are there corresponding to the opening try? Are we sure that the source bitmap isn't null? Bitmap.createScaledBitmap doesn't appear to ever return null so there must be another code path being taken not captured.

Honestly, my guess is that because you are opening the target file before reading it, Android is truncating it which results in BitmapFactory.decodeFile returning null, which then cascades through the code until eventually you get the error you see. You may want to move the call to decodeFile outside of your try-with-resources from the first post. Also I'm not sure that our bundled version of dx handles desugaring try-with-resources for older versions of Android prior to Android N, so just be aware this may not work on Android versions prior to 7.

1 Like

I sensed it was probably a timing/file lock out type thing....

I will have a go at moving the target decode up the code, outside of the try/catch....

Yep, that fixed it :slight_smile:
Thanks @ewpatton @Anke

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.