mirror of
https://github.com/cedricbonhomme/Stegano.git
synced 2025-05-12 17:18:30 +02:00
Porting code with 2to3 with some manual changes. The pillow modules is now required https://github.com/python-imaging/Pillow/
This commit is contained in:
parent
f629773772
commit
b3a4bdaf4b
10 changed files with 54 additions and 53 deletions
2
setup.py
2
setup.py
|
@ -34,7 +34,7 @@ setup(
|
||||||
**kw
|
**kw
|
||||||
)
|
)
|
||||||
|
|
||||||
print "Installing binaries"
|
print("Installing binaries")
|
||||||
shutil.copy2("./bin/slsb-set", "/bin/slsb-set")
|
shutil.copy2("./bin/slsb-set", "/bin/slsb-set")
|
||||||
shutil.copymode("./bin/slsb-set", "/bin/slsb-set")
|
shutil.copymode("./bin/slsb-set", "/bin/slsb-set")
|
||||||
|
|
||||||
|
|
|
@ -105,4 +105,4 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
elif sys.argv[1] == "reveal":
|
elif sys.argv[1] == "reveal":
|
||||||
img = Image.open(options.input_image_file)
|
img = Image.open(options.input_image_file)
|
||||||
print reveal(img)
|
print(reveal(img))
|
||||||
|
|
|
@ -177,20 +177,20 @@ class MinimalExifReader:
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import sys
|
import sys
|
||||||
if len(sys.argv) == 1:
|
if len(sys.argv) == 1:
|
||||||
print "Pass jpgs to process."
|
print("Pass jpgs to process.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
for filename in sys.argv[1:]:
|
for filename in sys.argv[1:]:
|
||||||
try:
|
try:
|
||||||
f = MinimalExifReader(filename)
|
f = MinimalExifReader(filename)
|
||||||
print filename
|
print(filename)
|
||||||
print "description: '%s'" % f.imageDescription()
|
print("description: '%s'" % f.imageDescription())
|
||||||
print "copyright: '%s'" % f.copyright()
|
print("copyright: '%s'" % f.copyright())
|
||||||
print "dateTimeOriginal: '%s'" % f.dateTimeOriginal()
|
print("dateTimeOriginal: '%s'" % f.dateTimeOriginal())
|
||||||
print "dateTimeOriginal: '%s'" % f.dateTimeOriginal('%B %d, %Y %I:%M:%S %p')
|
print("dateTimeOriginal: '%s'" % f.dateTimeOriginal('%B %d, %Y %I:%M:%S %p'))
|
||||||
print
|
print()
|
||||||
except ExifFormatException, ex:
|
except ExifFormatException as ex:
|
||||||
sys.stderr.write("Exif format error: %s\n" % ex)
|
sys.stderr.write("Exif format error: %s\n" % ex)
|
||||||
except:
|
except:
|
||||||
sys.stderr.write("Unable to process %s\n" % filename)
|
sys.stderr.write("Unable to process %s\n" % filename)
|
||||||
|
|
|
@ -43,7 +43,7 @@ if VERBOSE:
|
||||||
|
|
||||||
import mmap
|
import mmap
|
||||||
import sys
|
import sys
|
||||||
import minimal_exif_reader
|
from . import minimal_exif_reader
|
||||||
|
|
||||||
#---------------------------------------------------------------------
|
#---------------------------------------------------------------------
|
||||||
class ExifFormatException(Exception):
|
class ExifFormatException(Exception):
|
||||||
|
@ -91,7 +91,7 @@ class MinimalExifWriter:
|
||||||
self.getExistingExifInfo()
|
self.getExistingExifInfo()
|
||||||
|
|
||||||
if VERBOSE:
|
if VERBOSE:
|
||||||
print self
|
print(self)
|
||||||
|
|
||||||
import os
|
import os
|
||||||
try:
|
try:
|
||||||
|
@ -105,7 +105,7 @@ class MinimalExifWriter:
|
||||||
|
|
||||||
# We only add app0 if all we're doing is removing the exif section.
|
# We only add app0 if all we're doing is removing the exif section.
|
||||||
justRemovingExif = self.description is None and self.copyright is None and self.removeExifSection
|
justRemovingExif = self.description is None and self.copyright is None and self.removeExifSection
|
||||||
if VERBOSE: print 'justRemovingExif=%s' % justRemovingExif
|
if VERBOSE: print('justRemovingExif=%s' % justRemovingExif)
|
||||||
self.removeExifInfo(addApp0 = justRemovingExif)
|
self.removeExifInfo(addApp0 = justRemovingExif)
|
||||||
if justRemovingExif:
|
if justRemovingExif:
|
||||||
self.m.close()
|
self.m.close()
|
||||||
|
@ -114,7 +114,7 @@ class MinimalExifWriter:
|
||||||
# Get here means we are adding new description and/or copyright.
|
# Get here means we are adding new description and/or copyright.
|
||||||
self.removeApp0()
|
self.removeApp0()
|
||||||
|
|
||||||
totalTagsToBeAdded = len(filter(None, (self.description, self.copyright, self.dateTimeOriginal)))
|
totalTagsToBeAdded = len([_f for _f in (self.description, self.copyright, self.dateTimeOriginal) if _f])
|
||||||
assert(totalTagsToBeAdded > 0)
|
assert(totalTagsToBeAdded > 0)
|
||||||
|
|
||||||
# Layout will be: firstifd|description|copyright|exififd|datetime.
|
# Layout will be: firstifd|description|copyright|exififd|datetime.
|
||||||
|
@ -199,9 +199,9 @@ class MinimalExifWriter:
|
||||||
appMarker = self.m.read(2)
|
appMarker = self.m.read(2)
|
||||||
# See if there's an APP0 section, which sometimes appears.
|
# See if there's an APP0 section, which sometimes appears.
|
||||||
if appMarker == self.APP0_MARKER:
|
if appMarker == self.APP0_MARKER:
|
||||||
if VERBOSE: print 'app0 found'
|
if VERBOSE: print('app0 found')
|
||||||
app0DataLength = ord(self.m.read(1)) * 256 + ord(self.m.read(1))
|
app0DataLength = ord(self.m.read(1)) * 256 + ord(self.m.read(1))
|
||||||
if VERBOSE: print 'app0DataLength: %s' % app0DataLength
|
if VERBOSE: print('app0DataLength: %s' % app0DataLength)
|
||||||
# Back up 2 bytes to get the length bytes.
|
# Back up 2 bytes to get the length bytes.
|
||||||
self.m.seek(-2, 1)
|
self.m.seek(-2, 1)
|
||||||
existingApp0 = self.m.read(app0DataLength)
|
existingApp0 = self.m.read(app0DataLength)
|
||||||
|
@ -212,14 +212,14 @@ class MinimalExifWriter:
|
||||||
return
|
return
|
||||||
|
|
||||||
exifHeader = self.m.read(8)
|
exifHeader = self.m.read(8)
|
||||||
if VERBOSE: print 'exif header: %s' % binascii.hexlify(exifHeader)
|
if VERBOSE: print('exif header: %s' % binascii.hexlify(exifHeader))
|
||||||
if (exifHeader[2:6] != 'Exif' or
|
if (exifHeader[2:6] != 'Exif' or
|
||||||
exifHeader[6:8] != '\x00\x00'):
|
exifHeader[6:8] != '\x00\x00'):
|
||||||
self.m.close()
|
self.m.close()
|
||||||
raise ExifFormatException("Malformed APP1")
|
raise ExifFormatException("Malformed APP1")
|
||||||
|
|
||||||
app1Length = ord(exifHeader[0]) * 256 + ord(exifHeader[1])
|
app1Length = ord(exifHeader[0]) * 256 + ord(exifHeader[1])
|
||||||
if VERBOSE: print 'app1Length: %s' % app1Length
|
if VERBOSE: print('app1Length: %s' % app1Length)
|
||||||
|
|
||||||
originalFileSize = self.m.size()
|
originalFileSize = self.m.size()
|
||||||
|
|
||||||
|
@ -240,7 +240,7 @@ class MinimalExifWriter:
|
||||||
if app0DataLength:
|
if app0DataLength:
|
||||||
count -= app0DataLength + len(self.APP0_MARKER)
|
count -= app0DataLength + len(self.APP0_MARKER)
|
||||||
|
|
||||||
if VERBOSE: print 'self.m.move(%s, %s, %s)' % (dest, src, count)
|
if VERBOSE: print('self.m.move(%s, %s, %s)' % (dest, src, count))
|
||||||
self.m.move(dest, src, count)
|
self.m.move(dest, src, count)
|
||||||
|
|
||||||
if addApp0:
|
if addApp0:
|
||||||
|
@ -259,13 +259,13 @@ class MinimalExifWriter:
|
||||||
header = self.m.read(6)
|
header = self.m.read(6)
|
||||||
if (header[0:2] != self.SOI_MARKER or
|
if (header[0:2] != self.SOI_MARKER or
|
||||||
header[2:4] != self.APP0_MARKER):
|
header[2:4] != self.APP0_MARKER):
|
||||||
if VERBOSE: print 'no app0 found: %s' % binascii.hexlify(header)
|
if VERBOSE: print('no app0 found: %s' % binascii.hexlify(header))
|
||||||
return
|
return
|
||||||
|
|
||||||
originalFileSize = self.m.size()
|
originalFileSize = self.m.size()
|
||||||
|
|
||||||
app0Length = ord(header[4]) * 256 + ord(header[5])
|
app0Length = ord(header[4]) * 256 + ord(header[5])
|
||||||
if VERBOSE: print 'app0Length:', app0Length
|
if VERBOSE: print('app0Length:', app0Length)
|
||||||
|
|
||||||
# Shift stuff to overwrite app0.
|
# Shift stuff to overwrite app0.
|
||||||
# Start at app0 length bytes in + other bytes not incl in app0 length.
|
# Start at app0 length bytes in + other bytes not incl in app0 length.
|
||||||
|
@ -273,7 +273,7 @@ class MinimalExifWriter:
|
||||||
dest = len(self.SOI_MARKER)
|
dest = len(self.SOI_MARKER)
|
||||||
count = originalFileSize - app0Length - len(self.SOI_MARKER) - len(self.APP0_MARKER)
|
count = originalFileSize - app0Length - len(self.SOI_MARKER) - len(self.APP0_MARKER)
|
||||||
self.m.move(dest, src, count)
|
self.m.move(dest, src, count)
|
||||||
if VERBOSE: print 'm.move(%s, %s, %s)' % (dest, src, count)
|
if VERBOSE: print('m.move(%s, %s, %s)' % (dest, src, count))
|
||||||
self.m.resize(originalFileSize - app0Length - len(self.APP0_MARKER))
|
self.m.resize(originalFileSize - app0Length - len(self.APP0_MARKER))
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
@ -347,10 +347,10 @@ def usage(error = None):
|
||||||
"""Print command line usage and exit"""
|
"""Print command line usage and exit"""
|
||||||
|
|
||||||
if error:
|
if error:
|
||||||
print error
|
print(error)
|
||||||
print
|
print()
|
||||||
|
|
||||||
print """This program will remove exif info from an exif jpg, and can optionally
|
print("""This program will remove exif info from an exif jpg, and can optionally
|
||||||
add the ImageDescription exif tag and/or the Copyright tag. But it will always remove
|
add the ImageDescription exif tag and/or the Copyright tag. But it will always remove
|
||||||
some or all existing exif info (depending on options--see below)!
|
some or all existing exif info (depending on options--see below)!
|
||||||
So don't run this on your original images without a backup.
|
So don't run this on your original images without a backup.
|
||||||
|
@ -379,7 +379,7 @@ Options:
|
||||||
|
|
||||||
The image description and copyright must be > 4 characters long.
|
The image description and copyright must be > 4 characters long.
|
||||||
|
|
||||||
This software courtesy of Megabyte Rodeo Software."""
|
This software courtesy of Megabyte Rodeo Software.""")
|
||||||
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
@ -448,7 +448,7 @@ if __name__ == '__main__':
|
||||||
f.removeExif()
|
f.removeExif()
|
||||||
|
|
||||||
f.process()
|
f.process()
|
||||||
except ExifFormatException, ex:
|
except ExifFormatException as ex:
|
||||||
sys.stderr.write("Exif format error: %s\n" % ex)
|
sys.stderr.write("Exif format error: %s\n" % ex)
|
||||||
except SystemExit:
|
except SystemExit:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -35,7 +35,7 @@ def hide(img, img_enc, copyright="http://bitbucket.org/cedricbonhomme/stegano",
|
||||||
from zlib import compress
|
from zlib import compress
|
||||||
from zlib import decompress
|
from zlib import decompress
|
||||||
from base64 import b64encode
|
from base64 import b64encode
|
||||||
from exif.minimal_exif_writer import MinimalExifWriter
|
from .exif.minimal_exif_writer import MinimalExifWriter
|
||||||
|
|
||||||
if secret_file != None:
|
if secret_file != None:
|
||||||
with open(secret_file, "r") as f:
|
with open(secret_file, "r") as f:
|
||||||
|
@ -51,7 +51,7 @@ def hide(img, img_enc, copyright="http://bitbucket.org/cedricbonhomme/stegano",
|
||||||
try:
|
try:
|
||||||
shutil.copy(img, img_enc)
|
shutil.copy(img, img_enc)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("Impossible to copy image:", e)
|
print(("Impossible to copy image:", e))
|
||||||
return
|
return
|
||||||
|
|
||||||
f = MinimalExifWriter(img_enc)
|
f = MinimalExifWriter(img_enc)
|
||||||
|
@ -66,13 +66,13 @@ def reveal(img):
|
||||||
"""
|
"""
|
||||||
from base64 import b64decode
|
from base64 import b64decode
|
||||||
from zlib import decompress
|
from zlib import decompress
|
||||||
from exif.minimal_exif_reader import MinimalExifReader
|
from .exif.minimal_exif_reader import MinimalExifReader
|
||||||
try:
|
try:
|
||||||
g = MinimalExifReader(img)
|
g = MinimalExifReader(img)
|
||||||
except:
|
except:
|
||||||
print("Impossible to read description.")
|
print("Impossible to read description.")
|
||||||
return
|
return
|
||||||
print(b64decode(decompress(g.imageDescription())))
|
print((b64decode(decompress(g.imageDescription()))))
|
||||||
print(("\nCopyright " + g.copyright()))
|
print(("\nCopyright " + g.copyright()))
|
||||||
#print g.dateTimeOriginal()s
|
#print g.dateTimeOriginal()s
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ def OEIS_A000217():
|
||||||
"""
|
"""
|
||||||
n = 0
|
n = 0
|
||||||
while True:
|
while True:
|
||||||
yield (n*(n+1))/2
|
yield (n*(n+1))//2
|
||||||
n += 1
|
n += 1
|
||||||
|
|
||||||
def fermat():
|
def fermat():
|
||||||
|
@ -152,4 +152,4 @@ if __name__ == "__main__":
|
||||||
# Point of entry in execution mode.
|
# Point of entry in execution mode.
|
||||||
f = fibonacci()
|
f = fibonacci()
|
||||||
for x in range(13):
|
for x in range(13):
|
||||||
print f.next(), # 0 1 1 2 3 5 8 13 21 34 55 89 144
|
print(next(f), end=' ') # 0 1 1 2 3 5 8 13 21 34 55 89 144
|
||||||
|
|
|
@ -48,8 +48,8 @@ def hide(input_image_file, message):
|
||||||
if len(message_bits) > npixels * 3:
|
if len(message_bits) > npixels * 3:
|
||||||
raise Exception("""The message you want to hide is too long (%s > %s).""" % (len(message_bits), npixels * 3))
|
raise Exception("""The message you want to hide is too long (%s > %s).""" % (len(message_bits), npixels * 3))
|
||||||
|
|
||||||
for row in xrange(height):
|
for row in range(height):
|
||||||
for col in xrange(width):
|
for col in range(width):
|
||||||
|
|
||||||
if index + 3 <= len(message_bits) :
|
if index + 3 <= len(message_bits) :
|
||||||
|
|
||||||
|
@ -78,8 +78,8 @@ def reveal(input_image_file):
|
||||||
buff, count = 0, 0
|
buff, count = 0, 0
|
||||||
bitab = []
|
bitab = []
|
||||||
limit = None
|
limit = None
|
||||||
for row in xrange(height):
|
for row in range(height):
|
||||||
for col in xrange(width):
|
for col in range(width):
|
||||||
|
|
||||||
# color = [r, g, b]
|
# color = [r, g, b]
|
||||||
for color in img.getpixel((col, row)):
|
for color in img.getpixel((col, row)):
|
||||||
|
@ -103,9 +103,9 @@ def write(image, output_image_file):
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
image.save(output_image_file)
|
image.save(output_image_file)
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
# If hide() returns an error (Too long message).
|
# If hide() returns an error (Too long message).
|
||||||
print e
|
print(e)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# Point of entry in execution mode.
|
# Point of entry in execution mode.
|
||||||
|
@ -149,9 +149,9 @@ if __name__ == '__main__':
|
||||||
img_encoded = hide(options.input_image_file, secret)
|
img_encoded = hide(options.input_image_file, secret)
|
||||||
try:
|
try:
|
||||||
img_encoded.save(options.output_image_file)
|
img_encoded.save(options.output_image_file)
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
# If hide() returns an error (Too long message).
|
# If hide() returns an error (Too long message).
|
||||||
print e
|
print(e)
|
||||||
|
|
||||||
elif options.reveal:
|
elif options.reveal:
|
||||||
secret = reveal(options.input_image_file)
|
secret = reveal(options.input_image_file)
|
||||||
|
@ -160,4 +160,4 @@ if __name__ == '__main__':
|
||||||
with open(options.secret_binary, "w") as f:
|
with open(options.secret_binary, "w") as f:
|
||||||
f.write(data)
|
f.write(data)
|
||||||
else:
|
else:
|
||||||
print secret
|
print(secret)
|
||||||
|
|
|
@ -52,7 +52,7 @@ def hide(input_image_file, message, generator_function):
|
||||||
generator = getattr(generators, generator_function)()
|
generator = getattr(generators, generator_function)()
|
||||||
|
|
||||||
while index + 3 <= len(message_bits) :
|
while index + 3 <= len(message_bits) :
|
||||||
generated_number = generator.next()
|
generated_number = next(generator)
|
||||||
(r, g, b) = img_list[generated_number]
|
(r, g, b) = img_list[generated_number]
|
||||||
|
|
||||||
# Change the Least Significant Bit of each colour component.
|
# Change the Least Significant Bit of each colour component.
|
||||||
|
@ -90,7 +90,7 @@ def reveal(input_image_file, generator_function):
|
||||||
generator = getattr(generators, generator_function)()
|
generator = getattr(generators, generator_function)()
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
generated_number = generator.next()
|
generated_number = next(generator)
|
||||||
# color = [r, g, b]
|
# color = [r, g, b]
|
||||||
for color in img_list[generated_number]:
|
for color in img_list[generated_number]:
|
||||||
buff += (color&1)<<(7-count)
|
buff += (color&1)<<(7-count)
|
||||||
|
@ -113,9 +113,9 @@ def write(image, output_image_file):
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
image.save(output_image_file)
|
image.save(output_image_file)
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
# If hide() returns an error (Too long message).
|
# If hide() returns an error (Too long message).
|
||||||
print e
|
print(e)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# Point of entry in execution mode.
|
# Point of entry in execution mode.
|
||||||
|
@ -165,19 +165,19 @@ if __name__ == '__main__':
|
||||||
img_encoded = hide(options.input_image_file, secret, options.generator_function)
|
img_encoded = hide(options.input_image_file, secret, options.generator_function)
|
||||||
try:
|
try:
|
||||||
img_encoded.save(options.output_image_file)
|
img_encoded.save(options.output_image_file)
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
# If hide() returns an error (Too long message).
|
# If hide() returns an error (Too long message).
|
||||||
print e
|
print(e)
|
||||||
|
|
||||||
elif options.reveal:
|
elif options.reveal:
|
||||||
try:
|
try:
|
||||||
secret = reveal(options.input_image_file, options.generator_function)
|
secret = reveal(options.input_image_file, options.generator_function)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
print "Impossible to detect message."
|
print("Impossible to detect message.")
|
||||||
exit(0)
|
exit(0)
|
||||||
if options.secret_binary != "":
|
if options.secret_binary != "":
|
||||||
data = tools.base642binary(secret)
|
data = tools.base642binary(secret)
|
||||||
with open(options.secret_binary, "w") as f:
|
with open(options.secret_binary, "w") as f:
|
||||||
f.write(data)
|
f.write(data)
|
||||||
else:
|
else:
|
||||||
print secret
|
print(secret)
|
||||||
|
|
|
@ -43,15 +43,15 @@ def steganalyse(img):
|
||||||
colours[r] += 1
|
colours[r] += 1
|
||||||
|
|
||||||
most_common = colours.most_common(10)
|
most_common = colours.most_common(10)
|
||||||
dict_colours = OrderedDict(sorted(colours.items(), key=lambda t: t[1]))
|
dict_colours = OrderedDict(sorted(list(colours.items()), key=lambda t: t[1]))
|
||||||
|
|
||||||
colours = 0
|
colours = 0
|
||||||
for colour in dict_colours.keys():
|
for colour in list(dict_colours.keys()):
|
||||||
colours += colour
|
colours += colour
|
||||||
colours = colours / len(dict_colours)
|
colours = colours / len(dict_colours)
|
||||||
|
|
||||||
#return colours.most_common(10)
|
#return colours.most_common(10)
|
||||||
return dict_colours.keys()[:30], most_common
|
return list(dict_colours.keys())[:30], most_common
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# Point of entry in execution mode.
|
# Point of entry in execution mode.
|
||||||
|
|
|
@ -25,6 +25,7 @@ __date__ = "$Date: 2010/10/01 $"
|
||||||
__license__ = "GPLv3"
|
__license__ = "GPLv3"
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
def a2bits(chars):
|
def a2bits(chars):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Add table
Reference in a new issue