I have created an image picker library in which user can select multiple image for uploading to server.were I'm facing a problem ie, i have to compress the selected images without loosing the quality of image much like in popular application Facebook/Whatsapp etc were images maintain with high quality but less size .i have followed the official doc but it's not really satisfying me.if am uploading size less image only i can load it into UI in a fast manner.
Any suggestions/helps are greatly appreciated.
Here is a great library on GitHub for reducing image size without losing quality.
https://github.com/zetbaitsu/Compressor
Try this:
int width = YourImageView.getWidth();
int height = YourImageView.getHeight();
Bitmap bitmap = Bitmap.createBitmap((int)width, (int)height, Bitmap.Config.ARGB_8888);
float originalWidth = selectedBitmap.getWidth(), originalHeight = selectedBitmap.getHeight();
Canvas canvas = new Canvas(bitmap);
float scale = width/originalWidth;
float xTranslation = 0.0f, yTranslation = (height - originalHeight * scale)/2.0f;
Matrix transformation = new Matrix();
transformation.postTranslate(xTranslation, yTranslation);
transformation.preScale(scale, scale);
Paint paint = new Paint();
paint.setFilterBitmap(true);
canvas.drawBitmap(selectedBitmap, transformation, paint);
Related
I'm showing images from gallery to Imageview.
I'm using below code
Bitmap background = Bitmap.createBitmap((int) width, (int) height, Bitmap.Config.ARGB_8888);
float originalWidth = bMap.getWidth(), originalHeight = bMap.getHeight();
Canvas canvas = new Canvas(background);
float scale = width/originalWidth;
float xTranslation = 0.0f, yTranslation = (height - originalHeight * scale)/2.0f;
Matrix transformation = new Matrix();
transformation.postTranslate(xTranslation, yTranslation);
transformation.preScale(scale, scale);
Paint paint = new Paint();
paint.setFilterBitmap(true);
canvas.drawBitmap(bMap, transformation, paint);
imageView1.setImageBitmap(background);
Case 1: working.
Original Image
Output of above code.
Case 2: not working
Original Image.
Output of above code.
in case 2 why image is not getting scaled properly, to fill the imageview?
Please let me know where I'm going wrong.
Android already provides a method to create scaled bitmap. check this out LINK
Are you wanting it to stretch? Use fitxy.
Use the scaleType attribute on your ImageView in your layout xml file.
Example:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerCrop" />
Then you can set your image on the ImageView using setImageUri(Uri uri) (I assume you have the Uri of the image to show).
So, I'm using this library https://github.com/thuytrinh/android-collage-views to add "MultiTouchListener" feature to my ImageView. Basically I let user to modify a photo to his needs using rotation, scale and translation. Now the only problem is how to save it. I did it like this:
Bitmap bitmap = Bitmap.createBitmap(imageContainer.getWidth(), imageContainer.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.WHITE);
imageContainer.draw(canvas);
It works, but image is not big enough - it's as big as view on phone so it depends on screen resolution. And I want to "apply" these transformations on given bitmap with full size. And I want transformed image to look like on screen (so it'll need to crop everything out of screen)
I tried the following:
Bitmap newBitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(newBitmap);
canvas.drawColor(Color.WHITE);
Paint paint = new Paint();
paint.setAntiAlias(true);
canvas.drawBitmap(image, imageView.getMatrix(), paint);
But it doesn't look as expected.
User screen:
And output image (without cropping, because I don't want which side I should crop):
How can I fix this? Is there any solution?
Here is one way to do it, definitely not perfect but should give you a good start :
In this, container refers to the view that contains the transformed ImageView, the phone case on your screenshot and src the raw source bitmap.
First, you need to compute the desired width and height of the output bitmap, i.e the size it would be to make the image fit in it while keeping the ratio of the container :
float containerWidth = containerView.getWidth();
float containerHeight = containerView.getHeight();
float srcWidth = src.getWidth();
float srcHeight = src.getHeight();
float containerRatio = containerWidth / containerHeight;
float srcRatio = srcWidth / srcHeight;
float outputWidth, outputHeight;
if(srcRatio > containerRatio) { //fits in width
outputWidth = srcWidth;
outputHeight = srcWidth / containerRatio;
}
else if(srcRatio < containerRatio) { //fits in height
outputHeight = srcHeight;
outputWidth = srcHeight * containerRatio;
}
else {
outputWidth = srcWidth;
outputHeight = srcHeight;
}
Apply the ratio between container width/height and output width/height to the translation part of the matrix that hold the transformation that the user did
float containerToOutputRatioWidth = outputWidth / containerWidth;
float containerToOutputRatioHeight = outputHeight / containerHeight;
float[] values = new float[9];
transformedImageView.getMatrix().getValues(values);
values[2] = values[2] * containerToOutputRatioWidth;
values[5] = values[5] * containerToOutputRatioHeight;
Matrix outputMatrix = new Matrix();
outputMatrix.setValues(values);
Draw the output bitmap as you were doing with the correct size (outputWidth, outputHeight) and matrix (outputMatrix).
Bitmap newBitmap = Bitmap.createBitmap(Math.round(outputWidth), Math.round(outputHeight), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(newBitmap);
canvas.drawColor(Color.WHITE);
Paint paint = new Paint();
paint.setAntiAlias(true);
canvas.drawBitmap(src, outputMatrix, paint);
.
Warnings
You should be careful about memory allocation, this code will lead to allocate some massive bitmaps, you should implement some kind of limit that get along with your needs. (Also do allocation and drawing in background)
You might need to do some adjustment depending on where you place the image in the first place.
my goal is to create an app that allows users to take a picture with the camera and then add some images on it just like "face in hole" but reversed.
I'm already capable of showing the camera preview while display a imageview, but when i take the picture it has a different resolution so the bitmap over the photo is misplaced.
I've wrote this code but it isn't very accurate:
canvas.drawBitmap(cameraBitmap, 0f, 0f, null); //drawing the picture just taken on the canvas
float posx, posy, newx,newy;
RectF r = new RectF();
i.getImageMatrix().mapRect(r); // i is the imageview of the bitmap
posx= r.left;
posy= r.top;
newx=(posx*newImage.getWidth())/screenWidth;
newy = (posy*newImage.getHeight())/screenHeight;
canvas.drawBitmap( ((BitmapDrawable)i.getDrawable()).getBitmap(),newx,newy,null);
My question is: there's a better and more accurate way to place a bitmap on the picture with the new resolution keeping bitmap scale and rotation info?
Thanks in advance.
I'm trying to crop a bitmap. I first scale the original bitmap down to fit inside a view, then I draw a rectangle on the view that the user can move around and scale to crop the image, much like you can do in instagram when you import a picture from your gallery. The problem I'm having is scaling the rectangle up to match the original bitmap scale to crop from. Here is what's happening:
The middle of the square is what the final result should be
And what we actually get back:
I know it's just math but I spent hours last night trying to get it figured out.. What am I doing wrong?
Bitmap bmp;
float scalefactor = (float)this.mOriginalBitmap.getWidth() / (float)this.mBmpScaledForView.getWidth();
float dh = (this.mCropBoxRect.right - this.mCropBoxRect.left) * (scalefactor-1f);
float dv = (this.mCropBoxRect.bottom - this.mCropBoxRect.top) * (scalefactor-1f);
float l = (float)this.mCropBoxRect.left + dh/2f;
float r = (float)this.mCropBoxRect.right + dh/2f;
float t = (float)this.mCropBoxRect.top + dv/2f;
float b = (float)this.mCropBoxRect.bottom + dv/2f;
RectF scaleRec = new RectF(l, t, r, b);
bmp = Bitmap.createBitmap(this.mOriginalBitmap, (int)scaleRec.left, (int)scaleRec.top, (int)scaleRec.width(), (int)scaleRec.height());
bmp = Bitmap.createScaledBitmap(bmp, MyConsts.outputSize, MyConsts.outputSize, false);
I was able to get it to work by using a matrix. The answer is pretty simple, it was just arriving there what was difficult for me.
Bitmap bmp;
//Get the scale factors for both vertical and horizontal since we're dealing with a square inside of a rectangle
float scalefactorH = (float)mOriginalBitmap.getWidth() / (float)mBmpScaledForView.getWidth();
float scalefactorV = (float)mOriginalBitmap.getHeight() / (float)mBmpScaledForView.getHeight();
//Create a matrix and apply the scale factors
Matrix m = new Matrix();
m.postScale(scalefactorH, scalefactorV);
//Apply the matrix to a RectF
RectF crop = new RectF(mCropBoxRect);
m.mapRect(crop);
//And finally hit the bitmap with this diddy
bmp = Bitmap.createBitmap(this.mOriginalBitmap, (int)crop.left - mOffsetX, (int)crop.top - mOffsetY, (int)crop.width() - mOffsetX, (int)crop.height() - mOffsetY);
Here is my issue, I display in a ListView some Pictures come from web.
I would like to display in my ImageView only a specific area to my picture, without resizing it.
Here is a concret example :
https://docs.google.com/file/d/0B6J9AVdWXjwuWld5dU5CWXFSTjQ/edit?usp=sharing
I think it's possible with a Bitmap method, but I really don't know how to do this...
Thanks for your tips
Yes, the way to do this is to create a Bitmap object out of your source image. Here's an example:
File thumbFile = new File(thumbFileDir, imageName);
//Bitmap source = your image
Bitmap target= Bitmap.createBitmap(thumbSize, thumbSize,Config.ARGB_8888); //in my case the thumb image is square, use your dimensions instead of "thumbSize, thumbSize"
Canvas canvas = new Canvas(target);
float hScale = thumbSize/(float)source.getWidth(); //again, thumb dimensions here
float vScale = thumbSize/(float)source.getHeight(); //and here
float scale = Math.max(hScale, vScale);
Matrix matrix = new Matrix();
matrix.setScale(scale, scale);
matrix.postTranslate(thumbSize/2 - source.getWidth()/2 * scale, thumbSize/2 - source.getHeight()/2 * scale); //and here
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(source, matrix, new Paint());
The "target" object is what you are asking for