Hello I have two images and i am merging that images using canvas
here is the below code
Intent intent = getIntent();
//bm is the image get from camera
bm = BitmapFactory.decodeFile(intent.getStringExtra("getdata"));
//this is simple white text image
bm1 = BitmapFactory.decodeResource(getResources(), R.drawable.txt_made_hawk_nelson);
imgSeletedPhoto = (ImageView) findViewById(R.id.imgSelectedPhoto);
int width = bm.getWidth();
int height = bm.getHeight();
int maxWidth = (width > bm1.getWidth() ? width : bm1.getWidth());
int maxHeight = (height > bm1.getHeight() ? height : bm1.getHeight());
// calculate the scale - in this case = 0.4f
float scaleWidth = ((float) maxWidth) / width;
float scaleHeight = ((float) maxHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
bmOverlay = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
Canvas canvas = new Canvas(bmOverlay);
//canvas.drawBitmap(bm, 0, 0, null);
canvas.drawBitmap(bm1, 0, 50, null);
imgSeletedPhoto.setImageBitmap(bmOverlay);
} catch (Exception e) {
e.printStackTrace();
}
i want to scale image and image should look like below
but instead of by doing above code it is looking like
XML code of this file is
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:weightSum="10" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="7" > // this is covering 70% of screen
<ImageView
android:id="#+id/imgSelectedPhoto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_centerInParent="true" />
</RelativeLayout>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="3"
android:background="#baca9d"
android:gravity="center"
android:orientation="vertical"
android:paddingLeft="10dp"
android:paddingRight="10dp" >
can any body help me how to stretch image and make it full from bottom and top side also and put text in center
int targetWidth = 70% of screen width;
int targetHeight = 70% of screen height;
int saclex = (int)((float)targetWidth / (float)bmp1.getWidth());
int sacley = (int)((float)targetHeight / (float)bmp1.getHeight());
apply scale values to bmp1 and create scaled bitmap
saclex = (int)((float)targetWidth / (float)bmp.getWidth());
sacley = (int)((float)targetHeight / (float)bmp.getHeight());
apply scale values bmp and create scaled bitmap. Hope this will help. or else you can use this method to create it.
Bitmap bitmap = Bitmap.createScaledBitmap(mTargetImage, bWidth,
bHeight, false);
Related
I'm trying to get Width and Height of Bitmap and set them as Layout Parameter of CustomView
JAVA :
private void setBg() {
drawView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
drawView.getLayoutParams().height = orginalBitmap.getHeight();
drawView.getLayoutParams().width = orginalBitmap.getWidth();
relativeLayout.addView(drawView);
}
XML :
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/bottom"
android:layout_below="#+id/clear">
<ImageView
android:id="#+id/fullimg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_gravity="center_horizontal|center_vertical"
android:adjustViewBounds="true" />
<RelativeLayout
android:id="#+id/relative"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_gravity="center_horizontal|center_vertical"
android:gravity="center_horizontal|center_vertical"
android:orientation="vertical" />
</RelativeLayout>
But the code above doesn't work, when I run the app I get this
the emojis, for example, should stop right in the corner of image view but instead of that it still appears in the two empty spaces.
Use this method instead , you have to set the layout params this way and then add them to your drawView
private void setBg(){
android.view.ViewGroup.LayoutParams params = drawView.getLayoutParams();
params.width = orginalBitmap.getWidth();
params.height = orginalBitmap.getHeight();
drawView.setLayoutParams(params);
relativeLayout.addView(drawView);
}
Here's what I've done, and it works well
mDensity = getResources().getDisplayMetrics().density;
actionBarHeight = (int) (110 * mDensity);
bottombarHeight = (int) (60 * mDensity);
viewWidth = getResources().getDisplayMetrics().widthPixels;
viewHeight = getResources().getDisplayMetrics().heightPixels - actionBarHeight - bottombarHeight;
viewRatio = (double) viewHeight / (double) viewWidth;
bmRatio = (double) orginalBitmap.getHeight() / (double) orginalBitmap.getWidth();
if (bmRatio < viewRatio) {
bmWidth = viewWidth;
bmHeight = (int) (((double) viewWidth) * ((double) (orginalBitmap.getHeight()) / (double) (orginalBitmap.getWidth())));
} else {
bmHeight = viewHeight;
bmWidth = (int) (((double) viewHeight) * ((double) (orginalBitmap.getWidth()) / (double) (orginalBitmap.getHeight())));
}
final RelativeLayout.LayoutParams lparams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
lparams.addRule(RelativeLayout.CENTER_IN_PARENT);
lparams.height = bmHeight;
lparams.width = bmWidth;
drawView.setLayoutParams(lparams);
I implemented ACTION_MOVE for ImageView which is bigger then its parent (FrameLayout). Now I'm trying to add some code to stop movement (both drag and pinch zooming) when at least one of Image edges is inside its parent (so it won’t show background of a parent).
I used the code like in this question.
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) { //movement of first finger
matrix.set(savedMatrix);
float newX = event.getX() - start.x;
float newY = event.getY() - start.y;
if (view.getLeft() >= -392){
matrix.postTranslate(newX, newY);
}
}
else if (mode == ZOOM) { //pinch zooming
float[] f = new float[9];
float newDist = spacing(event);
if (newDist > 5f) {
matrix.set(savedMatrix);
scale = newDist / oldDist;
matrix.postScale(scale, scale, mid.x, mid.y);
}
matrix.getValues(f);
float scaleX = f[Matrix.MSCALE_X];
float scaleY = f[Matrix.MSCALE_Y];
if(scaleX <= MIN_ZOOM) {
matrix.postScale((MIN_ZOOM)/scaleX,
(MIN_ZOOM)/scaleY, mid.x, mid.y);
}
else if(scaleX >= MAX_ZOOM) {
matrix.postScale((MAX_ZOOM)/scaleX,
(MAX_ZOOM)/scaleY, mid.x, mid.y);
}
}
break;
I tried many things, and I know similar questions had been asked already but non of them fit my need so far.
My best guess was to add code below but it looks like mImageView.getLeft(), mImageView.getRight() etc returns parents edges not the images.
In onCreate():
DisplayMetrics displayMetrics =
getApplicationContext().getResources().getDisplayMetrics();
float screenWidth = displayMetrics.widthPixels;
float screenHeight = displayMetrics.heightPixels;
and in case MotionEvent.ACTION_MOVE
if (mImageView.getLeft() > 0 ||
mImageView.getRight() < screenWidth) {
matrix.postTranslate(0, newY);
break;
}
else if (mImageView.getTop() > 0 ||
mImageView.getBottom() < screenHeight) {
matrix.postTranslate(newX, 0);
break;
}
else {
matrix.postTranslate(newX, newY);
}
And this is my layout:
<RelativeLayout
android:id="#+id/imageViewContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/mag_background">
<TextView/>
<ImageView/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/imageViewHeadingLabel">
<ImageView
android:id="#+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/image"
android:scaleType="matrix"
android:layout_gravity="center_vertical|center_horizontal"
android:contentDescription="image to zoom"/>
</FrameLayout>
</RelativeLayout>
Thanks in advance for your help!
I found solution hire.
I reverse the checks so instead of not letting image to move outside layout I not letting image bounds to be move inside layout like this:
if (mode == DRAG) { //movement of first finger
matrix.set(savedMatrix);
matrix.getValues(matrixValues);
matrixX = matrixValues[2];
matrixY = matrixValues[5];
width = matrixValues[0] * (view.getDrawable().getIntrinsicWidth());
height = matrixValues[4] * (view.getDrawable().getIntrinsicHeight());
dx = event.getX() - start.x;
dy = event.getY() - start.y;
//if image will go inside left bound
if (matrixX + dx > 0){
dx = -matrixX;
}
//if image will go inside right bound
if(matrixX + dx + width < view.getWidth()){
dx = view.getWidth() - matrixX - width;
}
//if image will go inside top bound
if (matrixY + dy > 0){
dy = -matrixY;
}
//if image will go inside bottom bound
if(matrixY + dy + height < view.getHeight()){
dy = view.getHeight() - matrixY - height;
}
matrix.postTranslate(dx, dy);
}
However if you move zoomed image to the corner and then zoom out, it will show parent background until next touch event so problem is not fully solved.
This question already has answers here:
onMeasure custom view explanation
(3 answers)
Closed 7 years ago.
I have a layout with several views and one of these views have to be scaled based on screen size. As of now I have it set to 250dp as it looks good on a 5.1 inch device, but when used on smaller devices it isnt as good any more. I can't use wrap content as it will make the looks of it very bad and the size of buttons too small, so it has to be 1/3rd of the width of the screen. Is it possible to do that in the layout code, or does it have to be doen in java code?
Is it possible to do that in the layout code
Yes it is. It is pretty simple by using android:layout_weight and android:weightSum attributes of LinearLayout :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="3"
android:orientation="horizontal">
<View
android:id="#+id/thirdView"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1" />
</LinearLayout>
You need to override onMeasure(...) then do your view resizing login inside this function. Here is the perfect explanation and solution.
Some reference code from this link goes below...
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int desiredWidth = 100;
int desiredHeight = 100;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
//Measure Width
if (widthMode == MeasureSpec.EXACTLY) {
//Must be this size
width = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
width = Math.min(desiredWidth, widthSize);
} else {
//Be whatever you want
width = desiredWidth;
}
//Measure Height
if (heightMode == MeasureSpec.EXACTLY) {
//Must be this size
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
height = Math.min(desiredHeight, heightSize);
} else {
//Be whatever you want
height = desiredHeight;
}
//MUST CALL THIS
setMeasuredDimension(width, height);
}
You could have a look at the PercentRelativeLayout from the Percent Support Library. This is a RelativeLayout in which you can specify it's Views sizes in percentages, e.g. set its width to 33%.
<android.support.percent.PercentRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
app:layout_widthPercent="33%"
app:layout_heightPercent="33%"
app:layout_marginTopPercent="25%"
app:layout_marginLeftPercent="25%" />
</android.support.percent.PercentRelativeLayout>
I'm trying to crop a sprite from a spritesheet, however the cropped image is not the part of the image I specified.
The spritesheet contains sprites with a size of 32 x 32 px and therefore the first sprite should be at pixels 0 to 32 (horizontally) and 0 to 32 (vertically), supposed the most upper left pixel is [0, 0].
Bitmap spritesheet = BitmapFactory.decodeResource(getResources(), R.drawable.spritesheet_32x32);
Bitmap sprite = Bitmap.createBitmap(spritesheet, 0, 0, 32, 32);
The ImageView is just a plain ImageView without a src, width or height set.
ImageView view = (ImageView)findViewById(R.id.player1);
view.setImageBitmap(sprite);
But the displayed image is just a much smaller part of the first sprite.
What do I oversee? Is view.setImageBitmap(sprite); the right method for this? Does the ImageView need a fix width and height before setting the bitmap?
EDIT: Maybe I should get clearer about my layout. There are two ImageViews arranged on a LinearLayout. Here's the XML:
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:baselineAligned="false">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleX="-1"
android:id="#+id/player1"
android:layout_weight="1"
android:layout_gravity="center_vertical" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/player2"
android:layout_weight="1"
android:layout_gravity="center_vertical" />
</LinearLayout>
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
public class ImageResizer {
public static Bitmap decodeSampledBitmapFromFile(String filename,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options
options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filename, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(filename, options);
}
public static int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// BEGIN_INCLUDE (calculate_sample_size)
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
// This offers some additional logic in case the image has a strange
// aspect ratio. For example, a panorama may have a much larger
// width than height. In these cases the total pixels might still
// end up being too large to fit comfortably in memory, so we should
// be more aggressive with sample down the image (=larger inSampleSize).
long totalPixels = width * height / inSampleSize;
// Anything more than 2x the requested pixels we'll sample down further
final long totalReqPixelsCap = reqWidth * reqHeight * 2;
while (totalPixels > totalReqPixelsCap) {
inSampleSize *= 2;
totalPixels /= 2;
}
}
return inSampleSize;
// END_INCLUDE (calculate_sample_size)
}
}
Call the method
Bitmap bmp = ImageResizer.decodeSampledBitmapFromFile(new File(filePath).getAbsolutePath(), 512, 342);
I haven't tried but the follows might work pass the method parameter like
imageView.getWidth() , imageView.getHeight()
I want to display round image. I have a square image and I round it using below code.
public static void roundImageForImageView(ImageView imageView) {
try {
Bitmap bitmap = ((BitmapDrawable)imageView.getDrawable()).getBitmap();
int diameter = Math.min(bitmap.getWidth(), bitmap.getHeight());
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Paint paint = new Paint();
int rectX = (bitmap.getWidth() - diameter) / 2;
int rectY = (bitmap.getHeight() - diameter) / 2;
final Rect rect = new Rect(rectX, rectY, rectX + diameter, rectY
+ diameter);
final RectF rectF = new RectF(rect);
final float roundPx = diameter;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
imageView.setImageBitmap(output);
bitmap = null;
output = null;
} catch(OutOfMemoryError e) {
e.printStackTrace();
}
}
ImageView layout :
<ImageView
android:id="#+id/image_id"
android:background = "#drawable/placeholder"
android:scaleType="centerCrop"
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_marginTop="10dp"
android:contentDescription="#string/profile_picture_description" />
But displayed image has small tiny cuts on middle of all edges. I tried playing with image size.
Any idea of why these cuts are there or how to solve it?
**Update : ** Using android:scaleType="center" for ImageView gives below result.
You're using
android:scaleType="centerCrop"
This is cropping the image and making the lines at the top bottom left and right.
try using
android:scaleType="centerInside"
Also, take a look here at ImageView.ScaleTypes for some good info on the different scale types:
It was a mistake in layout file.
android:background = "#drawable/placeholder"
Above line was causing the blurry edged circle to appear. #drawable/placeholder is an image and that itself is blurry.
I had set it as background, instead of src.
android:src = "#drawable/placeholder"