Drawing portion of bitmap in Android? - java

I have here a method to draw a rotated scaled bitmap in Android:
public void drawRotatedScaledBitmap(Bitmap b,
float centerX, float centerY, float width, float height, float angle)
{
float scaleX = width / b.getWidth();
float scaleY = height / b.getHeight();
centerX -= (b.getWidth() * scaleX) / 2.0f;
centerY -= (b.getHeight() * scaleY) / 2.0f;
matrix.reset();
matrix.setTranslate(centerX, centerY);
matrix.postRotate(angle * (180.0f / (float)(Math.PI)),
centerX + (b.getWidth() * scaleX) / 2.0f,
centerY + (b.getHeight() * scaleY) / 2.0f);
matrix.preScale(scaleX,scaleY);
canvas.drawBitmap(b, matrix, null);
}
I'm not sure how I could modify this to take in float sourceX, float sourceY, float sourceW, float sourceH.
I want to render tile sets so I need to tell it say 64,64,64,64 on the bitmap.
How could I do this?
Thanks

Maybe you can try canvas.clipRect() to specify the drawing area.

Here is how I solved it:
public void drawRotatedScaledBitmap(Bitmap b,
float centerX, float centerY, float width, float height,
float sourceX, float sourceY,
float sourceWidth, float sourceHeight, float angle)
{
float cx = centerX;
float cy = centerY;
dstRect.left = (int)centerX - (int)(width / 2);
dstRect.top = (int)centerY - (int)(height / 2);
dstRect.right = dstRect.left + (int)width;
dstRect.bottom = dstRect.top + (int)height;
srcRect.left = (int)sourceX;
srcRect.top = (int)sourceY;
srcRect.right = srcRect.left + (int)sourceWidth;
srcRect.bottom = srcRect.top + (int)sourceHeight;
canvas.rotate(angle * (180.0f / (float)(Math.PI)),cx,cy);
canvas.drawBitmap(b, srcRect, dstRect, null);
canvas.rotate(-angle * (180.0f / (float)(Math.PI)),cx,cy);
}

Related

Android scale ImageView using anchor points

The goal is: the Imageview have 4 squares on each corners. If the user touch and drag one of this, the image is scaled.
Given the image, the 4 squares and the touched square how can i implement this feature? (square = Rectf class)
example of image
I have find out a possible solution, if anyone need the code:
float centerX, centerY, startScale, startX, startY;
private void startScaling(MotionEvent e) {
ImageView imageView = (ImageView) getChildAt(0);
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = e.getX();
startY = e.getY();
startScale = imageView.getScaleX();
centerX = imageView.getX() + imageView.getWidth() / 2F;
centerY = imageView.getY() + imageView.getHeight() / 2F;
break;
case MotionEvent.ACTION_MOVE:
// euclidean distance
double length1 = Point.distance(centerX, centerY, startX, startY);
double length2 = Point.distance(centerX, centerY, e.getX(), e.getY());
if(length2 > length1) {
//scale up
float scaleFactor = (float) (length2 / length1);
//scale the image
imageView.setScaleX(startScale * scaleFactor);
imageView.setScaleY(startScale * scaleFactor);
}else {
//scale down
// calculate the scale factor
float scaleFactor = (float) (length1 / length2);
// scale the image
imageView.setScaleX(startScale / scaleFactor);
imageView.setScaleY(startScale / scaleFactor);
}
float scaledWidth = imageView.getWidth() * imageView.getScaleX();
float scaledHeight = imageView.getHeight() * imageView.getScaleY();
// calculate new boubds of the image
float left = centerX - scaledWidth / 2F;
float top = centerY - scaledHeight / 2F;
float right = left + scaledWidth;
float bottom = top + scaledHeight;
break;
case MotionEvent.ACTION_UP:
break;
}
}

create percentage square in java instead circles

I am working in a existing project for an amazfit watchface. Code is based in java. The question is: In original project, for show battery, steps and sport percentage, show three circles. My idea is to draw a rectangle (or a line) instead the original circle. The problem is I am new programming in java and I donĀ“t know for change this without FC app.
this watch has two screens: one active and other in stand-by mode (8colors only)
active mode draws circle, standby mode works with an png image.
This is the code (for circles):
package es.xxxx.xxxx.widget;
private final float startAngleBattery = 30;
private final float arcSizeBattery = 360 - startAngleBattery - startAngleBattery;
#Override
public void init(Service service) {
this.thickness = (int) service.getResources().getDimension(R.dimen.xxxx_circles_thickness);
this.textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
this.textPaint.setTypeface(ResourceManager.getTypeFace(service.getResources(), ResourceManager.Font.BEBAS_NEUE));
this.textPaint.setTextSize(service.getResources().getDimension(R.dimen.xxxx_circles_font_size));
this.textPaint.setColor(service.getResources().getColor(R.color.xxxx_time_colour));
this.textPaint.setTextAlign(Paint.Align.CENTER);
this.ring = new Paint(Paint.ANTI_ALIAS_FLAG);
this.ring.setStrokeCap(Paint.Cap.ROUND);
this.ring.setStyle(Paint.Style.STROKE);
this.ring.setStrokeWidth(this.thickness);
this.circle = new Paint(Paint.ANTI_ALIAS_FLAG);
this.circle.setColor(Color.BLACK);
this.circle.setStrokeWidth(1f);
this.circle.setStyle(Paint.Style.STROKE);
#Override
public void draw(Canvas canvas, float width, float height, float centerX, float centerY) {
int count = canvas.save();
int radius = Math.round(Math.min(width / 2, height / 2)) - this.thickness;
RectF oval = new RectF(centerX - radius, centerY - radius, centerX + radius, centerY + radius);
// rotate from 0 to 270 degrees
canvas.rotate(90, centerX, centerY);
this.ring.setColor(this.backgroundColour);
canvas.drawArc(oval, startAngleBattery, arcSizeBattery, false, ring);
if (batterySweepAngle != null) {
float px = getPointX(oval, centerX, startAngleBattery, batterySweepAngle);
float py = getPointY(oval, centerY, startAngleBattery, batterySweepAngle);
this.ring.setColor(this.batteryColour);
canvas.drawArc(oval, startAngleBattery, batterySweepAngle, false, ring);
canvas.drawCircle(px, py, this.thickness / 3f, circle);
canvas.drawCircle(px, py, this.thickness / 6f, circle);
}
canvas.restoreToCount(count);
if (this.batteryData != null) {
String text = String.format("%02d", this.batteryData.getLevel() * 100 / this.batteryData.getScale());
canvas.drawText(text, batteryTextLeft, batteryTextTop, textPaint);
}
}
#Override
public void onDataUpdate(DataType type, Object value) {
switch (type) {
case BATTERY:
onBatteryData((Battery) value);
break;
}
}
#Override
public List<DataType> getDataTypes() {
return Arrays.asList(DataType.BATTERY);
private void onBatteryData(Battery battery) {
this.batteryData = battery;
if (batteryData == null) {
this.batterySweepAngle = 0f;
} else {
float scale = batteryData.getLevel() / (float) batteryData.getScale();
this.batterySweepAngle = Math.min(arcSizeBattery, arcSizeBattery * scale);
}
}
private RectF nextOval(RectF oval) {
oval.left = oval.left + this.thickness + MARGIN;
oval.top = oval.top + this.thickness + MARGIN;
oval.right = oval.right - this.thickness - MARGIN;
oval.bottom = oval.bottom - this.thickness - MARGIN;
return oval;
}
private float getPointX(RectF oval, float cx, float startAngle, float sweepAngle) {
float width = oval.right - oval.left;
return (float) (cx + (width / 2D) * Math.cos((sweepAngle + startAngle) * Math.PI / 180));
}
private float getPointY(RectF oval, float cy, float startAngle, float sweepAngle) {
float height = oval.bottom - oval.top;
return (float) (cy + (height / 2D) * Math.sin((sweepAngle + startAngle) * Math.PI / 180));
}
#Override
public List<SlptViewComponent> buildSlptViewComponent(Service service) {
Typeface timeTypeFace = ResourceManager.getTypeFace(service.getResources(), ResourceManager.Font.BEBAS_NEUE);
SlptLinearLayout power = new SlptLinearLayout();
power.alignX = 2;
power.alignY = 2;
power.add(new SlptPowerNumView());
power.setTextAttrForAll(
service.getResources().getDimension(R.dimen.xxxx_circles_font_size_slpt),
-1,
timeTypeFace
);
power.setStart(
(int) service.getResources().getDimension(R.dimen.xxxx_battery_text_left_slpt),
(int) service.getResources().getDimension(R.dimen.xxxx_battery_text_top_slpt));
SlptPowerArcAnglePicView powerArcView = new SlptPowerArcAnglePicView();
powerArcView.setImagePicture(Util.assetToBytes(service, "battery_splt.png"));
powerArcView.start_angle = (int) startAngleBattery + 180 - 3;
powerArcView.full_angle = (int) arcSizeBattery + 6;
return Arrays.asList(power, powerArcView);
}
}
Thanks in advance.
For anyone still searching...
You can draw the rectangular in the "draw" function that runs in loop constantly when screen is on, however, screen off (SLPT mode) uses ingenic's libraries to draw (function buildSlptViewComponent) and there is the real problem.
I don't want to get into details because it would be pages, so have a look at GreatFit project.

How to draw bitmap image on top in arc

I want to draw image on Top in each Arc of Canvas
private void drawImage(Canvas canvas, float tempAngle, Bitmap bitmap,String mValue) {
//get every arc img width and angle
int imgWidth = (radius / mWheelItems.size());
//int imgWidth = (radius / 3);
float angle = (float) ((tempAngle + 360 / mWheelItems.size() /2) * Math.PI / 180);
//calculate x and y
int x = (int) (center + radius / 2 / 2 * Math.cos(angle));
int y = (int) (center + radius / 2 / 2 * Math.sin(angle));
int top=y - imgWidth/2;
int bottom=y +imgWidth/2;
int left=x - imgWidth /2;
int right=x + imgWidth / 2;
Rect rect = new Rect(left, top, right, bottom);
final Rect rect1 = new Rect(x - imgWidth /2 , y - imgWidth / 2 , bitmap.getWidth() , bitmap.getHeight());
canvas.drawBitmap(bitmap, null, rect, null);
}
the Arc is made according to the size of items
The Result is shown like that
But I want the image bitmap shown on top like that of rect. Red also want to large size of images or bitmap
Solved by Specific Tab and Big Screen Tablets
Change the X and Y coordination According to Angle
if(tempAngle==0) {
x = x + 50;
}
if(tempAngle==60) {
y = y + 50;
}
if(tempAngle==120) {
imgWidth = imgWidth-12;
y = y + 20;
x = x - 40;
}
if(tempAngle==180) {
imgWidth = imgWidth+12;
x = x - 50;
}
if(tempAngle==240) {
y = y - 50;
}
if(tempAngle==300) {
y = y - 20;
x = x + 40;
}

libgdx: Making a cross shape rotate

I am experimenting with libgdx trying to make my first simple game. I have managed to make a line rotate.
What I haven't accomplished is adding a perpendicular line, and making it a cross and then rotating this shape.
public void render(ShapeRenderer renderer) {
renderer.set(ShapeType.Line);
renderer.setColor(COLOR);
/**
* finding the angle
*/
float elapsedNanoseconds = TimeUtils.nanoTime() - initialTime;
float elapsedSeconds = MathUtils.nanoToSec * elapsedNanoseconds;
float elapsedPeriods = elapsedSeconds / 2.0f;
float cyclePosition = elapsedPeriods % 1;
float x = WORLD_SIZE / 2 + radius * MathUtils.cos(MathUtils.PI2 * cyclePosition);
float y = WORLD_SIZE / 2 + radius * MathUtils.sin(MathUtils.PI2 * cyclePosition);
//line rotates and moves at the same time.
renderer.line(position.x - x, position.y + y, position.x + x, position.y - y);
}
position is a Vector2() class object which is updated every delta seconds and holds the current center of the line.
I managed to find the solution. I will leave it here in case someone is having similar issues:
public void render(ShapeRenderer renderer) {
/**
* find the angle
*/
float elapsedNanoseconds = TimeUtils.nanoTime() - initialTime;
float elapsedSeconds = MathUtils.nanoToSec * elapsedNanoseconds;
float elapsedPeriods = elapsedSeconds / 2.0f;
float cyclePosition = elapsedPeriods % 1;
float x = WORLD_SIZE / 2 + radius * MathUtils.cos(MathUtils.PI2 * cyclePosition);
float y = WORLD_SIZE / 2 + radius * MathUtils.sin(MathUtils.PI2 * cyclePosition);
float x2 = WORLD_SIZE / 2 + radius * MathUtils.sin(MathUtils.PI2 * -cyclePosition);
float y2 = WORLD_SIZE / 2 + radius * MathUtils.cos(MathUtils.PI2 * -cyclePosition);
renderer.set(ShapeType.Line);
renderer.setColor(COLOR);
renderer.line(position.x - x, position.y + y, position.x + x, position.y - y);
renderer.line(position.x - x2, position.y + y2, position.x + x2, position.y - y2);
}

How to rotate triangle around center?

I am drawing a triangle on canvas:
float x = 540;
float y = 960;
Path path = new Path();
path.moveTo(x, y);
path.lineTo(x+18, y+60);
path.lineTo(x-18, y+60);
path.lineTo(x, y);
canvas.drawPath(path, mPaint);
This canvas has another objects. But I need to rotate only this triangle around center of this triangle on a random angle (between 0 and 360). How to implement it? How to get coordinates vertexes of a triangle after rotation?
Its simple math, if the center of the triangle is (x,y) and the center-vertex distace is A, the three vertex will be
-(A*Math.cos(angle),A*Math.sin(angle))
-(A*Math.cos(angle+2*Math.PI/3),A*Math.sin(angle+2*Math.PI/3))
-(A*Math.cos(angle-2*Math.PI/3),A*Math.sin(angle-2*Math.PI/3))
I solve it by this way:
float angle = (float) Math.toRadians(90); // Angle to rotate
// Size of triangle
final float height = 60;
final float width = 36;
// Display coordinates where triangle will be drawn
float centerX = 540;
float centerY = 960;
// Vertex's coordinates before rotating
float x1 = centerX;
float y1 = centerY - height / 2;
float x2 = centerX + width / 2;
float y2 = centerY + height / 2;
float x3 = centerX - width / 2;
float y3 = y2;
// Rotating
float x1r = (float) ((x1 - centerX) * Math.cos(angle) - (y1 - centerY) * Math.sin(angle) + centerX);
float y1r = (float) ((x1 - centerX) * Math.sin(angle) + (y1 - centerY) * Math.cos(angle) + centerY);
float x2r = (float) ((x2 - centerX) * Math.cos(angle) - (y2 - centerY) * Math.sin(angle) + centerX);
float y2r = (float) ((x2 - centerX) * Math.sin(angle) + (y2 - centerY) * Math.cos(angle) + centerY);
float x3r = (float) ((x3 - centerX) * Math.cos(angle) - (y3 - centerY) * Math.sin(angle) + centerX);
float y3r = (float) ((x3 - centerX) * Math.sin(angle) + (y3 - centerY) * Math.cos(angle) + centerY);
// Drawing
Path path = new Path();
path.moveTo(x1r, y1r);
path.lineTo(x2r, y2r);
path.lineTo(x3r, y3r);
path.lineTo(x1r, y1r);
canvas.drawPath(path, mPaint);
Thanks to Gimka and Nofate for help.

Categories