mirror of
https://github.com/cedricbonhomme/Stegano.git
synced 2025-06-27 19:06:12 +02:00
chg: [typing] Make Mypy Happy Again.
This commit is contained in:
parent
21004219fa
commit
18fd8a8a49
5 changed files with 43 additions and 21 deletions
|
@ -21,7 +21,7 @@ repos:
|
|||
additional_dependencies:
|
||||
- flake8-bugbear
|
||||
- flake8-implicit-str-concat
|
||||
args: ["--max-line-length=125"]
|
||||
args: ["--max-line-length=125", "--ignore=E203"]
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.1.0
|
||||
hooks:
|
||||
|
|
|
@ -73,7 +73,7 @@ optional = true
|
|||
|
||||
|
||||
[tool.mypy]
|
||||
python_version = "3.12"
|
||||
python_version = "3.13"
|
||||
check_untyped_defs = true
|
||||
ignore_errors = false
|
||||
ignore_missing_imports = true
|
||||
|
@ -87,7 +87,12 @@ warn_unreachable = true
|
|||
show_error_context = true
|
||||
pretty = true
|
||||
|
||||
exclude = "build|dist|docs|stegano.egg-info"
|
||||
exclude = "build|dist|docs"
|
||||
|
||||
|
||||
[tool.isort]
|
||||
profile = "black"
|
||||
|
||||
|
||||
[tool.flake8]
|
||||
ignore = ["E203"]
|
||||
|
|
|
@ -23,7 +23,7 @@ __date__ = "$Date: 2010/10/01 $"
|
|||
__revision__ = "$Date: 2017/02/06 $"
|
||||
__license__ = "GPLv3"
|
||||
|
||||
from typing import IO, Union
|
||||
from typing import IO, Union, cast
|
||||
|
||||
from stegano import tools
|
||||
|
||||
|
@ -40,13 +40,17 @@ def hide(input_image: Union[str, IO[bytes]], message: str):
|
|||
assert message_length != 0, "message message_length is zero"
|
||||
assert message_length < 255, "message is too long"
|
||||
img = tools.open_image(input_image)
|
||||
# Ensure image mode is RGB
|
||||
if img.mode != "RGB":
|
||||
img = img.convert("RGB")
|
||||
# Use a copy of image to hide the text in
|
||||
encoded = img.copy()
|
||||
width, height = img.size
|
||||
index = 0
|
||||
for row in range(height):
|
||||
for col in range(width):
|
||||
(r, g, b) = img.getpixel((col, row))
|
||||
pixel = cast(tuple[int, int, int], img.getpixel((col, row)))
|
||||
r, g, b = pixel
|
||||
# first value is message_length of message
|
||||
if row == 0 and col == 0 and index < message_length:
|
||||
asc = message_length
|
||||
|
@ -70,12 +74,16 @@ def reveal(input_image: Union[str, IO[bytes]]):
|
|||
The red value of the first pixel is used for message_length of string.
|
||||
"""
|
||||
img = tools.open_image(input_image)
|
||||
# Ensure image mode is RGB
|
||||
if img.mode != "RGB":
|
||||
img = img.convert("RGB")
|
||||
width, height = img.size
|
||||
message = ""
|
||||
index = 0
|
||||
for row in range(height):
|
||||
for col in range(width):
|
||||
r, g, b = img.getpixel((col, row))
|
||||
pixel = cast(tuple[int, int, int], img.getpixel((col, row)))
|
||||
r, g, b = pixel
|
||||
# First pixel r value is length of message
|
||||
if row == 0 and col == 0:
|
||||
message_length = r
|
||||
|
|
|
@ -23,6 +23,8 @@ __date__ = "$Date: 2010/10/01 $"
|
|||
__revision__ = "$Date: 2019/06/06 $"
|
||||
__license__ = "GPLv3"
|
||||
|
||||
from typing import cast
|
||||
|
||||
from PIL import Image
|
||||
|
||||
|
||||
|
@ -34,7 +36,7 @@ def steganalyse(img: Image.Image) -> Image.Image:
|
|||
width, height = img.size
|
||||
for row in range(height):
|
||||
for col in range(width):
|
||||
if pixel := img.getpixel((col, row)):
|
||||
if pixel := cast(tuple[int, int, int], img.getpixel((col, row))):
|
||||
r, g, b = pixel[0:3]
|
||||
else:
|
||||
raise Exception("Error during steganlysis.")
|
||||
|
|
|
@ -26,7 +26,7 @@ __license__ = "GPLv3"
|
|||
import base64
|
||||
import itertools
|
||||
from functools import reduce
|
||||
from typing import IO, List, Union
|
||||
from typing import IO, List, Union, cast
|
||||
|
||||
from PIL import Image
|
||||
|
||||
|
@ -101,11 +101,12 @@ def base642binary(b64_fname: str) -> bytes:
|
|||
return base64.b64decode(b64_fname)
|
||||
|
||||
|
||||
def open_image(fname_or_instance: Union[str, IO[bytes]]):
|
||||
"""Opens a Image and returns it.
|
||||
def open_image(fname_or_instance: Union[str, IO[bytes], Image.Image]) -> Image.Image:
|
||||
"""Opens an image and returns it.
|
||||
|
||||
:param fname_or_instance: Can either be the location of the image as a
|
||||
string or the Image.Image instance itself.
|
||||
:param fname_or_instance: Can be a path to the image (str),
|
||||
a file-like object (IO[bytes]),
|
||||
or a PIL Image instance.
|
||||
"""
|
||||
if isinstance(fname_or_instance, Image.Image):
|
||||
return fname_or_instance
|
||||
|
@ -157,8 +158,15 @@ class Hider:
|
|||
return True if self._index + 3 <= self._len_message_bits else False
|
||||
|
||||
def encode_pixel(self, coordinate: tuple):
|
||||
# Get the colour component.
|
||||
r, g, b, *a = self.encoded_image.getpixel(coordinate)
|
||||
# Determine expected pixel format based on mode
|
||||
if self.encoded_image.mode == "RGBA":
|
||||
r, g, b, *a = cast(
|
||||
tuple[int, int, int, int], self.encoded_image.getpixel(coordinate)
|
||||
)
|
||||
else:
|
||||
r, g, b, *a = cast(
|
||||
tuple[int, int, int], self.encoded_image.getpixel(coordinate)
|
||||
)
|
||||
|
||||
# Change the Least Significant Bit of each colour component.
|
||||
r = setlsb(r, self._message_bits[self._index])
|
||||
|
@ -190,8 +198,11 @@ class Revealer:
|
|||
self.close_file = close_file
|
||||
|
||||
def decode_pixel(self, coordinate: tuple):
|
||||
# pixel = [r, g, b] or [r,g,b,a]
|
||||
pixel = self.encoded_image.getpixel(coordinate)
|
||||
# Tell mypy that this will be a 3- or 4-tuple of ints
|
||||
pixel = cast(
|
||||
tuple[int, int, int] | tuple[int, int, int, int],
|
||||
self.encoded_image.getpixel(coordinate),
|
||||
)
|
||||
|
||||
if self.encoded_image.mode == "RGBA":
|
||||
pixel = pixel[:3] # ignore the alpha
|
||||
|
@ -211,13 +222,9 @@ class Revealer:
|
|||
raise IndexError("Impossible to detect message.")
|
||||
|
||||
if len(self._bitab) - len(str(self._limit)) - 1 == self._limit:
|
||||
self.secret_message = "".join(self._bitab)[
|
||||
len(str(self._limit)) + 1 : # noqa: E203
|
||||
]
|
||||
self.secret_message = "".join(self._bitab)[len(str(self._limit)) + 1 :]
|
||||
if self.close_file:
|
||||
self.encoded_image.close()
|
||||
|
||||
return True
|
||||
|
||||
else:
|
||||
return False
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue