When I execute bitmap.getHeight(); I got a nullPointerException. This is how I try to get my bitmap:
In my json:"pic":"iVBORw0KGgoAAAANSUhEUgAAAgAAAAGACAIAAABUQk3......."
I retrieve from json the following:
byte[] decode = Base64.decode(jsonObj.getString("pic"), Base64.DEFAULT);
Log.i("size",decode.length+""); //65535
Bitmap pic = getImage(decode);
public static Bitmap getImage(byte[] image) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
return BitmapFactory.decodeByteArray(image, 0, image.length,options);
}
But I can't display the image.
Any ideas?
The error must be inside BitmapFactory.decodeByteArray and most probably the source of the problem is unsupported image format. Check that you pass base64 encoded jpeg, png, gif or bmp.
Also if you get 65535 as decode's size - it is very suspicious. Maybe the data is trimmed in database (if you have limit of 65535 for blob size) or somewhere else.
Related
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);
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.
Hello I have this piece of code:
EDIT:
imageName = data.getData();
try{
InputStream stream = getContentResolver().openInputStream(imageName);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
bitmap = BitmapFactory.decodeStream(stream,null,options);
final int REQUIRED_WIDTH=(int)screenWidth;
final int REQUIRED_HIGHT=(int)screenHeight;
int scale=1;
while(options.outWidth/scale/2>=REQUIRED_WIDTH && options.outHeight/scale/2>=REQUIRED_HIGHT)
scale*=2;
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
bitmap = BitmapFactory.decodeStream(stream, null, o2);
if ( bitmap != null ){
ok=true;
}
}catch(Exception e){
Toast.makeText(getBaseContext(),"error", Toast.LENGTH_SHORT).show();
}
But the bitmap is still null
Can Anyone tell me why ? or better... How to fix it ?
Ok, so If I'll do it like it's now in edited post, how can I "resize" the image to get rid of outOfMemory Exception ?
Aha! Now we are getting somewhere.
What you had, in a prior edit of your question, was:
read the entire bitmap into a byte array
write the entire bitmap into another byte array as a low-quality JPEG
read the entire bitmap into a Bitmap, backed by yet a third byte array
This will result in your consuming ~2.1x the heap space of your current implementation, which is already giving you OutOfMemoryError messages. The byte arrays from #1 and #3 above will be the same size, equal to:
width x height x 4
where the width and height are expressed in pixels.
To reduce your memory consumption, you need to do to things:
Read in the bitmap once, as your current code does.
Use BitmapFactory.Options to control the decoding of the bitmap. In particular, use inSampleSize to reduce the number of pixels in the resulting Bitmap. Quoting the JavaDocs for inSampleSize:
If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save memory. The sample size is the number of pixels in either dimension that correspond to a single pixel in the decoded bitmap. 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. Note: the decoder uses a final value based on powers of 2, any other value will be rounded down to the nearest power of 2.
This sample project demonstrates the use of inSampleSize for various hardcoded values. The actual Bitmap loading comes from:
private Bitmap load(String path, int inSampleSize) throws IOException {
BitmapFactory.Options opts=new BitmapFactory.Options();
opts.inSampleSize=inSampleSize;
return(BitmapFactory.decodeStream(assets().open(path), null, opts));
}
Your getPathFromUri method is failing. It should be returning something like /storage/emulated/0/DCIM/camera/bla bla.jpg. The file:// is the authority and isn't part of the path. BitmapFactory is looking for an actual file location path.
You can strip that manually or use Uri class with something like this:
Uri imgUri = Uri.parse(imgPath);
String filePath = imgUri.getPath();
In my android app I capture an image from the camera, compress it to jpeg, send it to the server and save it on hdd. There it takes 48,9kb (e.g.). I send it back in a Base64-String and decode it on the Android side like this:
byte[] img;
img = Base64.decode(base64, Base64.DEFAULT);
ByteArrayInputStream in = new ByteArrayInputStream(img);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 3;
Bitmap bmp = BitmapFactory.decodeStream(in, null, options);
return bmp;
Values bigger than 3 for
options.inSampleSize
will make the image look ugly. But if i now look at the size of
bmp
it is 156kb. Why does the size increase? How can I decode it, so that it keeps its original size and doesnt look ugly (too hard downsampling)?
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.