I am capturing the image from camera. The captured image's size shows too small when captured. But later if I check in gallery the captured image size shows in MB.
I tried debugging the code, so while debugging I checked length of the file after image is captured the length shows 26956 bytes, and when I checked same image in gallery the size of the image is 1.3 MB.
Why the image size shows reduced when captured?
private void cameraIntent() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, REQUEST_CAMERA);
}
private void onCaptureImageResult(Intent data) {
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
(thumbnail.getWidth()/2),(int)(thumbnail.getHeight()/2),true);
thumbnail.compress(Bitmap.CompressFormat.PNG, 100, bytes);
File destination = new File(Environment.getExternalStorageDirectory(),
System.currentTimeMillis() + ".png");
FileOutputStream fo;
try {
destination.createNewFile();
fo = new FileOutputStream(destination);
fo.write(bytes.toByteArray());
fo.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
long size = destination.length();// here size of the image is too small
selectFile = false;
loadImageFromFile(destination.getAbsolutePath());
}
public void loadImageFromFile(String imageFile) {
try {
ExifInterface ei = new ExifInterface(imageFile);
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
Bitmap bitmap = BitmapFactory.decodeFile(imageFile);
Bitmap rotatedBitmap = null;
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
rotatedBitmap = rotateImage(bitmap, 90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotatedBitmap = rotateImage(bitmap, 180);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotatedBitmap = rotateImage(bitmap, 270);
break;
case ExifInterface.ORIENTATION_NORMAL:
rotatedBitmap = bitmap;
break;
default:
rotatedBitmap = bitmap;
break;
}
if (rotatedBitmap != null) {
if (selectFile && fileSizeInKB > 500) {
rotatedBitmap = Bitmap.createScaledBitmap(rotatedBitmap, (int) (rotatedBitmap.getWidth() * 0.3), (int) (rotatedBitmap.getHeight() * 0.3), true);
}
else if(selectFile && fileSizeInKB > 1024){
rotatedBitmap = Bitmap.createScaledBitmap(rotatedBitmap, (int) (rotatedBitmap.getWidth() * 0.2), (int) (rotatedBitmap.getHeight() * 0.2), true);
}
else if(selectFile && fileSizeInMB > 2){
rotatedBitmap = Bitmap.createScaledBitmap(rotatedBitmap, (int) (rotatedBitmap.getWidth() * 0.1), (int) (rotatedBitmap.getHeight() * 0.1), true);
}
profileImageView.setImageBitmap(rotatedBitmap);
selectedBitmap = rotatedBitmap;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
selectedBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); //replace 100 with desired quality percentage.
byte[] byteArray = stream.toByteArray();
File tempFile = File.createTempFile("temp", null, getCacheDir());
FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(byteArray);
Long size = tempFile.length();
profileImage = tempFile;
}
} catch (IOException ex) {
}
}
I am scaling the images selected from gallery, I too want to scale the images captured from camera, but the size of the image I am not getting appropriate.
Can anyone help for this please? Thank you...
Edit :
private void cameraIntent() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
try {
photoFile = createImageFile();
} catch (IOException ex) {
}
// Continue only if the File was successfully created
if (photoFile != null) {
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
startActivityForResult(intent, REQUEST_CAMERA);
}
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "image";
File storageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
fileName = image.getAbsolutePath();
return image;
}
private void onCaptureImageResult(Uri data) {
try {
Bitmap thumbnail = MediaStore.Images.Media.getBitmap(this.getContentResolver(), data);
selectFile = false;
long fileSizeInBytes = photoFile.length();
// Convert the bytes to Kilobytes (1 KB = 1024 Bytes)
fileSizeInKB = fileSizeInBytes / 1024;
// Convert the KB to MegaBytes (1 MB = 1024 KBytes)
fileSizeInMB = fileSizeInKB / 1024;
loadImageFromFile(photoFile.getAbsolutePath());
}catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void loadImageFromFile(String imageFile) {
try {
ExifInterface ei = new ExifInterface(imageFile);
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
Bitmap bitmap = BitmapFactory.decodeFile(imageFile);
Bitmap rotatedBitmap = null;
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
rotatedBitmap = rotateImage(bitmap, 90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotatedBitmap = rotateImage(bitmap, 180);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotatedBitmap = rotateImage(bitmap, 270);
break;
case ExifInterface.ORIENTATION_NORMAL:
rotatedBitmap = bitmap;
break;
default:
rotatedBitmap = bitmap;
break;
}
if (rotatedBitmap != null) {
//
if (selectFile && fileSizeInMB < 1 && fileSizeInKB > 500) {
rotatedBitmap = Bitmap.createScaledBitmap(rotatedBitmap, (int) (rotatedBitmap.getWidth() * 0.9), (int) (rotatedBitmap.getHeight() * 0.9), true);
}
else if(selectFile && fileSizeInMB < 2){
rotatedBitmap = Bitmap.createScaledBitmap(rotatedBitmap, (int) (rotatedBitmap.getWidth() * 0.3), (int) (rotatedBitmap.getHeight() * 0.3), true);
}
else if(selectFile && fileSizeInMB > 2){
rotatedBitmap = Bitmap.createScaledBitmap(rotatedBitmap, (int) (rotatedBitmap.getWidth() * 0.2), (int) (rotatedBitmap.getHeight() * 0.2), true);
}
else if(selectFile && fileSizeInMB > 3){
rotatedBitmap = Bitmap.createScaledBitmap(rotatedBitmap, (int) (rotatedBitmap.getWidth() * 0.1), (int) (rotatedBitmap.getHeight() * 0.1), true);
}
// resize(rotatedBitmap,bitmap.getWidth()/2,bitmap.getHeight()/2);
profileImageView.setImageBitmap(rotatedBitmap);
selectedBitmap = rotatedBitmap;
ByteArrayOutputStream stream = new ByteArrayOutputStream();
selectedBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); //replace 100 with desired quality percentage.
byte[] byteArray = stream.toByteArray();
File tempFile = File.createTempFile("temp", null, getCacheDir());
FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(byteArray);
Long size = tempFile.length();
profileImage = tempFile;
}
} catch (IOException ex) {
// UiUtils.showAlert(getString(R.string.error),NewGroupAcvitity.this);
}
}
Now with this code, when I capture the image after capturing it takes time to load on image view and show blank screen till the image is set to the image view.
You are using the Thumbnail instead of the actual image.
To get the actual image you have to pass Image file uri to the Camera intent as MediaStore.EXTRA_OUTPUT
Sample :
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);//photoURI - file uri where you want the image to be saved
startActivityForResult(intent, REQUEST_CAMERA);
Refer https://developer.android.com/training/camera/photobasics.html#TaskPath for the required steps and complete code.
To get a scaled Bitmap from file path
int targetW = 800;
int targetH = 1000;
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imagePath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
int scaleFactor = Math.min(photoW / targetW, photoH / targetH);
// Decode the image file into a Bitmap
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(imagePath, bmOptions);
Related
I'm getting an image from gallery into a layout , then I'm getting the bitmap of that layout by using getBitmap(), after getting bitmap I'm saving the image into device storage by using saveImage().
After getting bitmap and saving the bitmap, the quality and pixel of that bitmap reduces too much as shown in the pictureSaved image AND Orignal image
Here is the code for getting and saving bitmap
private Bitmap getBitmap(View v) {
v.clearFocus();
v.setPressed(false);
boolean willNotCache = v.willNotCacheDrawing();
v.setWillNotCacheDrawing(false);
int color = v.getDrawingCacheBackgroundColor();
v.setDrawingCacheBackgroundColor(0);
if (color != 0) {
v.destroyDrawingCache();
}
v.buildDrawingCache();
Bitmap cacheBitmap = v.getDrawingCache();
if (cacheBitmap == null) {
Toast.makeText(this, "Something Wrong", Toast.LENGTH_SHORT).show();
return null;
}
Bitmap lastimage = Bitmap.createBitmap(cacheBitmap);
v.destroyDrawingCache();
v.setWillNotCacheDrawing(willNotCache);
v.setDrawingCacheBackgroundColor(color);
//2048x2048 resolution
int newWidth = 2048;
int newHeight = 2048;
int width = lastimage.getWidth();
int height = lastimage.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(lastimage, 0, 0, width, height, matrix, true);
lastimage.recycle();
saveImage(resizedBitmap);
return resizedBitmap;
}
For Saving:
private void saveImage (Bitmap finalBitmap) {
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/NewFolder");
myDir.mkdirs();
String fname = "Image-.png";
File file = new File(myDir, fname);
try {
FileOutputStream out = new FileOutputStream(file);
finalBitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Thanks for anyone's help.
I am getting an image from image view and convert it into bitmap and after that i have save it in a directory. Image is saved successfully in my directory but is is not showing in galley.
I have some other images in same directory that is saved after taking picture from camera are visible. I just save image from an ImageView and store it into a directory and in next screen i just want to use the saved image to fetch the information.
textToImage() method is used to create an encoded image.
Bitmap TextToImageEncode(String Value) throws WriterException {
BitMatrix bitMatrix;
try {
bitMatrix = new MultiFormatWriter().encode(
Value,
BarcodeFormat.DATA_MATRIX.QR_CODE,
QRcodeWidth, QRcodeWidth, null
);
} catch (IllegalArgumentException Illegalargumentexception) {
return null;
}
int bitMatrixWidth = bitMatrix.getWidth();
int bitMatrixHeight = bitMatrix.getHeight();
int[] pixels = new int[bitMatrixWidth * bitMatrixHeight];
for (int y = 0; y < bitMatrixHeight; y++) {
int offset = y * bitMatrixWidth;
for (int x = 0; x < bitMatrixWidth; x++) {
pixels[offset + x] = bitMatrix.get(x, y) ?
getResources().getColor(R.color.QRCodeBlackColor) : getResources().getColor(R.color.QRCodeWhiteColor);
}
}
Bitmap bitmap = Bitmap.createBitmap(bitMatrixWidth, bitMatrixHeight, Bitmap.Config.ARGB_4444);
bitmap.setPixels(pixels, 0, 500, 0, 0, bitMatrixWidth, bitMatrixHeight);
if (bitmap != null)
saveImageToSdCard(bitmap);
} else {
Log.e("Test data image or not", "No bitmap given");
}
return bitmap;
}
"I have use this method to save the image in my directory"
public void saveImageToSdCard(Bitmap bitmap1) {
File sdCard = Environment.getExternalStorageDirectory();
String ExternalStorageDirectoryPath = Environment
.getExternalStorageDirectory()
.getAbsolutePath();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
Locale.getDefault()).format(new Date());
if (sdCard != null) {
> Create the directory here with path
File directory = new File(ExternalStorageDirectoryPath+"/My App");
if (directory.exists()) {
directory.delete();
Log.e("it run", "directory is exists");
}
directory.mkdirs();
String strImageName = File.separator + "IMG_" + timeStamp + ".jpg";
File file = new File(directory, strImageName);
// strFinalImage = file.getAbsolutePath();
// Log.e(TAG + "strFinalImage22", strFinalImage + "");
> here we just scan the media
MediaScannerConnection.scanFile(getActivity(),
new String[] { file.toString() }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.e("ExternalStorage", "Scanned " + path + ":");
Log.e("ExternalStorage", "-> uri=" + uri);
}
});
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(file);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bitmap1.compress(Bitmap.CompressFormat.JPEG, 60, bytes);
fileOutputStream.write(bytes.toByteArray());
fileOutputStream.flush();
fileOutputStream.close();
// Toast.makeText(MainActivity.this, "Saved", Toast.LENGTH_SHORT).show();
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
} else {
Toast.makeText(getActivity(), "Sd card mount", Toast.LENGTH_SHORT).show();
}
}
I was trying to copy a picture from URI to a file path. Then I read the picture from the path, but the picture I got was rotated 90 degrees down. Below is my function. Anybody can help on this?
public boolean copyPicture(Context context, Uri source, String dest) {
boolean result = false;
int bytesum = 0;
int byteread = 0;
File destFile = new File(dest);
String scheme = source.getScheme();
if (ContentResolver.SCHEME_CONTENT.equals(scheme)
|| ContentResolver.SCHEME_FILE.equals(scheme)) {
InputStream inStream = null;
try {
inStream = context.getContentResolver().openInputStream(source);
if (!destFile.exists()) {
result = destFile.createNewFile();
}
if (result) {
FileOutputStream fs = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
while ((byteread = inStream.read(buffer)) != -1) {
bytesum += byteread; //字节数 文件大小
System.out.println(bytesum);
fs.write(buffer, 0, byteread);
}
inStream.close();
fs.flush();
fs.close();
}
} catch (Exception e) {
e.printStackTrace();
result = false;
}
}
return result;
}
EXIF INTERFACE is the answer. It allows you to read specified attributes from a image file.
Bitmap bitmap = BitmapFactory.decodeFile(path, options);
try {
ExifInterface exif = new ExifInterface(path);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
int angle = 0;
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
angle = 90;
}
else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
angle = 180;
}
else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
angle = 270;
}
Matrix mat = new Matrix();
mat.postRotate(angle);
Bitmap correctBmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), mat, true);
bitmap=correctBmp;
}
catch(Exception e){
}
I'm trying to write a method that accepts an image(Bitmap) and returns a byte[] array. finally, I try to write this byte[] array to a folder so I can see the difference, but my byte[] arraycan not displayed, and in addition, it is not scaled down! This is my method:
private byte[] changeSize(Bitmap image) {
byte[] picture;
int width = image.getWidth();
int height = image.getHeight();
int newHeight = 0, newWidth = 0;
if (width > 250 || height > 250) {
if (width > height) { //landscape-mode
newHeight = 200;
newWidth = (newHeight * width) / height;
} else { //portrait-mode
newWidth = 200;
newHeight = (newWidth * height) / width;
}
} else {
Toast.makeText(this, "Something wrong!", Toast.LENGTH_LONG).show();
}
Bitmap sizeChanged = Bitmap.createScaledBitmap(image, newWidth, newHeight, true);
//Convert bitmap to a byte array
int bytes = sizeChanged.getByteCount();
ByteBuffer bb = ByteBuffer.allocate(bytes);
sizeChanged.copyPixelsFromBuffer(bb);
picture = bb.array();
//Write to a hd
picturePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
String fileName = edFile.getText().toString() + "_downscaled" + ".jpg";
File file = new File(picturePath, fileName);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
fos.write(picture);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
return image;
}
I tried several hours to get my byte[] array visible, but I could simply not do this. Any help or hints to show me where I derail is/are very appreciated.
This was working for me
public static Bitmap byteArraytoBitmap(byte[] bytes) {
return (BitmapFactory.decodeByteArray(bytes, 0, bytes.length));
}
public static byte[] bitmaptoByteArray(Bitmap bmp) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream); //PNG format is lossless and will ignore the quality setting!
byte[] byteArray = stream.toByteArray();
return byteArray;
}
public static Bitmap bitmapFromFile(File file) {
//returns null if could not decode
return BitmapFactory.decodeFile(file.getPath());
}
public static boolean saveImage(Bitmap image, String filePath) {
LogInfo(TAG, "Saving image to: " + filePath);
File file = new File(filePath);
File fileDirectory = new File(file.getParent());
LogInfo(TAG, fileDirectory.getPath());
if (!fileDirectory.exists()) {
if (!fileDirectory.mkdirs()) {
Log.e(TAG, "ERROR CREATING DIRECTORIES");
return false;
}
}
try {
file.createNewFile();
FileOutputStream fo = new FileOutputStream(file);
fo.write(bitmaptoByteArray(image));
fo.flush();
fo.close();
return true;
}
catch (Exception e) {
e.printStackTrace();
return false;
}
}
For my application, I need to save a photo, taken from camera of a device, on an 7.7k nfc chip.
In the onActivityResult, I resize the bitmap as here :
String fileName = "original";
String path = Environment.getExternalStorageDirectory() + "/" + fileName + ".jpg";
//Resizing
BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap current = BitmapFactory.decodeFile(path);
Bitmap resized = resizeBitMapImage(path,largeur,(int)(largeur*1.8));
with
public static Bitmap resizeBitMapImage(String filePath, int targetWidth, int targetHeight) {
Bitmap bitMapImage = null;
try {
Options options = new Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
double sampleSize = 0;
Boolean scaleByHeight = Math.abs(options.outHeight - targetHeight) >= Math.abs(options.outWidth
- targetWidth);
if (options.outHeight * options.outWidth * 2 >= 1638) {
sampleSize = scaleByHeight ? options.outHeight / targetHeight : options.outWidth / targetWidth;
sampleSize = (int) Math.pow(2d, Math.floor(Math.log(sampleSize) / Math.log(2d)));
}
options.inJustDecodeBounds = false;
options.inTempStorage = new byte[128];
while (true) {
try {
options.inSampleSize = (int) sampleSize;
Log.v(LOG_TAG,"inSampleSize" + options.inSampleSize);
bitMapImage = BitmapFactory.decodeFile(filePath, options);
break;
} catch (Exception ex) {
try {
sampleSize = sampleSize + 1 ;
} catch (Exception ex1) {
}
}
}
} catch (Exception ex) {
}
return bitMapImage;
}
(Found on SO)
And then, I save it on the chip with :
NdefRecord picRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, "image/jpeg".getBytes(), null, byteArray);
When I choose a width of 200, and a compression of 50, the picture takes about 7k, but the quality is quite low. The bitmap is a contact photo.
So my questions :
What should I use as width, height, compression, in order to get the best photo quality (less than 7k?
Should the camera be set on high or low resolution ?
PNG or JPEG compression ?