How does masking work in C4? - c4

I've set up a shape and an image that I'd like to mask my shape with. I set both their centers to the center of the canvas and then I wrote:
shape.mask = img;
But this gives me very strange results. The shape appears to be masked... sort of... the only part that shows up is the bottom right corner, the left half and the top half are cut off.
I also tried with two images, and with two shapes. Neither seems to work.
Am I missing a step? Perhaps the image I'm trying to mask with doesn't have any alpha values (I'm guessing here, I saw it mentioned in another question that they have to be images with alpha values and they mentioned .png files, so that's what I used)?
When I tried with two shapes, I tried setting the alpha value of the fill of the shape I wanted to mask with to 0.5 and 0.0 and also just setting the fillColor to Nil... still nothing.
I also (in a desperate last attempt) tried the method described here: Mask a view in Objective-C but I'm not very good with objective-c on its own so that didn't work either.
What is the correct way to mask in C4?

You're masking the right way.
What's going on is that an object's mask must be positioned based on the coordinate space of the object itself. When you add a subview to an object, it gets positioned relative to the object's {0,0}.
The following code will work and show you 2 things.
First, the masking shape is positioned to the center of the object, and NOT the center of the canvas:
s.center = CGPointMake(m.width/2,m.height/2);
Second, when you touch the canvas the animation will trigger the mask to move to the "center" coordinate of the canvas, but you'll notice that it goes further off. This is because it counts its position from the origin of the image.
#implementation C4WorkSpace {
C4Image *m;
C4Shape *s;
}
-(void)setup {
m = [C4Image imageNamed:#"C4Sky"];
s = [C4Shape ellipse:CGRectMake(0, 0, m.height, m.height)];
m.center = self.canvas.center;
s.center = CGPointMake(m.width/2,m.height/2);
m.mask = s;
[self.canvas addImage:m];
}
-(void)touchesBegan {
s.animationDuration = 1.0f;
s.center = self.canvas.center;
}
#end

Related

Add Shape created by .intersect to a Canvas?

I am trying to highlight an Area that gets intersected by 2 Circle:
Example 1.:
The Yellow dots get, for testing purposes, random values. Those are used to draw a circle around, as well as to store an ellipse in the Background. In the Case of no intersection, the GUI acts correctly and display this:
After the random Values, the Shapes intersect. As I cannot seem to be able to add the new Shape made trough .intersect(), I just did a quick sp.setContent(), and got this image:
This basicly shows me the intersected space and colors it blue.
Everything is drawn on a Canvas, which basicly does the following:
Canvas canvas = new Canvas(250, 250);
....
gc = canvas.getGraphicsContext2D();
canvas.setHeight(imgTemp.getHeight());
canvas.setWidth(imgTemp.getWidth());
gc.drawImage(imgTemp, 0, 0);
Aswell as with some other Loops to draw the shapes and the circles.
Now, the code for the intersect is the following:
if (!(e.equals(eT))) {
if (e.getBoundsInParent().intersects(eT.getBoundsInParent())) {
System.out.println("Collision detected!");
Shape inter = Shape.intersect(e, eT);
if(inter.getBoundsInLocal().getWidth() > 0 && 0 < inter.getBoundsInLocal().getHeight()){
inter.setFill(BLUE);
inter.setStrokeWidth(3);
sp.setContent(inter);
}
}
I'm not that used to JavaFX and have only begun really working on it this Weekend for a small Project, but I am guessing that I might need to change from canvas to something else to make use of the shapes? Or is there a way to "tranform" the Shape of the intersect into something drawable by GraphicsContext2D?
Why don't you just put your Canvas into a Group and then add your shapes to the same Group. Why would you insist on drawing everything into the Canvas? A Canvas is just a Node like all the other Shapes and you can mix them freely in the SceneGraph.
Another question would be why you are using the Canvas at all if you have already realized that this leads to problems in your case.

Crop image in scilab

I want to crop image using mouse selection at particular region of interest in scilab,here my code is
I=imread('G:\SCI\FRAME\mixer2.jpg');
I1G = rgb2gray(I);
figure();ShowImage(I1G,'mixer');
IN1G = gca();
rect1 = rubberbox();
ROI1=imcrop(I1G,rect1);disp(ROI1);
But it gives the following error: The rectangle is out of the image range.
and i also use xclick and xgetmouse function for cropping using mouse selection and it also gives the same error.
please give me suggestions for correcting code .
Thanks and Regards
The problem arises from the difference between the image coordinate system (used by imcrop and all the other functions of the SIVP toolbox) and the "regular" coordinate system (used by rubberbox, xcick and all the builtin functions). Images have the first pixel at top-left. On the contrary rubberbox have the zero at bottom left.
To correct this you have to reverse the y (vertical) axes coordinate before applying imcrop():
imagefile="d:\Attila\PROJECTS\Scilab\Stackoverflow\mixer_crop.jpg";
I=imread(imagefile);
I1G=rgb2gray(I);
scf(0); clf(0);
ShowImage(I1G,'mixer');
rect1=rubberbox();
imheight=size(I1G,"r"); //image height
rect1(2)=imheight-rect1(2); //reverse y axes coordinates (0 is at top)
ROI1=imcrop(I1G,rect1);
scf(1); clf(1);
ShowImage(ROI1,'ROI1');

OpenGL Vertical Flip: -360 + -360 = 0?

I am working with OpenGL and I wanted to invert the image. So I went here, asked a question and finally I had the following code:
glMatrixMode(GL_PROJECTION);
glScalef(-1,1,1);
glTranslatef(-width(),0,0);
From what I understand from this, the position of every pixel gets inverted, so the pixels that were on the right of the image are now on the same absolute position, but are the left of the image, so I have to move the entire thing back exactly as many pixels as its wide: 360 (which is the size of the "canvas", so in the snippents the function width() is being used)! So to undo this process I would invert the image again and then move it back to where it came from:
glMatrixMode(GL_PROJECTION);
glScalef(-1,1,1);
glTranslatef(width(),0,0);
Nope, blackscreen. I have to do exactly the same thing twice to undo the flipping: I have to move with -360 every time I flip the image. Why?
It's exactly as Daniel Fischer mentioned in the comment. Here is an illustration of the process.
What you must have in mind is that the transformations operate on the transformed coordinate systems.
We start with the image (grey) on the screen (green):
Then we scale the image. So the origin is preserved, but the x-axis is mirrored.
No we have to move the image onto the screen again. Because the x-axis points to the left (but we want to move the image to the right), we have to use a negative offset for the translation:
If we flip the image again, the following happens. The origin is preserved and the x-axis is mirrored:
So we must translate the image by a negative offset:
Another way of undoing the flip is undoing the operations (but in the opposite order):
glTranslatef(width, 0, 0);
glScalef(-1,1,1);
The mathematical reason for that is that inversion reverses the oder. If we have Matrix A = B * C then A^-1 = (C^-1 * B^-1).

3D, AS3, Flex - Convert degrees of rotation to visible height

I need to know what the visible height of a display object will be after I change it's rotationX value.
I have an application that allows users to lay out a floor in 3D space. I want the size of the floor to automatically stretch after a 3D rotation so that it always covers a certain area.
Anyone know a formula for working this out?
EDIT: I guess what I am really trying to do is convert degrees to pixels.
On a 2D plane say 100 x 100 pixels, a -10 degree change on rotationX means that the plane has a gap at the top where it is no longer visible. I want to know how many pixels this gap will be so that I can stretch the plane.
In Flex, the value for the display objects height property remains the same both before and after applying the rotation, which may in fact be a bug.
EDIT 2: There must be a general math formula to work this out rather than something Flash/Flex specific. When viewing an object in 3D space, if the object rotates backwards (top of object somersaults away from the viewer), what would the new visible height be based on degrees of rotation? This could be in pixels, metres, cubits or whatever.
I don't have a test case, but off the top of my head I'd guess something like:
var d:DisplayObject;
var rotationRadians:Number = d.rotationX * Math.PI / 180;
var visibleHeight:Number = d.height * Math.cos(rotationRadians);
This doesn't take any other transformations into account, though.
Have you tried using the object's bounding rectangle and testing that?
var dO:DisplayObject = new DisplayObject();
dO.rotation = 10;
var rect:Rectangle = dO.getRect();
// rect.topLeft.y is now the new top point.
// rect.width is the new width.
// rect.height is the new height.
As to the floor, I would need more information, but have you tried setting floor.percentWidth = 100? That might work.
Have you checked DisplayObject.transform.pixelBounds? I haven't tried it, but it might be more likely to take the rotation into account.
Rotation actually changes DisplayObject's axis's (i.e. x and y axes are rotated). That is why you are not seeing the difference in height. So for getting the visual height and y you might try this.var dO:DisplayObject = new DisplayObject();
addChild();
var rect1:Rectangle = dO.getRect(dO.parent);
dO.rotation = 10;
var rect2:Rectangle = dO.getRect(dO.parent);
rect1 and rect2 should be different in this case. If you want to check the visual coordinates of the dO then just change dO.parent with root.

How do I rotate an image?

See also: Why is my image rotation algorithm not working?
This question isn't language specific, and is a math problem. I will however use some C++ code to explain what I need as I'm not experienced with the mathematic equations needed to express the problem (but if you know about this, I’d be interested to learn).
Here's how the image is composed:
ImageMatrix image;
image[0][0][0] = 1;
image[0][1][0] = 2;
image[0][2][0] = 1;
image[1][0][0] = 0;
image[1][1][0] = 0;
image[1][2][0] = 0;
image[2][0][0] = -1;
image[2][1][0] = -2;
image[2][2][0] = -1;
Here's the prototype for the function I'm trying to create:
ImageMatrix rotateImage(ImageMatrix image, double angle);
I'd like to rotate only the first two indices (rows and columns) but not the channel.
The usual way to solve this is by doing it backwards. Instead of calculating where each pixel in the input image ends up in the output image, you calculate where each pixel in the output image is located in the input image (by rotationg the same amount in the other direction. This way you can be sure that all pixels in the output image will have a value.
output = new Image(input.size())
for each pixel in input:
{
p2 = rotate(pixel, -angle);
value = interpolate(input, p2)
output(pixel) = value
}
There are different ways to do interpolation. For the formula of rotation I think you should check https://en.wikipedia.org/wiki/Rotation_matrix#In_two_dimensions
But just to be nice, here it is (rotation of point (x,y) angle degrees/radians):
newX = cos(angle)*x - sin(angle)*y
newY = sin(angle)*x + cos(angle)*y
To rotate an image, you create 3 points:
A----B
|
|
C
and rotate that around A. To get the new rotated image you do this:
rotate ABC around A in 2D, so this is a single euler rotation
traverse in the rotated state from A to B. For every pixel you traverse also from left to right over the horizontal line in the original image. So if the image is an image of width 100, height 50, you'll traverse from A to B in 100 steps and from A to C in 50 steps, drawing 50 lines of 100 pixels in the area formed by ABC in their rotated state.
This might sound complicated but it's not. Please see this C# code I wrote some time ago:
rotoZoomer by me
When drawing, I alter the source pointers a bit to get a rubber-like effect, but if you disable that, you'll see the code rotates the image without problems. Of course, on some angles you'll get an image which looks slightly distorted. The sourcecode contains comments what's going on so you should be able to grab the math/logic behind it easily.
If you like Java better, I also have made a java version once, 14 or so years ago ;) ->
http://www.xs4all.nl/~perseus/zoom/zoom.java
Note there's another solution apart from rotation matrices, that doesn't loose image information through aliasing.
You can separate 2D image rotation into skews and scalings, which preserve the image quality.
Here's a simpler explanation
It seems like the example you've provided is some edge detection kernel. So if what you want to is detect edges of different angles you'd better choose some continuous function (which in your case might be a parametrized gaussian of x1 multiplied by x2) and then rotate it according to formulae provided by kigurai. As a result you would be able to produce a diskrete kernel more efficiently and without aliasing.

Resources