I load images from assets folder, but I have one problem.
The same image loaded from assets and resource are not same dimensions - resolution.
For getting image from assets I use this method:
AssetManager am=this.getAssets();
try {
Bitmap bmp = BitmapFactory.decodeStream(am.open("imgs/a.jpg"));
imageViewDraw.setImageBitmap(bmp);
} catch (IOException e) {
e.printStackTrace();
}
Output for the same image loaded from R.drawable and assets are on images
Can some one tell me why and how can I read image from assets, but resolution should be the same as from R.drawable ?
Thanks
If you are loading the bitmap to an Imageview use the scaleType and adjustViewbounds parameters. So for example in XML:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="centerInside" />
The thing is that when you load images from the assets directory the system doesn't apply any scaling or processiong whatsoever to your bitmaps, instead when using the drawable folder, android tries to scale your image according to your device's resolution.
So the only real way to have the exact same result is to use a fixed size for the imageview, ideally you should specify it in dps and ideally you should put that value on a dimens.xml file so you can change that value for various system configurations
You need to use setDrawable instead with a scaled drawable.
imageView.setImageDrawable(new BitmapDrawable(getContext().getResources(),bitmap));
This is also why the other method that does not get the getResources() parameter is deprecated, it will take care of the scalings in this case.
Related
Hi Am trying to implement image mapping as like html in android. For that i referred this project. Its work good when i access the image from drawable-nodpi folder. But when i access from other drawable folder the image get scaled as per the android concepts. Here i used drawable folder for checking purpose only. Actually i get image from back end service.
I also tried with bitmap by setting the no density.
Bitmap bm;
bm=BitmapFactory.decodeResource(getResources(), R.drawable.blueprint);
bm.setDensity(Bitmap.DENSITY_NONE);
mImageMap.setImageBitmap(bm); //mImageMap is customized view which extends Imageview
But it's not working. Am also tried as per this post. Its not working.Is there any way to load image to image view without scaling?
you can use Bitmap.createScaledBitmap with the orignal mesaures of the picture..
int width = orignal bitmap width
int height = orignal bitmap height
Bitmap bm;
bm = getBitmap... from network
bm = Bitmap.createScaledBitmap(bm,width,height,true);
this will create a image scaled properly and just place it in the ImageView.
My app has an Activity that displays a vertically scrolling list of ImageButtons. I want each buttons image to (A) come from the assets folder and (B) retain it's aspect ratio as it scales. Unfortunately, my ImageButton doesn't size correctly when it's image comes from the assets folder.
ImageButton src set from drawable
The first screenshot is my test app where the images all come from my apps drawables. That's the "correct" aspect ratio for that image, which is what I want to keep (all of the image buttons have been given scaleType "fitXY" "centerCrop").
ImageButton src set from assets
The second screenshot is my test app where the images all come from my apps "assets" folder — as you can see, the images are stretched out to the full width of the screen as desired, but the original aspect ratio has been lost:
Activity code (MainActivity.java)
LinearLayout buttons = (LinearLayout) findViewById(R.id.buttons);
View button = layoutInflater.inflate(R.layout.snippet_imagebutton, null);
ImageButton imageButton = (ImageButton) button.findViewById(R.id.imageButton);
if (GET_IMAGE_FROM_ASSETS) {
InputStream s = assetManager.open("image.png");
Bitmap bmp = BitmapFactory.decodeStream(s);
imageButton.setImageBitmap(bmp);
} else {
imageButton.setImageResource(R.drawable.image);
}
TextView buttonText = (TextView) button.findViewById(R.id.textView);
buttonText.setText("Button text!");
buttons.addView(button,
new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
Button layout (snippet_imagebutton.xml)
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp">
<ImageButton
android:id="#+id/imageButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true" />
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:gravity="center"
android:textColor="#FFF"
android:background="#88000000"
android:textAppearance="?android:attr/textAppearanceMedium" />
</RelativeLayout>
Dodgy hack
I've found a dodgy hack which achieves what I want and illustrates the problem — the ImageButton will size correctly to match a scaled up image from the resources, but it won't size correctly to match a scaled up image from the assets. I'd prefer a "real" solution over the dodgy hack if there is one. :)
// to start with, scale the ImageButton based on an image in our
// resources that has the same dimensions as the image in our assets
imageButton.setImageResource(R.drawable.image);
// when we eventually render (we don't have width / height yet)...
imageButton.post(new Runnable() {
public void run() {
int height = imageButton.getHeight();
int width = imageButton.getWidth();
// replace our "resource" image with our "asset" image
imageButton.setImageBitmap(bmp);
// and force the ImageButton to keep the same scale as previously
imageButton.setLayoutParams(
new RelativeLayout.LayoutParams(width, height));
}
});
Summary
I want to get the images for these buttons from my apps "assets" folder. How do I fix my app so that the button images are all scaled properly (i.e. retain their original aspect ratio)?
I'm assuming this has something to do with the framework not actually knowing the width / height of the image before it renders the ImageButton to screen — so how do I fix that? I tried setting adjustViewBounds to "true" on both the RelativeLayout and the ImageButton itself, but that didn't seem to have any effect.
The aspect ratio is not kept when you give the scale type attribute as "fitXY". Try "center", "center_crop" or "center_inside" according to your needs. Check ImageViewScaleType as well.
From what I gather, AdjustViewBounds is actually the method that provides the exact functionality you need. However, as Roman Nurik explains here, AdjustViewBounds does NOT increase the ViewBounds beyond the natural dimensions of the drawable.
Without seeing how you allocated resources/assets, my suspicion would be that this is why you see a difference when loading from Resources and when loading from Assets. Your resource file is - presumably - being scaled up when you load it (since that is the default behavior for resources), so that the actual size of the drawable returned from /res is significantly larger than the bitmap you decode from /assets.
Overriding ImageButton (as Nurik suggests), is of course one option, but probably overkill.
Assuming I am correct about the problem, you should be able to fix it simply by setting your BitmapFactory.options correctly when you load the Assets file. You need to set inDensity and inTargetDensity correctly according to your device (get DisplayMetrics), and set inScaled to true.
Alternatively, you can always rescale the bitmap manually before loading it on the ImageButton. Just grab the screen width to determine how large you need to make it.
P.S.
Auto-scaling is obviously the elegant solution, but it does have a weakness (which applies equally to both resources and assets) - if the width of your display > bitmap witdh when scaled up, you'll likely still have the aspect ratio messed up. You can check this pretty easily by going to landscape mode and seeing whether the resource file still result in the right aspect ratio. If you have a large enough base image (or use different layouts according to the screen size/orientation), then this should not be a problem though. Just something to keep in mind.
I have a frame layout encompassing an imageview that's supposed to update the image it's showing when the user presses the next button (think of a slideshow). All the images that I want to thusly put in this imageview are of the same dimensions. The initial image that's shown by the imageview at the start of the activity is in the res/drawable-hdpi directory, while the other images live in the assets directory. The problem is that the images that I swap into the imageview appear smaller than the first image although all these images are of the same size.
With regard to layout parameters, my frame layout's layout_width and layout_height are set to wrap_content and so is the imageview, I tried setting the scaleType parameter to every possible value and I still see the same results. So unless the images stored in res/drawable-hdpi and assets are somehow scaled differently this behavior shouldn't happen.
So, what's the best approach to preserve the dimensions of the imageview as the user cycles through these images?
Here is my XML for the frame layout & my imageview
<FrameLayout
android:id="#+id/coverLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" >
<ImageView
android:id="#+id/coverImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="false"
android:scaleType="fitCenter"
android:src="#drawable/coverImage" />
</FrameLayout>
Here is my code that loads new images into my imageview
_coverImageView = (ImageView) findViewById(R.id.coverImageView);
...
...
if (loadNewImage) {
AssetManager assetMgr = getAssets();
InputStream stream;
try {
stream = assetMgr.open("covers/" + _coverImageName);
Drawable coverDrawable = Drawable.createFromStream(stream, _coverImageName);
_coverImageView.setImageDrawable(coverDrawable);
}
catch (IOException ex) {
System.out.println(ex);
}
}
So unless the images stored in res/drawable-hdpi and assets are somehow scaled differently this behavior shouldn't happen.
This is exactly the issue. Android scales bitmaps based on several rules including the density (class) of the screen and which resource folder the bitmap was from. See this related question/answer. If you want the same behavior for both assets and resources, you can put the initial cover image in drawable-nodpi instead of drawable-hdpi.
I would like to display an image from external storage which is 72x72 px.
My device has high density.
The image view height and width are "wrap_content".
I got different results if I load the image or use an URL.
If I use an URL like this then the result will be about 48x48px.
imageView.setImageURI(Uri.fromFile(file));
If I load the bitmap the result is 72x72 px as expected:
InputStream is = context.getContentResolver().openInputStream(Uri.fromFile(file));
Bitmap b = BitmapFactory.decodeStream(is, null, null);
is.close();
iv2.setImageBitmap(b);
You can see the results here:
It would be better if I could use the setImageURI and not to preload
the image and I would like to display the image in appwidgets too.
Can you tell me what cause the difference and how can I avoid it?
try by this i think it work
either change in xml file in imageview by
android:scaleType="centerCrop"
android:adjustViewBounds="true"
or either use in java code
image.setAdjustViewBounds(true);
image.setScaleType(ScaleType.CENTER_CROP);
either use "centercrop" or "fitxy" may it also works
If both images have different sizes and you can't change the image size you have to set in your xml the image width and height to for example 72dp. You shouldn't use px, but dp because otherwise it wouldn't display good on different phones.
I updated my build to build against Android 1.6, and now my bitmaps are scaled down on high density screens. I do NOT want this behavior. I gave this a shot:
http://blog.tomgibara.com/post/190539066/android-unscaled-bitmaps
but the images are STILL scaling, that is UNLESS I set them to a specific height & width. If I use wrap_content they are scaled down.
I have an image loader using the unscaled bitmap loader to create a drawable like so:
Bitmap bm = UnscaledBitmapLoader.loadFromResource(imageBufferInputStream);
drawable = new BitmapDrawable(bm);
which I later assign to an ImageView like so:
imageView.setImageDrawable( copyBitmapDrawable( (BitmapDrawable) drawable) );
In order to have an image not scaled when loading it from a resource (e.g. with BitmapFactory.decodeResource) you have to locate it in res/drawable-nodpi instead of the usual drawable, drawable-ldpi and so on.
Using
new BitmapDrawable(this.getResources(), bmp);
instead of
new BitmapDrawable(bmp);
should solve the issue.
Wrapping the bitmap with a Drawable is the problem. The Drawable scales the Bitmap. Instead of using a Drawable, assign the Bitmap to the ImageView directly using imageView.setImageBitmap(Bitmap).
Use ImageView.ScaleType. The CENTER constant preforms no scaling, so I guess that's what you are looking for.
By the way, do you use pixels or dips as size units? Using dips (density-independent-pixels) is a means of standardizing display on multiple resolutions. You'll find a couple of tips here.