I try to decode a bitmap(1920x1920) from res/raw folder,which is an png resource.I need the full-scale bitmap. I want to use the BimtapFactory.decodeFileDescriptor rather than BitmapFactory.decodeFile||decodeResource because the higher reliability than others to handle OOM:
While I try this code,The bitmap is NULL!!! But the file is not null. I've been playing hard.
Help Please!
Context mCtx=MainActivity.this;
Bitmap bm = null;
//id is the resId in res/raw
AssetFileDescriptor file =mCtx.getResources().openRawResourceFd(R.raw.skin_default_0);
bm = BitmapFactory.decodeFileDescriptor(file.getFileDescriptor(), null,
options);
InputStream bm = getResources().openRawResource(R.raw.splash);
BufferedInputStream bufferedInputStream = new BufferedInputStream(bm);
Bitmap bmp = BitmapFactory.decodeStream(bufferedInputStream);
int nh = (int) (bmp.getHeight() * (512.0 / bmp.getWidth()));
bmp = Bitmap.createScaledBitmap(bmp, 512, nh, true);
view.setImageBitmap(bmp);
Try this code.
Raw folder - keeping the files as uncompressed.
I dont think so , that the BitmapFactory.decodeFileDescriptor will give u efficient result when comparing with the BitmapFactory.decodeStream, Get the inputStream of the file and decode it. if u think the image is too big and u r using many images like this ur app is going to be very heavy, since the raw folder files willnt be compressed. if u want to scaled bitmap use the snippet code that i have added with my code. will give u a better understanding i thnk.
Thanks...
Related
I see that is a lot of solutions related to this issue, but none of this solved my problem.
I try to read image from png file to bitmap (image is very small ~16px so there is no option that I got OutOfMemoryException) using BitmapFactory.decodeFile(path) function.
My file hierarchy is as simple as possible:
-java
--example.com.app
---MainActivity.class
-res
--drawable
---array.png
I launch application from MainActivity and on button click I try to read png image to bitmap.
I try to read image to bitmap in the following ways:
String path = Uri.parse("android.resource://"+R.class.getPackage().getName() +"/drawable/arrow.png").toString();
Bitmap bitmap = BitmapFactory.decodeFile(path);
String path = Uri.parse("android.resource://drawable/arrow.png").toString();
Bitmap bitmap = BitmapFactory.decodeFile(path);
Everytime bitmap is null. Do you know where could be a problem?
Android API 27
Or use the simple method of BitmapFactory
BitmapFactory.decodeResource(getResources(), R.id.arrow);
Or you can use context.getDrawable(R.drawable.arrow) which will return a drawable that is ready to use.
Read more about this here
If you would like to still use the path then use java.nio.file.Paths(folder1, folder2.. .. .)
Read more about this here
You should use decodeResource, below is an example:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.arrow, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
Or use its simple way decodeResource.
BitmapFactory.decodeResource(getResources(), R.id.arrow);
I have some questions about Bitmap decode.
When I try to decode Bitmap from a byte[] array, using BitmapFactory.decodeByteArray, what is the difference between the param byte[] and the mBuffer byte[] in result bitmap. when the function return will the bitmap still hold reference to the byte[] param?
when I decode bitmap from a jpg file from sdcard using the following code:
File file = new File(getExternalCacheDir(), "large.jpg");
bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
if(mImageView != null){
mImageView.setImageBitmap(bitmap);
}
This jpg file has 10800*5400 resolution and 13.82M size, the result bitmap is not null, and there is no OOM error , but the bitmap not showing. How could that be ? I think in this case android should throw an OOM error so that I can catch it to try down scale the bitmap again. But it just shows nothing. It seems unreasonable. Does any know the reason?
Luckily, I found that when I set the layerType to LAYER_TYPE_SOFTWARE, the bitmap will show. So I believe there is a image size limit for hardware renderer.
I'am doing facedetection with the following java code as part of my project.iam getting a strange error
BitmapFactory.Options BitmapFactoryOptionsbfo = new BitmapFactory.Options();
/*BitMapFactory-Creates Bitmap objects from various sources, including
* files, streams, and byte-arrays.
*/
BitmapFactoryOptionsbfo.inPreferredConfig = Bitmap.Config.RGB_565;
imageWidth = myBitmap.getWidth();
imageHeight = myBitmap.getHeight();
myFace = new FaceDetector.Face[numberOfFace];
myFaceDetect = new FaceDetector(imageWidth, imageHeight, numberOfFace);
numberOfFaceDetected = myFaceDetect.findFaces(myBitmap, myFace);
}
//i get error over there in R.drawable.pics
myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pics, BitmapFactoryOptionsbfo);
I am supposed to give the name of the pic file in pics but it keeps giving me an error
pics cannot be resolved or is not a field. So I set the name of the pic file as pic PS it's a jpg file in the drawable folder. I also named the file within single quotes as 'pic' ---it gives me Invalid character constant error.
I also named it within double quotes but it still doesn't work. I also named it 'pic.jpg' still doesn't work
Possibly there is another variable in your code named 'pics'.
Try saving it in a different folder, say MyPics. And name the picture differently, say xyz1.jpg
In this case write the line as:
myBitmap = BitmapFactory.decodeResource(getResources(), R.MyPics.xyz1, BitmapFactoryOptionsbfo);
Also, did you initialise 'myBitmap' as a bitmap image? Meaning, did you include the line:
Bitmap myBitmap;
in your code, before performing the image read?
Just check with following line of code:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config RGB_565;
Bitmap bMap = BitmapFactory.decodeResource(getResources(), R.drawable.icon,options);
Let me know whether it works or not?
Also check image names which appears after you type R.drawable.
EDIT:
If still you are not able to access image from drawable, copy your image say pic.png to asset folder and access it using following code:
Updated Code:
try {
InputStream bitmap=getAssets().open("icon.png");
Bitmap bit=BitmapFactory.decodeStream(bitmap);
img.setImageBitmap(bit);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
I have a large number of resources in my drawable folder.All are having big size more than 500KB. I have to load all these 25 images all at once in a srollView. As usual I ran out of memory. Is there any way to reduce the size of the image programmatically.
I got this function but it's parameter is a File and I don't know how to create a File from a drawable.
private Bitmap decodeFile(File f){
Bitmap b = null;
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
FileInputStream fis = new FileInputStream(f);
BitmapFactory.decodeStream(fis, null, o);
fis.close();
int scale = 1;
if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) {
scale = Math.pow(2, (int) Math.round(Math.log(IMAGE_MAX_SIZE / (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5)));
}
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize = scale;
fis = new FileInputStream(f);
b = BitmapFactory.decodeStream(fis, null, o2);
fis.close();
} catch (FileNotFoundException e) {
}
return b;
}
I have to go thorugh this screen cyclically many times after a number of traversal the system is showing Low memory and it is removing the other views in the back from the stack , but I actually need it.
Please help me.
You can open an InputStream from your drawable resource using following code:
InputStream is = getResources().openRawResource(id);
here id is the identifier of your drawable resource. for eg: R.drawable.abc
Now using this input stream you can create a file. If you also need help on how create a file using this input stream then tell me.
Update: to write data in a file:
try
{
File f=new File("your file name");
InputStream inputStream = getResources().openRawResource(id);
OutputStream out=new FileOutputStream(f);
byte buf[]=new byte[1024];
int len;
while((len=inputStream.read(buf))>0)
out.write(buf,0,len);
out.close();
inputStream.close();
}
catch (IOException e){}
}
I like shortcuts so I prefer using this.
For creatting file from drawable see this.
Put this in your build.gradle
compile 'id.zelory:compressor:1.0.4'
And wherever you want to compress the image put
Bitmap compressedImageFile = Compressor.getDefault(context).compressToBitmap(your_file);
README.md provides much more information. Sorry for bringing the answer after 6 years.
bro there are two methods
Easiest one Use some 3rd party library
Or use Bitmap class to scale drawable down
just use Bitmap.createScaledBitmap method to compress drawables
steps :
// Step 1 Load drawable and convert it to bitmap
Bitmap b = BitmapFactory.decodeResource( context , resId )
// Step 2 reScale your Bitmap
Bitmap nBitmap = b.createScaledBitmap( getResources() , newHieght , newWidth , true );
// Step 3 Create a drawable from bitmap
BitmapDrawable drawable = new BitmapDrawable(nBitmap);
I highly recommend you to use 3rd part library because this method is very expensive
like https://github.com/Tourenathan-G5organisation/SiliCompressor
I took cue from #mudit's answer and created the drawable from Input Stream. And later loaded the drawable to the ImageView in the Adapter.
InputStream inputStream = mContext.getResources().openRawResource(R.drawable.your_id);
Bitmap b = BitmapFactory.decodeStream(inputStream);
b.setDensity(Bitmap.DENSITY_NONE);
Drawable d = new BitmapDrawable(b);
mImageView.setImageDrawable(d);
Here is the detailed version of solution
I'm trying to decode a .jpg file into a bitmap and reading the raw data from the Bitmap File.
The following is the code snippet of my app.
File file = new File(Environment.getExternalStorageDirectory(),"test.jpg");
int top = 450;
int left = 0;
int right= 1450;
int bottom = 2592;
int width = right-top;
int height = bottom-left;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), options);
Bitmap bitmapScaled = Bitmap.createBitmap(bitmap, top, left, width, height);
bitmap.recycle();
ByteBuffer buffer = ByteBuffer.allocate(width*height*4);
bitmapScaled.copyPixelsToBuffer(buffer);
bitmapScaled.recycle();
File file2 = new File(Environment.getExternalStorageDirectory(),"decodeFile");
FileOutputStream out = new FileOutputStream(file2.getAbsolutePath());
out.write(buffer.array());
In the above snippet, im trying to read the raw data from the Bitmap file into ByteBuffers and storing into a newly created file(decodeFile) in the SDCARD.
When i see the data in the "decodeFile" half of the data will becomes null, and the data is improper.
The above is one type of method of reading the raw data using Bitmap class methods.
When i follow the same thing by using the below code snippet, im getting the correct data.
BitmapRegionDecoder bitmapRegionDecoder = BitmapRegionDecoder.newInstance(file1.getAbsolutePath(), true);
Bitmap bitmap1 = bitmapRegionDecoder.decodeRegion(new Rect(top,left,width,height),options);
ByteBuffer buffer = ByteBuffer.allocate(width*height*4);
bitmapScaled.copyPixelsToBuffer(buffer);
bitmapScaled.recycle();
File file2 = new File(Environment.getExternalStorageDirectory(),"regionFile");
FileOutputStream out = new FileOutputStream(file2.getAbsolutePath());
out.write(buffer.array());
If i use this snippet, i'm getting the correct data. But the drawback of using BitmapRegionDecoder is memory Leakage. The application will lose 1.5 MB of memory everytime, it executes this API. This memory is not possible to get back to the application with GC also.
So can any body please help me how to copy the data from bitmap to another file without losing the data.. It will be very much helpful for me if any body respond to this..
Thanks in advance
See my answer to my own question here
You'll be interest in the onActivityResult method.