Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Hiding Data in an Image File

0.00/5 (No votes)
6 Nov 2014 1  
A simple method to join several images in a single file and recover them afterwards

Introduction

In this tip/trick, I'll try to explain an easy method to hide data (images in this case) in an image file. This file may be opened with any image viewer, and all you'll see is the image that covers the hidden data. Later, you may recover the hidden data using this method.

Motivation

Well, this tip is in fact an answer to a quick answers section question. But I thought this could be of any help to anyone else. :)

Hiding the Images

This process is very simple. What we are going to do is create a byte array and read all the images in it. But we must also store the number of images we are joining and the size of each image so we will be able to recover the information later:

foreach (string path in paths)
{
    byte[] b = File.ReadAllBytes(path);
    imageList.Add(b);
    byte[] imgsize = BitConverter.GetBytes(b.Length);
    byteArraySize += imgsize.Length;
    byteArraySize += b.Length;
}

byteArraySize++; //one extra byte to store the number of images

byte[] concatenatedImage = new byte[byteArraySize]; //the array where we will store all images and sizes

int pos = 0;


//Now we store all the images in the output array

foreach (byte[] b in imageList)
{
    foreach (byte bi in b)
    {
        concatenatedImage[pos] = bi;
        pos++;
    }
}

//After all the images, let's store their sizes (4 bytes each)
foreach (byte[] b in imageList)
{
    byte[] imgsize = BitConverter.GetBytes(b.Length);
    foreach (byte bi in imgsize)
    {
        concatenatedImage[pos] = bi;
        pos++;
    }
}

//Finally, the last byte indicates the number of images stored
concatenatedImage[pos] = Convert.ToByte(paths.Length);

So the output file will have:

  1. All the images, one after the other
  2. 4 bytes for each image, with the size of the file
  3. 1 byte with the number of images

When we open this output file with an image viewer, it will show us the first image we stored, leaving the others hidden.

Recovering the Hidden Data

This is very simple as well. We must read the previously created image and cut it into as many images as the last byte tells us, having each "piece" the size we also stored at the end of our file:

//First we read the composed image file
            byte[] images = File.ReadAllBytes(path);
            
            //We get the number of images 
            int numberOfImages = Convert.ToInt32(images[images.Length-1]);

            Image[] decodedImages = new Image[numberOfImages];

            //this array will store each image size (4 bytes each)
            int[] sizes = new int[numberOfImages];
            int pos=images.Length-1;
            pos = pos - (numberOfImages * 4);

            //We now store the sizes of each image to correctly split them
            for (int i = 0; i < numberOfImages; i++)
            {
                byte[] imgsize = new byte[4];
                Array.Copy(images,pos,imgsize,0,4);
                sizes[i] = BitConverter.ToInt32(imgsize, 0);
                pos += 4;
            }

            //Finally, we start splitting the images "cutting" 
            //the array in pieces of the size we previously read
            pos = 0;
            for (int i = 0; i < numberOfImages; i++)
            {
                byte[] image = new byte[sizes[i]];
                Array.Copy(images, pos, image, 0, sizes[i]);
                Image img;
                using (var ms = new MemoryStream(image))
                {
                    img = Image.FromStream(ms);
                }
                decodedImages[i] = img;
                pos += sizes[i];
            }

Points of Interest

When I first read the question, I thought of stenography, but this technique did not exactly meet the requirements. I really thought that creating a file with data attached which could be opened with a regular viewer was not possible, but lastly the thing was easier than expected.

Attached there is a sample project. If you have any suggestions, please comment.

BTW, this is my first submission, so please be kind :)

History

  • 11/06/2014: First submission

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here