mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-18 20:38:10 +00:00
feat(python/trezorctl): better conversion to Trezor homescreen format (fixes #2880)
This commit is contained in:
parent
67748f3c94
commit
f6534d4220
1
python/.changelog.d/2880.added
Normal file
1
python/.changelog.d/2880.added
Normal file
@ -0,0 +1 @@
|
|||||||
|
Auto-convert image to Trezor's homescreen format.
|
@ -14,7 +14,8 @@
|
|||||||
# You should have received a copy of the License along with this library.
|
# You should have received a copy of the License along with this library.
|
||||||
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
|
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
|
||||||
|
|
||||||
import os
|
import io
|
||||||
|
from pathlib import Path
|
||||||
from typing import TYPE_CHECKING, Optional, cast
|
from typing import TYPE_CHECKING, Optional, cast
|
||||||
|
|
||||||
import click
|
import click
|
||||||
@ -39,13 +40,13 @@ SAFETY_LEVELS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def image_to_t1(filename: str) -> bytes:
|
def image_to_t1(filename: Path) -> bytes:
|
||||||
if not PIL_AVAILABLE:
|
if not PIL_AVAILABLE:
|
||||||
raise click.ClickException(
|
raise click.ClickException(
|
||||||
"Image library is missing. Please install via 'pip install Pillow'."
|
"Image library is missing. Please install via 'pip install Pillow'."
|
||||||
)
|
)
|
||||||
|
|
||||||
if filename.endswith(".toif"):
|
if filename.suffix == ".toif":
|
||||||
raise click.ClickException("TOIF images not supported on Trezor One")
|
raise click.ClickException("TOIF images not supported on Trezor One")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -60,10 +61,10 @@ def image_to_t1(filename: str) -> bytes:
|
|||||||
return image.tobytes("raw", "1")
|
return image.tobytes("raw", "1")
|
||||||
|
|
||||||
|
|
||||||
def image_to_toif_144x144(filename: str) -> bytes:
|
def image_to_toif_144x144(filename: Path) -> bytes:
|
||||||
if filename.endswith(".toif"):
|
if filename.suffix == ".toif":
|
||||||
try:
|
try:
|
||||||
toif_image = toif.load(filename)
|
toif_image = toif.from_bytes(filename.read_bytes())
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise click.ClickException("TOIF file is corrupted") from e
|
raise click.ClickException("TOIF file is corrupted") from e
|
||||||
|
|
||||||
@ -90,38 +91,30 @@ def image_to_toif_144x144(filename: str) -> bytes:
|
|||||||
return toif_image.to_bytes()
|
return toif_image.to_bytes()
|
||||||
|
|
||||||
|
|
||||||
def image_to_jpeg_240x240(filename: str) -> bytes:
|
def image_to_jpeg_240x240(filename: Path) -> bytes:
|
||||||
if not (filename.endswith(".jpg") or filename.endswith(".jpeg")):
|
if filename.suffix in (".jpg", ".jpeg") and not PIL_AVAILABLE:
|
||||||
raise click.ClickException("Please use a jpg image")
|
click.echo("Warning: Image library is missing, skipping image validation.")
|
||||||
|
return filename.read_bytes()
|
||||||
|
|
||||||
elif not PIL_AVAILABLE:
|
if not PIL_AVAILABLE:
|
||||||
raise click.ClickException(
|
raise click.ClickException(
|
||||||
"Image library is missing. Please install via 'pip install Pillow'."
|
"Image library is missing. Please install via 'pip install Pillow'."
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
try:
|
||||||
try:
|
image = Image.open(filename)
|
||||||
image = Image.open(filename)
|
except Exception as e:
|
||||||
except Exception as e:
|
raise click.ClickException("Failed to open image") from e
|
||||||
raise click.ClickException("Failed to open image") from e
|
|
||||||
|
|
||||||
if "progressive" in image.info:
|
|
||||||
raise click.ClickException("Progressive JPEG is not supported")
|
|
||||||
|
|
||||||
if image.size != (240, 240):
|
if image.size != (240, 240):
|
||||||
raise click.ClickException("Wrong size of image - should be 240x240")
|
raise click.ClickException("Wrong size of image - should be 240x240")
|
||||||
|
|
||||||
image.close()
|
if image.mode != "RGB":
|
||||||
|
image = image.convert("RGB")
|
||||||
|
|
||||||
file_stats = os.stat(filename)
|
buf = io.BytesIO()
|
||||||
|
image.save(buf, format="jpeg", progressive=False)
|
||||||
if file_stats.st_size > 16384:
|
return buf.getvalue()
|
||||||
raise click.ClickException("File is too big, please use maximum 16kB")
|
|
||||||
|
|
||||||
in_file = open(filename, "rb")
|
|
||||||
bytes = in_file.read()
|
|
||||||
in_file.close()
|
|
||||||
return bytes
|
|
||||||
|
|
||||||
|
|
||||||
def _should_remove(enable: Optional[bool], remove: bool) -> bool:
|
def _should_remove(enable: Optional[bool], remove: bool) -> bool:
|
||||||
@ -237,23 +230,24 @@ def homescreen(client: "TrezorClient", filename: str) -> str:
|
|||||||
if filename == "default":
|
if filename == "default":
|
||||||
img = b""
|
img = b""
|
||||||
else:
|
else:
|
||||||
# use Click's facility to validate the path for us
|
path = Path(filename)
|
||||||
param = click.Path(dir_okay=False, readable=True, exists=True)
|
if not path.exists() or not path.is_file():
|
||||||
param.convert(filename, None, None)
|
raise click.ClickException("Cannot open file")
|
||||||
|
|
||||||
if client.features.model == "1":
|
if client.features.model == "1":
|
||||||
img = image_to_t1(filename)
|
img = image_to_t1(path)
|
||||||
else:
|
else:
|
||||||
if (
|
if (
|
||||||
client.features.homescreen_format
|
client.features.homescreen_format
|
||||||
== messages.HomescreenFormat.Jpeg240x240
|
== messages.HomescreenFormat.Jpeg240x240
|
||||||
):
|
):
|
||||||
img = image_to_jpeg_240x240(filename)
|
img = image_to_jpeg_240x240(path)
|
||||||
elif (
|
elif (
|
||||||
client.features.homescreen_format
|
client.features.homescreen_format
|
||||||
== messages.HomescreenFormat.Toif144x144
|
== messages.HomescreenFormat.Toif144x144
|
||||||
or client.features.homescreen_format is None
|
or client.features.homescreen_format is None
|
||||||
):
|
):
|
||||||
img = image_to_toif_144x144(filename)
|
img = image_to_toif_144x144(path)
|
||||||
else:
|
else:
|
||||||
raise click.ClickException(
|
raise click.ClickException(
|
||||||
"Unknown image format requested by the device."
|
"Unknown image format requested by the device."
|
||||||
|
Loading…
Reference in New Issue
Block a user