How to mask a grid BufferedImage displayed on top of a background BufferedImage - merge

First question here, quite new at java (and english not my native language), please be indulgent :)
Didn't find any similar issue.
I am trying to make a 2D game (turn by turn, so no real time issue). My map is displayed in a JPanel with a mix of images for background, grid, and movable objects.
All images are loaded and stored once before displayed. I have a BufferedImage for the background, an other one on which I draw the grid, and lots of images for other objects.
In the paintComponent(), I draw all BufferedImages on the Graphics2D (cast from the Graphics parameter).
My issue is to mask the grid when the player choose to (or when scale is too big, with variables "ruleGrid" and "zoom" respectively). The test text output is correctly logged but the grid is visible anyway.
Both images seems to be merged and I can't mask the 2nd one.
I have tried to display the grid elsewhere (other coordinates) and it works well. But if both images are overlapping, then the grid part on the other image stays (as if drawn on the first one, and not on the JPanel).
Sorry if it isn't clear enough...
Some screenshots might help :
Grid and background with same coordinates
Grid and background with different coordinates
When scrolling and zooming out : here is the problem. The overlapping part of the grid is still 'printed' on the background image and the rest of the grid is shown 'under' the background.
Why is it happening ? What did I do wrong ? Is it due to an optimization/render from the Graphics2D Class ? Should I rather use Layered Panes ?
For both BufferedImages, I use :
BufferedImage.TYPE_INT_ARGB
.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
Here is a simplication of my code :
BufferedImage mapZones;
BufferedImage mapGrid;
#Override
public void paintComponent(Graphics g1){
Graphics2D g = (Graphics2D)g1;
//Clear the map
clearBackground(g);
//Display Background
displayMap(g, mapZones);
//Grid
if (Options.ruleGrid && Options.zoom > 4f) {
displayMap(g, mapGrid);
System.out.println("Test if grid should be displayed");
}
}
/*********************************************************************************************************/
private void displayMap(Graphics2D g, BufferedImage bufI) {
g.drawImage(bufI, -x0, -y0, width, height, null);
}
/*********************************************************************************************************/
private void clearBackground(Graphics2D g1) {
g1.setColor(Color.WHITE);
int max = 500000;
g1.clearRect(-max, -max, max*2, max*2);
}
/*********************************************************************************************************/
Any help would be appreciated. Thanks.

Find the reason (though, not the 'why ?').
I had a 3rd call to 'displayMap' with an empty image
//Display Elements
displayMap(g, mapElements);
which is created by
mapElements = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
and I have not yet drawn onto it.
When I comment the call to 'displayMap(g, mapElements);', I finally have the desired behaviour.
But I still don't know why ? I think it's the way the Graphics Class and the 'drawn' functions are coded :
This method returns immediately in all cases, even if the complete image has not yet been loaded, and it has not been dithered and converted for the current output device.
I guess the JVM somehow 'pools' (?) the drawings in the same area and my maps were merged...
If anyone could explain this in a simple manner...

Related

overlapping elements in grid layout

In my game i add child object prefabs to a grid layout dynamically,
But the problem is when i do this the child objects overlap:
If i do this without code, the problem disappears but i want to do it through code.
instantiation code is fairly simple:
go = Instantiate(CardPrefab) as GameObject;
// go.GetComponent<Image>().sprite = card.GetSprite();
go.GetComponent<Image>().sprite = GC.GetSprite(1, card.GetIndex());
go.transform.GetChild(0).gameObject.SetActive(true);
go.transform.SetParent(GameObject.Find("Player1ScrollPannel").transform);
what is the solution?
there is nothing attached to my card prefab, just an image and a button as a child:
Note: I haven't really played with layout groups, but...
70 pixels times a scale of 8.34 results in a final size of 583.8, but you're asking your layout group to arrange things in 106 pixel-wide cells.
In pulling up Unity and shoving a few images with a high scale value into a layout group...I get the same behavior. You either need to remove the scale (1,1,1) or change the layout cell size.

Unity Resizing Dropdown Dynamically

I have a dropdown list on a filter panel which needs to stretch dynamically to fit the content as shown:
I have tried several content size fitters but cannot find anything, If possible I would like to set a max width it can expand to then truncate everything longer than that, I would also like it to expand only to the right with a right pivot point. I have found a similar example here: https://forum.unity3d.com/threads/resize-standard-dropdown-to-fit-content-width.400502/
Thanks!
Well. Lets start with the code from that Unity forum thread.
var widest = 0f;
foreach (var item in _inputMines.GetComponentsInChildren<Text>()) {
widest = Mathf.Max(item.preferredWidth, widest);
}
_inputMines.GetComponent<LayoutElement>().preferredWidth = widest + 40;
We want to have a max-width allowed, so any content longer than this will be truncated. So let's add that variable:
var maxWidth = 250f;
//or whatever value; you may wish this to be a property so you can edit it in the inspector
var widest = 0f;
foreach (var item in _inputMines.GetComponentsInChildren<Text>()) {
Now we use the smaller of the two width values. Then apply it to the content layout:
}
widest = Mathf.Min(maxWidth, widest);
_inputMines.GetComponent<LayoutElement>().preferredWidth = widest + 40;
The +40 should be retained because that deals with the scrollbar. Your maxWidth value should be chosen to account for this.
Finally we want the longer items to get cut off nicely.
Give each dropdown item a Rect Mask 2D component (Component -> UI -> Rect Mask 2D). The template object exists in the scene hierarchy before the game is run, just disabled. You can just add the component to the parent transform, the one with the image (so the text is clipped).
You'll need to make sure that the mask covers the same width as the image graphic and expands along with it, possibly slightly shorter on the X direction so the text gets cut off before the image border is drawn. This should happen automatically, but you will need to check and possibly make some alterations to the template object. Alternatively you can use an Image Mask, but you'll have to play with that one yourself, but it will allow for non-rectangular clipping.
That's it!

Center image in group JavaFX

I'm trying to make some figures in JavaFX. I can create these figures with the Polygon class or in this case with the Circle class. But I want to add an image on top of it. So I'm using a group for this with 2 elements, the figure and the image in an ImageView. But if I use this group, the image isn't in the middle. I would like to center the image. I also would like to be able to drag and drop it with a mouse, so then it needs to stay in the middle. I've tried it with a circle and a polygon but in both cases the image was in the bottom right corner.
Edit: I just figured out that you can move your image with setX and setY, but this isn't an easy way to center the image.
Here's what I have at the moment:
public class Figure extends Group {
public Figure() {
Circle circle = new Circle(100);
ImageView imageView = new ImageView();
circle.setFill(Color.BLUE);
circle.setStroke(Color.BLACK);
Image image = new Image("images/blue/bike.png");
imageView.setImage(image);
imageView.setFitWidth(100);
imageView.setPreserveRatio(true);
imageView.setSmooth(true);
imageView.setCache(true);
super.getChildren().addAll(circle, imageView);
}
The easiest solution would be to use a StackPane instead of a Group. That might give problems with clickability if you let them overlap: one of two Circles is then obscured by the other figure's StackPane.
Though a bit inelegant, I would do it with setX and setY as you propose.

Perspective correction of UIImage from Points

I'm working on a app where I'll let the user take a picture e.g of a business card or photograph.
The user will then mark the four corners of the object (which they took a picture off) - Like it is seen in a lot of document/image/business card scanning apps:
My question is how do i crop and fix the perspective according to these four points? I've been searching for days and looked at several image proccessing libraries without any luck.
Any one who can point me in the right direction?
From iOS8+ there is Filter for Core Image called CIPerspectiveCorrection. All you need to do is pass the image and four points.
Also there is one more filter supporting iOS6+ called CIPerspectiveTransform which can be used in similar way (skewing image).
If this image were loaded in as a texture, it'd be extremely simple to skew it using OpenGL. You'd literally just draw a full-screen quad and use the yellow correction points as the UV coordinate at each point.
I'm not sure if you've tried the Opencv library yet, but it has a very nice way to deskew an image. I've got here a small snippet that takes an array of corners, your four corners for example, and a final size to map it into.
You can read the man page for warpPerspective on the OpenCV site.
cv::Mat deskew(cv::Mat& capturedFrame, cv::Point2f source_points[], cv::Size finalSize)
{
cv::Point2f dest_points[4];
// Output of deskew operation has same color space as source frame, but
// is proportional to the area the document occupied; this is to reduce
// blur effects from a scaling component.
cv::Mat deskewedMat = cv::Mat(finalSize, capturedFrame.type());
cv::Size s = capturedFrame.size();
// Deskew to full output image corners
dest_points[0] = cv::Point2f(0,s.height); // lower left
dest_points[1] = cv::Point2f(0,0); // upper left
dest_points[2] = cv::Point2f(s.width,0); // upper right
dest_points[3] = cv::Point2f(s.width,s.height); // lower right
// Build quandrangle "de-skew" transform matrix values
cv::Mat transform = cv::getPerspectiveTransform( source_points, dest_points );
// Apply the deskew transform
cv::warpPerspective( capturedFrame, deskewedMat, transform, s, cv::INTER_CUBIC );
return deskewedMat;
}
I don't know exact solution of your case, but there is approach for trapezoid: http://www.comp.nus.edu.sg/~tants/tsm/TSM_recipe.html - the idea is to continuously build transformation matrix. Theoretically you can add transformation that converts your shape into trapecy.
And there are many questions like this: https://math.stackexchange.com/questions/13404/mapping-irregular-quadrilateral-to-a-rectangle , but I didn't check solutions.

Eclipse RCP Draw2d Transparency (setAlpha) makes borders / outline invisible

We are providing users option to make figures drawn on canvas transparent. To achieve this we are using method setAlpha(0). But this makes figure completely invisible.
Our requirement is that outline / border should be shown on transparent figures if user wishes to have borders.
We tried using method setOpaque(false). But it does not work.
We are using Ubuntu 9.1 OS.
Any suggestion to achieve this will be really helpful.
Regards,
Pankaj Sharma
You could extend the Shape you are using like this:
public class TranslucentRoundedRectangle extends RoundedRectangle
{
#Override
protected void fillShape(Graphics graphics)
{
int oldAlpha = graphics.getAlpha();
graphics.setAlpha(128);
super.fillShape(graphics);
graphics.setAlpha(oldAlpha);
}
}
This way you can set the alpha value for the filling independently of the outline.
setAlpha is applied to the whole figure, that is why it doesn't work for you. What you should probably do is create two figures one inside the other and change the alpha of the inner figure only. I can't think of another way to do it.
Good luck