2
votes

I'm trying to decode an inputstream to bitmap, the code is so simple :

Bitmap myBitmap = BitmapFactory.decodeStream(myStream);

BUT the quality of outputed bitmap is too low (sometimes, and sometimes the quality is good).

also the source has a good quality image.

i tried to play with Bitmap options but nothing changed:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
options.inDither = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap myBitmap = BitmapFactory.decodeStream(myStream, null, options);

so, how can i get the full quality bitmap?

Update 1:

I use this picture for an animation, like below:

coverAnimationImage.post(new Runnable()
{
    Override
    public void run()
    {
        try
        {
            InputStream coverStream = getCoverStream();
            if(coverStream != null)
            {
                bookCover = BitmapFactory.decodeStream(coverStream);
            }
        }
        catch (Exception e)
        {
            //  no cover
        }
        coverAnimationImage.setImageBitmap(bookCover);
        mBackground = new ColorDrawable(Color.BLACK);
        if(Build.VERSION.SDK_INT >= 16)
        {
            coverAnimationLayout.setBackground(mBackground);
        }
        else
        {
           coverAnimationLayout.setBackgroundDrawable(mBackground);
        }
        if (flag)
        {
            ViewTreeObserver observer = coverAnimationImage.getViewTreeObserver();
            observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
            {
                @Override
                public boolean onPreDraw()
                {
                    coverAnimationImage.getViewTreeObserver().removeOnPreDrawListener(this);
                    int[] screenLocation = new int[2];
                    coverAnimationImage.getLocationOnScreen(screenLocation);
                    mLeftDelta = coverLeft - (screenLocation[0]);
                    mTopDelta = coverTop - (screenLocation[1]);
                    mWidthScale = (float) coverWidth / coverAnimationImage.getWidth();
                    mHeightScale = (float) coverHeight / coverAnimationImage.getHeight();
                    runEnterAnimation();
                    return true;
                }
            });
        }
    }
});

I think when i run the animation the BitmapFactory.decodeStream isn't finished it's job! is it possible? or any idea whats happening here?

Update 2: the image info

enter image description here

Update 3:

low quality image:

enter image description here

high quality:

enter image description here

memory monitor:

enter image description here

YouTube Video:

android BitmapFactory.decodeStream low quality

Update 4:

the code of getCoverStream :

protected InputStream getCoverStream() 
{    
    String fileName = getCoverAddress();
    InputStream in = null;
    ZipEntry containerEntry = mZip.getEntry(fileName);
    if (containerEntry != null) 
    {
        try 
        {
            in = mZip.getInputStream(containerEntry);
        } 
        catch (IOException e) 
        {
            Log.e(TAG, "Error reading zip file " + fileName, e);
        }
    }

    if (in == null) 
    {
        Log.e(TAG, "Unable to find file in zip: " + fileName);
    }

    return in;
}
1
The standard approach should work... DecodeStream will decode full quality graphics by default. I'm wondering if your resource folders are correctly configured. For example, if you place a high quality graphic in the 'ldpi' folder, and low quality graphics in the 'xxhdpi' folder, the environment may think it is choosing a high quality graphic, but ends up pulling out a low quality graphic. Perhaps we could better help if you told us the image resolutions being used in each of the asset folders? (ldpi / mdpi / hdpi / xhdpi / xxhdpi) - 1owk3y
@1owk3y The image i used to decode is not in the drawable folders. the image extracted as stream from an epub book. i can see the image has a good qality. - mehdok
Is the image 'progressive'? Perhaps it is only stopping as soon as it gets the first sample pass (low quality). Try a non-progressive image? (just eliminating the possibility before we dig further). If using a non-progressive image fixes the issue, then you'll know it's stopping after the first pass (and can find how to tell Android how to not stop after the first pass. Sorry, I'd look this up myself right now but I'm in transit) - 1owk3y
@1owk3y, ok, the image is a png , i tested it with exiftool http://www.sno.phy.queensu.ca/~phil/exiftool/ and posted the result to original question. the thing is the quality is random, suppose the first time i ran the code the quality is low and 4rd time is good. - mehdok
@1owk3y , ok i have done what you said and i saw that sometimes the getCoverStream wont call at all and as result the quality is low, the problem is i pass a preview of cover as an extra to the second activity and sometimes the activity use that preview for animation. You really helped me find the original problem so i want to give the bounty to you. Just post an answer and i will do that. - mehdok

1 Answers

2
votes

It may not actually be an issue with BitmapFactory.decodeStream(), because decodeStream decodes full resolution data by default.

We see that you're using ZipEntry. It could be an issue of the stream not fully downloading, or the stream (getCoverStream) not being invoked.

Try mZip.getSize(); mZip.getCompressedSize(); mZip.getCrc(); in LogCat. Do the results vary on download attempts with different qualities? I'm trying to determine if the zip download is stopping after a certain amount of time, gives up, and then just displays the information it has etc