I just finished my camera activity and it's wonderfully saving the data.
What I do after the picture is taken:
protected void savePictureData() {
try {
FileOutputStream fs = new FileOutputStream(this.photo);
fs.write(this.lastCamData);
fs.close(); //okay, wonderful! file is just written to the sdcard
//---------------------
//---------------------
//TODO in here: dont save just the file but ROTATE the image and then save it!
//---------------------
//---------------------
Intent data = new Intent(); //just a simple intent returning some data...
data.putExtra("picture_name", this.fname);
data.putExtra("byte_data", this.lastCamData);
this.setResult(SAVED_TOOK_PICTURE, data);
this.finish();
} catch (IOException e) {
e.printStackTrace();
this.IOError();
}
}
What I want to is already as comment given in the code above. I dont want the image just to be saved to file but to be rotated and then saved! Thanks!
//EDIT: What I am currently up to (Works but still runs into memory issues with large images)
byte[] pictureBytes;
Bitmap thePicture = BitmapFactory.decodeByteArray(this.lastCamData, 0, this.lastCamData.length);
Matrix m = new Matrix();
m.postRotate(90);
thePicture = Bitmap.createBitmap(thePicture, 0, 0, thePicture.getWidth(), thePicture.getHeight(), m, true);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
thePicture.compress(CompressFormat.JPEG, 100, bos);
pictureBytes = bos.toByteArray();
FileOutputStream fs = new FileOutputStream(this.photo);
fs.write(pictureBytes);
fs.close();
Intent data = new Intent();
data.putExtra("picture_name", this.fname);
data.putExtra("byte_data", pictureBytes);
this.setResult(SAVED_TOOK_PICTURE, data);
this.finish();
Read the path from sd card and paste the following code...It'll Replace the existing photo after rotating it..
Note: Exif doesn't work on most of the devices, it returns incorrect data so it's good to hard code the rotation before saving to any degree you want to, Just change the angle value in postRotate.
String photopath = tempphoto.getPath().toString();
Bitmap bmp = BitmapFactory.decodeFile(photopath);
Matrix matrix = new Matrix();
matrix.postRotate(90);
bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
FileOutputStream fOut;
try {
fOut = new FileOutputStream(tempphoto);
bmp.compress(Bitmap.CompressFormat.JPEG, 85, fOut);
fOut.flush();
fOut.close();
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Before you create your FileOutputStream you can create a new Bitmap from the original that has been transformed using a Matrix. To do that you would use this method:
createBitmap(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)
Where the m defines a matrix that will transpose your original bitmap.
For an example on how to do this look at this question:
Android: How to rotate a bitmap on a center point
bitmap = RotateBitmap(bitmap, 90);
public static Bitmap RotateBitmap(Bitmap source, float angle)
{
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
}
Related
Please suggest me the way to rotate the bitmap image in android.
I have following sample but when I rotate the image with 10 degrees it gets black at corners as well as size of image is increased.
When i rotate image continuously with 10 degrees it throw memory out of bound exception.
private void rotateImage(String sourcePath, float angle) {
Bitmap bitmap = BitmapFactory.decodeFile(sourcePath);
Matrix matrix = new Matrix();
matrix.setRotate(angle);
Bitmap rotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
File file = new File(sourcePath);
FileOutputStream fOut = null;
try {
fOut = new FileOutputStream(file);
rotated.compress(Bitmap.CompressFormat.PNG, 85, fOut);
fOut.flush();
fOut.close();
bitmap.recycle();
rotated.recycle();
} catch (Exception e) {
e.printStackTrace();
}
}
Try ExifInterface for image rotation
check this solution for details, how to use ExifInterface
See more info about Exif
I'm trying to create a Bitmap from an existing URI, rotate the Bitmap and save it to the same place as a JPEG file. This is my current code after having tried several solutions:
try {
// Get the Bitmap from the known URI. This seems to work.
Bitmap bmp = MediaStore.Images.Media.getBitmap(this.getContentResolver(), this.currUserImgUri);
// Rotate the Bitmap thanks to a rotated matrix. This seems to work.
Matrix matrix = new Matrix();
matrix.postRotate(-90);
bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
// Create an output stream which will write the Bitmap bytes to the file located at the URI path.
File imageFile = new File(this.currUserImgUri.getPath());
FileOutputStream fOut = new FileOutputStream(imageFile); // --> here an Exception is catched; see below.
// The following doesn't work neither:
// FileOutputStream fOut = new FileOutputStream(this.currUserImgUri.getPath());
// Write the compressed file into the output stream
bmp.compress(Bitmap.CompressFormat.JPEG, 85, fOut);
fOut.flush();
fOut.close();
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
The catched exception is as follows:
java.io.FileNotFoundException: /external/images/media/8439: open failed: ENOENT (No such file or directory)
Can anyone explain to me how can the file not exist if I just created it and have access to its URI?
Perhaps I'm going all wrong about it? In this case, what would be the correct way to save the rotated image to the same location based on its URI?
hey you can do this to write bitmap to file using .
// Rotate the Bitmap thanks to a rotated matrix. This seems to work.
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContext().getContentResolver(), photoURI);
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap bmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
//learn content provider for more info
OutputStream os=getContext().getContentResolver().openOutputStream(photoURI);
bmp.compress(Bitmap.CompressFormat.PNG,100,os);
don't forget flush and close output stream.
actually content provider have it's own uri scheme.
Here's a Kotlin extension function which, given a URI to an image, will rotate the image and store it again at the same URI.
fun Context.rotateImage(imageUri: uri, angle: Float) {
// (1) Load from where the URI points into a bitmap
val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, imageUri)
// (2) Rotate the bitmap
val rotatedBitmap = bitmap.rotatedBy(angle)
// (3) Write the bitmap to where the URI points
try {
contentResolver.openOutputStream(imageUri).also {
rotateBitmap.compress(Bitmap.CompressFormat.PNG, 100, it)
}
} catch (e: IOException) {
// handle exception
}
}
fun Bitmap.rotatedBy(angle: Float) {
val matrix = Matrix().apply { postRotate(angle) }
return Bitmap.createBitmap(this, 0, 0, width, height, matrix, true)
}
You could instead define the function to accept the context as an argument, making the receiver whatever is convenient for you.
I am new to android.I have an application which has functionality to upload image from the gallery or take image from camera. Below I have written the code where I get the image.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode!=0){
if(PICK_MEDIA_FROM_GALLERY == requestCode){
if(null != data){
Uri uri = data.getData();
//String type = getMimeType(uri);
filePath = getRealPathFromURI(uri);
checkFileSupport(filePath);
}
}else{
if(ACTION_TAKE_PHOTO == requestCode){
checkFileSupport(filePath);
}else if(ACTION_TAKE_VIDEO == requestCode){
handleCameraVideo();
}
}
}
}
This function is used to fix the write orientation for the image.
public Bitmap fixOrientation(Bitmap bmp) {
try {
ExifInterface exif = new ExifInterface(filePath);
int orientation = exif.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
if (orientation==6)
{
Matrix matrix = new Matrix();
matrix.postRotate(90);
bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
}
else if (orientation==8)
{
Matrix matrix = new Matrix();
matrix.postRotate(270);
bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
}
else if (orientation==3)
{
Matrix matrix = new Matrix();
matrix.postRotate(180);
bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return bmp;
}
I set Image to imageview using the function
private void setImagePreview(final String realPath) throws IOException {
Display display = getWindowManager().getDefaultDisplay();
Bitmap bitmap = ImageUtils.getThumbnailBitmap(realPath, display.getWidth());
if(null!=bitmap){
//rotate image and save in the same filepath
bitmap = fixOrientation(bitmap);
FileOutputStream fOut = new FileOutputStream(filePath);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
fOut.flush();
fOut.close();
RelativeLayout tempLayout = (RelativeLayout) findViewById(R.id.previewLayout);
tempLayout.setVisibility(View.VISIBLE);
ImageView previewImageView = (ImageView) findViewById(R.id.previewImageView);
previewImageView.setImageBitmap(bitmap);
}
}
I have the an image in Camera.
When I select that image from Gallery for the first time,
When I try Changing the attachment and select the same picture the view appears like this
How can I solve this issue?Can anyone please help me out?
Your code seems to be OK. Whenever I resize the image I use BitmapFactory.Options class. See this class.
What Bitmap bitmap = ImageUtils.getThumbnailBitmap(realPath, display.getWidth()); returns? A full bitmap or a Thumbnail? Thumbnail is a pretty small.
It seems that you are changing the original image instead of copy of the image. Get the file path and create your image by yourself. And, to avoid OutOfMemoryException use BitmapFactory.Options property InSampleSize. I am not sure about property. Just Google out and you will find.
I hope this helps you solve your problem.
Your second image quality seems worse than the first one. You can check whether you set ImageView width and height wrap_content? If yes, try to set a fixed value for test. and whether the two bitmap sizes are same, width and height?
Is there a way to rotate byte array without decoding it to Bitmap?
Currently in jpeg PictureCallback I just write byte array directly to file. But pictures are rotated. I would like to rotate them without decoding to bitmap with hope that this will conserve my memory.
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(data, 0, data.length, o);
int orientation;
if (o.outHeight < o.outWidth) {
orientation = 90;
} else {
orientation = 0;
}
File photo = new File(tmp, "demo.jpeg");
FileOutputStream fos;
BufferedOutputStream bos = null;
try {
fos = new FileOutputStream(photo);
bos = new BufferedOutputStream(fos);
bos.write(data);
bos.flush();
} catch (IOException e) {
Log.e(TAG, "Failed to save photo", e);
} finally {
IOUtils.closeQuietly(bos);
}
Try this. It will solve the purpose.
Bitmap storedBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, null);
Matrix mat = new Matrix();
mat.postRotate("angle"); // angle is the desired angle you wish to rotate
storedBitmap = Bitmap.createBitmap(storedBitmap, 0, 0, storedBitmap.getWidth(), storedBitmap.getHeight(), mat, true);
You can set JPEG rotation via Exif header without decoding it. This is the most efficient method, but some viewers may still show a rotated image.
Alternatively, you can use JPEG lossless rotation. Unfortunately, I am not aware of free Java implementations of this algorithm.
Update on SourceForge, there is a Java open source class LLJTran. The Android port is on GitHub.
I don't think that there is such possibility. Bytes order depends from picture encoding (png, jpeg). So you are forced to decode image to do something with it.
Try like this,
private byte[] rotateImage(byte[] data, int angle) {
Log.d("labot_log_info","CameraActivity: Inside rotateImage");
Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length, null);
Matrix mat = new Matrix();
mat.postRotate(angle);
bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mat, true);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 100, stream);
return stream.toByteArray();
}
You can call the rotateImage by providing the image data which is getting from onPictureTaken method and an angle for rotation.
Eg: rotateImage(data, 90);
I'm trying to build a ring from twenty copies of a single image, which is a 1/20th slice of the full ring. I generate bitmaps that are this original image rotated to their correct degree amounts. The original image is a 130x130 square
The code that generates the rotated slices looks like this:
Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), R.drawable.battery_green);
FileOutputStream fos;
for(int i = 0; i < 20; i++) {
String idName = "batt_s_"+i;
Matrix m = new Matrix();
m.setRotate((i * 18)-8, bmp.getWidth()/2, bmp.getHeight()/2);
Bitmap newBmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), m, true);
try {
fos = context.openFileOutput(idName+"_"+color+".png", Context.MODE_WORLD_READABLE);
newBmp.compress(CompressFormat.PNG, 100, fos);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
m.reset();
BattConfigureSmall.saveInitPref(context, true);
}
The ImageViews that these generated bitmaps are eventually being slotted into all have scaleType="center" in their XML. However, the generated output looks like this:
Not exactly a perfect ring. The slices themselves, if rotated correctly, do make a perfect ring, because in API level 11 and up I'm using the android:rotate XML attribute on these ImageViews, but I need to support API levels 7-10 as well, so can anybody give me some advice? Thank you.
Don't use the matrix with createBitmap for this scenario, it'll do some odd things with image sizing, I think. Instead, create a new Bitmap and Canvas then draw to it with the matrix:
Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), R.drawable.battery_green);
FileOutputStream fos;
Paint paint = new Paint();
paint.setAntiAlias(true);
Matrix m = new Matrix();
for(int i = 0; i < 20; i++) {
String idName = "batt_s_"+i;
m.setRotate((i * 18)-8, bmp.getWidth()/2, bmp.getHeight()/2);
Bitmap newBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(newBmp);
canvas.drawBitmap(bmp, m, paint);
try {
fos = context.openFileOutput(idName+"_"+color+".png", Context.MODE_WORLD_READABLE);
newBmp.compress(CompressFormat.PNG, 100, fos);
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
m.reset();
BattConfigureSmall.saveInitPref(context, true);
}