get zoomed image bitmap height and width in android - 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.

Related

How to capture exactly the image inside the rectangular overlay in Camera?

I successfully made the auto crop to some extent for small devices so far. I am facing two issues:
1) the auto crop in big devices lets say 6.5 inches is not working properly
2) i want to take picture inside the rectangle frame
Below is my code:
public static Bitmap crop(Bitmap originalBitmap)
{
double originalWidth = originalBitmap.getWidth();
double originalHeight =
originalBitmap.getHeight();
double scaleX = originalWidth / 1280;
int navBarHeightPxIn1280x720Ui
CommonUtils.px2dp(CommonUtils.get
NavigationBarHeightInPx()) * 5 ;
double scaleXMultiplier = ((double) 1280) /
((double) (1280 - navBarHeightPxIn1280x720Ui));
scaleX = scaleX * scaleXMultiplier;
double scaleY = originalHeight / 720;
int x = (int) (52 * scaleX + 0.5);
int y = (int) (80 * scaleY + 0.5);
int width = (int) (896 * scaleX + 0.5);
int height = (int) (588 * scaleY + 0.5);
return Bitmap.createBitmap(originalBitmap, x, y,
width, height);
}

Imageview scaling method "centercrop" as code

Im trying to find out what android is doing when it scales an Image, specifically the "centercrop" type. So to find an answer I searched the ImageView sourcecode and find it here.
So what I tried is this code :
public Bitmap buildBluredBoxBackground () {
int [] screenSize = Utilities.getScreenSize(mainActivityContext); //screensize[0] = x and [1] is y
Matrix mDrawMatrix = new Matrix();
Bitmap bitmap = ((BitmapDrawable)fullscreenViewHolder.imageViewArt.getDrawable()).getBitmap();
float scale;
float dx = 0, dy = 0;
if (bitmap.getWidth() * screenSize[1] > screenSize[0] * bitmap.getHeight()) {
scale = (float) screenSize[1] / (float) bitmap.getHeight();
dx = (screenSize[0] - bitmap.getWidth() * scale) * 0.5f;
} else {
scale = (float) screenSize[0] / (float) bitmap.getWidth();
dy = (screenSize[1] - bitmap.getHeight() * scale) * 0.5f;
}
mDrawMatrix.setScale(scale, scale);
mDrawMatrix.postTranslate(Math.round(dx), Math.round(dy));
result = Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),mDrawMatrix,true);
... //Some processing work
return result;
}
But it is not giving me the same result. What am I doing wrong ?
Heres an example:
Original Picture
Orginal ImageView Centercrop
Tried Code
Edit:
XML of the ImageView
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/imageViewFullscreenArt"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/imageViewFullscreenArtBluredBox"/>
</FrameLayout>
So my ImageView is fullscreened. Thats why Im using the screenSize to process it.
Code how I'm applying it
Bitmap bluredBoxBackground = buildBluredBoxBackground();
imageViewBluredBox.setImageDrawable(new BitmapDrawable(getResources(),bluredBoxBackground));
Detailed Description:
Im just trying to get the same effect as ImageView.setScaleType(ScaleType.CENTER_CROP). So my code should do the same like the original setScaleType method. Why do I need it as code ? Because in my situation I can't get the drawingcache of my ImageView but I have to process & edit it somehow.
I adapted from teh source.
It will work with you change the return to Matrix how you apply.
public Matrix buildBluredBoxBackground () {
int dwidth = imageView.getDrawable().getIntrinsicWidth();
int dheight = imageView.getDrawable().getIntrinsicHeight();
int vwidth = imageView.getWidth() - imageView.getPaddingLeft() - imageView.getPaddingRight();
int vheight = imageView.getHeight() - imageView.getPaddingTop() - imageView.getPaddingBottom();
Matrix mDrawMatrix = imageView.getImageMatrix();
Bitmap bMap = imageView.getDrawingCache();
float scale;
float dx = 0, dy = 0;
if (dwidth * vheight > vwidth * dheight) {
scale = (float) vheight / (float) dheight;
dx = (vwidth - dwidth * scale) * 0.5f;
} else {
scale = (float) vwidth / (float) dwidth;
dy = (vheight - dheight * scale) * 0.5f;
}
mDrawMatrix.setScale(scale, scale);
mDrawMatrix.postTranslate(Math.round(dx), Math.round(dy));
return mDrawMatrix;
}
And then use:
Matrix bluredBoxBackground = buildBluredBoxBackground();
imageViewBluredBox.setImageMatrix(bluredBoxBackground));
imageViewBluredBox.invalidate();

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

Matrix scale video on TextureView Android

I'm trying to play video with ExoPlaye on TextureView. In order to scale and crop video to fit view I use matrix. My custom view extends `TextureView' Here is my code:
#Override
public void onVideoSizeChanged(int width, int height, float pixelWidthHeightRatio) {
updateTextureViewSize(width, height);
Log.v("EXO", "onVideoSizeChanged() " + width + "x" + height);
}
private void updateTextureViewSize(float videoWidth, float videoHeight) {
float viewWidth = getWidth();
float viewHeight = getHeight();
float scaleX = 1.0f;
float scaleY = 1.0f;
float viewRatio = viewWidth / viewHeight;
float videoRatio = videoWidth / videoHeight;
if (viewRatio > videoRatio) {
// video is higher than view
scaleY = videoHeight / videoWidth;
} else {
//video is wider than view
scaleX = videoWidth / videoHeight;
}
Matrix matrix = new Matrix();
matrix.setScale(scaleX, scaleY, viewWidth / 2, viewHeight / 2);
setTransform(matrix);
}
I had a rectangular views and it worked perfectly. But now views have 2 states: expanded (the old ones that are still rectangular) and collapsed (have smaller height.
So now video is stretched vertically in those collapsed views.
For instance I have view 1080x480 and video 360x640 but it looks like video is scaled and cropped to 1080x1080 and than stretched to 1080x480.
What am I doing wrong here ?
UPD: Here are screenshots:
I fixed this issue next by multiplying or dividing scale factors by viewRatio (width / height):
if (viewRatio > videoRatio) {
// video is higher than view
scaleY = videoHeight / videoWidth * viewRatio;
} else {
//video is wider than view
scaleX = videoWidth / videoHeight / viewRatio;
}
But I did not get why it works like this. According to my calculations if I have, for instance, view 1080x480 and video 360x640 video should be scaled to have width x' = 1080 and height proportional. So height should be y' = 640*1080/360 (videoHeight * viewHeight / videoWidth) and x' = 1080
According to this image:
sx * 360 = 1080 => sx = 1080 / 360
sy * 640 = 640*1080/360 => sy = 1080 / 360
Looks like it makes sense. If we need save proportions width and height should be multiplied by the same factor. But it does not work this way. Where is a mistake ? Is there any good doc on this ?
check updateTextureViewSize :
/**
* Set the display options
*
* #param layout <ul>
* <li>{#link #VIDEO_LAYOUT_ORIGIN}
* <li>{#link #VIDEO_LAYOUT_SCALE}
* <li>{#link #VIDEO_LAYOUT_STRETCH}
* <li>{#link #VIDEO_LAYOUT_ZOOM}
* </ul>
*/
public void updateTextureViewSize(int layout,float videoWidth, float videoHeight) {
RelativeLayout.LayoutParams lp = (android.widget.RelativeLayout.LayoutParams) getLayoutParams();
DisplayMetrics disp = m_Context.getResources().getDisplayMetrics();
int windowWidth = disp.widthPixels, windowHeight = disp.heightPixels;
float windowRatio = windowWidth / (float) windowHeight;
float videoRatio = (float) videoWidth / (float) videoHeight;
m_iSurfaceHeight = videoHeight;
m_iSurfaceWidth = videoWidth;
if (VIDEO_LAYOUT_ORIGIN == layout && m_iSurfaceWidth < windowWidth && m_iSurfaceHeight < windowHeight) {
lp.width = (int) (m_iSurfaceHeight * videoRatio);
lp.height = m_iSurfaceHeight;
} else if (layout == VIDEO_LAYOUT_ZOOM) {
lp.width = windowRatio > videoRatio ? windowWidth : (int) (videoRatio * windowHeight);
lp.height = windowRatio < videoRatio ? windowHeight : (int) (windowWidth / videoRatio);
} else {
boolean full = layout == VIDEO_LAYOUT_STRETCH;
lp.width = (full || windowRatio < videoRatio) ? windowWidth : (int) (videoRatio * windowHeight);
lp.height = (full || windowRatio > videoRatio) ? windowHeight : (int) (windowWidth / videoRatio);
lp.leftMargin = (disp.widthPixels - lp.width) / 2;
lp.topMargin = (disp.heightPixels - lp.height) / 2;
}
lp.leftMargin = (disp.widthPixels - lp.width) / 2;
lp.topMargin = (disp.heightPixels - lp.height) / 2;
getHolder().setFixedSize(m_iSurfaceWidth, m_iSurfaceHeight);
setLayoutParams(lp);
m_iVideoLayout = layout;
}

Get the displayed size of an image inside an ImageView

The code is simple:
<ImageView android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="#drawable/cat"/>
Notice the ImageView used fill_parent for width and height.
The image cat is a small image and it will be zoomed in to fit the ImageView, and keep the width/height ratio at the same time.
My question is how to get the displayed size of the image? I tried:
imageView.getDrawable().getIntrinsicHeight()
But which it the original height of the image cat.
I tried:
imageView.getDrawable().getBounds()
But which returns Rect(0,0,0,0).
the following will work:
ih=imageView.getMeasuredHeight();//height of imageView
iw=imageView.getMeasuredWidth();//width of imageView
iH=imageView.getDrawable().getIntrinsicHeight();//original height of underlying image
iW=imageView.getDrawable().getIntrinsicWidth();//original width of underlying image
if (ih/iH<=iw/iW) iw=iW*ih/iH;//rescaled width of image within ImageView
else ih= iH*iw/iW;//rescaled height of image within ImageView
(iw x ih) now represents the actual rescaled (width x height) for the image within the view (in other words the displayed size of the image)
EDIT: I think a nicer way to write the above answer (and one that works with ints) :
final int actualHeight, actualWidth;
final int imageViewHeight = imageView.getHeight(), imageViewWidth = imageView.getWidth();
final int bitmapHeight = ..., bitmapWidth = ...;
if (imageViewHeight * bitmapWidth <= imageViewWidth * bitmapHeight) {
actualWidth = bitmapWidth * imageViewHeight / bitmapHeight;
actualHeight = imageViewHeight;
} else {
actualHeight = bitmapHeight * imageViewWidth / bitmapWidth;
actualWidth = imageViewWidth;
}
return new Point(actualWidth,actualHeight);
Here is a helper function to get the bounds of image in an imageView.
/**
* Helper method to get the bounds of image inside the imageView.
*
* #param imageView the imageView.
* #return bounding rectangle of the image.
*/
public static RectF getImageBounds(ImageView imageView) {
RectF bounds = new RectF();
Drawable drawable = imageView.getDrawable();
if (drawable != null) {
imageView.getImageMatrix().mapRect(bounds, new RectF(drawable.getBounds()));
}
return bounds;
}
I guess a lot of people are coming from this example https://developer.android.com/training/animation/zoom.html and don't want to use android:scaleType="centerCrop" (maybe because the ImageView is in a constraint layout and you want to see the small picture uncroped) don't you worry, I got your back!
Just replace the entire block beginning with
// Adjust the start bounds to be the same aspect ratio as the final
// bounds using the "center crop" technique.
with the following
//adjust for scaled image to constraint
int realheight = ResourcesCompat.getDrawable(getResources(),imageResId,null).getIntrinsicHeight();
int realwidth = ResourcesCompat.getDrawable(getResources(),imageResId,null).getIntrinsicWidth();
// Adjust the start bounds to be the same aspect ratio as the final
// bounds using ueen's adjusteddimensions technique. This prevents undesirable
// stretching during the animation. Also calculate the start scaling
// factor (the end scaling factor is always 1.0).
float startScale;
if ((float) finalBounds.width() / finalBounds.height()
> (float) startBounds.width() / startBounds.height()) {
// Extend start bounds horizontally
// after check whether height or width needs adjusting
if ((float) startBounds.width() / startBounds.height() < (float) realwidth / realheight) {
int adjustedheight = realheight*startBounds.width()/realwidth;
int adjustedoffset = (startBounds.height()-adjustedheight) / 2;
startScale = (float) adjustedheight / finalBounds.height();
float startWidth = startScale * finalBounds.width();
float deltaWidth = (startWidth - startBounds.width()) / 2;
startBounds.left -= deltaWidth;
startBounds.right += deltaWidth;
startBounds.offset(+0, +adjustedoffset);
} else {
int adjustedwidth = realwidth*startBounds.height()/realheight;
int adjustedoffset = (startBounds.width()-adjustedwidth) / 2;
startScale = (float) startBounds.height() / finalBounds.height();
float startWidth = startScale * finalBounds.width();
float deltaWidth = (startWidth - adjustedwidth) / 2;
startBounds.left -= deltaWidth;
startBounds.right += deltaWidth;
startBounds.offset(+adjustedoffset, +0);
}
} else {
// Extend start bounds vertically
// after check whether height or width needs adjusting
if ((float) startBounds.width() / startBounds.height() > (float) realwidth / realheight) {
int adjustedwidth = realwidth*startBounds.height()/realheight;
int adjustedoffset = (startBounds.width()-adjustedwidth) / 2;
startScale = (float) adjustedwidth / finalBounds.width();
float startHeight = startScale * finalBounds.height();
float deltaHeight = (startHeight - startBounds.height()) / 2;
startBounds.top -= deltaHeight;
startBounds.bottom += deltaHeight;
startBounds.offset(+adjustedoffset, +0);
} else {
int adjustedheight = realheight*startBounds.width()/realwidth;
int adjustedoffset = (startBounds.height()-adjustedheight) / 2;
startScale = (float) startBounds.width() / finalBounds.width();
float startHeight = startScale * finalBounds.height();
float deltaHeight = (startHeight - adjustedheight) / 2;
startBounds.top -= deltaHeight;
startBounds.bottom += deltaHeight;
startBounds.offset(+0, +adjustedoffset);
}
}
works like a charme,
you're welcome :)
Further explanation: as usual we check wheter the picture is taller than wide (expanded the height of the picture should match the height of expandedImageView) or vice versa. Then we check if the picture in the original (smaller) ImageView (thumbView) is matching the width or the heigth, so we can adjust for the space.
This way we achieve a smooth scaling animation while not croping the picture in the thumbView, no matter it's dimension (as they may change from device to device when using constarints) or that of the picture.
use
// For getting imageview height
imgObj.getMeasuredHeight()
// For getting imageview width
imgObj.getMeasuredWidth();
//For getting image height inside ImageView
imgObj.getDrawable().getIntrinsicHeight();
//For getting image width inside ImageView
imgObj.getDrawable().getIntrinsicWidth();

Categories

Resources