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.