I am trying to draw on the surface view using the Camera2 API sample code from Google. But for some reason, the drawing disappears after the camera preview starts. I am really confused as to why this is happening.
private void drawonSurfaceView(){
Paint paint = new Paint();
SurfaceHolder surfaceHolder= mOverlay.getHolder();
if(surfaceHolder.getSurface().isValid()) {
Canvas canvas = surfaceHolder.lockCanvas();
//... actual drawing on canvas
paint.setStyle(Paint.Style.FILL);
int x = canvas.getWidth();
int y = canvas.getHeight();
paint.setColor(Color.GREEN);
paint.setStyle(Paint.Style.STROKE);
Rect rect = new Rect(50, 50, x-300, y-300);
canvas.drawRect(rect, paint );
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
I Have placed the code inside the setUpCameraOutputs() method.
That's true, you cannot lock the canvas of a preview surface for drawing. Some while ago, the SurfaceView used for camera preview required special settings (see What does SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS means?), but since API 11, this happens automagically.
You can always draw on a transparent view that is above the camera preview, but this is not the recommended solution. Much better, use a SurfaceTexture for your camera live stream, and draw with OpenGL in the 2D virtual world that includes that texture. To have your drawings synchronized with the camera stream, you should hide the preview texture and draw the camera frames yourself using the same callback that you use to feed the image processing algorithm.
Related
This problem seemed very obvious for me to solve, but whatever I try, it doesn't work. What I'm trying to do is to incorporate a mini-version of my PlayScreen in a ScrollPane as a tutorial where you can read text and try it out immediately.
Because I didn't find any better solution to add this to the Table inside the ScrollPane, I edited the draw() method of the PlayScreen to take the ScrollPane.getScrollPercentY() and offset the camera of the PlayScreen accordingly.
What I want to do now is to only render only part of the viewport that would be normally visible in the real game. Subsequently, I want to be able to control the size and position of this "window".
I also want to be able to resize and move the content, while cutting off the edges that are not visible to the camera. This is what I tried inside the PlayScreenDraw:
public void draw(final float yOffset,
final int xTiles,
final int yTiles) {
view.getCamera().position.y = yTiles / 2f - yOffset * yTiles / HEIGHT; // HEIGHT = 800
view.getCamera().position.x = xTiles / 2f;
view.setWorldSize(xTiles, yTiles); //Do i even need to change the world size?
b.setProjectionMatrix(view.getCamera().combined);
b.begin();
...
b.end();
view.update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
}
What this gives me, in terms of the picture above, is this
How do I need to change the viewport and/or the camera? Btw., this is how i set the two up:
cam = new OrthographicCamera();
cam.setToOrtho(false, WIDTH, HEIGHT); // WIDTH = 8, HEIGHT = 16
batch.setProjectionMatrix(cam.combined);
view = new FitViewport(WIDTH, HEIGHT, cam);
The Pixmap class can help you achieve what you want since you stated that you wanted to "cut off" the parts outside of the green selection box.
You need to render what the camera sees to an FBO and then get the pixmap from the FBO itself.
Framebuffer Objects are OpenGL Objects, which allow for the creation of user-defined Framebuffers. With them, one can render to non-Default Framebuffer locations, and thus render without disturbing the main screen.
-- OpenGL wiki
// Construct an FBO and keep a reference to it. Remember to dispose of it.
FrameBuffer fbo = new FrameBuffer(Format.RGBA8888, width, height, false);
public void render() {
//Start rendering to the fbo.
fbo.begin();
//From the camera's perspective.
batch.setProjectionMatrix(camera.combined);
batch.begin();
//Draw whatever you want to draw with the camera.
batch.end();
// Finished drawing, get pixmap.
Pixmap pixmap = ScreenUtils.getFrameBufferPixmap(0, 0, width, height);
//Stop drawing to your fbo.
fbo.end();
}
After getting the pixmap you can iterate through the pixels and set the alpha of the pixels outside your green selection window to 0 making them invisible or "cutting them off"
I basically have an ImageView which got modified with Canvas and looks like a cirlce. (original image had the dimensions of a square (500x500))
Image what the starting position looks like:
http://imgur.com/bvXdLoP
(red is transparent and got removed with help of the Canvas method)
The animation should take aroud 1000 miliseconds and during this time step for step restore to the original picture. So in the end there should be a sqaure again.
In other words the cut off corners, which are the differnce between a square and a circle (and red marked in the image), get step for step restored in around 1000 milliseconds, with a sort of spreading looking animation.
Don't really have any clue on how to achieve this, so I can just share the Canvas method I used to cut off the corners (if it helps :X):
private Bitmap createCircleImage(Bitmap bitmap) {
Bitmap bmp;
bmp = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Bitmap.Config.ARGB_8888);
BitmapShader shader = new BitmapShader(bitmap,
BitmapShader.TileMode.CLAMP,
BitmapShader.TileMode.CLAMP);
float radius = bitmap.getWidth() / 2f;
Canvas canvas = new Canvas(bmp);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(shader);
canvas.drawCircle(bitmap.getWidth()/2,bitmap.getHeight()/2,bitmap.getHeight()/2, paint);
return bmp;
}
Appreciate any help,
thank you!
There are many ways to achieve such behavior. For example you can create custom view and override its onDraw method such as
#Override
public void onDraw(Canvas canvas) {
canvas.drawCircle(viewWidth/2, viewHeight/2, currentRadius, paint);
}
and then you can just increase the radius little by little and invalidate the view.Since view is by default will clip on its clipBounds (you can only draw inside viewidth x viewheight rectangle unless you set it otherwise) you will get the effect that you want. And then you can tweak the interpolation to achieve smoother and more natural animation.
note: a bitmap shader is attached to the paint (you already know chow to create it). I don't include it in the code, since you shouldn't initialize it inside onDraw method for performance reason.
I need a little start-up aid. I want to animate a circle, that is 'flying' vertically, when the user swipes crabwise. What do i have to do, after creating a circle on a canvas?
Bitmap bg = Bitmap.createBitmap(480, 800, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas (bg);
canvas.drawCircle(canvas.getWidth()/2, (float) (canvas.getHeight()/1.8), 13, paint);
You can use Android Animation like in this tutorial, or "Canvas" animation like in that.
I have a sprite that I move around the world; it has its velocity increased based on a constant acceleration when the user touches the screen. I also move the camera with this sprite; but I also have a BG image that needs to stay still on the screen so the camera moves with the exact same velocity and acceleration as the background image so that it seems that the background is still. However, I see a slight out of sync between the camera and the background image; the background should stay still but it doesn't :
#Override
public void render () {
batch.setProjectionMatrix(camera.combined);
world_velocity += acceleration;
back.setPosition(back.getX(), back.getY() + world_velocity);
camera.position.y += world_velocity;
camera.update();
}
How can I sync the BG image with the camera so that the BG image stays still? NOTE : If I use constant velocity (no updates based on acceleration ) there is no issue.
I am making a finger painting app. Using Paths I have created a canvas for users to draw lines on as if finger painting. I have saved the paths and reload them when the device is rotated to landscape mode. However with the new screen dimensions part of the drawing is now off screen.
What is the best way of adjusting the points in my path to stretch the image across the new screen dimensions so the user doesn't loose any of their drawing off screen?
I solved my issue like this:
if(getWidth() > getHeight())
{
Matrix scaleMatrix = new Matrix();
RectF rectF = new RectF();
p.computeBounds(rectF, true);
scaleMatrix.setScale(1.6f, .6f,0,0);
p.transform(scaleMatrix);
}
canvas.drawPath(p, paint);
Where p is the path.