Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

Feature request: trim transparent borders of PNG images (single & batch, in-place)

Đã đóng
#332 6 bình luận 0 reaction 2 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

@cre8ive-marketing đang làm issue này rồi.

Từ ngày 22/10/2026.

  • #481 của @cre8ive-marketing — đã merge

Đánh giá

Issue này chưa được đánh giá.

Mô tả

enhancement

What would you like File to do?
Add a "Trim transparent borders" action for PNG images:

  • Runs on a single selected PNG, or on all PNGs inside a selected folder (with an optional "include subfolders" toggle)
  • Crops away the fully-transparent padding around the visible content and overwrites the file in place
  • Shows a brief summary afterwards: how many cropped / skipped (and why) / failed
  • Ideally also exposed on the command line (e.g. file --trim-png [-r]) so it can be scripted
    Scope suggestion: PNG only. WebP with alpha would be a nice bonus; JPEG can be left out since it has no alpha channel.
    Why / when would you use it?
    PNGs exported from Photoshop, Figma, slicing tools or renderers almost always carry a large transparent margin. Once such a file lands in a document, a web page or a UI mockup, the image box no longer matches the visible content, so you end up re-aligning and cropping by hand — one file at a time.
    My own case: I process dozens of product-render PNGs every day, and right now I depend on a separate standalone utility — one that registers its own Explorer context-menu entry — purely for this single action. It is by far the most frequent reason I have to leave File, so having it built in would remove an entire tool from my machine.
    Ideas for how it could work? (optional — engine or library suggestions welcome)
    The core is roughly 40 lines of image code and needs no new heavyweight dependency.
    Algorithm:
  1. Load the PNG and obtain its alpha channel.
  2. Threshold the alpha first — treat alpha < 8 as fully transparent. Using alpha != 0 looks simpler but fails in practice: one stray pixel with alpha = 1 on the border makes the bounding box collapse to the whole canvas, so the image "cannot be trimmed" and the user concludes the feature is broken.
  3. Compute the bounding box of the thresholded alpha.
  4. bbox empty → fully transparent, skip. bbox == full canvas → nothing to trim, skip (and do not rewrite the file).
  5. Crop to bbox.
    Four pitfalls worth handling up front — all of them show up in real asset folders:
  • Indexed / palette PNGs (8-bit P mode with a tRNS transparency chunk) have no separate alpha channel, so a naive "does it have an alpha band?" check classifies them as no transparency and silently skips them. Check the tRNS / transparency metadata, or convert to RGBA before testing.
  • Metadata: preserve DPI and ICC profile when saving. Dropping DPI turns a 300 DPI asset into 96 DPI, which is a real problem for print and design handoff.
  • Write atomically: never save() straight onto the original path — it truncates the file first, so a crash, a full disk or a power loss destroys the original image. Write to a temp file in the same directory, then rename over it. An optional "keep a copy in ./.backup" toggle is welcome.
  • Leave untouched files untouched: skipping no-op rewrites keeps mtimes stable, which matters for sync tools and backup software.
    One UX detail: if the action runs on a folder and everything gets skipped, say so explicitly in the summary. Silence reads as a bug report waiting to happen.
    Reference implementation (Python + Pillow):
    import os
    from PIL import Image

def trim_png(path, thresh=8):
with Image.open(path) as im:
im.load()
info = dict(im.info)

    # 1. resolve alpha, including palette images with a tRNS chunk
    if im.mode == 'P':
        if 'transparency' not in info:
            return 'skip: no alpha'
        im = im.convert('RGBA')
    elif 'A' in im.getbands():
        im = im if im.mode == 'RGBA' else im.convert('RGBA')
    else:
        return 'skip: no alpha'

    # 2. threshold: ignore near-invisible noise pixels
    mask = im.split()[-1].point(lambda v: 255 if v >= thresh else 0)

    # 3/4. bounding box
    bbox = mask.getbbox()
    if bbox is None:
        return 'skip: fully transparent'
    if bbox == (0, 0, im.width, im.height):
        return 'skip: nothing to trim'

    # 5. crop, keeping DPI and colour profile
    out = im.crop(bbox)
    kw = {'format': 'PNG', 'optimize': True}
    if info.get('dpi'):
        kw['dpi'] = info['dpi']
    if info.get('icc_profile'):
        kw['icc_profile'] = info['icc_profile']

    tmp = path + '.tmp'          # same directory -> same volume
    out.save(tmp, **kw)
    os.replace(tmp, path)        # atomic on Windows and POSIX

return 'ok: %dx%d -> %dx%d' % (im.width, im.height, out.width, out.height)

Happy to send a PR if the direction sounds right.

Ngôn ngữ chính
C#
Star
3.6k
Fork
192
Merge trung bình
5 giờ 40 phút
Pull request đã merge (30 ngày)
210

Chuẩn bị môi trường

Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của KnifeLemon/Filee

Tất cả issue của KnifeLemon/Filee

Issue tương tự

Thêm issue về C#

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.