Why bitmap compress with 100 quality became smaller - android

I am using camera with ImageFormat NV21 to preview, when I get NV21 data, I try to use this method following to get bytes that can be displayed to ImageView.
FONT FACE:
public static byte[] n21ToBitmap(byte[] data, Camera camera) {
try {
Camera.Parameters parameters = camera.getParameters();
Camera.Size size = parameters.getPreviewSize();
YuvImage image =
new YuvImage(data, parameters.getPreviewFormat(), size.width, size.height, null);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compressToJpeg(new Rect(0, 0, size.width, size.height), 100, stream);
Bitmap originBitmap = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.size());
stream.close();
Matrix matrix = new Matrix();
matrix.postRotate(270);
Bitmap rotateBitmap =
Bitmap.createBitmap(originBitmap, 0, 0, originBitmap.getWidth(), originBitmap.getHeight(),
matrix, true);
Bitmap temp = rotateBitmap.copy(rotateBitmap.getConfig(), true);
Log.e("TAG", "n21ToBitmap(ImageUtils.java:"
+ Thread.currentThread().getStackTrace()[2].getLineNumber()
+ ")"
+ "temp:"
+ temp.getByteCount());
stream = new ByteArrayOutputStream();
temp.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byte[] bytes = stream.toByteArray();
Log.e("TAG", "n21ToBitmap(ImageUtils.java:"
+ Thread.currentThread().getStackTrace()[2].getLineNumber()
+ ")"
+ "bytes:"
+ bytes.length);
return bytes;
} catch (Exception ex) {
Log.e(TAG, "Error:" + ex.getMessage());
}
return null;
}
And the LOG:
n21ToBitmap(ImageUtils.java:103)temp: 2073600
n21ToBitmap(ImageUtils.java:112)bytes:311627
So, why the bytes length become smallar?

See bytes length is the size of array so each array indexes have some value again in bytes.
byte[] bytes;
bytest.length = array size;
Now your array size = 20 = bytest.length;
and each index have some bytes value.
Assume 1024 byets each index containing.
So total size = 20*1024 this is the actual size
in your case array length is 311627 and each index have some bytes of value
so total size = 311627* value at each index

Related

How to reduce image size from MB to KB?

I made a gallery application and stored more images in a SQL Server databse,
now I am getting images takes a lot of time.
So I want image uploading time MB to KB conversion (i.e.: 20KB, 30KB).
What shall I do? Help me, please.
My code is:
private void onSelectFromGalleryResult(Intent data) {
Bitmap bm = null;
if (data != null) {
try {
bm = MediaStore.Images.Media.getBitmap(Admin.this.getApplicationContext().getContentResolver(), data.getData());
imgadminview.setImageBitmap(bm);
int bitmapByteCount= BitmapCompat.getAllocationByteCount(bm);
System.out.print(bitmapByteCount);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
byteArray = bytes.toByteArray();
long lengthbmp = byteArray.length;
System.out.print(lengthbmp);
if(lengthbmp<=1048576){
//KB or more
rxKb = lengthbmp/1024;
System.out.print(rxKb + " KBs");}
else if(rxKb>=1024) {
//MB or more
rxMB = rxKb / 1024;
System.out.print(rxMB + " MBs");
}else if(rxMB>=1024) {
//GB or more
long rxGB = rxMB / 1024;
System.out.print(rxGB + Long.toString(rxGB));
}else {
//rxMB>1024
//rxKb > 1024
}//rxBytes>=1024
byte[] test=String.valueOf(rxKb).getBytes();
encodedImage = Base64.encodeToString(test, Base64.DEFAULT);
btarray = Base64.decode(encodedImage, Base64.DEFAULT);
bmimage = BitmapFactory.decodeByteArray(byteArray, 0, btarray.length);
} catch (IOException e) {
e.printStackTrace();
}
}
imgadminview.setImageBitmap(bm);
}

Low size image uploading

I try upload image to server. I get image by path and convert it to byte array:
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
Bitmap picture = BitmapFactory.decodeFile(imagePath, bmOptions);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
ByteArrayOutputStream bao = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bao);
byte[] bytes = bao.toByteArray();
builder.addPart("uploadedfile", new ByteArrayBody(bytes, "name" + ".jpg"));
For example image's size is 300kb but size of uploaded image is 800kb.
How can I send image (selected by path) without size increasing?
SOULUTION
#greenapps right. I converted image as file:
public static byte[] fullyReadFileToBytes(File f) throws IOException {
int size = (int) f.length();
byte bytes[] = new byte[size];
byte tmpBuff[] = new byte[size];
FileInputStream fis= new FileInputStream(f);;
try {
int read = fis.read(bytes, 0, size);
if (read < size) {
int remain = size - read;
while (remain > 0) {
read = fis.read(tmpBuff, 0, remain);
System.arraycopy(tmpBuff, 0, bytes, size - remain, read);
remain -= read;
}
}
} catch (IOException e){
throw e;
} finally {
fis.close();
}
return bytes;
}
Put the image file in a byte array without using an intermediate Bitmap.

Drawing bitmaps to an image view with 30 FPS

I am working on android app which takes frames from the camera and display on surface view, I am using camera callbacks to get raw images and then convert it to byte stream and passes to the server for processing and then server return same frame. But the problem is Image view is very slow in drawing images (bitmaps) 15-20 fps. Is there any other solution using I can draw bitmaps quickly. In current code I am processing the bitmaps on a different thread and using UI thread I am setting bitmaps to image view.
Code in Camera callback is
Camera.Size pSize = camera.getParameters().getPreviewSize();
YuvImage yuv = new YuvImage(data, ImageFormat.NV21,
pSize.width, pSize.height, null);
yuv.compressToJpeg(new Rect(0, 0, pSize.width,
pSize.height), 100, baos);
rawImage = baos.toByteArray();
Bitmap bitmap = BitmapFactory.decodeByteArray(rawImage,
0, rawImage.length);
bitmap = Util.getResizedBitmap(bitmap, frameResolution);
final ByteArrayOutputStream rotatedStream = new ByteArrayOutputStream();
bitmap = Util.RotateBitmap(bitmap, 90);
bitmap.compress(Bitmap.CompressFormat.WEBP, 100, rotatedStream);
baos.close();
rawImage = rotatedStream.toByteArray();
if(isStreamingStart== true) {
beforeTime=(new Date()).getTime();
if(client.isConnected()==false){
client.connect();
}
client.send(rawImage);
rotatedStream.flush();
}
and code which returns bitmap is
decodedString = Base64.decode((String) data, Base64.DEFAULT);
byte[] dataString = ((String)data).getBytes();
String stringDecompressed = compressor.decompressToString(dataString);
byte[] imageAsBytes = stringDecompressed.getBytes();
final Bitmap bitmap = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
final Bitmap mutableBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
final Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
HomeActivity.this.runOnUiThread(new Runnable() {
public void run() {
try {
remoteViewImageView.setImageBitmap(bitmap);
} catch (Exception e) {
e.printStackTrace();
}
}
});

Android: mPrevCallback to JPG, results in black pictures

I am trying to capture the preview of the camera on a surfaceview ,to save it as a JPEG in the internal memory. I found some code here on this site, that does mostly I want but saves the image to the SD Card. I changed that, and came up with the following code.
Camera.PreviewCallback mPrevCallback = new Camera.PreviewCallback()
{
#Override
public void onPreviewFrame( byte[] data, Camera Cam ) {
//Log.d(TAG, "FRAME");
Camera.Parameters parameters = Cam.getParameters();
int format = parameters.getPreviewFormat();
//Log.d(TAG, "FORMAT:" + format);
//YUV formats require more conversion
if (format == ImageFormat.NV21 || format == ImageFormat.YUY2 || format == ImageFormat.NV16) {
int w = parameters.getPreviewSize().width;
int h = parameters.getPreviewSize().height;
// Get the YuV image
YuvImage yuv_image = new YuvImage(data, format, w, h, null);
// Convert YuV to Jpeg
Rect rect = new Rect(0, 0, w, h);
ByteArrayOutputStream output_stream = new ByteArrayOutputStream();
yuv_image.compressToJpeg(rect, 100, output_stream);
byte[] byt = output_stream.toByteArray();
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream("/data/data/com.example.max.camtest/files/test"+System.currentTimeMillis()+".jpg");
outStream.write(byt);
outStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
};
The preview is shown on the surfaceview and the mPrevCallback is triggered.It successfully saves pictures that have diffrent sizes (250~500Kb) but they are all black. When I try to capture a picture with the camera.takePicture function is it also black.
What Am I doing wrong? How can I debug this?
Thanks!
Use this intent to take picture
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File f = new File(android.os.Environment.getExternalStorageDirectory(), AppInfo.getInstance().getCurrentLoginUserInfo().getId()+".jpg");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(f));
intent.putExtra("return-data", true);
startActivityForResult(intent, 1);
and on Your Activity Result.... Note Bitmap bitmap = getScaledBitmap(uri.getPath(), 200, true); 200 is your max image size.
if(requestCode == 1)
{
String base = Environment.getExternalStorageDirectory().getAbsolutePath().toString();
final String imgPath = base + "/" +AppInfo.getInstance().getCurrentLoginUserInfo().getId()+".jpg";
File file = new File(imgPath);
if (file.exists())
{
Uri uri = Uri.fromFile(file);
Log.d(TAG, "Image Uri path: " + uri.getPath());
Bitmap bitmap = getScaledBitmap(uri.getPath(), 200, true);
}}
This method ll return image bitmap after resizing it-
private Bitmap getScaledBitmap(String imagePath, float maxImageSize, boolean filter) {
FileInputStream in;
BufferedInputStream buf;
try {
in = new FileInputStream(imagePath);
buf = new BufferedInputStream(in);
Bitmap realImage = BitmapFactory.decodeStream(buf);
float ratio = Math.min(
(float) maxImageSize / realImage.getWidth(),
(float) maxImageSize / realImage.getHeight());
int width = Math.round((float) ratio * realImage.getWidth());
int height = Math.round((float) ratio * realImage.getHeight());
Bitmap newBitmap = Bitmap.createScaledBitmap(realImage, width, height, filter);
return newBitmap;
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
Now you have scaled bitmap image.
Hope this ll help you.

How to save image bitmap after rotation? [duplicate]

This question already has answers here:
Android saving file to external storage
(13 answers)
Closed 2 years ago.
I develop app that save images to sd Card and all the pictures are upside i want to rotate them and save them in the rotate position i choose .
i know how to rotate on my code but the image is not saved permanently.
here is my code :
//Rotate the picture
public static Bitmap rotate(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(),source.getHeight(), matrix, false);
}
//Resize image
public void resizeImage(String path , int Wdist,int Hdist){
try
{
int inWidth = 0;
int inHeight = 0;
InputStream in = new FileInputStream(path);
// decode image size (decode metadata only, not the whole image)
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, options);
in.close();
in = null;
// save width and height
inWidth = options.outWidth;
inHeight = options.outHeight;
// decode full image pre-resized
in = new FileInputStream(path);
options = new BitmapFactory.Options();
// calc rought re-size (this is no exact resize)
options.inSampleSize = Math.max(inWidth/Wdist, inHeight/Hdist);
// decode full image
Bitmap roughBitmap = BitmapFactory.decodeStream(in, null, options);
// calc exact destination size
Matrix m = new Matrix();
RectF inRect = new RectF(0, 0, roughBitmap.getWidth(), roughBitmap.getHeight());
RectF outRect = new RectF(0, 0, Wdist, Hdist);
m.setRectToRect(inRect, outRect, Matrix.ScaleToFit.CENTER);
float[] values = new float[9];
m.getValues(values);
// resize bitmap
Bitmap resizedBitmap = Bitmap.createScaledBitmap(roughBitmap, (int) (roughBitmap.getWidth() * values[0]), (int) (roughBitmap.getHeight() * values[4]), true);
// save image
try
{
FileOutputStream out = new FileOutputStream(path);
resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
}
catch (Exception e)
{
Log.e("Image", e.getMessage(), e);
}
}
catch (IOException e)
{
Log.e("Image", e.getMessage(), e);
}
}
thanks for the helpers :)
You'll need to save the Bitmap back.
try {
File dir = new File("path/to/directory");
if(!dir.exists())
dir.mkdirs();
File file = new File(dir, "original_img_name.png");
FileOutputStream out;
out = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
} catch (Exception e) {
e.printStackTrace();
} finally {
try{
out.close();
} catch(Throwable ignore) {}
}
Edit 1 :
Replace
bmp.compress(Bitmap.CompressFormat.PNG, 90, out); with
resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out); and set correct values for the directory path and the image name. If you want to replace the previous images, use the original path and image name.
Also, make sure you include the following permission.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
You can also try this one
return Bitmap.createBitmap(source, 0, 0, source.getWidth(),source.getHeight(), matrix, true);
Go through this link
how to rotate a bitmap 90 degrees
The following code can help you compress and resize the bitmap.
Note:
Create a String type variable with name of photoPath and store the photo url in it.
public void compressImage(){
Log.i("compressPhoto", "Compress and resize photo started.");
// Getting Image
InputStream in = null;
try {
in = new FileInputStream(photoPath);
} catch (FileNotFoundException e) {
Log.e("TAG","originalFilePath is not valid", e);
}
BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap bitmap = BitmapFactory.decodeStream(in, null, options);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap = bitmap.createScaledBitmap(bitmap,(int)(bitmap.getWidth()*0.2), (int)(bitmap.getHeight()*0.2), true);
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, stream);
byte[] byteArray = stream.toByteArray();
// Storing Back
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(photoPath);
outStream.write(byteArray);
outStream.close();
} catch (Exception e) {
Log.e("TAG","could not save", e);
}
}

Categories

Resources