black + remove unused imports

This commit is contained in:
Peter Justin 2019-04-08 10:03:24 +02:00
parent 93de151025
commit d8fe34e5bc
6 changed files with 179 additions and 117 deletions

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
#-*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Stéganô - Stéganô is a basic Python Steganography module. # Stéganô - Stéganô is a basic Python Steganography module.
# Copyright (C) 2010-2019 Cédric Bonhomme - https://www.cedricbonhomme.org # Copyright (C) 2010-2019 Cédric Bonhomme - https://www.cedricbonhomme.org
@ -25,13 +25,17 @@ __date__ = "$Date: 2016/05/26 $"
__revision__ = "$Date: 2017/01/18 $" __revision__ = "$Date: 2017/01/18 $"
__license__ = "GPLv3" __license__ = "GPLv3"
from PIL import Image
import piexif import piexif
from stegano import tools from stegano import tools
def hide(input_image_file, img_enc, secret_message = None, secret_file = None, img_format = None): def hide(
input_image_file,
img_enc,
secret_message=None,
secret_file=None,
img_format=None,
):
"""Hide a message (string) in an image. """Hide a message (string) in an image.
""" """
from zlib import compress from zlib import compress
@ -72,13 +76,13 @@ def reveal(input_image_file):
img = tools.open_image(input_image_file) img = tools.open_image(input_image_file)
try: try:
if img.format in ['JPEG', 'TIFF']: if img.format in ["JPEG", "TIFF"]:
if 'exif' in img.info: if "exif" in img.info:
exif_dict = piexif.load(img.info.get("exif", b'')) exif_dict = piexif.load(img.info.get("exif", b""))
description_key = piexif.ImageIFD.ImageDescription description_key = piexif.ImageIFD.ImageDescription
encoded_message = exif_dict["0th"][description_key] encoded_message = exif_dict["0th"][description_key]
else: else:
encoded_message = b'' encoded_message = b""
else: else:
raise ValueError("Given file is neither JPEG nor TIFF.") raise ValueError("Given file is neither JPEG nor TIFF.")
finally: finally:
@ -91,41 +95,70 @@ if __name__ == "__main__":
# Point of entry in execution mode. # Point of entry in execution mode.
# TODO: improve the management of arguments # TODO: improve the management of arguments
from optparse import OptionParser from optparse import OptionParser
parser = OptionParser(version=__version__) parser = OptionParser(version=__version__)
parser.add_option('--hide', action='store_true', default=False, parser.add_option(
help="Hides a message in an image.") "--hide",
parser.add_option('--reveal', action='store_true', default=False, action="store_true",
help="Reveals the message hided in an image.") default=False,
help="Hides a message in an image.",
)
parser.add_option(
"--reveal",
action="store_true",
default=False,
help="Reveals the message hided in an image.",
)
# Original image # Original image
parser.add_option("-i", "--input", dest="input_image_file", parser.add_option(
help="Input image file.") "-i", "--input", dest="input_image_file", help="Input image file."
)
# Image containing the secret # Image containing the secret
parser.add_option("-o", "--output", dest="output_image_file", parser.add_option(
help="Output image containing the secret.") "-o",
"--output",
dest="output_image_file",
help="Output image containing the secret.",
)
# Secret raw message to hide # Secret raw message to hide
parser.add_option("-m", "--secret-message", dest="secret_message", parser.add_option(
help="Your raw secret message to hide.") "-m",
"--secret-message",
dest="secret_message",
help="Your raw secret message to hide.",
)
# Secret text file to hide. # Secret text file to hide.
parser.add_option("-f", "--secret-file", dest="secret_file", parser.add_option(
help="Your secret text file to hide.") "-f",
"--secret-file",
dest="secret_file",
help="Your secret text file to hide.",
)
parser.set_defaults(input_image_file = './pictures/Elisha-Cuthbert.jpg', parser.set_defaults(
output_image_file = './pictures/Elisha-Cuthbert_enc.jpg', input_image_file="./pictures/Elisha-Cuthbert.jpg",
secret_message = '', secret_file = '') output_image_file="./pictures/Elisha-Cuthbert_enc.jpg",
secret_message="",
secret_file="",
)
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
if options.hide: if options.hide:
if options.secret_message != "" and options.secret_file == "": if options.secret_message != "" and options.secret_file == "":
hide(input_image_file=options.input_image_file, \ hide(
img_enc=options.output_image_file, \ input_image_file=options.input_image_file,
secret_message=options.secret_message) img_enc=options.output_image_file,
secret_message=options.secret_message,
)
elif options.secret_message == "" and options.secret_file != "": elif options.secret_message == "" and options.secret_file != "":
hide(input_image_file=options.input_image_file, \ hide(
img_enc=options.output_image_file, \ input_image_file=options.input_image_file,
secret_file=options.secret_file) img_enc=options.output_image_file,
secret_file=options.secret_file,
)
elif options.reveal: elif options.reveal:
reveal(input_image_file=options.input_image_file) reveal(input_image_file=options.input_image_file)

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
#-*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Stéganô - Stéganô is a basic Python Steganography module. # Stéganô - Stéganô is a basic Python Steganography module.
# Copyright (C) 2010-2019 Cédric Bonhomme - https://www.cedricbonhomme.org # Copyright (C) 2010-2019 Cédric Bonhomme - https://www.cedricbonhomme.org
@ -25,17 +25,17 @@ __date__ = "$Date: 2016/08/04 $"
__revision__ = "$Date: 2017/05/04 $" __revision__ = "$Date: 2017/05/04 $"
__license__ = "GPLv3" __license__ = "GPLv3"
import sys from typing import IO, Union
from PIL import Image
from typing import Union, IO
from stegano import tools from stegano import tools
def hide(input_image: Union[str, IO[bytes]],
message: str, def hide(
encoding: str = 'UTF-8', input_image: Union[str, IO[bytes]],
auto_convert_rgb: bool = False): message: str,
encoding: str = "UTF-8",
auto_convert_rgb: bool = False,
):
"""Hide a message (string) in an image with the """Hide a message (string) in an image with the
LSB (Least Significant Bit) technique. LSB (Least Significant Bit) technique.
""" """
@ -44,14 +44,15 @@ def hide(input_image: Union[str, IO[bytes]],
img = tools.open_image(input_image) img = tools.open_image(input_image)
if img.mode not in ['RGB', 'RGBA']: if img.mode not in ["RGB", "RGBA"]:
if not auto_convert_rgb: if not auto_convert_rgb:
print('The mode of the image is not RGB. Mode is {}'.\ print(
format(img.mode)) "The mode of the image is not RGB. Mode is {}".format(img.mode)
answer = input('Convert the image to RGB ? [Y / n]\n') or 'Y' )
if answer.lower() == 'n': answer = input("Convert the image to RGB ? [Y / n]\n") or "Y"
raise Exception('Not a RGB image.') if answer.lower() == "n":
img = img.convert('RGB') raise Exception("Not a RGB image.")
img = img.convert("RGB")
encoded = img.copy() encoded = img.copy()
width, height = img.size width, height = img.size
@ -59,16 +60,19 @@ def hide(input_image: Union[str, IO[bytes]],
message = str(message_length) + ":" + str(message) message = str(message_length) + ":" + str(message)
message_bits = "".join(tools.a2bits_list(message, encoding)) message_bits = "".join(tools.a2bits_list(message, encoding))
message_bits += '0' * ((3 - (len(message_bits) % 3)) % 3) message_bits += "0" * ((3 - (len(message_bits) % 3)) % 3)
npixels = width * height npixels = width * height
len_message_bits = len(message_bits) len_message_bits = len(message_bits)
if len_message_bits > npixels * 3: if len_message_bits > npixels * 3:
raise Exception("The message you want to hide is too long: {}". \ raise Exception(
format(message_length)) "The message you want to hide is too long: {}".format(
message_length
)
)
for row in range(height): for row in range(height):
for col in range(width): for col in range(width):
if index + 3 <= len_message_bits : if index + 3 <= len_message_bits:
# Get the colour component. # Get the colour component.
pixel = img.getpixel((col, row)) pixel = img.getpixel((col, row))
@ -78,11 +82,11 @@ def hide(input_image: Union[str, IO[bytes]],
# Change the Least Significant Bit of each colour component. # Change the Least Significant Bit of each colour component.
r = tools.setlsb(r, message_bits[index]) r = tools.setlsb(r, message_bits[index])
g = tools.setlsb(g, message_bits[index+1]) g = tools.setlsb(g, message_bits[index + 1])
b = tools.setlsb(b, message_bits[index+2]) b = tools.setlsb(b, message_bits[index + 2])
# Save the new pixel # Save the new pixel
if img.mode == 'RGBA': if img.mode == "RGBA":
encoded.putpixel((col, row), (r, g, b, pixel[3])) encoded.putpixel((col, row), (r, g, b, pixel[3]))
else: else:
encoded.putpixel((col, row), (r, g, b)) encoded.putpixel((col, row), (r, g, b))
@ -93,7 +97,7 @@ def hide(input_image: Union[str, IO[bytes]],
return encoded return encoded
def reveal(input_image: Union[str, IO[bytes]], encoding='UTF-8'): def reveal(input_image: Union[str, IO[bytes]], encoding="UTF-8"):
"""Find a message in an image (with the LSB technique). """Find a message in an image (with the LSB technique).
""" """
img = tools.open_image(input_image) img = tools.open_image(input_image)
@ -106,20 +110,20 @@ def reveal(input_image: Union[str, IO[bytes]], encoding='UTF-8'):
# pixel = [r, g, b] or [r,g,b,a] # pixel = [r, g, b] or [r,g,b,a]
pixel = img.getpixel((col, row)) pixel = img.getpixel((col, row))
if img.mode == 'RGBA': if img.mode == "RGBA":
pixel = pixel[:3] # ignore the alpha pixel = pixel[:3] # ignore the alpha
for color in pixel: for color in pixel:
buff += (color&1)<<(tools.ENCODINGS[encoding]-1 - count) buff += (color & 1) << (tools.ENCODINGS[encoding] - 1 - count)
count += 1 count += 1
if count == tools.ENCODINGS[encoding]: if count == tools.ENCODINGS[encoding]:
bitab.append(chr(buff)) bitab.append(chr(buff))
buff, count = 0, 0 buff, count = 0, 0
if bitab[-1] == ":" and limit == None: if bitab[-1] == ":" and limit is None:
try: try:
limit = int("".join(bitab[:-1])) limit = int("".join(bitab[:-1]))
except: except:
pass pass
if len(bitab)-len(str(limit))-1 == limit : if len(bitab) - len(str(limit)) - 1 == limit:
img.close() img.close()
return "".join(bitab)[len(str(limit))+1:] return "".join(bitab)[len(str(limit)) + 1 :]

View file

@ -25,9 +25,10 @@ __date__ = "$Date: 2011/12/28 $"
__revision__ = "$Date: 2017/03/10 $" __revision__ = "$Date: 2017/03/10 $"
__license__ = "GPLv3" __license__ = "GPLv3"
import math
import itertools import itertools
from typing import Iterator, List, Dict import math
from typing import Dict, Iterator, List
def identity() -> Iterator[int]: def identity() -> Iterator[int]:
"""f(x) = x """f(x) = x
@ -37,15 +38,17 @@ def identity() -> Iterator[int]:
yield n yield n
n += 1 n += 1
def triangular_numbers() -> Iterator[int]: def triangular_numbers() -> Iterator[int]:
"""Triangular numbers: a(n) = C(n+1,2) = n(n+1)/2 = 0+1+2+...+n. """Triangular numbers: a(n) = C(n+1,2) = n(n+1)/2 = 0+1+2+...+n.
http://oeis.org/A000217 http://oeis.org/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() -> Iterator[int]: def fermat() -> Iterator[int]:
"""Generate the n-th Fermat Number. """Generate the n-th Fermat Number.
https://oeis.org/A000215 https://oeis.org/A000215
@ -53,7 +56,8 @@ def fermat() -> Iterator[int]:
y = 3 y = 3
while True: while True:
yield y yield y
y = pow(y-1,2)+1 y = pow(y - 1, 2) + 1
def mersenne() -> Iterator[int]: def mersenne() -> Iterator[int]:
"""Generate 2^p - 1, where p is prime. """Generate 2^p - 1, where p is prime.
@ -61,13 +65,14 @@ def mersenne() -> Iterator[int]:
""" """
prime_numbers = eratosthenes() prime_numbers = eratosthenes()
while True: while True:
yield 2**next(prime_numbers) - 1 yield 2 ** next(prime_numbers) - 1
def eratosthenes() -> Iterator[int]: def eratosthenes() -> Iterator[int]:
"""Generate the prime numbers with the sieve of Eratosthenes. """Generate the prime numbers with the sieve of Eratosthenes.
https://oeis.org/A000040 https://oeis.org/A000040
""" """
d = {} # type: Dict[int, List[int]] d = {} # type: Dict[int, List[int]]
for i in itertools.count(2): for i in itertools.count(2):
if i in d: if i in d:
for j in d[i]: for j in d[i]:
@ -77,6 +82,7 @@ def eratosthenes() -> Iterator[int]:
d[i * i] = [i] d[i * i] = [i]
yield i yield i
def composite() -> Iterator[int]: def composite() -> Iterator[int]:
"""Generate the composite numbers using the sieve of Eratosthenes. """Generate the composite numbers using the sieve of Eratosthenes.
https://oeis.org/A002808 https://oeis.org/A002808
@ -87,6 +93,7 @@ def composite() -> Iterator[int]:
yield n yield n
p1 = p2 p1 = p2
def carmichael() -> Iterator[int]: def carmichael() -> Iterator[int]:
"""Composite numbers n such that a^(n-1) == 1 (mod n) for every a coprime """Composite numbers n such that a^(n-1) == 1 (mod n) for every a coprime
to n. to n.
@ -94,11 +101,12 @@ def carmichael() -> Iterator[int]:
""" """
for m in composite(): for m in composite():
for a in range(2, m): for a in range(2, m):
if pow(a,m,m) != a: if pow(a, m, m) != a:
break break
else: else:
yield m yield m
def ackermann_naive(m: int, n: int) -> int: def ackermann_naive(m: int, n: int) -> int:
"""Ackermann number. """Ackermann number.
""" """
@ -109,6 +117,7 @@ def ackermann_naive(m: int, n: int) -> int:
else: else:
return ackermann(m - 1, ackermann(m, n - 1)) return ackermann(m - 1, ackermann(m, n - 1))
def ackermann(m: int, n: int) -> int: def ackermann(m: int, n: int) -> int:
"""Ackermann number. """Ackermann number.
""" """
@ -127,6 +136,7 @@ def ackermann(m: int, n: int) -> int:
else: else:
return n + 1 return n + 1
def fibonacci() -> Iterator[int]: def fibonacci() -> Iterator[int]:
"""Generate the sequence of Fibonacci. """Generate the sequence of Fibonacci.
https://oeis.org/A000045 https://oeis.org/A000045
@ -136,6 +146,7 @@ def fibonacci() -> Iterator[int]:
yield a yield a
a, b = b, a + b a, b = b, a + b
def log_gen() -> Iterator[int]: def log_gen() -> Iterator[int]:
"""Logarithmic generator. """Logarithmic generator.
""" """

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
#-*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Stéganô - Stéganô is a basic Python Steganography module. # Stéganô - Stéganô is a basic Python Steganography module.
# Copyright (C) 2010-2019 Cédric Bonhomme - https://www.cedricbonhomme.org # Copyright (C) 2010-2019 Cédric Bonhomme - https://www.cedricbonhomme.org
@ -25,20 +25,21 @@ __date__ = "$Date: 2016/03/13 $"
__revision__ = "$Date: 2018/12/18 $" __revision__ = "$Date: 2018/12/18 $"
__license__ = "GPLv3" __license__ = "GPLv3"
import sys from typing import IO, Iterator, Union
from PIL import Image from PIL import Image
from typing import Union, Iterator, IO
from stegano import tools from stegano import tools
from . import generators
def hide(input_image: Union[str, IO[bytes]],
message: str, def hide(
generator: Iterator[int], input_image: Union[str, IO[bytes]],
shift: int = 0, message: str,
encoding: str = 'UTF-8', generator: Iterator[int],
auto_convert_rgb: bool = False): shift: int = 0,
encoding: str = "UTF-8",
auto_convert_rgb: bool = False,
):
"""Hide a message (string) in an image with the """Hide a message (string) in an image with the
LSB (Least Significant Bit) technique. LSB (Least Significant Bit) technique.
""" """
@ -47,14 +48,15 @@ def hide(input_image: Union[str, IO[bytes]],
img = tools.open_image(input_image) img = tools.open_image(input_image)
if img.mode not in ['RGB', 'RGBA']: if img.mode not in ["RGB", "RGBA"]:
if not auto_convert_rgb: if not auto_convert_rgb:
print('The mode of the image is not RGB. Mode is {}'.\ print(
format(img.mode)) "The mode of the image is not RGB. Mode is {}".format(img.mode)
answer = input('Convert the image to RGB ? [Y / n]\n') or 'Y' )
if answer.lower() == 'n': answer = input("Convert the image to RGB ? [Y / n]\n") or "Y"
raise Exception('Not a RGB image.') if answer.lower() == "n":
img = img.convert('RGB') raise Exception("Not a RGB image.")
img = img.convert("RGB")
img_list = list(img.getdata()) img_list = list(img.getdata())
width, height = img.size width, height = img.size
@ -62,36 +64,39 @@ def hide(input_image: Union[str, IO[bytes]],
message = str(message_length) + ":" + str(message) message = str(message_length) + ":" + str(message)
message_bits = "".join(tools.a2bits_list(message, encoding)) message_bits = "".join(tools.a2bits_list(message, encoding))
message_bits += '0' * ((3 - (len(message_bits) % 3)) % 3) message_bits += "0" * ((3 - (len(message_bits) % 3)) % 3)
npixels = width * height npixels = width * height
len_message_bits = len(message_bits) len_message_bits = len(message_bits)
if len_message_bits > npixels * 3: if len_message_bits > npixels * 3:
raise Exception("The message you want to hide is too long: {}". \ raise Exception(
format(message_length)) "The message you want to hide is too long: {}".format(
message_length
)
)
while shift != 0: while shift != 0:
next(generator) next(generator)
shift -= 1 shift -= 1
while index + 3 <= len_message_bits : while index + 3 <= len_message_bits:
generated_number = next(generator) generated_number = next(generator)
r, g, b, *a = img_list[generated_number] r, g, b, *a = img_list[generated_number]
# Change the Least Significant Bit of each colour component. # Change the Least Significant Bit of each colour component.
r = tools.setlsb(r, message_bits[index]) r = tools.setlsb(r, message_bits[index])
g = tools.setlsb(g, message_bits[index+1]) g = tools.setlsb(g, message_bits[index + 1])
b = tools.setlsb(b, message_bits[index+2]) b = tools.setlsb(b, message_bits[index + 2])
# Save the new pixel # Save the new pixel
if img.mode == 'RGBA': if img.mode == "RGBA":
img_list[generated_number] = (r, g , b, a[0]) img_list[generated_number] = (r, g, b, a[0])
else: else:
img_list[generated_number] = (r, g , b) img_list[generated_number] = (r, g, b)
index += 3 index += 3
# create empty new image of appropriate format # create empty new image of appropriate format
encoded = Image.new('RGB', (img.size)) encoded = Image.new("RGB", (img.size))
# insert saved data into the image # insert saved data into the image
encoded.putdata(img_list) encoded.putdata(img_list)
@ -99,10 +104,12 @@ def hide(input_image: Union[str, IO[bytes]],
return encoded return encoded
def reveal(input_image: Union[str, IO[bytes]], def reveal(
generator: Iterator[int], input_image: Union[str, IO[bytes]],
shift: int = 0, generator: Iterator[int],
encoding: str = 'UTF-8'): shift: int = 0,
encoding: str = "UTF-8",
):
"""Find a message in an image (with the LSB technique). """Find a message in an image (with the LSB technique).
""" """
img = tools.open_image(input_image) img = tools.open_image(input_image)
@ -120,7 +127,7 @@ def reveal(input_image: Union[str, IO[bytes]],
generated_number = next(generator) 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)<<(tools.ENCODINGS[encoding]-1 - count) buff += (color & 1) << (tools.ENCODINGS[encoding] - 1 - count)
count += 1 count += 1
if count == tools.ENCODINGS[encoding]: if count == tools.ENCODINGS[encoding]:
bitab.append(chr(buff)) bitab.append(chr(buff))
@ -130,5 +137,5 @@ def reveal(input_image: Union[str, IO[bytes]],
limit = int("".join(bitab[:-1])) limit = int("".join(bitab[:-1]))
else: else:
raise IndexError("Impossible to detect message.") raise IndexError("Impossible to detect message.")
if len(bitab)-len(str(limit))-1 == limit : if len(bitab) - len(str(limit)) - 1 == limit:
return "".join(bitab)[len(str(limit))+1:] return "".join(bitab)[len(str(limit)) + 1 :]

View file

@ -25,12 +25,11 @@ __date__ = "$Date: 2010/10/01 $"
__revision__ = "$Date: 2017/02/06 $" __revision__ = "$Date: 2017/02/06 $"
__license__ = "GPLv3" __license__ = "GPLv3"
import sys from typing import IO, Union
from PIL import Image
from typing import Union, IO
from stegano import tools from stegano import tools
def hide(input_image: Union[str, IO[bytes]], message: str): def hide(input_image: Union[str, IO[bytes]], message: str):
""" """
Hide a message (string) in an image. Hide a message (string) in an image.
@ -54,15 +53,16 @@ def hide(input_image: Union[str, IO[bytes]], message: str):
if row == 0 and col == 0 and index < message_length: if row == 0 and col == 0 and index < message_length:
asc = message_length asc = message_length
elif index <= message_length: elif index <= message_length:
c = message[index -1] c = message[index - 1]
asc = ord(c) asc = ord(c)
else: else:
asc = r asc = r
encoded.putpixel((col, row), (asc, g , b)) encoded.putpixel((col, row), (asc, g, b))
index += 1 index += 1
img.close() img.close()
return encoded return encoded
def reveal(input_image: Union[str, IO[bytes]]): def reveal(input_image: Union[str, IO[bytes]]):
""" """
Find a message in an image. Find a message in an image.

View file

@ -27,16 +27,13 @@ __license__ = "GPLv3"
import base64 import base64
import itertools import itertools
from typing import List, Iterator, Tuple, Union
from functools import reduce from functools import reduce
from typing import IO, Iterator, List, Tuple, Union from typing import IO, Iterator, List, Tuple, Union
from PIL import Image from PIL import Image
ENCODINGS = { ENCODINGS = {"UTF-8": 8, "UTF-32LE": 32}
'UTF-8': 8,
'UTF-32LE': 32
}
def a2bits(chars: str) -> str: def a2bits(chars: str) -> str:
"""Converts a string to its bits representation as a string of 0's and 1's. """Converts a string to its bits representation as a string of 0's and 1's.
@ -44,9 +41,12 @@ def a2bits(chars: str) -> str:
>>> a2bits("Hello World!") >>> a2bits("Hello World!")
'010010000110010101101100011011000110111100100000010101110110111101110010011011000110010000100001' '010010000110010101101100011011000110111100100000010101110110111101110010011011000110010000100001'
""" """
return bin(reduce(lambda x, y : (x<<8)+y, (ord(c) for c in chars), 1))[3:] return bin(reduce(lambda x, y: (x << 8) + y, (ord(c) for c in chars), 1))[
3:
]
def a2bits_list(chars: str, encoding: str ='UTF-8') -> List[str]:
def a2bits_list(chars: str, encoding: str = "UTF-8") -> List[str]:
"""Convert a string to its bits representation as a list of 0's and 1's. """Convert a string to its bits representation as a list of 0's and 1's.
>>> a2bits_list("Hello World!") >>> a2bits_list("Hello World!")
@ -65,20 +65,24 @@ def a2bits_list(chars: str, encoding: str ='UTF-8') -> List[str]:
>>> "".join(a2bits_list("Hello World!")) >>> "".join(a2bits_list("Hello World!"))
'010010000110010101101100011011000110111100100000010101110110111101110010011011000110010000100001' '010010000110010101101100011011000110111100100000010101110110111101110010011011000110010000100001'
""" """
return [bin(ord(x))[2:].rjust(ENCODINGS[encoding],"0") for x in chars] return [bin(ord(x))[2:].rjust(ENCODINGS[encoding], "0") for x in chars]
def bs(s: int) -> str: def bs(s: int) -> str:
"""Converts an int to its bits representation as a string of 0's and 1's. """Converts an int to its bits representation as a string of 0's and 1's.
""" """
return str(s) if s<=1 else bs(s>>1) + str(s&1) return str(s) if s <= 1 else bs(s >> 1) + str(s & 1)
def setlsb(component: int, bit: str) -> int: def setlsb(component: int, bit: str) -> int:
"""Set Least Significant Bit of a colour component. """Set Least Significant Bit of a colour component.
""" """
return component & ~1 | int(bit) return component & ~1 | int(bit)
def n_at_a_time(items: List[int], n: int, fillvalue: str) \
-> Iterator[Tuple[Union[int, str]]]: def n_at_a_time(
items: List[int], n: int, fillvalue: str
) -> Iterator[Tuple[Union[int, str]]]:
"""Returns an iterator which groups n items at a time. """Returns an iterator which groups n items at a time.
Any final partial tuple will be padded with the fillvalue Any final partial tuple will be padded with the fillvalue
@ -88,6 +92,7 @@ def n_at_a_time(items: List[int], n: int, fillvalue: str) \
it = iter(items) it = iter(items)
return itertools.zip_longest(*[it] * n, fillvalue=fillvalue) return itertools.zip_longest(*[it] * n, fillvalue=fillvalue)
def binary2base64(binary_file: str) -> str: def binary2base64(binary_file: str) -> str:
"""Convert a binary file (OGG, executable, etc.) to a """Convert a binary file (OGG, executable, etc.) to a
printable string. printable string.
@ -97,12 +102,14 @@ def binary2base64(binary_file: str) -> str:
encoded_string = base64.b64encode(bin_file.read()) encoded_string = base64.b64encode(bin_file.read())
return encoded_string.decode() return encoded_string.decode()
def base642binary(b64_fname: str) -> bytes: def base642binary(b64_fname: str) -> bytes:
"""Convert a printable string to a binary file. """Convert a printable string to a binary file.
""" """
b64_fname += '===' b64_fname += "==="
return base64.b64decode(b64_fname) return base64.b64decode(b64_fname)
def open_image(fname_or_instance: Union[str, IO[bytes]]): def open_image(fname_or_instance: Union[str, IO[bytes]]):
"""Opens a Image and returns it. """Opens a Image and returns it.