I was wondering if anyone had any ideas what is going wrong with my LSB steganography application. The problem is that I cannot get a modified image file (with secret text hidden in the LSBs) to save. I have already tested out the algorithm in a small test program using an array of zero bytes (00000000) to hide a small message and it does modify the LSBs as intended. I have also tried to buffer and then re-save an unmodified image - which also works.
I cannot work out what is going wrong when trying to save it and have already tried various methods (FileOutPutStream, Image.io write) none of which appears to work. It saves successfully but every time it produces a blank image file (the file is the right size, however, when opened is all black and some applications cannot open it at all - does this on all save methods I've tried).
The program has a class to buffer images/text (Buffer), extract byte data from buffered images/text (GetBytes) and save the modified file (SaveFile). I have included the hide method and algorithm as well as the SaveFile class as I think thats where the problem may be. Please let me know if anymore info/code is needed.
Below is my code:
LSB hide method and algorithm
public class LSB_oneBit implements LSB {
protected byte[] imageBytes;
protected byte[] textBytes;
protected BufferedImage image;
protected int offset;
protected int messageLength;
protected SaveFile file;
protected GetBytes imageB;
protected GetBytes textB;
protected String dirName;
protected String imageFileName;
protected String textFileName;
protected String saveFileName;
protected InputStream in;
public LSB_oneBit() throws IOException
{
}
@Override
public boolean hide(String imageFileName, String textFileName, String saveFileName, String dirName, int offset)throws IOException
{
this.imageFileName = imageFileName;
this.textFileName = textFileName;
imageB = new GetBytes();
imageBytes = imageB.getImageBytes(imageFileName);
textB = new GetBytes();
textBytes = textB.getTextBytes(textFileName);
for(byte x: textBytes)
{
System.out.println("Text bytes: " + Integer.toBinaryString(0x100 + x).substring(1));
}
this.saveFileName = saveFileName;
this.dirName = dirName;
this.offset = offset;
if(algorithm()!=false)
{
in = new ByteArrayInputStream(imageBytes);
image = ImageIO.read(in);
System.out.println("Modified image buffered");
file = new SaveFile(saveFileName);
file.writeImage(image);
return true;
}
else
return false;
}
public boolean algorithm()
{
if(checkSize()!=false)
{
try
{
for (int i = 0; i<textBytes.length; i++)
{
int textByteValue = textBytes[i];
byte textByteValueB = (byte) textByteValue;
for(int x = 7; x>=0; x--)
{
int textBitValue = ((textByteValue>>>x)& 1);
byte textBitValueB = (byte)textBitValue;
imageBytes[offset] = (byte) ((imageBytes[offset]&0xFE) | textBitValueB);
offset++;
}
}
System.out.println("Image bytes modified");
return true;
}
catch (Exception e)
{
e.getMessage();
e.printStackTrace();
return false;
}
}
else
{
return false;
}
}
public boolean checkSize()
{
int imageSize = imageBytes.length;
System.out.println("Image size is: " + imageSize);
int textSize = textBytes.length;
System.out.println("Text size is: " + textSize);
if((textSize*8)<=imageSize)
{
System.out.println("Text can fit into the image");
return true;
}
return false;
}
}
SaveFile Class
public class SaveFile {
protected String saveFileName;
protected BufferedImage image;
protected BufferedWriter writer;
protected String dirName;
protected File file;
private BufferedImage bi;
protected Graphics graphics;
public SaveFile(String saveFileName )
{
this.saveFileName = saveFileName;
}
public boolean writeImage(BufferedImage nImage)
{
this.image = nImage;
file = new File(saveFileName);
if (file.exists()== true)
{
String stringConfirm = JOptionPane.showInputDialog("File already exists, do you wish to overwrite? Y/N");
char confirm = stringConfirm.charAt(0);
if (confirm =='Y')
{
try
{
bi = new BufferedImage(515,686, BufferedImage.TYPE_4BYTE_ABGR);
graphics = bi.getGraphics();
graphics.clearRect(0, 0, 515, 686);
graphics.drawImage(image, 0, 0, null);
graphics.dispose();
ImageIO.write(bi, "png", file);
System.out.println("Image written to PNG file");
return true;
}
catch(IOException e)
{
System.out.println("Unable to write image to file" + e.getMessage());
return false;
}
}
else
return false;
}
else
{
try
{
bi = new BufferedImage(515,686, BufferedImage.TYPE_4BYTE_ABGR);
graphics = bi.getGraphics();
graphics.clearRect(0, 0, 515, 686);
graphics.drawImage(image, 0, 0, null);
graphics.dispose();
ImageIO.write(bi, "png", file);
return true;
}
catch(IOException e)
{
System.out.println("Unable to write image to file" + e.getMessage());
return false;
}
}
}
public boolean writeText(String text)
{
writer = null;
try
{
writer = new BufferedWriter(new FileWriter(saveFileName));
writer.write(text);
return true;
}
catch(IOException e)
{
System.out.println("Cannot write to file");
e.getMessage();
e.printStackTrace();
return false;
}
finally
{
try
{
if(writer!=null)
writer.close();
}
catch(IOException e)
{
System.out.println("Cannot close writer");
e.getMessage();
e.printStackTrace();
}
}
}
}