Difference between the Image and BufferedImage in Java - java

What is the difference between Image and BufferedImage?
Can I create a BufferedImage directly from an Image source "image.png"?

If you are familiar with Java's util.List, the difference between Image and BufferedImage is the same as the difference between List and LinkedList.
Image is a generic concept and BufferedImage is the concrete implementation of the generic concept; kind of like BMW is a make of a Car.

Image is an abstract class. You can't instantiate Image directly. BufferedImage is a descendant, and you can instantiate that one. So, if you understand abstract classes and inheritance, you'll understand when to use each.
For example, if you were using more than one Image descendant, they're going to share some common properties, which are inherited from Image.
If you wanted to write a function that would take either kind of descendant as a parameter you could do something like this:
function myFunction(Image myImage) {
int i = myImage.getHeight();
...
}
You could then call the function by passing it a BufferedImage or a VolatileImage.
BufferedImage myBufferedImage;
VolatileImage myVolatileImage;
...
myFunction(myVolatileImage);
myFunction(myBufferedImage);
You won't convert an Image to a BufferedImage because you'll never have an Image.

What is the difference between Image and BufferedImage?
As stated in the Oracle Java tutorial for working with Images
The java.awt.Image class is the superclass that represents graphical images as rectangular arrays of pixels.
The java.awt.image.BufferedImage class, which extends the Image class to allow the application to operate directly with image data (for example, retrieving or setting up the pixel color). Applications can directly construct instances of this class.
The BufferedImage class is a cornerstone of the Java 2D immediate-mode imaging API. It manages the image in memory and provides methods for storing, interpreting, and obtaining pixel data. Since BufferedImage is a subclass of Image it can be rendered by the Graphics and Graphics2D methods that accept an Image parameter.
A BufferedImage is essentially an Image with an accessible data buffer. It is therefore more efficient to work directly with BufferedImage. A BufferedImage has a ColorModel and a Raster of image data. The ColorModel provides a color interpretation of the image's pixel data.
Can I create a BufferedImage directly from an Image source "image.png"?
Sure.
BufferedImage img = ImageIO.read(getClass().getResource("/path/to/image"));

Related

Serializing Canvas objects in Java

I am trying to serialize a Canvas instance (using the Serializable interface) on which I have painted some pixels like the following code suggests:
Canvas board = new Canvas();
Graphics g = board.getGraphics();
g.setColor(Color.BLACK);
g.drawString("txt", 10, 20);
g.dispose();
Then when I serialize board it doesn't save the pixels I've painted. I'm guessing this is because by using getGraphics() I am not saving those pixels to any instance, so I thought that perhaps I should instead paint from within the Canvas's paint() method. Would serializing the Canvas then save the modified pixels too? If not, what are my options to save/serialize a Canvas with the pixels I've modified? I am guessing I would have to serialize the Graphics object instead of the Canvas? I am new to Java graphics, any help will be greatly appreciated.
To be more clear, what I'm trying to do is have the pixels I've put on a Canvas instance saved to a file using serialization. Then later I need to reload this Canvas instance from the serialized file I saved earlier, so that when I use it on the screen I see the exact same pixels I modified just before I serialized the Canvas. I know how to serialize objects and all that. I am just unclear where all the pixels are stored.
Update1:
The way the user draws something on the screen is by left-clicking on the Canvas area. Then MouseListener calls the following method, passing along the Point object specifying the mouse xy:
private void drawAt(Point p)
{
Graphics g = board.getGraphics();
g.setColor(brushColor);
g.setFont(brushFont);
g.drawString(brushText, p.x, p.y);
g.dispose();
}
Don't serialize Canvas or any other GUI components as you'd be serializing the "View" portion of your program, a risky thing to do (high risk for serialization exceptions due to attempting to serialize and unserialize unserializable sub components) and an inefficient thing to do -- serializing large amounts of data which are built automatically by the JVM and thus don't need serialization.
Instead you will want to serialize the "Model" portion of your data, that portion which holds the logical data of your program. So if your GUI is drawn using data held by an ArrayList, or a collection of ArrayLists, or whatever data it takes, then serialize that data. Then be sure to create your GUI so that can be built using the serialized data.
Or if you need to store an image, then store an image, probably best as a loss-less png file.
Also, I suggest that you draw into a BufferedImage, that you then display that BufferedImage within the paintComponent method override of a JPanel, and that you then save and restore the image. For more on how to draw and save, please have a look at these links. The first two contain my code, the third is that of MadProgrammer's:
Save image from JPanel after draw,
Convert a Graphics2D to an Image or BufferedImage and
Paint BufferedImage on JFrame and write to File.

Why use ImageIcon rather than Image?

In what instance would I want to use ImageIcon to represent a picture file rather than an Image object? I've been searching and I've seen people say that you would use an ImageIcon object when dealing with images that will be part of the GUI, but I still don't understand the implications of this. In other words, what is the actual difference between the two object types and what situations are they each suited for?
Image is an object that represents a bitmap: an array of pixels of different colors.
Icon is an object that can draw a rectangular piece of graphics. Since it is an interface (and a simple one too), you can imagine many different types of icons: drawing predefined vector graphics, generating images on the fly etc. Therefore it is a useful abstraction and is used by Swing components (buttons, labels).
ImageIcon is an object that IS an Icon, but HAS-A Image. That is - it draws graphics based on a specific image.
When you say "why should I be using an ImageIcon instead of Image" you miss the point: in fact you are using an Image either way.
An Image is an object representing the data model of a picture. An ImageIcon is a Swing component that draws an Image on the screen, and you have to provide it with the appropriate Image to draw (either by passing in an existing Image or by giving it enough information to find and load the image).
The relationship is similar to that between a String and a JTextField; one is the representation of the data, and the other is the graphical component that draws it on the screen.
The implementation is to not hold up the Swing thread.
Images that are created from a URL, filename or byte array are preloaded using MediaTracker to monitor the loaded state of the image.
Basically, then you can set an ImageIcon for a button without actually forcing it to be loaded beforehand.
This can be seen by having a very large icon and setting the Frame's icon to this image. Once set visible, it may take a few seconds to actually appear.

Java - Creating an image

I'm currently working on a game in Java and am trying to create a background without using any image files. The image consists of a square split into 4 triangles, each of which is a different color.
If anyone could point me towards some was of using Graphics2D and then saving it to a BufferedImage, that would be great.
I recommend:
First create a BufferedImage using the constructor that takes three ints: a width, height, and a BufferedImage type, BufferedImage.TYPE_INT_ARGB would probably work well, and the width and height will likely be constants in your program.
You would extract a Graphics2D object out of the BufferedImage by calling its createGraphics() method.
Then draw with the Graphics object using its drawXXX(...) methods of which you have many to select from.
To change color, simply call setColor(Color c) on your Graphics/Graphics2D object.
When done drawing, be sure to dispose of your Graphics object via its dispose() method.
Edit as per Adrian Blackburn, check out the BufferedImage Tutorial as part of the standard Oracle Java tutorials.

Height of java.awt.Graphics underlying device?

I'm drawing a histogram (custom data, not related to coloring) on an BufferedImage. And I'd like to make it as wide and tall as possible. Can I do this passing only BufferedImage.createGraphics result to my drawing function? I can't find how to obtain image dimensions through an instance of Graphics.
Can I do this passing only BufferedImage.createGraphics result to my drawing function?
I recommend to pass either:
The BufferedImage itself or
The Graphics instance and a Dimension (unless the plot only requires height, as opposed to WxH - then use an int).

Resizing TYPE_CUSTOM BufferedImages?

When I read a JPEG from disk, Java sometimes gives me a BufferedImage whose getType() returns TYPE_CUSTOM -- that is, it has a custom color model. I'd like to resize this BufferedImage but I'm not sure how to construct the destination object. Can someone please provide sample code for using the following constructor?
BufferedImage(ColorModel cm, WritableRaster raster, boolean isRasterPremultiplied, Hashtable properties)
I would like to create a BufferedImage of the same type as the source, just bigger, and transfer the contents over. Any ideas?
Answering my own question, it looks like ImageTypeSpecifier is the answer. Specifically:
Invoke ImageTypeSpecifier.createFromRenderedImage(RenderedImage image) to get back an ImageTypeSpecifier from the image with the custom color model.
Invoke ImageTypeSpecifier.createBufferedImage(int width, int height) on the ImageTypeSpecifier from step 1 to create a new image with the same color model as the original image.

Categories