The task is to crop video by given points(like rectangle) and display the cropped video.
The code works with cropping the first halh of video(0, 0, videoWidth/2, videoHeight). But when i tryed to display the second one(videoWidth/2, 0, videoWidth, videoHeight), that is what was displayed.
The video is displayed on TextureView inside FrameLayout.
The part, that doesn't work:
private void updateTextureViewSize(int ax, int ay, int bx, int by) {
float scaleX;
float scaleY;
//proportions between screen and frame dimensions
scaleX = mVideoWidth / mDisplayWidth;
scaleY = mVideoHeight / mDisplayHeight;
float scaleRegionW = mVideoWidth / Math.abs(ax - bx);
float scaleRegionH = mVideoHeight / Math.abs(ay - by);
float scaleRegion = scaleRegionW < scaleRegionH ? scaleRegionW : scaleRegionH;
Matrix matrix = new Matrix();
if (scaleX > scaleY) {
matrix.setScale(scaleRegion / scaleY, scaleRegion);
matrix.postTranslate(-ax * (int) scaleRegion / scaleY, -ay * scaleRegion / scaleY);
} else {
matrix.setScale(scaleRegion, scaleRegion / scaleX);
matrix.postTranslate(-ax * scaleRegion / scaleX, -ay * scaleRegion / scaleX);
}
mTextureView.setTransform(matrix);
mTextureView.setLayoutParams(new FrameLayout.LayoutParams((int) mDisplayWidth, (int) mDisplayHeight));
}
The answer was found by Dmitry Yacenko.
The full code.
An easy way to crop video by given points (ax, ay, bx, xy) is:
float scaleX = mDisplayWidth / mVideoWidth, scaleY = mDisplayHeight / mVideoHeight;
//proportions between screen and frame dimensions
float scale = mDisplayHeight / Math.abs(by - ay);
Matrix matrix = new Matrix();
matrix.reset();
matrix.setScale(scale / scaleX, scale / scaleY);
//scaling video
matrix.postTranslate(-scale * ax, -scale * ay);
//move video, so the needed part of it will be displayed properly
mTextureView.setLayoutParams(new FrameLayout.LayoutParams((int) mDisplayWidth, (int) mDisplayHeight));
mTextureView.setTransform(matrix);
//updating the Texture view
Related
I want to scale the bitmap and translate that bitmap center of the screen(screen size not specified ).
I'm trying this way
Matrix matrix = new Matrix();
protected void setImageDrawableCenter(#NonNull Drawable imgDrawable,float sc) {
float width = getWidth();//this provide framelayout width
float height = getHeight();//this provide framelayout height
float offsetX = width - imgDrawable.getIntrinsicWidth();
float offsetY = height - imgDrawable.getIntrinsicHeight();
offsetY /= sc;
offsetX /= sc;
matrix.postTranslate(offsetX, offsetY);
float scaleFactor, widthScaleFactor, heightScaleFactor;
widthScaleFactor = (float) getWidth() / imgDrawable.getIntrinsicWidth();
heightScaleFactor = (float) getHeight() / imgDrawable.getIntrinsicHeight();
scaleFactor = widthScaleFactor > heightScaleFactor ? heightScaleFactor : widthScaleFactor;
matrix.postScale(scaleFactor / sc, scaleFactor / sc, getWidth() / sc, getHeight() / sc);
invalidate();
}
When calling the above function.
setImageDrawableCenter(imgDrawable,2); when scale is 2f is perfectly work.(note image size is 512x512)
setImageDrawableCenter(imgDrawable,1); when scale is 1.5f is image not set in center.
[More detail on this link. Line number : 720](https://github.com/wuapnjie/StickerView/blob/master/sticker/src/main/java/com/xiaopo/flying/sticker/StickerView.java#:~:text=protected%20void-,addStickerImmediately,-(%40NonNull)
I am using the following texture
It is being displayed only partially and it gets repeated when I used the following code:
float scale = (float)( (float)Gdx.graphics.getWidth() / (float)(tex.getWidth()));
w = Gdx.graphics.getWidth();
h = scale * tex.getHeight();
float x = 0.0f;
float y = Gdx.graphics.getWidth() - h * splashTimer;
Sprite s = new Sprite(tex);
//s.setOriginCenter();
// s.setScale(scale);
//s.setOriginCenter();
// s.setOriginCenter();
//s.setSize(s.getWidth() * scale, s.getHeight() * scale);
//s.setOriginCenter();
s.setScale(0.1f);//1.0f + (1.0f - scale));
s.setOrigin(0, 0);
s.setPosition(x, y);
batch.begin();
batch.draw(s,0,0,Gdx.graphics.getWidth(), scale * s.getHeight());
// s.draw(batch);
batch.end();
It gets chopped and repeated in Android and looks like this:
Orange isn't even drawn. Why is this happening?
Apparently this happened because I was using mipmaps. I disabled the use of mipmaps and now it works.
in my project I want to draw my drawable to the screen to fit its height and width , and then I want to draw other things on its center . The problem is when I want to draw it , it not shows fit to the screen , I have tried many things but nothing work for me.
I know my question is not clear so shortly asking that how to fit the image to fit the background using canvas.drawmethod()
here is what I am using
final Drawable dial = mDial;
int w = dial.getIntrinsicWidth();
int h = dial.getIntrinsicHeight();
boolean scaled = false;
if (availableWidth < w || availableHeight < h) {
scaled = true;
float scale = Math.min((float) availableWidth / (float) w,
(float) availableHeight / (float) h);
canvas.save();
canvas.scale(scale, scale, x, y);
Log.d("Scaling the width and height","here we go");
}
if (changed) {
dial.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
Log.d("bounds have been changed","here we go");
}
dial.draw(canvas);
please help
I am creating a little game in Java and I have an image which gets rotated.
As you can see in the two images below, there is a giant ship which slowly rotates in the game, but when it gets to a certain point it gets cut off (due to its own little BufferedImage).
Heres my rendering code:
public void drawImageRotated(BufferedImage img, double x, double y, double scale, double angle) {
x -= xScroll;
y -= yScroll;
BufferedImage image = new BufferedImage((int)(img.getWidth() * 1.5D), (int)(img.getHeight() * 1.5D), 2);
Graphics2D g = (Graphics2D)image.getGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.rotate(Math.toRadians(angle), image.getWidth() / 2, image.getHeight() / 2);
g.drawImage(img, image.getWidth() / 2 - img.getWidth() / 2, image.getHeight() / 2 - image.getHeight() / 2, null);
g2d.drawImage(image, (int)(x-image.getWidth()*scale/2), (int)(y-image.getHeight()*scale/2), (int)(image.getWidth()*scale), (int)(image.getHeight()*scale), null);
g.dispose();
}
Back to the matter at hand, how can i work out the maximum x and y size of an image during rotation so I can compensate with my buffered images size?
If you have a basically rectangular image which is rotated around its center, the maximum width and height during rotation will be when a diagonal of the image rectangle is horizontal or vertical. This diagonal distance could be computed with the Pythagorean Theorem and used for the width and height of the BufferedImage.
int size = (int) Math.sqrt((img.getWidth() * img.getWidth()) + (img.getHeight() * img.getHeight()));
BufferedImage image = new BufferedImage(size, size, 2);
// The rest of your code as before
how can i work out the maximum x and y size of an image during rotation so I can compensate with my buffered images size?
double sin = Math.abs(Math.sin(angle));
double cos = Math.abs(Math.cos(angle));
int w = image.getWidth();
int h = image.getHeight();
int neww = (int)Math.floor(w*cos+h*sin);
int newh = (int)Math.floor(h*cos+w*sin);
The above code was taken from this example: Java(SWING) working with Rotation
An alternative is to rotate the actual Graphics object, draw the image, and restore the rotation:
AffineTransform old = g2d.getTransform();
g2d.rotate(Math.toRadians(angle), x + image.getWidth() / 2, y + image.getWidth() / 2);
g2d.drawImage(image, x, y, null);
g2d.setTransform(old);
Let's consider width being the width of the original image, height its original height and angle the rotation angle value in radians.
According to my calculations, the size of the rotated image is something like this:
rotatedWidth = Math.cos(angle) * width + Math.sin(angle) * height;
rotatedHeight = Math.sin(angle) * width + Math.cos(angle) * height;
You may also need to take a look at this thread as well, as it may help.
If I have an image of which I know the height and the width, how can I fit it in a rectangle with the biggest possible size without stretching the image.
Pseudo code is enough (but I'm going to use this in Java).
Thanks.
So, based on the answer, I wrote this: but it doesn't work. What do I do wrong?
double imageRatio = bi.getHeight() / bi.getWidth();
double rectRatio = getHeight() / getWidth();
if (imageRatio < rectRatio)
{
// based on the widths
double scale = getWidth() / bi.getWidth();
g.drawImage(bi, 0, 0, (int) (bi.getWidth() * scale), (int) (bi.getHeight() * scale), this);
}
if (rectRatio < imageRatio)
{
// based on the height
double scale = getHeight() / bi.getHeight();
g.drawImage(bi, 0, 0 , (int) (bi.getWidth() * scale), (int) (bi.getHeight() * scale), this);
}
Determine the aspect ratio of both (height divided by width, say, so tall, skinny rectangles have an aspect ratio > 1).
If your rectangle's aspect ratio is greater than that of your image, then scale the image uniformly based on the widths (rectangle width / image width).
If your rectangle's aspect ratio is less than that of your image, then scale the image uniformly based on the heights (rectangle height / image height).
Here is my two cents:
/**
* Calculate the bounds of an image to fit inside a view after scaling and keeping the aspect ratio.
* #param vw container view width
* #param vh container view height
* #param iw image width
* #param ih image height
* #param neverScaleUp if <code>true</code> then it will scale images down but never up when fiting
* #param out Rect that is provided to receive the result. If <code>null</code> then a new rect will be created
* #return Same rect object that was provided to the method or a new one if <code>out</code> was <code>null</code>
*/
private static Rect calcCenter (int vw, int vh, int iw, int ih, boolean neverScaleUp, Rect out) {
double scale = Math.min( (double)vw/(double)iw, (double)vh/(double)ih );
int h = (int)(!neverScaleUp || scale<1.0 ? scale * ih : ih);
int w = (int)(!neverScaleUp || scale<1.0 ? scale * iw : iw);
int x = ((vw - w)>>1);
int y = ((vh - h)>>1);
if (out == null)
out = new Rect( x, y, x + w, y + h );
else
out.set( x, y, x + w, y + h );
return out;
}
This will not affect your aspect ration and will fit exactly on one side and not overshoot on the other side.
public static Rect getScaled(int imgWidth, int imgHeight, int boundaryWidth, int boundaryHeight) {
int original_width = imgWidth;
int original_height = imgHeight;
int bound_width = boundaryWidth;
int bound_height = boundaryHeight;
int new_width = original_width;
int new_height = original_height;
// first check if we need to scale width
if (original_width > bound_width) {
//scale width to fit
new_width = bound_width;
//scale height to maintain aspect ratio
new_height = (new_width * original_height) / original_width;
}
// then check if we need to scale even with the new height
if (new_height > bound_height) {
//scale height to fit instead
new_height = bound_height;
//scale width to maintain aspect ratio
new_width = (new_height * original_width) / original_height;
}
return new Rect(0,0,new_width, new_height);
}