Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BMP Writer only supports TYPE_4BYTE_ABGR #547

Closed
FlorianKirmaier opened this issue Jun 24, 2020 · 2 comments
Closed

BMP Writer only supports TYPE_4BYTE_ABGR #547

FlorianKirmaier opened this issue Jun 24, 2020 · 2 comments
Assignees

Comments

@FlorianKirmaier
Copy link

The BMPImageWriter currently only supports TYPE_4BYTE_ABGR
With the previous version, 3.4.3 it worked in our environment because another ImageWriter was found.
With 3.5 the twelve-monkey implementation is found randomly which ends with the "Blows!" exception.
But we have to remove the other implementation anyway.

The issue can be found in the class DIBImageWriter
The required ColorModel is hardcoded. If the code finds another "Type" then a "Blows!" exception is thrown.

I assume this is relatively easy to fix? Can I help somehow?

Test class:

package test;

import javax.imageio.ImageIO;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.ImageWriter;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Iterator;

public class TestImageWriter {

    public static void main(String[] args)
    {
        BufferedImage image = createTestImage(100, 100 );
        int imageWidth = image.getWidth();
        int imageHeight = image.getHeight();
        final int imageLengthInBytes = createBytesFromImage(image).length;
    }

    private static BufferedImage createTestImage(final int width, final int height) {
        // works: TYPE_4BYTE_ABGR
        // doesn't work: TYPE_INT_RGB
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = image.createGraphics();
        g2.setBackground(java.awt.Color.BLUE);
        g2.setColor(java.awt.Color.PINK);
        g2.drawLine(0,0, width, height);
        g2.dispose();
        return image;
    }


    public static byte[] createBytesFromImage(BufferedImage image) {
        int bufferSize = 1024;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] result = null;

        BufferedOutputStream bufferedStream = new BufferedOutputStream(out, bufferSize);
        String format = "bmp";
        try {
            ImageTypeSpecifier type =
                    ImageTypeSpecifier.createFromRenderedImage(image);
            Iterator<ImageWriter> writers = ImageIO.getImageWriters(type, format);
            while(writers.hasNext()) {
                ImageWriter writer = writers.next();
                if(writer.getClass().getName().contains("welve")) {
                    writer.setOutput(ImageIO.createImageOutputStream(bufferedStream));
                    System.out.println("Found writer: " + writer);
                    writer.write(image);
                }
            }

            ImageIO.write(image, format, bufferedStream);

            bufferedStream.flush();
            result = out.toByteArray();


        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
        return result;
    }
}

@haraldk
Copy link
Owner

haraldk commented Jun 25, 2020

Ahem... What can I say. This is embarrassing...

But thanks for reporting!

The TwelveMonkeys BMPImageWriter was added only to support writing of ICO format, which needs BMPs with alpha. Which is not supported by the built-in BMPImageWriter... But it should probably not be enabled as a general BMP writer, as it only supports just that, BMPs with alpha.

Can you try just editing the META-INF/services/javax.imageio.spi.ImageWriterSpi inside the JAR, and either comment out (with a #) or remove the line com.twelvemonkeys.imageio.plugins.bmp.BMPImageWriterSpi? I think that should work. Or just leave the entire JAR out, if you don't need the extra BMP/ICO/CUR support.

Best regards,

--
Harald K

@haraldk haraldk self-assigned this Jun 25, 2020
haraldk added a commit that referenced this issue Jun 28, 2020
…registers with low pri.

Better exception message for other image types.
@haraldk
Copy link
Owner

haraldk commented Jun 28, 2020

Hi Florian,

I just pushed a fix for the issue, your test case will now pass (but may not write anything) for TYPE_INT_ARGB and other types. I don't think the built-in BMP writer will write BMPs with alpha, at least not maintaining the alpha channel.

If you skip the type parameter to ImageIO.getImageWriters, you will still get an exception, but now with a meaningful exception message.

If you need a specific implementation/plugin, but don't want to clutter your read/write code with this, it's possible to set the ordering of ImageIO service providers (XxxSpi), as described in this SO answer.

PS: It should be fairly easy to support TYPE_4BYTE_ABGR_PRE, by simply dividing out the premultiplied alpha. It's also possible to support the TYPE_INT_XXX types by converting each line before writing. Feel free to submit a PR for this, should you have the time/need for this. 😀

Best regards,

--
Harald K

@haraldk haraldk closed this as completed Jun 28, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants