# Check Display Dimensions Before Queuing a Social Image

A hypothetical publishing brief calls for a portrait image. The file inspector reports a wider-than-tall pixel grid, while a preview shows the photo standing upright. Someone rotates the file by hand to fix the mismatch, and the next viewer rotates it again.

The missing detail is orientation. Encoded dimensions and the dimensions of an orientation-aware rendering can be different. A publishing workflow needs to say which representation it is checking before it decides that an image fits the brief.

## Inspect both representations

For a small preflight report, keep four properties together: the detected image format, the encoded dimensions, the EXIF orientation value and the dimensions after applying that orientation.

Do not infer these properties from a filename. A name such as `portrait-final.jpg` records an intention; it does not establish the decoder's output or the way a viewer will present it.

Pillow provides [ImageOps.exif_transpose](https://pillow.readthedocs.io/en/stable/reference/ImageOps.html#PIL.ImageOps.exif_transpose), which applies the orientation instruction and removes it from the resulting image. Its default returns a new image, so an inspector can examine that representation while preserving the original input bytes.

## A narrow preflight example

This example accepts one-frame JPEG or PNG data. The byte and pixel budgets are illustrative engineering choices, not social-platform limits or SMTasker settings. The function reports properties; it does not rewrite the input file or certify an entire upload pipeline.

```python
from io import BytesIO
from PIL import Image, ImageOps

MAX_BYTES = 8_000_000
MAX_PIXELS = 12_000_000


def inspect_still_image(blob):
    if not blob or len(blob) > MAX_BYTES:
        raise ValueError("Outside this example's byte budget")
    with Image.open(BytesIO(blob)) as image:
        kind = image.format
        if kind not in {"JPEG", "PNG"}:
            raise ValueError("This example accepts JPEG or PNG only")
        if getattr(image, "n_frames", 1) != 1:
            raise ValueError("This example accepts one frame only")
        if image.width * image.height > MAX_PIXELS:
            raise ValueError("Outside this example's pixel budget")
        orientation = image.getexif().get(274, 1)
        if type(orientation) is not int or orientation not in range(1, 9):
            raise ValueError("Unexpected EXIF orientation")
        encoded_size = image.size
        image.load()
        with ImageOps.exif_transpose(image) as display:
            display_size = display.size
    return {
        "format": kind,
        "encoded_size": encoded_size,
        "display_size": display_size,
        "orientation": orientation,
    }
```

The EXIF Orientation tag identifier is `274`. An absent tag is treated as the ordinary orientation in this example. An unexpected value is reported as an error instead of being guessed around.

Calling `Image.open` alone does not establish that all image data has decoded. Pillow documents its [lazy loading behavior](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.open); this helper calls `load()` before reporting success. Decoder failures should reach the caller's review path rather than become a green preflight result.

The format and frame checks deliberately keep the example about still images. Supporting animation is a separate contract, with questions about frames and duration that this helper does not answer.

## Use a fixture that exposes the mismatch

In the local check, a synthetic JPEG contained an 80-by-40 pixel grid and orientation value `6`. The result was:

```python
{
    "format": "JPEG",
    "encoded_size": (80, 40),
    "display_size": (40, 80),
    "orientation": 6,
}
```

These are tiny test-fixture dimensions, not a recommendation for publishing resolution. They make it easy to see which pair of dimensions a rule is using.

Dimensions are also an incomplete visual check. A mirror operation or a half turn can preserve width and height. Seeing the same numbers in both fields therefore does not establish that the pixels have the same presentation. Review an orientation-aware thumbnail, not just an aspect-ratio label.

## Make preview and execution agree

The inspection result does not make another program honor orientation metadata. Decide how the rest of the pipeline handles the asset.

One option is to retain the original and ensure that the preview and the execution path interpret it consistently. Another is to produce a derived asset with the orientation applied to its pixels, then use that same derived asset for review and execution. Either choice needs a clear owner.

Do not apply a manual rotation and then leave an instruction that makes the next step repeat it. Similarly, do not discard orientation metadata before deciding whether its transformation must first be applied.

Cropping, resizing, color handling and metadata removal need their own explicit decisions. A successful orientation check does not choose a crop, establish the right export format for a destination, or remove all private metadata.

## What the local checks established

The example was executed with the already available Pillow 12.3.0. Eight checks covered JPEG and PNG without an orientation tag; all eight orientation values; corrupt and truncated input; byte and pixel budgets; an unsupported format; a multi-frame PNG; an unexpected orientation; and a PNG whose header identifies correctly but whose pixel stream fails to decode.

That verifies the helper against those fixtures. Keep the decoder maintained, choose resource budgets for the actual service, and test the behavior in the preview and worker you deploy. A production service still needs controls around uploads, decoding resources and failures beyond this small inspection function.

## Applying the question to a social workflow

This article is published by the official [SMTasker](https://smtasker.com/) account. Its [feature overview](https://smtasker.com/features/) describes preparing photos, videos and captions for supported social workflows, with execution through connected Android devices and a Windows or Mac client.

The Python helper is an illustrative design pattern. It does not describe SMTasker's internal media processing or claim a native EXIF preflight feature.

Before your next image enters a publishing queue, compare the encoded dimensions, the orientation-aware preview and the representation the worker will actually use. Resolve a disagreement at that boundary while the image is still easy to review.
