Capture image on current drawing state - android

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();

Related

Android creating bitmap from two bitmaps bottom bitmap not visible

I have a list of items where I am displaying a bitmap next to the item's name. This bitmap is to be created from 2 images, I have a background image with a smaller foreground image to add on top of the background.
I am seeing that the background image appears to not be present on some of my rows in my list. It is not consistent when and which row has the combined bitmap without the background. It is not always the same row where the combined bitmap does not have the background and it is not always the first or not always the last row where the bitmap does not have the background. And sometimes the whole list has every row with the correct image.
The image below is a mockup showing my issue.
My code for creating the combined bitmap is as follows.
Bitmap combinedBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas combinedCanvas = new Canvas(combinedBitmap);
// Add the first bitmap to the canvas (this is my background and this is what appears to be
// missing on some rows in my list on some occasions)
combinedCanvas.drawBitmap(backgroundBitmap, 0, 0, null);
// my second smaller image, on top of the first image but 1 pixel in
// from the left and 20 pixels down from the top
combinedCanvas.drawBitmap(foregroundBitmap, 1, 20, null);
return combinedBitmap;
Note: My backgroundBitmap is generated from a Drawable using the following code
Bitmap backgroundBitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
drawable.getMinimumHeight(),
Bitmap.Config.ARGB_8888);
backgroundBitmap.setDensity(resources.getDisplayMetrics().densityDpi);
Canvas canvas = new Canvas(backgroundBitmap);
drawable.draw(canvas);
Any suggestions of what I have wrong or even where to look to try and resolve this would be greatly appreciated.
EDIT: I have tested adding a colour to the background of my combinedCanvas to try and see where the image generation is going wrong by adding the following code
// TEMP: fill the canvas in red for now so I can see which combinedBitmaps are missing
// the background image
combinedCanvas.drawColor(Color.RED);
Now the rows which do not have the background are coloured in red. This indicates that the code above to create the combined canvas is somehow not adding the backgroundBitmap. I have checked and my background image is not null for every row in my list.
This method works fine for me. It's in C# (Xamarin), you'll have to translate it to Java I'm afraid.
public static Bitmap CombineImages(Bitmap background, Bitmap foreground)
{
int width = background.Width, height = background.Height;
Bitmap cs = Bitmap.CreateBitmap(width, height, Bitmap.Config.Argb8888);
Canvas comboImage = new Canvas(cs);
background = Bitmap.CreateScaledBitmap(background, width, height, true);
comboImage.DrawBitmap(background, 0, 0, null);
int top = (int)(0.05 * height);
int left = (int)(width - (foreground.Width + (width * 0.05)));
comboImage.DrawBitmap(foreground, left, top, null);
return cs;
}
The left and top are hardcoded for my requirements, it would be better to pass them in as arguments.

Android: Image is too big when using canvas drawBitmap

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();

Captured image stretches wrongly after cropping in Android

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

Applying an overlay (image filter) to a Bitmap

I am trying to capture an image from the camera intent and then apply an image filter on it. To elaborate the image would be an image captured by the camera and the image filter would be available in the resources as a png file. I am able to overlay the filter on top of the original image. But, once overlay-ed the original image is 'almost' invisible (which means that the filter is infact being stacked on the original image and not merely replacing it). I have a couple of images to illustrate my problem. The first image was in Photoshop - when I placed a filter on top of an image, it seemed just fine. The second image is the produced by the code cited below - you can clearly see that the filter effect is missing. Would someone have a clue as to why something like this is occurring. Am I missing some logic here?
The following is the code that I have. I apologize if you find any best practices missing here. I am initially trying to test the code:
mPictureView = (ImageView) findViewById(R.id.pictureView);
filterButton = (Button) findViewById(R.id.filter_button1);
// define the threshold fro scaling the image
private final double SCALE_THRESHOLD = 6.0;
// acquire the bitmap (photo captured) from the Camera Intent - the uri is
// passed from a previous activity that accesses the camera and the current
// activity is used to display the bitmap
Uri imageUri = getIntent().getData();
Bitmap imageBitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
// set the imageView in the current activity to display the picture retrieved
// from the camera
mPictureView.setImageBitmap(imageBitmap);
// get the dimensions of the original bitmap
int photoWidth = imageBitmap.getWidth();
int photoHeight = imageBitmap.getHeight();
filterButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// set the options
Options options = new BitmapFactory.Options();
options.inScaled = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
// get the image (png file) filter from resources using the options
Bitmap filter = BitmapFactory.decodeResource(getResources(), R.drawable.colorful_filter,options);
// create a scaled copy of the filter
Bitmap filtercopy = Bitmap.createScaledBitmap(filter, (int)(photoWidth/SCALE_THRESHOLD,(int)(photoHeight/SCALE_THRESHOLD), true);
// recycle the used bitmap
filter.recycle();
filter = null;
// get a scaled, mutable copy of the orginial image
Bitmap imagecopy = Bitmap.createScaledBitmap(imageBitmap,(int)(photoWidth/SCALE_THRESHOLD), (int)(photoHeight/SCALE_THRESHOLD),true);
// recycle the used bitmap
imageBitmap.recycle();
imageBitmap = null;
Paint paint = new Paint();
paint.setAntiAlias(true);
//paint.setAlpha(230); - if a discrete value is set, then the image beneath
// the filter is visible. But, I don't understand why I need to do this.
// Besides, that reduces the efficacy of the filter
// create a canvas with the original image as the underlying image
Canvas canvas = new Canvas(imagecopy);
// now, draw the filter on top of the bitmap
canvas.drawBitmap(filtercopy, 0, 0, paint);
// recycle the used bitmap
filtercopy.recycle();
filtercopy = null;
//set the filtered bitmap as the image
mPictureView.setImageBitmap(imagecopy);
}
EDIT 1: I was able to make some progress with the help of the article that Joru has provided. The problem seems to be with blending of the 2 bitmaps. The method drawBitmap would just draw one bitmap over the other in the situation that I have. The following line of code will actually attempt to blend the 2 bitmaps. I have also attached an image which depicts my progress. The underlying bitmap is noticeably more visible now:
paint.setXfermode(new PorterDuffXfermode(Mode.MULTIPLY));
I have to still play around with it for some time, before achieving the desired output.
You could try a few things:
Bitmap new = old.copy(Config.ARGB_8888, true);
To make sure the bitmap you are opening from MediaStore is in that format. If it isn't, that is likely to cause your problem.

Android - Rotated text on a large bitmap

I have a picture (bitmap) and I want to draw some shapes and rotated
text on it.
This works fine as long as the picture doesn't get too large. However,
when using a picture (2560 x 1920 pixels)taken with the build-in
camera of my android 2.1 phone, the result is distorted.
It looks like the rotation back, after drawing the rotated text, has
not been completed. Also, the distortion point is not always the same,
like it depends on the cpu usage.
You can see some resulting pictures here:
http://dl.dropbox.com/u/4751612/Result1.png
http://dl.dropbox.com/u/4751612/Result2.png
The code is executed inside a AsyncTask. The strange this is that this code works fine in one Activity, but not in another. In both activities the AsyncTask is executed when a button is clicked.
These are some excerpts of the code I'm using.
// Load the image from the MediaStore
c = MediaStore.Images.Media.query(context.getContentResolver(),
Uri.parse(drawing.fullImage), new String[] {MediaColumns.DATA});
if (c != null && c.moveToFirst()) {
imageFilePath = c.getString(0);
bitmap = ImageUtil.getBitmap(new File(imageFilePath), 10000);
}
c.close();
// Create a canvas to draw on
drawingBitmap = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Bitmap.Config.ARGB_8888);
canvas = new Canvas(drawingBitmap);
// Draw image
canvas.drawBitmap(bitmap, 0, 0,
MeasureFactory.getMeasurePaint(context));
// calculate text width
rect = new Rect();
paint.getTextBounds(text, 0, text.length(), rect);
// Draw rotated text
canvas.save();
canvas.rotate(-angle, centerPoint.x, centerPoint.y);
canvas.drawText(text, centerPoint.x-Math.abs(rect.exactCenterX()),
Math.abs(centerPoint.y-rect.exactCenterY()), paint);
canvas.restore();
// Upload the bitmap to the Media Library
Uri uri =
getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
values);
OutputStream outStream = getContentResolver().openOutputStream(uri);
drawingBitmap.compress(Bitmap.CompressFormat.JPEG, 90, outStream);
outStream.flush();
outStream.close();
Thanks in advance for any help.
Since it works as long as the resolution isn't too high, I would just rescale all images to something that works.
You can accomplish this using
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, 800 /* width */, 600 /* height */, true);
This turned out to be a memory problem although no OutOfMemoryException was visible in the log.
So, I "solved" it by scaling the image if the resolution is too high, as suggested by ingo. The problem is that I don't know how to determine the limits of a device. I suppose they are different for every device and depends on the current memory usage.

Categories

Resources