I need to crop image like this
I need to draw partial image from center
I know there is draw() method of batch with a lot of params, but there is no good documentation about all this params, so i can't figure out how to use it.
Here is what i implemented:
public class TexturePart {
Texture tex;
Vector2 position;
// Target Dimension of image
int targetWidth;
int targetHeight;
// Src Dimensions of Image
int srcWidth;
int srcHeight;
int srcX;
int srcY;
// Ratio of dimension of target and source
float srcTargetRatioX;
float srcTargetRatioY;
// ImagePart variables with values between 0-100 to draw part of image
int startPercentX;
int endPercentX;
int startPercentY;
int endPercentY;
int clipWidth;
int clipHeight;
int clipSrcWidth;
int clipSrcHeight;
public TexturePart(TextureRegion reg, float x, float y) {
tex = reg.getTexture();
position = new Vector2(x, y);
srcX = reg.getRegionX();
srcY = reg.getRegionY();
srcWidth = reg.getRegionWidth();
srcHeight = reg.getRegionHeight();
clipSrcWidth = srcWidth;
clipSrcHeight = srcHeight;
startPercentX = 28;
startPercentY = 28;
endPercentX = 72;
endPercentY = 72;
SetTargetDimension(srcWidth, srcHeight);
}
public void setSrcWidthHeight(int width, int height){
this.srcWidth=width;
this.srcHeight=height;
}
public void setSrcHeight(int height){
this.srcHeight=height;
}
public void SetTargetDimension(int targetWidth, int targetHeight) {
this.targetWidth = targetWidth;
this.targetHeight = targetHeight;
clipWidth = targetWidth;
clipHeight = targetHeight;
srcTargetRatioX = (float) targetWidth / (float) srcWidth;
srcTargetRatioY = (float) targetHeight / (float) srcHeight;
}
public void SetStart(int x, int y) {
startPercentX = x;
startPercentY = y;
}
public void SetEnd(int x, int y) {
endPercentX = x;
endPercentY = y;
}
public void Draw(SpriteBatch sp) {
clipSrcWidth = (int) (Math.abs(startPercentX - endPercentX) / 100f * srcWidth);
clipSrcHeight = (int) (Math.abs(startPercentX - endPercentY) / 100f * srcHeight);
int startX = clipWidth/2 + (int) ((float) startPercentX / 100f * (float) srcX);
int startY = clipHeight/2 + (int) ((float) startPercentY / 100f * (float) srcY);
clipWidth = (int) (srcTargetRatioX * clipSrcWidth);
clipHeight = (int) (srcTargetRatioY * clipSrcHeight);
sp.begin();
float scaleX=targetWidth/(srcWidth+0.f);
float scaleY=targetHeight/(srcHeight+0.f);
sp.draw(tex, 0, 0, srcWidth, srcHeight, srcWidth, srcHeight, 1, 1, 0, startX, startY, clipSrcWidth, clipSrcHeight, false, false);
//sp.draw(tex, 0,0,clipWidth, clipHeight, clipWidth, clipHeight, clipSrcWidth, clipSrcHeight, false, false);
sp.end();
}
But its not working as expected
To crop the texture you just need to use TextureRegion
TextureRegion(Texture texture, int x, int y, int width, int height)
in your case it should look like:
Texture texture; //this is your original image
...
TextureRegion region = new TextureRegion(texture, texture.getWidth()*0.28f, 0, texture.getWidth()*0.44f, texture.getHeight() );
...
//now you can just draw your texture region
sp.draw(region); //you can also use other versions of draw to set region position on screen and so on
Why i set x as texture.getWidth()*0.28f? Because if want it centered it should have left margin = 50% of original texture width - texture region width.
(1 - 0.44) / 2 = 0.28
Related
I am trying to get the color from an image where the user touches the image. I am able to get the x,y coordinates and can calculate the pixels from it using Matrix, however my issue is it is not giving me the right color.
private void getColor(MotionEvent event, Button capture) {
float HeightRatio = (float) image.getHeight() / (float) imageView.getHeight();
float WidthRatio = (float) image.getWidth() / (float) imageView.getWidth();
Matrix inverse = new Matrix();
imageView.getImageMatrix().invert(inverse);
float[] touchPoint = new float[]{event.getX(), event.getY()};
i2.setX(event.getX());
i2.setY(event.getY());
inverse.mapPoints(touchPoint);
int x = Integer.valueOf((int) touchPoint[0]);
int y = Integer.valueOf((int) touchPoint[1]);
x = (int) (x * WidthRatio);
y = (int) (y * HeightRatio);
if (x < 0) {
x = 0;
} else if (x > image.getWidth() - 1) {
x = image.getWidth() - 1;
}
if (y < 0) {
y = 0;
} else if (y > image.getHeight() - 1) {
y = image.getHeight() - 1;
}
i2.setBackgroundColor(image.getPixel(x, y));
i2.setVisibility(View.VISIBLE);
capture.setBackgroundColor(image.getPixel(x, y));
}
This is the method i am using to get the color of the touched coordinate.
Thanks,
Vipin
try this:
final Bitmap bitmap = ((BitmapDrawable)imageView.getDrawable()).getBitmap();
imageView.setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event){
int x = (int)event.getX();
int y = (int)event.getY();
int pixel = bitmap.getPixel(x,y);
//then do what you want with the pixel data, e.g
int redValue = Color.red(pixel);
int blueValue = Color.blue(pixel);
int greenValue = Color.green(pixel);
return false;
}
});
Why so complicated?
https://stackoverflow.com/a/7807442/1979882
Have you tried this?:
private void getColor(MotionEvent event, Button capture) {
float[] touchPoint = new float[]{event.getX(), event.getY()};
float x = touchPoint[0];
float y = touchPoint[1];
ImageView imageView = ((ImageView)v);
Bitmap bitmap = ((BitmapDrawable)imageView.getDrawable()).getBitmap();
int pixel = bitmap.getPixel(x,y);
capture.setBackgroundColor(image.getPixel(x, y));
}
I'm trying to make a frame for TextView as a cloud. But the content area does not behave as expected. What am i doing wrong?
I have a suggestion that is not working properly because the content area less scale area. So sad. I remade it to handle 9-patch manually. Save pictures without .9.png. Get Bitmap. There are 9-line present. With getPixels calculated padding and set it on the TextView. After that calculating and set LayoutParams.width and LayoutParams.height. Looks a bit ugly, but it works quite quickly, and most importantly correctly.
private int startX=-1;
private int endX=-1;
private int contentW=-1;
private int contentH=-1;
Bitmap bmp=BitmapFactory.decodeResource(getResources(), mIconResId);
int[] pixels=new int[bmp.getWidth()*bmp.getHeight()];
bmp.getPixels(pixels, 0, bmp.getWidth(), 0, 0, bmp.getWidth(),bmp.getHeight());
for(int i=0;i<bmp.getWidth();i++){
if(startX==-1 && pixels[bmp.getWidth()*(bmp.getHeight()-1)+i]==Color.BLACK){
startX=i;
}
if(startX!=-1 && pixels[bmp.getWidth()*(bmp.getHeight()-1)+i]!=Color.BLACK){
endX=i;
break;
}
}
int startY=-1;
int endY=-1;
for(int i=0;i<bmp.getHeight();i++){
if(startY==-1 && pixels[bmp.getWidth()*(i+1)-1]==Color.BLACK){
startY=i;
}
if(startY!=-1 && pixels[bmp.getWidth()*(i+1)-1]!=Color.BLACK){
endY=i;
break;
}
}
setBackground(new BitmapDrawable(getResources(),Bitmap.createBitmap(bmp, 1, 1, bmp.getWidth()-2, bmp.getHeight()-2)));
contentW=endX-startX;
endX=bmp.getWidth()-endX;
contentH=endY-startY;
endY=bmp.getHeight()-endY;
new Handler().post(new Rannable(){
#Override
public void run() {
int w=textview.getWidth();
int h=textview.getHeight();
if(w>endX-startX){
float k=((float)w)/contentW;
startX=(int) (startX*k);
endX=(int) (endX*k);
}
if(h>endY-startY){
float k=((float)h)/contentH;
startY=(int) (startY*k);
endY=(int) (endY*k);
}
w+=startX+startX;
h+=startY+endY;
textview.setPadding(startX, startY, endX, endY);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(w,h);
textview.setLayoutParams(lp);
}
});
You set good values for right and bottom borders. You just have to set same values for left and top borders, left border = right border and top border = bottom border.
The result in draw9patch:
And here the 9-patch file:
For your information, your image is not really suitable for using with 9-patch format.
I extended/adapted #ahtartam code. I am not sure if it is the cleanest way but it works for me. If someone needs help, just contact me or ask in comments!
public void setTextLayout(int orgW, int orgH,int actW,int actH,int top,int left) {
int startX = -1;
int endX = -1;
int startY = -1;
int endY = -1;
int contentW;
int contentH;
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.image);
int[] pixels = new int[orgW * orgH];
bmp.getPixels(pixels, 0, orgW, 0, 0, orgW, orgH);
for (int i = 0; i < orgW; i++) {
if (startX == -1 && pixels[orgW * (orgH - 1) + i] == Color.BLACK) {
startX = i;
}
if (startX != -1 && pixels[orgW * (orgH - 1) + i] != Color.BLACK) {
endX = i;
break;
}
}
for (int i = 0; i < orgH; i++) {
if (startY == -1 && pixels[orgW * (i + 1) - 1] == Color.BLACK) {
startY = i;
}
if (startY != -1 && pixels[orgW * (i + 1) - 1] != Color.BLACK) {
endY = i;
break;
}
}
m_marvin.setImageDrawable(new BitmapDrawable(getResources(), Bitmap.createBitmap(bmp, 1, 1, orgW - 2, orgH - 2)));
RelativeLayout.LayoutParams rp = (RelativeLayout.LayoutParams) m_marvin.getLayoutParams();
contentW=endX- startX;
contentH=endY-startY;
endX=orgW-endX;
endY=orgH-endY;
double scaleX = ((double)actW) / bmp.getWidth();
double scaleY = ((double)actH) / bmp.getHeight();
startX = (int) (startX * scaleX);
endX = (int) (endX * scaleX);
startY = (int) (startY * scaleY);
endY = (int) (endY * scaleY) ;
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams((int)(contentW*scaleX),(int)(contentH*scaleY));
layoutParams.setMargins(startX+rp.leftMargin+left, startY+rp.topMargin+top, endX+rp.rightMargin, endY+rp.bottomMargin);
layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL,RelativeLayout.TRUE);
m_text.setLayoutParams(layoutParams);
m_text.bringToFront();
}
Instead TextView I use SizeAwareImageView from -> https://stackoverflow.com/a/15538856/1438596
In my case it looks like this->
public class SizeAwareImageView extends ImageView {
MainActivity m_mainActivity;
public SizeAwareImageView(Context context,AttributeSet attrss){
super(context,attrss);
m_mainActivity = (MainActivity)context;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if(m_mainActivity.getTextMeasured())return;
// Get image matrix values and place them in an array
float[] f = new float[9];
getImageMatrix().getValues(f);
// Extract the scale values using the constants (if aspect ratio maintained, scaleX == scaleY)
final float scaleX = f[Matrix.MSCALE_X];
final float scaleY = f[Matrix.MSCALE_Y];
// Get the drawable (could also get the bitmap behind the drawable and getWidth/getHeight)
final Drawable d = getDrawable();
final int origW = d.getIntrinsicWidth();
final int origH = d.getIntrinsicHeight();
// Calculate the actual dimensions
final int actW = Math.round(origW * scaleX);
final int actH = Math.round(origH * scaleY);
int top = (int) (imgViewH - actH)/2;
int left = (int) (imgViewW - actW)/2;
if(origW!=actW){
m_mainActivity.setTextMeasured(true);
m_mainActivity.setTextLayout(origW, origH, actW, actH,top,left);
}
}
}
You could use this tool for creating your nine-patch images.
I have customview for displaying two bitmaps but the problem is it is scaling to center crop but I don't want to crop bitmap instead I want to display full bitmap in canvas.
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
mLayoutWidth = MeasureSpec.getSize(widthMeasureSpec);
mLayoutHeight = MeasureSpec.getSize(heightMeasureSpec);
this.setMeasuredDimension(mLayoutWidth, mLayoutHeight);
mBitmap = scaleCenterCrop(mBitmap, mLayoutWidth, mLayoutHeight);
overlayDefault = FastBlur.doBlur(mBitmap, 20, false);
overlayDefault = scaleCenterCrop(overlayDefault, mLayoutWidth,
mLayoutHeight);
overlay = mBitmap.copy(Config.ARGB_8888, true);
overlay = scaleCenterCrop(overlay, mLayoutWidth, mLayoutHeight);
cx = (mLayoutWidth - mBitmap.getWidth()) >> 1;
cy = (mLayoutHeight - mBitmap.getHeight()) >> 1;
c2 = new Canvas(overlay);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final Rect bitmapRect = ImageViewUtil.getBitmapRectCenterInside(
mBitmap.getWidth(), mBitmap.getHeight(), mLayoutWidth, mLayoutHeight);
setBitmapRect(bitmapRect);
invalidate();
}
public Bitmap scaleCenterCrop(Bitmap original, int deviceHeight,
int deviceWidth) {
int old_width = original.getWidth();
int old_height = original.getHeight();
float scale = Math.max((float) deviceHeight / old_height,
(float) deviceWidth / old_width);
float newWidth = scale * old_width;
float newHeight = scale * old_height;
float left = (deviceWidth - newWidth) / 2;
float top = (deviceHeight - newHeight) / 2;
RectF rectF = new RectF(left, top, left + newWidth, top + newHeight);
Bitmap scaled = Bitmap.createBitmap(deviceWidth, deviceHeight,
original.getConfig());
Canvas canvas = new Canvas(scaled);
canvas.drawBitmap(original, null, rectF, null);
return scaled;
}
I want implement move a sprite from position (x ,y ) to position action_down (x1 , y1) .But I can't rotate it .Please help me .Thanks
This is my code:
public Sprite(GameView gameView, Bitmap bmp) {
this.gameView = gameView;
this.bmp = bmp;
this.width = bmp.getWidth() / BMP_COLUMNS;// create width, height
this.height = bmp.getHeight() / BMP_ROWS;
Random rnd = new Random(System.currentTimeMillis());
x = rnd.nextInt(gameView.getWidth() - bmp.getWidth());
y = rnd.nextInt(gameView.getHeight() - bmp.getHeight());
}
public void onDraw(Canvas canvas) {
Matrix matrix = new Matrix();
matrix.postTranslate(x, y);
float dx = x1-x;
float dy = y1-y;
float d = (float)Math.sqrt(dx*dx+dy*dy);
vx = (float) (dx*5/d)/3 ;
vy = (float) (dy*5/d)/3 ;
if(k==1){
x += vx ;
y += vy ;
}
currentFrame = ++currentFrame % BMP_COLUMNS;
int srcX = currentFrame * width;
int srcY = 0 * height;
Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
Rect dst = new Rect(x, y, x + width, y + height);
canvas.drawBitmap(bmp, src, dst, null);
}
You should look at matrix.postRotate or canvas.rotate.
Here you go:
Note: you need to convert from Bitmap to Image.
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
/**
* Created by Chris on 3/28/2014.
*/
public class Sprite {
private Image i;
public Sprite(Image image) {
this.i = image;
}
private BufferedImage image = null;
private Graphics2D graphics = null;
public void onDraw(Canvas canvas) {
if(image == null || graphics == null) {
setup();
}
Graphics g = canvas.getGraphics();
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, image.getWidth(), image.getHeight());
//Where to draw the Sprite on the canvas.
int x = 100;
int y = 100;
//Because graphics is an instance of Graphics2D
//Converts the degrees "45" to radians.
double rotationAngle = Math.toRadians(45);
double locX = image.getWidth() / 2;
double locY = image.getHeight() / 2;
AffineTransform tx = AffineTransform.getRotateInstance(rotationAngle, locX, locY);
AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
graphics.drawImage(op.filter(image, null), 0, 0, null);
g.drawImage(image, x, y, (int) (image.getWidth() / 2), (int) (image.getHeight() / 2), null);
}
/**
* Sets the Image up.
*/
private void setup() {
if(image != null) {
image.flush();
image = null;
}
if(graphics != null) {
graphics.dispose();
graphics = null;
}
image = new BufferedImage(i.getWidth(null) * 2, i.getHeight(null) * 2, BufferedImage.TYPE_INT_ARGB);
graphics = image.createGraphics();
}
}
i want my bitmap in the center of my screen..i m trying it that way but its not working...
Bitmap myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.compass);
int w = canvas.getWidth();
int h = canvas.getHeight();
int bw=myBitmap.getWidth();
int bh=myBitmap.getHeight();
int cx = w / 2;
int cy = h / 2;
Display d = getWindowManager().getDefaultDisplay();
int x = d.getWidth();
int y = d.getHeight();
int dx = x / 2;
int dw = y /2;
canvas.translate(cx, cy);
if (mValues != null) {
canvas.rotate(-mValues[0]);
}
int centreX = (x - bw) /2;
int centreY = (cy - bh) /2;
//canvas.drawPath(mPath, mPaint);
canvas.drawBitmap(myBitmap, centreX,centreY, null);
Here's the code you need in your view:
private int mWidth;
private int mHeight;
private float mAngle;
#Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
mWidth = View.MeasureSpec.getSize(widthMeasureSpec);
mHeight = View.MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(mWidth, mHeight);
}
#Override protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Bitmap myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.compass);
// Here's the magic. Whatever way you do it, the logic is:
// space available - bitmap size and divide the result by two.
// There must be an equal amount of pixels on both sides of the image.
// Therefore whatever space is left after displaying the image, half goes to
// left/up and half to right/down. The available space you get by subtracting the
// image's width/height from the screen dimensions. Good luck.
int cx = (mWidth - myBitmap.getWidth()) >> 1; // same as (...) / 2
int cy = (mHeight - myBitmap.getHeight()) >> 1;
if (mAngle > 0) {
canvas.rotate(mAngle, mWidth >> 1, mHeight >> 1);
}
canvas.drawBitmap(myBitmap, cx, cy, null);
}
Screenshot just for fun: http://imgur.com/EYpMJ
(Diagonal lines not part of the code posted here)
EDIT: Added NickT's solution.
EDIT 2: Changed mvalues[0] to mAngle and made it conditional. Changed divide by 2 operations to bitshifts. Remove rotation code if you don't need it.
You can try this :
int width = containerBitmap.getWidth();
int height = containerBitmap.getHeight();
float centerX = (width - centeredBitmap.getWidth()) * 0.5f;
float centerY = (height- centeredBitmap.getHeight()) * 0.5f;
You can use it to draw a bitmap at the center of another bitmap.