Cropping image by setting height dynamically - android

Guess a picture of man. (Head at top & legs at bottom) :P
I am setting height dynamically using layoutparam.
When I set height for instance 300,
It sets height from HEAD to 300 units toward legs of image.
What I want is to set height from LEGs to top 300 units.
imageView.setHeight()

Use this method in your java class:
private void scaleImage(ImageView view) throws NoSuchElementException {
// Get bitmap from the the ImageView.
Bitmap bitmap = null;
try {
Drawable drawing = view.getDrawable();
bitmap = ((BitmapDrawable) drawing).getBitmap();
} catch (NullPointerException e) {
throw new NoSuchElementException("No drawable on given view");
} catch (ClassCastException e) {
// Check bitmap is Ion drawable
// bitmap = Ion.with(view).getBitmap();
}
// Get current dimensions AND the desired bounding box
int width = 0;
try {
width = bitmap.getWidth();
} catch (NullPointerException e) {
throw new NoSuchElementException("Can't find bitmap on given view/drawable");
}
int height = bitmap.getHeight();
int bounding = dpToPx(150);// set height
Logger.i("Test", "original width = " + Integer.toString(width));
Logger.i("Test", "original height = " + Integer.toString(height));
Logger.i("Test", "bounding = " + Integer.toString(bounding));
// Determine how much to scale: the dimension requiring less scaling is
// closer to the its side. This way the image always stays inside your
// bounding box AND either x/y axis touches it.
float xScale = ((float) bounding) / width;
float yScale = ((float) bounding) / height;
float scale = (xScale <= yScale) ? xScale : yScale;
Logger.i("Test", "xScale = " + Float.toString(xScale));
Logger.i("Test", "yScale = " + Float.toString(yScale));
Logger.i("Test", "scale = " + Float.toString(scale));
// Create a matrix for the scaling and add the scaling data
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
// Create a new bitmap and convert it to a format understood by the ImageView
Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
width = scaledBitmap.getWidth(); // re-use
height = scaledBitmap.getHeight(); // re-use
BitmapDrawable result = new BitmapDrawable(scaledBitmap);
Logger.i("Test", "scaled width = " + Integer.toString(width));
Logger.i("Test", "scaled height = " + Integer.toString(height));
// Apply the scaled bitmap
view.setImageDrawable(result);
// Now change ImageView's dimensions to match the scaled image
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams();
params.width = width;
params.height = height;
view.setLayoutParams(params);
Logger.i("Test", "done");
}
private int dpToPx(int dp) {
float density = getApplicationContext().getResources().getDisplayMetrics().density;
return Math.round((float) dp * density);
}
Now, how to call this methord :
Bitmap bitmap;
try {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), selectedImage);
imageView.setImageBitmap(bitmap);
scaleImage(imageView);// call your imageview
} catch (IOException e) {
e.printStackTrace();
}

Related

Capture image using dynamic co-ordinates through the camera

I am making a camera based application, where I put a rectangular view over the camera.
When I capture an image using new Camera.PictureCallback(), I cropped that image so as it will get the part of the rectangle.
Well, its working fine.
Now I implemented View.OnTouchListener and using that I made the shape movable.
So, I need to capture the image with the final selection of the user, like where they place the rectangle.
Bitmap imageOriginal = BitmapFactory.decodeByteArray(data, 0, data.length); // 2560×1440
float scale = 1280 / 1000;
int left = (int) (scale * (imageOriginal.getWidth() - 250) / 2);
int top = (int) (scale * (imageOriginal.getHeight() - 616) / 2);
int width = (int) (scale * 750);
int height = (int) (scale * 616);
Bitmap imageConverted = Bitmap.createBitmap(imageOriginal, left, top, width, height, null, false);
This is the method i used to crop image.The values are hard corded to find the exact position.
Now i need values for that top ,bottom, height, width with the changing rectangle.
//My customView that used to draw that rectangle
public class CustomView extends View {
private Paint paint = new Paint();
public CustomView(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) { // Override the onDraw() Method
super.onDraw(canvas);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.GREEN);
paint.setStrokeWidth(10);
//center
int x0 = canvas.getWidth()/2;
int y0 = canvas.getHeight()/2;
int dx = canvas.getHeight()/3;
int dy = canvas.getHeight()/3;
//draw guide box
canvas.drawRect(x0-dx, y0-dy, x0+dx, y0+dy, paint);
}
}
//my picture callback code
Camera.PictureCallback mPicture = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
// Replacing the button after a photho was taken.
// File name of the image that we just took.
fileName = "IMG_" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()).toString() + ".jpg";
// Creating the directory where to save the image. Sadly in older
// version of Android we can not get the Media catalog name
File mkDir = new File(sdRoot, dir);
mkDir.mkdirs();
// Main file where to save the data that we recive from the camera
File pictureFile = new File(sdRoot, dir + fileName);
// Cropping image with the corresponding co-ordinates and save in to a file
try {
Bitmap imageOriginal = BitmapFactory.decodeByteArray(data, 0, data.length); // 2560×1440
float scale = 1280 / 1000;
int left = (int) (scale * (imageOriginal.getWidth() - 250) / 2);
int top = (int) (scale * (imageOriginal.getHeight() - 616) / 2);
int width = (int) (scale * 750);
int height = (int) (scale * 616);
Bitmap imageConverted = Bitmap.createBitmap(imageOriginal, left, top, width, height, null, false);
FileOutputStream purge = new FileOutputStream(pictureFile);
imageConverted.compress(Bitmap.CompressFormat.JPEG, 100, purge);
purge.flush();
purge.close();
} catch (FileNotFoundException e) {
Log.d("DG_DEBUG", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("DG_DEBUG", "Error accessing file: " + e.getMessage());
}
// Adding Exif data for the orientation.
try {
ProjectManager.getInstance().settings.IMAGE_LOCATION = "/sdcard/" + dir + fileName;
exif = new ExifInterface(ProjectManager.getInstance().settings.IMAGE_LOCATION);
exif.setAttribute(ExifInterface.TAG_ORIENTATION, "" + orientation);
exif.saveAttributes();
mView.saveImage(dir + fileName);
} catch (IOException e) {
e.printStackTrace();
}
}
};
For me, I take a image then crop according to dimension of the selected area of the image..
public void onPictureTaken(byte[] data, Camera camera) {
Bitmap imageOriginal = BitmapFactory.decodeByteArray(data, 0, data.length, null);
int width = imageOriginal.getWidth();
int height = imageOriginal.getHeight(); // for width
int narrowSize = Math.min(width, height); // for height
int differ = (int) Math.abs((imageOriginal.getHeight() - imageOriginal.getWidth()) / 2.0f); // for dimension
width = (width == narrowSize) ? 0 : differ;
height = (width == 0) ? differ : 0;
Matrix rotationMatrix = new Matrix();
rotationMatrix.postRotate(90); // for orientation
Bitmap imageCropped = Bitmap.createBitmap(imageOriginal, width, height, narrowSize, narrowSize, rotationMatrix, false);
}
Capture Image
Output Image
Your rectangle is mCustomView.getWidth()*2/3 pixels wide, and mCustomView.getHeight()*2/3 pixels high, and its left corner is at 1/6 of mCustomView.getWidth(), if I understand your post correctly.
public void onPictureTaken(byte[] data, Camera camera) {
//.../
Bitmap imageOriginal = BitmapFactory.decodeByteArray(data, 0, data.length);
int[] customViewPosition;
mCustomView.getLocationInWindow(customViewPosition);
int[] surfacePosition;
mSurfaceView.getLocationInWindow(surfacePosition);
float scale = imageOriginal.getWidth()/(float)mSurfaceView.getWidth();
int left = (int) scale*(customViewPosition[0] + mCustomView.getWidth()/6F - surfacePosition[0]);
int top = (int) scale*(customViewPosition[1] + mCustomView.getHeight()/6F - surfacePosition[1]);
int width = (int) scale*mCustomView.getWidth()*2/3;
int height = (int) scale*mCustomView.getHeight()*2/3;
Bitmap imageCropped = Bitmap.createBitmap(imageOriginal, left, top, width, height, null, false);
//.../
}

android : drawing to canvas without stretching

I an trying to draw a bitmap to canvas. it results in stretching the bitmap. What i want is not to stretch if image small and crop the image if it is bigger than the display. How this can be achieved.
I have a custom drawable that extends DrawableWrapper
public class MyDrawable extends DrawableWrapper {
public MyDrawable(Drawable drawable) {
super(drawable);
}
public MyDrawable(final Context context, Bitmap bitmap) {
this(new BitmapDrawable(context.getResources(),bitmap));
}
I am having this code in boundsChnage()
protected void onBoundsChange(Rect bounds) {
mBitmap = Bitmap.createBitmap(bounds.width(), bounds.height(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(mBitmap);
super.draw(canvas);
}
This results in drawing a cropped part of the stretched drawable.
i think it will help you.
Bitmap scaleBitmap = scaleBitmap(bitmap);
RectF rectF = new RectF(0, (mHeight scaleBitmap.getHeight()),
scaleBitmap.getWidth(), scaleBitmap.getHeight());
canvas.drawBitmap(scaleBitmap, null, rectF, null);
private Bitmap scaleBitmap(Bitmap bm) {
int width = bm.getWidth();
int height = bm.getHeight();
Log.v("Pictures", "Width and height are " + width + "--" + height);
int mWidth = this.getResources().getDisplayMetrics().widthPixels;
int mHeight = this.getResources().getDisplayMetrics().heightPixels;
if (width > height) {
// landscape
int ratio = width / mWidth;
width = mWidth;
height = height / ratio;
} else if (height > width) {
// portrait
int ratio = height / mHeight;
height = mHeight;
width = width / ratio;
} else {
// square
height = mWidth;
width = mWidth;
}
Log.v("Pictures", "after scaling Width and height are " + width + "--" + height);
bm = Bitmap.createScaledBitmap(bm, width, height, true);
return bm;
}

Scaling Imageview on auto rotation

I am getting a url and displaying it in Imageview. the auto roation of my device is ON. i want the imageview to scale according to width of device once it is rotated.
is it possible when I am getting image from a url?
You can do this in code as well if the image is adjusted in away that doesnt look right or you just want more control over what is happening on rotate.
First get the device width and height:
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
Then you can use that information to resize the image.
You can set o.inJustDecodeBounds = true to get the image sizes without loading the image. If the image is to big, you can resize it. Example code below.
private Bitmap getBitmap(String path) {
Uri uri = getImageUri(path);
InputStream in = null;
try {
final int IMAGE_MAX_SIZE = 1200000; // 1.2MP
in = mContentResolver.openInputStream(uri);
// Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, o);
in.close();
int scale = 1;
while ((o.outWidth * o.outHeight) * (1 / Math.pow(scale, 2)) > IMAGE_MAX_SIZE) {
scale++;
}
Log.d(TAG, "scale = " + scale + ", orig-width: " + o.outWidth + ", orig-height: " + o.outHeight);
Bitmap b = null;
in = mContentResolver.openInputStream(uri);
if (scale > 1) {
scale--;
// scale to max possible inSampleSize that still yields an image
// larger than target
o = new BitmapFactory.Options();
o.inSampleSize = scale;
b = BitmapFactory.decodeStream(in, null, o);
// resize to desired dimensions
int height = b.getHeight();
int width = b.getWidth();
Log.d(TAG, "1th scale operation dimenions - width: " + width + ", height: " + height);
double y = Math.sqrt(IMAGE_MAX_SIZE / (((double) width) / height));
double x = (y / height) * width;
Bitmap scaledBitmap = Bitmap.createScaledBitmap(b, (int) x, (int) y, true);
b.recycle();
b = scaledBitmap;
System.gc();
} else {
b = BitmapFactory.decodeStream(in);
}
in.close();
Log.d(TAG, "bitmap size - width: " +b.getWidth() + ", height: " + b.getHeight());
return b;
} catch (IOException e) {
Log.e(TAG, e.getMessage(),e);
return null;
}
}

Android scaling down a Bitmap based on SurfaceView

So I am trying to scale down a bitmap based on the size of a surface view I have written the following code
public Bitmap scaleBitMap(int width, int height, Bitmap b){
// scale down based on the size of the Surface view.
// width and height = canvas.getHeight(), canvas.getWidth();
// this should set the height and width of the bitmap based on a percentage
// the bit map is returned and then displayed by canvas.drawBitmap(scaleBitMap(canvas.getHeight(),canvas.getWidth(),bitmapHere)....
Bitmap bitmap = null;
try{
bitmap = Bitmap.createScaledBitmap(b, (height/100 * 10), (width/100 * 10), true);
}catch(Exception e){
}
return bitmap;
}
Ok so this code works! returns a scaled bitmap.
I am not sure what are you trying to do, but i have done similar thing before. This code scales bitmap to match screensize. Maybe it will help you.
public Bitmap scaleBitMap(int width, int height, Bitmap b){
// scale down based on the size of the Surface view.
// width and height = canvas.getHeight(), canvas.getWidth();
// this should set the height and width of the bitmap based on a percentage
// the bit map is returned and then displayed by canvas.drawBitmap(scaleBitMap(canvas.getHeight(),canvas.getWidth(),bitmapHere)....
Bitmap bitmap = null;
try{
float scaledvalues[] = scale(b.getWidth(), b.getHeight(), width, height);
bitmap = Bitmap.createScaledBitmap(b, scaledvalues[1], scaledvalues[0], true);
}catch(Exception e){
}
return bitmap;
}
public float[] scale(int bitmapWidth, int bitmapHeight, int viewWidth, int viewHeight){
float scaledheight = -1f;
float scaledwidth = -1f;
float scaledheightpros = -1f;
float scaledwidthpros = -1f;
float finalheight = -1f;
float finalwidth = -1f;
if(bitmapHeight > viewHeight){
scaledheight = bitmapHeight - viewHeight;
float s = scaledheight*100f;
scaledheightpros = s / 100f;
}
if(bitmapWidth > viewWidth){
scaledwidth = bitmapWidth - viewWidth;
float z = scaledwidth * 100f;
scaledwidthpros = z / bitmapWidth;
}
if(scaledheightpros > scaledwidthpros){
float a = bitmapHeight/100f;
float b = bitmapWidth/100f;
finalheight = bitmapHeight - (a * scaledheightpros);
finalwidth = bitmapWidth - (b * scaledheightpros);
}
else{
float a = bitmapHeight/100f;
float b = bitmapWidth/100f;
finalheight = bitmapHeight - (a * scaledwidthpros);
finalwidth = bitmapWidth - (b * scaledwidthpros);
}
float array[] = {finalwidth, finalheight};
return array;
}
It works.. but perhaps i should check my math!
here is the working code....
public Bitmap scaleBitMap(int width, int height, Bitmap b){
// scale down based on the size of the Surface view.
// width and height = canvas.getHeight(), canvas.getWidth();
// this should set the height and width of the bitmap based on a percentage
// the bit map is returned and then displayed by canvas.drawBitmap(scaleBitMap(canvas.getHeight(),canvas.getWidth(),bitmapHere)....
Bitmap bitmap = null;
try{
bitmap = (Bitmap) createScaledBitmap(b, (height/100 * 22), (width/100 * 22), false);
}catch(Exception e){
Log.d("Bitmap","Issue: "+e);
}
return bitmap;
}

Resizeing bitmap

Hie. I am working on the live wallpaper and I have got a problem. I am done with the parallax effect in my wallpaper. Now, the problem is the bitmap (i.e., the static background) of my live wallpaper, is not getting scaled properly. In some screens the width is proper but in some the bitmap (i.e., the background) appears only half way.
I have tried the density, windowmanager and the px to dp conversion.
None of them seem to work for me. Or may be my approach towards it is not in a proper manner.
I need help for the same.
Code Snippet
this._backgroundImage = BitmapFactory.decodeResource(context.getResources(),R.drawable.scene, options);
Bitmap background_image = Bitmap.createScaledBitmap(_backgroundImage, width, height, false);
canvas.drawBitmap(this.background_image, 0, 0, null);
I was using following methods sometimes back.. I dont know if these will be helpful for you or not .. please check if this works for you
float scale = getResources().getDisplayMetrics().density;
Display display = ((WindowManager) main.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
int WIDTH = display.getWidth();
int HEIGHT = display.getHeight();
public static Drawable resizeDrawable(Drawable d, float scale) {
Drawable drawable = null;
if (d != null) {
try {
Bitmap bitmap1 = ((BitmapDrawable) d).getBitmap();
int width = 0;
int height = 0;
if (Math.min(WIDTH, HEIGHT) > 600) {
width = (int) (100 * scale + 0.5f);
height = (int) (100 * scale + 0.5f);
} else if (Math.min(WIDTH, HEIGHT) > 240) {
width = (int) (70 * scale + 0.5f);
height = (int) (70 * scale + 0.5f);
} else {
width = (int) (44 * scale + 0.5f);
height = (int) (44 * scale + 0.5f);
}
drawable = new BitmapDrawable(resizeBitmap(bitmap1,
width, height));
} catch (Exception e) {
e.printStackTrace();
}
}
return drawable;
}
please note that value used in if-else conditions in resizeDrawable method are just arbitrary values taken by trial n error (which suits my app).. you can try other values according to screens you are targeting
public static Bitmap resizeBitmap(final Bitmap bitmap, final int width,
final int height) {
final int oldWidth = bitmap.getWidth();
final int oldHeight = bitmap.getHeight();
final int newWidth = width;
final int newHeight = height;
// calculate the scale
final float scaleWidth = ((float) newWidth) / oldWidth;
final float scaleHeight = ((float) newHeight) / oldHeight;
// create a matrix for the manipulation
final Matrix matrix = new Matrix();
// resize the Bitmap
matrix.postScale(scaleWidth, scaleHeight);
// if you want to rotate the Bitmap
// recreate the new Bitmap
final Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
oldWidth, oldHeight, matrix, true);
return resizedBitmap;
}
Try this:
Bitmap resizedBitmap=Bitmap.createScaledBitmap(bb, newWidth, newHeight, false);
Tell me if it works.
You can use this to get the screen size and scale it accordingly.
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth(); // deprecated
int height = display.getHeight();

Categories

Resources