I'm try to get a byte array from a picture stored on an android device, but the byte array size is width * heigth * 2, and I need a byte array of the size width * heigth * 3.
My problem is that I need to send a picture byte array to a matlab server that need the array in this RGB format.
Here is the code that creates a byte array of "width * height" size:
Bitmap photo = BitmapHelper.readBitmap(CameraIntentActivity.this, photoUri);
if (photo != null) {
photo = BitmapHelper.shrinkBitmap(photo, 300, rotateXDegrees);
Bitmap bm = Bitmap.createScaledBitmap(photo, 640, 480, true);
final int lnth= bm.getByteCount();
ByteBuffer dst= ByteBuffer.allocate(lnth);
bm.copyPixelsToBuffer( dst);
byte[] byteArray = dst.array();
The readBitmap method:
public static Bitmap readBitmap(Context context, Uri selectedImage) {
Bitmap bm = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.RGB_565;
options.inScaled = false;
AssetFileDescriptor fileDescriptor = null;
try {
fileDescriptor = context.getContentResolver().openAssetFileDescriptor(selectedImage, "r");
} catch (FileNotFoundException e) {
return null;
} finally {
try {
bm = BitmapFactory.decodeFileDescriptor(
fileDescriptor.getFileDescriptor(), null, options);
fileDescriptor.close();
} catch (IOException e) {
return null;
}
}
return bm;
}
Related
I'm working on an application to capture images but I'd like to rotate a JPEG image before saving it, I already saw this link :
Android Rotate Picture before saving
This is what I'm doing right now.
ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(mImageFileName);
fileOutputStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
I tried this to rotate the image like this :
// Bytes array to bitmap and matrix rotation
Bitmap sourceBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Matrix m = new Matrix();
m.setRotate((float)90, sourceBitmap.getWidth(), sourceBitmap.getHeight());
Bitmap targetBitmap = Bitmap.createBitmap(sourceBitmap, 0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight(), m, true);
// Bitmap to bytes array
int size = targetBitmap.getRowBytes() * targetBitmap.getHeight();
ByteBuffer targetByteBuffer = ByteBuffer.allocate(size);
targetBitmap.copyPixelsToBuffer(targetByteBuffer);
bytes = targetByteBuffer.array();
But when I look into the file into my gallery, I cannot read it, the image seems broken.
EDIT: Doesn't work on Android 7.1.1 :/ Any idea ? Can I do something similar for a video record?
You are Coverting Your Bitmap to bytes array,
Now You stop That way save Bitmap directly to File
Bitmap sourceBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Matrix m = new Matrix();
m.setRotate((float)90, sourceBitmap.getWidth(), sourceBitmap.getHeight());
Bitmap rotatedBitmap= Bitmap.createBitmap(sourceBitmap, 0, 0, sourceBitmap.getWidth(), sourceBitmap.getHeight(), m, true);
// Save Bitmap directly to the file
String filename = "hello.jpg";
File sd = Environment.getExternalStorageDirectory();
File dest = new File(sd, filename);
try {
FileOutputStream out = new FileOutputStream(dest);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
This little change apparently did the trick ! Thanks Nikunj !
ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer();
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Matrix matrix = new Matrix();
matrix.setRotate((float)90, bitmap.getWidth(), bitmap.getHeight());
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(mImageFileName);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
I am uploading an image to the amazon server. Everything works well but only on few devices the orientation changes to landscape. At the time of uploading the orientation changes on a few Samsung devices and tablets. I have tried to fix it but nothing seems to be working. Below mentioned is my code.
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
value = true;
viewPager.setVisibility(View.VISIBLE);
Uri takenPhotoUri = getPhotoFileUri(photoFileName); //get the uri of the photo in order to get the path.
System.out.println("URI==" + takenPhotoUri);
al.add(takenPhotoUri);
Bitmap takenImage = BitmapFactory.decodeFile(takenPhotoUri.getPath());
final int maxSize = 1560;
int outWidth, outHeight;
int inWidth = takenImage.getWidth();
int inHeight = takenImage.getHeight();
if (inWidth > inHeight) {
outHeight = maxSize;
outWidth = (inHeight * maxSize) / inWidth;
} else {
outHeight = maxSize;
outWidth = (inWidth * maxSize) / inHeight;
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
takenImage = Bitmap.createScaledBitmap(takenImage, outWidth, outHeight, false);
String newDate = sdf.format(new Date());
Canvas canvas = new Canvas(takenImage); //bmp is the bitmap to dwaw into
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setTextSize(30);
paint.setTextAlign(Paint.Align.RIGHT);
canvas.drawText(newDate, 200, 100, paint);
//Creating a byte array output stream which is used to store the image once it has been compressed.
ByteArrayOutputStream bos = new ByteArrayOutputStream();
//Compress the image and store it in our ByteArrayOutPutStream
takenImage.compress(Bitmap.CompressFormat.JPEG, 90, bos);
int rotate = 0;
try {
getContentResolver().notifyChange(takenPhotoUri, null);
File imageFile = new File(String.valueOf(al.get(0)));
ExifInterface exif = new ExifInterface(
imageFile.getAbsolutePath());
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_270:
rotate = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotate = 90;
break;
}
Matrix matrix = new Matrix();
matrix.postRotate(rotate);
} catch (Exception e) {
e.printStackTrace();
}
try {
s3Client = new AmazonS3Client(
new BasicAWSCredentials(MY_ACCESS_KEY_ID, MY_SECRET_KEY));
byte[] contentBytes = bos.toByteArray(); //Create a byte array to store the size of the stream.
is = new ByteArrayInputStream(contentBytes);
Long contentLength = Long.valueOf(contentBytes.length);
objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(contentLength);
myAsyncTask = new MyAsyncTask();
myAsyncTask.execute();
responseUrl += s3Client.getResourceUrl(BUCKET_NAME, photoFileName) + " ";
System.out.println("URL IS +==========" + responseUrl);
} catch (Exception e) {
e.printStackTrace();
}
//Add the path of the image to the array list and pass it to our custom adapter.
bitmapArrayList.add(takenImage);
imageSwipeAdapter = new ImageSwipeAdapter(this, iv, bitmapArrayList, viewPager, this, al,
viewPagerLayout, cameraBtn);
viewPager.setAdapter(imageSwipeAdapter);
} else {
Toast.makeText(this, "Picture Wasn't taken!", Toast.LENGTH_SHORT).show();
}
My AsyncTask is uploading the image in the background.
In my app when i upload an image i want to reduce the data so i call this function. But this piece of code is giving me an outOfMemoryError.
LOGCAT: 09-17 15:32:01.712: E/AndroidRuntime(7771): at com.technow.pereo.FileHelper.reduceImageForUpload(FileHelper.java:64)
public static byte[] reduceImageForUpload(byte[] imageData) {
Bitmap bitmap = ImageResizer.resizeImageMaintainAspectRatio(imageData,
SHORT_SIDE_TARGET);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 50, outputStream);
bitmap.recycle();
byte[] reducedData = outputStream.toByteArray();
try {
outputStream.close();
} catch (IOException e) {
// Intentionally blank
}
return reducedData;
}
What is causing this error and how do I resolve it?!
Seems ImageResizer is a custom class. Use the snippet below to re-size the image before you brought the image for further processing.
//decodes image and scales it to reduce memory consumption
private Bitmap decodeFile(File f){
try {
//decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE=70;
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale*=2;
}
//decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}
I want to resize an image and then to write it back to outputstream, for this I need to convert the scaled image into bytes, how can I convert it?
ByteArrayInputStream bais = new ByteArrayInputStream(ecn.getImageB());
BufferedImage img = ImageIO.read(bais);
int scaleX = (int) (img.getWidth() * 0.5);
int scaleY = (int) (img.getHeight() * 0.5);
Image newImg = img.getScaledInstance(scaleX, scaleY, Image.SCALE_SMOOTH);
outputStream.write(newImg); //cannot resolve
how to fix outputStream.write(newImg)???
Use this method for scaling:
public static BufferedImage scale(BufferedImage sbi,
int imageType, /* type of image */
int destWidth, /* result image width */
int destHeight, /* result image height */
double widthFactor, /* scale factor for width */
double heightFactor /* scale factor for height */ )
{
BufferedImage dbi = null;
if(sbi != null) {
dbi = new BufferedImage(destWidth, destHeight, imageType);
Graphics2D g = dbi.createGraphics();
AffineTransform at = AffineTransform.getScaleInstance(widthFactor, heightFactor);
g.drawRenderedImage(sbi, at);
}
return dbi;
}
Then you'll have a BufferedImage which you can write to a byte array
public static byte[] writeToByteArray(BufferedImage bi, String dImageFormat) throws IOException, Exception {
byte[] scaledImageData = null;
ByteArrayOutputStream baos = null;
try {
if(bi != null) {
baos = new ByteArrayOutputStream();
if(! ImageIO.write(bi, dImageFormat, baos)) {
throw new Exception("no appropriate writer found for the format " + dImageFormat);
}
scaledImageData = baos.toByteArray();
}
} finally {
if(baos != null) {
try {
baos.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}
return scaledImageData;
}
Include this line and check:-
ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
ImageIO.write(originalImage, "jpg", outputStream);
byte[] imageInByte=outputStream.toByteArray();
I have converted an image(String url) using a bitmap but sometimes it produces an out of memory error. Here is my code:
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//Find the correct scale value. It should be the power of 2.
final int REQUIRED_SIZE=150;
int width_tmp=o.outWidth, height_tmp=o.outHeight;
int scale=1;
while(true){
if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
break;
width_tmp/=2;
height_tmp/=2;
scale++;
}
//decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
First of all, reduce the size of an image. You can do it without drastically change the quality. And for an experiment just try to save your image as a bitmap. You will be shocked. If, for instance, your jpg is 3MB in size, it will be about 21MB after converting to bmp - huge number!
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = true;
bmpFactoryOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;
try {
bmp = BitmapFactory
.decodeStream(
getContentResolver().openInputStream(
imageFileUri), null, bmpFactoryOptions);
bmpFactoryOptions.inSampleSize = quality;
System.out.println("The Quality is" + quality);
bmpFactoryOptions.inJustDecodeBounds = false;
bmp = BitmapFactory
.decodeStream(
getContentResolver().openInputStream(
imageFileUri), null, bmpFactoryOptions);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
String[] orientationColumn = { ImageColumns.ORIENTATION };
#SuppressWarnings("deprecation")
Cursor cur = managedQuery(imageFileUri, orientationColumn, null,
null, null);
int orientation = -1;
if (cur != null && cur.moveToFirst()) {
orientation = cur.getInt(cur
.getColumnIndex(orientationColumn[0]));
}
Matrix matrix = new Matrix();
matrix.postRotate(orientation);
bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(),
bmp.getHeight(), matrix, true);
view.setImageBitmap(bmp);
int quality = 4;
find it more effective with big bitmaps.