issue displaying byte array to bitmap to fetch an image in android - java

I'm having problem converting byte array to bitmap. Now what I'm trying to achieve is I'm getting image as a byte array and trying to convert into bitmap so that I can display the image. but after running my below code in my bitmap output i'm getting Null value.
String t= "byte array of the image";
byte[] temp = t.getBytes() ;
Bitmap bmp = BitmapFactory.decodeByteArray(temp, 0, temp.length);
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
System.out.println("bitmap output"+bmp);
I have googled a lot and found this code works for every1. can please someone tell me where I'm doing wrong.
Thanks in advance

In my case this is working
String result = "here imge;
if (result != "") {
byte[] bloc = Base64.decode(result);
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap b = BitmapFactory.decodeByteArray(bloc, 0, bloc.length);

Try this way
String t= "byte array of the image";
byte[] temp = Base64.decode(t, Base64.NO_WRAP); //UPDATE HERE
Bitmap bmp = BitmapFactory.decodeByteArray(temp, 0, temp.length);
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
System.out.println("bitmap output"+bmp);

Related

How to create Bitmap from Android MediaImage in OUTPUT_IMAGE_FORMAT_RGBA_8888 format?

I am trying to use this new feature of CameraX Image Analysis (version 1.1.0-alpha08): using setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888), images sent to the analyzer will have RGBA format.
See this for reference: https://developer.android.com/reference/androidx/camera/core/ImageAnalysis#OUTPUT_IMAGE_FORMAT_RGBA_8888
I need to turn the image sent to the analyzer into a Bitmap so that I can input it to a TensorFlow classifier.
Without this new feature I would receive the image in the standard YUV_420_888 format then I would have to use one of the several solutions that can be googled in order to turn YUV_420_888 to RGBA then to Bitmap. Like this: https://blog.minhazav.dev/how-to-convert-yuv-420-sp-android.media.Image-to-Bitmap-or-jpeg/.
I assume getting the Media Image directly in RGBA format should help me avoid implementing those painfull solutions (that I have actually tried and do not seem to work very well for me so far).
Problem is I don't know how to turn this RGBA Media Image into a Bitmap. I have noticed that calling mediaImage.getFormat() returns 1 which is not an ImageFormat value but a PixelFormat one, the one logically corresponding to RGBA_8888 format, which is in line with the documentation: "All ImageProxy sent to ImageAnalysis.Analyzer.analyze(ImageProxy) will have format PixelFormat.RGBA_8888".
I have tried this:
private Bitmap toBitmapRGBA(Image image) {
Image.Plane[] planes = image.getPlanes();
ByteBuffer buffer = planes[0].getBuffer();
buffer.rewind();
int size = buffer.remaining();
byte[] bytes = new byte[size];
buffer.get(bytes);
Bitmap bitmapImage = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, null);
return bitmapImage;
}
This returns null indicating the decodeByteArray does not work. (I notice the image has got only one plane).
private Bitmap toBitmapRGBA2(Image image) {
Image.Plane[] planes = image.getPlanes();
ByteBuffer buffer = planes[0].getBuffer();
Bitmap bitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
buffer.rewind();
bitmap.copyPixelsFromBuffer(buffer);
return bitmap;
}
This returns a Bitmap that looks noting but noise.
Please help!
Kind regards
Mickael
I actually found a solution myself, so I post it here if anyone is interested:
private Bitmap toBitmap(Image image) {
Image.Plane[] planes = image.getPlanes();
ByteBuffer buffer = planes[0].getBuffer();
int pixelStride = planes[0].getPixelStride();
int rowStride = planes[0].getRowStride();
int rowPadding = rowStride - pixelStride * image.getWidth();
Bitmap bitmap = Bitmap.createBitmap(image.getWidth()+rowPadding/pixelStride,
image.getHeight(), Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);
return bitmap;
}
if you want to process the pixel array further on without creating a bitmap object you can do something like this:
val data = imageProxy.planes[0].buffer.toByteArray()
val pixels = IntArray(data.size / imageProxy.planes[0].pixelStride) {
var index = it * imageProxy.planes[0].pixelStride
(data[index++].toInt() and 0xff.shl(16)) or
(data[index++].toInt() and 0xff).shl(8) or
(data[index++].toInt() and 0xff).shl(0) or
(data[index].toInt() and 0xff).shl(24)
}
And then you can create bitmap this way:
Bitmap.createBitmap(
pixels,
0,
imageProxy.planes[0].rowStride / imageProxy.planes[0].pixelStride,
imageProxy.width,
imageProxy.height,
Bitmap.Config.ARGB_8888
)

animationDrawable only displays last frame

I'm trying to create an animation out of multiple png images. Here's my code:
AnimationDrawable animation = new AnimationDrawable();
for (int i = 0; i < translate_text.length(); i++)
{
byte[] byteArray = Base64.getDecoder().decode(client._fromServer.elementAt(i));
Bitmap bmp = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
ImageView image = (ImageView) findViewById(R.id.sign);
image.setImageBitmap(Bitmap.createScaledBitmap(bmp, image.getWidth(), image.getHeight(), false));
animation.addFrame(image.getDrawable(), 1000);
}
animation.setOneShot(true);
animation.start();
but this only displays the last frame... Any ideas?
Edit: Probably should've done this earlier, but here goes:
translate_text is a string. It represents the image sequence. For example if the string is "bob" then there should be 3 images: the letter B, the letter O and the letter B.
client._fromServer is a vector of strings. Each string is the image itself encoded in base64. That's why client._fromServer.elementsAt(i) is a string that needs to be decoded and turned into byteArray.
I think it is because you get the Drawable from the same ImageView.
When you do image.setImageBitmap() it updates the reference of the Drawable in the ImageView and the AnimationDrawable gets affected also.
You should use a different Drawable instance for each addFrame call.
Something like that:
AnimationDrawable animation = new AnimationDrawable();
ImageView image = (ImageView) findViewById(R.id.sign);
for (int i = 0; i < translate_text.length(); i++)
{
byte[] byteArray = Base64.getDecoder().decode(client._fromServer.elementAt(i));
Bitmap bmp = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
final Bitmap scaledBitmap = Bitmap.createScaledBitmap(bmp, image.getWidth(), image.getHeight(), false);
Drawable drawable = new BitmapDrawable(getResources(), scaledBitmap);
animation.addFrame(drawable, 1000);
}
animation.setOneShot(true);
animation.start();

how to decode byte array to bitmap without OOM Exception

I stuck in out of memory. I’m trying to load an image with byte array but what ever i’ve done it wouldn’t work. I get bitmap decoder error I guess. These are all code :
String password = prefs.getString("BookKey", "");
BufferedInputStream buf = new BufferedInputStream(new FileInputStream(file));
buf.read(bytes, 0, bytes.length);
buf.close();
byte[] bytesdecrpy = decrypt(bytes, password);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inDither = true;
options.inJustDecodeBounds = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
options.inTempStorage = new byte[32 * 1024];
options.inBitmap = BitmapFactory.decodeByteArray(bytesdecrpy, 0,
bytesdecrpy.length, options);
bm = Bitmap.createBitmap(options.outWidth,
options.outHeight, Bitmap.Config.ARGB_8888);
imageView.setImage(ImageSource.bitmap(bm));
I read as a byte array my encrypt png from device file but i having problem that when i create bitmap for bitmap variable. I still couldn’t run as well for 2 days. If anyone can help me to solve this problem it would be great. Thank you.
EDIT
I've tried only decode my byte array to bitmap like this but problem never changed i've started get problem in decode then
bm = BitmapFactory.decodeByteArray(bytesdecrpy, 0,
bytesdecrpy.length, options);
This can cause OOM Exception if the bitmap is too large
You could use a background thread to decode and load an image in the container
or use a caching technique as explained in https://developer.android.com/training/displaying-bitmaps/index.html

How to convert byteArray into bitmap image to show in an imageview in Android?

I have the following code for this purpose in my app but it does nothing, and halts the application:
bmImage.setImageBitmap(BitmapFactory.decodeByteArray(byteImage2, 0, byteImage2.length));
Try like this
Bitmap bmp = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
ImageView image = (ImageView) findViewById(R.id.imageView1);
image.setImageBitmap(bmp);
Then I suppose you draw the image too like this:
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
canvas.drawBitmap(bmImage, 0, 0, paint);
use below line to convert bytes into Bitmap, it is working for me.
Bitmap bmp = BitmapFactory.decodeByteArray(imageData, 0, imageData.length);
you need to put above line outside of loop, as it takes Bytes Array and convert into Bitmap.
P.S. :- here imageData is bytes array of Image
Try this :
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bg);
ByteArrayOutputStream blob = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.PNG, 95, blob);
byte[] bitmapdata = blob.toByteArray();
Bitmap bmp = BitmapFactory.decodeByteArray(bitmapdata , 0, bitmapdata .length);
ImageView image = (ImageView) findViewById(R.id.ivPhoto);
image.setImageBitmap(bmp);

encoding and decoding in JPG images in Android

I am creating an application over Android where I need to manipulate my JPG files. I am not getting much of header information for JPG format so for that I am converting it to Bitmap, manipulated the pixel values in bitmap and then again convert it back to JPG.
Here what problem I am facing is- after manipulating only some pixels of bitmap and
converting it back to JPG, I do not get the same set of pixels I got earlier (for those pixels which I did not manipulate). I am getting the same image as the original in the new image. But when I check new image pixels values for decoding, the untouched pixels are different...
File imagefile = new File(filepath);
FileInputStream fis = new FileInputStream(imagefile);
Bitmap bi = BitmapFactory.decodeStream(fis);
int intArray[];
bi=bi.copy(Bitmap.Config.ARGB_8888,true);
intArray = new int[bi.getWidth()*bi.getHeight()];
bi.getPixels(intArray, 0, bi.getWidth(), 0, 0, bi.getWidth(), bi.getHeight());
int newArray[] = encodeImage(msgbytes,intArray,mbytes); // method where i am manipulating my pixel values
// converting the bitmap data back to JPG file
bi = Bitmap.createBitmap(newArray, bi.getWidth(), bi.getHeight(), Bitmap.Config.ARGB_8888);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bi.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] data = baos.toByteArray();
Bitmap bitmapimage = BitmapFactory.decodeByteArray(data, 0, data.length);
String filepath = "/sdcard/image/new2.jpg";
File imagefile = new File(filepath);
FileOutputStream fos = new FileOutputStream(imagefile);
bitmapimage.compress(CompressFormat.JPEG, 100, fos);
Help me if I am wrong somewhere or whether I should use some other method to manipulate JPG pixel values...
JPEG is an image format that is usually based on lossy compression. That means that some information that is not important for the human eye is thrown away to further shrink the file size. Try to save your image as a PNG (a lossless format).
Be careful with using
Bitmap bi = BitmapFactory.decodeStream(fis);
bi = bi.copy(Bitmap.Config.ARGB_8888, true);
At the point where you have the first bi you may have already lost a lot of information, instead try using BitmapFactory.Options to force 8888 (which is the default too):
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
options.inDither = false;
Bitmap bi = BitmapFactory.decodeStream(fis, options);
If you stay with copy you should still recycle() the one that you throw away.

Categories