Click here to Skip to main content
15,891,136 members
Articles / Programming Languages / C#
Tip/Trick

Hiding Data in an Image File

Rate me:
Please Sign up or sign in to vote.
4.77/5 (10 votes)
6 Nov 2014CPOL2 min read 25.7K   10   8
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:

C#
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:

C#
//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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Spain Spain
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Questionthere is an error occured when I opened the normal images by Open Button Pin
silas_yao7-Nov-14 2:40
silas_yao7-Nov-14 2:40 
AnswerRe: there is an error occured when I opened the normal images by Open Button Pin
Pikoh10-Nov-14 3:58
Pikoh10-Nov-14 3:58 
QuestionMy vote of #5 Pin
BillWoodruff6-Nov-14 8:47
professionalBillWoodruff6-Nov-14 8:47 
AnswerRe: My vote of #5 Pin
Pikoh6-Nov-14 21:15
Pikoh6-Nov-14 21:15 
SuggestionFor info - Steganography Pin
DaveAuld6-Nov-14 8:07
professionalDaveAuld6-Nov-14 8:07 
GeneralRe: For info - Steganography Pin
Pikoh6-Nov-14 21:12
Pikoh6-Nov-14 21:12 
GeneralRe: For info - Steganography Pin
DaveAuld6-Nov-14 22:04
professionalDaveAuld6-Nov-14 22:04 
GeneralRe: For info - Steganography Pin
Pikoh6-Nov-14 22:33
Pikoh6-Nov-14 22:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.