I am using MPAndroidChart and need to implement a BarChart to display user scores with user profile pictures.
Can anyone help me to customize the BarChart ?
Thanks
I solved my problem by using a custom BarChartRenderer.
Below is the source code of custom BarRenderer :
import android.graphics.Bitmap;
import android.graphics.Canvas;
import com.github.mikephil.charting.animation.ChartAnimator;
import com.github.mikephil.charting.buffer.BarBuffer;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider;
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet;
import com.github.mikephil.charting.renderer.BarChartRenderer;
import com.github.mikephil.charting.utils.ViewPortHandler;
/**
* Created by hemantchhonkar on 21-02-2018.
*/
public class BarChartImageRenderer extends BarChartRenderer {
private final Bitmap[] imageToRender;
public BarChartImageRenderer(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler, Bitmap[] imageToRender) {
super(chart, animator, viewPortHandler);
this.imageToRender=imageToRender;
}
#Override
protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) {
super.drawDataSet(c, dataSet, index);
drawBarImages(c, dataSet, index);
}
protected void drawBarImages(Canvas c, IBarDataSet dataSet, int index) {
BarBuffer buffer = mBarBuffers[index];
float left; //avoid allocation inside loop
float right;
float top;
float bottom;
for (int j = 0; j < buffer.buffer.length * mAnimator.getPhaseX(); j += 4) {
left = buffer.buffer[j];
right = buffer.buffer[j + 2];
top = buffer.buffer[j + 1];
bottom = buffer.buffer[j + 3];
float x = (left + right) / 2f;
if (!mViewPortHandler.isInBoundsRight(x))
break;
if (!mViewPortHandler.isInBoundsY(top)
|| !mViewPortHandler.isInBoundsLeft(x))
continue;
BarEntry entry = dataSet.getEntryForIndex(j / 4);
float val = entry.getY();
final Bitmap scaledBarImage = scaleBarImage(buffer,imageToRender[j / 4]);
int starWidth = scaledBarImage.getWidth();
int starOffset = starWidth / 2;
drawImage(c, scaledBarImage, x - starOffset, top);
}
}
private Bitmap scaleBarImage(BarBuffer buffer, Bitmap image) {
float firstLeft = buffer.buffer[0];
float firstRight = buffer.buffer[2];
int firstWidth = (int) Math.ceil(firstRight - firstLeft);
return Bitmap.createScaledBitmap(image, firstWidth, firstWidth, false);
}
protected void drawImage(Canvas c, Bitmap image, float x, float y) {
if (image != null) {
c.drawBitmap(image, x, y, null);
}
}
}
Then set the renderer into the chart in your activity/fragment:
//Create and array of images(this array size should match the size of dataset)
Bitmap[] starBitmap = new Bitmap[]{ BitmapFactory.decodeResource(getResources(), R.drawable.my_dp),
BitmapFactory.decodeResource(getResources(), R.drawable.profile_pic),
BitmapFactory.decodeResource(getResources(), R.drawable.my_dp),
BitmapFactory.decodeResource(getResources(), R.drawable.profile_pic),
BitmapFactory.decodeResource(getResources(), R.drawable.my_dp),
BitmapFactory.decodeResource(getResources(), R.drawable.profile_pic),
BitmapFactory.decodeResource(getResources(), R.drawable.my_dp),
BitmapFactory.decodeResource(getResources(), R.drawable.profile_pic),
BitmapFactory.decodeResource(getResources(), R.drawable.my_dp),
BitmapFactory.decodeResource(getResources(), R.drawable.my_dp)};
//Create the object of the chart renderer and set into the chart
barChart2.setRenderer(new BarChartImageRenderer(barChart2, barChart2.getAnimator(), barChart2.getViewPortHandler(), starBitmap));
Screenshot of the rendered chart
Related
I made this project from this open source https://github.com/uptechteam/MotionViews-Android
I'm actually creating a Memegenerator app,
The problem is when I resize the height/width of one of the bitmap inside canvas
The bitmap also moving aside, But it actually should not move from x y axis while I scroll the seekbar, Thats the problem.
This is the ImageEntity class
public ImageEntity(#NonNull Layer layer,
#NonNull Bitmap bitmap,
#IntRange(from = 1) int canvasWidth,
#IntRange(from = 1) int canvasHeight) {
super(layer, canvasWidth, canvasHeight);
this.bitmap = bitmap;
layer.widthSize(bitmap.getWidth());
layer.heightSize(bitmap.getHeight());
updateIMGEntity(false);
}
public void updateIMGEntity() {
updateIMGEntity(true);
}
private void updateIMGEntity(boolean moveToPreviousCenter) {
// save previous center
PointF oldCenter = absoluteCenter();
Bitmap newBitmap = Bitmap.createScaledBitmap(bitmap, layer.getWidth(),
layer.getHeight(), false);
// recycle previous bitmap (if not reused) as soon as possible
if (bitmap != null && bitmap != newBitmap && !bitmap.isRecycled()) {
bitmap.recycle();
}
this.bitmap = newBitmap;
float width = bitmap.getWidth();
float height = bitmap.getHeight();
#SuppressWarnings("UnnecessaryLocalVariable")
float widthAspect = 1.0F * canvasWidth / height;
// for text we always match text width with parent width
this.holyScale = widthAspect;
// initial position of the entity
srcPoints[0] = 0; srcPoints[1] = 0;
srcPoints[2] = width; srcPoints[3] = 0;
srcPoints[4] = width; srcPoints[5] = height;
srcPoints[6] = 0; srcPoints[7] = height;
srcPoints[8] = 0; srcPoints[8] = 0;
if (moveToPreviousCenter) {
// move to previous center
moveCenterTo(oldCenter);
}
}
#Override
public void drawContent(#NonNull Canvas canvas, #Nullable Paint drawingPaint) {
//updateMatrix();
canvas.drawBitmap(bitmap, matrix, drawingPaint);
//release();
}
Please someone help me.
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;
}
Why does this AI class doesn't draw to the canvas?
package com.dragon.game;
import android.graphics.*;
import com.dragon.game.Game.*;
import java.util.*;
public class AI {
public static Bitmap a;
int x, y, dirX, dirY;
int width, height;
long start, stop;
boolean fg = true;
SurView ov;
Random r = new Random();
public AI(SurView surView, Bitmap ai){
a = ai;
ov = surView;
width = a.getWidth();
height = a.getHeight();
x = Remote.wt / 4;
y = Remote.wt / 4;
}
public void update(){
x++;
}
public void onDraw(Canvas canvas){
if(fg){
x = Remote.wt / 4;
y = Remote.wt / 4;
fg = false;
}
update();
Rect src = new Rect(0, 0, width, height);
Rect dst = new Rect(x, y, x + Remote.pw, y + Remote.pw);
canvas.drawBitmap(a, src, dst, null);
}
}
The reason is that you have initialized Bitmap a inside Public AI method and then you are using it inside onDraw method , you cannot do this , either you have to initialize it globally or you have to give a reference to it
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've some sample code that comes with Android that distorts a bitmap image(Bitmapmesh.java). I'm wanting a circle placed on my image that gives a fisheye effect. I'm new to android and especially graphics, is it possible to create this effect in the bitmapmesh sample?
I'm not sure where to start with this so any pointers would be appreciated. Can anyone give me a high level view of what's involved, eg i'd like to place a circle on the image firstly. i've placed buttons over images before that seem to float, this was done by using a relative layout then adding child buttons. what i'm tring to do now is different and will probably involve calling some onDraw method? i also have an algorithm that does the distortion, i'm just not sure how to apply this to the image.
Below is the bitmapmesh code. Can anyone talk me through where to start, even if it's just placing the circle on the image first, then i can tackle implementing the effect.
thanks mat
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import android.content.Context;
import android.graphics.;
import android.os.Bundle;
import android.os.Environment;
import android.view.;
import android.util.FloatMath;
public class BitMapFishEye extends GraphicsActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}
private static class SampleView extends View {
private static final int WIDTH = 20;
private static final int HEIGHT = 20;
private static final int COUNT = (WIDTH + 1) * (HEIGHT + 1);
private final Bitmap mBitmap;
private final float[] mVerts = new float[COUNT*2];
private final float[] mOrig = new float[COUNT*2];
private final Matrix mMatrix = new Matrix();
private final Matrix mInverse = new Matrix();
private File tempFile;
private byte[] imageArray;
private 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.beach);*/
tempFile = new File(Environment.getExternalStorageDirectory().
getAbsolutePath() + "/"+"image.jpg");
imageArray = new byte[(int)tempFile.length()];
try{
InputStream is = new FileInputStream(tempFile);
BufferedInputStream bis = new BufferedInputStream(is);
DataInputStream dis = new DataInputStream(bis);
int i = 0;
while (dis.available() > 0) {
imageArray[i] = dis.readByte();
i++;
}
dis.close();
} catch (Exception e) {
e.printStackTrace();
}
BitmapFactory.Options bfo = new BitmapFactory.Options();
bfo.inSampleSize = 5;
mBitmap = BitmapFactory.decodeByteArray(imageArray, 0, imageArray.length, bfo);
float w = mBitmap.getWidth();
float h = mBitmap.getHeight();
// construct our mesh
int index = 0;
for (int y = 0; y <= HEIGHT; y++) {
float fy = h * y / HEIGHT;
for (int x = 0; x <= WIDTH; x++) {
float fx = w * x / WIDTH;
setXY(mVerts, index, fx, fy);
setXY(mOrig, index, fx, fy);
index += 1;
}
}
mMatrix.setTranslate(10, 10);
mMatrix.invert(mInverse);
}
#Override protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFFCCCCCC);
canvas.concat(mMatrix);
canvas.drawBitmapMesh(mBitmap, WIDTH, HEIGHT, mVerts, 0,
null, 0, null);
}
private void warp(float cx, float cy) {
final float K = 10000;
float[] src = mOrig;
float[] dst = mVerts;
for (int i = 0; i < COUNT*2; i += 2) {
float x = src[i+0];
float y = src[i+1];
float dx = cx - x;
float dy = cy - y;
float dd = dx*dx + dy*dy;
float d = FloatMath.sqrt(dd);
float pull = K / (dd + 0.000001f);
pull /= (d + 0.000001f);
// android.util.Log.d("skia", "index " + i + " dist=" + d + " pull=" + pull);
if (pull >= 1) {
dst[i+0] = cx;
dst[i+1] = cy;
} else {
dst[i+0] = x + dx * pull;
dst[i+1] = y + dy * pull;
}
}
}
private int mLastWarpX = -9999; // don't match a touch coordinate
private int mLastWarpY;
#Override public boolean onTouchEvent(MotionEvent event) {
float[] pt = { event.getX(), event.getY() };
mInverse.mapPoints(pt);
int x = (int)pt[0];
int y = (int)pt[1];
if (mLastWarpX != x || mLastWarpY != y) {
mLastWarpX = x;
mLastWarpY = y;
warp(pt[0], pt[1]);
invalidate();
}
return true;
}
}
}