sjamesr / jfreesane

Java API to talk to the SANE scanning daemon
Apache License 2.0
60 stars 25 forks source link

CS_GRAY image is too light #49

Closed Mogaba closed 8 years ago

Mogaba commented 8 years ago

Relates to issue #28. I found out that there's the exact same problem with "Gray" mode, image is lighter than it should be. Is there a workaround?

sjamesr commented 8 years ago

With my Canon Pixma MX892, I tried the following:

    SaneDevice device = session.getDevice("pixma");
    device.open();
    device.getOption("mode").setStringValue("Gray");
    device.getOption("resolution").setIntegerValue(300);
    ImageIO.write(device.acquireImage(), "png", new File("/tmp/foo.png"));

and used scanimage to obtain the "correct" image:

scanimage --mode Gray --resolution 300 \ 
  -d pixma > /tmp/best.pnm && convert /tmp/best.pnm /tmp/best.png

There weren't any significant differences in the images as far as I could tell. Could you post more details on how I might be able to reproduce the issue?

Mogaba commented 8 years ago

Here's the test class:

public class Test {
    JFrame mFrame = new JFrame();
    JPanel iPanel = new JPanel();
    JLabel iLabel = new JLabel();

    public static void main(String[] args) throws Exception {
        new Test();
    }

    public Test() throws Exception {
        InetAddress srv = InetAddress.getByName("10.55.12.32");
        SaneSession session = SaneSession.withRemoteSane(srv);
        SaneDevice dev = session.listDevices().get(0);

        dev.open();
        dev.getOption("mode").setStringValue("Gray");
        dev.getOption("resolution").setIntegerValue(300);
        final BufferedImage badImg = dev.acquireImage();
        dev.close();

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                drawAndShow(badImg);
            }
        });

        File iFile = new File("good.png");
        ImageIO.write(badImg, "png", iFile);
        BufferedImage stillBadImg = ImageIO.read(iFile);
        BufferedImage goodImg = new BufferedImage(stillBadImg.getWidth(), stillBadImg.getHeight(),
                BufferedImage.TYPE_INT_RGB);
        goodImg.getGraphics().drawImage(stillBadImg, 0, 0, null);

        printRGB(badImg, 2000, 100);
        printRGB(stillBadImg, 2000, 100);
        printRGB(goodImg, 2000, 100);
    }

    public void drawAndShow(BufferedImage bimg) {
        mFrame.setSize(600, 800);
        mFrame.setLocationRelativeTo(null);
        mFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mFrame.add(iPanel);
        iPanel.add(iLabel);
        mFrame.setVisible(true);
        iLabel.setIcon(new ImageIcon(bimg.getScaledInstance(-1, iPanel.getHeight(), Image.SCALE_SMOOTH)));
    }

    public void printRGB(BufferedImage bimg, int x, int y) {
        Color c = new Color(bimg.getRGB(x, y));
        System.out.println(c.getRed() + ", " + c.getGreen() + ", " + c.getBlue());
    }
}

Here's the output:

128, 128, 128 128, 128, 128 55, 55, 55

Here're JLabel and PNG images: https://imagebin.ca/v/2rsHpwuATtaA https://imagebin.ca/v/2rsIVA66NTzq

I'm using Java 7 if it matters.

sjamesr commented 8 years ago

@Mogaba thank you for the detailed test code. By now I've learned that I know nothing at all about java.awt.color!

Can you please try https://github.com/sjamesr/jfreesane/commit/9dcbd6dfe8a6018815e79b8c7dde7b3147efacf7, it seems to work for me.

Mogaba commented 8 years ago

It works, thank you!

sjamesr commented 8 years ago

Fixed in JFreeSane 0.97.