I can't tell if I'm doing something silly or if there is a bug in Corona simulator. When I write the following code:
rect = display.newRect(0, 0, 100, 100)
rect.anchorX = 0
rect.anchorY = 0
rect.x = 0
rect.y = 0
This just sets the anchor point of a 100x100 square to its top left, and sets the position to 0,0. This should make the square snug in the corner, but instead it produces this. It is always a little too far down in the Y axis, but the X axis functions correctly. Does anyone have a fix for this?
With my Corona simulator (build 2016.2992) code works as expected.
main.lua
---------------------------------------------
local rect = display.newRect( 0, 0, 100, 100)
rect.anchorX = 0
rect.anchorY = 0
First of all check your config.lua file. I think it depends on display resolution. For example, in letterbox mode you may have "black bars" on devices with aspect ratios that differ from your content aspect ratio. Read more on Corona documentation.
Below is code from my config.lua file I'm using
config.lua
---------------------------------------------
--calculate the aspect ratio of the device
local aspectRatio = display.pixelHeight / display.pixelWidth
application = {
content = {
width = aspectRatio >= 1.5 and 800 or math.floor( 1200 / aspectRatio ),
height = aspectRatio <= 1.5 and 1200 or math.floor( 800 * aspectRatio ),
scale = "letterBox",
fps = 30,
imageSuffix = {
["#2x"] = 1.3,
},
},
}
Related
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);
I am trying to create a drag-able square, which changes its transparency the closer it goes to the center of the screen (from being invisible in the sides to being completely visible in the center, like in the pictures below)
you can use alpha and transition to achieve that try below code , It should work .. below code changes square opacity from 0 to 100% over a time period of 1.5 seconds while moving
display.setDefault( "background", 80/255 )
local square = display.newRect( 0, display.contentHeight/2, 100, 100 )
square.anchorChildren = true
square:setFillColor( 255,255,0 )
square.alpha = 0
local w,h = display.contentWidth, display.contentHeight
transition.moveTo( square, { x = w/2, y = h/2, time=1500 , alpha = 1.0} )
So I tried everything an can't seem to get the image to take up the full screen and be centered. I have attached the image, and how it looks when I run on corona.
I tried this and got what I attached:
local background = display.newImageRect( "bg.png",
display.contentCenterX, display.contentCenterY)
Thanks in advance for the help!
background image
how it looks on corona
example your config.lua is like below
application = {
content = {
width = 640,
height = 960,
scale = "letterBox",
fps = 30,
},
}
then use like below to display image in fullscreen
local background = display.newImageRect( "bg.png",
640 , 960 )
// then center it like below
background.x = display.contentCenterX
background.y = display.contentCenterY
According to documentation you need to pass width and height, not x and y. Try this:
--take screen width and height, so image can take whole screen
local width = display.contentWidth
local height = display.contentHeight
local background = display.newImageRect( "bg.png", width, height)
--setting coordinates to center
background.x = display.contentCenterX
background.y = display.contentCenterY
Edit: If you are using letterbox scaling mode you should ajust width and height
width = display.contentWidth - 2 * display.screenOriginX
height = display.contentHeight - 2 * display.screenOriginY
If you want preserve aspect ratio of image try
local _CX = display.contentCenterX
local _CY = display.contentCenterY
local imgW = 440 -- width of image
local imgH = 623-- height of image
local imgR = imgH / imgW
local screenW = display.contentWidth - 2 * display.screenOriginX
local screenH = display.contentHeight - 2 * display.screenOriginY
local screenR = screenH / screenW
local factor = imgR > screenR and screenW / imgW or screenH / imgH
local background = display.newImageRect( 'bg.jpg', imgW * factor, imgH * factor )
background .x, background .y = _CX, _CY
I tested code against letterbox mode.
Other solution from Corona forum How to make an image full screen?:
if you want to fill the screen with an image, it's better to make the
image larger than any potential screen aspect ratio, then accept some
amount of clipping on certain screens when the image goes beyond the
edges.
I am new in Corona SDK and I have a problem,
when I place an image at the top of the screen, there is an empty space, how can I make it disappear?
thanks!
It all depends on which device you are running an app. Some of them are taller, some are wider. So there's a value display.screenOriginY which has to be added to a y value if you place an object in a distance from top of screen.
Here's more info:
https://docs.coronalabs.com/api/library/display/screenOriginY.html
In your config.lua file, you can make Corona fill the entire device screen by setting scale = "adaptive". You can read more about adaptive content scaling here
When you use this adaptive scaling, the coordinate (0,0) will be the upper left of the device screen. However, the width and height will vary from device to device and you have to take this into account in your code. You can get these parameters using display.contentWidth and display.contentHeight.
Try (point (0, 0) is located in upper top corner od screen)
--calculate the aspect ratio of the device
local aspectRatio = display.pixelHeight / display.pixelWidth
application = {
content = {
width = aspectRatio >= 1.5 and 800 or math.floor( 1200 / aspectRatio ),
height = aspectRatio <= 1.5 and 1200 or math.floor( 800 * aspectRatio ),
scale = "letterBox",
fps = 30,
imageSuffix = {
["#2x"] = 1.3,
},
},
}
How to get newWebView to zoom to fit screen for difference devices?
So I am create some simple HTML pages with a table, saving this to file (with the below meta tag) and then. I've discovered the meta tag but even with the below, whilst it works well with iPhone 5, with iPad it only take up 1/2 the width of the screen?
<head>
<meta name = "viewport" content = "width = device-width">
</head>
Not sure if this is relevant however my config.lua has:
local aspectRatio = display.pixelHeight / display.pixelWidth
local width = aspectRatio > 1.5 and 320 or math.ceil( 480 / aspectRatio )
local height = aspectRatio < 1.5 and 480 or math.ceil( 320 * aspectRatio )
application = {
content = {
width = width,
height = height,
scale = "letterBox",
fps = 60,
imageSuffix = {
["#2x"] = 1.5,
["#3x"] = 3.0,
},
},
}
EDIT: Setup code:
local displayW, displayH = display.contentWidth, display.contentHeight
local webViewHeight = displayH - navBar.height
webView = native.newWebView(
displayW/2, navBar.height + webViewHeight/2,
displayW, webViewHeight
)
scene.view:insert(webView)
I also use the same code in your config.lua and to make it fit here is what I use for my webviews:
local _H = display.contentHeight
local _W = display.contentWidth
local SBH = display.topStatusBarContentHeight -- Status bar height
webView = native.newWebView( 0, SBH, _W, _H-SBH )
webView.anchorX = 0
webView.anchorY = 0
webView:request( "file.html", system.DocumentDirectory ) -- make sure you choose the right location of your file
The API:
native.newWebView( centerX, centerY, width, height )
As you can see from my code, I have set the anchor point to TopLeft because it's easy to position it that way. Then, width takes the whole screen and the height is the contentHeight minus the status bar height.
This solution will work on all devices, iOS & Android.