3

Hide a photo inside another photo

 2 years ago
source link: https://www.avestura.dev/blog/hide-a-photo-inside-another-photo
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Have you ever thought of hiding a photo inside another photo? So when you share the photo, it looks like a single ordinary photo, but it's actually two photos. One of them is hidden inside of the other, and it can only be revealed using an external tool.

Mark sends photo to Julia

Photos as matrices

To be able to manipulate photos and embedding things inside them, we first need to know how they are represented and stored. One way to look at the photos is to see them as a mathematical matrix, where every cell of the matrix represents a pixel, and the value of it is the color of that pixel/cell.

Pm,n=(a1,1a1,2⋯a1,na2,1a2,2⋯a2,n⋮⋮⋱⋮am,1am,2⋯am,n)\begin{equation*} P_{m,n} = \begin{pmatrix} a_{1,1} & a_{1,2} & \cdots & a_{1,n} \\ a_{2,1} & a_{2,2} & \cdots & a_{2,n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m,1} & a_{m,2} & \cdots & a_{m,n} \end{pmatrix} \end{equation*}Pm,n​=⎝⎛​a1,1​a2,1​⋮am,1​​a1,2​a2,2​⋮am,2​​⋯⋯⋱⋯​a1,n​a2,n​⋮am,n​​⎠⎞​​

For example for a matrix like this:

P3,3=(1344702552550193470)\begin{equation*} P_{3,3} = \begin{pmatrix} 134 & 47 & 0 \\ 255 & 255 & 0 \\ 193 & 47 & 0 \end{pmatrix} \end{equation*}P3,3​=⎝⎛​134255193​4725547​000​⎠⎞​​

We'll get a photo like this:

Mark sends photo to Julia

As you can see in the matrix and the photo, the closer the value is to 255 the whiter the pixel becomes. 0 means black, and anything between 0 and 255 describes a shade of gray.

Photos as matrices of bits

We've already presented our photos as a bunch of matrices. Lets push our nerdiness a little bit further and represent value of each cell using binaries, instead of decimals (I swear it will come in handy later). The same photo we've seen before will be represented using this matrix:

P3,3=(100001100010111100000000111111111111111100000000110000010010111100000000)\begin{equation*} P_{3,3} = \begin{pmatrix} 10000110 & 00101111 & 00000000 \\ 11111111 & 11111111 & 00000000 \\ 11000001 & 00101111 & 00000000 \end{pmatrix} \end{equation*}P3,3​=⎝⎛​100001101111111111000001​001011111111111100101111​000000000000000000000000​⎠⎞​​

Now let's find out what happens to the photo if we change the least significant bit (LSB, aka the rightmost bit). So I'm gonna swap all of the LSBs and see how the new matrix and the photo will look like:

P3,3=(100001110010111000000001111111101111111000000001110000000010111000000001)\begin{equation*} P_{3,3} = \begin{pmatrix} 10000111 & 00101110 & 00000001 \\ 11111110 & 11111110 & 00000001 \\ 11000000 & 00101110 & 00000001 \end{pmatrix} \end{equation*}P3,3​=⎝⎛​100001111111111011000000​001011101111111000101110​000000010000000100000001​⎠⎞​​
Mark sends photo to Julia

Can your eyes detect any changes in the result photo? I assume no, it surely looks like the previous photo (unless you've got supernatural eyes), because we've only changed a single bit with the least significance. With this basic trick we can embed a photo inside another photo without anyone noticing that something is a little bit off (pun intended).

Emdeb the other photo

For embedding the other photo, we need to replace every LSB of the main photo with every single bit of the hidden photo, which means the hidden photo has to be smaller than the main photo in size.

Mark sends photo to Julia

But how much smaller shall the hidden photo be? For a visible photo of size n∗mn * mn∗m there are nm8\frac{nm}{8}8nm​ LSBs, which means we can have a hidden photo of the size nm8∗nm8\sqrt{\frac{nm}{8}} * \sqrt{\frac{nm}{8}}8nm​​∗8nm​​ inside the visible photo. As an example, for a visible photo of the size 1000∗10001000 * 10001000∗1000 we have:

1000∗10008=10000008=125000=353.553...\sqrt{\frac{1000 * 1000}{8}} = \sqrt{\frac{1000000}{8}} = \sqrt{125000} = 353.553...81000∗1000​​=81000000​​=125000​=353.553...

That means we can hide a photo with the size of 353∗353353 * 353353∗353 inside of a host photo with size of 1000∗10001000 * 10001000∗1000.

RGB Photos

In colorful photos, every pixel of the photo is represented by three matrices. Red matrix, Green matrix, and the Blue matrix. Instead of 3 different matrices, you might also think of it as a single matrix with a tuple of 3 values, all ranging from 0 to 255.

P3,3=((12,20,133)(15,47,255)(255,255,0)(210,20,230)(21,14,133)(255,255,255)(80,50,90)(96,68,160)(140,0,130))\begin{equation*} P_{3,3} = \begin{pmatrix} (12, 20, 133) & (15, 47, 255) & (255, 255, 0) \\ (210, 20, 230) & (21, 14, 133) & (255, 255, 255) \\ (80, 50, 90) & (96, 68, 160) & (140, 0, 130) \end{pmatrix} \end{equation*}P3,3​=⎝⎛​(12,20,133)(210,20,230)(80,50,90)​(15,47,255)(21,14,133)(96,68,160)​(255,255,0)(255,255,255)(140,0,130)​⎠⎞​​

Our approach to hide the photo still works in this case. You just need to replace all the LSBs for every matrix of every cell.

PNG, JPEG, and compressions

As you might already know, some photo formats (like JPEG) heavily compress the source image using different mathematical approaches (e.g. Haar wavelet). So you might ask what happens to the hidden photo in that case? Well, the hidden photo will most likely be destroyed and you'll see a bunch of noises after trying to reveal your secret. But there are other formats like PNG that preserve your photo as is, and you can try this trick using those formats.

Implementation

I've implemented this method long ago back when I was a bachelor student. You might want to check it out at github.com/avestura/PhotoFiremark. It's a desktop application, and uses Emgu CV to play with photo bits.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK