この例は、PNGの先頭メタデータとローカル予算だけを確認する小さなPython実装です。完全な画像検証、安全性評価、個人情報の検出、サービス側の受理確認を行うものではありません。
Disclosure: I help promote Car Customizer. This project-associated technical article was AI-assisted, not an independent review or a claim that the product uses the example code. The code below was run locally with the supplied synthetic tests. No private vehicle photograph, customer record or product backend was used to establish its behavior.
A metadata result should have a narrow name
A helper that reads an image header is easy to describe too broadly. Names such as safe image or validated upload can suggest that the file was decoded, its contents reviewed and its use approved. Reading a few structured bytes does none of those things. The example here returns dimensions and byte count only after a deliberately small set of checks. Its name says header rather than image validation.
This distinction matters in an ordinary image workflow. A person may need to decide whether an authorized public asset fits a local size budget before preparing an upload. That decision is useful, but it is separate from privacy, visual quality, ownership and the destination service's requirements. A passing metadata result should not silently become approval for all of those other decisions.
Make the contract explicit before writing the parser
The function accepts bytes and two positive integer budgets. It checks the PNG signature, the presence of a first thirteen-byte IHDR chunk, that chunk's CRC, positive dimensions and the chosen byte and pixel budgets. It returns an immutable metadata object. It does not read subsequent chunks, decompress pixels, evaluate all PNG mode combinations or require the rest of the stream to be a complete image.
Those omissions are intentional and visible in the tests. A header without IDAT or IEND can pass this narrow contract. So can a correct header followed by an invalid remainder. If those results would be unacceptable for the caller's purpose, the caller needs a different operation, not a more impressive label for this one. Keep this helper separate from a real decoder and any further application-specific checks.
An appearance workflow provides context, not authority
Car Customizer is a car customization website for exploring paint, wheels, wraps and body-styling directions on an authorized car photograph. Its public interface lists JPG, PNG and WebP uploads up to the current ten-megabyte limit. This article's example handles PNG metadata only; it is not the product's upload validator and says nothing about how its backend handles other formats.
Previews use credits. The current public pricing page describes a one-time allocation of nine welcome credits for new accounts, with paid subscriptions or credit packs for further use. No product generation was performed for these tests. An appearance concept also cannot verify fitment, clearances, road legality or mechanical safety. A small local file check should not borrow authority from decisions that require separate information and qualified judgment.
Read the fixed header without pretending to decode it
The signature occupies the first eight bytes. A chunk then supplies a big-endian length, a four-byte type, its payload and a CRC. For this example, the first chunk must be IHDR with a thirteen-byte payload. The dimensions are the first eight bytes of that payload. The implementation checks the minimum buffer length before taking those slices so that malformed short input has a specific failure result.
A CRC mismatch is an integrity signal for the examined chunk, not proof about who created the file. Someone who changes data can also recompute its CRC. The function does not authenticate a photograph or detect every alteration. Similarly, dimensions describe header values; they are not evidence that the depicted object has a particular real-world size.
The complete implementation
Save this block as png_header_budget.py. The command line reads only the explicitly supplied local path and prints metadata; it never uploads a file. The returned scope label is part of making the limit visible to a reader who sees the result without the surrounding article. Error strings identify the particular contract check that failed, not a conclusion about the safety of the whole file.
"""Inspect PNG header metadata only; this is not an image decoder or safety check."""
from dataclasses import dataclass
from pathlib import Path
import argparse
import json
import struct
import zlib
SIGNATURE = b"\x89PNG\r\n\x1a\n"
@dataclass(frozen=True)
class HeaderInfo:
width: int
height: int
byte_count: int
def inspect_png_header(data: bytes, *, max_bytes: int = 10_000_000,
max_pixels: int = 12_000_000) -> HeaderInfo:
"""Check a narrow header/budget contract without decoding pixels.
A passing result does not establish complete PNG validity, privacy,
authenticity, visual quality, compatibility, or upload acceptance.
"""
if not isinstance(data, bytes):
raise TypeError("data must be bytes")
for name, limit in (("max_bytes", max_bytes), ("max_pixels", max_pixels)):
if type(limit) is not int or limit <= 0:
raise ValueError(f"{name} must be a positive integer")
if len(data) > max_bytes:
raise ValueError("byte_budget_exceeded")
if len(data) < 33:
raise ValueError("header_too_short")
if data[:8] != SIGNATURE:
raise ValueError("not_png_signature")
length = struct.unpack(">I", data[8:12])[0]
chunk_type = data[12:16]
if chunk_type != b"IHDR" or length != 13:
raise ValueError("expected_first_13_byte_IHDR")
payload = data[16:29]
stored_crc = struct.unpack(">I", data[29:33])[0]
if stored_crc != zlib.crc32(chunk_type + payload) & 0xFFFFFFFF:
raise ValueError("IHDR_crc_mismatch")
width, height = struct.unpack(">II", payload[:8])
if width == 0 or height == 0:
raise ValueError("zero_dimension")
if width * height > max_pixels:
raise ValueError("pixel_budget_exceeded")
return HeaderInfo(width, height, len(data))
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("path", type=Path)
parser.add_argument("--max-bytes", type=int, default=10_000_000)
parser.add_argument("--max-pixels", type=int, default=12_000_000)
args = parser.parse_args()
# This small CLI reads the explicitly supplied file. It never uploads it.
# A production ingestion boundary should bound streaming before allocation.
info = inspect_png_header(args.path.read_bytes(), max_bytes=args.max_bytes,
max_pixels=args.max_pixels)
print(json.dumps({"width": info.width, "height": info.height,
"byte_count": info.byte_count,
"scope": "PNG header metadata only"}))
if __name__ == "__main__":
main()
Budgets are caller choices, not product specifications
The defaults are illustrative local budgets. Ten million bytes is a decimal quantity, not ten mebibytes. An upload interface may express or enforce its limit differently. Check the current destination requirements rather than assuming this example reproduces them. The pixel budget is also a caller-selected threshold, not a claim about the appearance product's supported resolutions.
Python integers make the multiplication straightforward, but a dimension product does not establish decoded memory use. Channels, sample depth, processing and other factors still matter. This example is not decompression-bomb protection. The CLI also reads the entire file before checking its length. A production ingestion boundary should impose an appropriate streaming limit before allocation instead of treating this convenience command as a hardened upload service.
Test the boundary as well as the positive cases
The accompanying unittest module creates synthetic IHDR headers in memory. It covers dimensions, minimum lengths, signatures, first-chunk layout, the examined CRC, zero dimensions, exact and exceeded budgets, invalid budget types and immutable results. The tests deliberately include a header-only case and an invalid remainder to demonstrate what is outside the contract.
All eighteen test methods passed in the local run, including the budget-input subcases. That statement describes these supplied tests and this implementation, not every possible file, Python environment or image parser. Additional checks on an authorized public logo and a public landing-page screenshot returned their dimensions and byte counts. No private saved project was used, and those two metadata results were not treated as privacy or upload-acceptance proofs.
The complete synthetic tests
Save this block beside the implementation as test_png_header_budget.py. The helper named header builds only the bytes needed by the narrow test contract; it is not a fixture generator for complete displayable PNG images. A reader should not mistake the deliberately incomplete examples for files that a browser or an image service is expected to accept.
import struct
import unittest
import zlib
from dataclasses import FrozenInstanceError
from png_header_budget import SIGNATURE, inspect_png_header
def header(width=32, height=24):
payload = struct.pack(">IIBBBBB", width, height, 8, 6, 0, 0, 0)
chunk = b"IHDR" + payload
return (SIGNATURE + struct.pack(">I", 13) + chunk
+ struct.pack(">I", zlib.crc32(chunk) & 0xFFFFFFFF))
class HeaderBudgetTests(unittest.TestCase):
def test_dimensions_and_byte_count(self):
data = header() + b"trailing bytes are outside this narrow check"
info = inspect_png_header(data)
self.assertEqual((info.width, info.height, info.byte_count), (32, 24, len(data)))
def test_empty(self):
with self.assertRaisesRegex(ValueError, "header_too_short"):
inspect_png_header(b"")
def test_truncated_header(self):
with self.assertRaisesRegex(ValueError, "header_too_short"):
inspect_png_header(header()[:32])
def test_wrong_signature(self):
with self.assertRaisesRegex(ValueError, "not_png_signature"):
inspect_png_header(b"X" + header()[1:])
def test_first_chunk_must_be_ihdr(self):
data = header()
with self.assertRaisesRegex(ValueError, "expected_first_13_byte_IHDR"):
inspect_png_header(data[:12] + b"IDAT" + data[16:])
def test_ihdr_length(self):
data = header()
with self.assertRaisesRegex(ValueError, "expected_first_13_byte_IHDR"):
inspect_png_header(data[:8] + struct.pack(">I", 12) + data[12:])
def test_crc_mismatch(self):
data = header()
with self.assertRaisesRegex(ValueError, "IHDR_crc_mismatch"):
inspect_png_header(data[:-1] + bytes([data[-1] ^ 1]))
def test_zero_width(self):
with self.assertRaisesRegex(ValueError, "zero_dimension"):
inspect_png_header(header(0, 24))
def test_zero_height(self):
with self.assertRaisesRegex(ValueError, "zero_dimension"):
inspect_png_header(header(32, 0))
def test_byte_budget_exceeded(self):
with self.assertRaisesRegex(ValueError, "byte_budget_exceeded"):
inspect_png_header(header(), max_bytes=32)
def test_exact_byte_budget(self):
self.assertEqual(inspect_png_header(header(), max_bytes=33).byte_count, 33)
def test_pixel_budget_exceeded(self):
with self.assertRaisesRegex(ValueError, "pixel_budget_exceeded"):
inspect_png_header(header(32, 24), max_pixels=767)
def test_exact_pixel_budget(self):
self.assertEqual(inspect_png_header(header(), max_pixels=768).height, 24)
def test_invalid_limits(self):
for value in (0, -1, True, 1.5, "100"):
for key in ("max_bytes", "max_pixels"):
with self.subTest(value=value, key=key):
with self.assertRaises(ValueError):
inspect_png_header(header(), **{key: value})
def test_non_bytes(self):
with self.assertRaises(TypeError):
inspect_png_header(bytearray(header()))
def test_header_only_is_not_complete_image_validation(self):
# No IDAT or IEND exists. Passing is intentionally only a metadata result.
self.assertEqual(inspect_png_header(header()).width, 32)
def test_invalid_remainder_is_outside_contract(self):
data = header() + b"not a valid remaining PNG stream"
self.assertEqual(inspect_png_header(data).byte_count, len(data))
def test_returned_metadata_is_immutable(self):
info = inspect_png_header(header())
with self.assertRaises(FrozenInstanceError):
info.width = 999
if __name__ == "__main__":
unittest.main()
Run locally without sending an image anywhere
Run the tests from the directory containing the two files. For the CLI example, replace public-example.png with an explicitly authorized local PNG; that file is not supplied by this article. An exception identifies a failed local check. Successful JSON output should retain its metadata-only scope when copied into another note or workflow.
python -m unittest -v test_png_header_budget
python png_header_budget.py public-example.png
The command performs no network request, but that does not make every possible input appropriate to handle. Obtain the relevant permission before using a real photograph and minimize unnecessary collection. A header check cannot tell whether the pixels contain people, registration details, addresses, confidential material or copyrighted content. Cropping and reviewing an image are separate tasks; neither should be silently attributed to this parser.
Keep the handoff honest
When passing a result to another person, state which file was checked, which budgets were used and what the helper did not inspect. Do not turn header metadata passed into image approved. The destination service may still reject a file, and a visually acceptable concept may still be unsuitable for a real-world decision. Those outcomes do not contradict this small local result because they concern different contracts.
The useful engineering habit is to keep evidence attached to a clearly named operation. A narrow helper can remain small, testable and understandable when its limits travel with its output. Expanding its name to imply privacy, authenticity or physical suitability would make the surrounding workflow less reliable even if every line of the header parser continued to behave exactly as tested.
