On this page
Separate the four image layers
The source dates shown in this guide identify documentation checks on 22 October 2026, not original publication dates. Follow each citation for the Pillow module being discussed.
Record four distinct observations: pixel geometry, orientation intent, color intent, and metadata exposure. Pixel geometry includes stored width, height, mode, frame count, and whether the pixel array changed. Orientation intent is the EXIF Orientation tag, if present, and whether a consumer is expected to apply it. Color intent is mode, ICC profile presence and parse status, and documented source and target profiles. Metadata exposure is the category list, such as EXIF, GPS, XMP, comments, or application tags, without copying raw values into a report.
Pillow’s Pillow documentation, (opens in a new tab) documentation describes Image.getexif() as an EXIF mapping that can be read or changed and Image.info as file-handler information that may not carry into every new image. Treat those stores as different. A missing key is not proof that no metadata exists elsewhere in the container.
| Layer | Record | Do not infer |
|---|---|---|
| Pixels | Width, height, mode, frames, and pixel digest | That geometry expresses display orientation |
| EXIF orientation | Tag state and transform policy | That a viewer or derivative applied it |
| ICC profile | Presence, identity state, and parse result | That profile presence proves color accuracy |
| Metadata | Category state and exposure policy | That one mapping lists every container field |
| Derivative | New reference, transform, and retained source | That normalization overwrote the source safely |
Use a synthetic contract before opening sensitive images
A synthetic fixture makes the intended comparison unambiguous without copying a face, location, creator label, or camera value. Keep profile identity and GPS state explicit when they are unknown. Do not infer a transform from a number without applying the selected library or owner-approved policy.
Synthetic image metadata summary
{
"pixel_geometry": {"width": 1600, "height": 900, "mode": "RGB"},
"exif_orientation": 6,
"icc_profile": "present_but_profile_identity_unverified",
"metadata_categories": ["EXIF", "comment"],
"gps_value": "not_copied_into_report"
}The dimensions and tags are invented for this worksheet. Orientation value 6 is an observation to interpret with a library or an approved policy, not a reason to swap dimensions manually. The profile state says only that a profile is present and identity remains unverified. The safe output is a category and state, not a raw metadata dump.
If real images may contain sensitive content, start with a synthetic image, controlled metadata summary, or owner-approved derivative. This preparation does not establish ownership, permission, visual fidelity, privacy clearance, buyer demand, pricing, or legal clearance.
Inspect orientation without losing source evidence
Pillow’s ImageOps.exif_transpose() applies the EXIF orientation to a copy when the tag is not 1 and removes the orientation data from that transposed result Pillow documentation, (opens in a new tab). Its in_place option controls whether the original image is modified. That makes it useful for a deliberate normalized derivative, but it does not mean the original pixels were corrected in place.
Bounded orientation and profile observation
from PIL import ImageOps
def inspect_image(image, max_width=10_000, max_height=10_000, max_pixels=100_000_000):
width, height = image.size
if (
width <= 0
or height <= 0
or width > max_width
or height > max_height
or width * height > max_pixels
):
raise ValueError("image_dimension_limit_reached")
exif = image.getexif()
profile_bytes = image.info.get("icc_profile")
categories = {"exif": bool(exif), "icc_profile": isinstance(profile_bytes, bytes)}
orientation = exif.get(274) # EXIF Orientation tag
normalized = ImageOps.exif_transpose(image, in_place=False)
return {
"size_before": image.size,
"size_after_orientation": normalized.size,
"mode": image.mode,
"orientation_tag": orientation,
"metadata_categories_present": categories,
"normalized_is_copy": normalized is not image,
}The example checks width, height, and pixel count before calling ImageOps.exif_transpose; an oversized or empty fixture returns image_dimension_limit_reached before metadata or pixel work. The example reports booleans and dimensions, not a filename, EXIF value dump, or image pixels. If orientation is unknown or malformed, retain the source and record that state. If a normalized derivative is approved, save it under a new artifact reference and record that orientation was applied and removed. Do not overwrite the only source merely to make a viewer look upright.
| Observation | Safe interpretation | Next action |
|---|---|---|
| Orientation tag absent | No EXIF orientation was observed in the inspected mapping | Compare pixels with source notes; do not assume upright |
| Orientation tag present | A display transform may be expected | Test a synthetic or approved copy and record derivative behavior |
| Normalized dimensions change | The chosen transform changed geometry | Preserve source and derivative references separately |
| Unknown or malformed tag | Orientation intent is unresolved | Hold the source and request a documented policy |
Treat ICC profiles and metadata as policy inputs
Pillow’s Pillow documentation, (opens in a new tab) module provides LittleCMS2-backed profile management and can build or apply transforms between named input and output profiles. A profile’s presence says that a color-management input is available; it does not prove that the profile describes the pixels correctly, that a viewing environment is calibrated, or that two displays will match.
Before a conversion, record source profile state, target profile, image mode, rendering intent, transform result, and derivative reference. If any is unknown, classify the conversion as not tested. A profile conversion can change pixel values and should never be reported as metadata-only. Do not silently assume sRGB for every missing profile; if an owner chooses a fallback, label it as a decision and derivative.
| Observation | Safe interpretation | Next action |
|---|---|---|
| ICC profile present | A profile is available for a color workflow | Identify and validate source and target before conversion |
| ICC profile missing | Profile-based conversion is not established | Ask for source color context or record unknown |
| EXIF or comment category present | Non-pixel information exists | Apply approved exposure policy without copying values |
| GPS category present | Location information may be present | Hold for owner-approved handling; do not publish coordinates |
| No listed category observed | Selected inspection found none | Do not claim every container field is absent |
Metadata removal is not automatically safe or correct. A creator may need a copyright or capture field, while a public derivative may need narrower exposure. Name the policy and fields affected without reproducing sensitive values.
Keep diagnostics safe and the next step qualified
A public report can contain pixel dimensions, mode, orientation state, profile presence, bounded metadata categories, derivative relation, and tool version. It should not contain GPS coordinates, camera serial numbers, creator labels, private paths, faces, or raw image bytes. A category count is safer than a value dump, but it is not a privacy guarantee.
Pair this check with the text and encoding checks and data provenance log. Those resources own byte and source evidence; this guide owns image geometry, display intent, profile state, and metadata exposure observations.
After the owner has a supported non-health scope, authority to describe the images, and a metadata or synthetic review packet, the qualified appraisal request path may be a next preparation step. It does not validate orientation, certify color accuracy, scrub metadata, produce a quote, match a buyer, issue a legal opinion, or grant a license. Keep raw images outside this guide and within the owner-approved handling boundary.
Takeaways
- Keep pixel geometry, EXIF orientation, ICC profile state, and metadata exposure as separate fields.
- Use ImageOps.exif_transpose for an explicit derivative and preserve the source rather than silently overwriting it.
- Treat ICC profiles as inputs to a documented color-management transform, not proof of color accuracy.
- Report metadata categories and policy decisions without copying GPS, creator, device, or other raw values.
- Keep structural observations separate from visual, privacy, rights, and ownership conclusions.