Unable to draw Bitmaps - android

im building a game, when i use OnDraw my app do work, but i saw people in youtube drawing without it so im trying to draw some bitmaps without an OnDraw in a SurfaceView.
thank you for your help :)
public Graphics(Game activity) {
super(activity);
this.activity = activity;
left = BitmapFactory.decodeResource(getResources(), R.drawable.left_button);
right = BitmapFactory.decodeResource(getResources(), R.drawable.right_button);
shootUp = BitmapFactory.decodeResource(getResources(), R.drawable.shoot_up_button);
shootSide = BitmapFactory.decodeResource(getResources(), R.drawable.shoot_side_button);
this.setBackgroundResource(R.drawable.background);
paint = new Paint();
ninja = new Ninja(screenW * 5 / 12, upY, screenW / 18, buttonH, getResources());
createEnemies();
resize();
resume();
}
public void draw() {
if (getHolder().getSurface().isValid()) {
Canvas canvas = getHolder().lockCanvas();
canvas.drawBitmap(ninja.main, ninja.x, ninja.y, paint);
canvas.drawBitmap(left,leftX,leftY,paint);
canvas.drawBitmap(right,rightX,rightY,paint);
canvas.drawBitmap(shootUp,upX,upY,paint);
canvas.drawBitmap(shootSide,sideX,sideY,paint);
System.out.println("drawing");
getHolder().unlockCanvasAndPost(canvas);
}
}

Related

How to Auto capture without any user interface ("Button") inside an overlay using camera2 by google?

I am using google camera2 api and was able to successfully make a GREEN rectangular overlay using surface view. Now the challenge is to capture a preview with out button only when the object comes inside rectangular overlay after touching the four corners of the the overlay. Tried alot but still no success. The whole code is from google sample camera2 so presenting only the part where changes were made.
(https://github.com/googlesamples/android-Camera2Basic):
#Override
public void onViewCreated(final View view, Bundle savedInstanceState) {
view.findViewById(R.id.picture).setOnClickListener(this);
view.findViewById(R.id.info).setOnClickListener(this);
mTextureView = view.findViewById(R.id.texture);
final SurfaceView surfaceView = view.findViewById(R.id.surfaceView);
surfaceView.setVisibility(View.VISIBLE);
surfaceView.setZOrderOnTop(true);
SurfaceHolder mHolder = surfaceView.getHolder();
mHolder.setFormat(PixelFormat.TRANSPARENT);
mHolder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder)
{
Canvas canvas = holder.lockCanvas();
if (canvas == null) {
Log.e(TAG, "Cannot draw onto the canvas as it's null");
} else {
int w = canvas.getWidth();
int h = canvas.getHeight();
int outerFillColor = 0x33000000;
float radius = 10.0f;
RectF rect = new RectF(100, 100, w - 100, h - 100);
// first create an off-screen bitmap and its canvas
Bitmap bitmap = null;
if (android.os.Build.VERSION.SDK_INT >=
android.os.Build.VERSION_CODES.O) {
bitmap = Bitmap.createBitmap(w, h,
Bitmap.Config.ARGB_8888);
}
Canvas auxCanvas = new Canvas(bitmap);
// then fill the bitmap with the desired outside color
Paint paint = new Paint(Paint.FAKE_BOLD_TEXT_FLAG);
paint.setColor(outerFillColor);
paint.setStyle(Paint.Style.FILL);
auxCanvas.drawPaint(paint);
// then punch a transparent hole in the shape of the rect
paint.setXfermode(new
PorterDuffXfermode(PorterDuff.Mode.CLEAR));
auxCanvas.drawRoundRect(rect, radius, radius, paint);
// then draw the white rect border (being sure to get rid of the xfer
mode!)
paint.setXfermode(null);
paint.setColor(Color.GREEN);
paint.setStyle(Paint.Style.STROKE);
auxCanvas.drawRoundRect(rect, radius, radius, paint);
// finally, draw the whole thing to the original canvas
canvas.drawBitmap(bitmap, 0, 0, paint);
holder.unlockCanvasAndPost(canvas);
}
}
Check this link..
In this section image captures in onClick event. You can capture image without click by placing the capture code where you want
Show rectangle in camera preview and crop image within it using android camera2

To draw transparent line over image in imageview

I have made a paint app in which i have used ImageView in layout to show image that can be taken from camera or gallery.I want to draw transparent line over image so that image can be seen after drawing.please help me.
Thanks for support
I have used the code to make draw line transparent is :
myPaint.setAlpha(50);
My code is:
protected void onDraw(Canvas canvas) {
Toast.makeText(PaintScreen.this, "onDraw is called", Toast.LENGTH_SHORT).show();
// myPaint.setAlpha(100);
canvas.drawBitmap(PaintScreen.this.localBitmap, 0,0,null);
// canvas.drawPath(myPath, paintBlur);
canvas.drawPath(myPath, myPaint); Log.i("OnDRAWING", "REACH ON DRAW"); }
public class CustomView extends ImageView {
private float mX, mY;
public CustomView(Context context) {
super(context);
localBitmap = Bitmap.createBitmap(myBitmap.getWidth(), myBitmap.getHeight(), Config.ARGB_8888);
myCanvas = new Canvas(localBitmap);
myPaint = new Paint(); setPaintForDraw(paintcolor, false, 30);
setFocusable(true);
setFocusableInTouchMode(true); myPath = new Path();
}
}
private void setPaintForDraw(int color, boolean eraseMode, int brushSize) {
//myPaint.setAlpha(100);
myPaint.setAntiAlias(true);
myPaint.setDither(true);
myPaint.setStyle(Paint.Style.STROKE);
myPaint.setColor(color);
myPaint.setStrokeCap(Paint.Cap.ROUND);
myPaint.setStrokeJoin(Paint.Join.ROUND);
myPaint.setStrokeWidth(brushSize);
myPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
if (eraseMode) {
myPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
else { myPaint.setXfermode(null); }
}
see this thread How to maintain multi layers of ImageViews and keep their aspect ratio based on the largest one?, here you can use multiple Draeable layers that are drawn over the image
First, you have to check that your Bitmap is mutable. If it is not, make a copy of it. And here is how you can draw a line on your image:
Bitmap copyBmp = yourBMP.copy(Bitmap.Config.ARGB_8888, true); //Copy if yourBMP is not mutable
Canvas canvas = new Canvas(copyBmp);
Paint paint = new Paint();
paint.setAlpha(50); //Put a value between 0 and 255
paint.setColor(Color.GRAY); //Put your line color
paint.setStrokeWidth(5); //Choose the width of your line
canvas.drawLine(startX, startY, stopX, stopY, paint); //Set the coordinates of the line
Now, if you display copyBmp, you should see a line drawn over it.

Android SurfaceView filling background with a picture

I'm a beginner/intermediate java-student and I just started working with android 2D programming. I'm working in surfaceView and want to set a backgroud, but the problem is I dont know how to make the background fill 100% of the screen, this is how I draw my background:
public GFXSurface(Context context) {
super(context);
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.roadtest);
getHolder().addCallback(this);
mThread = new ViewThread(this);
}
public void doDraw(Canvas canvas){
canvas.drawBitmap(mBitmap, 0, 0, null);
}
Something like that should do the trick, place it after obtaining your bitmap
float scale = (float)mBitmap.getHeight()/(float)getHeight();
int newWidth = Math.round(mBitmap.getWidth()/scale);
int newHeight = Math.round(mBitmap.getHeight()/scale);
Bitmap scaledBitmap = Bitmap.createScaledBitmap(mBitmap, newWidth, newHeight, true);
then draw it like you already do :)

Android - Touch to erase portions of foreground ImageView to expose background View

So I've been struggling with this for a better part of a day. Suppose I have a custom ImageView that I want to overlay over a background View (both within a RelativeLayout), which when touched, it erases portions of the View's source bitmap like an erase tool in MS Paint, exposing the View below it. I've checked pretty much all of the threads (like this one) and they suggest to use PorterDuff SRC Mode in the Paint object as well as creating a Canvas out out the ARGB_8888 shadow copy of the source bitmap to apply the masking.
Also, I can't set the source of the overlay ahead of time since I have to download it over the network so that the ImageView's scale type takes care of the scaling for me.
Every time I override onDraw, when I apply the erase on the IV's Bitmap, it unveils a black background instead of the view below it, even though I set the background to transparent. So I'm at my last rope as to what to do in order to unveil the background view.
Here's what I have so far:
view constructor:
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
paint.setColor(Color.TRANSPARENT);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(STROKE_WIDTH);
paint.setAntiAlias(true);
overrode setImageBitmap to set my canvas from my re-configed source bitmap:
public void setImageBitmap(Bitmap bitmap){
super.setImageBitmap(bitmap);
Drawable bd = getDrawable();
if(bd == null){
return;
}
Bitmap fullSizeBitmap = ((BitmapDrawable) bd).getBitmap();
overlay = fullSizeBitmap.copy(Config.ARGB_8888, true);
c2 = new Canvas(overlay);
}
onDraw method:
protected void onDraw(Canvas canvas) {
/*
* Override paint call by re-drawing the view's Bitmap first, then overlaying our path on top of it
*/
Drawable bd = getDrawable();
if(bd == null){
return;
}
Bitmap fullSizeBitmap = ((BitmapDrawable) bd).getBitmap();
if(fullSizeBitmap != null && c2 != null){
canvas.drawColor(Color.TRANSPARENT);
c2.drawBitmap(fullSizeBitmap, 0, 0, null);
c2.drawPath(path, paint);
canvas.drawBitmap(overlay, 0, 0, null);
}
}
I know this is a really old question but here is what I did to fix a similar problem I had. Maybe it helps someone in the future.
From API level 11 and up you have to specify this piece of code for your ImageView to unveil the image in the back and not a black area.
if (Build.VERSION.SDK_INT >= 11) {
imageview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
This helped me displaying the back image successfully
Can you try this solution it will help you with the erasing images in android on touch .. Or download a demo example
public class MainActivity extends Activity {
Bitmap bp;
Canvas bitmapCanvas;
DrawView drawImg;
LinearLayout ln1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ln1 = (LinearLayout) findViewById(R.id.ln1);
drawImg = new DrawView(this);
ln1.addView(drawImg);
}
public class DrawView extends View implements View.OnTouchListener {
private int x = 0;
private int y = 0;
Bitmap bitmap;
Path circlePath;
Paint circlePaint;
private final Paint paint = new Paint();
private final Paint eraserPaint = new Paint();
public DrawView(Context context){
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
// Set background
this.setBackgroundColor(Color.CYAN);
bp = BitmapFactory.decodeResource(getResources(), R.drawable.bg);
// Set bitmap
bitmap = Bitmap.createBitmap(320, 480, Bitmap.Config.ARGB_8888);
bitmapCanvas = new Canvas();
bitmapCanvas.setBitmap(bitmap);
bitmapCanvas.drawColor(Color.TRANSPARENT);
bitmapCanvas.drawBitmap(bp, 0, 0, null);
circlePath = new Path();
circlePaint = new Paint();
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.BLUE);
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeJoin(Paint.Join.MITER);
circlePaint.setStrokeWidth(4f);
// Set eraser paint properties
eraserPaint.setAlpha(0);
eraserPaint.setStrokeJoin(Paint.Join.ROUND);
eraserPaint.setStrokeCap(Paint.Cap.ROUND);
eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
eraserPaint.setAntiAlias(true);
}
#Override
public void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, 0, 0, paint);
bitmapCanvas.drawCircle(x, y, 30, eraserPaint);
canvas.drawPath(circlePath, circlePaint);
}
public boolean onTouch(View view, MotionEvent event) {
x = (int) event.getX();
y = (int) event.getY();
bitmapCanvas.drawCircle(x, y, 30, eraserPaint);
circlePath.reset();
circlePath.addCircle(x, y, 30, Path.Direction.CW);
int ac=event.getAction();
switch(ac){
case MotionEvent.ACTION_UP:
Toast.makeText(MainActivity.this, String.valueOf(x), Toast.LENGTH_SHORT).show();
circlePath.reset();
break;
}
invalidate();
return true;
}
}
}

Android, canvas: How do I clear (delete contents of) a canvas (= bitmaps), living in a surfaceView?

In order to make a simple game, I used a template that draws a canvas with bitmaps like this:
private void doDraw(Canvas canvas) {
for (int i=0;i<8;i++)
for (int j=0;j<9;j++)
for (int k=0;k<7;k++) {
canvas.drawBitmap(mBits[allBits[i][j][k]], i*50 -k*7, j*50 -k*7, null); } }
(The canvas is defined in "run()" / the SurfaceView lives in a GameThread.)
My first question is how do I clear (or redraw) the whole canvas for a new layout?
Second, how can I update just a part of the screen?
// This is the routine that calls "doDraw":
public void run() {
while (mRun) {
Canvas c = null;
try {
c = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder) {
if (mMode == STATE_RUNNING)
updateGame();
doDraw(c); }
} finally {
if (c != null) {
mSurfaceHolder.unlockCanvasAndPost(c); } } } }
Draw transparent color with PorterDuff clear mode does the trick for what I wanted.
Canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
How do I clear (or redraw) the WHOLE canvas for a new layout (= try at the game) ?
Just call Canvas.drawColor(Color.BLACK), or whatever color you want to clear your Canvas with.
And: how can I update just a part of the screen ?
There is no such method that just update a "part of the screen" since Android OS is redrawing every pixel when updating the screen. But, when you're not clearing old drawings on your Canvas, the old drawings are still on the surface and that is probably one way to "update just a part" of the screen.
So, if you want to "update a part of the screen", just avoid calling Canvas.drawColor() method.
Found this in google groups and this worked for me..
Paint clearPaint = new Paint();
clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawRect(0, 0, width, height, clearPaint);
This removes drawings rectangles etc. while keeping set bitmap..
use the reset method of Path class
Path.reset();
I tried the answer of #mobistry:
canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
But it doesn't worked for me.
The solution, for me, was:
canvas.drawColor(Color.TRANSPARENT, Mode.MULTIPLY);
Maybe some one has the same problem.
mBitmap.eraseColor(Color.TRANSPARENT);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawColor(Color.TRANSPARENT, Mode.MULTIPLY);
please paste below code on surfaceview extend class constructor.............
constructor coding
SurfaceHolder holder = getHolder();
holder.addCallback(this);
SurfaceView sur = (SurfaceView)findViewById(R.id.surfaceview);
sur.setZOrderOnTop(true); // necessary
holder = sur.getHolder();
holder.setFormat(PixelFormat.TRANSPARENT);
xml coding
<com.welcome.panelview.PanelViewWelcomeScreen
android:id="#+id/one"
android:layout_width="600px"
android:layout_height="312px"
android:layout_gravity="center"
android:layout_marginTop="10px"
android:background="#drawable/welcome" />
try above code...
Here is the code of a minimal example showing that you always have to redraw every pixel of the Canvas at each frame.
This activity draw a new Bitmap every second on the SurfaceView, without clearing the screen before.
If you test it, you will see that the bitmap is not always written to the same buffer, and the screen will alternate between the two buffers.
I tested it on my phone (Nexus S, Android 2.3.3), and on the emulator (Android 2.2).
public class TestCanvas extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new TestView(this));
}
}
class TestView extends SurfaceView implements SurfaceHolder.Callback {
private TestThread mThread;
private int mWidth;
private int mHeight;
private Bitmap mBitmap;
private SurfaceHolder mSurfaceHolder;
public TestView(Context context) {
super(context);
mThread = new TestThread();
mBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon);
mSurfaceHolder = getHolder();
mSurfaceHolder.addCallback(this);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
mWidth = width;
mHeight = height;
mThread.start();
}
#Override
public void surfaceCreated(SurfaceHolder holder) {/* Do nothing */}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mThread != null && mThread.isAlive())
mThread.interrupt();
}
class TestThread extends Thread {
#Override
public void run() {
while (!isInterrupted()) {
Canvas c = null;
try {
c = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder) {
c.drawBitmap(mBitmap, (int) (Math.random() * mWidth), (int) (Math.random() * mHeight), null);
}
} finally {
if (c != null)
mSurfaceHolder.unlockCanvasAndPost(c);
}
try {
sleep(1000);
} catch (InterruptedException e) {
interrupt();
}
}
}
}
}
For me calling Canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR) or something similar would only work after I touch the screen. SO I would call the above line of code but the screen would only clear after I then touched the screen. So what worked for me was to call invalidate() followed by init() which is called at the time of creation to initialize the view.
private void init() {
setFocusable(true);
setFocusableInTouchMode(true);
setOnTouchListener(this);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(6);
mCanvas = new Canvas();
mPaths = new LinkedList<>();
addNewPath();
}
Erasing on Canvas in java android is similar erasing HTML Canvas via javascript with globalCompositeOperation. The logic was similar.
U will choose DST_OUT (Destination Out) logic.
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
Note: DST_OUT is more useful because it can erase 50% if the paint color have 50% alpha. So, to clear completely to transparent, the alpha of color must be 100%. Apply paint.setColor(Color.WHITE) is recommended. And make sure that the canvas image format was RGBA_8888.
After erased, go back to normal drawing with SRC_OVER (Source Over).
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
Update small area display literally will need to access graphic hardware, and it maybe not supported.
The most close for highest performance is using multi image layer.
With the following approach, you can clear the whole canvas or just a part of it.
Please do not forget to disable Hardware acceleration since PorterDuff.Mode.CLEAR doesn’t work with hardware acceleration and finally call setWillNotDraw(false) because we override the onDraw method.
//view's constructor
setWillNotDraw(false);
setLayerType(LAYER_TYPE_SOFTWARE, null);
//view's onDraw
Paint TransparentPaint = new Paint();
TransparentPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawRect(0, 0, width, height, TransparentPaint);
Don't forget to call invalidate();
canvas.drawColor(backgroundColor);
invalidate();
path.reset();
I found my solution.
PaintView class:
public void clear() {
mPath.reset();
mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
paths.clear();
}
And MainActivity:
clear_canvas_.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
paintView.clear();
}
});
Your first requirement, how to clear or redraw whole canvas - Answer - use canvas.drawColor(color.Black) method for clearing the screen with a color of black or whatever you specify .
Your second requirement, how to update part of the screen - Answer - for example if you want to keep all other things unchanged on the screen but in a small area of screen to show an integer(say counter) which increases after every five seconds. then use canvas.drawrect method to draw that small area by specifying left top right bottom and paint. then compute your counter value(using postdalayed for 5 seconds etc., llike Handler.postDelayed(Runnable_Object, 5000);) , convert it to text string, compute the x and y coordinate in this small rect and use text view to display the changing counter value.
Try to remove the view at onPause() of an activity and add onRestart()
LayoutYouAddedYourView.addView(YourCustomView);
LayoutYouAddedYourView.removeView(YourCustomView);
The moment you add your view, onDraw() method would get called.
YourCustomView, is a class which extends the View class.
In my case, I draw my canvas into linearlayout.
To clean and redraw again:
LinearLayout linearLayout = findViewById(R.id.myCanvas);
linearLayout.removeAllViews();
and then, I call the class with the new values:
Lienzo fondo = new Lienzo(this,items);
linearLayout.addView(fondo);
This is the class Lienzo:
class Lienzo extends View {
Paint paint;
RectF contenedor;
Path path;
ArrayList<Items>elementos;
public Lienzo(Context context,ArrayList<Items> elementos) {
super(context);
this.elementos=elementos;
init();
}
private void init() {
path=new Path();
paint = new Paint();
contenedor = new RectF();
paint.setStyle(Paint.Style.FILL);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
contenedor.left = oneValue;
contenedor.top = anotherValue;
contenedor.right = anotherValue;
contenedor.bottom = anotherValue;
float angulo = -90; //starts drawing at 12 o'clock
//total= sum of all element values
for (int i=0;i<elementos.size();i++){
if (elementos.get(i).angulo!=0 && elementos.get(i).visible){
paint.setColor(elementos.get(i).backColor);
canvas.drawArc(contenedor,angulo,(float)(elementos.get(i).value*360)/total,true,paint);
angulo+=(float)(elementos.get(i).value*360)/total;
}
} //for example
}
}
In my case, creating canvas every time worked for me, even though it's not memory-friendly
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.image);
imageBitmap = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), bm.getConfig());
canvas = new Canvas(imageBitmap);
canvas.drawBitmap(bm, 0, 0, null);
I had to use a separate drawing pass to clear the canvas (lock, draw and unlock):
Canvas canvas = null;
try {
canvas = holder.lockCanvas();
if (canvas == null) {
// exit drawing thread
break;
}
canvas.drawColor(colorToClearFromCanvas, PorterDuff.Mode.CLEAR);
} finally {
if (canvas != null) {
holder.unlockCanvasAndPost(canvas);
}
}
The following worked for me:
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SCREEN);
Just call
canvas.drawColor(Color.TRANSPARENT)

Categories

Resources