Android-universal-image-loader: EXIF Orientation bug

Created on 4 Mar 2014  ·  37Comments  ·  Source: nostra13/Android-Universal-Image-Loader

Hello,
I'm using UIL 1.9.1 in my recent project. I saw that UIL is now supporting EXIF orientation https://github.com/nostra13/Android-Universal-Image-Loader/issues/172 but I encountered issue when loading photos from SD card. In my application image is rotated by 90 degrees, but in Android gallery everything is ok.

Screens:

Code:
ImageLoader.getInstance().displayImage("file:///" + currentPhotoAbsolutePath, imageView, ImageLoaderOptions.GALLERY);

public static DisplayImageOptions GALLERY = new DisplayImageOptions.Builder()
.cacheInMemory(true)
.build();

According to https://github.com/nostra13/Android-Universal-Image-Loader/issues/172#issuecomment-17120841 it should work because I'm loading local files.

The problem occurs on:

  • Samsung Galaxy S (Cyanogenmod 11)
  • Xperia s LT26i (Android 4.1.2)
Bug

Most helpful comment

Hi, @Ziem
I consider this is not an issue. Have you tried to set considerExifParams(true) and cacheOnDisc(true) to your DisplayImageOption which you use in ImageLoader.displayImage() method?

All 37 comments

Hi, @Ziem
I consider this is not an issue. Have you tried to set considerExifParams(true) and cacheOnDisc(true) to your DisplayImageOption which you use in ImageLoader.displayImage() method?

You are right. I overlooked it. considerExifParams(true) solved my problem, thanks.

It really helped me to solve this problem.

Thanks a lot. This is really awesome library.

hi :I used the 1.9.2 jar and set considerExifParams(true) and cacheOnDisc(true) but this problem is also exist

@carl1990 I have the same problem

Can you provide image URL which is displayed wrong?

sorry! I am in debug environment use company intranet,so the url u can not access.

before is wrong

    public static DisplayImageOptions getDefaultDisplayImageOptions(
            Context context) {
        return new DisplayImageOptions.Builder()
                .showImageOnLoading(R.drawable.ic_default)
                .showImageForEmptyUri(R.drawable.ic_default)
                .showImageOnFail(R.drawable.ic_default)
                .cacheInMemory(true)
                .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2)
                .cacheOnDisk(true)
                .considerExifParams(true)
                .displayer(
                        new RoundedBitmapDisplayer(context.getResources()
                                .getDimensionPixelSize(R.dimen.icon_rounded)))
                .build();
    }

after is right

    public static DisplayImageOptions getDefaultDisplayImageOptions(
            Context context) {
        return new DisplayImageOptions.Builder()
                .showImageOnLoading(R.drawable.ic_default)
                .showImageForEmptyUri(R.drawable.ic_default)
                .showImageOnFail(R.drawable.ic_default)
                .cacheInMemory(true)
                .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2)
                .cacheOnDisk(true)
                .considerExifParams(false)
                .displayer(
                        new RoundedBitmapDisplayer(context.getResources()
                                .getDimensionPixelSize(R.dimen.icon_rounded)))
                .build();
    }

When I set "considerExifParams (true)",the picture displayed on the phone in the wrong direction.But when I open the SD card cache files and found the picture in the right direction,this is really incredible.

After several attempts, I set "considerExifParams (false)",the picture displayed on the phone in the right direction.
notes:
(1) My program set the phone to force portrait.
(2) Only a few pictures displayed incorrectly direction.
(3) I use the jar version 1.9.3.

@ihenk I tested your link and realized this weird behavior. It seems this image is rotated during decoding into Bitmap. I'll investigate this case.

I faced this issue now. I also try considerExifParams on both true and false but the image still rotate 90 degree.
I use version 1.9.3. Here is my display image configure:

 mDisplayImageOptions = new DisplayImageOptions.Builder()
                .cacheInMemory(true)
                .imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2)
                .bitmapConfig(Bitmap.Config.ARGB_4444)
                .considerExifParams(false)
                .build();

Can someone help me to point out the issue here?

I also meet the problem.
I'm making gallery feature, so I need to load images from MediaStore.
Original image files works well when I set considerExifParams to true.(otherwise it rotated wrongly)

But when I use MediaStore.Image.Thumbnail.Data, the Image rotated wrongly even though I set considerExifParams to true.

I also set cacheOnDisk, but it doesn't solve the problem.

To make gallery for images, I am using below code to query Media Store:
final String[] columns = { MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID,
MediaStore.Images.Media.MIME_TYPE, MediaStore.Images.Media.DISPLAY_NAME, MediaStore.Images.Media.SIZE};
final String orderBy = MediaStore.Images.Media._ID;
Cursor imageCursor = managedQuery(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns,
null, null, orderBy);
if (imageCursor != null && imageCursor.getCount() > 0) {

                while (imageCursor.moveToNext()) {
                    CustomGalleryItem item = new CustomGalleryItem();

                    int dataColumnIndex = imageCursor
                            .getColumnIndex(MediaStore.Images.Media.DATA);

                    item.sdcardPath = imageCursor.getString(dataColumnIndex);

                    int mimeTypeColumnIndex = imageCursor.getColumnIndex(MediaStore.Images.Media.MIME_TYPE);
                    item.mimeType = imageCursor.getString(mimeTypeColumnIndex);

                    int idColumnIndex = imageCursor.getColumnIndex(MediaStore.Images.Media._ID);
                    item.id = imageCursor.getString(idColumnIndex);

                    int nameColumnIndex = imageCursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME);
                    item.fileName = imageCursor.getString(nameColumnIndex);

                    int sizeColumnIndex = imageCursor.getColumnIndex(MediaStore.Images.Media.SIZE);
                    item.fileSize = imageCursor.getString(sizeColumnIndex);

                    if(selectedList != null && selectedList.size() > 0) {
                        for(CustomGalleryItem selectedItem : selectedList) {
                            if(selectedItem.id.equals(item.id)) {
                                item.isSeleted = true;
                                break;
                            }
                        }
                    }
                    galleryList.add(item);
                }
            }

To initialize Image Loader, I have used below code:

DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
.imageScaleType(ImageScaleType.EXACTLY_STRETCHED)
.bitmapConfig(Bitmap.Config.RGB_565)
.considerExifParams(true).build();
ImageDecoder smartUriDecoder = new SmartUriDecoder(this, getContentResolver(), new BaseImageDecoder(false));

    ImageLoaderConfiguration.Builder builder = new ImageLoaderConfiguration.Builder(
            this).defaultDisplayImageOptions(defaultOptions).memoryCache(
                    new WeakMemoryCache())
                    .imageDecoder(smartUriDecoder);

    ImageLoaderConfiguration config = builder.build();
    ImageLoader imageLoader = ImageLoader.getInstance();
    imageLoader.init(config);

I have written custom ImageDecoder because Universal Image loader works properly to show image thumbnail. But I wanted to show thumbnail for videos, audios as well.

I am using "universal-image-loader-1.9.2-SNAPSHOT-with-sources"

The same issue for me. Both
.considerExifParams(false)
and
.considerExifParams(true)

leads to the same result - not properly rotated photo for portrait made images. Landscape photo is shown properly.

universal-image-loader:1.9.4

Hello i faced the problem in U.I.L. V-1.9.4.Please share the findings and fix the bug.I think it is one of the major bug of this library as they offered that feature with a heavy note.

Until the problem is fixed, I used Picasso. It automatically solves this.

@Cedriga The Picasso has the same problem in SAMSUNG NOTE III with android 4.4

Actually .considerExifParams(true) works for me. However make sure that you setup options and pass them to ImageLoader on any activity where you display images, Gallery, ImageDetail etc... Here is my code:

DisplayImageOptions options = new DisplayImageOptions.Builder()
                .showImageOnLoading(R.drawable.blank)
                .showImageForEmptyUri(R.drawable.blank)
                .showImageOnFail(R.drawable.blank)
                .cacheInMemory(true)
                .cacheOnDisk(true)
                .considerExifParams(true)
                .bitmapConfig(Bitmap.Config.RGB_565)
                .build();

imageLoader.displayImage(GalleryActivity.mThumbIds[position] ,imageView, options);

My activity view is in landscape mode.

I am using all but still image is set rotate on image view.

options = new DisplayImageOptions.Builder()
.showImageOnLoading(android.R.color.white)
.showImageForEmptyUri(android.R.color.white)
.showImageOnFail(android.R.color.white)
.imageScaleType(ImageScaleType.EXACTLY)
.cacheInMemory(true)
.cacheOnDisk(true)
.considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.build();

The same issue for me. Both
.considerExifParams(false)
and
.considerExifParams(true)

It's more of a compatibility issue in KitKat, Lollipop I think.
Here is another thread https://github.com/square/picasso/issues/579
I'm using Picasso and having this issue.
I'll use and see if UIL gives solution.

you need override the BaseImageDecoder.class and override the canDefineExifParams method,add image/png mimetype,then everything is ok

Is this solved?

sorry ,no...

------------------ 原始邮件 ------------------
发件人: "Jorge Garrido";[email protected];
发送时间: 2016年4月1日(星期五) 下午3:22
收件人: "nostra13/Android-Universal-Image-Loader"[email protected];

主题: Re: [nostra13/Android-Universal-Image-Loader] EXIF Orientation bug(#559)

Is this solved?


You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub

i got the reason,that is because of mimeType in method canDefineExifParams(String imageUri, String mimeType) of the class BaseImageDecoder you should add "image/png" in this method.
I did it like this,and it works.

在 2016-04-01 15:25:18,"dylan" [email protected] 写道:
sorry ,no...

------------------ 原始邮件 ------------------
发件人: "Jorge Garrido";[email protected];
发送时间: 2016年4月1日(星期五) 下午3:22
收件人: "nostra13/Android-Universal-Image-Loader"[email protected];

主题: Re: [nostra13/Android-Universal-Image-Loader] EXIF Orientation bug(#559)

Is this solved?


You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub


You are receiving this because you commented.
Reply to this email directly or view it on GitHub

Some sample code @rx123rx ?

thanks ,i try it later...

------------------ 原始邮件 ------------------
发件人: "Monkey.D.Ren";[email protected];
发送时间: 2016年4月1日(星期五) 下午3:42
收件人: "nostra13/Android-Universal-Image-Loader"[email protected];
抄送: "kevin"[email protected];
主题: Re: [nostra13/Android-Universal-Image-Loader] EXIF Orientation bug(#559)

i got the reason,that is because of mimeType in method canDefineExifParams(String imageUri, String mimeType) of the class BaseImageDecoder you should add "image/png" in this method.
I did it like this,and it works.

在 2016-04-01 15:25:18,"dylan" [email protected] 写道:
sorry ,no...

------------------ 原始邮件 ------------------
发件人: "Jorge Garrido";[email protected];
发送时间: 2016年4月1日(星期五) 下午3:22
收件人: "nostra13/Android-Universal-Image-Loader"[email protected];

主题: Re: [nostra13/Android-Universal-Image-Loader] EXIF Orientation bug(#559)

Is this solved?


You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub


You are receiving this because you commented.
Reply to this email directly or view it on GitHub

You are receiving this because you commented.
Reply to this email directly or view it on GitHub

private boolean canDefineExifParams(String imageUri, String mimeType) {
if (mimeType == null) {
return false;
}
return ("image/jpeg".equalsIgnoreCase(mimeType) || "image/png".equalsIgnoreCase(mimeType)) && (Scheme.ofUri(imageUri) == Scheme.FILE);
}

because of the suffix of the pictures in the cache is .png,i just override this method like this.

在 2016-04-01 15:44:36,"Jorge Garrido" [email protected] 写道:

Some sample code @rx123rx ?


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub

ha ha ,thanks,may i take your contact information?

------------------ 原始邮件 ------------------
发件人: "Monkey.D.Ren";[email protected];
发送时间: 2016年4月1日(星期五) 下午3:52
收件人: "nostra13/Android-Universal-Image-Loader"[email protected];
抄送: "kevin"[email protected];
主题: Re: [nostra13/Android-Universal-Image-Loader] EXIF Orientation bug(#559)

private boolean canDefineExifParams(String imageUri, String mimeType) {
if (mimeType == null) {
return false;
}
return ("image/jpeg".equalsIgnoreCase(mimeType) || "image/png".equalsIgnoreCase(mimeType)) && (Scheme.ofUri(imageUri) == Scheme.FILE);
}

because of the suffix of the pictures in the cache is .png,i just override this method like this.

在 2016-04-01 15:44:36,"Jorge Garrido" [email protected] 写道:

Some sample code @rx123rx ?


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub

You are receiving this because you commented.
Reply to this email directly or view it on GitHub

does it work?

在 2016-04-01 15:45:42,"dylan" [email protected] 写道:
thanks ,i try it later...

------------------ 原始邮件 ------------------
发件人: "Monkey.D.Ren";[email protected];
发送时间: 2016年4月1日(星期五) 下午3:42
收件人: "nostra13/Android-Universal-Image-Loader"[email protected];
抄送: "kevin"[email protected];
主题: Re: [nostra13/Android-Universal-Image-Loader] EXIF Orientation bug(#559)

i got the reason,that is because of mimeType in method canDefineExifParams(String imageUri, String mimeType) of the class BaseImageDecoder you should add "image/png" in this method.
I did it like this,and it works.

在 2016-04-01 15:25:18,"dylan" [email protected] 写道:
sorry ,no...

------------------ 原始邮件 ------------------
发件人: "Jorge Garrido";[email protected];
发送时间: 2016年4月1日(星期五) 下午3:22
收件人: "nostra13/Android-Universal-Image-Loader"[email protected];

主题: Re: [nostra13/Android-Universal-Image-Loader] EXIF Orientation bug(#559)

Is this solved?


You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub


You are receiving this because you commented.
Reply to this email directly or view it on GitHub

You are receiving this because you commented.
Reply to this email directly or view it on GitHub


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub

@rx123rx Seems to work on Samsung devices... but Sony fails

i think u can watch the logcat ,have a look what kind of suffix of the pictures in the cache then add this kind of mimeType in that method.
Maybe it works.good luck!

在 2016-04-01 17:51:02,"Jorge Garrido" [email protected] 写道:

@rx123rx Seems to work on Samsung devices... but Sony fails


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub

And it works on my HTC M8 .

在 2016-04-01 17:51:02,"Jorge Garrido" [email protected] 写道:

@rx123rx Seems to work on Samsung devices... but Sony fails


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub

@nostra13 : I have tried this section of logic and it works in mine case.

http://stackoverflow.com/a/39226824/2382964

I just faced the same problem on samsung devices but considerExifParams(true) just solved it.

Hello ,

I am using this universal image loader lib for caching images.
But when I received the image i am adding the encryption on file and decryption while the decode is called.
I am facing issue of Samsung devices , As my image is get rotated.
exif param is not applying at this time. please help if anyone has fixed this issue .

my code is :
For Encryption is
`@Override
public boolean save(String imageUri, InputStream imageDataStream, IoUtils.CopyListener listener) throws IOException {

    InputStream imageStream = EncryptionHandler.getSecureInputStream(imageDataStream, EncryptionHandler.MODE_ENCRYPT, ImageDbEncryptionAlgo.getInstance());
    File imageFile = getFile(imageUri);
    File tmpFile = new File(imageFile.getAbsolutePath() + TEMP_IMAGE_POSTFIX);
     boolean loaded = false;
    try {
        OutputStream os = new BufferedOutputStream(new FileOutputStream(tmpFile), bufferSize);
        try {
            loaded = IoUtils.copyStream(imageStream, os, listener, bufferSize);
          } finally {
            IoUtils.closeSilently(os);
        }
    } finally {
        if (loaded && !tmpFile.renameTo(imageFile)) {
            loaded = false;
        }
           if (!loaded) {
            tmpFile.delete();
        }
        if(imageStream !=null){
            IoUtils.closeSilently(imageStream);
        }
        if(imageDataStream !=null){
            IoUtils.closeSilently(imageDataStream);
        }
        imageStream =null;
        imageDataStream =null;
    }
    return loaded;
}

`` @Override public boolean save(String imageUri, Bitmap bitmap) throws IOException { File imageFile = getFile(imageUri); File tmpFile = new File(imageFile.getAbsolutePath() + TEMP_IMAGE_POSTFIX); OutputStream os = new BufferedOutputStream(new FileOutputStream(tmpFile), bufferSize); boolean savedSuccessfully = false; try { savedSuccessfully = EncryptionHandler.encryptBitmap(bitmap, tmpFile.getAbsolutePath(),ImageDbEncryptionAlgo.getInstance()); } finally { IoUtils.closeSilently(os); if (savedSuccessfully && !tmpFile.renameTo(imageFile)) { savedSuccessfully = false; } if (!savedSuccessfully) { tmpFile.delete(); } } bitmap.recycle(); return savedSuccessfully; }

For decryption code is : 

public Bitmap decode(ImageDecodingInfo decodingInfo) throws IOException {
Bitmap decodedBitmap;
ImageFileInfo imageInfo;
InputStream decryptedStream =null;
InputStream imageStream = getImageStream(decodingInfo);
if (imageStream == null) {
L.e("Error no image stream", decodingInfo.getImageKey());
return null;
}
try {
String imageKey = decodingInfo.getImageUri();

        boolean isLocalImage= isLocalCachedFile(imageKey);
        if (isLocalImage) {
            decryptedStream = EncryptionHandler.getSecureInputStream(imageStream, EncryptionHandler.MODE_DECRYPT, ImageDbEncryptionAlgo.getInstance());
        } else {
            decryptedStream = imageStream;
        }


        imageInfo = defineImageSizeAndRotation(decryptedStream, decodingInfo);

        decryptedStream = resetStream(decryptedStream, decodingInfo);

        BitmapFactory.Options decodingOptions = prepareDecodingOptions(imageInfo.imageSize, decodingInfo);
        decodedBitmap = BitmapFactory.decodeStream(decryptedStream, null, decodingOptions);
    } finally {
        IoUtils.closeSilently(decryptedStream);
        IoUtils.closeSilently(imageStream);
    }

    if (decodedBitmap == null) {
        L.e(ERROR_CANT_DECODE_IMAGE, decodingInfo.getImageKey());
    } else {
        decodedBitmap = considerExactScaleAndOrientatiton(decodedBitmap, decodingInfo, imageInfo.exif.rotation,
                imageInfo.exif.flipHorizontal);
    }
            return decodedBitmap;
}

```

I used this;-
DisplayImageOptions options = new DisplayImageOptions.Builder()
.cacheInMemory(true)
.cacheOnDisk(true)
.displayer(new SimpleBitmapDisplayer())
.resetViewBeforeLoading(true)
.considerExifParams(true)
.build();

considerExifParams(true) worked for me.

Was this page helpful?
0 / 5 - 0 ratings