Click here to Skip to main content
15,886,258 members
Articles / Programming Languages / C#

Steganography IX - The Cross-Format Solution

Rate me:
Please Sign up or sign in to vote.
4.36/5 (15 votes)
29 Nov 2004CPOL5 min read 72K   1.7K   28  
Merging the pieces into one application.
/* This class has been written by
 * Corinna John (Hannover, Germany)
 * picturekey@binary-universe.net
 * 
 * You can use the code in any context you like,
 * as long as you do not delete this comment.
 * 
 * Please send me a little feedback about what you're
 * using this code for and what changes you'd like to
 * see in later versions. (And please excuse my bad english)
 * 
 * WARNING: This is experimental code.
 * Some bugs and flaws have been left in there,
 * to keep the code readable to people who want
 * to understand the algorithm.
 * Please do not expect "Release Quality".
 * */

using System;
using System.IO;
using System.Drawing;
using System.Windows.Forms;

namespace SteganoDemo
{
	/// <summary>
	/// Zusammendfassende Beschreibung f�r AviUtility.
	/// </summary>
	public class AviUtility : FileUtility
	{
		private const String TempSourceFileName = "steganodemo_temp1.bmp";
		private const String TempDestinationFileName = "steganodemo_temp2.bmp";

		public override void Hide(Stream messageStream, Stream keyStream){
			AviWriter aviWriter = new AviWriter();
			AviReader aviReader = new AviReader();
			ImageUtility utility = new ImageUtility();

			aviReader.Open(carrierFile.SourceFileName);
			aviWriter.Open(carrierFile.DestinationFileName, aviReader.FrameRate);
			
			String fileName = Application.ExecutablePath;
			int index = fileName.LastIndexOf("\\")+1;
			CarrierFile frameCarrierFile = new CarrierFile(
				fileName.Substring(0, index) + TempSourceFileName,
				fileName.Substring(0, index) + TempDestinationFileName,
				0,
				carrierFile.CountBitsToHidePerCarrierUnit,
				carrierFile.NoisePercent );
			
			//ignore length of entire message
			byte[] buffer = new Byte[messageStream.Length - 4];
			messageStream.Seek(4, SeekOrigin.Begin);
			messageStream.Read(buffer, 0, buffer.Length);
			messageStream.SetLength(buffer.Length);
			messageStream.Seek(0, SeekOrigin.Begin);
			messageStream.Write(buffer, 0, buffer.Length);
			messageStream.Seek(0, SeekOrigin.Begin);
			
			Bitmap bmp;
			Stream messageWithCount = null;
			for(int frameIndex=0; frameIndex<aviReader.CountFrames; frameIndex++){
				//export a frame
                aviReader.ExportBitmap(frameIndex, frameCarrierFile.SourceFileName);

                //pass the frame to ImageUtility
				utility.Initialize(frameCarrierFile);
				frameCarrierFile.CountUseableCarrierUnits = utility.CountUseableUnits(keyStream);
				frameCarrierFile.CountBytesToHide = (Int32)Math.Ceiling( (float)carrierFile.CountBytesToHide * ((float)frameCarrierFile.CountUseableCarrierUnits / carrierFile.CountCarrierUnits) );
				
				messageWithCount = FileUtility.GetMessagePart(messageStream, frameCarrierFile.CountBytesToHide);
				utility.Hide(messageWithCount, keyStream);
			
				//add the new frame
				bmp = (Bitmap)Image.FromFile(frameCarrierFile.DestinationFileName);
				aviWriter.AddFrame(bmp);
				bmp.Dispose();
			}
			messageWithCount.Close();
			
			//delete temporary files
			if(File.Exists(frameCarrierFile.SourceFileName)){ File.Delete(frameCarrierFile.SourceFileName); }
			if(File.Exists(frameCarrierFile.DestinationFileName)){ File.Delete(frameCarrierFile.DestinationFileName); }

			aviReader.Close();
			aviWriter.Close();
		}

		public override void Extract(Stream messageStream, Stream keyStream){
			AviReader aviReader = new AviReader();
			ImageUtility utility = new ImageUtility();

			aviReader.Open(carrierFile.SourceFileName);
			
			String fileName = Application.ExecutablePath;
			int index = fileName.LastIndexOf("\\")+1;
			CarrierFile frameCarrierFile = new CarrierFile(
				fileName.Substring(0, index) + TempSourceFileName,
				fileName.Substring(0, index) + TempDestinationFileName,
				0,
				carrierFile.CountBitsToHidePerCarrierUnit,
				carrierFile.NoisePercent );
			
			Stream messagePart = new MemoryStream();
			byte[] buffer;
			for(int frameIndex=0; frameIndex<aviReader.CountFrames; frameIndex++){
				//export a frame
				aviReader.ExportBitmap(frameIndex, frameCarrierFile.SourceFileName);
				
				//pass the frame to ImageUtility
				frameCarrierFile.CountBytesToHide = 0;
				utility.Initialize(frameCarrierFile);
				/*if(carrierFile.CountBytesToHide > 0){
					frameCarrierFile.CountUseableCarrierUnits = utility.CountUseableUnits(keyStream);
					frameCarrierFile.CountBytesToHide = (Int32)Math.Ceiling( (float)carrierFile.CountBytesToHide * ((float)frameCarrierFile.CountUseableCarrierUnits / carrierFile.CountCarrierUnits) );
				}*/

				messagePart.SetLength(0);
				utility.Extract(messagePart, keyStream);
				
				//copy extracted stream into message
				buffer = new byte[messagePart.Length];
				messagePart.Seek(0, SeekOrigin.Begin);
				messagePart.Read(buffer, 0, buffer.Length);
				messageStream.Write(buffer, 0, buffer.Length);
			}

			//delete temporary files
			if(File.Exists(frameCarrierFile.SourceFileName)){ File.Delete(frameCarrierFile.SourceFileName); }
			
			aviReader.Close();
		}

		public override long CountUnits(){
			AviReader ar = new AviReader();
			ar.Open(carrierFile.SourceFileName);
			Size size = ar.BitmapSize;
			long countPixels = size.Width * size.Height * ar.CountFrames;
			ar.Close();
			return countPixels;
		}
		
		public override FileType GetFileType(){
			return new VideoFileType();
		}


	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Germany Germany
Corinna lives in Hanover/Germany and works as a C# developer.

Comments and Discussions