Skip to main content

gray scale images using int elements - why does this work?

Please note these java.net forums are being decommissioned and use the new and improved forums at https://community.oracle.com/community/java.
2 replies [Last post]
yahugh
Offline
Joined: 2009-04-27

My application requires me to operate on gray scale images in which the elements are >16 bit integers. Through trial and error I've found that the following code does what I need it to do.

import java.awt.image.DataBufferInt;
import java.awt.image.BandedSampleModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;


public class BufferedImageTest {

    public static void main(String[] args) {
        int M = Integer.MAX_VALUE;
        int[] inputArray = {M, 0,     0,     0,
                            0, M - 1, 0,     0,
                            0, 0,     M - 2, 0,
                            0, 0,     0,     M - 3};      
        int width = 4;
        int height = 4;
        int numBands = 1;
        DataBufferInt inputDataBuffer =
                new DataBufferInt(inputArray, inputArray.length);
        BandedSampleModel sampleModel =
                new BandedSampleModel(inputDataBuffer.getDataType(), width, height, numBands);
        WritableRaster inputRaster =
                Raster.createWritableRaster(sampleModel, inputDataBuffer, new Point(0, 0));
        ///////// why does this work? /////////
<strong>        </strong>BufferedImage inputBufferedImage =                
                new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        ///////////////////////////////////////
        inputBufferedImage.getRaster().setDataElements(0, 0, inputRaster);
     
        AffineTransform affineTransform = new AffineTransform();
        affineTransform.setToRotation(java.lang.Math.PI,2.5,2.5);
        AffineTransformOp affineTransformOp =
                new AffineTransformOp(affineTransform,AffineTransformOp.TYPE_BILINEAR);
        BufferedImage outImage = affineTransformOp.filter(inputBufferedImage, null);
      
        int newWidth = outImage.getWidth();
        int newHeight = outImage.getHeight();
        for (int r=0; r&lt;newHeight; r++) {
            for (int c=0; c&lt;newWidth; c++) {
                int x = outImage.getRaster().getDataBuffer().getElem(c + r*newWidth);
                System.out.print(x + &quot;\t&quot;);
            }
            System.out.println();
        }

    }
}

When I run the above code I see inputArray rotated by 180 degrees, as expected. (The array is padded with an additional row and column of zeros, which I'm still trying to understand.) The part that confuses me is the use of the BufferedImage constructor with the image type BufferedImage.TYPE_INT_ARGB. Why does this work?

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
rgd
Offline
Joined: 2005-08-23

I'm not 100% sure about this (and the code is impossible to read - lost
all the line breaks!). But I think the INT_ARGB says to interpret the
integer as 4 byte components... alpha, r,g,b. So if the pixels are
really 4-byte ints, that doesn't match. Interpolation specifically
would look at each byte separately rather than the int as a whole.

The reason it works I suspect is due to the 180 degree rotation. A
rotation of exactly 180 degrees doesn't require any interpolation, so
the pixels are simply moved around without any calculation. If you did
an angle of something other than 90, 180, or 270, it might fall apart.

-Bob

On 11/28/11 11:21 AM, forums@java.net wrote:
> My application requires me to operate on gray scale images in which the
> elements are >16 bit integers. Through trial and error I've found that the
> following code does what I need it to do.
>
> import java.awt.image.DataBufferInt; import
> java.awt.image.BandedSampleModel;
> import java.awt.image.Raster; import java.awt.image.WritableRaster; import
> java.awt.Point; import java.awt.image.BufferedImage; import
> java.awt.geom.AffineTransform; import java.awt.image.AffineTransformOp;
> public class BufferedImageTest { public static void main(String[] args)
> { int
> M = Integer.MAX_VALUE; int[] inputArray = {M, 0, 0, 0, 0, M - 1, 0, 0,
> 0, 0,
> M - 2, 0, 0, 0, 0, M - 3}; int width = 4; int height = 4; int numBands = 1;
> DataBufferInt inputDataBuffer = new DataBufferInt(inputArray,
> inputArray.length); BandedSampleModel sampleModel = new
> BandedSampleModel(inputDataBuffer.getDataType(), width, height, numBands);
> WritableRaster inputRaster = Raster.createWritableRaster(sampleModel,
> inputDataBuffer, new Point(0, 0)); * BufferedImage inputBufferedImage = new
> BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);*
> inputBufferedImage.getRaster().setDataElements(0, 0, inputRaster);
> AffineTransform affineTransform = new AffineTransform();
> affineTransform.setToRotation(java.lang.Math.PI,2.5,2.5); AffineTransformOp
> affineTransformOp = new
> AffineTransformOp(affineTransform,AffineTransformOp.TYPE_BILINEAR);
> BufferedImage outImage = affineTransformOp.filter(inputBufferedImage,
> null);
> int newWidth = outImage.getWidth(); int newHeight =
> outImage.getHeight(); for
> (int r=0; r outImage.getRaster().getDataBuffer().getElem(c + r*newWidth);
> System.out.print(x + "\t");
> } System.out.println();
> } } }
> When I run the above code I see inputArray rotated by 180 degrees, as
> expected. (The array is padded with an additional row and column of zeros,
> which I'm still trying to understand.) The part that confuses me is the use
> of the BufferedImage constructor with the image type
> BufferedImage.TYPE_INT_ARGB. (See highlighted code.) Why does this work?
>
>

yahugh
Offline
Joined: 2009-04-27

I used the 180 degree rotation in the above example because it makes it easy to see the numerical results. When I set the rotation to 0.0001*PI, the output equals the input with just a slight difference in the (1,0) and (3,3) elements. Lastly, when I use an actual image with arbitrary scaling, rotation and shear, I get reasonable results.