Universal Image Loader get original image size

2019-07-18 06:30发布

问题:

I am using the Android-Universal-Image-Loader library to loading/caching remote images, and have been digging through the source for quite a while trying to find a way to retrieve the original image size (width and height) for my ImageLoadingListener.

The sample code below is just give you an idea of what I'm trying to do.

    protected class ViaImageLoadingListener implements ImageLoadingListener {
    final SelectableImageView selectableImageView ;


    protected ViaImageLoadingListener(SelectableImageView selectableImageView) {
        this.selectableImageView = selectableImageView;
    }

    @Override
    public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {

            selectableImageView.setImageBitmap(loadedImage);
            // loadedImage.getWeight() will not return the original 
            // dimensions of the image if it has been scaled down
            selectableImageView.setOriginalImageSize(width, height);
            selectableImageView.invalidate();


    }

I have tried extending the ImageDecoder class and the ImageLoader class to find a round-about way to linking the decoder (from which I can get the original image size in the #prepareDecodingOptions method) to my custom ImageLoadingListener. But the configuration object is private and the fields (including the decoder) are inaccessible from subclasses (and feels like an overly hacky way of solving the problem anyways).

Have I overlooked a simple "built-in" way of getting the original image size without losing the benefit of the UIL's scaling/memory management?

回答1:

There is no way to pass original image size from ImageDecoder to listener through params.

I think the solution for you is following. Extend BaseImageDecoder and create map in it for keeping image sizes:

Map<String, ImageSize> urlToSizeMap = new ConcurrentHashMap<String, ImageSize>();

Then override defineImageSizeAndRotation(...):

protected ImageFileInfo defineImageSizeAndRotation(InputStream imageStream, String imageUri) throws IOException {
    ImageFileInfo info = super.defineImageSizeAndRotation(imageStream, imageUri);
    urlToSizeMap.put(imageUri, info.imageSize); // Remember original image size for image URI
    return info;
}

Note: info.imageSize won't compile because imageSize isn't visible. I'll fix it in next version (1.8.5) but you can use reflection for now.

Set this decoder into configuration and keep reference to this decoder anywhere (or you can make urlToSizeMap static to access from listener).

Then in your listener:

@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
        selectableImageView.setImageBitmap(loadedImage);

        ImageSize imageSize = decoder.urlToSizeMap.get(imageUri);
        selectableImageView.setOriginalImageSize(imageSize.getWidth(), imageSize.getHeight());
        selectableImageView.invalidate();
}


回答2:

It seems that you do not have to implement own ImageLoadingListener if you want to get original size of loaded image. I use loadImage method and it seems recieved bitmap has origin sizes. UIL v1.8.6

  loader.loadImage(pin_url, option, new SimpleImageLoadingListener() {
        @Override
        public void onLoadingFailed(String imageUri, View view,
                                    FailReason failReason) {
            showErrorLayout();
        }

        @Override
        public void onLoadingComplete(String imageUri, View view,
                                      Bitmap loadedImage) {

             // width - device width
             // height - OpenGl maxTextureSize
            if (width < loadedImage.getWidth() || height < loadedImage.getHeight()) {
                // handle scaling
            }

            iv.setImageBitmap(loadedImage);


        }
    });