Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6020273
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 23, 20262026-05-23T03:32:39+00:00 2026-05-23T03:32:39+00:00

In some Java code running on Windows, I’m reading some large blocks of RGB

  • 0

In some Java code running on Windows, I’m reading some large blocks of RGB data from disk and want to display this to screen as quickly as possible. The RGB data is 8 bits per channel without any alpha. Currently I have code like the following to create the BufferedImage.

BufferedImage getBufferedImage(File file, int width, int height) {

    byte[] rgbData = readRGBFromFile(file);

    WritableRaster raster = Raster.createInterleavedRaster(
        rgbData, width, height, 
        width * 3, // scanlineStride
        3, // pixelStride
        new int[]{0, 1, 2}, // bandOffsets
        null);

    ColorModel colorModel = new ComponentColorModel(
        ColorSpace.getInstance(ColorSpace.CS_sRGB), 
        new int[]{8, 8, 8}, // bits
        false, // hasAlpha
        false, // isPreMultiplied
        ComponentColorModel.OPAQUE, 
        DataBuffer.TYPE_BYTE);

    return new BufferedImage(colorModel, raster, false, null);
}

The problem is that the performance of rendering this to the screen is pretty slow. Around 250 – 300 ms. I’ve read that for the best performance you need to display in a BufferedImage that’s compatible with the screen. To do that, I pass the buffered image returned from the above method to a method like this.

BufferedImage createCompatibleImage(BufferedImage image)
{
    GraphicsConfiguration gc = GraphicsEnvironment.
        getLocalGraphicsEnvironment().
        getDefaultScreenDevice().
        getDefaultConfiguration();

    BufferedImage newImage = gc.createCompatibleImage(
        image.getWidth(), 
        image.getHeight(), 
        Transparency.TRANSLUCENT);

    Graphics2D g = newImage.createGraphics();
    g.drawImage(image, 0, 0, null);
    g.dispose();

    return newImage;
}

That method essentially converts it from RGB to ARGB on Windows and it really speeds up the displaying, but this method takes ~300 ms for a 1600 x 1200 RGB data block. So now I’ve basically traded the performance hit of the drawing problem to a converting problem.

300ms is about the same time as it takes to load the RGB data from disk. I would think I could do something faster.

Is there a better way I can do the conversion? Or would it help if I modified the RGB data and added an alpha channel myself beforehand? If so what would my Raster and ColorModel look like. Also, since my RGB data doesn’t contain transparency can I get any performance improvements by using pre multiplied alpha or something?

Sorry, bit I’m a little lost on this ColorModel, Raster stuff.

Thanks!

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-23T03:32:39+00:00Added an answer on May 23, 2026 at 3:32 am

    After playing around with this I have a decent answer that works for Windows if the current graphics configuration is using ARGB integer packed rasters.

    What I do is create the compatible BufferedImage first, then I manually convert my RGB bytes array to an ARGB int array. Then I get the Raster from the compatible BufferedImage and write my ARGB ints into it. This is much faster.

    I also have a class that checks if the compatible BufferedImage is in the format I expect, if it isn’t it defaults to the older slower approach.

    Here is the class. Hope it helps you.

    /**
     * This class can read chunks of RGB image data out of a file and return a BufferedImage.
     * It may use an optimized technique for loading images that relies on assumptions about the 
     * default image format on Windows.
     */
    public class RGBImageLoader
    {
        private byte[] tempBuffer_;
        private boolean fastLoading_;
    
        public RGBImageLoader()
        {
            fastLoading_ = canUseFastLoadingTechnique();
        }
    
        private boolean canUseFastLoadingTechnique()
        {
            // Create an image that's compatible with the screen
            GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
            BufferedImage image = gc.createCompatibleImage(100, 100, Transparency.TRANSLUCENT);
    
            // On windows this should be an ARGB integer packed raster. If it is then we can 
            // use our optimization technique
    
            if(image.getType() != BufferedImage.TYPE_INT_ARGB)
                return false;
    
            WritableRaster raster = image.getRaster();
    
            if(!(raster instanceof IntegerInterleavedRaster))
                return false;
    
            if(!(raster.getDataBuffer() instanceof DataBufferInt))
                return false;
    
            if(!(image.getColorModel() instanceof DirectColorModel))
                return false;
    
            DirectColorModel colorModel = (DirectColorModel) image.getColorModel();
    
            if(!(colorModel.getColorSpace() instanceof ICC_ColorSpace) ||
                 colorModel.getNumComponents() != 4 ||
                 colorModel.getAlphaMask() != 0xff000000 ||
                 colorModel.getRedMask() != 0xff0000 ||
                 colorModel.getGreenMask() != 0xff00 ||
                 colorModel.getBlueMask() != 0xff)
                return false;
    
            if(raster.getNumBands() != 4 ||
               raster.getNumDataElements() != 1 ||
               !(raster.getSampleModel() instanceof SinglePixelPackedSampleModel))
                return false;
    
            return true;
        }
    
        public BufferedImage loadImage(File file, int width, int height, long imageOffset) throws IOException
        {
            if(fastLoading_)
                return loadImageUsingFastTechnique(file, width, height, imageOffset);
            else
                return loadImageUsingCompatibleTechnique(file, width, height, imageOffset);
        }
    
        private BufferedImage loadImageUsingFastTechnique(File file, int width, int height, long imageOffset) throws IOException
        {
            int sizeBytes = width * height * 3;
    
            // Make sure buffer is big enough
            if(tempBuffer_ == null || tempBuffer_.length < sizeBytes)
                tempBuffer_ = new byte[sizeBytes];
    
            RandomAccessFile raf = null;
            try
            {
                raf = new RandomAccessFile(file, "r");
    
                raf.seek(imageOffset);
    
                int bytesRead = raf.read(tempBuffer_, 0, sizeBytes);
                if (bytesRead != sizeBytes)
                    throw new IOException("Invalid byte count. Should be " + sizeBytes + " not " + bytesRead);
    
                GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
                BufferedImage image = gc.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
                WritableRaster raster = image.getRaster();
                DataBufferInt dataBuffer = (DataBufferInt) raster.getDataBuffer();
    
                addAlphaChannel(tempBuffer_, sizeBytes, dataBuffer.getData());
    
                return image;
            }
            finally
            {
                try
                {
                    if(raf != null)
                    raf.close();
                }
                catch(Exception ex)
                {
                }
            }
        }
    
        private BufferedImage loadImageUsingCompatibleTechnique(File file, int width, int height, long imageOffset) throws IOException
        {
            int sizeBytes = width * height * 3;
    
            RandomAccessFile raf = null;
            try
            {
                raf = new RandomAccessFile(file, "r");
    
                // Lets navigate to the offset
                raf.seek(imageOffset);
    
                DataBufferByte dataBuffer = new DataBufferByte(sizeBytes);
                byte[] bytes = dataBuffer.getData();
    
                int bytesRead = raf.read(bytes, 0, sizeBytes);
                if (bytesRead != sizeBytes)
                    throw new IOException("Invalid byte count. Should be " + sizeBytes + " not " + bytesRead);
    
                WritableRaster raster = Raster.createInterleavedRaster(dataBuffer, // dataBuffer
                                width, // width
                                height, // height
                                width * 3, // scanlineStride
                                3, // pixelStride
                                new int[]{0, 1, 2}, // bandOffsets
                                null); // location
    
                ColorModel colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), // ColorSpace
                                new int[]{8, 8, 8}, // bits
                                false, // hasAlpha
                                false, // isPreMultiplied
                                ComponentColorModel.OPAQUE, DataBuffer.TYPE_BYTE);
    
                BufferedImage loadImage = new BufferedImage(colorModel, raster, false, null);
    
                // Convert it into a buffered image that's compatible with the current screen.
                // Not ideal creating this image twice....
                BufferedImage image = createCompatibleImage(loadImage);
    
                return image;
            }
            finally
            {
                try
                {
                    if(raf != null)
                    raf.close();
                }
                catch(Exception ex)
                {
                }
            }
        }
    
        private BufferedImage createCompatibleImage(BufferedImage image)
        {
            GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
    
            BufferedImage newImage = gc.createCompatibleImage(image.getWidth(), image.getHeight(), Transparency.TRANSLUCENT);
    
            Graphics2D g = newImage.createGraphics();
            g.drawImage(image, 0, 0, null);
            g.dispose();
    
            return newImage;
        }
    
    
        private void addAlphaChannel(byte[] rgbBytes, int bytesLen, int[] argbInts)
        {
            for(int i=0, j=0; i<bytesLen; i+=3, j++)
            {
                argbInts[j] = ((byte) 0xff) << 24 |                 // Alpha
                            (rgbBytes[i] << 16) & (0xff0000) |      // Red
                            (rgbBytes[i+1] << 8) & (0xff00) |       // Green
                            (rgbBytes[i+2]) & (0xff);               // Blue
            }
        }
    
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

No related questions found

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.