How to change View width and height with Use ObjectAnimator property scaleX and scaleY? - objectanimator

I use ObjectAnimator to change view scaleX and scaleY. `
AnimatorSet animatorSet = new AnimatorSet();
ObjectAnimator scaleX = ObjectAnimator.ofFloat(recyclerView, "scaleX", 0.5f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(recyclerView, "scaleY", 0.5f);
animatorSet.setDuration(50);
animatorSet.setInterpolator(new LinearInterpolator());
animatorSet.play(scaleX).with(scaleY);
animatorSet.start();
`
when the scale change end, the view's width and height not change. So my problem come, in the layout, the scale view has change small only half, but the width not change, how i can do something to change the with with scale?

Related

Issue when drawing image on canvas on iPad

I'm working on an HTML5 project, that will run in a WKWebView on iPad.
I'm doing everything programatically.
My WKWebView frame takes the full screen, viewport is 1180x820,
so I set my canvas size and height to 1180x820 too.
Here is my original picture I'd like to display:
But when I'm displaying an 1920x1080 image on my canvas with the drawImage function,
the image does not fit on the screen (obsviously) but is really well displayed (not blurred).
_canvasContext.drawImage(imgMenu,0,0,1920,1080).
So I rescale the image when drawing it, still with the drawImage function.
_canvasContext.drawImage(imgMenu,0,0,1920/2,1080/2)
The image fits in the screen, but is blurred.
The downscaling is really really bad (it really could be better, this example is not the worst one).
I already tried the parameters
_canvasContext.imageSmoothingEnabled = true;
_canvasContext.webkitImageSmoothingEnabled = true;
_canvasContext.mozImageSmoothingEnabled = true;
_canvasContext.imageSmoothingQuality = "high";
It does not help.
Maybe I do something wrong, I don't understand what to do.
Screen resolution of my ipad is 2360x1640, so displaying a 1920x1080 picture should not be a problem.
If anyone could help me, that would save my life :)
Best regards,
Alex
This is one of those annoying and confusing things about canvas. What you need to do is size the canvas using devicePixelRatio. This will increase the actual size of the canvas to match the pixel density of the device. This could be 2, or 1.5 etc... a retina screen is often 2.
For drawing your image, the smart way is to support any image size and fit it into the canvas area (usually scaling down). With a tiny image, this code will scale up and lose resolution.
const IMAGE_URL = 'https://unsplash.it/1920/1080';
const canvas = document.createElement('canvas');
const _canvasContext = canvas.getContext('2d');
// you will probably want this, unless you want to support many screen sizes in which case you will actually want the window size:
/*
const width = 1180;
const height = 820;
*/
const width = window.innerWidth
const height = window.innerHeight
const ratio = window.devicePixelRatio;
// size the canvas to use pixel ratio
canvas.width = Math.round(width * ratio);
canvas.height = Math.round(height * ratio);
// downsize the canvas with css - making it
// retina compatible
canvas.style.width = width + 'px';
canvas.style.height = height + 'px';
document.body.appendChild(canvas);
_canvasContext.fillStyle = 'gray'
_canvasContext.fillRect(0, 0, canvas.width, canvas.height);
function drawImage(url) {
const img = new Image()
img.addEventListener('load', () => {
// find a good scale value to fit the image
// on the canvas
const scale = Math.min(
canvas.width / img.width,
canvas.height / img.height
);
// calculate image size and padding
const scaledWidth = img.width * scale;
const scaledHeight = img.height * scale;
const padX = scaledWidth < canvas.width ? canvas.width - scaledWidth : 0;
const padY = scaledHeight < canvas.height ? canvas.height - scaledHeight : 0;
_canvasContext.drawImage(img, padX / 2, padY / 2, scaledWidth, scaledHeight);
})
img.src = url;
}
drawImage(IMAGE_URL);
body,html {
margin: 0;
padding: 0;
}
As mentioned in a comment in the code snippet. If your want your canvas to always use 1180x820... be sure to change the width and height variables:
const width = 1180;
const height = 820;
For the purposes of the snippet I used the window size. Which may be better for you if you wish to support other device sizes.

Image auto cropping when rotate in OpenCV.js

I'm using OpenCV.js to rotate image to the left and right, but it was cropped when I rotate.
This is my code:
let src = cv.imread('img');
let dst = new cv.Mat();
let dsize = new cv.Size(src.rows, src.cols);
let center = new cv.Point(src.cols/2, src.rows/2);
let M = cv.getRotationMatrix2D(center, 90, 1);
cv.warpAffine(src, dst, M, dsize, cv.INTER_LINEAR, cv.BORDER_CONSTANT, new cv.Scalar());
cv.imshow('canvasOutput', dst);
src.delete(); dst.delete(); M.delete();
Here is an example:
This is my source image:
This is what I want:
But it returned like this:
What should I do to fix this problem?
P/s: I don't know how to use different languages except javascript.
A bit late but given the scarcity of opencv.js material I'll post the answer:
The function cv.warpAffine crops the image because it only does a mathematical transformation as documented on OpenCV and other sources, if you wish to do rotations to any angle you'll need to calculate the padding in order to compensate that.
If you wish to only rotate in multiples of 90 degrees you could use cv.rotate as follows:
cv.rotate(src, dst, cv.ROTATE_90_CLOCKWISE);
Where src is the matrix with your source image, dst is the destination matrix which could be defined empty as follows let dst = new cv.Mat(); and cv.ROTATE_90_CLOCKWISE is the rotate flag indicating the angle of rotation, there are three different options:
cv.ROTATE_90_CLOCKWISE
cv.ROTATE_180
cv.ROTATE_90_COUNTERCLOCKWISE
You can find which OpenCV functions are implemented on OpenCV.js on the repository's opencv_js.congif.py file if the function is indicated as whitelisted then is working on opencv.js even if it is not included in the opencv.js tutorial.
The info about how to use each function can be found in the general documentation, the order of the parameters is generally the indicated on the C++ indications (don't be distracted by the oscure C++ vector types sintax) and the name of the flags (like rotate flag) is usually indicated on the python indications.
I was also experiencing this issue so had a look into #fernando-garcia's answer, however I couldn't see that rotate had been implemented in opencv.js so it seems that the fix in the post #dan-mašek's links is the best solution for this, however the functions required are slightly different.
This is the solution I came up with (note, I haven't tested this exact code and there is probably a more elegant/efficient way of writing this, but it gives the general idea. Also this will only work with images rotated by multiples of 90°):
const canvas = document.getElementById('canvas');
const image = cv.imread(canvas);
let output = new cv.Mat();
const size = new cv.Size();
size.width = image.cols;
size.height = image.rows;
// To add transparent borders
const scalar = new cv.Scalar(0, 0, 0, 0);
let center;
let padding;
let height = size.height;
let width = size.width;
if (height > width) {
center = new cv.Point(height / 2, height / 2);
padding = (height - width) / 2;
// Pad out the left and right before rotating to make the width the same as the height
cv.copyMakeBorder(image, output, 0, 0, padding, padding, cv.BORDER_CONSTANT, scalar);
size.width = height;
} else {
center = new cv.Point(width / 2, width / 2);
padding = (width - height) / 2;
// Pad out the top and bottom before rotating to make the height the same as the width
cv.copyMakeBorder(image, output, padding, padding, 0, 0, cv.BORDER_CONSTANT, scalar);
size.height = width;
}
// Do the rotation
const rotationMatrix = cv.getRotationMatrix2D(center, 90, 1);
cv.warpAffine(
output,
output,
rotationMatrix,
size,
cv.INTER_LINEAR,
cv.BORDER_CONSTANT,
new cv.Scalar()
);
let rectangle;
if (height > width) {
rectangle = new cv.Rect(0, padding, height, width);
} else {
/* These arguments might not be in the right order as my solution only needed height
* > width so I've just assumed this is the order they'll need to be for width >=
* height.
*/
rectangle = new cv.Rect(padding, 0, height, width);
}
// Crop the image back to its original dimensions
output = output.roi(rectangle);
cv.imshow(canvas, output);

Which is the right way to calculate number of points of an image?

View.Bounds gave me values of (0.0, 0.0, 375.0, 667.0) to help calculate view dimensions. And CGImage, size of bitmap gave me pixel count of 490 - pixel width and 751 - pixel height. I don't understand why I get UIView bounds content size less than CGImage pixel width and height when scale factor gave me value of 2. But how can I calculate number of points from the dimensions ? How can I take out 375.0 and 667.0 and calculate ? Below code helped me to get view dimensions and scale factor.
let ourImage: UIImage? = imageView.image
let viewBounds = view.bounds
print("\(viewBounds)")
var scale: CGFloat = UIScreen.mainScreen().scale
print("\(scale)")
And this is the code I worked to receive pixel height and width of 490 * 751.
public init?(image: UIImage) {
guard let cgImage = image.CGImage else { return nil }
// Redraw image for correct pixel format
let colorSpace = CGColorSpaceCreateDeviceRGB()
var bitmapInfo: UInt32 = CGBitmapInfo.ByteOrder32Big.rawValue
bitmapInfo |= CGImageAlphaInfo.PremultipliedLast.rawValue & CGBitmapInfo.AlphaInfoMask.rawValue
width = Int(image.size.width)
height = Int(image.size.height)
.... }
Or can I use (pixelWidth * 2 + pixelHeight * 2) as to calculate number of points ? I need to calculate or fix number of points (n) to substitute in further equation of image segmentation using active contour method.
An image view does not resize to match the image property you set to it. Nor does the image you set resize to match the image view's frame.
Instead, the image view presents a representation of that image scaled to whatever size matches the image view (based on the rules you pick, aspect fit, aspect fill, scale to fill, others, etc).
So the actual size of the image is exactly whatever is returns from the image's size property.
To get the actual image's actual width, use:
image.size.width
Likewise, to get the actual image's actual height, use:
image.size.height

In XNA , what's the difference between the rectangle width and the texture's width in a sprite?

Let's say you did this: spriteBatch.Draw(myTexture, myRectangle, Color.White);
And you have this:
myTexture = Content.Load<Texture2D>("myCharacterTransparent");
myRectangle = new Rectangle(10, 100, 30, 50);
Ok, so now we have a rectangle width of 30. Let's say the myTexture's width is 100.
So with the first line, does it make the sprite's width 30 because that's the width you set to the rectangle, while the myTexture width stays 100? Or does the sprite's width go 100 because that's the width of the texture?
the Rectangles used by the Draw-method defines what part of the Texture2D should be drawn in what part of the rendertarget (usually the screen).
This is how we use tilesets, for instance;
class Tile
{
int Index;
Vector2 Position;
}
Texture2D tileset = Content.Load<Texture2D>("sometiles"); //128x128 of 32x32-sized tiles
Rectangle source = new Rectangle(0,0,32,32); //We set the dimensions here.
Rectangle destination = new Rectangle(0,0,32,32); //We set the dimensions here.
List<Tile> myLevel = LoadLevel("level1");
//the tileset is 4x4 tiles
in Draw:
spriteBatch.Begin();
foreach (var tile in myLevel)
{
source.Y = (int)((tile.Index / 4) * 32);
source.X = (tile.Index - source.Y) * 32;
destination.X = (int)tile.Position.X;
destination.Y = (int)tile.Position.Y;
spriteBatch.Draw(tileset, source, destination, Color.White);
}
spriteBatch.End();
I may have mixed up the order of which the rectangles are used in the draw-method, as I am doing this off the top of my head while at work.
Edit; Using only Source Rectangle lets you draw only a piece of a texture on a position of the screen, while using only destination lets you scale the texture to fit wherever you want it.

How can I operate on a size_t and end up with a CGFloat?

To determine the ratio at which to scale an image, I'm using the following code (borrowed from Trevor Harmon's UIImage+Resize):
CGFloat horizontalRatio = 600 / CGImageGetWidth(imageRef);
CGFloat verticalRatio = 600 / CGImageGetHeight(imageRef);
CGFloat ratio = MAX(horizontalRatio, verticalRatio);
The 600 represents the maximum size I want for the scaled image. CGImageGetWidth and CGImageGetHeight return a size_t which, according to ARC, evaluate to an unsigned long on the iPhone platform (iOS 5).
The problem with the present code is that ratio always evaluates 0.0000.
The width and height of imageRef are actually w=768, h=780, so the ratio should be MAX(0.781, 0.769) = 0.78. How do I this?
P.S. When I used the code above for UIImage's initWithCGImage:scale:orientation: I found that scale works differently than I'd expected: passing in a ratio of 0.78 enlarged the image. Dividing the width or height by the desired size (as in CGImageGetWidth(imageRef) /600, etc.) fixed the problem.
You need one value to be a float to do proper division. Integer division always truncates the floating point numbers. The easiest solution is to turn your numbers into float literals.
CGFloat horizontalRatio = 600.0f / CGImageGetWidth(imageRef);
CGFloat verticalRatio = 600.0f / CGImageGetHeight(imageRef);
CGFloat ratio = MAX(horizontalRatio, verticalRatio);

Resources