Alternative(s) of converting Canvas to WritableImage - java

I'm developing an application which needs a lot of comparing image data in JavaFX. For that comparing, I need to to get rgb data of pixels in the images. Let's say that the picture I need to compare is Picture1 and Picture2. Picture1 is an input picture selected by the user. Picture2 is a drawing that I make programmatically.
AFAIK, the only way to get rgb data per pixel in JavaFX is with PixelReader of Image. It's fine for the Picture1 since it's an input. But I need to do a drawing on Picture2 and Picture2 is a Canvas (I draw polygons on Picture2 and because drawing pixel by pixel with PixelWriter is a bit complicated IMO) and doesn't have a PixelReader or something with similar functionality. So my solution is as follows:
Read input image and make Picture1
Make a Canvas and do the drawing
Attach the Canvas to a Scene
Make snapshot of the Scene and make WritableImage (Picture2)
Compare Picture1 and Picture2
So I have a method with something like:
public static WritableImage makeDrawableImage(Canvas in) {
AnchorPane root = new AnchorPane(in);
WritableImage out = new WritableImage((int)in.getWidth(), (int)in.getHeight());
Scene sc = new Scene(root, in.getWidth(), in.getHeight());
out = in.snapshot(null, null);
return out;
}
However it takes a really long time for the snapshot to finish. The value of out never gets assigned. I don't know what I did wrong.
Is there any alternative to convert Canvas to Image or WritableImage? Or maybe there is a library to do drawing of polygons easier with PixelWriter?
Please be soft on me. This is my first question on Stack Overflow and I'm not a real programmer nor an IT student. I code as a hobby.
So, thanks in advance. Cheers.

You can create a snapshot of a canvas with this method:
public static WritableImage pixelScaleAwareCanvasSnapshot(Canvas canvas, double pixelScale) {
WritableImage writableImage = new WritableImage((int)Math.rint(pixelScale*canvas.getWidth()), (int)Math.rint(pixelScale*canvas.getHeight()));
SnapshotParameters spa = new SnapshotParameters();
spa.setTransform(Transform.scale(pixelScale, pixelScale));
return canvas.snapshot(spa, writableImage);
}
The pixel scale normally is 1.0 unless you have a HiDPI screen.

Related

Shrinking JavaFX Graphics

I'm looking for a way of rendering a scene hidden from view and then creating a second shrunken copy for initial display. Plainly I could render the contents a second time to create this copy only smaller. The original code written in another language though produced a better result using a smooth (spatially filtered) shrinking function to create the small copy. Is there such a bitmap copy/shrink/smooth function in JavaFX and is it any good?
You can create a snapshot of a scene as a WritableImage as follows:
Scene scene = ... ;
Image image = scene.snapshot(null);
and then display a scaled version of it in an image view with:
ImageView sceneImage = new ImageView();
sceneImage.setFitWidth(desiredWidth);
sceneImage.setFitHeight(desiredHeight);
// force aspect ratio to be preserved if fitWidth and fitHeight would distort it:
sceneImage.setPreserveRatio(true);
// this provides a tiny bit of control over the scaling used:
sceneImage.setSmooth(true);
sceneImage.setImage(image);

How to make a BufferedImage work with this image? (java)

I've got this picture:
Imagine this as a 4x4 tile world of which the tiles are 32x32 pixels each.
then take a look at picture:
Look at the stone tile, it has edges which are outside the grid. Can I use a bufferedImage for this or do I need to do something else to make this work?
If so, could you help me with it by explain it because I've got no clue on how to achieve this is my game?
another example picture:
Let me explain it More Clearly... 1st image = Grid, 2nd Image = Tile Overlapping the grid... (thats what i want to have because then it's a new tile which I can use to make my game look better!), 3d Image = An example of how it would tile!
To completely eliminate boundary artifact, you can use Penrose tiles.
You can mitigate the edge artifact using anti-aliasing. This example uses TexturePaint with three variant shades of each color: original, darker and lighter. You can experiment with a larger number of shades for better results.
Simply use PhotoShop to edit the image to 32x32 pixel size....then use it in your game....
/////////////EDITED//////////////////
As shown here, AffineTransformOp offers the additional flexibility of choosing the interpolation type.
BufferedImage before = getBufferedImage(encoded);
int w = before.getWidth();
int h = before.getHeight();
BufferedImage after = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
AffineTransform at = new AffineTransform();
at.scale(2.0, 2.0);
AffineTransformOp scaleOp =
new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
after = scaleOp.filter(before, after);

combine two images one transparent to another under Android

I have an android project to process images, I have two images, I want to overlay one over another (blending). To combine these two images, it’s a bit simple, using drawing on canvas:
I used this code:
public static Bitmap overlay(Bitmap bottomImg, Bitmap topImg) {
Bitmap bmOverlay = Bitmap.createBitmap(bottomImg.getWidth(),bottomImg.getHeight(),bottomImg.getConfig());
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(bottomImg, new Matrix(), null);
canvas.drawBitmap(topImg, 0, 0, null);
return bmOverlay;
}
It works well, but It doesn’t manipulate the transparency of overlaed image. Actually I want the top image to be transparent, in order to see how it matches the bottom one. It’s something to access alpha channel or to do it manually, Can someone help me to do this task.
You can try :
topImg.eraseColor(Color.TRANSPARENT);
This will set all the pixels to transparent.

Save graphics as image?

I'm developing an app for BlackBerry with Eclipse and want to know if there is any way to save a picture that is drawn with a Graphics object...The app involves drawing a pie chart using Graphics.It works fine the first time I open the screen to display the chart but the next time I try to create the chart by calling the screen, it goes haywire.So I was wondering if I can save the chart as an image...that way I wont have to keep drawing over and over everytime I open the screen...Please help...Thanks in advance!
I understood you are using the java.awt.Graphics class, right?
Ensure you are drawing only on the AWT event thread.
Use
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// YOUR CODE
}
});
to run your saving code on the event thread. If you try to save from another thread, the image could get distorted if it is not drawn completely.
I don't know the blackberry API but you could take other aproach to your problem. You could do offscreen rendering. Create a BufferedImage, get a reference to its Graphics object, do the rendering and then save the BufferedImage as a png for example.
For example:
int width = 200, height = 200;
// TYPE_INT_ARGB specifies the image format: 8-bit RGBA packed
// into integer pixels
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D ig2 = bi.createGraphics();
// Draw your chart
ImageIO.write(bi, "PNG", new File("yourImageName.PNG"));
This way you can do all your drawing once, saving it as a file or just in memory (depends on what you need) and then you just need either to load the image from the file or do g.drawImage() in your screen.
But as i said before i don't know if this applies to the Blackberry API it works for sure with the JDK/JRE in a desktop.

Put together tiles in android sdk and use as background

In a feeble attempt to learn some Android development am I stuck at graphics. My aim here is pretty simple:
Take n small images and build a random image, larger than the screen with possibility to scroll around.
Have an animated object move around on it
I have looked at the SDK examples, Lunar Lander especially but there are a few things I utterly fail to wrap my head around. I've got a birds view plan (which in my head seems reasonably sane):
How do I merge the tiles into one large image?
The background is static so I figure I should do like this:
Make a 2d array with refs to the tiles
Make a large Drawable and draw the tiles on it
At init draw this big image as the background
At each onDraw redraw the background of the previous spot of the moving object, and the moving object at its new location
The problem is the hands on things. I load the small images with "Bitmap img1 = BitmapFactory.decodeResource (res, R.drawable.img1)", but then what? Should I make a canvas and draw the images on it with "canvas.drawBitmap (img1, x, y, null);"? If so how to get a Drawable/Bitmap from that?
I'm totally lost here, and would really appreciate some hands on help (I would of course be grateful for general hints as well, but I'm primarily trying to understand the Graphics objects). To make you, dear reader, see my level of confusion will I add my last desperate try:
Drawable drawable;
Canvas canvas = new Canvas ();
Bitmap img1 = BitmapFactory.decodeResource (res, R.drawable.img1); // 50 x 100 px image
Bitmap img2 = BitmapFactory.decodeResource (res, R.drawable.img2); // 50 x 100 px image
canvas.drawBitmap (img1, 0, 0, null);
canvas.drawBitmap (img2, 50, 0, null);
drawable.draw (canvas); // obviously wrong as draw == null
this.setBackground (drawable);
Thanks in advance
I finally figured it out, what I need for the basic problem of tiling a bunch of Bitmaps together was a BitmapDrawable:
Bitmap myImage = Bitmap.createBitmap(450, 300, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(myImage);
Bitmap img1 = BitmapFactory.decodeResource (res, R.drawable.img1); // 50 x 100 px image
Bitmap img2 = BitmapFactory.decodeResource (res, R.drawable.img2); // 50 x 100 px image
canvas.drawBitmap (img1, 0, 0, null);
canvas.drawBitmap (img2, 50, 0, null);
this.setBackgroundDrawable(new BitmapDrawable(myImage));
I obviously had it backwards with the relationship between Canvas and Bitmap, I thought Canvas was a blank screen on which to paint on. Apparently (if I got it right this time) it's connected to a Bitmap, and if having that one it's possible to use it.
I still wouldn't know how to get it in the onDraw(Canvas) function though, but this solves the problem I had.

Categories

Resources