Save graphics as image? - java

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.

Related

Java Swing: Erase part of image, exposing another image underneath

I have a JPanel with an two images (one underneath the other). The goal is for the user to be able to use the mouse the "scratch off" the top image and thus expose that part of the bottom image.
It is Erase part of image on Tkinter canvas, exposing another image underneath exactly except in Java Swing instead of Python.
Is this possible? I know you can use BufferedImage.getSubimage, but, as far as I can tell, this only works to crop the image.
Assuming your Image supports alpha transparency then you can just read the Image into a BufferedImage and then use the setRGB(...) method of the BufferedImage to clear the image:
BufferedImage image = ImageIO.read( new File( ... );
int transparent = new Color(0, 0, 0, 0).getRGB();
image.setRGB(??, ??, transparent);
So you would need to use a MouseListener to handle a MouseEvent to get the location of the pixels you want to make transparent.

How can I load images in the background in a Swing application?

I've got a simple Swing/AWT application that runs in full screen mode on Windows. I have a couple of different PNG files that it loads as its own background image depending on context.
It loads them like this:
BufferedImage bufferedImage;
bufferedImage = ImageIO.read(getClass().getResource("/bg1.png"));
Image bgImage1 = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
bufferedImage = ImageIO.read(getClass().getResource("/bg2.png"));
Image bgImage2 = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
bufferedImage = ImageIO.read(getClass().getResource("/bg3.png"));
Image bgImage3 = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
And later draws them like this:
window.repaint();
graphics.drawImage(bgImage1, 0, 0, null);
// draw some other stuff too, like text
And just to be thorough, window is a JWindow variable, and graphics is a Graphics2D variable.
The problem I'm running into happens when I switch out one of the background images for another. The first time I do the switch, calling something like this:
window.repaint();
graphics.drawImage(bgImage2, 0, 0, null);
// draw some other stuff too, like text
...the entire screen goes white for about a second. And then it does successfully show the image, but that flicker is really annoying. My guess is that because the images are relatively large and high resolution (2560x1440), it needs about a second to load them and scale them to the appropriate size.
How can I get it to load those images silently? As in... how do I avoid drawing a blank white screen for a second, that first time it displays a new background image? All subsequent times are already instantaneous, probably because it's truly grabbed them into memory at that point. But simply calling getScaledInstance apparently isn't enough to put things into memory, because it doesn't actually flicker until I call drawImage down the line.
ImageIcon will load in the background as a feature.
You can also accomplish this fairly easily with a background thread e.g.:
final String path = "/example.png";
new SwingWorker<BufferedImage, Void>() {
#Override
public BufferedImage doInBackground() throws IOException {
return ImageIO.read(ClassName.class.getResource(path));
}
#Override
public void done() {
try {
BufferedImage img = get();
// put img somewhere
} catch(InterruptedException ignored) {
} catch(ExecutionException ex) {
ex.printStackTrace(System.err);
}
}
}.execute();
Also,
window.repaint();
graphics.drawImage(bgImage2, 0, 0, null);
This worries me a little bit. In general we do not need to ask for a repaint of an entire top-level container. You should also not be using getGraphics() to paint.
Non-top-level Swing components are double-buffered but if you are painting outside of the paint structure you do not get this. It will result in flickering.
Two good sources for correct custom painting are:
Lesson: Performing Custom Painting
Painting in AWT and Swing
Painting should be done passively by overriding paintComponent on a JComponent. A JLabel can also display an ImageIcon as a feature so you do not necessarily have to do custom painting if you just want to display an image.
I notice that the scaling takes a lot of time, not the loading of the images.
Because of this, I usually store a scaled image so I can use it later on so I only have to scale once.

Java: GC transparent background

I am using GC (org.eclipse.swt.graphics.GC) to combine some pictures into one image (using drawImage). The problem is that, by default GC has got white background. Is it possible to set background to transparent? Or any other solution to cut part from one picture and paste into second?
Simply, GC is a pen, pen can't control canvas's transparency. It just can only draws something on canvas. So, GC can't manipulate image itself, just GC can draw something on Image.
However, You can directly control transparency data with ImageData API.
You should have to know what there is no advanced drawing API except setPixel(x, y, pixel), setAlpha(x, y, alpha) on ImageData.
You could use a Canvas with no background
Canvas canvas = new Canvas(parent, SWT.NO_REDRAW_RESIZE | SWT.NO_BACKGROUND);
And then you could (like in this example) make one(or more) colors of the image transparent.
ImageData ideaData = new ImageData(getClass().getResourceAsStream("Idea.jpg"));
int whitePixel = ideaData.palette.getPixel(new RGB(255,255,255));
ideaData.transparentPixel = whitePixel;
Image transparentIdeaImage = new Image(display,ideaData);

Is it possible to add transparency to jpg in Java and Android

I want to load some images to the cloud, but I want to add some protections when someone views the photos and saves the images; they will not see anything because of the transparency.
would the code be common for Java and Android? I would like to prototype it in Java first.
I have found some code that combines two files. One file is my main file the other is a transparent file. The combined file does not have a transparent overlay.
Do I need to use an image drawing order?
http://www.developer.nokia.com/document/Java_Developers_Library_v2/GUID-D3E35E6F-0C45-48ED-B09D-F716E14C1C02/javax/microedition/amms/control/imageeffect/OverlayControl.html
BufferedImage image = ImageIO.read(new File("rose.jpg"));
BufferedImage overlay = ImageIO.read(new File("myimg1.gif"));
// create the new image, canvas size is the max. of both image sizes
int w = Math.max(image.getWidth(), overlay.getWidth());
int h = Math.max(image.getHeight(), overlay.getHeight());
BufferedImage combined = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
// paint both images, preserving the alpha channels
Graphics g = combined.getGraphics();
g.drawImage(image, 0, 0, null);
g.drawImage(overlay, 0, 0, null);
// Save as new image
ImageIO.write(combined, "PNG", new File("combined.png"));
This won't work. If they can see the image, they can copy it, one way or another. A solution to consider is providing watermarked thumbnails at no charge, then only offering the full resolution image for a fee. However, they can still copy the full resolution image once they pay.
You can actually put a trans image as an overlay to the orginial image, that will
Protect from download, I think this is usually done by the server side aka your cloud
I know from some websites that they use some kind of an overlay such as yours
And the browser can't see the image below so you can't download.
I actually didn't understand how you implementing this - the image is opened in the browser?
Just a wild though, you can also cut the image into pieces like a jigsaw puzzle
The device won't have problems connecting it togther but when you download you'll
Download only "one piece of the puzzle" :-P

Java applet stutters on first time drawing a BufferedImage (Java2D)

I am writing a game as a java applet using the Java2D libraries along with the BufferedImage class. The game stutters (2-3 seconds) the very first time an image is drawn. The BufferImage files are all loaded before the game begins, using this method:
bufferedImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
try {
URL url = new URL(a.getCodeBase(), "images//smoke5frames.png");
bufferedImage = ImageIO.read(url);
} catch (IOException e) { e.printStackTrace(); }
mSmoke = bufferedImage;
To draw the image, I am using this method:
public void draw(Graphics2D g) {
g.drawImage(mTextures[iCurrentFrame], mAffineTransform, null); }
The images in question are SheetedSprites, typically cut from a sprite sheet using:
for each frame in animation...
myBufferedImage.getSubimage(i * iFrameWidth, 0, iFrameWidth, iHeight);
Which is done during game play when the entity is created. Removing this line did not solve the problem, so I am assuming (perhaps poorly) getSubimage() isn't expensive enough to cause the issue.
I could loop though each and every frame of animation and draw them all for a quick-fix, but I'd like to understand more about the problem and why it happens.
The kicker is that once the SheetedSprite has been drawn once, you can refresh the page and the problem doesn't occur again. The game runs perfectly smoothly after everything has been drawn before. This is the case in both IE and Chrome (I haven't tried it on any other browsers). As a side note, the problem never occurs in Eclipse's Applet Viewer.
My best guess is that the images are somehow cached by the browser, though really I'm stumped. I haven't tried loading/drawing images with a different set of graphical libraries either (Slick2D, LWJGL, etc). Thanks for any suggestions!
I had this problem about 2 years ago, and I found a fix for it on the great Java-gaming.org. The problem for me, was that Java has a problem with certain kinds of png-files. Some would cause lag when utilized for the first time, and some wouldn't. This "fixer-upper-method" takes a BufferedImage, and returns a BufferedImage, but in between, it does some magic, that makes the image easier for Java to decode (don't ask me how).
Enjoy!
private BufferedImage toCompatibleImage(BufferedImage image)
{
if(image==null)System.out.println("Image is null");
// obtain the current system graphical settings
GraphicsConfiguration gfx_config = GraphicsEnvironment.
getLocalGraphicsEnvironment().getDefaultScreenDevice().
getDefaultConfiguration();
/*
* if image is already compatible and optimized for current system
* settings, simply return it
*/
if (image.getColorModel().equals(gfx_config.getColorModel()))
return image;
// image is not optimized, so create a new image that is
BufferedImage new_image = gfx_config.createCompatibleImage(
image.getWidth(), image.getHeight(), image.getTransparency());
// get the graphics context of the new image to draw the old image on
Graphics2D g2d = (Graphics2D) new_image.getGraphics();
// actually draw the image and dispose of context no longer needed
g2d.drawImage(image, 0, 0, null);
g2d.dispose();
// return the new optimized image
return new_image;
}

Categories

Resources