Take a picture with the normal smartphone camera.
Ok I've been Googling this for a while now, and everyone seems to use something like the following:
Bitmap bm = BitmapFactory.decodeStream(getContentResolver().openInputStream(fileUri));
ByteArrayOutputStream out = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 25, out);
Bitmap decoded = BitmapFactory.decodeStream(new ByteArrayInputStream(out.toByteArray()));
I use this to check the file size:
#TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
protected int sizeOf(Bitmap data) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1) {
return data.getRowBytes() * data.getHeight();
} else {
return data.getByteCount();
}
}
The Bitmap is not getting any smaller, before and after:
Log.d("image", sizeOf(bm)+"");
Log.d("image", sizeOf(decoded)+"");
Results:
11-05 02:51:52.739: D/image(2558): 20155392
11-05 02:51:52.739: D/image(2558): 20155392
Pointers?
Answer:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 50;
Bitmap bmpSample = BitmapFactory.decodeFile(fileUri.getPath(), options);
Log.d("image", sizeOf(bmpPic)+"");
ByteArrayOutputStream out = new ByteArrayOutputStream();
bmSample.compress(Bitmap.CompressFormat.JPEG, 1, out);
byte[] byteArray = out.toByteArray();
Log.d("image", byteArray.length/1024+"");
The compress method, as mentioned in the documentation:
Write a compressed version of the bitmap to the specified outputstream. The bitmap can be reconstructed by passing a corresponding inputstream to BitmapFactory.decodeStream()
Thus the variable out now contains the compressed bitmap. Since you check the size after calling decodeStream the bitmap is decompressed and returned to you. Therefore the size is same.
Related
I am trying to implement Converting bitmap to byteArray android. I need to convert my byte[] to bitmap without compression. But everytime im getting whole black image. How to do it?
What I am doing:
int bytes = bmp.getByteCount();
ByteBuffer buffer = ByteBuffer.allocate(bytes);
bmp.copyPixelsToBuffer(buffer);
byte[] resarray = buffer.array();
And here how I get it to bitmap:
BitmapFactory.Options options = new
BitmapFactory.Options();
options.inScaled = false;
Bitmap bmp = BitmapFactory.decodeByteArray(barray,0, barray.length,options);
ImageView imageView = (ImageView) findViewById(R.id.resdetayimage);
imageView.setImageBitmap(bmp);`
EDIT
Bitmap factory decode only compressed things. Thats why my code not work. So I need something like:
Bitmap.Config configBmp = Bitmap.Config.valueOf(bitmap.getConfig().name());
Bitmap bitmap_tmp = Bitmap.createBitmap(width, height, configBmp);
ByteBuffer buffer = ByteBuffer.wrap(byteArray);
bitmap_tmp.copyPixelsFromBuffer(buffer);
But the code still not working. How can I implement this ? I got byte[] from intent.
Convert bitmap to byteArray
ByteArrayOutputStream bStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 90, bStream);
byte[] mByteArray = bStream.toByteArray();
Convert byteArray to Bitmap
Bitmap bitmap = BitmapFactory.decodeByteArray(mByteArray , 0, mByteArray.length);
Use copyPixelsFromBuffer() as it is the reverse of copyPixelsToBuffer().
public void onPictureTaken(byte[] data, Camera camera) {
Uri imageFileUri = null;
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = true;
Bitmap mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, bmpFactoryOptions);
Log.d("SIZE", "mBitmap size :" + data.length);
bmpFactoryOptions.inJustDecodeBounds = false;
mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, bmpFactoryOptions);
imageFileUri = getApplicationContext().getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new ContentValues());
OutputStream imageFileOS = getContentResolver().openOutputStream(imageFileUri);
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, imageFileOS);
imageFileOS.flush();
imageFileOS.close();
ByteArrayOutputStream stream1 = new ByteArrayOutputStream();
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream1);
byte[] imageInByte1 = stream1.toByteArray();
long lengthbmp1 = imageInByte1.length;
Log.d("SIZE", "ByteArrayOutputStream1 size :" + lengthbmp1);
output of the Log is like below :
D/SIZE (23100): mBitmap size :4858755
D/SIZE (23100): ByteArrayOutputStream1 size :8931843
Can anybody help me why this difference.
I need to compress the image based on the size, but without compressing the size getting different..
You appear to be loading the image and then recompressing to bitmap
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream1);
Then you're wondering why the image size isn't the same? The answer is you've re-encoded it. Is 100 the compression ratio? If you load a bitmap compressed at 80% and then resave it to 100% in any image editor the size will grow.
The first question is why you reencode the bitmap when you already have the bytes. The size difference you observe comes from the different compression. The camera app will typically compress the image with a quality lower than 100 but you recompress it with 100. It is clear that your image representation will need more space.
If recompression is really necessary (for example if you altered the image in some way), try lower quality factors for better compression. Depending on your image something between 90 and 100 may work well.
I am using Base64 Encoded String to convert image and then create it at Windows Server.
It is working fine in most of devices but It is giving error java.lang.OutOfMemoryError in android Version 2.3.5. I tried android:largeHeap="true" but it din't work.
Android Code:
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
Bitmap bitmap = drawable.getBitmap();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] data = baos.toByteArray();
strBase64 = Base64.encodeToString(data, Base64.DEFAULT);
I want to give crop image option to user and then store it at windows server. Is there any easy and better way for this ?
My code at asp.net:
public System.Drawing.Image Base64ToImage(string base64String)
{
byte[] imageBytes = Convert.FromBase64String(base64String);
using (var ms = new MemoryStream(imageBytes, 0, imageBytes.Length))
{
ms.Write(imageBytes, 0, imageBytes.Length);
System.Drawing.Image image = System.Drawing.Image.FromStream(ms, true);
return image;
}
}
System.Drawing.Image convertedImage = Base64ToImage(Photo);
convertedImage.Save(Server.MapPath("~\\images\\profileImg\\jeeten.jpg"), System.Drawing.Imaging.ImageFormat.Jpeg);
I tried some cropping image codes but It gave error : A generic error occurred in GDI+.
I would make these changes:
Instead of getting the image from the ImageView, consider using it's original source (file system? asset?). Then you dont have to re-compress the image.
Do not compress JPGs at 100% quality. There is large cost for un-noticeable image quality gains. If you need 100%, use PNG, otherwise use an 85% quality JPG.
You have several copies of the image in memory - in the drawable, in your byte array, in your base 64 string, etc. You can eliminate some of these.
Why convert to base 64? Just send the bytes to the server - Here's an example using PHP, but in .NET use HttpPostedFile to receive it.
Before Compressing the bitmap you can follow this:
//Put your image in file.
File file = new File("/mnt/sdcard/image.jpg");
//Pass your file in decodeImage method (your file, with its width and height as you want to display)
Bitmap bitmapImg=decodeImage(file,100,100);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmapImg.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] byteArray = stream.toByteArray();
String encodedString = Base64.encodeToString(byteArray, Base64.DEFAULT);
//Body of decodeFile(File f,int WIDTH,int HIGHT)
public Bitmap decodeFile(File f,int WIDTH,int HIGHT)
{
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//The new size we want to scale to
final int REQUIRED_WIDTH=WIDTH;
final int REQUIRED_HIGHT=HIGHT;
//Find the correct scale value. It should be the power of 2.
int scale=1;
while(o.outWidth/scale/2>=REQUIRED_WIDTH && o.outHeight/scale/2>=REQUIRED_HIGHT)
scale*=2;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
b1= BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (Exception e) {}
return b1;
}
I've converted an bitmap image into string to save it:
............
Bitmap photo = extras.getParcelable("data");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] b = baos.toByteArray();
String encodedImage = Base64.encodeToString(b, Base64.DEFAULT);
Then I retrieve the bitmap from string to set an activity's background just like that:
byte[] temp = Base64.decode(encodedImage, Base64.DEFAULT);
Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap bitmap = BitmapFactory.decodeByteArray(temp, 0,
temp.length, options);
Drawable d = new BitmapDrawable(getResources(), bitmap);
getWindow().setBackgroundDrawable(d);
Everything works fine but the image quality reduces tremendously. I know it is because photo.compress(Bitmap.CompressFormat.JPEG, 100, baos); as I am compressing this image(though in best compressing resolution). So how can I do this without compressing the image? I have also tried the following code but it returns nothing
.......
Bitmap photo = extras.getParcelable("data");
int bytes = photo.getWidth() * photo.getHeight() * 4;
ByteBuffer buffer = ByteBuffer.allocate(bytes);
photo.copyPixelsToBuffer(buffer);
byte[] b = buffer.array();
String encodedImage = Base64.encodeToString(b, Base64.DEFAULT);
Also I am using sharedPreference to save the image. I thought of sqlite or internal storage also, but in both case compressing is needed as I found in internet
I use the following code to get a Blob back from my SQLite database and get back a bitmap. My problem is that the reconstructed bitmap is larger than the original picture (input). It seems that my BitmapFactory.Options isn't working, but I have no idea what is wrong, nor am I getting an error. What is wrong with this code?
byte[] blob = contact.getMP();
ByteArrayInputStream inputStream = new ByteArrayInputStream(blob);
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
bmpFactoryOptions.inScaled = false;
bmpFactoryOptions.outHeight = 240;
bmpFactoryOptions.outWidth = 320;
Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, bmpFactoryOptions);
try {
FileOutputStream out = new FileOutputStream("mnt/sdcard/test5.png"); bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
} catch (Exception e) {
e.printStackTrace();
}
When I check the output my 320 x 240 picture is 427 x 320. I don't want to use Bitmap.createScaledBitmap because it messes up the quality.
you have to pass to decodeStream in order to work
Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, bmpFactoryOptions);