Android 4.0 ImageView setImageBitmap does not work - android

I develop a App with ffmpeg to decode a media frame. I filled a Bitmap object with the decode result and use ImageView.setImageBitmap to display the bitmap.
In Android 2.3 it works well, but in Android 4.0 or up it doesn't work.
The code is simply :
imgVedio.setImageBitmap(bitmapCache);//FIXME:in 4.0 it displays nothing
Then I tried write the Bitmap to a file and reload the file to display.
String fileName = "/mnt/sdcard/myImage/video.jpg";
FileOutputStream b = null;
try
{
b = new FileOutputStream(fileName);
bitmapCache.compress(Bitmap.CompressFormat.JPEG, 100, b);// write data to file
}
catch (FileNotFoundException e)
{
e.printStackTrace();
} finally
{
try
{
if(b != null)
{
b.flush();
b.close();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
Bitmap bitmap = BitmapFactory.decodeFile(fileName);
imgVedio.setImageBitmap(bitmap);
It works, but the performance is too poor.
So can someone help me resolve the problem?

I think it's an out of memory problem, you can fix it using this method :
private Bitmap loadImage(String imgPath) {
BitmapFactory.Options options;
try {
options = new BitmapFactory.Options();
options.inSampleSize = 2;
Bitmap bitmap = BitmapFactory.decodeFile(imgPath, options);
return bitmap;
} catch(Exception e) {
e.printStackTrace();
}
return null;
}
The "inSampleSize" option will return a smaller image and save memory. You can just call this in the ImageView.setImageBitmap :
imgVedio.setImageBitmap(loadImage(IMAGE_PATH));

Related

how can i use a picture for background of a button from assets? and how can i add different music in background for each layout? [duplicate]

i need to load a image from assets to avoid a froyo 2.2.2 bug resizing POT images in some particular cases. The way to avoid it is loading the image files from assets dir.
I'm trying to do with this:
String imagePath = "radiocd5.png";
AssetManager mngr = context.getAssets();
// Create an input stream to read from the asset folder
InputStream is = null;
try {
is = mngr.open(imagePath);
} catch (IOException e1) { e1.printStackTrace();}
//Get the texture from the Android resource directory
//InputStream is = context.getResources().openRawResource(R.drawable.radiocd5);
Bitmap bitmap = null;
try {
//BitmapFactory is an Android graphics utility for images
bitmap = BitmapFactory.decodeStream(is);
} finally {
//Always clear and close
try {
is.close();
is = null;
} catch (IOException e) {}
}
But i am getting NullPointerException on the line is.close();
i capture a FileNotFoundException: radiocd5.png, but that file is on my assets directory :S
What am i doing bad? The file is called radiocd5.png and it is on the assets directory
You can follow my tutorials on displaying data from Assets: https://xjaphx.wordpress.com/2011/10/02/store-and-use-files-in-assets/
The sample with loading image and text to display.
I now added the relevant part of the provided link
(in case of earthquake or something) ;-) Taifun
// load image
try {
// get input stream
InputStream ims = getAssets().open("avatar.jpg");
// load image as Drawable
Drawable d = Drawable.createFromStream(ims, null);
// set image to ImageView
mImage.setImageDrawable(d);
}
catch(IOException ex) {
return;
}
Instead of using the assets dir, put the file into /res/raw, and you can then access it using the following URI: android.resource://com.your.packagename/" + R.raw.radiocd5
try {
InputStream istr = this.context.getAssets().open(P.strImage);
//set drawable from stream
this.imgProduct.setImageDrawable(Drawable.createFromStream(istr, null));
} catch (IOException e) {
e.printStackTrace();
}
protected String openImageInAssets(String imageName) {
String encodedImageBase64 = "";
AssetManager assetManager = getAssets();
InputStream fileStream = null;
try {
fileStream = assetManager.open(imageName);
if (fileStream != null) {
// BitmapFactory.Options bfo = new BitmapFactory.Options();
// bfo.inPreferredConfig = Bitmap.Config.ARGB_8888;
// Bitmap bitmap = BitmapFactory.decodeStream(fileStream, null, bfo);
Bitmap bitmap = BitmapFactory.decodeStream(fileStream);
// Convert bitmap to Base64 encoded image for web
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
// to get image extension file name split the received
int fileExtensionPosition = imageName.lastIndexOf('.');
String fileExtension = imageName.substring(fileExtensionPosition+1);
// Log.d(IConstants.TAG,"fileExtension: " + fileExtension);
if (fileExtension.equalsIgnoreCase("png")) {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
// Log.d(IConstants.TAG,"fileExtension is PNG");
} else if (fileExtension.equalsIgnoreCase("jpg") || fileExtension.equalsIgnoreCase("jpeg")) {
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
// Log.d(TAG,"fileExtension is JPG");
}
byte[] byteArray = byteArrayOutputStream.toByteArray();
String imgageBase64 = Base64.encodeToString(byteArray, Base64.DEFAULT);
encodedImageBase64 = "data:image/png;base64," + imgageBase64;
}
} catch (IOException e) {
e.printStackTrace();
return encodedImageBase64="";
} finally {
//Always clear and close
try {
if (fileStream != null) {
fileStream.close();
fileStream = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}
// Log.d(TAG,"encodedImageBase64: " + encodedImageBase64);
return encodedImageBase64;
}
Here is an alternative way
setImageBitmap(BitmapFactory.decodeStream(assets.open("photo.jpg")))
Another version, inside a fragment:
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
root = inflater.inflate(R.layout.createrestaurant_layout, container, false);
Resources res = getResources();
img = (ImageView) root.findViewById(R.id.img);
AssetManager amanager = res.getAssets();
try {
InputStream imageStream = amanager.open("restaurant.jpg");
Drawable drawable = new BitmapDrawable(res, imageStream);
img.setImageDrawable(drawable);
} catch (Exception e) {
e.printStackTrace();
}
}
This process seems much simpler in iOS/UIKit or iOS/SwiftUI.

Bitmap size after using BitmapFactory.decodeStream

I am using BitmapFactory.decodeStream(inputStream) to create a bitmap. But the size of the bitmap returned by bitmap.getByteCount() is coming out be very huge compared to the actual image size. The actual image size when I download(on disk) is around 36kb, but the bitmap generated has a size of around 800kb. Since it is the same image, how come there is such a huge difference ? I am using the following piece of code.
Bitmap.Config.RGB_565 is helping me to reduce the size of the image
public Bitmap downloadImage(String imageUrl) {
Bitmap bitmap = null;
InputStream inputStream = null;
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
inputStream = (new URL(imageUrl)).openStream();
bitmap = BitmapFactory.decodeStream(inputStream, null, options);
Log.d("downloadImage","size of downloaded image " + bitmap.getByteCount()/1024);
return bitmap;
} catch (Exception e) {
}
finally {
try {
if(inputStream != null) {
inputStream.close();
}
} catch(Exception e) {
}
}
return bitmap;
}

Prevent bitmap being written to disk being scaled

I'm having an issue whereby when I write a bitmap to disk, it gets written to disk, however it gets written as a miniscule image (3kb or less in filesize).
I have checked that the source image is indeed the correct dimensions, however the output image seems shrunk despite configuring the bitmap options to not scale.
#Override
protected Void doInBackground(PPImage... params) {
String filename = "pp_" + position + ".jpg";
File externalStorageDirectory = Environment.getExternalStorageDirectory();
final File destination = new File(externalStorageDirectory, filename);
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 16;
opts.inPurgeable = true;
opts.inScaled = false;
decode(opts, Uri.parse(params[0].getUri()), getActivity(), new OnBitmapDecodedListener() {
#Override
public void onDecoded(Bitmap bitmap) {
try {
FileOutputStream out = new FileOutputStream(destination, false);
writeImageToFileTask.this.holder.pathToImage = destination.getAbsolutePath();
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
MediaStore.Images.Media.insertImage(getActivity().getContentResolver(), destination.getAbsolutePath(), destination.getName(), destination.getName());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
});
return null;
}
private void decode(BitmapFactory.Options options, Uri mUri, Context mContext, OnBitmapDecodedListener listener) {
try {
InputStream inputStream;
if (mUri.getScheme().startsWith("http") || mUri.getScheme().startsWith("https")) {
inputStream = new URL(mUri.toString()).openStream();
} else {
inputStream = mContext.getContentResolver().openInputStream(mUri);
}
Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options);
listener.onDecoded(bitmap);
} catch (Exception e) {
e.printStackTrace();
}
}
How do I ensure that the image being written to file is the same dimensions as the original source image?
You have specified sample size in your code, which will result in resizing:
opts.inSampleSize = 16;
Just remove this line, and the dimension of the output image should be the same.
About the usage of inSampleSize, according to official doc:
For example, inSampleSize == 4 returns an image that is 1/4 the
width/height of the original, and 1/16 the number of pixels. Any value
<= 1 is treated the same as 1.

Read images byte by byte from android internal storage takes too much time

I'm trying to display images from android internal storage, I have only 4images(the images are screen shots taked before), I display these images in a GridView, it works, but it takes too much time, this is my code :
FileInputStream fis = null;
DataOutputStream outWriter = null;
ByteArrayOutputStream bufStream = null;
String imageFile;
int occurence;
for (int i=0; i<4; i++) {
try {
occurence = i+1;
imageFile = "preview"+occurence+".png";
fis = openFileInput(imageFile);
bufStream = new ByteArrayOutputStream();
outWriter = new DataOutputStream(bufStream);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int ch;
byte[] data = null;
try {
**while((ch = fis.read()) != -1)
outWriter.write(ch);**
outWriter.close();
data = bufStream.toByteArray();
bufStream.close();
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
favorPreviews.add(BitmapFactory.decodeByteArray(data, 0, data.length)) ;
}
As you can see, I'm using FileInputStream to read them, but that reads the files byte by byte in this loop :
while((ch = fis.read()) != -1)
outWriter.write(ch);
And it takes too much time, is anyone know a faster way to read these images?
To be faster is indicated to reduced the image size. It can be done using the Bitmap decodeFile (String pathName, BitmapFactory.Options opts)
Look this example:
public Bitmap getReducedBitmap(String path) {
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inSampleSize=4; // reduced the image to 1/4 of the orignal size
return BitmapFactory.decodeFile(path, opt);
}
Use BitmapFactory.decodeFile(String) instead. Then all of this file reading is handled for you.

How to load a image from assets?

i need to load a image from assets to avoid a froyo 2.2.2 bug resizing POT images in some particular cases. The way to avoid it is loading the image files from assets dir.
I'm trying to do with this:
String imagePath = "radiocd5.png";
AssetManager mngr = context.getAssets();
// Create an input stream to read from the asset folder
InputStream is = null;
try {
is = mngr.open(imagePath);
} catch (IOException e1) { e1.printStackTrace();}
//Get the texture from the Android resource directory
//InputStream is = context.getResources().openRawResource(R.drawable.radiocd5);
Bitmap bitmap = null;
try {
//BitmapFactory is an Android graphics utility for images
bitmap = BitmapFactory.decodeStream(is);
} finally {
//Always clear and close
try {
is.close();
is = null;
} catch (IOException e) {}
}
But i am getting NullPointerException on the line is.close();
i capture a FileNotFoundException: radiocd5.png, but that file is on my assets directory :S
What am i doing bad? The file is called radiocd5.png and it is on the assets directory
You can follow my tutorials on displaying data from Assets: https://xjaphx.wordpress.com/2011/10/02/store-and-use-files-in-assets/
The sample with loading image and text to display.
I now added the relevant part of the provided link
(in case of earthquake or something) ;-) Taifun
// load image
try {
// get input stream
InputStream ims = getAssets().open("avatar.jpg");
// load image as Drawable
Drawable d = Drawable.createFromStream(ims, null);
// set image to ImageView
mImage.setImageDrawable(d);
}
catch(IOException ex) {
return;
}
Instead of using the assets dir, put the file into /res/raw, and you can then access it using the following URI: android.resource://com.your.packagename/" + R.raw.radiocd5
try {
InputStream istr = this.context.getAssets().open(P.strImage);
//set drawable from stream
this.imgProduct.setImageDrawable(Drawable.createFromStream(istr, null));
} catch (IOException e) {
e.printStackTrace();
}
protected String openImageInAssets(String imageName) {
String encodedImageBase64 = "";
AssetManager assetManager = getAssets();
InputStream fileStream = null;
try {
fileStream = assetManager.open(imageName);
if (fileStream != null) {
// BitmapFactory.Options bfo = new BitmapFactory.Options();
// bfo.inPreferredConfig = Bitmap.Config.ARGB_8888;
// Bitmap bitmap = BitmapFactory.decodeStream(fileStream, null, bfo);
Bitmap bitmap = BitmapFactory.decodeStream(fileStream);
// Convert bitmap to Base64 encoded image for web
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
// to get image extension file name split the received
int fileExtensionPosition = imageName.lastIndexOf('.');
String fileExtension = imageName.substring(fileExtensionPosition+1);
// Log.d(IConstants.TAG,"fileExtension: " + fileExtension);
if (fileExtension.equalsIgnoreCase("png")) {
bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
// Log.d(IConstants.TAG,"fileExtension is PNG");
} else if (fileExtension.equalsIgnoreCase("jpg") || fileExtension.equalsIgnoreCase("jpeg")) {
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
// Log.d(TAG,"fileExtension is JPG");
}
byte[] byteArray = byteArrayOutputStream.toByteArray();
String imgageBase64 = Base64.encodeToString(byteArray, Base64.DEFAULT);
encodedImageBase64 = "data:image/png;base64," + imgageBase64;
}
} catch (IOException e) {
e.printStackTrace();
return encodedImageBase64="";
} finally {
//Always clear and close
try {
if (fileStream != null) {
fileStream.close();
fileStream = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}
// Log.d(TAG,"encodedImageBase64: " + encodedImageBase64);
return encodedImageBase64;
}
Here is an alternative way
setImageBitmap(BitmapFactory.decodeStream(assets.open("photo.jpg")))
Another version, inside a fragment:
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
root = inflater.inflate(R.layout.createrestaurant_layout, container, false);
Resources res = getResources();
img = (ImageView) root.findViewById(R.id.img);
AssetManager amanager = res.getAssets();
try {
InputStream imageStream = amanager.open("restaurant.jpg");
Drawable drawable = new BitmapDrawable(res, imageStream);
img.setImageDrawable(drawable);
} catch (Exception e) {
e.printStackTrace();
}
}
This process seems much simpler in iOS/UIKit or iOS/SwiftUI.

Categories

Resources