Android - Draw on top of an image - android

b2.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
setContentView(R.layout.new_main);
String editTextStr = text.getText().toString();
Toast msg = Toast.makeText(getBaseContext(),"/sdcard/Stored_Images/" + editTextStr + ".jpg", Toast.LENGTH_LONG);
msg.show();
Bitmap bmp = BitmapFactory.decodeFile("/sdcard/Stored_Images/" + editTextStr + ".jpg");
ImageView img = (ImageView) findViewById(R.id.ImageView01);
img.setImageBitmap(bmp);
}
});
The code above displays an image on the screen that is saved on the sd card.
Canvas c = holder.lockCanvas();
c.drawARGB(255,0,0,0);
onDraw(c);
holder.unlockCanvasAndPost(c);
This code creates a canvas to draw on (black screen).
I want to be able to combine the two to set/display an image as the canvas so that I can draw on it. So if i take a picture of someones face, I want to be able to display that image so that I can draw a mustache or something on it.

You are probably better off creating the canvas, adding the bitmap image to it and then handling the user touch/drawing from there.
Bitmap bmp = BitmapFactory.decodeFile("/sdcard/Stored_Images/" + editTextStr + ".jpg");
mCanvas = new Canvas(bmp);
then for the drawing... sound like you have that figured out, but if not you can check out the fingerPaint samples from the api demos that demonstrate drawing on a canvas (which you would have your image on at that point.)

You may customize the ImageView and made drawing on your image in onDraw(Canvas canvas)
For Example:
In your Activity:
1)create Bitmap from the image
2)set the Bitmap to customized ImageView
a) create object for customized ImageView
MyImageView view =new MyImageView(this);
b) set the bitmap
view.setImageBitmap(bmp);
MyImageView.java:
class MyImagView extends ImageView{
//constructor
public MyImageView(Context context){
}
//onDraw()
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
//drawlines where ever you want using canvas.drawLine()
}
#Override
public void setImageBitmap(Bitmap bm)
{
super.setImageBitmap(bm);
}
}

Related

Android Eraser removes background image how to avoid it

I am trying to erase contents of Canvas without erasing the Background Image. I just want to remove drawable content i.e lines, colors etc from canvas. But currently background image also gets erased. Basically what I tried so far is that I created a frame layout and place an ImageView over another ImageView, considering that if image on top is erased the one below which is exact copy will not be erased.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="310dp">
<com.almaarijsoft.kanvas.DrawingView
android:id="#+id/drawing"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#color/smoky" />
<com.almaarijsoft.kanvas.DrawingView
android:id="#+id/drawingViewBackground"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_gravity="bottom|center"
android:background="#color/smoky" />
</FrameLayout>
and then
private Paint drawPaint;
//usage
//set erase true or false
public void setErase(boolean isErase) {
erase = isErase;
if (erase) {
drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
} else{
drawPaint.setXfermode(null);
}
}
this is how i am setting image to canvas
public static void setCanvasFromGalleryImage(Intent data, DrawingView drawView, DrawingView drawView2, Activity activity) {// DrawingView is class extended from View
if (data != null) {
// our BitmapDrawable for the thumbnail
BitmapDrawable bmpDrawable = null;
// try to retrieve the image using the data from the intent
Cursor cursor = activity.getContentResolver().query(data.getData(), null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
String fileSrc = cursor.getString(idx);
bitmap = BitmapFactory.decodeFile(fileSrc); // load
bitmap = Bitmap.createScaledBitmap(bitmap, 750, 600, false);
drawView.setImage(bitmap);
drawView2.setImage(bitmap);
drawView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); // IMPORTANT set hardware acceleration off with this line. Otherwise your view's background will NOT be transparent
drawView.bringToFront(); //
} else {
bmpDrawable = new BitmapDrawable(activity.getResources(), data.getData().getPath());
drawView.setImage(bitmap);
}
} else {
MyAppUtil.getToast(activity.getApplicationContext(), "Cancelled");
}
}
EDIT
// inside Drawview following implementation is added by me.
private Canvas drawCanvas;
//start new drawing
public void setImage(Bitmap bitmap) {
drawCanvas.drawBitmap(bitmap, 0, 0, null);
invalidate();
}
loading image from source(gallery) and setting it as background(as bitmap) on canvas
You can try to modify the setImage of DrawingView like this:
public void setImage(Bitmap bitmap) {
Drawable drawable = new BitmapDrawable(getResources(), bitmap);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
this.setBackground(drawable);
} else {
this.setBackgroundDrawable(drawable);
}
}
If you set the bitmap as background when you use setErase(true) only the content drawn on the canvas will be erased.
And also you don't need need multiple DrawingView but only one.
I was able to get your described behavior just by extending ImageView and calling the super method in onDraw.
public class DrawingView extends ImageView
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
canvas.drawPath(drawPath, drawPaint);
}
Set the "background" via the ImageView's methods:
drawView.setImageBitmap(bitmap);

Draw a line on ImageView set by Picasso

I am trying to figure out how to simply draw a line on an image that is being set in Picasso. I found that if I simply set the image, given a URI, with Picasso and try to draw paint to it using the following:
canvas = new Canvas(bitmap);
image.draw(canvas);
topEdge = new Paint();
topEdge.setColor(context.getResources().getColor(R.color.blue));
topEdge.setStrokeWidth(5);
canvas.drawLine(c1.getX(), c1.getY(), c2.getX(), c2.getY(), topEdge);
Then I get a crash saying that the bitmap needs to be mutable first. So I added this above that code:
Bitmap workingBitmap = ((BitmapDrawable) image.getDrawable()).getBitmap();
Bitmap mutableBitmap = workingBitmap.copy(Bitmap.Config.ARGB_8888, true);
And then create the canvas with new Canvas(mutableBitmap) instead. This removed the crash, however nothing is being drawn. I believe this is because my Picasso is setting the image before, so now I need to reset Picasso with this new mutable bitmap. The problem is this code is in the onSuccess() callback for Picasso. What can I do to allow Paint to be drawn on an image through Picasso?
just follow the steps below:
Write your own class extends the class Transformation like below:
class DrawLineTransformation implements Transformation {
#Override
public String key() {
// TODO Auto-generated method stub
return "drawline";
}
#Override
public Bitmap transform(Bitmap bitmap) {
// TODO Auto-generated method stub
synchronized (DrawLineTransformation.class) {
if(bitmap == null) {
return null;
}
Bitmap resultBitmap = bitmap.copy(bitmap.getConfig(), true);
Canvas canvas = new Canvas(resultBitmap);
Paint paint = new Paint();
paint.setColor(Color.BLUE);
paint.setStrokeWidth(10);
canvas.drawLine(0, resultBitmap.getHeight()/2, resultBitmap.getWidth(), resultBitmap.getHeight()/2, paint);
bitmap.recycle();
return resultBitmap;
}
}
}
2、Add the Transformation to RequestCreator created with Picasso.load() function like below:
Picasso picasso = Picasso.with(getApplicationContext());
DrawLineTransformation myTransformation = new DrawLineTransformation();
picasso.load("http://www.baidu.com/img/bdlogo.png").transform(myTransformation).into(imageview);
That's all steps you need to do , just enjoy!

How to set the Image to appear behind the current canvas?

I am using canvas to draw the Different colour.
I want to set the Image that should be appear as the background of the canvas. And while i am drawing on that image it should be drawn on the Image not behind the image.
Right now with below code it is drawing behind the Image.
#Override
public void run() {
Canvas canvas = null;
while (_run){
try{
canvas = mSurfaceHolder.lockCanvas(null);
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
commandManager.executeAll(canvas);
} finally {
Bitmap kangoo = BitmapFactory.decodeResource(getResources(),R.drawable.icon);
canvas.drawBitmap(kangoo, 130, 100, null);
mSurfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
So what should i have to do to make drawing on the image ???
As you redrawing the canvas in While(1) loop you can put the statement canvas.drawBitmap(kangoo, 130, 100, null) at the top inside the loop so that its drawn again and again then do you painting over top of it.
If you want to save the drawn part to you do something like converting the Canvas to bitmap like:
Bitmap bitmapToBeDrawnFromNextTime = Bitmap.createBitmap( canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
Canvas imageCanvas = new Canvas(bitmapToBeDrawnFromNextTime);
imageCanvas.draw(canvas);
No one have giving me answer.
But i got solution, I have to set the image after clearing canvas.
code:
#Override
public void run() {
//Canvas canvas = null;
while (_run){
try{
canvas = mSurfaceHolder.lockCanvas(null);
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
Bitmap kangoo = BitmapFactory.decodeResource(getResources(),R.drawable.icon);
canvas.drawBitmap(kangoo, 130, 100, null);
commandManager.executeAll(canvas);
} finally {
mSurfaceHolder.unlockCanvasAndPost(canvas);
}
}

Drawing to a created Bitmap from onDraw()

I'm trying to draw to a Bitmap so I can put my custom view inside an imageView.The code within the onDraw method is:
public void onDraw(Canvas canvas) {
Bitmap drawGraph = Bitmap.createBitmap(canvas.getWidth(),canvas.getHeight(),Bitmap.Config.ARGB_8888);
canvas.setBitmap(drawGraph);
canvas.drawBitmap(drawGraph, 0, 0, bgPaint);
My problem is that if I try to use a Bitmap in this way, I just get a black screen. I know that the rest of my code works as it displays if I don't try to draw to a bitmap.
If I comment out the line
canvas.setBitmap(drawGraph);
Then everything works perfectly, so this is the problem but I dont know why.
where am I going wrong?
Turns out I did have to create a second canvas. My working code is below just for anyone who might need it:
public void onDraw(Canvas canvas) {
Canvas singleUseCanvas = new Canvas();
drawGraph = Bitmap.createBitmap(canvas.getWidth(),canvas.getHeight(),Bitmap.Config.ARGB_8888);
singleUseCanvas.setBitmap(drawGraph);
canvas.drawBitmap(drawGraph, 100, 100, bgPaint);
I think is the canvas and canvas2 dichotomy. Try to use only canvas2 (the parameter) to draw.
AFAIK The most efficient way is to override drawable setters.
#Override
public void setImageBitmap(Bitmap bm) {
bmp = bm;
}
#Override
public void setImageDrawable(Drawable drawable) {
try {
bmp = ((BitmapDrawable) drawable).getBitmap();
} catch (Exception e){
log(e.toString());
}
}

Use canvas for the GestureOverlayView

I have a GestureOverlayView on which the user can draw gesture stokes, I want to save these strokes in a PNG file.
I have tried the public void draw (Canvas canvas) ,and I get a PNG file as an output of my following code, but I was not able get any strokes in that, can any one help me with this....
thanks in advance.
My code
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.create_gesture);
bitmap= Bitmap.createBitmap(12, 12, Bitmap.Config.RGB_565);
can=new Canvas(bitmap);
GestureOverlayView overlay = (GestureOverlayView) findViewById(R.id.gestures_overlay);
overlay.addOnGestureListener(new GesturesProcessor());
overlay.draw(can);
}
Code to save the strokes as PNG
bm=mGesture.toBitmap(313, 343, 8,3);
can.drawBitmap(bm, 0, 0, null);
File file = new File(Environment.getExternalStorageDirectory()
+ File.separator+"Strokes");
out = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.PNG,100, out);
Toast.makeText(this, "PNG file Created "+mGesture, Toast.LENGTH_LONG).show();
Modification as specified by Dr.J
Paint paint=new Paint();
Bitmap bitmap=Bitmap.createBitmap(412, 412, Bitmap.Config.ARGB_4444);
Canvas can=new Canvas(bitmap);
Path path = new Path();
paint.setColor(255);
.
.
.
.
private class GesturesProcessor implements GestureOverlayView.OnGestureListener {
public void onGestureEnded(final GestureOverlayView overlay, MotionEvent event) {
new Thread(new Runnable() {
public void run() {
mGesture = overlay.getGesture();
try{
path=overlay.getGesturePath();
can.drawPath(path, paint);
can.drawBitmap(bitmap, 0, 0, null);
File file = new File(Environment.getExternalStorageDirectory()
+ File.separator+"Strokes");
out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG,100, out);
Toast.makeText(getBaseContext(), "Created gesture 12:56 section active "+mGesture, Toast.LENGTH_LONG).show();
}catch(Exception exp){exp.printStackTrace();}
}
}).start();
}
You need to capture the gestures from the user directly, the Canvas given to you from Draw(Canvas canvas) is for you to draw on, it doesn't hold data for you to capture from.
You should use:
public Path getGesturePath (Path path)
Then if you want to save it use the Canvas's drawPath AndDev Docs
. It can be drawn with canvas.drawPath(path, paint), either filled or stroked (based on the paint's Style), or it can be used for clipping or to draw text on a path.

Categories

Resources