有没有办法使用getRGB和setRGB与隐写术?

时间:2014-12-20 23:44:30

标签: java bufferedimage steganography

我正在编写一个简单的隐写术实现程序。

我有一个问题因为如果我使用setRGB然后getRGB为一个像素我得到不同的值。 我读到setRGB和getRGB不是字节和位操作的最佳选择,但也许有办法吗?我想使用每个像素的蓝绿色和蓝色的LSB,我不知道如何用栅格做到这一点,说实话,我花了很多时间编写一些代码来生成正确的TYPE_INT_ARGB值...... 我想使用来自ARGB的每2 LSB,所以我有8位像素 - 给像素一个字符。

System.out.println("ARGB in int befor edit: " + obraz.getRGB(0, 0));
    int RGB = obraz.getRGB(0, 0);
    int alpha = (RGB >> 24) & 0xFF;
    int red = (RGB >> 16) & 0xFF;
    int green = (RGB >> 8) & 0xFF;
    int blue = (RGB) & 0xFF;

   System.out.println("RGB: " + RGB);
   System.out.println("alpha: " + alpha);
   System.out.println("red: " + red); 
   System.out.println("green: " + green); 
   System.out.println("blue: " + blue);

   System.out.println("After:");
   int newARGB = addLetter(RGB, 'b'); //this change every two bits of ARGB
   int alpha2 = (newARGB >> 24) & 0xFF;
   int red2 = (newARGB >> 16) & 0xFF;
   int green2 = (newARGB >> 8) & 0xFF;
   int blue2 = (newARGB) & 0xFF;


obraz.setRGB(0,0,newRGB);

 System.out.println("ARGB in int after edition: " + obraz.getRGB(0, 0));
    int RGB3 = obraz.getRGB(0, 0);
    int alpha3 = (RGB3 >> 24) & 0xFF;
    int red3 = (RGB3 >> 16) & 0xFF;
    int green3 = (RGB3 >> 8) & 0xFF;
    int blue3 = (RGB3) & 0xFF;

   System.out.println("RGB: " + RGB3);
   System.out.println("alpha: " + alpha3);
   System.out.println("red: " + red3); 
   System.out.println("green: " + green3); 
   System.out.println("blue: " + blue3);

并且结果不同,所以stegenography不起作用......

这是addLetter函数

    public static int addLetter(int i, char letter)
{
    byte tym, tc;
    tc = (byte) letter;
    int ARGB;


    byte byte3 = (byte) ((i & 0xFF000000) >> 24);
    byte3 = (byte) (byte3 & (~0x00000003));
    tym = (byte) ((tc & 0xC0) >> 6);
    byte3 = (byte) (byte3 | tym);


    byte byte2 = (byte) ((i & 0x00FF0000) >> 16);
    byte2 = (byte) (byte2 & (~0x00000003));
    tym = (byte) ((tc & 0x30) >> 4);
    byte2 = (byte) (byte2 | tym);

    byte byte1 = (byte) ((i & 0x0000FF00) >> 8);
    byte1 = (byte) (byte1 & (~0x00000003));
    tym = (byte) ((tc & 0x0C) >> 2);
    byte1 = (byte) (byte1 | tym);

    byte byte0 = (byte) ((i & 0x000000FF));
    byte0 = (byte) (byte0 & (~0x00000003));
    tym = (byte) ((tc & 0x03));
    byte0 = (byte) (byte0 | tym);

    byte[] wynik = (new byte[]{byte3, byte2, byte1, byte0});
    return ByteBuffer.wrap(wynik).getInt();   

对于任何帮助和理解,我都会非常感激。我仍然是Java的初学者

编辑:

我会再试一次解释我的问题: 我正在使用功能 // int i - 我为像素传递getRGB的结果 // char letter - 这是一个加上A,R,G和B值的2 LSB的字母 public static int addLetter(int i,char letter)     {         byte tym,tc;         tc =(字节)字母;         int ARGB;

    byte byte3 = (byte) ((i & 0xFF000000) >> 24);
    byte3 = (byte) (byte3 & (~0x00000003));
    tym = (byte) ((tc & 0xC0) >> 6);
    byte3 = (byte) (byte3 | tym);


    byte byte2 = (byte) ((i & 0x00FF0000) >> 16);
    byte2 = (byte) (byte2 & (~0x00000003));
    tym = (byte) ((tc & 0x30) >> 4);
    byte2 = (byte) (byte2 | tym);

    byte byte1 = (byte) ((i & 0x0000FF00) >> 8);
    byte1 = (byte) (byte1 & (~0x00000003));
    tym = (byte) ((tc & 0x0C) >> 2);
    byte1 = (byte) (byte1 | tym);

    byte byte0 = (byte) ((i & 0x000000FF));
    byte0 = (byte) (byte0 & (~0x00000003));
    tym = (byte) ((tc & 0x03));
    byte0 = (byte) (byte0 | tym);

    byte[] result = (new byte[]{byte3, byte2, byte1, byte0});
    return ByteBuffer.wrap(result).getInt();   
}

问题是,在使用setRGB将其传递给BufferedImage之后,它会更改与我想要的值不同的值。我通过另一个getRGB检查它,并且值略有不同,所以我无法读取我的隐藏信件。

2 个答案:

答案 0 :(得分:0)

您可能在此处遇到问题:

tym = (byte) ((tc & 0xC0) >> 6);

如果tcbyte}为1100 0100,则掩码将为1100 0000,并使用>>运算符右移6 ...... 1111 1111

不确定这是不是你的意思。如果你想要的是0000 0011,那么你必须使用>>>>>运算符带有符号位。

答案 1 :(得分:0)

我会猜测并假设您的BufferedImage是RGB类型,即使您认为您已将其设置为ARGB。 RGB类型不支持Alpha通道,并且通过设置像素值,默认为255.如果您需要正确存储Alpha通道中的信息,则以类似于下面的方式加载图像应该有效。

使用网址设置的示例案例,但您可以忽略它并加载您想要的任何图像。

您会注意到,如果您将BufferedImage.TYPE_INT_ARGB更改为BufferedImage.TYPE_INT_RGB,则在您获取像素值时,Alpha通道默认为255.

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.*;
import java.net.URL;

class Blah {
    public static BufferedImage loadImage(String fname) {
        BufferedImage img = null;
        try {
            //File file = new File(fname);
            URL file = new URL("http://cdn.sstatic.net/stackexchange/img/logos/so/so-logo-med.png");
            BufferedImage in = ImageIO.read(file);
            img = new BufferedImage(in.getWidth(), in.getHeight(), BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = img.createGraphics();
            g.drawImage(in, 0, 0, null);
            g.dispose();
        } catch (IOException e) { 
            e.printStackTrace();
        }
        return img;
    }

    public static int addLetter(int i, char letter) {
        byte byteChar = (byte)letter;
        int embeddingBits = (((byteChar >> 6) & 3) << 24) +
                            (((byteChar >> 4) & 3) << 16) +
                            (((byteChar >> 2) & 3) << 8) + 
                            (byteChar & 3);
        return (i & 0xfcfcfcfc) + embeddingBits;
    }

    public static char extractLetter(int i) {
        int intChar = (((i >> 24) & 3) << 6) +
                      (((i >> 16) & 3) << 4) +
                      (((i >> 8) & 3) << 2) +
                      (i & 3);
        return (char)intChar;
    }

    public static void main(String[] args) {
        BufferedImage img = loadImage("secret.png");

        int pixel = img.getRGB(0, 0);
        int modifiedPixel = addLetter(pixel, 'b');
        img.setRGB(0, 0, modifiedPixel);

        int checkPixel = img.getRGB(0, 0);
        char newLetter = extractLetter(checkPixel);

        System.out.println(modifiedPixel + " " + checkPixel);
        System.out.println("Extracted letter: " + newLetter);
    }
}