I'm trying to 'take a photo' of both the camera preview, and an overlayed GLSurfaceView.
I have the camera preview element working, via camera.takePicture() and PictureCallback(), but now need to either include the GLSurfaceView elements, or capture the current screen seperately and merge the two bitmaps into one file.
I have tried to grab an image from the surfaceView using the code below, but this just results in a null bitmap.
public Bitmap grabImage() {
this.setDrawingCacheEnabled(true);
Bitmap b = null;
try {
b = this.getDrawingCache(true);
if (b==null) {
b = this.getDrawingCache(true);
}
} catch (Exception e) {
e.printStackTrace();
}
this.setDrawingCacheEnabled(false);
return b;
}
I would appreciate any thoughts/ snippets on this. Many thanks in advance.
I've done something similar and it was a bit convoluted but not too terrible.
In my case I'm using camera preview frame which I decode to a bitmap. Then get a canvas from that bitmap pass it to call to draw() on the views (surfaceview or otherwise) that I want drawn over top of the picture.
Bitmap bm;
MySurfaceViewImpl sv;
Canvas c = new Canvas(bm);
sv.draw(c);
You will need to use your own View implementation to handle the fact that the canvas size is going to change and you'll need to rescale things between the calls to draw() that happen in the normal running of your app and the when you call it manually as the canvas from the picture size is almost certainly going to be different than what's being drawn to the screen.
Also, the primary reason I'm using preview frames rather than captured pictures is due to memory limits. Very few phones support smallish sized pictures but all support reasonable sizes for preview frames. Getting a full size camera picture into a bitmap is probably too much memory. On devices with less than 24MB heap, I'm ok with about a 600 x 480 image and about 4 views that get drawn on top of that but it gets tight.
In your case, you'll probably need to scale the bitmap down to be able to pass a canvas from it to a view.
Good luck!
Related
I'm trying build a camera app in android using camera API.
I follow the instructions: https://examples.javacodegeeks.com/android/core/hardware/camera-hardware/android-camera-example/ and I have built one camera app
Now i need to display preview camera inside a frame and take picture include the frame
Please see the two pictures below:
Frame in resource folder : https://i.stack.imgur.com/AaNIQ.png
The photo I want to achieve: https://i.stack.imgur.com/UWXcq.jpg
Anyone can give me suggestions or if possible give me a simple example?
I searched about this but didn't get proper example.
Thank you so much.
Half of the answer can be found here: https://stackoverflow.com/a/47240902/192373.
As for keeping the same layout for full-res picture capture, first of all make sure that you keep preview- and picture- sizes in sync. This does not mean that they must be the same, but the aspect ratios should. Some devices have weird effects when the aspect ratio changes to capture a photo.
Next, you capture the jpeg as usual, unpack it to bitmap, overlay with the frame bitmap (you may need a hi-res version of your frame here) and combine the two (based on https://stackoverflow.com/a/4863551/192373):
public Bitmap combineImages(Bitmap picture, Bitmap frame) {
Bitmap bmp = Bitmap.createBitmap(picture.getWidth(), picture.getHeight(), Bitmap.Config.ARGB_8888);
Canvas comboImage = new Canvas(bmp);
comboImage.drawBitmap(picture, 0f, 0f, null);
comboImage.drawBitmap(frame, 0f, 0f, null);
return bmp;
}
I am developing an application,where i am doing video call(videos are from Opentok).but when i try to take screenshot of my screen,videos are displaying black.
i used following link but dint work
Taking screenshot programmatically doesnt capture the contents of surfaceVIew
i have attached my screenshot screenshot is shown in imageview which is in black colour
i used following code to take screenshot but not working
public Bitmap getScreenShot() {
View rootView = getWindow().getDecorView().findViewById(android.R.id.content);
View screenView = rootView.getRootView();
screenView.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(screenView.getDrawingCache());
// bitmap=Bitmap.createScaledBitmap(bitmap,50,70,false);
Log.e("new_bitmap","--->"+bitmap);
screenView.setDrawingCacheEnabled(false);
return bitmap;
}
plz help me to get solution
Thanks.
Grafika's "texture from camera" activity demonstrates manipulation of incoming video data with GLES. After rendering you can get the pixels with glReadPixels(). The performance of glReadPixels() can vary significantly between devices and different use cases. EglSurfaceBase#saveFrame() shows how to capture to a Bitmap and save as PNG.
I am creating an android application and am working with canvas bitmaps (specifically the Samsung SPen SDK). I currently have the functionality I want working working, but the way the loading is implemented makes the run-time too long.
What I have:
Saving: I am saving the canvas as a bitmap and splitting this bitmap into X smaller bitmaps of a specific size (saving only the sections with writing in them). There is no problem with the efficiency of this section.
Loading::
I then take the X number of smaller bitmaps and combine them to reform the original bitmap using canvas.drawBitmap(imgs[x][y], xCoordinate, yCoordinate, null) for all of the images that have writing in them(imgs[][] = array of bitmaps).
I then display this in the foreground of the canvas using the setclearImageBitmap(BitmapName) function in the SCanvasView class. This works fine besides the fact that loading the one large image into the foreground is taking ~90% of the run time.
private void loadCanvasImage(){
Bitmap bmOverlay = Bitmap.createBitmap(mSCanvas.getWidth(), mSCanvas.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmOverlay);
int yCo = 0;
for(int yCount=0; yCount
}
Question:
I am wondering if there is a more efficient way to do this. Potentially by implementing this idea:
By adding multiple bitmaps to the canvas view (preferably foreground) at specific x,y coordinates (This may make it faster since the smaller bitmaps without writing on them will not have to be displayed).
Another method I failed to implement was to set the SCanvasView to the canvas containing the one large bitmap that I recreated. I did this by trying to override the onDraw(Canvas) method, and passing the canvas result of canvas.drawBitmap(imgs[x][y], xCoordinate, yCoordinate, null)
I'm trying to dynamically create images in android by taking an existing Bitmap and removing the centre of it in order to make a "cropped" version. The resulting image's height would naturally be smaller than the original, something like the attached example.
I've got a rough way of doing this by creating two new Bitmaps from the original, one containing the top of the image above the crop section (e.g. the android's head in the example) and the other containing the remaining image below the crop section (the android's feet) using the Bitmap.createBitmap(source, x, y, width, height) method, then drawing both of these bitmaps onto a canvas of a size equal to the original image minus the removed space.
This feels a bit clunky, and as I could be calling this method several times a second, it seems wasteful to create two bitmaps each time.
I was wondering if there was a more efficient way of doing this. Something like drawing the original Bitmap onto a canvas using a Path with it's Paint's xfermode set to a
new PorterDuffXfermode(Mode.DST_OUT) in order to cut out the portion of the image I wish to delete. But this seems to clear that area and not shrink the image down i.e. it leaves a big empty gap in the Android's middle.
Any suggestions greatly appreciated!
Why do you create two bitmaps? You only need to create one bitmap and then do canvas.drawBitmap() twice.
Bitmap bmpOriginal;
Bitmap bmpDerived = Bitmap.create(...);
Canvas canvas = new Canvas(bmpDerived);
canvas.drawBitmap(bmpOriginal, rectTopSrc, rectTopDst, null);
canvas.drawBitmap(bmpOriginal, rectBottomSrc, rectBottomDst, null);
Done.
For my live wallpaper I use the following code (called by a Runnable) to draw each frame. Each time it is called, I fill the current canvas with a solid color and draw a background bitmap (bg_image has been resized to perfectly fit the screen). I then call drawParticles(c), which simply uses c.drawCircle(...) a bunch of times drawing particles all over the canvas.
In the live wallpaper preview mode, this code works great. However, when I actually set this as my live wallpaper it flickers and seems to not clear the canvas before drawing. Let me 'splain:
Frame 1: The bitmap is drawn and circles are overlaid.
Frame 2: The bitmap is drawn and circles are overlaid (based on my rough understanding, there are two canvases that are drawn on and posted alternately for efficiency).
Frame 3: The canvas is not being cleared! This frame includes the new positions of each drawn circle as well as the circles from Frame 1!.
Frame 4: Includes the new positions of each drawn circle as well as the circles from Frame 2!
The end effect is that the circles leave "trails" all over the screen that flicker between (I believe) the two alternating canvases. Why, based on my code below, isn't my canvas being cleared each frame? Again, this works fine during preview mode but not when it is actually set as my live wallpaper. It's also worth noting that this flickering problem only occurs if I am drawing a bitmap; if the background is just a solid color, this problem never arises.
final SurfaceHolder holder = getSurfaceHolder();
Canvas c = null;
try {
c = holder.lockCanvas();
if (c != null) {
c.drawColor(Color.BLACK);
c.drawBitmap(bg_image, 0, 0, null);
fluid.drawParticles(c);
}
} finally {
if (c != null) holder.unlockCanvasAndPost(c);
}
mHandler.removeCallbacks(mDrawRunnable);
mHandler.postDelayed(mDrawRunnable, 1000/targetFramerate -(System.currentTimeMillis() - mLastTime));
}
My guess is that your animation is too complex to keep up with your frame rate. If you slow the frame rate way down, do you still have the problem? Also, if you are drawing an opaque background bitmap at each frame, you do not need to paint the screen black first--that just wastes time, and limits your maximum frame rate.
I'm guessing that the problem does not happen in preview mode because more of the phone's resources are focused on you, whereas once the wallpaper is set, more stuff is going on in the background.