Load image from internet url, some are rotated 90 degrees - android

How to recognize the image load from url is rotated?
I have a list of images which are from the url, and some of the loaded images are 90 degrees rotated compared to the original image.

Here you have it. This will re-orientate your image if it is in landscape mode :
int width = bitmap.getWidth();
int height = bitmap.getHeight();
if (width > height){
rotatedBitmap = rotate(bitmap,-90)
}
private Bitmap rotate(Bitmap bm, int rotation) {
if (rotation != 0) {
Matrix matrix = new Matrix();
matrix.postRotate(rotation);
Bitmap bmOut = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
return bmOut;
}
return bm;
}

Related

How to increase pixels size of a Bitmap

I want to know if it's possible to modify bitmap pixels by pixels. I'm not asking for changing bitmap size/scale. What I'm looking for is that I want to increase size of all or some specific pixels of a bitmap.
I tried this
Thread(Runnable {
val newBitmap = Bitmap.createScaledBitmap(bitmap, bitmap.width * 4,
bitmap.height * 4, true);
for (x in 0 until bitmap.getWidth()) {
for (y in 0 until bitmap.getHeight()) {
val pixel = bitmap.getPixel(x, y);
val redValue = Color.red(pixel)
val blueValue = Color.blue(pixel)
val greenValue = Color.green(pixel)
newBitmap.setPixel(x * 4, y * 4, Color.rgb(redValue, greenValue, blueValue))
}
}
runOnUiThread({ imageView.setImageBitmap(newBitmap) })
}).start()
But it has no effect on the bitmap. Any kind of help is highly appreciated.
If you want to pixelate just a part of your bitmap, then you could create a Bitmap of the part which you wish to edit, perform changes on the new bitmap and then overlay the changed bitmap on top of the original bitmap.
So for example, you could pixelate a portion of a Bitmap by doing something along the following lines,
#Override
protected void onCreate(Bundle savedInstanceState) {
...
Bitmap originalBitmap = ((BitmapDrawable) getResources().getDrawable(R.drawable.drawabledroid)).getBitmap();
// Pixelate just the top half
int x = 0, y = 0, width = originalBitmap.getWidth(), height = originalBitmap.getHeight()/2;
//Or pixelate a rectangle in the middle
//int x = originalBitmap.getWidth()/2 - 50, y = originalBitmap.getHeight()/2 - 50, width = 100, height = 100;
//Get bitmap with region you want to pixelate
Bitmap original = Bitmap.createBitmap(originalBitmap, x,y,width,height);
int normalWidth = original.getWidth(), normalHeight = original.getHeight();
int smallWidth = normalWidth/15, smallHeight = normalHeight/15;
Bitmap small = getResizedBitmap(original, smallWidth, smallHeight);
Bitmap pixelated = getResizedBitmap(small, normalWidth, normalHeight);
//Overlay the pixelated bitmap on top of the original
Bitmap overlayed = overlayBitmaps(originalBitmap, pixelated,x,y, width, height);
}
public Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
return Bitmap.createBitmap(
bm, 0, 0, width, height, matrix, false);
}
public static Bitmap overlayBitmaps(Bitmap bmp1, Bitmap bmp2, int x, int y, int width, int height) {
Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth(), bmp1.getHeight(), bmp1.getConfig());
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(bmp1, new Matrix(), null);
//If you know the background in transparent or any specific color
//Then you can color the region before overlaying the pixelated bitmap
Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.TRANSPARENT);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT));
mPaint.setAntiAlias(true);
canvas.drawRect(x,y, x+width,y+height, mPaint);
//Overlay the pixelated bitmap
canvas.drawBitmap(bmp2, x, y, null);
return bmOverlay;
}

Scaling the image and setting in Image View reduces image quality and squeezes it

I am tying to make a custom camera and after taking picture I am setting it in image view in the same activity as in which I am setting camera. I have been successful in taking the photos but before setting the image in image view I have to scale it which reduces the image quality. Is there any way to show the real image instead of scaling it?
My images are as below First one is real view of camera which is surface view:
After Taking photo it becomes:
The code I am using is:
Camera.PictureCallback picture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
mCamera.stopPreview();
surface_view.setVisibility(View.INVISIBLE);
setupImageDisplay(data);
}
};
private void setupImageDisplay(byte[] data) {
photo = BitmapFactory.decodeByteArray(data, 0, data.length);
photo = scaleDown(photo, true);//scaling down bitmap
imageview_photo.setImageBitmap(photo); //setting bitmap in imageview
}
public Bitmap scaleDown(Bitmap realImage, boolean filter) {
int screenWidth = width;
int screenHeight = height;
Bitmap scaled;
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
// Notice that width and height are reversed
scaled = Bitmap.createScaledBitmap(realImage, screenHeight, screenWidth, filter);
int w = scaled.getWidth();
int h = scaled.getHeight();
// Setting post rotate to 90
Matrix mtx = new Matrix();
if (camera_id == Camera.CameraInfo.CAMERA_FACING_FRONT) {
float[] mirrorY = {-1, 0, 0, 0, 1, 0, 0, 0, 1};
Matrix matrixMirrorY = new Matrix();
matrixMirrorY.setValues(mirrorY);
mtx.postConcat(matrixMirrorY);
}
mtx.postRotate(90);
// Rotating Bitmap
realImage = Bitmap.createBitmap(scaled, 0, 0, w, h, mtx, filter);
} else {// LANDSCAPE MODE
//No need to reverse width and height
scaled = Bitmap.createScaledBitmap(realImage, screenHeight, screenWidth, filter);
int w = scaled.getWidth();
int h = scaled.getHeight();
// Setting post rotate to 90
Matrix mtx = new Matrix();
if (camera_id == Camera.CameraInfo.CAMERA_FACING_FRONT) {
float[] mirrorY = {-1, 0, 0, 0, 1, 0, 0, 0, 1};
Matrix matrixMirrorY = new Matrix();
matrixMirrorY.setValues(mirrorY);
mtx.postConcat(matrixMirrorY);
}
mtx.postRotate(180);
// Rotating Bitmap
realImage = Bitmap.createBitmap(scaled, 0, 0, w, h, mtx, filter);
}
return realImage;
}
After taking photo the image is like squeezed is there any way that image remains the same after scaling?
You can create a separate file which is temporary file and stores the thumbnail size of the image. You can make a POJO like this to store both images. You can display the smaller one and use the original file to keep high quality.
public class Image {
File fullSize;
File Thumbnail;
public Image(File fullSize, File thumbnail) {
this.fullSize = fullSize;
Thumbnail = thumbnail;
}
public File getFullSize() {
return fullSize;
}
public void setFullSize(File fullSize) {
this.fullSize = fullSize;
}
public File getThumbnail() {
return Thumbnail;
}
public void setThumbnail(File thumbnail) {
Thumbnail = thumbnail;
}
}

poor image quality after saving rotated bitmap to sdcard

I am making an app where in one of the activity i am fetching image from gallery and showing it in adapter like image below
I have to rotate that image and save it to sdcard. My code is doing fine but after saving it to sdcard i get very poor quality of image. my code is:
viewHolder.imgViewRotate.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
imagePosition = (Integer) v.getTag();
Matrix matrix = new Matrix();
matrix.postRotate(90);
Bitmap rotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
try {
FileOutputStream out = new FileOutputStream(new File(uriList.get(rotatePosition).toString()));
rotated.compress(Bitmap.CompressFormat.PNG, 100, out);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
notifyDataSetChanged();
}
});
Any suggestions will be great help.
Try out below code to reduce image size without losing its quality:
public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth)
{
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// create a matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
return resizedBitmap;
}
EDITED:
Resize the image using BitmapFactory inSampleSize option and the image doesn't lose quality at all. Code:
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = true;
Bitmap bm = BitmapFactory.decodeFile(tempDir+"/"+photo1_path , bmpFactoryOptions);
int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)600);
int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)800);
if (heightRatio > 1 || widthRatio > 1)
{
if (heightRatio > widthRatio){
bmpFactoryOptions.inSampleSize = heightRatio;
} else {
bmpFactoryOptions.inSampleSize = widthRatio;
}
}
bmpFactoryOptions.inJustDecodeBounds = false;
bm = BitmapFactory.decodeFile(tempDir+"/"+photo1_path, bmpFactoryOptions);
// recreate the new Bitmap
src = Bitmap.createBitmap(bm, 0, 0,bm.getWidth(), bm.getHeight(), matrix, true);
src.compress(Bitmap.CompressFormat.PNG, 100, out);

Android - scale, rotate and save a bitmap to sdcard without losing quality

I'm doing an app which takes a photo with the camera and then rotates it and scales it.
I need to rotate the image because the camera returns a wrong rotated image and I need to scale it to reduce its size.
I first save in a temp directory the original image returned by camera, then I read it and make modifications, saving the new image to a new file.
I tried using matrix to rotate and scale the picture, but it loses quality.
Then I tried to scale it first with Bitmap.createScaledBitmap and then rotate it with matrix, but the result is even uglier than the one using only matrix.
Then I tried to rotate it first and then resize it using always Bitmap.createScaledBitmap. The image doesn't lose quality, but it's stretched as I scaled it after rotating it and width and height are inverted. Tried also to invert height and width according to the rotation made, but it loses quality again.
This is the last code I've written:
in= new FileInputStream(tempDir+"/"+photo1_path);
out = new FileOutputStream(file+"/picture.png");
Bitmap src = BitmapFactory.decodeStream(in);
int iwidth = src.getWidth();
int iheight = src.getHeight();
int newWidth = 0;
int newHeight = 0;
newWidth = 800;
newHeight = 600;
// calculate the scale - in this case = 0.4f
float scaleWidth = ((float) newWidth) / iwidth;
float scaleHeight = ((float) newHeight) / iheight;
// createa matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
//matrix.postScale(scaleWidth, scaleHeight);
int orientation = getOrientation(MyActivity.this,Uri.parse(tempDir+"/"+photo1_path));
switch(orientation) {
case 3:
orientation = 180;
break;
case 6:
orientation = 90;
break;
case 8:
orientation = 270;
break;
}
int rotate = 0;
switch(orientation) {
case 90:
rotate=90;
break;
case 180:
rotate=180;
break;
case 270:
rotate=270;
break;
}
// rotate the Bitmap
matrix.postRotate(rotate);
src =Bitmap.createScaledBitmap(src , newWidth, newHeight, false);
// recreate the new Bitmap
Bitmap new_bit = Bitmap.createBitmap(src, 0, 0,
src.getWidth(), src.getHeight(), matrix, true);
new_bit.compress(Bitmap.CompressFormat.PNG, 100, out);
Any advice?
EDIT: If I only rotate or only scale the image, it doesn't lose quality. It's when I do both that the image loses quality. Also, if I put the image in an ImageView after resizing it and scaling it, it doesn't lose quality, it's just when I save it to file that loses quality.
Solved!
I resize the image using BitmapFactory inSampleSize option and the image doesn't lose quality at all.
Code:
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = true;
Bitmap bm = BitmapFactory.decodeFile(tempDir+"/"+photo1_path , bmpFactoryOptions);
int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)600);
int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)800);
if (heightRatio > 1 || widthRatio > 1)
{
if (heightRatio > widthRatio){
bmpFactoryOptions.inSampleSize = heightRatio;
} else {
bmpFactoryOptions.inSampleSize = widthRatio;
}
}
bmpFactoryOptions.inJustDecodeBounds = false;
bm = BitmapFactory.decodeFile(tempDir+"/"+photo1_path, bmpFactoryOptions);
//bm.compress(Bitmap.CompressFormat.PNG, 100, out);
/*Bitmap new_bit = Bitmap.createScaledBitmap(src , newWidth, newHeight, true);
new_bit.compress(Bitmap.CompressFormat.PNG, 100, out);*/
// recreate the new Bitmap
src = Bitmap.createBitmap(bm, 0, 0,bm.getWidth(), bm.getHeight(), matrix, true);
//Bitmap dest = Bitmap.createScaledBitmap(new_bit , newWidth, newHeight, true);
src.compress(Bitmap.CompressFormat.PNG, 100, out);
use this method to rotate the bitmap...
private Bitmap checkifImageRotated() {
ExifInterface exif;
try {
exif = new ExifInterface(file.getAbsolutePath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
int rotate = 0;
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_270 :
rotate = -90;
break;
case ExifInterface.ORIENTATION_ROTATE_180 :
rotate = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_90 :
rotate = 90;
break;
}
if (rotate != 0) {
Bitmap bitmap = BitmapFactory.decodeFile(getTempFile().getPath());
Matrix matrix = new Matrix();
matrix.setRotate(rotate);
Bitmap bmpRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
recycle(bitmap);
return bmpRotated;
}
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
Don't make the new bitmap just override
int angle=0; int valueangle=0; Bitmap bitmap;
#Override
public void onClick(View v) {
System.out.println("valueeeeeee " + angle);
if (bitmap != null) {
angle = valueangle + 90;
Matrix matrix = new Matrix();
matrix.postRotate(angle);
bitmap = Bitmap.createBitmap(
bitmap , 0, 0,
bitmap .getWidth(),
bitmap .getHeight(), matrix, true);
main_img.setImageBitmap(bitmap );
} else {
System.out.println(" bitmap is null");
}
}

How to stop changes of bitmap size when it is Rotating?

I want to rotate bitmap in my app. When i am going to rotate bitmap, bitmap size also changed.Please help me..
I tried with following Methods,but failed:
1st Method:
public Bitmap rotate(Bitmap bitmapOrg) {
int width = bitmapOrg.getWidth();
int height = bitmapOrg.getHeight();
Matrix matrix = new Matrix();
matrix.postRotate(45);
Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0, width,
height, matrix, true);
BitmapDrawable bmd = new BitmapDrawable(resizedBitmap);
bitmapOrg = resizedBitmap;
ImageView imageView = new ImageView(mContext);
imageView.setImageDrawable(bmd);
imageView.setScaleType(ScaleType.CENTER);
bitmapOrg=((BitmapDrawable)imageView.getDrawable()).getBitmap();
return bitmapOrg;
}
float totalRotated = 0;
public Bitmap rotate(Bitmap mBitmap,float degrees){
// compute the absolute rotation
totalRotated = (totalRotated + degrees) % 360;
// precompute some trig functions
double radians = Math.toRadians(totalRotated);
double sin = Math.abs(Math.sin(radians));
double cos = Math.abs(Math.cos(radians));
// figure out total width and height of new bitmap
int newWidth = (int) (mBitmap.getWidth() * cos + mBitmap.getHeight() * sin);
int newHeight = (int) (mBitmap.getWidth() * sin + mBitmap.getHeight() * cos);
// set up matrix
matrix.reset();
matrix.postTranslate((newWidth - mBitmap.getWidth()) / 2, (newHeight - mBitmap.getHeight()) / 2);
matrix.setRotate(totalRotated);
// create new bitmap by rotating mBitmap
Bitmap rotated = Bitmap.createBitmap(mBitmap, 0, 0,newWidth, newHeight, matrix, true);
return rotated;
}

Categories

Resources