gpt4 book ai didi

java - 隐写术 Lsb 信息容量

转载 作者:行者123 更新时间:2023-11-30 07:14:53 33 4
gpt4 key购买 nike

我知道使用 LSB 意味着您可以将消息存储在图像载体大小的 12% 左右。 我制作了一个 java 程序,它将一条消息分成 n 个片段,并用这些片段填充图像载体,直到 12% 都被占用。我这样做是为了通过裁剪图像,消息不会丢失。 问题是生成的图像失真并且与原始图像不同。我认为如果我只填充图像的 12%,更准确地说是图像的 LSB,图像就不会失真。

    int numHides = imLen/(totalLen*DATA_SIZE); // the number of messages I can store in the image
int offset = 0;
for(int h=0; h < numHides; h++) //hide all frags, numHides times
for(int i=0; i < NUM_FRAGS; i++) {//NUM_FRAGS ..the number of fragments
hideStegoFrag(imBytes, stegoFrags[i], offset);//the method that hides the fragment into the picture starting at the offset position
offset += stegoFrags[i].length*DATA_SIZE;
}

private static boolean hideStegoFrag(byte[] imBytes,byte[] stego,int off){
int offset=off;
for (int i = 0; i < stego.length; i++) { // loop through stego
int byteVal = stego[i];
for(int j=7; j >= 0; j--) { // loop through 8 bits of stego byte
int bitVal = (byteVal >>> j) & 1;
// change last bit of image byte to be the stego bit
imBytes[offset] = (byte)((imBytes[offset] & 0xFE) | bitVal);
offset++;
}
}
return true;
}

将缓冲图像转换为位的代码

       private static byte[] accessBytes(BufferedImage image)
{
WritableRaster raster = image.getRaster();
DataBufferByte buffer = (DataBufferByte) raster.getDataBuffer();
return buffer.getData();
}

使用提供的名称和源图像的缓冲图像创建新图像的代码

      public static boolean writeImageToFile(String imFnm , BufferedImage im){
try {
ImageIO.write(im, "png", new File(imFnm));
} catch (IOException ex) {
Logger.getLogger(MultiSteg.class.getName()).log(Level.SEVERE, null, ex);
}
return true;

} original image The modified image

最佳答案

您发布的输出图像是 16 色调色板图像。

我看到的数据表明您实际上已将更改应用到调色板索引,而不是图像的颜色。您看到失真的原因是调色板的组织方式,您没有修改颜色的 LSB,而是修改索引的 LSB,这可能会将其更改为完全不同的(并且非常明显) ,如您所见)颜色。 (实际上,您正在修改所有其他索引的 LSB,16 色形式是每像素 4 位,每字节 2 像素。)

您似乎加载了原始图像数据,但并未将其解码为 RGB 颜色信息。您的算法仅适用于原始 RGB(或原始灰度)数据;每个像素 3 个字节(或 1 个灰度)。在操作之前,您需要将图像转换为 RGB888 或类似的格式。当您保存它时,您还需要以无损全彩色(除非您实际上可以将所有颜色放入调色板)格式保存它,否则您可能会丢失信息。

您的问题实际上不在于程序的隐写部分,而在于图像数据本身的加载和保存。

加载图像数据时,需要将其转换为 RGB 格式。您的应用程序最方便的格式是 BufferedImage.TYPE_3BYTE_BGR ,它将每个像素存储为蓝色、绿色、红色顺序的三个字节(因此您的字节数组将是 B、G、R、B、G、R、B、G、R、...)。你可以这样做:

public static BufferedImage loadRgbImage (String filename) {
// load the original image
BufferedImage originalImage = ImageIO.read(filename);
// create buffer for converted image in RGB format
BufferedImage rgbImage = new BufferedImage(originalImage.getWidth(), originalImage.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
// render original image into buffer, changes to destination format
rgbImage.getGraphics().drawImage(originalImage, 0, 0, null);
return rgbImage;
}

如果您经常使用已经是 BGR 格式的源图像,您可以进行一个简单的优化,以便在图像已经是您想要的格式时不转换图像:

public static BufferedImage loadRgbImage (String filename) {
BufferedImage originalImage = ImageIO.read(filename);
BufferedImage rgbImage;
if (originalImage.getType() == BufferedImage.TYPE_3BYTE_BGR) {
rgbImage = originalImage; // no need to convert, just return original
} else {
rgbImage = new BufferedImage(originalImage.getWidth(), originalImage.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
rgbImage.getGraphics().drawImage(originalImage, 0, 0, null);
}
return rgbImage;
}

然后您可以将转换后的图像用于所有操作。请注意,转换后图像的字节数组将包含 3 * rgbImage.getWidth() * rgbImage.getHeight() 字节。

您不必对当前的图像保存代码进行任何更改; ImageIO 将检测图像为 RGB 并写入 24 位 PNG。

关于java - 隐写术 Lsb 信息容量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18271389/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com