简体   繁体   中英

Write in 5-5-5 RGB and read in RGBA, BufferedImage

What I want to do can be explained shortly. Let's consider a number "x". I operate on an image with TYPE_USHORT_555_RGB. I use setRGB(x), save the image. Unfortunately Java obligates me to read the resulting image with TYPE_INT_ARGB through getRGB. How can I find my initial x? What worries me the most is that while some numbers read through getRGB are equal between them, this pattern of equivalence is not respected in the source, here's what I mean:

READ: -16777216 -16777216 -16777216 -16777183 -16777117 -16777101 -16777093 -16777101

SOURCE: 00 00 00 20 66 74 79 70 (in HEX)

The numbers in position 6 and 8 are equal in the read file, but different in the source (74 != 70)

//Write part:
BufferedImage img=new BufferedImage(8, 1, BufferedImage.TYPE_USHORT_555_RGB);
      for(int q=0;q<8;q++)
          img.setRGB(q,0,realVal[q]);//realVal contains the hex values
  File f= new File("randomfile.bmp");
  ImageIO.write(img, "bmp", f);

//Read part:
BufferedImage img;
        try{
        img=ImageIO.read(new File("randomfile.bmp"));
        for(int q=0;q<8;q++)
            System.out.println(img.getRGB(q,0));
        }catch(Exception e){}

The BufferedImage.TYPE_USHORT_555_RGB type uses a packed 15 bit (or 16 bit, but the 16th bit is not used) representation for pixels, where each R, G and B sample uses 5 bits.

The BufferedImage.getRGB(...) methods on the other hand, are convenience methods for getting/setting the color of a single or a group of pixels, and always operates on a packed 32 bit ARGB representation, where each A, R, G and B sample uses 8 bits (and the color model is always sRGB), just like TYPE_INT_ARGB as you say. Because of this difference in representation, the 5 bit samples needs to be "scaled" to 8 bits (and back) for retrieval/storage, which is slow and may create rounding/truncating errors.

However, you don't need to use this representation if you don't like to. Instead, you can access the " ushort " (Java does not have unsigned integral types, so they are stored as short s) directly through the Raster / DataBuffer :

DataBufferUShort dataBuffer = (DataBufferUShort) image.getRaster().getDataBuffer();
short[] data = dataBuffer.getData(); // Get the backing array

Any changes to the backing array will be reflected in the image (it's a "live" view). Also, accessing the backing array will most likely disable any chances of hardware acceleration, but that may not be an issue (it's not in the code you posted, as it only reads/writes the image, no display).


That said, you should consider @gpasch's comment, and see if you could just use the TYPE_INT_RGB or TYPE_INT_ARGB models, as they are usually easier to work with (especially if you don't like bit twiddling).

And a final warning: Not all file formats will support the TYPE_USHORT_555_RGB pixel layout. BMP does though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM