Most of the time, the abstraction you get in Java is brilliant. It hides the complexity and lets you get on with real-life problem solving. This is especially true of the Image classes where you can forget about Tiffs, PNGs and Jpegs and just work with images.
Occasionally though you need to dig deeper and here you can find things are more complex. For example, you sometimes want to access the actual data inside an image (the raster data). We use this to downsample images in our PDF library – if the image in the PDF file is 5000×5000 pixels, you can shrink it down to more a manageable size. This saves a lot of memory and makes things much faster without any noticeable loss of image quality. Indeed, with black and white images, you can improve image quality!
A BufferedImage contains the actual pixel and color data. You can access these directly but then you need to starting thinking more concretely in terms of actual physical data structures. The pixel data is stored in the Raster object (actually it is an interface as you will see below). Obtaining a Raster and the data it contains is easy in Java…
BufferedImage image = myImage;//or whatever
The interesting thing here is that we are now accessing the underlying data which may be stored in different ways, depending on the type of image and even Java implementation. In particular, it may be a set of 8 bit byte values or 32 bit integer values – the DataBuffer is just an abstraction.
So the next stage is to see which is being used and then handle the data accordingly
if(data instanceof DataBufferInt)
type=1; //its a set of ints
You get a similar issue when directly creating a Raster – here is an example….
ras=Raster.createInterleavedRaster(new DataBufferByte(newData,newData.length), newW, newH, newW*comp, comp, bands, null);
So a BufferedImage is a very useful generic object in Java. But if you want to manipulate the raw data, you need to take some care depending on what sort of image you are using.