At first glance, there's nothing special on below image..
..but in fact, on this picture is hidden another one:
It was done, by using steganography, the second image was stored on two lowest bits of the pixels. On two bits we may save values from 0 to 7, pixel in the image may have values from 0 to 255, so such small change is not visible to the human eye.
I used this python script:
#!/usr/bin/env python import sys import Image, ImageOps def extract_image(from_image, s=4): data = Image.open(from_image) for x in range(data.size[0]): for y in range(data.size[1]): p = data.getpixel((x, y)) red = (p[0] % s) * 255 / s green = (p[1] % s) * 255 / s blue = (p[2] % s) * 255 / s data.putpixel((x, y), (red, green, blue)) return data def hide_image(public_img, secret_img, s=4): data = Image.open(public_img) key = ImageOps.autocontrast(Image.open(secret_img)) for x in range(data.size[0]): for y in range(data.size[1]): p = data.getpixel((x, y)) q = key.getpixel((x, y)) red = p[0] - (p[0] % s) + (s * q[0] / 255) green = p[1] - (p[1] % s) + (s * q[1] / 255) blue = p[2] - (p[2] % s) + (s * q[2] / 255) data.putpixel((x, y), (red, green, blue)) return data def show_help(): print "wrong usage, try:" print "%s show from.jpg" % sys.argv[0] print "%s hide public.jpg secret.jpg" % sys.argv[0] if __name__=="__main__": if len(sys.argv) != 3 and len(sys.argv) != 4: show_help() elif sys.argv[1] == "show": print "image will be saved as extracted.png" extract_image(sys.argv[2]).save("extracted.png"); elif sys.argv[1] == "hide": hide_image(sys.argv[2], sys.argv[3]).save("hidden.png") else: show_help()
Below is example of usage, first line shows how to hide image, second shows how to extract image.
bash-3.2$ ./hider.py hide kosciol_Marii_Magdaleny.jpg GOR-Rabka.JPG bash-3.2$ ./hider.py show hidden.png
The script collapses if images have different sizes.
ReplyDeleteHi,
Deleteyou're right, but IMHO it would fix would overcomplicate the script, image can be adjusted in Gimp or similar program.
If a simple resize is ok for you, then you can probably replace this line:
key = ImageOps.autocontrast(Image.open(secret_img))
by this one:
key = ImageOps.autocontrast(Image.open(secret_img).resize(data.size))
Robert
would be great to have a browser plugin that would check those bits in each image and analyze if there is a hidden image in them. it's so simple algorithm that i'm sure it's used somewhere on the internet
ReplyDeletehey,
ReplyDeletehow do you get the modules you import at the top of your program?
Hi Jacob,
Deletewhat operating system are you using?
The script was written for Python 2.x versions, not the current one, so you need to have installed some version of the Python 2.x.
The only modules you need to have installed by yourself are Image, ImageOps, they came from the PIL (python image library). Note: PIL library is an abandoned project.
Sorry for late replay, if you have any questions, please tell me.
Have fun with this script :-)
-Bob
Cool post!
ReplyDeleteAs it turns out, I have created an iPhone/iPad app that performs a similar operation (was just approved). This app also allows you to hide one photo within another. It's free so please try it out: https://itunes.apple.com/us/app/veil-hide-and-reveal-photos/id1171571496
Cool, I would try it but I don't have iphone :)
DeleteThat's a great code and idea!
ReplyDeleteHow about using a password to hide image and then ask the password to show? would it be possible?
thanks!!!
It keeps saying that it doesn't support the image mode of the images, even though they're both rbg mode pngs
ReplyDeleteThe error is coming from ImageOps, line 59. Here's the traceback.
DeleteTraceback (most recent call last):
File "C:\Users\alexa\Pictures\0\imageHider.py", line 44, in
hide_image(sys.argv[2], sys.argv[3]).save("hidden.png")
File "C:\Users\alexa\Pictures\0\imageHider.py", line 18, in hide_image
key = ImageOps.autocontrast(Image.open(secret_img))
File "C:\Python27\lib\site-packages\PIL\ImageOps.py", line 138, in autocontrast
return _lut(image, lut)
File "C:\Python27\lib\site-packages\PIL\ImageOps.py", line 59, in _lut
raise IOError, "not supported for this image mode"
IOError: not supported for this image mode
I'm not sure what I could be doing wrong. (although I am new to python)
Do you know how to do this in Java?
ReplyDeletewhere can i see the output??
ReplyDeleteIn the first image.
Delete