Crop rectangle from image issue - android

I need to take picture from camera in landscape orientation (capture the full screen) with this mask:
Then crop rectangle from image like this:
I have some problem with cropping.
I do(android):
public Bitmap getCropImage() {
Bitmap bitmap = getBitmap();
int captureBitmapWidth = bitmap.getWidth();
int captureBitmapHeight = bitmap.getHeight();
// to get a multiplicative factor of axises.
float xCoefficient = captureBitmapWidth / 720.0;
float yCoefficient = captureBitmapHeight / 480.0;
int cropRectangleWidth = 200;
int cropRectangleHeight = 100;
int cropRectangle_a_x = 200;
int cropRectangle_a_y = 300;
bitmap = Bitmap.createBitmap(bitmap,
Math.round(cropRectangle_a_x * xCoefficient),
Math.round(cropRectangle_a_y * yCoefficient),
Math.round(cropRectangleWidth * xCoefficient),
Math.round(cropRectangleHeight * yCoefficient));
return bitmap;
}
iphone:
extension UIImage {
func crop() -> UIImage {
// to get a multiplicative factor of axises.
let xCoefficient : CGFloat = self.size.width / RectangleConfig.WIDTH;
let yCoefficient : CGFloat = self.size.height / RectangleConfig.HEIGTH;
var cropRect = CGRectMake(RectangleConfig.x * xCoefficient,
RectangleConfig.y * yCoefficient,
RectangleConfig.cropRectWidth * xCoefficient,
RectangleConfig.cropRectHeight * yCoefficient)
cropRect.origin.x *= self.scale
cropRect.origin.y *= self.scale
cropRect.size.width *= self.scale
cropRect.size.height *= self.scale
let imageRef = CGImageCreateWithImageInRect(self.CGImage, cropRect)
let image = UIImage(CGImage: imageRef!, scale: self.scale, orientation: self.imageOrientation)
return image
}
}
On some mobile devices, I get the correct result, on other the crop rectangle shifted down and to the left. Where is the mistake?

My guess is that the problem with your code is that you always use 720x480, which is always the case with different android devices.
Maybe more like:
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
float xCoefficient = captureBitmapWidth / metrics.widthPixels;
float yCoefficient = captureBitmapHeight / metrics.heightPixels;

Related

android-gpuimage - image straightening with GPUImageView

In my android app.I want to make image Straightening edit feature using android-gpuimage library but GPUImageView doesn't give feature of getBitmap() or setMatrix() then how is it possible please let me know? here is the code to review :
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if(isStraightenEffectEnabled){
float angle = (progress - 45);
float width = mGPUImageView.getWidth();
float height = mGPUImageView.getHeight();
if (width > height) {
width = mGPUImageView.getHeight();
height = mGPUImageView.getWidth();
}
float a = (float) Math.atan(height/width);
// the length from the center to the corner of the green
float len1 = (width / 2) / (float) Math.cos(a - Math.abs(Math.toRadians(angle)));
// the length from the center to the corner of the black
float len2 = (float) Math.sqrt(Math.pow(width/2,2) + Math.pow(height/2,2));
// compute the scaling factor
float scale = len2 / len1;
Matrix matrix = mGPUImageView.getMatrix();
if (mMatrix == null) {
mMatrix = new Matrix(matrix);
}
matrix = new Matrix(mMatrix);
float newX = (mGPUImageView.getWidth() / 2) * (1 - scale);
float newY = (mGPUImageView.getHeight() / 2) * (1 - scale);
matrix.postScale(scale, scale);
matrix.postTranslate(newX, newY);
matrix.postRotate(angle, mGPUImageView.getWidth() / 2, mGPUImageView.getHeight() / 2);
Is it possible to get mGPUImageView.setMatrix(matrix);
NOW HERE getMatrix() is a method of GPUImageView but setMatrix() or getBitmap() is not method available with GPUImageView class. Any workarounds if possible ?
add getGPUImage in GPUImageView class
public GPUImage getGPUImage() {
return mGPUImage;
}
then get you can get bitmap like this:
mGPUImageView.getGPUImage().getBitmapWithFilterApplied();
You can also get bitmap like this:
Bitmap bitmap = mGPUImageView.capture();
You can get filtered bitmap renderer and Pixelbuffer. This might be helpful for you.
GPUImageLookupFilter amatorka = new GPUImageLookupFilter();
amatorka.setBitmap(BitmapFactory.decodeResource(getResources(), getResources().getIdentifier("fil_" + position, "drawable", getPackageName())));
GPUImageRenderer renderer = new GPUImageRenderer(amatorka);
renderer.setImageBitmap(bitmap, false);
PixelBuffer buffer = new PixelBuffer(80, 80);
buffer.setRenderer(renderer);
buffer.getBitmap();

Calculations in Wallpaper Cropper

I need to know why this extraspace is added as left margin. Due to this wakllpaper is not setting properly in my app. If i try to set leftmost portion as wallpaper then centre portion is getting set as wallpaper due to this extraspace margin.
cropImageAndSetWallpaper(android.net.Uri uri, com.android.wallpapercropper.WallpaperCropActivity$OnBitmapCroppedHandler onBitmapCroppedHandler, boolean finishActivityWhenDone)
boolean centerCrop = getResources().getBoolean(R.bool.center_crop);
// Get the crop
boolean ltr = mCropView.getLayoutDirection() == View.LAYOUT_DIRECTION_LTR;
Display d = getWindowManager().getDefaultDisplay();
Point displaySize = new Point();
d.getSize(displaySize);
boolean isPortrait = displaySize.x < displaySize.y;
Point defaultWallpaperSize = getDefaultWallpaperSize(getResources(),
getWindowManager());
// Get the crop
RectF cropRect = mCropView.getCrop();
Point inSize = mCropView.getSourceDimensions();
int cropRotation = mCropView.getImageRotation();
float cropScale = mCropView.getWidth() / (float) cropRect.width();
Matrix rotateMatrix = new Matrix();
rotateMatrix.setRotate(cropRotation);
float[] rotatedInSize = new float[] { inSize.x, inSize.y };
rotateMatrix.mapPoints(rotatedInSize);
rotatedInSize[0] = Math.abs(rotatedInSize[0]);
rotatedInSize[1] = Math.abs(rotatedInSize[1]);
// Due to rounding errors in the cropview renderer the edges can be slightly offset
// therefore we ensure that the boundaries are sanely defined
cropRect.left = Math.max(0, cropRect.left);
cropRect.right = Math.min(rotatedInSize[0], cropRect.right);
cropRect.top = Math.max(0, cropRect.top);
cropRect.bottom = Math.min(rotatedInSize[1], cropRect.bottom);
// ADJUST CROP WIDTH
// Extend the crop all the way to the right, for parallax
// (or all the way to the left, in RTL)
float extraSpace;
if (centerCrop) {
extraSpace = 2f * Math.min(rotatedInSize[0] - cropRect.right, cropRect.left);
} else {
extraSpace = ltr ? rotatedInSize[0] - cropRect.right : cropRect.left;
}
// Cap the amount of extra width
float maxExtraSpace = defaultWallpaperSize.x / cropScale - cropRect.width();
extraSpace = Math.min(extraSpace, maxExtraSpace);
if (centerCrop) {
cropRect.left -= extraSpace / 2f;
cropRect.right += extraSpace / 2f;
} else {
if (ltr) {
cropRect.right += extraSpace;
} else {
cropRect.left -= extraSpace;
}
}
// ADJUST CROP HEIGHT
if (isPortrait) {
cropRect.bottom = cropRect.top + defaultWallpaperSize.y / cropScale;
} else { // LANDSCAPE
float extraPortraitHeight =
defaultWallpaperSize.y / cropScale - cropRect.height();
float expandHeight =
Math.min(Math.min(rotatedInSize[1] - cropRect.bottom, cropRect.top),
extraPortraitHeight / 2);
cropRect.top -= expandHeight;
cropRect.bottom += expandHeight;
}
final int outWidth = (int) Math.round(cropRect.width() * cropScale);
final int outHeight = (int) Math.round(cropRect.height() * cropScale);
Runnable onEndCrop = new Runnable() {
public void run() {
if (finishActivityWhenDone) {
setResult(Activity.RESULT_OK);
finish();
}
}
};
BitmapCropTask cropTask = new BitmapCropTask(this, uri,
cropRect, cropRotation, outWidth, outHeight, true, false, onEndCrop);
if (onBitmapCroppedHandler != null) {
cropTask.setOnBitmapCropped(onBitmapCroppedHandler);
}
cropTask.execute();
Extra space is added to the wallpaper to allow for a parallax effect. In case your phone uses a right-to-left layout, this space is added to the left of the crop you chose. Google's launcher starts out on the rightmost page in RTL layouts.
If you choose a crop on the left side of the picture, then the expansion will take place on the right side of the crop, an you will see mainly this extension on the main page of the launcher.

How to increase scanning area size in zxing

Hii everyone currently iam working on scanning qr code from my app and i have used zxing library and it's working good and my problem is in my galaxy s4 mobile the scanning area is very small
Please help me
thanks in advance
I know it is too much late but help for others
just go to camera manager class and paste this code on replacement of given method
it works for all types of screens
public Rect getFramingRect() {
if (framingRect == null) {
if (camera == null) {
return null;
}
Point screenResolution = configManager.getScreenResolution();
int width = screenResolution.x * 3 / 4;
int height = screenResolution.y * 3 / 4;
Log.v("Framing rect is : ", "width is "+width+" and height is "+height);
int leftOffset = (screenResolution.x - width) / 2;
int topOffset = (screenResolution.y - height) / 2;
framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
Log.d(TAG, "Calculated framing rect: " + framingRect);
}
return framingRect;
}
public Rect getFramingRect() {
if (framingRect == null) {
if (camera == null) {
return null;
}
Point screenResolution = configManager.getScreenResolution();
int screenx = screenResolution.x;
int screeny = screenResolution.y;
int width, height, left, top;
if (screenx > screeny) {
width = (int) (screenx * 12.5 / 100);
height = (int) (screeny * 25 / 100);
left = (int) screenx * 83 / 100;
top = (int) screeny * 75 / 100;
} else {
left = (int) (screenx * 12.5 / 100);
top = (int) (screeny * 25 / 100);
width = (int) screenx * 83 / 100;
height = (int) screeny * 75 / 100;
}
framingRect = new Rect(left,top, width, height);
Log.d(TAG, "Calculated framing rect: " + framingRect);
}
return framingRect;
}
Replace the above code in CameraManager.java file
this worked for me try this out
The CameraManager class has two constants defined MIN_FRAME_WIDTH and MIN_FRAME_HEIGHT. You should modify them as desired and everything should work:
private static final int MIN_FRAME_WIDTH = 240; // (your desired value here)
private static final int MIN_FRAME_HEIGHT = 240; // (your desired value here)
If you are calling this from another android app, use intent extras SCAN_WIDTH and SCAN_HEIGHT for this.
If you happen to be using phonegap-plugin-barcodescanner (3.0.0 or later), then passing the same intents like xxxxx.scan(onSuccessFunc,onFailFunc,{SCAN_HEIGHT:111,SCAN_WIDTH:222}) will produce the same result. 111 being the height, and 222 being the width.
If you are using ZxingScannerView, you can override createViewFinderView() and increase or decrease the framing rectangle size via viewFinderView like this :
scannerView = object : ZXingScannerView(requireContext()) {
override fun createViewFinderView(context: Context?): IViewFinder {
val viewfinderView = super.createViewFinderView(context)
viewfinderView.setViewFinderOffset(-90) // increase size of framing rectangle
return viewfinderView;
}
}
yourLayour.addView(scannerView)
scannerView.startCamera()

Why does my libGDX resize code break camera.unproject?

I'm using the following code in my resize method to maintain aspect ratio across multiple screen sizes:
#Override
public void resize(int width, int height)
{
float aspectRatio = (float)width / (float)height;
float scale = 1f;
Vector2 crop = new Vector2(0, 0);
if (aspectRatio > globals.ASPECT_RATIO)
{
scale = (float)height / (float)globals.VIRTUAL_HEIGHT;
crop.x = (width - globals.VIRTUAL_WIDTH * scale) / 2f;
}
else if (aspectRatio < globals.ASPECT_RATIO)
{
scale = (float)width / (float)globals.VIRTUAL_WIDTH;
crop.y = (height - globals.VIRTUAL_HEIGHT * scale) / 2f;
}
else
{
scale = (float)width / (float)globals.VIRTUAL_WIDTH;
}
float w = (float)globals.VIRTUAL_WIDTH * scale;
float h = (float)globals.VIRTUAL_HEIGHT * scale;
viewport = new Rectangle(crop.x, crop.y, w, h);
}
VIRTUAL_WIDTH, VIRTUAL_HEIGHT and ASPECT_RATIO are set as follows:
public final int VIRTUAL_WIDTH = 800;
public final int VIRTUAL_HEIGHT = 480;
public final float ASPECT_RATIO = (float)VIRTUAL_WIDTH / (float)VIRTUAL_HEIGHT;
This works perfectly with regards to maintaining the correct ratio when the screen size changes. However, camera.uproject (which I call before all touch events) doesn't work properly - touch positions are not correct when the resize code changes the screen size to anything other than 800x480.
Here's how I setup my camera in my create() method:
camera = new OrthographicCamera(globals.VIRTUAL_WIDTH, globals.VIRTUAL_HEIGHT);
camera.setToOrtho(true, globals.VIRTUAL_WIDTH, globals.VIRTUAL_HEIGHT);
And this is the start of my render() method:
camera.update();
Gdx.graphics.getGL20().glViewport((int)viewport.x, (int)viewport.y,
(int)viewport.width, (int)viewport.height);
Gdx.graphics.getGL20().glClearColor(0, 0, 0, 1);
Gdx.graphics.getGL20().glClear(GL20.GL_COLOR_BUFFER_BIT);
If I ignore the resize code and set the glViewport method call to Gdx.graphics.getWidth() and Gdx.graphics.getHeight(), camera.unproject works, but I obviously lose the maintaining of the aspect ratio. Anyone have any ideas?
Here's how I perform the unproject on my touch events:
private Vector3 touchPos = new Vector3(0, 0, 0);
public boolean touchDown (int x, int y, int pointer, int newParam)
{
touchPos.x = x;
touchPos.y = y;
touchPos.z = 0;
camera.unproject(touchPos);
//touch event handling goes here...
}
UPDATE
I've made a little more progress with this by implementing a Stage object, but it's still not working perfectly.
Here's how I now setup the stage and camera in my create method:
stage = new Stage();
camera = new OrthographicCamera(globals.VIRTUAL_WIDTH, globals.VIRTUAL_HEIGHT);
camera.setToOrtho(true, globals.VIRTUAL_WIDTH, globals.VIRTUAL_HEIGHT);
stage.setCamera(camera);
Here's my resize code:
public void resize(int width, int height)
{
Vector2 size = Scaling.fit.apply(800, 480, width, height);
int viewportX = (int)(width - size.x) / 2;
int viewportY = (int)(height - size.y) / 2;
int viewportWidth = (int)size.x;
int viewportHeight = (int)size.y;
Gdx.gl.glViewport(viewportX, viewportY, viewportWidth, viewportHeight);
stage.setViewport(800, 480, true, viewportX, viewportY, viewportWidth, viewportHeight);
}
Here's the start of my render code:
stage.getCamera().update();
Gdx.graphics.getGL20().glClearColor(0, 0, 0, 1);
Gdx.graphics.getGL20().glClear(GL20.GL_COLOR_BUFFER_BIT);
spriteBatch.setProjectionMatrix(stage.getCamera().combined);
And here's how I handle touch events:
private Vector3 touchPos = new Vector3(0, 0, 0);
public boolean touchDown (int x, int y, int pointer, int newParam)
{
touchPos.x = x;
touchPos.y = y;
touchPos.z = 0;
stage.getCamera().unproject(touchPos);
//touch event handling goes here...
}
This now works when the screen is at default size and when the screen is enlarged. However, when the screen size is reduced the touch points become more and more inaccurate the smaller the screen gets.
Managed to find the answer to this. I simply needed to use the camera.unproject method call which takes Vector3, viewportX, viewportY, viewportWidth and viewportHeight parameters. The required viewport params are those calculated by the resize code shown above.
To solve your issue there is already a implemented solution inside of the new Stage system. Please take a look at the wiki scene2d #viewport. To have a fixed aspec ratio you do not need to resize and fit in manually. Here is the example with blackbars from the wiki:
public void resize (int width, int height) {
Vector2 size = Scaling.fit.apply(800, 480, width, height);
int viewportX = (int)(width - size.x) / 2;
int viewportY = (int)(height - size.y) / 2;
int viewportWidth = (int)size.x;
int viewportHeight = (int)size.y;
Gdx.gl.glViewport(viewportX, viewportY, viewportWidth, viewportHeight);
stage.setViewport(800, 480, true, viewportX, viewportY, viewportWidth, viewportHeight);
}

get zoomed image bitmap height and width in android

How to get ImageView's Height and Width after Zoom in Zoom out.
I am using the following code:
mRectSrc.left = (int)(panX * bitmapWidth - viewWidth / (zoomX * 2));
mRectSrc.top = (int)(panY * bitmapHeight - viewHeight / (zoomY * 2));
mRectSrc.right = (int)(mRectSrc.left + viewWidth / zoomX);
mRectSrc.bottom = (int)(mRectSrc.top + viewHeight / zoomY);
mRectDst.left = getLeft();
mRectDst.top = getTop();
mRectDst.right = getRight();
mRectDst.bottom = getBottom();
// Adjust source rectangle so that it fits within the source image.
if (mRectSrc.left < 0) {
mRectDst.left += -mRectSrc.left * zoomX;
mRectSrc.left = 0;
}
if (mRectSrc.right > bitmapWidth) {
mRectDst.right -= (mRectSrc.right - bitmapWidth) * zoomX;
mRectSrc.right = bitmapWidth;
}
if (mRectSrc.top < 0) {
mRectDst.top += -mRectSrc.top * zoomY;
mRectSrc.top = 0;
}
if (mRectSrc.bottom > bitmapHeight) {
mRectDst.bottom -= (mRectSrc.bottom - bitmapHeight) * zoomY;
mRectSrc.bottom = bitmapHeight;
}
canvas.drawBitmap(mBitmap, mRectSrc, mRectDst, mPaint);
So using This code i am getting zoom effect on image. How Can i Get Bitmap Height and width after zoom in and zoom out.
I tried looking for some inbuilt function for getting the size of the bitmap attached with the image view but couldn't find any. So, I made a workaround. Just store the initial height and width of the bitmap in some variable and then update these variable values with the scale factor.
This is how you can get the bitmap attached with the image(will always return the initial size):
Drawable d = imageView.getDrawable();
Bitmap bmp = ((BitmapDrawable)d).getBitmap();
float w = bmp.getWidth();
float h = bmp.getHeight();
Method to update the values:
public void updateSize(float scaleFactor)
{
w *= scaleFactor;
h *= scaleFactor;
}
You can call this method from where you are adding zoom to the image.

Categories

Resources