简体   繁体   English

有什么方法可以将getRGB和setRGB与隐写术一起使用?

[英]Is there any way to use getRGB and setRGB with steganography?

Im writing a program with simple steganography implementation. 我正在用简单的隐写术实现编写程序。

I have a problem becouse if I use setRGB and then getRGB for one pixel i got different values. 我有一个问题,因为如果我使用setRGB然后将getRGB用于一个像素,则会得到不同的值。 I read that setRGB and getRGB are not the best idea for byte and bits operation but maybe there is a way? 我读到setRGB和getRGB不是字节和位操作的最佳方法,但也许有办法吗? i would like to work with LSB of alpha red green and blue of every pixel and I have no idea how to do it with rasters and to be honest i spend a lot of time with writing some code to generate proper TYPE_INT_ARGB value... I would like to use every 2 LSB from ARGB so I have 8 bits for pixel - that gives one char for pixel. 我想使用每个像素的阿尔法红色,绿色和蓝色的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);

and the results are different so stegenography does not work... 结果不一样,所以体相学不起作用...

this is the addLetter function 这是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();   

I will be greatefull for any help and understanding. 如果有任何帮助和理解,我将不胜感激。 Im still a beginer in Java 我还是Java的初学者

EDITED: 编辑:

I will try to explain my problem one more time: Im using function //int i - im passing result of getRGB for pixel //char letter - that is a letter that im adding to 2 LSB of A,R,G and B value public static int addLetter(int i, char letter) { byte tym, tc; 我将尝试再一次解释我的问题:我使用函数// int i-im传递getRGB像素的结果// char字母-这是一个将im加到A,R,G和B值的2 LSB的字母public static int addLetter(int i,char letter){字节tym,tc; tc = (byte) letter; tc =(字节)字母; int ARGB; 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();   
}

The problem is that after i pass it to BufferedImage using setRGB it change the values different than I want it to. 问题是,在我使用setRGB将其传递给BufferedImage之后,它更改的值不同于我想要的值。 Im checking it by another getRGB and the values are slighty different so I can't read my hidden letter. 我通过另一个getRGB对其进行检查,其值略有不同,因此我无法读取隐藏的字母。

You may have a problem here: 您可能在这里遇到问题:

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

If tc (which is a byte ) is 1100 0100 , the mask will give 1100 0000 and right shifting by 6 using the >> operator will give... 1111 1111 ! 如果tc (即byte )为1100 0100 ,则掩码将给出1100 0000并且使用>>运算符向右移6将得到... 1111 1111

Not sure whether this is what you really mean. 不确定这是否是您的真实意思。 If what you wanted is 0000 0011 then you must use >>> . 如果您想要的是0000 0011则必须使用>>> The >> operator carries the sign bit. >>运算符带有符号位。

I will take a guess and assume that your BufferedImage is of type RGB, even if you think you've set it to ARGB. 我猜一下,并假设您的BufferedImage是RGB类型,即使您认为已将其设置为ARGB。 The RGB type doesn't support an alpha channel and by setting your pixel value, it defaults to 255. If you need the information in the alpha channel to be stored properly, loading your image in a manner similar to below should work. RGB类型不支持Alpha通道,并且通过设置像素值将其默认设置为255。如果您需要正确存储Alpha通道中的信息,则可以按照以下方式加载图像。

Example case set with a url, but you can ignore that and load any image you want. 示例示例设置了一个url,但是您可以忽略该示例并加载所需的任何图像。

You will notice that if you change BufferedImage.TYPE_INT_ARGB to BufferedImage.TYPE_INT_RGB , the alpha channel defaults to 255 when you fetch the pixel value. 您会注意到,如果将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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM