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

我有这个用于在java中的jpeg图像中编码数据。 我正在将文本转换为二进制forms,并将其插入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); 

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

我能够解码所写图像中的隐藏位,并在给定正确的LSB被选中的情况下查看消息。

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

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

我是否必须在我的申请中拨打电话? 修改它? 我怎么解码?

这是我见过的代码的链接 。

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

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

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

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

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

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

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

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