本文介绍了如何结束嵌套循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个代码,试图用最小有效位的方法在图像中编码消息。我无法弄清楚的是,如果没有消息要编码留下来,如何结束消息的编码。



它只是一直持续到循环结束。



我尝试了类似limit的计数器。我和解码部分一样,但没有效果,所以我删除了它。

我包含了这些方法,因为它们被使用,可以用来包含计数器确定消息是否已完成编码,并可以停止迭代。

编码和解码在构造函数中。

  public class Steganography {

public static SteganographyGUI gui;
public static String binarizedMessage =,encodedMessage =,decodedMessage =;
public static int count = 0,limit = 0;

public static BufferedImage image;
public static int width,height,numLSB;
$ b $ public隐式加密(){
if(gui.isEncode()){
try {
字符串messageToBeHidden = gui.getMessage();
binarizedMessage = stringToBinary(messageToBeHidden);

File input = new File(gui.getPath());
image = ImageIO.read(input);
width = image.getWidth();
height = image.getHeight();
gui.appendStatus(File Name:+ gui.getFileName()+\\\
Width:+ width +\\\
Height:+ height +\ nLSB:+ gui.getSelectedLSB );
numLSB = gui.getSelectedLSB();
//编码
for(int i = 0; i for(int j = 0; 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));

颜色newColor =新颜色(红色,绿色,蓝色);
image.setRGB(j,i,newColor.getRGB());


$ b gui.appendStatus(Binarized message is:+ binarizedMessage);
File output = new File(gui.getOutput()+lossy.jpg);

ImageWriter jpgWriter = ImageIO.getImageWritersByFormatName(jpg)。next();
ImageWriteParam jpgWriteParam = jpgWriter.getDefaultWriteParam();
jpgWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
jpgWriteParam.setCompressionQuality(1f);

FileImageOutputStream outputStream = new FileImageOutputStream(output); //例如,FileImageOutputStream
jpgWriter.setOutput(outputStream);
IIOImage outputImage = new IIOImage(image,null,null);
jpgWriter.write(null,outputImage,jpgWriteParam);
jpgWriter.dispose();

File output2 = new File(gui.getOutput()+lossless.jpg);
ImageIO.write(image,png,output2);
gui.appendStatus(Message \+ messageToBeHidden +\被编码在+ gui.getFileName()+。\\\
输出文件为:+ gui.getOutput()+ .jpg \\\
\t+ gui.getOutput()+lossless.jpg);
} catch(Exception e){}
}
else {
File input = new File(gui.getPath());
String encodedData =;
尝试{
image = ImageIO.read(input);
} catch(IOException ex){}
width = image.getWidth();
height = image.getHeight();
gui.appendStatus(File Name:+ gui.getFileName()+\\\
Width:+ width +\\\
Height:+ height +\ nLSB:+ gui.getSelectedLSB );
numLSB = gui.getSelectedLSB();
String eData =;
//解码
for(int i = 0; i for(int j = 0; j Color c = new Color(image.getRGB(j,i));

encodedData + = getLSB(integerToBinary((int)(c.getRed())),numLSB);
encodedData + = getLSB(integerToBinary((int)(c.getGreen())),numLSB);
encodedData + = getLSB(integerToBinary((int)(c.getBlue())),numLSB);

if(limit> = 8 * numLSB){
break;
}
}
}
int counter = 0;
while(counter * 8< encodedData.length()){
int index = counter * 8;
String str = encodedData.substring(index,index + 8);
eData + = str; ();
if(!str.equals(00000000)){
encodedMessage + = new Character((char)Integer.parseInt(str,2))。toString();
counter ++;
}
else {
eData = eData.substring(0,eData.length() - 8);
break;

$ b gui.appendStatus(解码的数据是:\+ eData +\。);
gui.appendStatus(解码的邮件是:\+ encodedMessage +\。);
gui.appendStatus(字符数:+ counter);
}
reinitialize();


public static void reinitialize(){
binarizedMessage = encodedMessage = decodedMessage =;
count = limit = width = height = numLSB = 0;


public static String stringToBinary(String s){
byte [] bytes = s.getBytes(); // http://stackoverflow.com/questions/917163/convert-a-string-like-testing123-to-binary-in-java
StringBuilder binary = new StringBuilder();
for(byte b:bytes){
int val = b; (int i = 0; i binary.append((val& 128)== 0?0:1)的
;
val<< = 1;
}
}
return binary.toString();

$ b $ public static String integerToBinary(int i){
return String.format(%8s,Integer.toBinaryString(i))。replace('','' 0' ); //http://stackoverflow.com/questions/21856626/java-integer-to-binary-string
}

public static int binaryToInteger(String s){
return Integer.parseInt(s,2); //http://stackoverflow.com/questions/7437987/how-to-convert-binary-string-value-to-decimal
} //http://stackoverflow.com/questions/10178980/how- (String s,int x){
StringBuilder result = a-binary-string-to-a-base-10-integer-in-java

public static String新的StringBuilder(s); (int i = 8 - x; i<< i< ; 8; i ++){
result.setCharAt(i,'0');
}
return result.toString(); //http://www.tutorialspoint.com/java/lang/stringbuilder_tostring.htm

$ b $ public static String insertMessage(String s,int x){
String result = clearLSB(s,x);
StringBuilder temp = new StringBuilder(result); (b,b,b,b,b,b,b,b,b,b,b),如果(计数 temp.setCharAt(i, binarizedMessage.charAt(计数++));
}

return temp.toString();


public static String getLSB(String s,int x){
String result =;
for(int i = 8 -x; i result + = s.charAt(i);
if(s.charAt(i)=='0')
limit + = 1;
else
limit = 0;
}
返回结果;


public static String binaryToText(String s){
StringBuilder sb = new StringBuilder();
count = 0;
while(count< s.length()){
StringBuilder sb2 = new StringBuilder();
for(int i = 0; i if(count sb2.append(s.charAt(count ++));
else
sb2.append('0');
break;

//二进制到char并附加到sb
sb.append((char)Integer.parseInt(sb.toString(),2));
}
return sb.toString();


public static void main(String [] args){
gui = new SteganographyGUI();
gui.setVisible(true);


$ b $ / code $ / pre
$ b $编辑: >

看来第一个问题已经解决了,但又产生了另一个问题。

现在我改变了我的解码和编码基于Reti43下面的答案,我不能让我的datacomparison工作。我尝试应用您指出的解码行,但是我无法获得图片中的编码数据。

这是原始的DataComparison

  import java.awt.Color; 
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Arrays;
import javax.imageio.ImageIO;

公共类DataComparison {

公共静态DataComparisonGUI gui;
public static BufferedImage image,image2;
public static int width,height,lsb,limit = 0;

public static String lossyData =,losslessData =,lsData =,lyData =;
public static String lossyMessage =,losslessMessage =;

public static int [] [] [] cLossyData,cLosslessData;

public DataComparison(){
lsb = gui.getLSB();

尝试{
File lossy = new File(gui.getLossyPath());
File lossless = new File(gui.getLosslessPath());

image = ImageIO.read(有损);
image2 = ImageIO.read(无损);
width = image.getWidth();
height = image.getHeight();

cLossyData = new int [height] [width] [3];
cLosslessData = new int [height] [width] [3]; (int j = 0; j< width; j ++){
; color = c = new(i ++){
)为

。颜色(image.getRGB(j,i));
颜色c2 =新颜色(image2.getRGB(j,i));

lossyData + = getLSB(integerToBinary((int)(c.getRed())),lsb);
lossyData + = getLSB(integerToBinary((int)(c.getGreen())),lsb);
lossyData + = getLSB(integerToBinary((int)(c.getBlue())),lsb);

losslessData + = getLSB(integerToBinary((int)(c2.getRed())),lsb);
losslessData + = getLSB(integerToBinary((int)(c2.getGreen())),lsb);
losslessData + = getLSB(integerToBinary((int)(c2.getBlue())),lsb);

cLossyData [i] [j] [0] = c.getRed();
cLossyData [i] [j] [1] = c.getGreen();
cLossyData [i] [j] [2] = c.getBlue();

cLosslessData [i] [j] [0] = c2.getRed();
cLosslessData [i] [j] [1] = c2.getGreen();
cLosslessData [i] [j] [2] = c2.getBlue();

if(limit> = 8 * lsb){
break;
}
}
}

int counter = 0;
while(counter * 8 int index = counter * 8;
String str = lossyData.substring(index,index + 8);
String str2 = losslessData.substring(index,index + 8);
lyData + = str;
lsData + = str2; ();
if(!str2.equals(00000000)){
lossyMessage + = new Character((char)Integer.parseInt(str,2))。toString();
losslessMessage + = new Character((char)Integer.parseInt(str2,2))。toString();
counter ++;
}
else {
lyData = lyData.substring(0,lyData.length() - 8);
lsData = lsData.substring(0,lsData.length() - 8);
break;
}
}
int i = 0,lostBits = 0;
while(i< lyData.length()){
if(lyData.charAt(i)!= lsData.charAt(i)){
lostBits ++;
}
i ++;

gui.appendStatus(解码的数据是(Lossless):\\\+ lsData +\。);
gui.appendStatus(数据解码为(有损):\\\+ lyData +\。);
gui.appendStatus(lsb:+ lsb);
gui.appendStatus(位数(隐藏信息):+ counter * 8);
gui.appendStatus(丢失位数(隐藏消息):+ lostBits);

float z =((lostBits * 100)/(counter * 8));
String percentage = String.format(%。04f,z);

gui.appendStatus(丢失的百分比(隐藏信息):+百分比+%);
gui.appendStatus(解码后的消息是(Lossless):\+ losslessMessage +\。);
gui.appendStatus(解码后的消息是(有损):\+ lossyMessage +\。);
gui.appendStatus(字符数:+ counter);

int counterR = 0,counterG = 0,counterB = 0; (int q = 0; q if(cLosslessData [p] [q ] [0]!= cLossyData [p] [q] [0]){
counterR ++;

else if(cLosslessData [p] [q] [1]!= cLossyData [p] [q] [1]){
counterG ++;

else if(cLosslessData [p] [q] [2]!= cLossyData [p] [q] [2]){
counterB ++;


$ b gui.appendStatus(Total RGB values:+ width * height * 3);
gui.appendStatus(Red red values:+ counterR);
gui.appendStatus(改变的绿色值:+ counterG);
gui.appendStatus(改变的蓝色值:+ counterB);
gui.appendStatus(Total Altered values:+(counterR + counterG + counterB));
$ b z =((counterR + counterG + counterB)* 10000)/(width * height * 3);
百分比= String.format(%。02f,z / 100);

gui.appendStatus(Percentage Altered values:+ percentage +%);

reinitialize();
} catch(Exception e){}


$ b public static void reinitialize(){
losslessData = lossyData = lsData = lyData = losslessMessage = lossyMessage =;
limit = width = height = lsb = 0;
Arrays.fill(cLossyData,0);
Arrays.fill(cLosslessData,0);

$ b $ public static String integerToBinary(int i){
return String.format(%8s,Integer.toBinaryString(i))。replace('','' 0' ); //http://stackoverflow.com/questions/21856626/java-integer-to-binary-string
}

public static String getLSB(String s,int x){
String result =;
for(int i = 8 -x; i result + = s.charAt(i);
if(s.charAt(i)=='0')
limit + = 1;
else
limit = 0;
}
返回结果;


public static void main(String [] args){
// TODO代码应用程序逻辑
gui = new DataComparisonGUI();
gui.setVisible(true);





$ p $上面的代码是基于我原来的编码/解码算法。一个不停止循环。我尝试编辑代码,并应用新的解码算法,但我不能使它工作。

解决方案

编码更改



首先,对于编码部分,您需要更改以下行:

  binarizedMessage = stringToBinary(messageToBeHidden); 

  binarizedMessage = stringToBinary(messageToBeHidden)+00000000; 

这是因为在提取过程中,当您连续发现8个0时, 。

现在,为了终止编码顺序,您需要相应地修改您的循环。

对于(int j = 0; j )来说, encoding:
for(int i = 0; i<颜色c =新颜色(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));

颜色newColor =新颜色(红色,绿色,蓝色);
image.setRGB(j,i,newColor.getRGB());

if(count == binarizedMessage.length())break encoding;



$ b $变量 count 每当您在 insertMessage 方法中嵌入一点,code>就会增加。一旦达到 binarizedMessage.length()的值,即使被调用,它也会停止嵌入。所以,你只需要检查你是否每次在(i,j)处访问一个新的像素都嵌入了所有的位。然而,嵌入可能会被完成一个像素的红色,但为绿色和蓝色调用 insertMessage ,即使它不会嵌入任何新的东西,它仍然会清除这些颜色的LSB。因此,让我们修改 insertMessage 以防止这些不必要的修改。

  public static String insertMessage(String s,int x){
String result;
if(count< binarizedMessage.length()){
result = clearLSB(s,x);
} else {
result = s;

StringBuilder temp = new StringBuilder(result); (b,b,b,b,b,b,b,b,b,b,b),如果(计数 temp.setCharAt(i, binarizedMessage.charAt(计数++));
}

return temp.toString();




$ b $ h2解码变更

<$ (int i = 0; i for(int j = 0; j
颜色c =新颜色(image.getRGB(j,i));

encodedData + = getLSB(integerToBinary((int)(c.getRed())),numLSB);
if(限制> = 8)中断解码;
encodedData + = getLSB(integerToBinary((int)(c.getGreen())),numLSB);
if(限制> = 8)中断解码;
encodedData + = getLSB(integerToBinary((int)(c.getBlue())),numLSB);
if(限制> = 8)中断解码;




$ b每当你从一种颜色中提取新的位时,使用 limit 变量来检查(至少)最后8位是否为0,表示消息结束。在嵌入每种颜色之后而不是在蓝色之后,必须检查这种情况。考虑在红色后发现消息结束的情况,但进行绿色和蓝色,你会遇到1重置限制。



最后,您需要更改以下代码块:

$ $ $ $ $ $ $ $ $> int counter = 0;
while(counter * 8< encodedData.length()){
int index = counter * 8;
String str = encodedData.substring(index,index + 8);
eData + = str; ();
if(!str.equals(00000000)){
encodedMessage + = new Character((char)Integer.parseInt(str,2))。toString();
counter ++;
}
else {
eData = eData.substring(0,eData.length() - 8);
break;




$ b $ p $
$ b (int index = 0; index< encodedData.length()/ 8; index ++){
String str = encodedData.substring(8 * index, 8 *指数+ 8);
eData + = str;
encodedMessage + = new Character((char)Integer.parseInt(str,2))。toString();



$ b $ p
$ b $由于你检查最后8位是0的方式,消息你好世界。这是11个字符,所以88位+8用于终止消息= 96位。然而,d的二进制数是01100100,所以一旦你提取了94位,就会遇到8个0,并且中断提取顺序。如果我们用8进行94的整数除法,则得到整个数字11,这是我们消息的字符数。所以我们把前88位转换成字符,我们的工作就完成了。




这个答案超出了范围,但一个建议。考虑使用 AND 和 OR 。这是更优雅,因为你不必将整数转换为字符串,然后回到整数,它会提供较小的,但在你的情况下,不明显,性能改善。

I have this code, trying to do encoding message in images using least significant bit method. What I can't figure out is that how to end the encoding of message when there is no message to encode left.

It just continues until the end of the end of the loop.

I tried counters like limit. Same with what I did in the decoding part but with no avail that's why I removed it.

I included these methods because they were used and can be used to contain counters to identify if message is done encoding and can stop iterating

Encoding and Decoding are in the constructor.

public class Steganography {

    public static SteganographyGUI gui;
    public static String binarizedMessage = "", encodedMessage = "", decodedMessage = "";
    public static int count = 0, limit = 0;

    public static BufferedImage image;
    public static int width, height, numLSB;

    public Steganography() {
        if(gui.isEncode()){
            try {
                String messageToBeHidden = gui.getMessage();
                binarizedMessage = stringToBinary(messageToBeHidden);

                File input = new File(gui.getPath());
                image = ImageIO.read(input);
                width = image.getWidth();
                height = image.getHeight();
                gui.appendStatus("File Name: " + gui.getFileName() + "\nWidth: " + width + "\nHeight: " + height + "\nLSB: " + gui.getSelectedLSB());
                numLSB = gui.getSelectedLSB();
                //encoding
                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()+"lossy.jpg");

                ImageWriter jpgWriter = ImageIO.getImageWritersByFormatName("jpg").next();
                ImageWriteParam jpgWriteParam = jpgWriter.getDefaultWriteParam();
                jpgWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
                jpgWriteParam.setCompressionQuality(1f);

                FileImageOutputStream outputStream = new FileImageOutputStream(output); //For example, FileImageOutputStream
                jpgWriter.setOutput(outputStream);
                IIOImage outputImage = new IIOImage(image, null, null);
                jpgWriter.write(null, outputImage, jpgWriteParam);
                jpgWriter.dispose();

                File output2 = new File(gui.getOutput()+"lossless.jpg");
                ImageIO.write(image, "png", output2);
                gui.appendStatus("Message \""+ messageToBeHidden +"\" was encoded in "+ gui.getFileName() +".\nOutput files are: " + gui.getOutput() + "lossy.jpg \n\t"+ gui.getOutput() + "lossless.jpg");
            } catch (Exception e) {}
        }
        else{
            File input = new File(gui.getPath());
            String encodedData = "";
            try {
                image = ImageIO.read(input);
            } catch (IOException ex) {}
            width = image.getWidth();
            height = image.getHeight();
            gui.appendStatus("File Name: " + gui.getFileName() + "\nWidth: " + width + "\nHeight: " + height + "\nLSB: " + gui.getSelectedLSB());
            numLSB = gui.getSelectedLSB();
            String eData = "";
            //decoding
            for(int i = 0; i < height; i++){
                for(int j = 0; j < width; j++){
                    Color c = new Color(image.getRGB(j, i));

                    encodedData += getLSB(integerToBinary((int)(c.getRed())),numLSB);
                    encodedData += getLSB(integerToBinary((int)(c.getGreen())),numLSB);
                    encodedData += getLSB(integerToBinary((int)(c.getBlue())),numLSB);

                    if(limit >= 8 * numLSB){
                        break;
                    }
                }
            }
            int counter = 0;
            while(counter * 8 < encodedData.length()){
                int index = counter * 8;
                String str = encodedData.substring(index, index + 8);
                eData += str;
                if(!str.equals("00000000")){
                    encodedMessage += new Character((char)Integer.parseInt(str, 2)).toString();
                    counter++;
                }
                else{
                    eData = eData.substring(0,eData.length()-8);
                    break;
                }
            }
            gui.appendStatus("Data decoded was: \""   + eData + "\".");
            gui.appendStatus("Message decoded was: \""   + encodedMessage + "\".");
            gui.appendStatus("Number of characters: " + counter);
        }
        reinitialize();
    }

    public static void reinitialize(){
        binarizedMessage = encodedMessage = decodedMessage = "";
        count = limit = width = height = numLSB = 0;
    }

    public static String stringToBinary(String s){
        byte[] bytes = s.getBytes();                    // http://stackoverflow.com/questions/917163/convert-a-string-like-testing123-to-binary-in-java
        StringBuilder binary = new StringBuilder();
        for (byte b : bytes) {
            int val = b;
            for (int i = 0; i < 8; i++){
                binary.append((val & 128) == 0 ? 0 : 1);
                val <<= 1;
            }
        }
        return binary.toString();
    }

    public static String integerToBinary(int i){
        return String.format("%8s", Integer.toBinaryString(i)).replace(' ', '0');           //http://stackoverflow.com/questions/21856626/java-integer-to-binary-string
    }

    public static int binaryToInteger(String s){
        return Integer.parseInt(s, 2);                                       //http://stackoverflow.com/questions/7437987/how-to-convert-binary-string-value-to-decimal
    }                                                                       //http://stackoverflow.com/questions/10178980/how-to-convert-a-binary-string-to-a-base-10-integer-in-java

    public static String clearLSB(String s, int x){
        StringBuilder result = new StringBuilder(s);                //http://stackoverflow.com/questions/6952363/java-replace-a-character-at-a-specific-index-in-a-string
        for (int i = 8 - x; i < 8; i++){
            result.setCharAt(i, '0');
        }
        return result.toString();                       //http://www.tutorialspoint.com/java/lang/stringbuilder_tostring.htm
    }

    public static String insertMessage(String s, int x){
        String result = clearLSB(s, x);
        StringBuilder temp = new StringBuilder(result);

        for (int i = 8 - x; i < 8; i++){
            if(count < binarizedMessage.length())
                temp.setCharAt(i, binarizedMessage.charAt(count++));
        }

        return temp.toString();
    }

    public static String getLSB(String s, int x){
        String result = "";
        for (int i = 8 - x; i < 8; i++){
            result += s.charAt(i);
            if(s.charAt(i) == '0')
                limit += 1;
            else
                limit = 0;
        }
        return result;
    }

    public static String binaryToText(String s){
        StringBuilder sb = new StringBuilder();
        count = 0;
        while(count<s.length()){
            StringBuilder sb2 = new StringBuilder();
            for (int i = 0; i < 8; i++){
                if(count<s.length())
                    sb2.append(s.charAt(count++));
                else
                    sb2.append('0');
                break;
            }
            //binary to char and append to sb
            sb.append((char)Integer.parseInt( sb.toString(), 2 ) );
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        gui = new SteganographyGUI();
        gui.setVisible(true);
    }

}

EDIT:

Seems that the first problem was fixed but created another problem.

Now that i've changed my decoding and encoding based on the answer below by Reti43, I cant get my dataComparison to work. I tried applying the decoding lines you pointed out but I fail to get the encoded data in the picture.

Here is the original DataComparison

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Arrays;
import javax.imageio.ImageIO;

public class DataComparison {

    public static DataComparisonGUI gui;
    public static BufferedImage image, image2;
    public static int width, height, lsb, limit = 0;

    public static String lossyData = "", losslessData = "", lsData = "", lyData = "";
    public static String lossyMessage = "", losslessMessage = "";

    public static int[][][] cLossyData, cLosslessData;

    public DataComparison(){
        lsb = gui.getLSB();

        try{
            File lossy = new File(gui.getLossyPath());
            File lossless = new File(gui.getLosslessPath());

            image = ImageIO.read(lossy);
            image2 = ImageIO.read(lossless);
            width = image.getWidth();
            height = image.getHeight();

            cLossyData = new int[height][width][3];
            cLosslessData = new int[height][width][3];

            for(int i = 0; i < height; i++){
                for(int j = 0; j < width; j++){
                    Color c = new Color(image.getRGB(j, i));
                    Color c2 = new Color(image2.getRGB(j, i));

                    lossyData += getLSB(integerToBinary((int)(c.getRed())),lsb);
                    lossyData += getLSB(integerToBinary((int)(c.getGreen())),lsb);
                    lossyData += getLSB(integerToBinary((int)(c.getBlue())),lsb);

                    losslessData += getLSB(integerToBinary((int)(c2.getRed())),lsb);
                    losslessData += getLSB(integerToBinary((int)(c2.getGreen())),lsb);
                    losslessData += getLSB(integerToBinary((int)(c2.getBlue())),lsb);

                    cLossyData[i][j][0] = c.getRed();
                    cLossyData[i][j][1] = c.getGreen();
                    cLossyData[i][j][2] = c.getBlue();

                    cLosslessData[i][j][0] = c2.getRed();
                    cLosslessData[i][j][1] = c2.getGreen();
                    cLosslessData[i][j][2] = c2.getBlue();

                    if(limit >= 8 * lsb){
                        break;
                    }
                }
            }

            int counter = 0;
            while(counter * 8 < losslessData.length()){
                int index = counter * 8;
                String str = lossyData.substring(index, index + 8);
                String str2 = losslessData.substring(index, index + 8);
                lyData += str;
                lsData += str2;
                if(!str2.equals("00000000")){
                    lossyMessage += new Character((char)Integer.parseInt(str, 2)).toString();
                    losslessMessage += new Character((char)Integer.parseInt(str2, 2)).toString();
                    counter++;
                }
                else{
                    lyData = lyData.substring(0,lyData.length()-8);
                    lsData = lsData.substring(0,lsData.length()-8);
                    break;
                }
            }
            int i = 0, lostBits = 0;
            while(i < lyData.length()){
                if(lyData.charAt(i) != lsData.charAt(i)){
                    lostBits++;
                }
                i++;
            }
            gui.appendStatus("Data decoded was (Lossless):\n\""   + lsData + "\".");
            gui.appendStatus("Data decoded was (Lossy):\n\""   + lyData + "\".");
            gui.appendStatus("Number of lsb: " + lsb);
            gui.appendStatus("Number of bits (hidden message): " + counter * 8);
            gui.appendStatus("Number of lost bits (hidden message): " + lostBits);

            float z = ((lostBits*100)/(counter*8));
            String percentage = String.format("%.04f", z);

            gui.appendStatus("Percentage of lost bits (hidden message): " + percentage + "%");
            gui.appendStatus("Message decoded was (Lossless): \""   + losslessMessage + "\".");
            gui.appendStatus("Message decoded was (Lossy): \""   + lossyMessage + "\".");
            gui.appendStatus("Number of characters: " + counter);

            int counterR = 0, counterG = 0, counterB = 0;
            for(int p = 0; p < height; p++){
                for(int q = 0; q < width; q++){
                    if(cLosslessData[p][q][0] != cLossyData[p][q][0]){
                        counterR++;
                    }
                    else if(cLosslessData[p][q][1] != cLossyData[p][q][1]){
                        counterG++;
                    }
                    else if(cLosslessData[p][q][2] != cLossyData[p][q][2]){
                        counterB++;
                    }
                }
            }
            gui.appendStatus("Total RGB values: " + width * height * 3);
            gui.appendStatus("Altered Red values: " + counterR);
            gui.appendStatus("Altered Green values: " + counterG);
            gui.appendStatus("Altered Blue values: " + counterB);
            gui.appendStatus("Total Altered values: " + (counterR + counterG + counterB));

            z = ((counterR + counterG + counterB)*10000)/(width * height * 3);
            percentage = String.format("%.02f", z/100);

            gui.appendStatus("Percentage Altered values: " + percentage + "%");

            reinitialize();
        } catch (Exception e) {}

    }

    public static void reinitialize(){
        losslessData = lossyData = lsData = lyData = losslessMessage = lossyMessage = "";
        limit = width = height = lsb = 0;
        Arrays.fill(cLossyData, 0);
        Arrays.fill(cLosslessData, 0);
    }

    public static String integerToBinary(int i){
        return String.format("%8s", Integer.toBinaryString(i)).replace(' ', '0');           //http://stackoverflow.com/questions/21856626/java-integer-to-binary-string
    }

    public static String getLSB(String s, int x){
        String result = "";
        for (int i = 8 - x; i < 8; i++){
            result += s.charAt(i);
            if(s.charAt(i) == '0')
                limit += 1;
            else
                limit = 0;
        }
        return result;
    }

    public static void main(String[] args) {
        // TODO code application logic here
        gui = new DataComparisonGUI();
        gui.setVisible(true);
    }

}

The code above was working based on my original encoding/decoding algorithm. The one that doesnt stop the loop. I tried editing the code and applying the new decoding algorithm but I cant make it work.

解决方案

Encoding changes

First things first, for the encoding part you need to change the following line

binarizedMessage = stringToBinary(messageToBeHidden);

to

binarizedMessage = stringToBinary(messageToBeHidden) + "00000000";

This is because in the extraction, the end of message is reached when you find eight 0s in a row.

Now, for terminating the encoding sequence, you need to modify your loops accordingly.

encoding:
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());

        if (count == binarizedMessage.length()) break encoding;
    }
}

The variable count is incremented every time you embed a bit in the insertMessage method. As soon as it has reached the value of binarizedMessage.length(), it will stop embedding even though it is called. So, you just need to check whether you have embedded all bits every time you access a new pixel at (i, j).

However, the embedding may be finished with the red color of a pixel, but calling insertMessage for green and blue, even though it will not embed anything new, it will still clear the lsbs of those colors. So, let's modify insertMessage to prevent these unnecessary modifications.

public static String insertMessage(String s, int x){
    String result;
    if (count < binarizedMessage.length()) {
        result = clearLSB(s, x);
    } else {
        result = s;
    }
    StringBuilder temp = new StringBuilder(result);

    for (int i = 8 - x; i < 8; i++){
        if(count < binarizedMessage.length())
            temp.setCharAt(i, binarizedMessage.charAt(count++));
    }

    return temp.toString();
}

Decoding changes

decoding:
for(int i = 0; i < height; i++){
    for(int j = 0; j < width; j++){
        Color c = new Color(image.getRGB(j, i));

        encodedData += getLSB(integerToBinary((int)(c.getRed())),numLSB);
        if(limit >= 8) break decoding;
        encodedData += getLSB(integerToBinary((int)(c.getGreen())),numLSB);
        if(limit >= 8) break decoding;
        encodedData += getLSB(integerToBinary((int)(c.getBlue())),numLSB);
        if(limit >= 8) break decoding;
    }
}

Every time you extract new bits from a color, you use the limit variable to check whether (at least) the last 8 bits are 0, signifying the end of message. This condition must be checked after embedding in each color and not after blue. Consider the case where the end of message is found after red, but carrying on to green and blue, you come across with a 1 which resets limit.

Finally, you need to change the following block

int counter = 0;
while(counter * 8 < encodedData.length()){
    int index = counter * 8;
    String str = encodedData.substring(index, index + 8);
    eData += str;
    if(!str.equals("00000000")){
        encodedMessage += new Character((char)Integer.parseInt(str, 2)).toString();
        counter++;
    }
    else{
        eData = eData.substring(0,eData.length()-8);
        break;
    }
}

to

for (int index = 0; index < encodedData.length()/8; index++) {
    String str = encodedData.substring(8*index, 8*index+8);
    eData += str;
    encodedMessage += new Character((char)Integer.parseInt(str, 2)).toString();
}

Because of the way you check for the last eight bits being 0, consider the message "hello world". That's 11 characters, so 88 bits + 8 for terminating the message = 96 bits. However, the binary for "d" is 01100100, So once you have extracted 94 bits, you have come across with eight 0s and break the extracting sequence. If we do integer division of 94 with 8, we get the whole number 11, which is the number of characters of our message. So we convert the first 88 bits to characters and our job is done.


This is out of scope for the answer, but a piece of advice. Consider clearing, modifying and extracting bits using the bitwise operations AND and OR. It's more elegant since you don't have to convert integers to strings and then back to integers and it would provide minor, though not noticeable in your case, performance improvements.

这篇关于如何结束嵌套循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-19 12:50