有损压缩中的隐写术 (JAVA) [英] Steganography in lossy compression (JAVA)

查看:35
本文介绍了有损压缩中的隐写术 (JAVA)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have this for encoding data in jpeg images in java. I am converting the text to its binary form and insert it to the LSB (depending on what the user has chosen.1,2,3,4) of the RGB in each pixel from (0,0) till (width,height).

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);

目前,我把它写成 png 并且效果很好,但我希望用 jpeg 制作.我成功地以 png 格式获取这些数据.但正如预期的那样,在 jpeg 中失败.

Currently, im writing it as a png and it works well but I am hoping to make this in jpeg. I am successful getting those data in png. But as expected, failing in jpeg.

如果选择了正确的 LSB,我能够解码所写入图像中的隐藏位并查看消息.

I am able to decode the hidden bits in the image written and see the message given that the correct LSB was chosen.

我目前正在阅读有关 JPEG 隐写术的信息,但没有完全了解我应该如何开始它.我见过算法,也没有帮助我.

I am currently reading about about JPEG steganography but not getting it quite exactly how should I start it. I've seen algorithms, didnt helped me either.

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

I saw a code that doesnt have any main classes found.

我必须在我的应用程序中调用它吗?修改?我将如何解码?

Do I have to call it in my application? Modify it? How would I decode?

这是一个 代码链接 我见过.

推荐答案

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

The jpeg uses a lossy compression method to achieve smaller file sizes. Unfortunately, that very method directly affects the value of (some) pixels, thereby destroying the information the way you have embedded it. You need to save the file in a lossless format to avoid this problem, such as bmp or png.

Jpeg 隐写术的编码稍微复杂一些,但概念很简单.您要么需要编写一个 jpeg 编码器,要么使用已经存在的编码器.您链接到的代码确实是一个编码器,只需稍加修改,您就可以将其用于您的项目.

Jpeg steganography is somewhat more complex to code, but the concept is straightforward. You will either need to write up a jpeg encoder, or use one in existence already. The code you linked to is indeed an encoder and with some minor modifications you can use it for your project.

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

If you want to understand the code, you can read the wikipedia article on jpeg encoding. I will briefly summarise some of its key steps.

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

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

The quantisation in the second step is the lossy bit, but everything that follows afterwards is lossless. So basically, obtain the quantised coefficients from the second step, modify them with your steganography algorithm and continue with the third step.

链接代码的实际修改.Compress 方法是您需要调用以将 rgb 图像存储到文件的方法.它负责写入头数据和压缩系数.您只需要在 WriteCompressedData 方法中添加一些代码即可.它现在所做的是循环遍历每个 8x8 图像块,应用 dct 并量化存储在 dctArray3 中的系数.然后将此数据压缩写入文件.这就是你必须干预的地方,通过在调用 Huf.HuffmanBlockEncoder 之前修改 dctArray3.

Onto the practical modifications of the linked code. The Compress method is what you need to call to store an rgb image to a file. It takes care of writing the header data and the compressed coefficients. You just need to add a bit of code in the WriteCompressedData method. What it does for now is loop over each 8x8 image block, apply the dct and quantise the coefficients, which are stored in dctArray3. This data is then compressed written to file. That's where you have to intervene, by modifying dctArray3 before calling Huf.HuffmanBlockEncoder.

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

For example, let's say you have a byte array of your secret, called message, and you want to embed one bit per 8x8 block in the lsb of a specific coefficient.

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]);
    ...
}

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

The decoding is the reverse of this, where you read the DCT coefficients and extract your secret from them with the appropriate algorithm. You will require a jpeg decoder for this, so I just borrowed the relevant files from the F5 Steganography project. Specifically, you need the files in the ortega folder and then you can use it like this.

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();
        }
    }
}

这篇关于有损压缩中的隐写术 (JAVA)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆