1
我建立了一个小的Java程序,使用最低有效位的方法隐藏图像中的消息。当输入一个jpg文件时它工作正常。输出可能是png或jpg。当输入一个PNG时,结果看起来非常直观。隐写,只有JPG作为输入工作,当使用PNG的结果图像看起来很奇怪
这里分别原始和结果图像是:
public abstract class Builder{
public static void leastSignificantBitEncryption(String imageSource, String message, String newPath) {
BufferedImage image = returnImage(imageSource);
//prepare variables
String[] messageBinString = null;
String[] pixelBinString = null;
final byte[] messageBin = message.getBytes(StandardCharsets.UTF_8);
final byte[] pixelsBin = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
//convert message and image to binary string array
try {
messageBinString = stringToBinaryStrings(messageBin);
pixelBinString = stringToBinaryStrings(pixelsBin);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String[] messageBinStringCut = splitIn2Bit(messageBinString); //split message binary into 2 bit strings
String[] pixelBinStringNew = pixelBinString.clone(); //insert 2 bit strings in last 2 bits of bytes from bitmap
insert2Bit(messageBinStringCut, pixelBinStringNew);
byte[] pixelsBinNew = stringArrayToByteArray(pixelBinStringNew); //Convert string array to byte array
try { //Create new image out of bitmap
int w = image.getWidth();
int h = image.getHeight();
BufferedImage imageNew = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);
imageNew.setData(Raster.createRaster(imageNew.getSampleModel(), new DataBufferByte(pixelsBinNew, pixelsBinNew.length), new Point()));
File imageFile = new File(newPath);
ImageIO.write(imageNew, "png", imageFile);
} catch (IOException e) {
e.printStackTrace();
}
}
private static String[] stringToBinaryStrings(byte[] messageBin) throws UnsupportedEncodingException{
String[] bytes = new String[messageBin.length];
int i = 0;
for(byte b : messageBin) {
bytes[i] = String.format("%8s", Integer.toBinaryString(b & 0xFF)).replace(' ', '0');
i++;
}
return bytes;
}
private static String binaryStringsToString(String[] messageBin) throws UnsupportedEncodingException{
StringBuilder stringBuilder = new StringBuilder();
int i = 0;
while(messageBin[i] != null) {
stringBuilder.append((char) Integer.parseInt(messageBin[i], 2));
i++;
}
return stringBuilder.toString();
}
private static BufferedImage returnImage(String imageSource) {
try{
try {
return ImageIO.read(new URL(imageSource));
} catch (MalformedURLException e) {
return ImageIO.read(new File(imageSource));
}
} catch (IOException ioe) {
ioe.printStackTrace();
return null;
}
}
private static byte[] stringArrayToByteArray(String[] stringArray) {
byte[] byteArray = new byte[stringArray.length];
for(int i = 0; i < stringArray.length; i++) {
byteArray[i] = (byte) Integer.parseInt(stringArray[i], 2);
}
return byteArray;
}
private static String[] splitIn2Bit(String[] inputArray) {
String[] outputArray = new String[inputArray.length * 4];
for(int i = 0; i < outputArray.length; i += 4) {
String[] splitByte = inputArray[i/4].split("(?<=\\G..)");
outputArray[i] = splitByte[0];
outputArray[i + 1] = splitByte[1];
outputArray[i + 2] = splitByte[2];
outputArray[i + 3] = splitByte[3];
}
return outputArray;
}
private static String[] insert2Bit(String[] twoBitArray, String[] insertArray) {
for(int i = 0; i < twoBitArray.length; i++) {
insertArray[i] = insertArray[i].substring(0, 6) + twoBitArray[i];
}
return insertArray;
}
}
此外,识别TestClass:
public class Test {
public static void main(String[] args) {
Builder.leastSignificantBitEncryption("IMAGEPATH OR URL", "MESSAGE", "PATH FOR IMAGE CONTAINING MESSAGE");
Builder.leastSignificantBitDecryption("PATH OF IMAGE CONTAINING MESSAGE", "PATH FOR TXT CONTAINING OUTPUT");
}
}
如果您清理意大利面代码,它将更易于阅读,从而更容易理解并更容易发现问题;既为你和我们。我可以很容易地检查5行方法并给出关于正确性的声明,但是对于40行方法很难。帮你一个忙,把大方法分成小块。从前11行开始,从文件名中给出位图 –
将变量移近使用,例如'w'和'h'似乎不会在接下来的16行中使用。这让我怀疑他们是否被使用过。如果他们没有使用,删除它。 –
另外:你说图片看起来不对。这告诉我问题在于加密方法。解密方法应该与问题无关。去掉它。最后,在我离开这里之前,有太多的'String's。如果需要位操作的操作使用了如此多的字符串和很少的字节,那么就会出现问题。 –