8 Replies - 1005 Views - Last Post: 15 November 2012 - 02:28 PM Rate Topic: -----

#1 Sai077  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 15-November 12

Need help with Steganography

Posted 15 November 2012 - 09:03 AM

Hey D.I.C,

I'm new to Java and was hoping I could get some help involving Steganography. I've already looked at the code over at http://www.dreaminco...-steganography/ and I'm currently trying to modify it to remove the GUI. In other words, I want to combine the Stegonagraphy.java and Steganography_Controller.java classes. So far I have come up with the following:

package Steg;

import java.io.File;

import java.awt.Point;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.awt.image.DataBufferByte;

import javax.imageio.ImageIO;
import javax.swing.JOptionPane;


public class Steganography
{
	public static void main(String args[])
	{
		System.out.println(decode(null, null));
	}
	
	/*
	 *Encrypt an image with text, the output file will be of type .png
	 *@param path         The path (folder) containing the image to modify
	 *@param original    The name of the image to modify
	 *@param ext1          The extension type of the image to modify (jpg, png)
	 *@param stegan      The output name of the file
	 *@param message  The text to hide in the image
	 *@param type	  integer representing either basic or advanced encoding
	 */
	public boolean encode(String path, String original, String ext1, String stegan, String message)
	{
		
		message = "Confidence is the feeling you have before you understand the situation";
		ext1  = ".jpeg";
		original = "ColumbineLakeColorado";
		path = "C:/Users/Sai077/workspace/Stegonagraphy/src";
		stegan = "Colorado";
		
		String			file_name 	= image_path(path,original,ext1);
		BufferedImage 	image_orig	= getImage(file_name);
		
		//user space is not necessary for Encrypting
		BufferedImage image = user_space(image_orig);
		image = add_text(image,message);
		
		return(setImage(image,new File(image_path(path,stegan,"png")),"png"));
	}
	
	/*
	 *Decrypt assumes the image being used is of type .png, extracts the hidden text from an image
	 *@param path   The path (folder) containing the image to extract the message from
	 *@param name The name of the image to extract the message from
	 *@param type integer representing either basic or advanced encoding
	 */
	public static String decode(String path, String name)
	{
		
		path = "C:/Users/Sai077/workspace/Stegonagraphy/src";
		name ="stegTowerMtnColorado";
		byte[] decode;
		try
		{
			//user space is necessary for decrypting
			BufferedImage image  = user_space(getImage(image_path(path,name,"png")));
			decode = decode_text(get_byte_data(image));
			return(new String(decode));
		}
        catch(Exception e)
        {
			JOptionPane.showMessageDialog(null, 
				"There is no hidden message in this image!","Error",
				JOptionPane.ERROR_MESSAGE);
			return "";
        }
    }
    
	/*
	 *Returns the complete path of a file, in the form: path\name.ext
	 *@param path   The path (folder) of the file
	 *@param name The name of the file
	 *@param ext      The extension of the file
	 *@return A String representing the complete path of a file
	 */
	private static String image_path(String path, String name, String ext)
	{
		return path + "/" + name + "." + ext;
	}
	
	/*
	 *Get method to return an image file
	 *@param f The complete path name of the image.
	 *@return A BufferedImage of the supplied file path
	 *@see    Steganography.image_path
	 */
	private static BufferedImage getImage(String f)
	{
		f = "C:/Users/Sai077/workspace/Stegonagraphy/src/stegTowerMtnColorado";
		BufferedImage 	image	= null;
		File 		file 	= new File(f);
		
		try
		{
			image = ImageIO.read(file);
		}
		catch(Exception ex)
		{
			JOptionPane.showMessageDialog(null, 
				"Image could not be read!","Error",JOptionPane.ERROR_MESSAGE);
		}
		return image;
	}
	
	/*
	 *Set method to save an image file
	 *@param image The image file to save
	 *@param file      File  to save the image to
	 *@param ext      The extension and thus format of the file to be saved
	 *@return Returns true if the save is succesful
	 */
	private boolean setImage(BufferedImage image, File file, String ext)
	{
		ext = ".png";
		try
		{
			file.delete(); //delete resources used by the File
			ImageIO.write(image,ext,file);
			return true;
		}
		catch(Exception e)
		{
			JOptionPane.showMessageDialog(null, 
				"File could not be saved!","Error",JOptionPane.ERROR_MESSAGE);
			return false;
		}
	}
	
	/*
	 *Handles the addition of text into an image
	 *@param image The image to add hidden text to
	 *@param text     The text to hide in the image
	 *@return Returns the image with the text embedded in it
	 */
	private BufferedImage add_text(BufferedImage image, String text)
	{
		text = "Confidence is the feeling you have before you understand the situation";
		//convert all items to byte arrays: image, message, message length
		byte img[]  = get_byte_data(image);
		byte msg[] = text.getBytes();
		byte len[]   = bit_conversion(msg.length);
		try
		{
			encode_text(img, len,  0); //0 first position
			encode_text(img, msg, 32); //4 bytes of space for length: 4bytes*8bit = 32 bits
		}
		catch(Exception e)
		{
			JOptionPane.showMessageDialog(null, 
"Target File cannot hold message!", "Error",JOptionPane.ERROR_MESSAGE);
		}
		return image;
	}
	
	/*
	 *Creates a user space version of a Buffered Image, for editing and saving bytes
	 *@param image The image to put into user space, removes compression interferences
	 *@return The user space version of the supplied image
	 */
	private static BufferedImage user_space(BufferedImage image)
	{
		//create new_img with the attributes of image
		BufferedImage new_img  = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
		Graphics2D    graphics = new_img.createGraphics();
		graphics.drawRenderedImage(image, null);
		graphics.dispose(); //release all allocated memory for this image
		return new_img;
	}
	
	/*
	 *Gets the byte array of an image
	 *@param image The image to get byte data from
	 *@return Returns the byte array of the image supplied
	 *@see Raster
	 *@see WritableRaster
	 *@see DataBufferByte
	 */
	private static byte[] get_byte_data(BufferedImage image)
	{
		WritableRaster raster   = image.getRaster();
		DataBufferByte buffer = (DataBufferByte)raster.getDataBuffer();
		return buffer.getData();
	}
	
	/*
	 *Gernerates proper byte format of an integer
	 *@param i The integer to convert
	 *@return Returns a byte[4] array converting the supplied integer into bytes
	 */
	private byte[] bit_conversion(int i)
	{
		//originally integers (ints) cast into bytes
		//byte byte7 = (byte)((i & 0xFF00000000000000L) >>> 56);
		//byte byte6 = (byte)((i & 0x00FF000000000000L) >>> 48);
		//byte byte5 = (byte)((i & 0x0000FF0000000000L) >>> 40);
		//byte byte4 = (byte)((i & 0x000000FF00000000L) >>> 32);
		
		//only using 4 bytes
		byte byte3 = (byte)((i & 0xFF000000) >>> 24); //0
		byte byte2 = (byte)((i & 0x00FF0000) >>> 16); //0
		byte byte1 = (byte)((i & 0x0000FF00) >>> 8 ); //0
		byte byte0 = (byte)((i & 0x000000FF)       );
		//{0,0,0,byte0} is equivalent, since all shifts >=8 will be 0
		return(new byte[]{byte3,byte2,byte1,byte0});
	}
	
	/*
	 *Encode an array of bytes into another array of bytes at a supplied offset
	 *@param image     Array of data representing an image
	 *@param addition Array of data to add to the supplied image data array
	 *@param offset      The offset into the image array to add the addition data
	 *@return Returns data Array of merged image and addition data
	 */
	private byte[] encode_text(byte[] image, byte[] addition, int offset)
	{
		//check that the data + offset will fit in the image
		if(addition.length + offset > image.length)
		{
			throw new IllegalArgumentException("File not long enough!");
		}
		//loop through each addition byte
		for(int i=0; i<addition.length; ++i)
		{
			//loop through the 8 bits of each byte
			int add = addition[i];
			for(int bit=7; bit>=0; --bit, ++offset) //ensure the new offset value carries on through both loops
			{
				//assign an integer to b, shifted by bit spaces AND 1
				//a single bit of the current byte
				int b = (add >>> bit) & 1;
				//assign the bit by taking: [(previous byte value) AND 0xfe] OR bit to add
				//changes the last bit of the byte in the image to be the bit of addition
				image[offset] = (byte)((image[offset] & 0xFE) | b );
			}
					}
		return image;
	}
    
	/*
	 *Retrieves hidden text from an image
	 *@param image Array of data, representing an image
	 *@return Array of data which contains the hidden text
	 */
	private static byte[] decode_text(byte[] image)
	{
		int length = 0;
		int offset  = 32;
		//loop through 32 bytes of data to determine text length
		for(int i=0; i<32; ++i) //i=24 will also work, as only the 4th byte contains real data
		{
			length = (length << 1) | (image[i] & 1);
		}
		
		byte[] result = new byte[length];
		
		//loop through each byte of text
		for(int b=0; b<result.length; ++b )
		{
			//loop through each bit within a byte of text
			for(int i=0; i<8; ++i, ++offset)
			{
				//assign bit: [(new byte value) << 1] OR [(text byte) AND 1]
				result[b] = (byte)((result[b] << 1) | (image[offset] & 1));
			}
		}
		return result;
	}
}



I'm getting an error hat the file could not be read, and I'm assuming it just has something to do with how I've combined the two programs. Essentially I just want to read a Jpeg in, assign the text, save it as a .png out, then read the test again from the .png.

Is This A Good Question/Topic? 0
  • +

Replies To: Need help with Steganography

#2 pbl  Icon User is offline

  • There is nothing you can't do with a JTable
  • member icon

Reputation: 8334
  • View blog
  • Posts: 31,858
  • Joined: 06-March 08

Re: Need help with Steganography

Posted 15 November 2012 - 09:08 AM

Post your stack trace

and respect Java conventions, a package name is all in lower case

private static BufferedImage getImage(String f)  
     {  

     f = "C:/Users/Sai077/workspace/Stegonagraphy/src/stegTowerMtnColorado"; 


And, what is the use to pass f as parameter to the getImage method if the first thing do you in that method is to overload that f ?
Your path, that you use to overload f, shouldn'it have a file extension ?

This post has been edited by pbl: 15 November 2012 - 09:12 AM

Was This Post Helpful? 0
  • +
  • -

#3 Sai077  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 15-November 12

Re: Need help with Steganography

Posted 15 November 2012 - 09:24 AM

View Postpbl, on 15 November 2012 - 09:08 AM, said:

Post your stack trace

and respect Java conventions, a package name is all in lower case

private static BufferedImage getImage(String f)  
     {  

     f = "C:/Users/Sai077/workspace/Stegonagraphy/src/stegTowerMtnColorado"; 


And, what is the use to pass f as parameter to the getImage method if the first thing do you in that method is to overload that f ?
Your path, that you use to overload f, shouldn'it have a file extension ?


The reason I thought I needed to overload f was because f is never assigned as anything else in the program. I've changed it to:
private static BufferedImage getImage(String f)  
     {  

     f = "C:/Users/Sai077/workspace/Stegonagraphy/src/stegTowerMtnColorado.png"; 



And it runs, except I get a "java.lang.OutOfMemoryError: Java heap space" now when running at the lines:

byte[] result = new byte[length];

decode = decode_text(get_byte_data(image));

System.out.println(decode(null, null));



Also, when assigning String f a JPEG file, the code still gives me a file not found error.
Was This Post Helpful? 0
  • +
  • -

#4 pbl  Icon User is offline

  • There is nothing you can't do with a JTable
  • member icon

Reputation: 8334
  • View blog
  • Posts: 31,858
  • Joined: 06-March 08

Re: Need help with Steganography

Posted 15 November 2012 - 10:16 AM

so write

private static BufferedImage getImage()  
     {  
     Sting f = "C:/Users/Sai077/workspace/Stegonagraphy/src/stegTowerMtnColorado.png"; 


kind of bad not having a general method would have been better to

     String file = "C:/Users/Sai077/workspace/Stegonagraphy/src/stegTowerMtnColorado.png"; 
     ...
     BufferedImage img = getImage(file);
     ...


    private static BufferedImage getImage(String f)  
    {  
      .. continue using f received as parameter



.png Image are very large. What is the size of your's ?
Was This Post Helpful? 0
  • +
  • -

#5 Sai077  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 15-November 12

Re: Need help with Steganography

Posted 15 November 2012 - 11:48 AM

Also, so I just decided to start the whole program over and not try to combine the two previous programs, however; I am running into some trouble. Here is my code so far:

package Steg;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;

import javax.imageio.ImageIO;

public class Encode {
	static final String MESSAGEFILE = "src/message.txt";
	static final String COVERIMAGEFILE = "src/ColumbineLakeColorado.jpeg";
	static final String STEGIMAGEFILE = "src/stegTowerMtnColorado.png";
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		String[] allWords = new String[1000];
		int sizeOfWords = 0;
		String message = "";

		sizeOfWords = readFile(allWords);
		for (int i = 0; i < sizeOfWords; i++) {
			message = message + " " + allWords[i];
		}

		boolean[] bits = createArrayOfBits(message);
		System.out.print(bits);
        BufferedImage theImage = readImageFile(COVERIMAGEFILE);
	}

	public static int readFile(String[] words) {
		int wordCount = 0;
		File file = new File(MESSAGEFILE);

		try {

			Scanner scanner = new Scanner(file);

			while (scanner.hasNext()) {

				words[wordCount] = scanner.next();
				wordCount = wordCount + 1;

			}
			scanner.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}

		return wordCount;
	}

	public static boolean[] createArrayOfBits(String message) {
		boolean[] bits = new boolean[1000];
		int m1 = message.length();
		double count = 0;
		int i = 0;
		for (; i < 16; i++) {
			count = Math.pow(2, 15 - i);
			if (m1 < count) {
				bits[i] = false;
				System.out.println(bits[i]);
			} else {
				bits[i] = true;
				System.out.println(bits[i]);
			}
			m1 = m1 - (15 - i);
		}
		return bits;
		
	}
	
public static BufferedImage readImageFile (String filePath) {
	BufferedImage theImage = null;
	File f = new File(filePath);
	try {
		theImage = ImageIO.read(f);
	} catch (IOException e) {
		e.printStackTrace();
		System.exit(1);
	}
	return theImage;
}

public static void writeImageFile(BufferedImage theImage) {
	File f = new File (STEGIMAGEFILE);
	try {
		ImageIO.write(theImage, "png", f);
	} catch (IOException e) {
		e.printStackTrace();
		System.exit(1);
	}
}


public static void hideTheMessage(boolean [] bits, String filepath) {
	
}

}


Here are my problems:

1. My bits array is not assigning correct vaules and I don't understand why. Everything is coming out as false. For the message it should be:

0 false
1 false
2 false
3 false
4 false
5 false
6 false
7 false
8 false
9 true
10 false
11 false
12 false
13 true
14 true
15 true

2. I'm getting a Can't read input file error on:
theImage = ImageIO.read(f);
. Not sure what's wrong there either.
Was This Post Helpful? 0
  • +
  • -

#6 pbl  Icon User is offline

  • There is nothing you can't do with a JTable
  • member icon

Reputation: 8334
  • View blog
  • Posts: 31,858
  • Joined: 06-March 08

Re: Need help with Steganography

Posted 15 November 2012 - 12:05 PM

If the read failed, how do you expect the bit array to be correct ?
boolean array are initialized to false in Java so here you have your answer. You create it but never filled it as the read failed
Was This Post Helpful? 0
  • +
  • -

#7 Sai077  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 15-November 12

Re: Need help with Steganography

Posted 15 November 2012 - 12:42 PM

View Postpbl, on 15 November 2012 - 12:05 PM, said:

If the read failed, how do you expect the bit array to be correct ?
boolean array are initialized to false in Java so here you have your answer. You create it but never filled it as the read failed


The bit array should be correct because it is reading from the message.txt and converting the amount of characters in the txt file to a binary value. There are 71 values in the txt file, therefore my output should be 0000 0000 0100 0111.
Was This Post Helpful? 0
  • +
  • -

#8 macosxnerd101  Icon User is offline

  • Self-Trained Economist
  • member icon




Reputation: 10596
  • View blog
  • Posts: 39,259
  • Joined: 27-December 08

Re: Need help with Steganography

Posted 15 November 2012 - 12:55 PM

Duplicate threads merged. Please avoid duplicate posting.
Was This Post Helpful? 0
  • +
  • -

#9 Sai077  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 5
  • Joined: 15-November 12

Re: Need help with Steganography

Posted 15 November 2012 - 02:28 PM

View Postmacosxnerd101, on 15 November 2012 - 12:55 PM, said:

Duplicate threads merged. Please avoid duplicate posting.


Apologies. :\ In the meantime, I have gotten my bits array working correctly (for the length of the message). However Im having trouble reading through the array letter by letter now and converting the value to ASCII. My read code is:

 		m1 = message.length();
		for (int j = 0; j < m1; j++) {
			String c = allWords[j];
			System.out.println(c);
}



Okay, before posting this I did a little investigating. right now my Scanner reads allWords in word by word. For this loop to execute correctly, I need to analyze each character in the message. How can I grab individual characters out?
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1