简体   繁体   中英

Handling of java.awt.Color while saving file (JPG) with ImageIO.write

Taking part in a Coursera course, I've been trying to use steganography to hide an image in another. This means I've tried to store the "main" picture's RGB values on 6 bits and the "second" picture's values on the last 2 bits. I'm merging these two values to create a joint picture, and have also coded a class to parse the joint picture, and recover the original images.

Image recovery has not been successful, although it seems (from other examples provided within the course) that the parser is working fine. I suppose that saving the pictures after modification, using ImageIO.write somehow modifies the RGB values I have carefully set in the code. :D

public static BufferedImage mergeImage(BufferedImage original,
        BufferedImage message, int hide) {
    // hidden is the num of bits on which the second image is hidden
    if (original != null) {
        int width = original.getWidth();
        int height = original.getHeight();
        BufferedImage output = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_RGB);
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                int pix_orig = original.getRGB(i, j);
                int pix_msg = message.getRGB(i, j);
                int pixel = setpixel(pix_orig, pix_msg, hide);
                output.setRGB(i, j, pixel);
            }
        }
        return output;
    }
    return null;
}

    public static int setpixel(int pixel_orig, int pixel_msg, int hide) {
    int bits = (int) Math.pow(2, hide);
    Color orig = new Color(pixel_orig);
    Color msg = new Color(pixel_msg);
    int red = ((orig.getRed() / bits) * bits); //+ (msg.getRed() / (256/bits));
    if (red % 4 != 0){
        counter+=1;
    }
    int green = ((orig.getGreen() / bits) * bits) + (msg.getGreen() / (256/bits));
    int blue = ((orig.getBlue() / bits) * bits) + (msg.getBlue() / (256/bits));
    int pixel = new Color(red, green, blue).getRGB();
    return pixel;
}

This is the code I use for setting the RGB values of the merged picture. As you can see, I have commented part of the code belonging to red to check whether the main picture can actually be saved on 6 bits, assuming I take

int hide=2
Although if I make the same checks in the parsing part of the code:

  public static BufferedImage parseImage(BufferedImage input, int hidden){ // hidden is the num of bits on which the second image is hidden if (input != null){ int width = input.getWidth(); int height = input.getHeight(); BufferedImage output = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); for(int i=0;i<width;i++){ for(int j=0;j<height;j++){ int pixel = input.getRGB(i, j); pixel = setpixel(pixel,hidden); output.setRGB(i, j, pixel); } } return output; } return null; } public static int setpixel(int pixel, int hidden){ int bits = (int) Math.pow(2,hidden); Color c = new Color(pixel); if (c.getRed() % 4 != 0){ counter+=1; } int red = (c.getRed() - (c.getRed()/bits)*bits)*(256/bits); int green = (c.getGreen() - (c.getGreen()/bits)*bits)*(256/bits); int blue = (c.getBlue() - (c.getBlue()/bits)*bits)*(256/bits); pixel = new Color(red,green,blue).getRGB(); return pixel; } 

I get ~100k pixels where the R value has a remainder if divided by four. I suspect there' some problem with the function of ImageIO.write. I know the question is going to be vague, but 1) Can someone confirm this 2) What can I do to get this code working?

Thanks a lot!

JPEG has lossy compression, which means some pixels will effectively be modified when reloading the image. This isn't a fault of ImageIO.write , it's how the format works. If you want to embed your data directly to pixel values, you want to save the image to a lossless format, such as BMP or PNG.

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