Convert sinusoid values to audio in android - android

I am graphically representing audio on x and y axis. From those y-axis points I want to generate audio again.
Followed https://github.com/billthefarmer/scope this to get points on y-axis. I have all of the values of y-axis points. These points can be used to represent a wave graphically.
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Locale;
// Scope
public class Scope extends View {
private int width;
private int height;
private Path path;
private Canvas cb;
private Paint paint;
private Bitmap bitmap;
private Bitmap graticule;
protected boolean storage;
protected boolean clear;
protected float step;
protected float scale;
protected float start;
protected float index;
protected float yscale;
protected boolean points;
protected MainActivity.Audio audio;
// Scope
public Scope(Context context, AttributeSet attrs) {
super(context, attrs);
// Create path and paint
path = new Path();
paint = new Paint();
}
// On size changed
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// Get dimensions
width = w;
height = h;
// Create a bitmap for trace storage
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
cb = new Canvas(bitmap);
// Create a bitmap for the graticule
graticule = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(graticule);
// Black background
canvas.drawColor(Color.BLACK);
// Set up paint
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.argb(255, 0, 63, 0));
// Draw graticule
for (int i = 0; i < width; i += MainActivity.SIZE)
canvas.drawLine(i, 0, i, height, paint);
canvas.translate(0, height / 2);
for (int i = 0; i < height / 2; i += MainActivity.SIZE) {
canvas.drawLine(0, i, width, i, paint);
canvas.drawLine(0, -i, width, -i, paint);
}
// Draw the graticule on the bitmap
cb.drawBitmap(graticule, 0, 0, null);
cb.translate(0, height / 2);
}
private int max;
// On draw
#Override
protected void onDraw(Canvas canvas) {
// Check for data
if ((audio == null) || (audio.data == null)) {
canvas.drawBitmap(graticule, 0, 0, null);
return;
}
// Draw the graticule on the bitmap
if (!storage || clear) {
cb.drawBitmap(graticule, 0, -height / 2, null);
clear = false;
}
// Calculate x scale etc
float xscale = (float) (2.0 / ((audio.sample / 100000.0) * scale));
int xstart = Math.round(start);
int xstep = Math.round((float) 1.0 / xscale);
int xstop = Math.round(xstart + ((float) width / xscale));
if (xstop > audio.length)
xstop = (int) audio.length;
// Calculate y scale
if (max < 4096)
max = 4096;
yscale = (float) (max / (height / 2.0));
max = 0;
// Draw the trace
path.rewind();
path.moveTo(0, 0);
if (xscale < 1.0) {
for (int i = 0; i < xstop - xstart; i += xstep) {
if (max < Math.abs(audio.data[i + xstart]))
max = Math.abs(audio.data[i + xstart]);
float x = (float) i * xscale;
float y = -(float) audio.data[i + xstart] / yscale;
path.lineTo(x, y);
Log.d("y values", "y = " + String.valueOf(y)); // KING
writeToFile("y = " + String.valueOf(y), getContext());
}
} else {
for (int i = 0; i < xstop - xstart; i++) {
if (max < Math.abs(audio.data[i + xstart]))
max = Math.abs(audio.data[i + xstart]);
float x = (float) i * xscale;
float y = -(float) audio.data[i + xstart] / yscale;
path.lineTo(x, y);
Log.d("y values", "y = " + String.valueOf(y)); // KING
writeToFile("y = " + String.valueOf(y), getContext());
// Draw points at max resolution
if (points) {
path.addRect(x - 2, y - 2, x + 2, y + 2, Path.Direction.CW);
path.moveTo(x, y);
Log.d("y values", "y = " + String.valueOf(y)); // KING
writeToFile("y = " + String.valueOf(y), getContext());
}
}
}
// Green trace
paint.setColor(Color.GREEN);
paint.setAntiAlias(true);
cb.drawPath(path, paint);
// Draw index
if (index > 0 && index < width) {
// Yellow index
paint.setColor(Color.YELLOW);
paint.setAntiAlias(false);
cb.drawLine(index, -height / 2, index, height / 2, paint);
paint.setAntiAlias(true);
paint.setTextSize(height / 48);
paint.setTextAlign(Paint.Align.LEFT);
// Get value
int i = Math.round(index / xscale);
if (i + xstart < audio.length) {
float y = -audio.data[i + xstart] / yscale;
// Draw value
String s = String.format(Locale.getDefault(), "%3.2f",
audio.data[i + xstart] / 32768.0);
cb.drawText(s, index, y, paint);
}
paint.setTextAlign(Paint.Align.CENTER);
// Draw time value
if (scale < 100.0) {
String s = String.format(Locale.getDefault(),
(scale < 1.0) ? "%3.3f" :
(scale < 10.0) ? "%3.2f" : "%3.1f",
(start + (index * scale)) /
MainActivity.SMALL_SCALE);
cb.drawText(s, index, height / 2, paint);
// Log.d("y values", "y = " + String.valueOf(y));
} else {
String s = String.format(Locale.getDefault(), "%3.3f",
(start + (index * scale)) /
MainActivity.LARGE_SCALE);
cb.drawText(s, index, height / 2, paint);
}
}
canvas.drawBitmap(bitmap, 0, 0, null);
}
private void writeToFile(String data, Context context) {
try {
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(context.openFileOutput("Sinusoids.txt", Context.MODE_PRIVATE));
outputStreamWriter.write(data);
outputStreamWriter.close();
} catch (IOException e) {
Log.e("Exception", "File write failed: " + e.toString());
}
}
// On touch event
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
// Set the index from the touch dimension
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
index = x;
break;
case MotionEvent.ACTION_MOVE:
index = x;
break;
case MotionEvent.ACTION_UP:
index = x;
break;
}
return true;
}
}
Generate byte array from y-axis points. The array can then be converted to sound.

Related

Face Warp Technique to make it Old

I am developing face app like "Aging Booth". I have successfully detected face and applied wrinkle on it.
Now I want to warp face like as following example
Can any one help me to solve this problem, by guiding me which technique I should use, OR any source code to warp image like this.
I try to solve it using following code.
But it is not giving required result. So any one please edit it to get required result OR any other technique....
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.widget.ImageView;
import android.widget.LinearLayout;
public class MainActivity extends Activity {
////////////////////////////////////////////////////////
ImageView img;
Bitmap face;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
LinearLayout ll01 = (LinearLayout) findViewById(R.id.linearLayout1);
SampleView sv = new SampleView(this);
ll01.addView(sv);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private static class SampleView extends View {
static int WIDTH = 8; // sections
static int HEIGHT = 8;
static int COUNT = (WIDTH + 1) * (HEIGHT + 1); // total verts count
Bitmap mBitmap; // declaring a bitmap
float[] matrixVertsMoved = new float[COUNT * 2]; // declaring an array with double amount of vert count, one for x and one for y
float[] matrixOriganal = new float[COUNT * 2];
float clickX;
float clickY;
static void setXY(float[] array, int index, float x, float y) {
array[index * 2 + 0] = x;
array[index * 2 + 1] = y;
}
///
public SampleView(Context context) {
super(context);
setFocusable(true);
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.w);
// construct our mesh
int index = 0;
for (int y = 0; y <= HEIGHT; y++) {
float fy = mBitmap.getHeight() * y / HEIGHT;
for (int x = 0; x <= WIDTH; x++) {
float fx = mBitmap.getWidth() * x / WIDTH;
setXY(matrixVertsMoved, index, fx, fy);
setXY(matrixOriganal, index, fx, fy);
index += 1;
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmapMesh(mBitmap, WIDTH, HEIGHT, matrixVertsMoved, 0, null, 0, null);
Paint p1 = new Paint();
p1.setColor(0x660000FF);
Paint p2 = new Paint();
p2.setColor(0x99FF0000);
Paint p3 = new Paint();
p3.setColor(0xFFFFFB00);
for (int i = 0; i < COUNT * 2; i += 2) {
float x = matrixOriganal[i + 0];
float y = matrixOriganal[i + 1];
canvas.drawCircle(x, y, 4, p1);
float x1 = matrixOriganal[i + 0];
float y1 = matrixOriganal[i + 1];
float x2 = matrixVertsMoved[i + 0];
float y2 = matrixVertsMoved[i + 1];
canvas.drawLine(x1, y1, x2, y2, p1);
}
for (int i = 0; i < COUNT * 2; i += 2) {
float x = matrixVertsMoved[i + 0];
float y = matrixVertsMoved[i + 1];
canvas.drawCircle(x, y, 4, p2);
}
canvas.drawCircle(clickX, clickY, 6, p3);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void smudge() {
for (int i = 0; i < COUNT * 2; i += 2) {
float xOriginal = matrixOriganal[i + 0];
float yOriginal = matrixOriganal[i + 1];
float dist_click_to_origin_x = clickX - xOriginal; // distance from current vertex in the original matrix to the place clicked.
float dist_click_to_origin_y = clickY - yOriginal;
float kv_kat = dist_click_to_origin_x * dist_click_to_origin_x + dist_click_to_origin_y * dist_click_to_origin_y;
float pull = (1000000 / kv_kat / (float) Math.sqrt(kv_kat));
if (pull >= 1) {
matrixVertsMoved[i + 0] = clickX;
matrixVertsMoved[i + 1] = clickY;
} else {
matrixVertsMoved[i + 0] = xOriginal + dist_click_to_origin_x * pull;
matrixVertsMoved[i + 1] = yOriginal + dist_click_to_origin_y * pull;
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#Override
public boolean onTouchEvent(MotionEvent event) {
clickX = event.getX();
clickY = event.getY();
smudge(); // change the matrix.
invalidate(); // calls a redraw on the canvas.
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
public Bitmap ExtendBitmap(Bitmap normalImage){
int w = normalImage.getWidth();
int h = normalImage.getHeight();
int thirdWidht = w / 3;
//create a new blank image
Bitmap stretchImage = Bitmap.createBitmap(w + thirdWidht, h, Bitmap.Config.ARGB_8888 );
Canvas c = new Canvas(stretchImage);
//draw left bit
c.drawBitmap(normalImage, new Rect(0,0,thirdWidht,h), new Rect(0,0,thirdWidht,h), null);
//draw stretched middle bit
c.drawBitmap(normalImage, new Rect(thirdWidht,0,thirdWidht * 2, h), new Rect(thirdWidht,0,thirdWidht * 3,h), null);
//draw right bit
c.drawBitmap(normalImage, new Rect(thirdWidht * 2,0,w,h), new Rect(thirdWidht * 3,0,w + thirdWidht,h), null);
return stretchImage;
}

Android path disappears after changing path offset and then calling invalidate

I've managed to draw a staircase and also a smiley face (called Avatar in the code) using paths in my custom view. Id like to move the happy face up the stairs using my nextStep function. nextStep iterates the current step and then calls a function called moveToStep(int step) which offsets the Avatar to the location of the specified step. Lastly, nextStep calls this.invalidate so that onDraw gets called again in hopes that the Avatar is redrawn at the new offset. The problem is that after nextStep is called, the Avatar disappears even though the staircase still remains. I know its not offscreen because I checked the coordinates the smiley is offset to.
Custom View Code
public class StaircaseView extends View {
// setup initial color
private final int paint_color = Color.BLACK;
private int curr_step = 1;
int STEPS = 5;
private float avatar_radius;
// defines paint and canvas
private Paint DrawPaint;
private int view_width, view_height, view_size;
private Path StaircasePath, Avatar;
private float scale, side_length;
private char constrainer;
public StaircaseView(Context context, AttributeSet attrs) {
super(context, attrs);
setupPaint();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.d("StaircaseView", "onDraw called");
canvas.drawPath(StaircasePath, DrawPaint);
canvas.drawPath(Avatar, DrawPaint);
}
#Override
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld){
super.onSizeChanged(xNew, yNew, xOld, yOld);
view_height = yNew;
view_width = xNew;
view_size = Math.min(view_height, view_width);
if (view_width == view_size) {
constrainer = 'w';
} else {
constrainer = 'h';
}
scale = (float)view_size/100;
Log.i("StaircaseView", "onSizeChanged --> view width: " + String.valueOf(xNew) + ", view height: " + String.valueOf(yNew) + ", scale: " + String.valueOf(scale) + ", view size: " + String.valueOf(view_size));
float padding = 5 * scale;
StaircasePath = createStaircase(padding);
avatar_radius = 7*scale;
Avatar = createAvatar(0, 0, avatar_radius);
StaircasePath.offset(0, view_height);
moveToStep(curr_step);
}
public void nextStep() {
if (curr_step < STEPS) {
curr_step++;
} else {
curr_step = 1;
}
moveToStep(curr_step);
this.invalidate();
}
private void moveToStep(int step) {
float x = step * side_length - avatar_radius;
float y = view_height - (step - 1) * side_length - avatar_radius;
Log.i("StaircaseView", String.valueOf(x) + ", " + String.valueOf(y));
Avatar.offset(x, y);
}
// Setup paint with color and stroke styles
private void setupPaint() {
DrawPaint = new Paint();
DrawPaint.setColor(paint_color);
DrawPaint.setAntiAlias(true);
DrawPaint.setStrokeWidth(5);
DrawPaint.setStyle(Paint.Style.STROKE);
DrawPaint.setStrokeJoin(Paint.Join.ROUND);
DrawPaint.setStrokeCap(Paint.Cap.ROUND);
}
private Path createStaircase(float padding) {
if (constrainer == 'w') {
side_length = (view_size-padding)/(STEPS+1);
} else {
side_length = (view_size-padding)/STEPS;
}
Path path = new Path();
float curr_x = 0;
float curr_y = 0;
path.moveTo(curr_x, curr_y);
curr_x += side_length;
path.lineTo(curr_x, curr_y);
for(int i=0; i<STEPS; i++) {
curr_y -= side_length;
path.lineTo(curr_x, curr_y);
curr_x += side_length;
path.lineTo(curr_x, curr_y);
}
path.lineTo(curr_x, 0);
path.lineTo(0, 0);
return path;
}
private Path createShape(ArrayList<PointF> points) {
Path path = new Path();
path.moveTo(points.get(0).x, points.get(0).y);
for(int i=1; i< points.size(); i++) {
path.lineTo(points.get(i).x, points.get(i).y);
}
return path;
}
private Path createAvatar(int x, int y, float radius){
Path avatar = new Path();
float width = radius*2;
avatar.addCircle(x, y, radius, Path.Direction.CW);
avatar.addCircle(x - (radius /2), y - (radius / 5), radius/5, Path.Direction.CW);
avatar.addCircle(x + (radius / 2), y - (radius / 5), radius / 5, Path.Direction.CW);
avatar.addRect((float) x - (radius / 5), (float) y - (radius / 5), (float) x + (radius / 5), (float) y - (radius/5), Path.Direction.CCW);
return avatar;
}
}
After looking at this question decided to figure out another way to do this. So what I did was I changed my moveToStep method to return the coordinates to move the Avatar to instead of offsetting him. I then passed these coordinates to the createAvatar method as start coordinates. It worked after that.
New Code
/**
* Created by yako on 11/5/15.
*/
public class StaircaseView extends View {
// setup initial color
private final int paint_color = Color.BLACK;
private int curr_step = 1;
int STEPS = 5;
private float avatar_radius;
// defines paint and canvas
private Paint DrawPaint;
private int view_width, view_height, view_size;
private Path StaircasePath, Avatar;
private float scale, side_length;
private char constrainer;
public StaircaseView(Context context, AttributeSet attrs) {
super(context, attrs);
setupPaint();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.d("StaircaseView", "onDraw called");
canvas.drawPath(StaircasePath, DrawPaint);
canvas.drawPath(Avatar, DrawPaint);
}
#Override
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld){
super.onSizeChanged(xNew, yNew, xOld, yOld);
view_height = yNew;
view_width = xNew;
view_size = Math.min(view_height, view_width);
if (view_width == view_size) {
constrainer = 'w';
} else {
constrainer = 'h';
}
scale = (float)view_size/100;
Log.i("StaircaseView", "onSizeChanged --> view width: " + String.valueOf(xNew) + ", view height: " + String.valueOf(yNew) + ", scale: " + String.valueOf(scale) + ", view size: " + String.valueOf(view_size));
float padding = 5 * scale;
// Log.i("StaircaseView", String.valueOf(view_height/2 + padding/2));
StaircasePath = createStaircase(padding);
// Center the staircase in the view
// if (constrainer == 'w') {
// StaircasePath.offset(padding/2, view_height - (view_height - view_width - padding*2));
// } else {
// StaircasePath.offset(view_height/2 - padding/2, view_height-padding/2);
// }
avatar_radius = 7*scale;
Avatar = createAvatar(moveToStep(curr_step), avatar_radius);
StaircasePath.offset(0, view_height);
}
public void nextStep() {
if (curr_step <= STEPS) {
curr_step++;
} else {
curr_step = 1;
}
Avatar = createAvatar(moveToStep(curr_step), avatar_radius);
this.invalidate();
}
private float[] moveToStep(int step) {
float[] offset = new float[2];
offset[0] = step * side_length - avatar_radius;
offset[1] = view_height - (step - 1) * side_length - avatar_radius;
Log.i("StaircaseView", "Moving avatar to "+ String.valueOf(offset[0]) + ", " + String.valueOf(offset[1]));
return offset;
}
// Setup paint with color and stroke styles
private void setupPaint() {
DrawPaint = new Paint();
DrawPaint.setColor(paint_color);
DrawPaint.setAntiAlias(true);
DrawPaint.setStrokeWidth(5);
DrawPaint.setStyle(Paint.Style.STROKE);
DrawPaint.setStrokeJoin(Paint.Join.ROUND);
DrawPaint.setStrokeCap(Paint.Cap.ROUND);
}
private Path createStaircase(float padding) {
if (constrainer == 'w') {
side_length = (view_size-padding)/(STEPS+1);
} else {
side_length = (view_size-padding)/(STEPS+1);
}
Path path = new Path();
float curr_x = 0;
float curr_y = 0;
path.moveTo(curr_x, curr_y);
curr_x += side_length;
path.lineTo(curr_x, curr_y);
for(int i=0; i<STEPS; i++) {
curr_y -= side_length;
path.lineTo(curr_x, curr_y);
curr_x += side_length;
path.lineTo(curr_x, curr_y);
}
path.lineTo(curr_x, 0);
path.lineTo(0, 0);
return path;
}
private Path createShape(ArrayList<PointF> points) {
Path path = new Path();
path.moveTo(points.get(0).x, points.get(0).y);
for(int i=1; i< points.size(); i++) {
path.lineTo(points.get(i).x, points.get(i).y);
}
return path;
}
private Path createAvatar(float[] offset, float radius){
float x = offset[0];
float y = offset[1];
Path avatar = new Path();
float width = radius*2;
avatar.addCircle(x, y, radius, Path.Direction.CW);
avatar.addCircle(x - (radius /2), y - (radius / 5), radius/5, Path.Direction.CW);
avatar.addCircle(x + (radius / 2), y - (radius / 5), radius / 5, Path.Direction.CW);
avatar.addRect((float) x - (radius / 5), (float) y - (radius / 5), (float) x + (radius / 5), (float) y - (radius/5), Path.Direction.CCW);
return avatar;
}
}

How keep previous draw on same canvas?

I am able to draw a text on canvas on motion view now the problem is that when i draw text & go for the next draw on same canvas my draw text is getting disappear i mean screen is getting redraw because of invalidate i want keep my previous draw and make new draw on same canvas how am i going to do that ?
public class PuzzleView extends View {
private float width; // width of one tile
private float height; // height of one tile
private int selX; // X index of selection
private int selY; // Y index of selection
private final Rect selRect = new Rect();
private final Game game;
float positionX = 5;
float positionY = 15;
String strgettile = null;
float x, y;
Paint foreground = new Paint(Paint.ANTI_ALIAS_FLAG);
String getorientation;
public PuzzleView(Context context) {
super(context);
this.game = (Game) context;
setFocusable(true);
setFocusableInTouchMode(true);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
width = w / 9f;
height = h / 9f;
// getRect(selX, selY, selRect);
Log.d(TAG, "onSizeChanged: width " + width + ", height " + height);
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
//super.onDraw(canvas);
// canvas.save();
// Draw the background...
Paint background = new Paint();
background.setColor(getResources().getColor(R.color.puzzle_background));
canvas.drawRect(0, 0, getWidth(), getHeight(), background);
// Draw the board...
// Define colors for the grid lines
Paint dark = new Paint();
dark.setColor(getResources().getColor(R.color.puzzle_dark));
Paint hilite = new Paint();
hilite.setColor(getResources().getColor(R.color.puzzle_hilite));
Paint light = new Paint();
light.setColor(getResources().getColor(R.color.puzzle_light));
// Draw the minor grid lines
for (int i = 0; i < 9; i++) {
canvas.drawLine(0, i * height, getWidth(), i * height, light);
canvas.drawLine(0, i * height + 1, getWidth(), i * height + 1,
hilite);
canvas.drawLine(i * width, 0, i * width, getHeight(), light);
canvas.drawLine(i * width + 1, 0, i * width + 1, getHeight(),
hilite);
}
// Draw the major grid lines
for (int i = 0; i < 9; i++) {
if (i % 3 != 0)
continue;
canvas.drawLine(0, i * height, getWidth(), i * height, dark);
canvas.drawLine(0, i * height + 1, getWidth(), i * height + 1,
hilite);
canvas.drawLine(i * width, 0, i * width, getHeight(), dark);
canvas.drawLine(i * width + 1, 0, i * width + 1, getHeight(),
hilite);
}
// // Draw the numbers...
Paint hint = new Paint();
int m;
if (strgettile != null) {
for (m = 0; m < strgettile.length(); m++) {
System.out.println(strgettile.charAt(m));
char convertst = strgettile.charAt(m);
String characterToString = Character.toString(convertst);
if (getorientation.equalsIgnoreCase("Horizontal")) {
canvas.drawText(characterToString, m * width + positionX,
positionY, foreground); // for motion event
hint.setColor(Color.BLACK);
hint.setTextSize(45);
} else {
canvas.drawText(characterToString, positionX, m * height
+ positionY, foreground);
hint.setColor(Color.BLACK);
hint.setTextSize(45);
}
}
//invalidate();
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() != MotionEvent.ACTION_DOWN)
return super.onTouchEvent(event);
// select((int) (event.getX() / width), (int) (event.getY() /
// height));
game.showKeypadOrError(selX, selY);
foreground.setColor(getResources().getColor(R.color.puzzle_foreground));
foreground.setStyle(Style.FILL);
foreground.setTextSize(height * 0.75f);
foreground.setTextScaleX(width / height);
foreground.setTextAlign(Paint.Align.CENTER);
// // Draw the number in the center of the tile
FontMetrics fm = foreground.getFontMetrics();
// // Centering in X: use alignment (and X at midpoint)
// positionX = width / 2;
// // Centering in Y: measure ascent/descent first
// positionY = height / 2 - (fm.ascent + fm.descent) / 2;
positionX = (int) event.getX();
positionY = (int) event.getY() - (fm.ascent + fm.descent) / 2;
// Draw the numbers...
// Define color and style for numbers
// invalidate();
Log.d(TAG, "onTouchEvent: x " + selX + ", y " + selY);
return true;
}
public void setSelectedTile(String tile, String strorientations) {
// TODO Auto-generated method stub
Log.v("getting string in puzzle view ", tile);
strgettile = tile;
getorientation = strorientations;
invalidate();
}
}
Call invalidate() at the end of onDraw.
This function let the onDraw to get called again.

Rotate a sprite in game android

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();
}
}

how to rotate text using canvas in Android

i was draw a pie chart using canvas in android and using the below code i draw a text on each slice of that pie chart (draw arc on path), now i want to draw the text length wise i.e. from center to end of the each slice,so how to rotate the arc using start and sweep angle.
p.addArc(mEventsRect, fStartAngle, fSweepAngle);
mBgPaints.setColor(iTextColor);
canvas.drawTextOnPath(sTextValue, p, fHOffSet, fVOffSet, mBgPaints);
You can try this snippet: (from: http://www.helloandroid.com/tutorials/how-use-canvas-your-android-apps-part-2)
int x = 75;
int y = 185;
paint.setColor(Color.GRAY);
paint.setTextSize(25);
String rotatedtext = "Rotated helloandroid :)";
//Draw bounding rect before rotating text:
Rect rect = new Rect();
paint.getTextBounds(rotatedtext, 0, rotatedtext.length(), rect);
canvas.translate(x, y);
paint.setStyle(Paint.Style.FILL);
canvas.drawText(rotatedtext , 0, 0, paint);
paint.setStyle(Paint.Style.STROKE);
canvas.drawRect(rect, paint);
canvas.translate(-x, -y);
paint.setColor(Color.RED);
canvas.rotate(-45, x + rect.exactCenterX(),y + rect.exactCenterY());
paint.setStyle(Paint.Style.FILL);
canvas.drawText(rotatedtext, x, y, paint);
A bit late to the party but I had to figure this one out and it's a bit simpler than what I found around. You'll already have the x and y for your text, use these to rotate the canvas
canvas.rotate(yourDegrees, x, y)
canvas.drawText(yourText, x, y, yourPaint)
canvas.rotate(-yourDegrees, x, y)
The negative sign negates the first rotation. You could swap it around to rotate in the opposite direction.
You could do this in a loop but the rotation cycle must be done each time either coordinate changes.
may be this will help you,,
here 39.5 is radius,, this will perfectly show result on mdpi screen
protected void onDraw(){
canvas.save();
PointF pf = PointOnCircle(35f, 45f, new PointF(39.5f, 39.5f));
canvas.rotate(-45, pf.x, pf.y);
canvas.drawText("67%", pf.x, pf.y, red);//23.5
canvas.restore();
canvas.save();
PointF pfa = PointOnCircle(35f, 135f, new PointF(39.5f, 39.5f));
canvas.rotate(45, pfa.x, pfa.y);
canvas.drawText("33%", pfa.x, pfa.y, red);//23.5
canvas.restore();
canvas.save();
pfa = PointOnCircle(27.5f, 225f, new PointF(39.5f, 39.5f));
canvas.rotate(-45, pfa.x, pfa.y);
canvas.drawText("45%", pfa.x, pfa.y, red);//23.5
canvas.restore();
canvas.save();
pfa = PointOnCircle(27.5f, 315f, new PointF(39.5f, 39.5f));
canvas.rotate(45, pfa.x, pfa.y);
canvas.drawText("55%", pfa.x, pfa.y, red);//23.5
canvas.restore();}
protected static final PointF PointOnCircle(float radius, float angleInDegrees, PointF origin) {
// Convert from degrees to radians via multiplication by PI/180
float x = (float) (radius * Math.cos(angleInDegrees * Math.PI / 180F)) + origin.x;
float y = (float) (radius * Math.sin(angleInDegrees * Math.PI / 180F)) + origin.y;
return new PointF(x, y);
}
Here's how i finally did it after two days of search with help of this library https://github.com/Ken-Yang/AndroidPieChart
And equations to center text done with help of my friends and alot of search
on MainActivity onCreate or oncreateView if you are using fragments:
PieChart pie = (PieChart) rootView.findViewById(R.id.pieChart);
ArrayList<Float> alPercentage = new ArrayList<Float>();
alPercentage.add(2.0f);
alPercentage.add(8.0f);
alPercentage.add(20.0f);
alPercentage.add(10.0f);
alPercentage.add(10.0f);
alPercentage.add(10.0f);
alPercentage.add(10.0f);
alPercentage.add(10.0f);
alPercentage.add(10.85f);
alPercentage.add(9.15f);
try {
// setting data
pie.setAdapter(alPercentage);
// setting a listener
pie.setOnSelectedListener(new OnSelectedLisenter() {
#Override
public void onSelected(int iSelectedIndex) {
Toast.makeText(getActivity(),
"Select index:" + iSelectedIndex,
Toast.LENGTH_SHORT).show();
}
});
} catch (Exception e) {
if (e.getMessage().equals(PieChart.ERROR_NOT_EQUAL_TO_100)) {
Log.e("kenyang", "percentage is not equal to 100");
}
}
public class PieChart extends View {
public interface OnSelectedLisenter {
public abstract void onSelected(int iSelectedIndex);
}
private OnSelectedLisenter onSelectedListener = null;
private static final String TAG = PieChart.class.getName();
public static final String ERROR_NOT_EQUAL_TO_100 = "NOT_EQUAL_TO_100";
private static final int DEGREE_360 = 360;
private static String[] PIE_COLORS = null;
private static int iColorListSize = 0;
ArrayList<Float> array;
private Paint paintPieFill;
private Paint paintPieBorder;
private Paint paintCenterCircle;
private ArrayList<Float> alPercentage = new ArrayList<Float>();
private int mCenterX = 320;
private int mCenterY = 320;
private int iDisplayWidth, iDisplayHeight;
private int iSelectedIndex = -1;
private int iCenterWidth = 0;
private int iShift = 0;
private int iMargin = 0; // margin to left and right, used for get Radius
private int iDataSize = 0;
private Canvas canvas1;
private RectF r = null;
private RectF centerCircle = null;
private float fDensity = 0.0f;
private float fStartAngle = 0.0f;
private float fEndAngle = 0.0f;
float fX;
float fY;
public PieChart(Context context, AttributeSet attrs) {
super(context, attrs);
PIE_COLORS = getResources().getStringArray(R.array.colors);
iColorListSize = PIE_COLORS.length;
array = new ArrayList<Float>();
fnGetDisplayMetrics(context);
iShift = (int) fnGetRealPxFromDp(30);
iMargin = (int) fnGetRealPxFromDp(40);
centerCircle = new RectF(200, 200, 440, 440);
// used for paint circle
paintPieFill = new Paint(Paint.ANTI_ALIAS_FLAG);
paintPieFill.setStyle(Paint.Style.FILL);
// used for paint centerCircle
paintCenterCircle = new Paint(Paint.ANTI_ALIAS_FLAG);
paintCenterCircle.setStyle(Paint.Style.FILL);
paintCenterCircle.setColor(Color.WHITE);
// used for paint border
paintPieBorder = new Paint(Paint.ANTI_ALIAS_FLAG);
paintPieBorder.setStyle(Paint.Style.STROKE);
paintPieBorder.setStrokeWidth(fnGetRealPxFromDp(3));
paintPieBorder.setColor(Color.WHITE);
Log.i(TAG, "PieChart init");
}
// set listener
public void setOnSelectedListener(OnSelectedLisenter listener) {
this.onSelectedListener = listener;
}
float temp = 0;
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.i(TAG, "onDraw");
float centerX = (r.left + r.right) / 2;
float centerY = (r.top + r.bottom) / 2;
float radius1 = (r.right - r.left) / 2;
radius1 *= 0.5;
float startX = mCenterX;
float startY = mCenterY;
float radius = mCenterX;
float medianAngle = 0;
Path path = new Path();
for (int i = 0; i < iDataSize; i++) {
// check whether the data size larger than color list size
if (i >= iColorListSize) {
paintPieFill.setColor(Color.parseColor(PIE_COLORS[i
% iColorListSize]));
} else {
paintPieFill.setColor(Color.parseColor(PIE_COLORS[i]));
}
fEndAngle = alPercentage.get(i);
// convert percentage to angle
fEndAngle = fEndAngle / 100 * DEGREE_360;
// if the part of pie was selected then change the coordinate
if (iSelectedIndex == i) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
float fAngle = fStartAngle + fEndAngle / 2;
double dxRadius = Math.toRadians((fAngle + DEGREE_360)
% DEGREE_360);
fY = (float) Math.sin(dxRadius);
fX = (float) Math.cos(dxRadius);
canvas.translate(fX * iShift, fY * iShift);
}
canvas.drawArc(r, fStartAngle, fEndAngle, true, paintPieFill);
float angle = (float) ((fStartAngle + fEndAngle / 2) * Math.PI / 180);
float stopX = (float) (startX + (radius/2) * Math.cos(angle));
float stopY = (float) (startY + (radius/2) * Math.sin(angle));
// if the part of pie was selected then draw a border
if (iSelectedIndex == i) {
canvas.drawArc(r, fStartAngle, fEndAngle, true, paintPieBorder);
canvas.drawLine(startX, startY, stopX, stopY, paintPieFill);
canvas.restore();
}
fStartAngle = fStartAngle + fEndAngle;
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// get screen size
iDisplayWidth = MeasureSpec.getSize(widthMeasureSpec);
iDisplayHeight = MeasureSpec.getSize(heightMeasureSpec);
if (iDisplayWidth > iDisplayHeight) {
iDisplayWidth = iDisplayHeight;
}
/*
* determine the rectangle size
*/
iCenterWidth = iDisplayWidth / 2;
int iR = iCenterWidth - iMargin;
if (r == null) {
r = new RectF(iCenterWidth - iR, // top
iCenterWidth - iR, // left
iCenterWidth + iR, // right
iCenterWidth + iR); // bottom
}
if (centerCircle == null) {
// centerCircle=new RectF(left, top, right, bottom);
}
setMeasuredDimension(iDisplayWidth, iDisplayWidth);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// get degree of the touch point
double dx = Math.atan2(event.getY() - iCenterWidth, event.getX()
- iCenterWidth);
float fDegree = (float) (dx / (2 * Math.PI) * DEGREE_360);
fDegree = (fDegree + DEGREE_360) % DEGREE_360;
// get the percent of the selected degree
float fSelectedPercent = fDegree * 100 / DEGREE_360;
// check which pie was selected
float fTotalPercent = 0;
for (int i = 0; i < iDataSize; i++) {
fTotalPercent += alPercentage.get(i);
if (fTotalPercent > fSelectedPercent) {
iSelectedIndex = i;
break;
}
}
if (onSelectedListener != null) {
onSelectedListener.onSelected(iSelectedIndex);
}
invalidate();
return super.onTouchEvent(event);
}
private void fnGetDisplayMetrics(Context cxt) {
final DisplayMetrics dm = cxt.getResources().getDisplayMetrics();
fDensity = dm.density;
}
private float fnGetRealPxFromDp(float fDp) {
return (fDensity != 1.0f) ? fDensity * fDp : fDp;
}
public void setAdapter(ArrayList<Float> alPercentage) throws Exception {
this.alPercentage = alPercentage;
iDataSize = alPercentage.size();
float fSum = 0;
for (int i = 0; i < iDataSize; i++) {
fSum += alPercentage.get(i);
}
if (fSum != 100) {
Log.e(TAG, ERROR_NOT_EQUAL_TO_100);
iDataSize = 0;
throw new Exception(ERROR_NOT_EQUAL_TO_100);
}
}
in your Layout:
<com.example.piecharts.PieChart
android:id="#+id/pieChart"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</com.example.piecharts.PieChart>
This question is pretty old, but I figured I would write a general answer.Here I assume you want to draw your pie chart in the middle of the canvas and that you have your start and seep angles in an array.
x = canvas.getWidth/2 //Horizontal center of canvas view
y = canvas.getHeight/2 //Vertical center of canvas view
canvas.rotate(fStartAngle[i]+ fSweepAngle[i]/2, x ,y ); //Rotates canvas to a line in the middle
//of start and end of arc
canvas.translate(50f,0);//Moves the text a little out of the center of the circle (50f is arbitrary)
paintText.setStyle(Paint.Style.FILL);
canvas.drawText(rotatedtext, x, y, paintText);
//Undo the translations and rotations so that next arc can be drawn normally
canvas.translate(-50f,0);
canvas.rotate(-(temp+ value_degree[i]/2), x ,y );
it's 2023 there might be other answers out there but here is one that is sure to work
//the path where your text/paint will be drawn across
Path path = new Path();
path.addArc(mEventsRect, fStartAngle, fSweepAngle);//add this if you want your path to be drawn across the arc of your sector
//if you are using a text get the width
float textWidth = mTextPaint.measureText("text");
//this is the y co-ordinate your text will start from
int hOffset = 100;
//this is the x co-ordinate your text will start from
int vOffset = 100;
//we will be using the matrix to rotate the bunds of our current path
Matrix matrix = new Matrix();
//we will use this to get the bounds of our current path
RectF bounds = new RectF();
path.computeBounds(bounds,true);
//we are using the matrix to rotate the bound (with is the bound of the path) by 90 degrees
matrix.setRotate(90,bounds.centerX(),bounds.centerY());
the we transform the points in the path using the matrix
path.transform(matrix);
//you can now draw the text on the path
canvas.drawTextOnPath("text", path, hOffset, vOffset , mBgPaints);

Categories

Resources