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

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

问题描述

我有这样的编码jpeg图像中的数据在java。我将文本转换为二进制形式,并将其插入到从(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系数并将其量化为整数。 li>
  • Split the image in 8x8 blocks.
  • Use the discrete cosine transform (DCT) on each to obtain the float DCT coefficients and quantise them to integers.
  • Store the quantised coefficients to a file using Huffman coding and run length encoding.

第二步中的量化是有损比特,但随后的一切都是无损的。因此,基本上,从第二步获得量化系数,使用隐身算法修改它们,并继续第三步。

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 。然后将该数据压缩写入文件。这是你必须干预的地方,通过修改 dctArray3 ,然后调用 Huf.HuffmanBlockEncoder

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 ,并且要在每个8x8块中嵌入一个位在lsb

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天全站免登陆