File imghdr.py of Package failed_python-mediafile
"""
A minimal replacement for the deprecated and removed stdlib `imghdr` module.
This provides the `what(filename, h=None)` function used by code that imports
`imghdr`. It performs basic image type detection from the file header bytes.
It is intentionally small and only implements the checks needed for common
formats (jpeg, png, gif, tiff, bmp, webp). If more formats are needed they
can be added following the same pattern.
This file is intended as the smallest necessary change to restore compatibility
with Python versions where the stdlib `imghdr` module is not available.
"""
from typing import Optional, Union
def _read_header_from_filename(filename: str, n: int = 32) -> Optional[bytes]:
try:
with open(filename, "rb") as f:
return f.read(n)
except Exception:
return None
def what(filename: Union[str, bytes, bytearray, None], h: Optional[bytes] = None) -> Optional[str]:
"""
Determine the image type based on file header.
Arguments:
- filename: path to the file (str) or raw bytes (bytes/bytearray) when h is None.
- h: optional header bytes to examine (if provided, filename can be None).
Returns a short string identifying the file type like 'jpeg', 'png', 'gif',
'tiff', 'bmp', 'webp' or None if unknown.
"""
header = h
# If header not given, and filename is bytes/bytearray treat it as header.
if header is None and isinstance(filename, (bytes, bytearray)):
header = bytes(filename[:64])
filename = None
# If header still not given, try to read from filename.
if header is None:
if filename is None:
return None
header = _read_header_from_filename(filename, 64)
if header is None:
return None
# Ensure we have a bytes object.
if not isinstance(header, (bytes, bytearray)):
try:
header = bytes(header)
except Exception:
return None
h = header
# JPEG: starts with 0xFF 0xD8
if h.startswith(b"\xff\xd8"):
return "jpeg"
# PNG: 89 50 4E 47 0D 0A 1A 0A
if h.startswith(b"\x89PNG\r\n\x1a\n"):
return "png"
# GIF: GIF87a or GIF89a
if h[:6] in (b"GIF87a", b"GIF89a"):
return "gif"
# TIFF: little endian II*\x00 or big-endian MM\x00*
if h[:4] in (b"II*\x00", b"MM\x00*"):
return "tiff"
# BMP: 'BM' at start
if h.startswith(b"BM"):
return "bmp"
# WEBP: 'RIFF'....'WEBP' (bytes 0-3 RIFF, bytes 8-11 WEBP)
if h.startswith(b"RIFF") and len(h) >= 12 and h[8:12] == b"WEBP":
return "webp"
# XBM: starts with '#define ' (text-based X bitmap)
# Check first few bytes as ASCII
try:
start = h.lstrip()[:8].lower()
if start.startswith(b"#define") or start.startswith(b"/*"):
# Not highly accurate, but helps identify xbm-like files
return "xbm"
except Exception:
pass
return None
# For compatibility: expose common names from the original imghdr module
tests = None # placeholder, some code imports imghdr.tests; we don't provide it here.
what.__doc__ = what.__doc__ # keep docstring accessible.