Reading Raw data from Bitmap files - android

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.

Related

Android BitmapFactory.decodeFile(path) always returns null

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);

Android: Attempting to Pass Bitmap as a Byte Array from One Activity to Another

I have been trying to pass a single byte array (compressed bitmap) from one activity to another. When I attempt to decode the byte array back to a bitmap, and show the bitmap, it appears to be a completely transparent bitmap.
I use this code on the first activity to compress the bitmap and send the byte array:
try {
InputStream selectedImage = getContentResolver().openInputStream(Uri.parse(photoPath));
bitmap = BitmapFactory.decodeStream(selectedImage);
} catch (FileNotFoundException exception) {
Log.e(this.toString(), exception.toString());
}
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte [] byteArray = stream.toByteArray();
Log.e("PANTHERIT_BYTEARRAY", byteArray.toString());
Intent stickerActivity = new Intent (this, StickerActivity.class);
stickerActivity.putExtra("byteArray", byteArray);
startActivity(stickerActivity);
And I use this code in the accepting activity to decompress and store the bitmap:
byte [] byteArray = getIntent().getByteArrayExtra("byteArray");
Log.e("STICKER_BYTEARRAY", byteArray.toString());
BitmapFactory.Options options = new BitmapFactory.Options();
options.inMutable = true;
bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length, options);
ImageView bitmapview = (ImageView) findViewById(R.id.bitmap_view);
bitmapview.setImageBitmap(bitmap);
I copied the code to the first activity, compressed the bitmap and immediately decompressed it. I took the decompressed bitmap and set it to an ImageView in that activity and it worked fine. So the error seems to be in the passing of the byte array from the first activity to the second, but I cannot figure out why that would be.
I found an answer. I do not really know why the byte array was getting messed up, maybe it was too large? Even so, both the input and output byte arrays were the same length, so not a very good explanation.
Anyway, I found my answer here: Send Bitmap Using Intent Android. The first answer by Zaid Daghestani is the same as what I initially tried, but his edit is what worked. Instead of passing a byte array, you save the compressed bitmap to a temporary file, and pass the filename through the intent. Definitely works for passing a bitmap, now I just have to figure out how to display the bitmap on a SurfaceView instead of an ImageView...
Also, just in case you need a mutable bitmap (in order to pass it to an ImageView) you can use:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inMutable = true;
bitmap = BitmapFactory.decodeStream(input, null, options);

Why the bitmap from res/raw folder is null?

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...

Loading a jpeg using BitmapRegionDecoder gives checkerboard distortion

I'm loading a big jpeg file from a url using an InputStream from a URLConnection. The goal is to get an int[] with the image data as this is more efficient than using a Bitmap for further use. There are two options here.
The first is to create a Bitmap object and to copy the results in an int[]. This works in my application but the full image is in memory twice upon loading as the image data is copied into the int[] image.
Bitmap full = BitmapFactory.decodeStream(conn.getInputStream());
full.getPixels(image, 0, width, 0, 0, width, height);
To save memory, I'm trying to perform this process in a tiled fashion using a BitmapRegionDecoder.
int block = 256;
BitmapRegionDecoder decoder = BitmapRegionDecoder.
newInstance(conn.getInputStream(), false);
Rect tileBounds = new Rect();
// loop blocks
for (int i=0; i<height; i+=block) {
// get vertical bounds limited by image height
tileBounds.top = i;
int h = i+block<height ? block : height-i;
tileBounds.bottom = i+h;
for (int j=0; j<width; j+=block) {
// get hotizontal bounds limited by image width
tileBounds.left = j;
int w = j+block<width ? block : width-j;
tileBounds.right = j+w;
// load tile
tile = decoder.decodeRegion(tileBounds, null);
// copy tile in image
int index = i*width + j;
tile.getPixels(image, index, width, 0, 0, w, h);
}
}
Technically this works and I get the full image in the int[] image. Also the tiles are seemlessly inserted into the image.
Now my problem. The second method results in an image which has some kind of strange checkerboard distortion. Pixels seem to alternate between being slightly darker or slightly lighter. BitmapRegionDecoder is supposed to support jpeg, and BitmapFactory.decodeStream has no problems. What is the problem here?
Found it! apparently if you feed null into decoder.decodeRegion(tileBounds, null); it returns a Bitmap with quality Bitmap.Config.RGB_565 (not sure if this is device dependant). Simply feeding it a new options set returns a Bitmap of Bitmap.Config.RGB_ARGB8888 quality. By default this preferred quality is set.
BitmapFactory.Options options = new BitmapFactory.Options();
...
// load tile
tile = decoder.decodeRegion(tileBounds, options);
Thanks for your self-investigation!
Though I would recommend avoid relying on some default and make it clear:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig=Config.ARGB_8888; //explicit setting!
result_bitmap=regionDecoder.decodeRegion(cropBounds, options);
Thanks!

Error:Bitmap size Exceed VM budget, when converting image to ARGB_8888

Here is my code:
File file = new File(Path to Jpeg File size is 700kb);
InputStream in = null;
try {
in = new BufferedInputStream(new FileInputStream(file));
}
catch (Exception e) {
// TODO: handle exception
}
bitmap =BitmapFactory.decodeStream(in);
bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
Please help i get error in this copy line i want to make its ARGB_8888 image.Need Help :(
You need to reduce the memory usage.
From you code, you first decode stream to one bitmap, and then copy it, which means you create two large bitmap objects.
You don't need to decode and then copy it, you can try
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888
// You can try value larger than 1
options.inSampleSize = 2 // If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save memory.
// Decode bitmap
bitmap = BitmapFactory.decodeStream(in, null, options)
In this case, there's only one bitmap created. And you set inSampleSize to large values to reduce the loaded bitmap size.

Categories

Resources