So here is what my app is doing:
I have a camera preview.
I have an overlay image on top of this camera preview.
When I capture the image I combine both the captured image and the overlay.
I display the combined imaged on an imageview.
However, the overlay is way too big when it's displayed on the imageview.
The overlay image is displayed perfectly when on the camera preview. It looks like the canvas.drawBitmap is scaling it somehow but I want to keep the original size.
IMPORTANT: This works fine on a Samsung S3, the issue occurs when using a Moto G.
Here's some of the code:
protected PictureCallback mPicture = new PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
cameraPreview.getCamera().stopPreview();
Bitmap cameraBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
Matrix matrix = new Matrix();
matrix.preScale(-1, 1);
matrix.postRotate(90);
cameraBitmap = Bitmap.createBitmap(cameraBitmap, 0, 0, cameraBitmap.getWidth(), cameraBitmap.getHeight(), matrix, true);
//Get the overlay image
ImageView imageview = (ImageView)findViewById(R.id.imageView2);
imageview.setDrawingCacheEnabled(true);
imageview.buildDrawingCache();
Bitmap overlayImage = Bitmap.createBitmap(imageview .getDrawingCache());
Bitmap mutableBitmap = cameraBitmap.copy(Bitmap.Config.ARGB_8888, true);
//Here is where I combine both images by drawing the overlay onto the captured bitmap
Canvas canvas = new Canvas(mutableBitmap);
canvas.drawBitmap(overlayImage , 0 , canvas.getHeight() - overlayImage.getHeight(), paint);
//Here is where i set the image so that you can view the finished result - the combined image - but the overlay image is way too big!
ImageView capturedView = (ImageView)findViewById(R.id.capturedImageView);
capturedView.setImageBitmap(mutableBitmap);
Solved it! The solution was to forget about the canvas altogether and just get a screenshot of capturedView since it already had the captured image and the overlay on it.
Also, I had make sure to bring the overlay to front before getting the screenshot of capturedView.
// This is the imageview where I first display the
// image which was captured from the camera.
capturedView.bringToFront();
// This is the overlay imageview,
// by bringing this in front of the capturedView
// I can take a screenshot of it and get both the captured
// image and the overlay image.
imageview.bringToFront();
capturedView.setDrawingCacheEnabled(true);
capturedView.buildDrawingCache();
// And now you have a bitmap with both images combined :-)
combinedBitmap = capturedView.getDrawingCache();
Related
I'm drawing a rectangle over a camera preview and i want to crop that specific region covered by the rectangle and display it in ImageView. I managed to crop the the Bitmap by using :
Bitmap croppedBmp = Bitmap.createBitmap(imageOriginal, 50, 100, 1000, 550);
Code to draw the rectangle :
Rect rect = new Rect(50, 100,1000, 550);
as you can see i'm using the same parameters but i'm not getting the desired result. What i'm missing here ?. Thank you in advance.
Camera Preview :
Cropped Bitmap displayed in new activity :
What I'm trying to do is get an image after it be zoomed or moved but it's not working, the image is always the original one.
My code (not working):
mImageView.setDrawingCacheEnabled(true);
mImageView.buildDrawingCache();
Bitmap bmBg = mImageView.getDrawingCache();
bmBg = Bitmap.createBitmap(bmBg, 0, 0, bmBg.getWidt(), bmBg.getHeight());
mImageView.destroyDrawingCache();
I have one image image 1 and one is coming from server that is image 2 i am trying to draw second one just at the center of the first. as result i want single image like in pic .
This should do what you're looking for:
The backgroundBitmap variable would be your image1 and the bitmapToDrawInTheCenter would be your image2.
public void centerImageInOtherImage()
{
Bitmap backgroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
Bitmap bitmapToDrawInTheCenter = BitmapFactory.decodeResource(getResources(), R.drawable.ic_action_search);
Bitmap resultingBitmap = Bitmap.createBitmap(backgroundBitmap.getWidth(), backgroundBitmap.getHeight(), backgroundBitmap.getConfig());
Canvas canvas = new Canvas(resultingBitmap);
canvas.drawBitmap(backgroundBitmap, new Matrix(), null);
canvas.drawBitmap(bitmapToDrawInTheCenter, (backgroundBitmap.getWidth() - bitmapToDrawInTheCenter.getWidth()) / 2, (backgroundBitmap.getHeight() - bitmapToDrawInTheCenter.getHeight()) / 2, new Paint());
ImageView image = (ImageView)findViewById(R.id.myImage);
image.setImageBitmap(resultingBitmap);
}
Courtesy : Draw text/Image on another Image in Android
Drawing images over each other is fairly simple with Canvas. Canvas basically acts as the drawing board to draw text/Image. You just need to construct a canvas with the first Image and then draw the second Image at the center as shown below
/* This ImageOne will be used as the canvas to draw an another image over it. Hence we make it mutable using the copy API
as shown below
*/
Bitmap imageOne = BitmapFactory.decodeResource(getResources(), R.drawable.imageOne).copy(Bitmap.Config.ARGB_8888,true);
// Decoding the image two resource into a Bitmap
Bitmap imageTwo= BitmapFactory.decodeResource(getResources(), R.drawable.imageTwo);
// Here we construct the canvas with the specified bitmap to draw onto
Canvas canvas=new Canvas(imageOne);
/*Here we draw the image two on the canvas using the drawBitmap API.
drawBitmap takes in four parameters
1 . The Bitmap to draw
2. X co-ordinate to draw from
3. Y co ordinate to draw from
4. Paint object to define style
*/
canvas.drawBitmap(imageTwo,(imageOne.getWidth())/2,(imageOne.getHeight())/2,new Paint());
imageView.setImageBitmap(imageOne);
I want to capture an image from my camera and crop the captured image at specified co-ordinates then draw it on the middle of another image. The following code doesn't crash, but the captured image is screwing up, since the image stretches wrong.
Where am I going wrong?
Merry X'mas!
//Get the bottom image Bitmap
Bitmap bottomImage = BitmapFactory.decodeResource(getResources(), SelectDollarActivity.selectedImageId);
//Get the captured image Bitmap
Bitmap capturedImage = BitmapFactory.decodeFile(CaptureImage.cImagePath) ;
//************ CROP THE CAPTURED IMAGE *******************
int targetBitmapWidth = bottomImage.getWidth();
int targetBitmapHeight = bottomImage.getHeight() ;
//create a Bitmap with specified width & height
Bitmap clippedBitmap = Bitmap.createBitmap(targetBitmapWidth, targetBitmapHeight, Bitmap.Config.ARGB_8888);
//Construct a canvas with the specified bitmap to draw into.
Canvas canvas = new Canvas(clippedBitmap);
//************** cropping process goes HERE.........
//Create a new rectangle with the specified coordinates
RectF rectf = new RectF(left, top, right, bottom);
//Create an empty path
Path path = new Path();
//Add a closed oval contour to the path
path.addOval(rectf, Path.Direction.CW);
//Intersect the current clip with the specified path : CROPPING
canvas.clipPath(path);
canvas.drawBitmap(capturedImage, null, new Rect(0, 0, targetBitmapWidth, targetBitmapHeight), null);
//******** MERGING PROCESS *******************
//Construct a canvas with the specified bitmap to draw into.
Canvas combo = new Canvas(bottomImage);
// Then draw the second on top of that
combo.drawBitmap(clippedBitmap, 0f, 0f, null);
// bottomImage is now a composite of the two. so, display the bottom image
//************** DISPLAY THE MERGED IMAGE ****************
((ImageView)findViewById(R.id.billImage)).setImageBitmap(bottomImage);
Documentation states that drawBitmap accepts two more arguments, width and heights. In your code,
combo.drawBitmap(clippedBitmap, 0f, 0f, null);
only has the positioning.
You will need to set a few more arguments of course, but it should work :D
My application has a "photobooth" feature which will allow the user to take a picture with the camera and at the same time show an overlay image on top of the camera view. After the picture is taken, i need to save what the user saw while taking the picture to the filesystem.
I have experienced 1 big problem while developing a solution to this: capturing an image with the compatible dimensions in which i can attach an overlay image to resulting in what the user saw while taking the picture.
It seems i cannot capture an image from the camera with defined dimensions(i have to basically pick from a list of them). Some phones only can produce certain dimensions.
Since i cannot choose the size of the captured image, it seems as though i will be required to include many different sizes of the overlay image, and attach the best match to the captured image. I can't just slap any old overlay on top of the camera image and make it look right.
Questions:
Am i over-complicating this "camera image + overlay image creation" process?
What suggestions do you have in completing this task without the need of including several different sizes overlay images?
Edit:
Here is my solution(brief). Please realize this is not a perfect and maybe not most efficient way to do this, but it works. Some things may be unnecessary/redundant but whatever!
Notes:
this doesn't work too great on tablet devices.
the overlay image needs to be rotated to be in landscape mode(even though you will be taking the image holding the phone in portrait)
overlay size is 480x320
you need to force the activity to landscape mode while taking the picture(now the overlay looks like its portrait!)
i add the overlay image view using addContentView(overlayImageView, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
...
final Camera.PictureCallback jpegCallback = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap mutableBitmap = null;
try {
//for a PORTRAIT overlay and taking the image holding the phone in PORTRAIT mode
mutableBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options).copy(Bitmap.Config.RGB_565, true);
Matrix matrix = new Matrix();
int width = mutableBitmap.getWidth();
int height = mutableBitmap.getHeight();
int newWidth = overlayImage.getDrawable().getBounds().width();
int newHeight = overlayImage.getDrawable().getBounds().height();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
matrix.postScale(scaleWidth, scaleHeight);
matrix.postRotate(90);
Bitmap resizedBitmap = Bitmap.createBitmap(mutableBitmap, 0, 0, mutableBitmap.getWidth(), mutableBitmap.getHeight(), matrix, true);
finalBitmap = resizedBitmap.copy(Bitmap.Config.RGB_565, true);
Canvas canvas = new Canvas(finalBitmap);
Bitmap overlayBitmap = BitmapFactory.decodeResource(getResources(), overlay);
matrix = new Matrix();
matrix.postRotate(90);
Bitmap resizedOverlay = Bitmap.createBitmap(overlayBitmap, 0, 0, overlayBitmap.getWidth(), overlayBitmap.getHeight(), matrix, true);
canvas.drawBitmap(resizedOverlay, 0, 0, new Paint());
canvas.scale(50, 0);
canvas.save();
//finalBitmap is the image with the overlay on it
}
catch(OutOfMemoryError e) {
//fail
}
}
}
I think this is a question of how you manipulate your overlays. You can crop it according to the captured image size and resize it to fit, preserving its ratio. You can place the overlay, by comparing its ratio to the backround ratio, to its optimal position.
I would keep overlays big enough, with a wide border (bleed), to easily size them to an image using filters to draw it with good qaulity. I guess overlays are something which you would design and have transparent parts, like an image of a clown without a face so the user can snap somebody elses face into it?