Domanda

I've written image processing code that copies the pixel data into integer array like this:

void processImage(BufferedImage source) {

    WritableRaster raster = source.getRaster();
    int numBands = raster.getNumBands();
    int height = raster.getHeight();
    int width = raster.getWidth();

    int[] pixelRow = new int[width * numBands];
    for (int i = 0; i < height; i++) {
        raster.getPixels(raster.getMinX(), raster.getMinY() + i, width, 1, pixelRow);

        // do some processing
    }

    // create a new image
    return newImage;
}

The code works with the images I've tested so far. The pixelRow array seems to always receive the pixel components in the order Red, Green and Blue for images with 3 bands (no alpha channel) and in the order Red, Green, Blue and Alpha for those with 4 bands (with alpha channel).

However, I cannot find any description that states this. Is it guaranteed that I will always get the pixel components in that order? Is there any specification that describes this?

È stato utile?

Soluzione

The SampleModel.getPixel() (used internally by the Raster.getPixel()) returns pixel components in the order of bands. While it is possible to create a bogus instance of SampleModel programmatically with the band order different from the RGB, usually instances of the SampleModels are created by some ColorModel which constructs the SampleModel with bands in the same order as the order of color components in the ColorModel.

The order of color model components is documented in the java.awt.image.ColorModel javadoc:

The number, order, and interpretation of color components for a ColorModel is specified by its ColorSpace.

In theory you should check whether the color space is from the RGB family:

public static void processImage( BufferedImage source )
{
    ColorSpace colorSpace = source.getColorModel().getColorSpace();
    if ( dumpColorSpaceProperties ) {
        System.out.printf( "color space type: %d, is RGB = %s%n", colorSpace.getType(), colorSpace.isCS_sRGB() );
        for ( int i = 0; i < colorSpace.getNumComponents(); i++ ) {
            System.out.printf( "component %d = %s%n", i, colorSpace.getName( i ) );
        }
    }

    if ( colorSpace.getType() == ColorSpace.TYPE_RGB ) {
        // guaranteed RGB(A) order, proceed with raster.getPixels()
    } else {
        // well, find a way to convert from that space into RGB
        throw new AssertionError( "color space type = " + colorSpace.getType() );
    }
}

In practice it all depends on the source of the image. Images created via BufferedImage(width, height, imageType) always use RGB space. Images obtained from a file can use some other color space if the image file format supports different color space and if that particular image file uses non-RGB space.

If you know the image source you do not need to check the color space and you can assume the RGB(A) output from the Raster.getPixels().

The ColorSpace.getName(int) source provides insight into default components for most color sets that can be encountered in practice.

Altri suggerimenti

A Raster object includes a SampleModel. The SampleModel describes the pixel layout within the Raster object.

Here are some links:

This document PNG Specification seems to suggest that the order you described is, in fact, standard. Section 3.1.44 implies as much. However, in other cases involving colors it seems the usual is [alpha,] red, green, blue as described by Microsoft here. Seeing as several methods in classes of the java.awt.image package use or return a similar array of samples, it should be pretty safe to assume that this order is standard. Despite this, I could not find one instance where this behaviour was specified.

I don't have the definitive answer either. But the relevant information is more likely found in the ColorModel instance (rather than in the Raster or SampleModel instances).

The ColorModel instance is directly accessible from the BufferedImage.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top