FIT_XY not working when scaling and rotating image using Matrix - android

I'm trying to resize and rotate an image and I want the full image to be shown, not a cropped version of the image. I have a resize button next to the image that when it is pressed performs the resize/rotation. I tried setting the scale type of the ImageView to FIT_XY and then tried FIT_CENTER but the image is always cropped, not scaled properly.
//MainActivity code
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RelativeLayout container = (RelativeLayout) findViewById(R.id.container);
RelativeLayout.LayoutParams layoutParamsImage = new RelativeLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
LinearLayout l1 = new LinearLayout(getApplicationContext());
LinearLayout l2 = new LinearLayout(getApplicationContext());
l2.setOrientation(LinearLayout.VERTICAL);
ImageView imageView = new ImageView(getApplicationContext());
Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.butterfly);
imageView.setImageBitmap(bitmap);
ImageView resizeButton = new ImageView(getApplicationContext());
resizeButton.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent motionEvent) {
LinearLayout stickerContainer = (LinearLayout) v.getParent().getParent();
ImageView stickerImage = (ImageView) stickerContainer.getChildAt(0);
double r=Math.atan2(motionEvent.getX()-stickerImage.getWidth(), stickerImage.getHeight()-motionEvent.getY());
int rotation=(int)Math.toDegrees(r);
int y = (int) motionEvent.getY();
int x1=0;
int y1=0;
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
x1 = (int) motionEvent.getX();
y1= (int) motionEvent.getY();
}
else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
int x2 = (int) motionEvent.getX();
int y2= (int) motionEvent.getY();
int height = Math.abs(y2-y1) *2;
int width = Math.abs(x2-x1) *2;
width = Math.max(width, 100);
height = Math.max(height, 100);
width = Math.min(width, 500);
height = Math.min(height, 500);
width=height;
float newRot=new Float(rotation);
Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.butterfly);
Matrix matrix=new Matrix();
matrix.postRotate(newRot,width,height);
matrix.postScale(2, 2);
stickerImage.requestLayout();
stickerImage.getLayoutParams().height = height;
stickerImage.getLayoutParams().width = width;
//Bitmap reDrawnBitmap=Bitmap.createBitmap(bitmap,0,0,width, height,matrix,true);
Bitmap reDrawnBitmap=Bitmap.createBitmap(bitmap,0,0,stickerImage.getWidth(), stickerImage.getHeight(),matrix,true);
//Bitmap reDrawnBitmap=Bitmap.createScaledBitmap(bitmap, dstWidth, dstHeight, filter)
stickerImage.setScaleType(ImageView.ScaleType.FIT_XY);
stickerImage.setAdjustViewBounds(true);
stickerImage.setImageBitmap(reDrawnBitmap);
stickerImage.setScaleType(ImageView.ScaleType.FIT_XY);
}
return true;
}
});
resizeButton.setBackgroundResource(R.drawable.resize);
layoutParamsImage.height = 100;
layoutParamsImage.width = 100;
imageView.setLayoutParams(layoutParamsImage);
l1.addView(imageView);
l2.addView(resizeButton);
l1.addView(l2);
//imageView.setMaxHeight(100);
//imageView.setMaxWidth(100);
container.addView(l1);
}
}
//layout code activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.doodle4.MainActivity"
tools:ignore="MergeRootFrame"></RelativeLayout>

I figured out the scaling part. I need to create a scaled Bitmap after creating the bitmap that is created using matrix.
In the
else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
code block use this code instead of what's there at the bottom:
Bitmap reDrawnBitmap=Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(), bitmap.getHeight(),matrix,true);
Bitmap reDrawnBitmapRescaled=Bitmap.createScaledBitmap(reDrawnBitmap, width, height, false);
stickerImage.setImageBitmap(reDrawnBitmapRescaled);

Related

Moving only bitmap inside an ImageView

I have an ImageView with a black background set in xml, and in code I'm placing bitmap with imageView.setImageBitmap(bitmap);
You can select between ScaleType.CENTER_CROP and ScaleType.CENTER_INSIDE.
If ScaleType.CENTER_INSIDE is selected, bitmap is smaller than the ImageView, and the black background is visible.
I would like to move only bitmap across the screen. I tried with this code, but it moves whole ImageView, not only bitmap inside ImageView.
imageView.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
int eid = event.getAction();
switch (eid) {
case MotionEvent.ACTION_MOVE:
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) imageView.getLayoutParams();
int x = (int) event.getRawX();
int y = (int) event.getRawY();
layoutParams.leftMargin = x - 50;
layoutParams.topMargin = y - 100;
imageView.setLayoutParams(layoutParams);
break;
default:
break;
}
return true;
}
});
Is there a way to only move bitmap that's inside ImageView?
Also I would like to increase and decrease width and height of a bitmap and maintain the bitmap's aspect ratio.
I tried with this, but it's not working:
buttonIncrease.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) imageView.getLayoutParams();
layoutParams.width = (int) ((layoutParams.width + 10) * scale + 0.5f);
layoutParams.height = (int) ((layoutParams.height + 10) * scale + 0.5f);
}
});

Pinch to zoom IN or OUT imageview added dynamically to Layout

I working on an application where in the ImageView is created dynamically and added to the layout, after the user selects image from the gallery of the device.
With the code what I have written, am able to move and rotate the ImageView. But, I also want to implement Pinch zoom in/out for the ImageView.
The bug which exists in the code is when after the ImageView is added to the layout, the ImageView when taken to the extreme right shrinks so that what I want to do, but that should happen on the pinch.
EDIT: After debugging my code I found that i want to increase the size of the ImageView by increasing the width and height.
When i changed the following line :
final RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
To:
final RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
240,
200);
I got what i wanted. So can I do this inside the class DragImageView on pinch.
Here's the code for the custom Imageview.
public class DragImageView extends ImageView {
private float mLastTouchX;
private float mLastTouchY;
private float mDeltaX;
private float mDeltaY;
private Bitmap bmpImg;
Context mContext;
public DragImageView(Context context, Bitmap bmpImg) {
super(context);
this.bmpImg = bmpImg;
this.mContext = context;
init();
}
public DragImageView(final Context context, final AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
// TODO Auto-generated method stub
Bitmap resized = Bitmap.createScaledBitmap(bmpImg, 180, 200, true);
Bitmap conv_bm = getRoundedShape(resized); //function to get the imageview as rounded shape
setImageBitmap(conv_bm);
setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(final View v, MotionEvent event) {
PopupMenu popup = new PopupMenu(mContext, v);
// Inflating the Popup using xml file
popup.getMenuInflater().inflate(R.menu.popup_menu,
popup.getMenu());
popup.setOnMenuItemClickListener(new OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
// TODO Auto-generated method stub
int itemId = item.getItemId();
if (itemId == R.id.delete_DragImgView) {
ViewGroup parentView = (ViewGroup) v.getParent();
parentView.removeView(v);
} else if (itemId == R.id.rotate_DraagImgView) {
final RotateAnimation rotateAnim = new RotateAnimation(
0.0f, 90, RotateAnimation.RELATIVE_TO_SELF,
0.5f, RotateAnimation.RELATIVE_TO_SELF,
0.5f);
rotateAnim.setDuration(0);
rotateAnim.setFillAfter(true);
v.startAnimation(rotateAnim);
}
return false;
}
});
final int action = event.getAction();
mLastTouchX = event.getRawX();
mLastTouchY = event.getRawY();
switch (action) {
case MotionEvent.ACTION_DOWN: {
RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) getLayoutParams();
mDeltaX = mLastTouchX - lParams.leftMargin;
mDeltaY = mLastTouchY - lParams.topMargin;
popup.show();
break;
}
case MotionEvent.ACTION_MOVE: {
mLastTouchX = event.getRawX();
mLastTouchY = event.getRawY();
final RelativeLayout.LayoutParams params = (LayoutParams) getLayoutParams();
params.leftMargin = (int) (mLastTouchX - mDeltaX);
params.topMargin = (int) (mLastTouchY - mDeltaY);
setLayoutParams(params);
break;
}
}
invalidate();
return true;
}
});
}
The imageview is added as follows from the activity.
final DragImageView dynamicImgView = new DragImageView(
getApplicationContext(), yourSelectedImage);
final RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
dynamicImgView.setLayoutParams(params);
relativeLayout.addView(dynamicImgView);
I know the pinch to zoom is possible but after trying lots of codes and Help from stackover flow, thought of finally putting it on so.
Please help me. Thanks in advance.
Solved my problem.. I simply increased the height & width of the imageview. Code
} else if (itemId == R.id.zoom_in) {
if (height > 100) {
height = height - ZoomCounter;
width = width - ZoomCounter;
final RelativeLayout.LayoutParams params = (LayoutParams) getLayoutParams();
getLayoutParams().height = height;
getLayoutParams().width = width;
setLayoutParams(params);
invalidate();
}
} else if (itemId == R.id.zoom_out) {
if (height < 600) {
height = height + ZoomCounter;
width = width + ZoomCounter;
final RelativeLayout.LayoutParams params = (LayoutParams) getLayoutParams();
getLayoutParams().height = height;
getLayoutParams().width = width;
setLayoutParams(params);
invalidate();
}
}

Get the touch position inside the imageview in android

I have a imageview in my activity and I am able to get the position where the user touch the imageview, through onTouchListener. I placed another image where the user touch over that image. I need to store the touch position(x,y), and use it in another activity, to show the tags. I stored the touch position in the first activity. In the first activity, my imageview at the top of the screen. In the second activity its at the bottom of the screen. If I use the position stored from the first acitvity, it place the tag image at the top, not on the imageview, where I previously clicked in the first activity. Is there anyway to get the position inside the imageview.
FirstActivity:
cp.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
x = (int) event.getX();
y = (int) event.getY();
Log.v("touched x val of cap img >>", x + "");
Log.v("touched y val of cap img >>", y + "");
tag.setVisibility(View.VISIBLE);
int[] viewCoords = new int[2];
cp.getLocationOnScreen(viewCoords);
int imageX = x - viewCoords[0]; // viewCoods[0] is the X coordinate
int imageY = y - viewCoords[1]; // viewCoods[1] is the y coordinate
Log.v("Real x >>>",imageX+"");
Log.v("Real y >>>",imageY+"");
RelativeLayout rl = (RelativeLayout) findViewById(R.id.lay_lin);
ImageView iv = new ImageView(Capture_Image.this);
Bitmap bm = BitmapFactory.decodeResource(getResources(),
R.drawable.tag_icon_32);
iv.setImageBitmap(bm);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.leftMargin = x;
params.topMargin = y;
rl.addView(iv, params);
Intent intent= new Intent(Capture_Image.this,Tag_Image.class);
Bundle b=new Bundle();
b.putInt("xval", imageX);
b.putInt("yval", imageY);
intent.putExtras(b);
startActivity(intent);
return false;
}
});
In TagImage.java I used the following:
im = (ImageView) findViewById(R.id.img_cam22);
b=getIntent().getExtras();
xx=b.getInt("xval");
yy=b.getInt("yval");
im.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
int[] viewCoords = new int[2];
im.getLocationOnScreen(viewCoords);
int imageX = xx + viewCoords[0]; // viewCoods[0] is the X coordinate
int imageY = yy+ viewCoords[1]; // viewCoods[1] is the y coordinate
Log.v("Real x >>>",imageX+"");
Log.v("Real y >>>",imageY+"");
RelativeLayout rl = (RelativeLayout) findViewById(R.id.lay_lin);
ImageView iv = new ImageView(Tag_Image.this);
Bitmap bm = BitmapFactory.decodeResource(getResources(),
R.drawable.tag_icon_32);
iv.setImageBitmap(bm);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
30, 40);
params.leftMargin =imageX ;
params.topMargin = imageY;
rl.addView(iv, params);
return true;
}
});
You can get the top left corner of your view as follows:
int[] viewCoords = new int[2];
imageView.getLocationOnScreen(viewCoords);
From this and the touch coordinates you can calculate the point inside the ImageView:
int touchX = (int) event.getX();
int touchY = (int) event.getY();
int imageX = touchX - viewCoords[0]; // viewCoords[0] is the X coordinate
int imageY = touchY - viewCoords[1]; // viewCoords[1] is the y coordinate
Add these lines to ImageView
android:scaleType="fitXY"
and
android:adjustViewBounds="true"
to your image view it is because image are not having their original dimensions in IV

How to rotate the image without changing its size?

I am developing an android app where I have to rotate a circular image around another circular image, but when I am running this the size of my circular image gets automatically changing continuously. So please help me how to solve this. Here is my code
public class JobSearch extends Activity implements OnTouchListener {
private ImageView dialer;
private float y=0;
public boolean onTouch(View v, MotionEvent event) {
double r=Math.atan2(event.getX()-dialer.getWidth()/2, dialer.getHeight()/2-event.getY());
int rotation=(int)Math.toDegrees(r);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
//x=event.getX();
y=event.getY();
updateRotation(rotation);
break;
case MotionEvent.ACTION_UP:
break;
}//switch
return true;
}//onTouch
private void updateRotation(double rot){
float newRot=new Float(rot);
Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.round_button_big);
Matrix matrix=new Matrix();
matrix.postRotate(newRot);//,bitmap.getWidth()/2,bitmap.getHeight()/2);
Bitmap reDrawnBitmap=Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true);
dialer.setImageBitmap(reDrawnBitmap);
if(newRot>=-5 && newRot<=5)
Toast.makeText(this,"12 O\'Clock",Toast.LENGTH_SHORT).show();
if(newRot>=85 && newRot<=95)
Toast.makeText(this,"3 O\'Clock",Toast.LENGTH_SHORT).show();
if(newRot>=175 || newRot<=-175)
Toast.makeText(this,"6 O\'Clock",Toast.LENGTH_SHORT).show();
if(newRot>=-95 && newRot<=-85)
Toast.makeText(this,"9 O\'Clock",Toast.LENGTH_SHORT).show();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
dialer = (ImageView) findViewById(R.id.big_button);
dialer.setOnTouchListener(this);
}//onCreate
}
This this one; worked for me perfectly.
private Bitmap rotateBitmap(Bitmap bitmap, int rotationAngleDegree){
int w = bitmap.getWidth();
int h = bitmap.getHeight();
int newW=w, newH=h;
if (rotationAngleDegree==90 || rotationAngleDegree==270){
newW = h;
newH = w;
}
Bitmap rotatedBitmap = Bitmap.createBitmap(newW,newH, bitmap.getConfig());
Canvas canvas = new Canvas(rotatedBitmap);
Rect rect = new Rect(0,0,newW, newH);
Matrix matrix = new Matrix();
float px = rect.exactCenterX();
float py = rect.exactCenterY();
matrix.postTranslate(-bitmap.getWidth()/2, -bitmap.getHeight()/2);
matrix.postRotate(rotationAngleDegree);
matrix.postTranslate(px, py);
canvas.drawBitmap(bitmap, matrix, new Paint( Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG | Paint.FILTER_BITMAP_FLAG ));
matrix.reset();
return rotatedBitmap;
}
Try this code for Rotating Image -
public class bitmaptest extends Activity {
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
LinearLayout linLayout = new LinearLayout(this);
// load the origial BitMap (500 x 500 px)
Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(),
R.drawable.android);
int width = bitmapOrg.width();
int height = bitmapOrg.height();
int newWidth = 200;
int newHeight = 200;
// calculate the scale - in this case = 0.4f
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// createa matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight);
// rotate the Bitmap
matrix.postRotate(45);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0,
width, height, matrix, true);
// make a Drawable from Bitmap to allow to set the BitMap
// to the ImageView, ImageButton or what ever
BitmapDrawable bmd = new BitmapDrawable(resizedBitmap);
ImageView imageView = new ImageView(this);
// set the Drawable on the ImageView
imageView.setImageDrawable(bmd);
// center the Image
imageView.setScaleType(ScaleType.CENTER);
// add ImageView to the Layout
linLayout.addView(imageView,
new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT
)
);
// set LinearLayout as ContentView
setContentView(linLayout);
}
}
And, also see this Tutorial
This is my code to rotate image around itself and slowly reduce the speed
rotateAnimation1 = new RotateAnimation(0, 360,
Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation1.setInterpolator(new LinearInterpolator());
rotateAnimation1.setDuration(duration);
rotateAnimation1.setRepeatCount(0);
imgBottle.startAnimation(rotateAnimation1);
flagSpinAvailable = false;
rotateAnimation1.setAnimationListener(new AnimationListener() {
public void onAnimationStart(Animation anim) {
};
public void onAnimationRepeat(Animation anim) {
};
public void onAnimationEnd(Animation anim) {
duration = duration + 70;
startMoving();
};
});
this is the code of rotate the image
Bitmap bMap = BitmapFactory.decodeResource(getResources(),R.drawable.test);
Matrix mat = new Matrix();
mat.postRotate(90);
Bitmap bMapRotate = Bitmap.createBitmap(bMap, 0, 0,
bMap.getWidth(), bMap.getHeight(), mat, true);
BitmapDrawable bmd = new BitmapDrawable(bMapRotate);
image.setImageBitmap(bMapRotate);
image.setImageDrawable(bmd);

Resize Bitmap image?

I want to change the image size when changing screen orientation. I tried to use the following code, but it does not work.
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
myImage = Bitmap.createBitmap(BitmapFactory
.decodeResource(this.getResources(), R.drawable.pic));
Display d = ((WindowManager)getSystemService(WINDOW_SERVICE))
.getDefaultDisplay();
int ScreenHeight = d.getHeight();
int ScreenWidth = d.getWidth();
Bitmap ScaledImage = Bitmap.createScaledBitmap(myImage , ScreenWidth, ScreenHeight,
true);
imageview = (ImageView)findViewById(R.id.imageView2);
imageview.setImageBitmap(ScaledImage);
}
}
Below is the code to rotate or re size your image in android
public class bitmaptest extends Activity {
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
LinearLayout linLayout = new LinearLayout(this);
// load the origial BitMap (500 x 500 px)
Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(),
R.drawable.android);
int width = bitmapOrg.width();
int height = bitmapOrg.height();
int newWidth = 200;
int newHeight = 200;
// calculate the scale - in this case = 0.4f
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// createa matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight);
// rotate the Bitmap
matrix.postRotate(45);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0,
width, height, matrix, true);
// make a Drawable from Bitmap to allow to set the BitMap
// to the ImageView, ImageButton or what ever
BitmapDrawable bmd = new BitmapDrawable(resizedBitmap);
ImageView imageView = new ImageView(this);
// set the Drawable on the ImageView
imageView.setImageDrawable(bmd);
// center the Image
imageView.setScaleType(ScaleType.CENTER);
// add ImageView to the Layout
linLayout.addView(imageView,
new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT
)
);
// set LinearLayout as ContentView
setContentView(linLayout);
}
}

Categories

Resources