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
Code:
public class LSB_oneBit implements LSB {
 
//Variables ending in R are for reveal method not yet implemented.
protected byte[] imageBytes;
protected byte[] textBytes;
protected BufferedImage image;
//protected byte[] imageBytesR;
//protected byte[] textBytesR; 
 
protected int offset;
//protected int offsetR;
protected int messageLength;
 
protected SaveFile file;
 
protected GetBytes imageB;
protected GetBytes textB;
//protected GetBytes revealImageR;
 
protected String dirName;
protected String imageFileName;
//protected String imageFileNameR;
protected String textFileName;
//protected String messageR;
protected String saveFileName;
//protected String saveFileNameR;
 
//protected OutputStream out;
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)
        {                  
            //All in one way of reading ByteArray.     
            in = new ByteArrayInputStream(imageBytes);
            image = ImageIO.read(in);
            System.out.println("Modified image buffered");
            file = new SaveFile(saveFileName);
            file.writeImage(image);
            return true;
 
            //Method for returning byte[] to SaveFile class instead of bufferedImage
            /*InputStream in = new ByteArrayInputStream(imageBytes);
            //BufferedImage modifiedImage = ImageIO.read(in);
            System.out.println("Modified image buffered");
            file = new SaveFile(saveFileName, modifiedImage, dirName);
            file.writeImage(); 
            return true;*/
 

            //Method for writing to file straight from LSB_oneBit class using FileOutputStream
            /*File myFile = new File(dirName,saveFileName);
            System.out.println("Filename is: " + saveFileName);
 
            try 
            {
                out = new FileOutputStream(myFile);
            } 
            catch (FileNotFoundException ex) 
            {
                Logger.getLogger(LSB_oneBit.class.getName()).log(Level.SEVERE, null, ex);
            }
            try
            {
            out.write(imageBytes);
            System.out.println("Image file written successfully");
            return true;
            }
            catch(IOException e)
            {
            System.out.println("Cannot save file " + e.getMessage());
            e.printStackTrace();
            e.getMessage();
            return false;
            }
            finally
            {
            out.close();
            }*/
      }
 
   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
Code:
public class SaveFile {
 
protected String saveFileName;
protected BufferedImage image;
protected BufferedWriter writer;
protected String dirName;
//Used for writing byte[] method
//protected byte[] imageBytes;
protected File file;
private BufferedImage bi;
protected Graphics graphics;
 

public SaveFile(String saveFileName /*String dirName*/ /*byte[] imageBytes*/ )
{
    this.saveFileName = saveFileName;
    //this.dirName = dirName;
    //this.imageBytes = imageBytes;
}
 

 
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
            {
             //Method for writing byte[] object
             /*FileOutputStream output = new FileOutputStream(file);
             output.write(imageBytes);
             output.flush();
             output.close();*/
 
             //Method for writing BufferedImage object   
 
              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();
 

 
             //file = new File(dirName);
             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);  
       /*FileOutputStream output = new FileOutputStream(file);
       output.write(imageBytes);
       output.flush();
       output.close();
       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;
 
       }
 
  }
}
 
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();
        }
    }
}
 

 
}