Skip to content

fix: letterbox image to exact target size when fitscreen is false - #175

Open
kjames2001 wants to merge 1 commit into
HASwitchPlate:mainfrom
kjames2001:fix/letterbox-fitscreen-false
Open

fix: letterbox image to exact target size when fitscreen is false#175
kjames2001 wants to merge 1 commit into
HASwitchPlate:mainfrom
kjames2001:fix/letterbox-fitscreen-false

Conversation

@kjames2001

Copy link
Copy Markdown

Problem

When push_image is called with fitscreen false (the default) and the
source image's aspect ratio differs from the requested width/height,
image_to_rgb565 uses PIL.Image.thumbnail(), which preserves aspect
ratio and returns an image smaller than the requested box.

Example: a square 512x512 cover pushed into a 400x160 object is
thumbnail-scaled to 160x160, not 400x160.

The plate decodes the RGB565 payload using the width stored in the
header as the row stride. A pushed image narrower than the object box
therefore renders doubled / split (the top of the image repeated,
second copy cut off — a "1.5 image") instead of centered. 16:9 sources
into 16:9 boxes are unaffected, which is why cameras usually look fine
while square covers glitch.

Fix

After thumbnail(), paste the result onto a black canvas at the exact
target size (centered). The pushed width now always matches the object
width, which is what the plate's decoder expects.

  • Sources smaller than the box keep the existing no-upscale behaviour
    (the min() clamp is unchanged; output identical to before).
  • The fitscreen=True path (ImageOps.fit) is untouched.

Verification

  • Functional test of image_to_rgb565 across: square->wide box,
    16:9->16:9 box (196x110 / 400x160 / 480x270), small source, exact
    size, RGBA source, and the fitscreen path — all outputs carry the
    expected width/height header.
  • Verified on a real 0.7.9 installation (openHASP 0.7.0-rc12 plate,
    480x480): the doubled image no longer appears; the rendered box is
    pixel-identical to the expected letterboxed frame (max channel diff 5).
  • black --check clean.

image_to_rgb565 with fitscreen=False used only PIL thumbnail(), which
preserves aspect ratio and returns an image smaller than the requested
box whenever the source aspect differs from the box (e.g. a square cover
pushed into a wide 400x160 object).

The plate decodes the RGB565 payload using the width in the header as
the row stride, so a pushed image narrower than the object box renders
doubled/split (a '1.5 image') instead of centered.

Letterbox the thumbnail onto a black canvas at the exact target size so
the pushed width always matches the object width. Sources smaller than
the box keep the existing no-upscale behaviour (unchanged output).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants