有损压缩中的隐写术(JAVA)

Inn*_*ynn 3 java compression jpeg steganography image

我有这个用于在java中的jpeg图像中编码数据.我正在将文本转换为二进制形式,并将其插入LSB(取决于用户选择的内容.1,2,3,4),每个像素中的RGB从(0,0)到(宽度,高度) .

outer:
    for(int i = 0; i < height; i++){
        for(int j = 0; j < width; j++){
            Color c = new Color(image.getRGB(j, i));                  

            int red = binaryToInteger(insertMessage(integerToBinary((int)(c.getRed())),numLSB));
            int green = binaryToInteger(insertMessage(integerToBinary((int)(c.getGreen())),numLSB));
            int blue = binaryToInteger(insertMessage(integerToBinary((int)(c.getBlue())),numLSB));

            Color newColor = new Color(red,green,blue);
            image.setRGB(j,i,newColor.getRGB());

        }
    }
    gui.appendStatus("Binarized message is: " + binarizedMessage);
    File output = new File(gui.getOutput()+".jpg");

    ImageIO.write(image, "png", output);
Run Code Online (Sandbox Code Playgroud)

目前,我正在把它写成一个png,它运作良好,但我希望在jpeg中做到这一点.我成功地在png中获取这些数据.但正如预期的那样,jpeg失败了.

我能够解码所写图像中的隐藏位,并在选择正确的LSB时看到消息.

我目前正在阅读有关JPEG隐写术的内容,但我没有准确地了解它应该如何启动它.我见过算法,也没有帮助我.

我看到一个没有找到任何主类的代码.

我是否必须在我的应用程序中调用它?修改它?我怎么解码?

这是我见过的代码链接.

Ret*_*i43 6

jpeg使用有损压缩方法来实现更小的文件大小.不幸的是,这种方法直接影响(某些)像素的值,从而以嵌入它的方式破坏信息.您需要以无损格式保存文件以避免此问题,例如bmp或png.

Jpeg隐写术对代码来说有点复杂,但这个概念很简单.您将需要编写一个jpeg编码器,或者已经使用了一个编码器.您链接的代码确实是一个编码器,只需稍作修改即可将其用于您的项目.

如果您想了解代码,可以阅读有关jpeg编码的维基百科文章.我将简要总结一些关键步骤.

  • 以8x8块分割图像.
  • 在每个上使用离散余弦变换(DCT)来获得浮点DCT系数并将它们量化为整数.
  • 使用霍夫曼编码和行程编码将量化的系数存储到文件中.

第二步中的量化是有损位,但之后的所有内容都是无损的.所以基本上,从第二步获得量化系数,用你的隐写算法修改它们,然后继续第三步.

在链接代码的实际修改上.Compress您需要调用该方法将rgb图像存储到文件中.它负责编写标题数据和压缩系数.您只需要在WriteCompressedData方法中添加一些代码.它现在做的是循环每个8x8图像块,应用dct并量化存储的系数dctArray3.然后将该数据压缩写入文件.这是你必须通过dctArray3在打电话之前进行干预而进行干预的地方Huf.HuffmanBlockEncoder.

例如,假设您有一个秘密的字节数组,称为message,并且您希望在特定系数的lsb中每8x8块嵌入一位.

public void WriteCompressedData(BufferedOutputStream outStream, byte[] message) {
    byte currentByte;
    int nBytes = message.length;
    int iByte = 0;
    int iBit = 7;
    if (nBytes > 0) {
        currentByte = message[0];
    } else {
        currentByte = (byte) 0;
    }
    // Original method code up until the following line
    dctArray3 = dct.quantizeBlock(dctArray2, JpegObj.QtableNumber[comp]);
    // ******************** our stuff *******************
    if (iByte < nBytes) {
        int bit = (currentByte >> iBit) & 1;
        iBit--;
        if (iBit == -1) {
            iBit = 7;
            iByte++;
            if (iByte < nBytes) {
                currentByte = message[iByte];
            }
        }
        dctArray3[23] = (dctArray3[23] & 0xfffffffe) | bit;
    }
    // **************************************************
    Huf.HuffmanBlockEncoder(outStream, dctArray3, lastDCvalue[comp], JpegObj.DCtableNumber[comp], JpegObj.ACtableNumber[comp]);
    ...
}
Run Code Online (Sandbox Code Playgroud)

解码与此相反,您可以使用适当的算法读取DCT系数并从中提取秘密.你需要一个jpeg解码器,所以我只是借用了F5 Steganography项目中的相关文件.具体来说,您需要文件ortega夹中的文件,然后您可以像这样使用它.

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import ortega.HuffmanDecode;

public class Extract {
    private static byte[] deZigZag = {
            0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42, 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31,
            40, 44, 53, 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60, 21, 34, 37, 47, 50, 56, 59, 61,
            35, 36, 48, 49, 57, 58, 62, 63 };

    private static int[] extract(InputStream fis, int flength) throws IOException {
        byte[] carrier = new byte[flength];
        fis.read(carrier);
        HuffmanDecode hd = new HuffmanDecode(carrier);
        int[] coeff = hd.decode();
        return coeff;
    }

    public static void main(String[] args) {
        // run with argument the stego jpeg filename
        try {
            File f = new File(args[0]);
            FileInputStream fis = new FileInputStream(f);
            int[] coeff = extract(fis, (int) f.length());

            int idx = deZigZag[23];
            // The coeff array has all of the DCT coefficients in one big
            // array, so that the first 64 elements are the coefficients 
            // from the first block, the next 64 from the second and so on.
            //
            // idx is the position of the embedding DCT coefficient.
            // You can start with that and extract its lsb, then increment
            // by 64 to extract the next bit from the next "block" and so on.
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)