jpeg使用有损压缩方法来实现较小的文件大小。不幸的是,该方法直接影响(某些)像素的值,从而破坏了嵌入信息的方式。您需要以无损格式保存文件以避免这种问题,例如bmp或png。
Jpeg隐写术的代码编写有些复杂,但是概念很简单。您将需要编写jpeg编码器,或者已经使用一个编码器。您链接到的代码确实是一种编码器,只需稍作修改,就可以将其用于您的项目。
如果您想了解代码,可以阅读有关jpeg编码的维基百科文章。我将简要总结其一些关键步骤。
- 将图像分成8x8块。
- 在每一个上使用离散余弦变换(DCT)获得浮点DCT系数并将其量化为整数。
- 使用霍夫曼编码和游程长度编码将量化系数存储到文件中。
第二步中的量化是有损比特,但是随后进行的所有 *** 作都是无损的。因此,基本上,从第二步获取量化系数,使用隐写算法对其进行修改,然后继续第三步。
关于链接代码的实际修改。该
Compress方法是您需要调用以将rgb图像存储到文件中的方法。它负责写头数据和压缩系数。您只需要在该
WriteCompressedData方法中添加一些代码即可。现在要做的是循环遍历每个8x8图像块,应用dct并量化存储在中的系数
dctArray3。然后将这些数据压缩写入文件。那是您必须进行干预的地方,
dctArray3在致电之前进行修改
Huf.HuffmanBlockEnprer。
例如,假设您有一个秘密的字节数组,称为
message,并且您希望将每个8x8块的一位嵌入特定系数的lsb中。
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 pre 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.HuffmanBlockEnprer(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.HuffmanDepre;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); HuffmanDepre hd = new HuffmanDepre(carrier); int[] coeff = hd.depre(); 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(); } }}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)