Skip to content

Add htop-logo.png as the README header#1983

Open
corygabrielsen wants to merge 1 commit intohtop-dev:mainfrom
corygabrielsen:htop-wordmark-icons
Open

Add htop-logo.png as the README header#1983
corygabrielsen wants to merge 1 commit intohtop-dev:mainfrom
corygabrielsen:htop-wordmark-icons

Conversation

@corygabrielsen
Copy link
Copy Markdown

@corygabrielsen corygabrielsen commented May 5, 2026

Motivation

The README's top-of-page logo links to htop.png, which currently renders as a stylized "H" — while htop.dev and the other htop logo assets (htop-logo.png, htop-small.png, htop.ico) all use the full HTOP wordmark.

Rather than touch the application icon files (htop.png, htop.svg) — which are installed by Makefile.am as pixmap_DATA and appicon_DATA and may be the bare "H" by intent — this PR isolates the change to the README. The application icons stay as-is.

Changes

What this PR does NOT change

  • htop.png and htop.svg (the installed app icons) — untouched.
  • Makefile.am — untouched. htop-logo.png is a README-only asset, not installed. This matches the existing pattern for docs/images/screenshot.png, which is also referenced from the README and not in EXTRA_DIST.
  • htop.desktop — untouched.

Scope

This patch addresses one decision: which image to use at the top of the README. A separate question — whether to also include an htop-logo.svg in the source repository — is discussed in the PR comments without affecting this patch.

Licensing & AI disclosure

  • htop-logo.png is htop-dev's own asset; license remains GPL-2.0+.
  • AI assistance was used while preparing this PR; disclosed via the Assisted-by: trailer in the commit per CONTRIBUTING.md's "Use of AI" section.

@Explorer09
Copy link
Copy Markdown
Contributor

Please keep the icons htop.png and htop.svg. They are required for depicting htop in desktop environments' menus. You didn't know what you are deleting and Claude gave you the wrong solution.

@corygabrielsen
Copy link
Copy Markdown
Author

Hi @Explorer09, thank you for your remarks.

From the outside this looks unintentional — the README, the website, and the other assets are all consistent with each other but disagree with the in-repo icons. That said, there may well be a reason for the bare "H" that I'm not aware of: an intentional square-friendly app-icon treatment, continuity with something I haven't found, or context I'm missing as a newcomer. If the bare "H" was intentional for a context I'm missing, it can live under a different filename alongside the wordmark — let me know.

@Explorer09
Copy link
Copy Markdown
Contributor

Hi @Explorer09, thank you for your remarks.

From the outside this looks unintentional — the README, the website, and the other assets are all consistent with each other but disagree with the in-repo icons. That said, there may well be a reason for the bare "H" that I'm not aware of: an intentional square-friendly app-icon treatment, continuity with something I haven't found, or context I'm missing as a newcomer. If the bare "H" was intentional for a context I'm missing, it can live under a different filename alongside the wordmark — let me know.

Who is this "I" within the quoted text? You or the Claude AI?

@corygabrielsen
Copy link
Copy Markdown
Author

My name is Cory Gabrielsen. Your README is inaccurate and has been for four years. I wrote code to fix it. Do you want to help me merge it or do you want to chastise me?

@Explorer09
Copy link
Copy Markdown
Contributor

My name is Cory Gabrielsen. Your README is inaccurate and has been for four years. I wrote code to fix it. Do you want to help me merge it or do you want to chastise me?

What inaccuracy are you referring to?

@corygabrielsen
Copy link
Copy Markdown
Author

Hi @Explorer09 . All of the information has been written clearly. Please let me know what is confusing you. I do not know how to answer such questions that I have already written an answer for in the pull request.

Motivation

The top of the README links to htop.png as the project's logo, but that file currently renders as a stylized "H" — while htop.dev and the other htop logo assets (htop-logo.png, htop-small.png, htop.ico) all use the full HTOP wordmark. The icons installed by Makefile.am (htop.png, htop.svg) appear to be the only place the project's branding diverges from "HTOP".

Please advise, thank you.

@corygabrielsen
Copy link
Copy Markdown
Author

Before After
image image

@corygabrielsen
Copy link
Copy Markdown
Author

If the bare "H" was intentional for a context I'm missing, it can live under a different filename alongside the wordmark — let me know.

Please advise.

@Explorer09
Copy link
Copy Markdown
Contributor

Hi @Explorer09 . All of the information has been written clearly. Please let me know what is confusing you. I do not know how to answer such questions that I have already written an answer for in the pull request.

Motivation

The top of the README links to htop.png as the project's logo, but that file currently renders as a stylized "H" — while htop.dev and the other htop logo assets (htop-logo.png, htop-small.png, htop.ico) all use the full HTOP wordmark. The icons installed by Makefile.am (htop.png, htop.svg) appear to be the only place the project's branding diverges from "HTOP".

Please advise, thank you.

In the Makefile.am file:

pixmapdir = $(datadir)/pixmaps
pixmap_DATA = htop.png
appicondir = $(datadir)/icons/hicolor/scalable/apps
appicon_DATA = htop.svg

Yes. The filenames are not arbitrary or useless. When you replaced the icon with the banner, you are going to break the display of the htop app icons in desktop environments.

That's why I said to leave the files alone. If you want a logo in the README, make it a separate filename such as htop-logo.svg.

@corygabrielsen corygabrielsen force-pushed the htop-wordmark-icons branch from 861ef66 to 8e76170 Compare May 5, 2026 13:49
@corygabrielsen
Copy link
Copy Markdown
Author

Please keep the icons htop.png and htop.svg. They are required for depicting htop in desktop environments' menus. You didn't know what you are deleting and Claude gave you the wrong solution.

I reverted changes to htop.png and htop.svg in favor of adding a new htop-readme.svg.

This strikes me as a bit odd, but let me know if you would prefer a different filename or to overwrite a different file.

I am only trying to update the README.

@corygabrielsen corygabrielsen force-pushed the htop-wordmark-icons branch from 8e76170 to 9aa3df6 Compare May 5, 2026 13:52
Comment thread README.md Outdated
@corygabrielsen corygabrielsen force-pushed the htop-wordmark-icons branch from 9aa3df6 to c661cd7 Compare May 5, 2026 13:53
@corygabrielsen
Copy link
Copy Markdown
Author

That's why I said to leave the files alone. If you want a logo in the README, make it a separate filename such as htop-logo.svg.

I renamed the file to htop-logo.svg per suggestion.

@corygabrielsen corygabrielsen force-pushed the htop-wordmark-icons branch from c661cd7 to a00be4c Compare May 5, 2026 13:57
@corygabrielsen corygabrielsen changed the title Use full HTOP wordmark in icon files Add htop-logo.svg as the README header May 5, 2026
@corygabrielsen
Copy link
Copy Markdown
Author

I think it's ready. Let me know if you want any further changes.

@corygabrielsen corygabrielsen requested a review from Explorer09 May 5, 2026 13:59
@Explorer09
Copy link
Copy Markdown
Contributor

Two minor questions, which I think I'd let the maintainers to decide. I'm just a contributor and cannot make these decisions:

  • Whether the width="100%" attribute is necessary in the <img> tag of the logo.
  • Whether the logo SVG file should reside in the top directory, or in the doc/ subdirectory.

@natoscott
Copy link
Copy Markdown
Member

@corygabrielsen thanks for your contribution.

I think you're on the right track - I agree that the README rendering can be improved as you say, and made consistent here with the htop.dev website at the same time.

Do you want to help me merge it or do you want to chastise me?

Don't worry about him - he's a terrible communicator, seems to quickly forget previous warnings, and is particularly triggered by any use of AI (so he's having a bad day every day now - explains his poor attitude I guess).

@BenBE created these files originally and I'm sure will take a closer look when time becomes available. htop-logo.svg is a good name to use - it matches the htop-logo.png file in the website git repo; for some reason the original full-word svg doesn't seem to be committed there though, perhaps @BenBE still has a copy of that file somewhere?

@corygabrielsen
Copy link
Copy Markdown
Author

corygabrielsen commented May 5, 2026

@natoscott @BenBE — surfacing the provenance of htop-logo.svg: I generated it from the canonical htop-logo.png (the wordmark on htop.dev) using a small Python script. The script reads which bars are lit per letter directly from the PNG, then emits an SVG using the gradient stops, bracket geometry, and Gaussian-blur filter that already live in htop.svg. Nothing aesthetic was invented for this PR — just the layout extracted from the PNG.

Reproducible byte-for-byte:

$ python3 svg_from_png.py htop-logo.png > regen.svg
$ sha256sum regen.svg htop-logo.svg
0eb0e1aa98349c66249a4485682b028dd7a19b6dea97d7d46b3bfc27f406aa30  regen.svg
0eb0e1aa98349c66249a4485682b028dd7a19b6dea97d7d46b3bfc27f406aa30  htop-logo.svg

If you'd rather use a different vector master (yours, @BenBE), drop it in and the script becomes superfluous. This is just a clean record of how this one was built — happy to delete, move under docs/, or commit it in-tree if you'd like.

svg_from_png.py
#!/usr/bin/env python3
"""
svg_from_png.py — Reconstruct htop-logo.svg from htop-logo.png.

Reads the canonical 486x86 wordmark PNG (the htop logo on htop.dev) and
emits an SVG that renders to the same wordmark.

Provenance:
- The 4-stop linear gradients (green/red/grey-bracket) are the same stops
  htop's existing application icon (htop.svg) uses. They are not invented
  here.
- The bracket geometry (10x26 outer rect with a 4x18 cutout) is also the
  shape used by htop.svg, just laid out at the canvas edges.
- The Gaussian blur filter (stdDeviation=0.4) provides the same
  "phosphor glow" softening already present on htop.svg's bars, scaled
  to this canvas.
- The only data extracted from htop-logo.png is the bar mask: which of
  the 9 columns x 3 rows per letter are lit, and whether each is green
  or red. Everything else is fixed by htop's existing visual vocabulary.

Run with the path to the canonical PNG. Output is the SVG on stdout:

    python3 svg_from_png.py htop-logo.png > htop-logo.svg

Reproducing the file committed in this PR:

    python3 svg_from_png.py htop-logo.png | diff -u - htop-logo.svg
    # (no output -> byte-for-byte match)
"""

import sys
from PIL import Image

# ---- Layout, derived directly from the canonical 486x86 PNG ----------------

# Each letter is a 9-column x 3-row grid of 6px-wide bars on a 12px stride.
# Letters start at x=12, 132, 252, 372 (a 120px stride between letter starts;
# 108px of letter content + a 12px inter-letter gutter).
LETTERS = ("H", "T", "O", "P")
LETTER_X = {"H": 12, "T": 132, "O": 252, "P": 372}

# The three meter rows. Each row's bars span 26px vertically; rows are
# separated by 4px gutters at y=26..30 and y=56..60.
ROW_Y = ((0, 26), (30, 56), (60, 86))

BAR_W = 6
COL_STRIDE = 12
N_COLS = 9

# Brackets sit at the very left and right of the canvas. They are drawn as
# 10x26 outer rectangles with a 4x18 inner cutout (even-odd fill).
BRACKET_LEFT_X = 0
BRACKET_RIGHT_X = 476
BRACKET_GRADIENT_LEFT_X = 5    # gradient sample x (center of the 10px-wide bracket)
BRACKET_GRADIENT_RIGHT_X = 481

# ---- Colour palette: htop's existing icon vocabulary -----------------------
# Stops, offsets, and IDs match htop's existing htop.svg verbatim.
GRADIENT_TEMPLATES = (
    ("a", (("#8bf18b", "0"), ("#5bc15b", ".2"), ("#47a347", ".8"), ("#177317", "1"))),
    ("b", (("#fe7f7f", "0"), ("#ce4f4f", ".2"), ("#b23030", ".8"), ("#920000", "1"))),
    ("c", (("#363d36", "0"), ("#565d56", ".2"), ("#6c766c", ".8"), ("#8c968c", "1"))),
)

# ---- Reading the PNG -------------------------------------------------------

def classify(rgba):
    """Classify one sampled pixel as 'G' (green bar), 'R' (red), or '-' (empty).

    Bars in the canonical PNG are saturated phosphor green (G channel
    dominant) or saturated red (R channel dominant). Background is
    transparent.
    """
    r, g, b, a = rgba
    if a < 128:
        return "-"
    if g > r and g > 100:
        return "G"
    if r > g and r > 100:
        return "R"
    return "-"


def extract_bars(png_path):
    """Sample the canonical PNG and return the lit bars in canonical order.

    Iteration order is letter (H, T, O, P), then row (top, mid, bot), then
    column (0..8). Empty cells are skipped. Each entry is
    (letter, row_idx, col, color).
    """
    img = Image.open(png_path).convert("RGBA")
    if img.size != (486, 86):
        raise SystemExit(f"expected 486x86 PNG, got {img.size}")

    bars = []
    for letter in LETTERS:
        x_off = LETTER_X[letter]
        for row_idx, (y_top, y_bot) in enumerate(ROW_Y):
            y_mid = (y_top + y_bot) // 2
            for col in range(N_COLS):
                x_mid = x_off + col * COL_STRIDE + BAR_W // 2
                cls = classify(img.getpixel((x_mid, y_mid)))
                if cls != "-":
                    bars.append((letter, row_idx, col, cls))
    return bars


# ---- Emitting the SVG ------------------------------------------------------

def emit_svg(bars):
    """Render the SVG. Layout matches the file committed in this PR exactly."""
    lines = []

    lines.append('<?xml version="1.0" encoding="UTF-8"?>')
    lines.append('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 486 86">')
    lines.append(" <defs>")

    # 3 colour-stop templates (a=green, b=red, c=grey-bracket) — same as htop.svg.
    for tid, stops in GRADIENT_TEMPLATES:
        lines.append(f'  <linearGradient id="{tid}">')
        for color, offset in stops:
            lines.append(f'   <stop stop-color="{color}" offset="{offset}"/>')
        lines.append("  </linearGradient>")

    # Soft phosphor-glow filter — same primitive as htop.svg, scaled to this canvas.
    lines.append('  <filter id="f" x="-.05" y="-.05" width="1.1" height="1.1" color-interpolation-filters="sRGB">')
    lines.append('   <feGaussianBlur stdDeviation="0.4"/>')
    lines.append("  </filter>")

    # One gradient instance per lit bar, positioned vertically over the bar.
    bar_gradients = []  # (gid, bar_x, y_top, y_bot, template_id)
    gid = 1
    for letter, row_idx, col, color in bars:
        bar_x = LETTER_X[letter] + col * COL_STRIDE
        y_top, y_bot = ROW_Y[row_idx]
        x_center = bar_x + BAR_W // 2
        template = "a" if color == "G" else "b"
        bar_gradients.append((gid, bar_x, y_top, y_bot, template))
        lines.append(
            f'  <linearGradient id="g{gid}" x1="{x_center}" x2="{x_center}" '
            f'y1="{y_top}" y2="{y_bot}" gradientUnits="userSpaceOnUse" xlink:href="#{template}"/>'
        )
        gid += 1

    # Bracket gradients: one per bracket per row (six total).
    bracket_gradients = []  # (gid, y_top, y_bot, side)
    for row_idx, (y_top, y_bot) in enumerate(ROW_Y):
        for x_center in (BRACKET_GRADIENT_LEFT_X, BRACKET_GRADIENT_RIGHT_X):
            bracket_gradients.append((gid, y_top, y_bot, x_center))
            lines.append(
                f'  <linearGradient id="g{gid}" x1="{x_center}" x2="{x_center}" '
                f'y1="{y_top}" y2="{y_bot}" gradientUnits="userSpaceOnUse" xlink:href="#c"/>'
            )
            gid += 1

    lines.append(" </defs>")
    lines.append(' <g fill-rule="evenodd">')

    # Bracket paths: 6 total, ordered by row (top L, top R, mid L, mid R, bot L, bot R).
    for (g_bid, y_top, y_bot, x_center) in bracket_gradients:
        if x_center == BRACKET_GRADIENT_LEFT_X:
            d = f"M{BRACKET_LEFT_X},{y_top} h10 v26 h-10 z M6,{y_top + 4} v18 h4 v-18 z"
        else:
            d = f"M{BRACKET_RIGHT_X},{y_top} h10 v26 h-10 z M{BRACKET_RIGHT_X},{y_top + 4} v18 h4 v-18 z"
        lines.append(
            f'  <path d="{d}" fill="url(#g{g_bid})" fill-rule="evenodd" filter="url(#f)"/>'
        )

    # Bar rects: 81 total, in the same order as the bar gradients.
    for (g_bid, bar_x, y_top, y_bot, _template) in bar_gradients:
        lines.append(
            f'  <rect x="{bar_x}" y="{y_top}" width="{BAR_W}" height="26" '
            f'fill="url(#g{g_bid})" filter="url(#f)"/>'
        )

    lines.append(" </g>")
    lines.append("</svg>")

    return "\n".join(lines) + "\n"


def main():
    if len(sys.argv) != 2:
        print(f"usage: {sys.argv[0]} <htop-logo.png>", file=sys.stderr)
        sys.exit(1)
    bars = extract_bars(sys.argv[1])
    sys.stdout.write(emit_svg(bars))


if __name__ == "__main__":
    main()

I don't think the script should be committed. It's one prompt away and the provenance is here in PR.

@corygabrielsen
Copy link
Copy Markdown
Author

@corygabrielsen thanks for your contribution.

happy to help hello from LA

@BenBE
Copy link
Copy Markdown
Member

BenBE commented May 5, 2026

@BenBE created these files originally and I'm sure will take a closer look when time becomes available. htop-logo.svg is a good name to use - it matches the htop-logo.png file in the website git repo; for some reason the original full-word svg doesn't seem to be committed there though, perhaps @BenBE still has a copy of that file somewhere?

Yes and no. The original files (available here in the repo) are still the ones created by @hishamhm – when I did some stickers a while back I took these files and hand-crafted some streamlined versions (that are not public).

Looking into our resources repo (and the website) I only can find the variant with the H only right now and I doubt that I've seen a SVG of the full htop text. Thus for the full text variant one would need to create a SVG version, which is complicated by the way the gradient was done in the original.

@BenBE
Copy link
Copy Markdown
Member

BenBE commented May 5, 2026

@corygabrielsen Does your script survive the PNG rendering full circle? I.e. given the original PNG, would the SVG when rendered be identical (regarding the pixels + alpha)?

@Explorer09
Copy link
Copy Markdown
Contributor

surfacing the provenance of htop-logo.svg: I generated it from the canonical htop-logo.png (the wordmark on htop.dev) using a small Python script. The script reads which bars are lit per letter directly from the PNG, then emits an SVG using the gradient stops, bracket geometry, and Gaussian-blur filter that already live in htop.svg. Nothing aesthetic was invented for this PR — just the layout extracted from the PNG.

If this SVG is not original but "traced" from a PNG, then it could be a better idea to just use the PNG. Because, (1) the PNG could be smaller in file size, and (2) you would need a hard time tuning the SVG to make it pixel-by-pixel identical to the PNG if rendered in the same resolution.

My concern here is whether we want to use this "traced" logo to be the new, official logo or whether we should use the PNG as the official one. Once this image is in the repository, we should expect that downstream forks may modify it. The file should be the "preferred form of the work for making modifications to it" (according to the GPL license text). A "traced" SVG image might not meet this requirement, and thus it might not be worth it for including in the repository (comparing to PNG).

@Explorer09
Copy link
Copy Markdown
Contributor

Don't worry about him - he's a terrible communicator, seems to quickly forget previous warnings, and is particularly triggered by any use of AI (so he's having a bad day every day now - explains his poor attitude I guess).

I didn't get appreciated. Objective fact: The original version of this PR suggested replacing the htop.png and htop.svg icons with the banner logos. While the README was indeed wrong to say that the icon is a "logo", the suggestion of replacing images would break the htop icon display in desktop environments.

As the patch was obviously wrong, I replied to keep the two images (htop.png and htop.svg) alone. (The icon file names are sensitive; we can't change them, see Icon Theme Specification.)

If the submitter (@corygabrielsen) studied carefully about the context (including how icons in desktop environments work), they shouldn't make such a mistake. The PR looked like someone rushed to contribute in order to make a name in the project -- until another person tells them that they could mess up. Please understand this is not about AI, but people who try to contribute without caring quality.

@BenBE
Copy link
Copy Markdown
Member

BenBE commented May 5, 2026

@Explorer09 If you can't take subtle hints, let me write this in plain words, so you can understand:

I don’t recall anyone mentioning cake, so I’m not sure why the crumbs keep talking.

Instead of helping you are currently creating just noise and distraction. So if you could please stop causing distractions to people who actually work on a solution, it would be much appreciated.

At the moment there are I think primarily three people who can potentially add to this: That'd be @corygabrielsen (that's why I asked them), @hishamhm (who might know about the origins of the original PNG file or if there's some [vector] master somewhere), and me (having worked on the streamlined logo variants).

Okay, now back on topic. The original logo (can also be seen in the hires variant in the repo with just the H) is not exact integer multiples. In particular there's some weird transform matrix applied that shifts things slightly off. Furthermore, and this is something you'll only notice looking at the SVG directly, the individual bars aren't exactly square. And the spacing is not even regular either.

So question is if we can find the master document for the website banner somewhere, or if we need to go the route of re-tracing the logo (or hand-crafting the SVG).

@BenBE BenBE added documentation 📖 Improvements or additions to documentation enhancement Extension or improvement to existing feature labels May 5, 2026
@BenBE BenBE added question ❔ Further information is requested needs-discussion 🤔 Changes need to be discussed and require consent labels May 5, 2026
@corygabrielsen corygabrielsen force-pushed the htop-wordmark-icons branch from a00be4c to ae38842 Compare May 6, 2026 01:13
@corygabrielsen corygabrielsen changed the title Add htop-logo.svg as the README header Add htop-logo.png as the README header May 6, 2026
@corygabrielsen
Copy link
Copy Markdown
Author

corygabrielsen commented May 6, 2026

This is a nice discussion with thoughtful considerations.

I figure the most useful thing I can do is construct the best SVGs, so that the maintainers can take a decision on what they want to do here.

Decisions

There are at least two main decisions to be made:

  • D1: What image to use at the top of the README
  • D2: Whether to include an htop-logo.svg in the source repository

For D1, the simplest decision and smallest patch is to use htop-logo.png. This would address my original motivation for opening the PR.

SVG options

With the attention on this, however, it is reasonable to give some thought to D2.

On the GPL "preferred form" point that came up earlier: the GPL explicitly counts build scripts as Corresponding Source (§1, §3), so a generator script paired with the canonical PNG satisfies "preferred form for modification" regardless of whether we ship the PNG, the SVG, or both — the script makes the SVG reproducible from the PNG.

I figure the SVG should be optimized along three criteria:

  • C1: Pixel accuracy vs htop-logo.png
  • C2: File size
  • C3: Elegance, readability, handwritten feel

As it turns out, pixel-perfect accuracy costs ~100× the file size. The reason is structural: PNG is a binary format that compresses pixel-to-pixel residuals via predictive filtering and DEFLATE, achieving roughly 0.18 bytes per visible pixel on this asset. SVG is text describing geometric shapes, so a pixel-perfect SVG must emit one shape per same-colored pixel run — paying ~50 bytes of XML syntax (tag name, attribute names, quotes) per shape regardless of compression. We're using a vector format to encode raster data, which is not what either format was designed for.

The most elegant SVG I was able to construct (with Opus 4.7) is below. It uses htop's existing color palette from htop.svg, defines the bar as a single primitive reused via <use>, and groups by meter row with comments naming each letter's cells. 5 KB, 100 lines, byte-identical render across cairosvg and librsvg.

htop-logo.svg (elegant variant — 100 lines)
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 486 86">

  <!--
    htop wordmark. Four letters [HTOP] across three meter rows of nine
    columns. Bars are 6 px wide on a 12 px stride; letters start at
    x = 12, 132, 252, 372. Outer brackets sit at x = 0..9 and 476..485.
    Each row is 26 px tall, separated by 4 px transparent gutters.
  -->

  <defs>

    <!-- Vertical gradients, lighter at top. objectBoundingBox by default,
         so each shape gets the gradient mapped to its own bounds. -->
    <linearGradient id="green" x2="0" y2="1">
      <stop offset="0"  stop-color="#8bf18b"/>
      <stop offset=".2" stop-color="#5bc15b"/>
      <stop offset=".8" stop-color="#47a347"/>
      <stop offset="1"  stop-color="#177317"/>
    </linearGradient>

    <linearGradient id="red" x2="0" y2="1">
      <stop offset="0"  stop-color="#fe7f7f"/>
      <stop offset=".2" stop-color="#ce4f4f"/>
      <stop offset=".8" stop-color="#b23030"/>
      <stop offset="1"  stop-color="#920000"/>
    </linearGradient>

    <linearGradient id="grey" x2="0" y2="1">
      <stop offset="0"  stop-color="#8c968c"/>
      <stop offset=".2" stop-color="#6c766c"/>
      <stop offset=".8" stop-color="#565d56"/>
      <stop offset="1"  stop-color="#363d36"/>
    </linearGradient>

    <!-- One bar shape, reused for all 81 lit cells. -->
    <rect id="bar" width="6" height="26"/>

    <!-- Brackets: 10x26 outer rect with a 4x18 cutout on the open side. -->
    <path id="bracket-l" fill-rule="evenodd"
          d="M0,0 h10 v26 h-10 z  M6,4 v18 h4 v-18 z"/>
    <path id="bracket-r" fill-rule="evenodd"
          d="M0,0 h10 v26 h-10 z  M0,4 v18 h4 v-18 z"/>

  </defs>

  <!-- Top row.  H verticals  ·  T crossbar  ·  O top arc  ·  P top loop. -->
  <g transform="translate(0,0)" fill="url(#green)">
    <use href="#bracket-l"           fill="url(#grey)"/>
    <use href="#bar" x="12"/>  <use href="#bar" x="24"/>  <use href="#bar" x="36"/>
    <use href="#bar" x="84"/>  <use href="#bar" x="96"/>  <use href="#bar" x="108"/>
    <use href="#bar" x="132"/> <use href="#bar" x="144"/> <use href="#bar" x="156"/>
    <use href="#bar" x="168"/> <use href="#bar" x="180"/> <use href="#bar" x="192"/>
    <use href="#bar" x="204"/> <use href="#bar" x="216"/> <use href="#bar" x="228"/>
    <use href="#bar" x="252"/> <use href="#bar" x="264"/> <use href="#bar" x="276"/>
    <use href="#bar" x="288"/> <use href="#bar" x="300"/> <use href="#bar" x="312"/>
    <use href="#bar" x="324"/> <use href="#bar" x="336"/> <use href="#bar" x="348"/>
    <use href="#bar" x="372"/> <use href="#bar" x="384"/> <use href="#bar" x="396"/>
    <use href="#bar" x="408"/> <use href="#bar" x="420"/> <use href="#bar" x="432"/>
    <use href="#bar" x="444" fill="url(#red)"/>
    <use href="#bar" x="456" fill="url(#red)"/>
    <use href="#bar" x="468" fill="url(#red)"/>
    <use href="#bracket-r" x="476"   fill="url(#grey)"/>
  </g>

  <!-- Middle row.  H crossbar  ·  T stem  ·  O sides  ·  P bowl into red. -->
  <g transform="translate(0,30)" fill="url(#green)">
    <use href="#bracket-l"           fill="url(#grey)"/>
    <use href="#bar" x="12"/>  <use href="#bar" x="24"/>  <use href="#bar" x="36"/>
    <use href="#bar" x="48"/>  <use href="#bar" x="60"/>  <use href="#bar" x="72"/>
    <use href="#bar" x="84"/>  <use href="#bar" x="96"/>  <use href="#bar" x="108"/>
    <use href="#bar" x="168"/> <use href="#bar" x="180"/> <use href="#bar" x="192"/>
    <use href="#bar" x="252"/> <use href="#bar" x="264"/> <use href="#bar" x="276"/>
    <use href="#bar" x="324"/> <use href="#bar" x="336"/> <use href="#bar" x="348"/>
    <use href="#bar" x="372"/> <use href="#bar" x="384"/> <use href="#bar" x="396"/>
    <use href="#bar" x="408" fill="url(#red)"/>
    <use href="#bar" x="420" fill="url(#red)"/>
    <use href="#bar" x="432" fill="url(#red)"/>
    <use href="#bar" x="444" fill="url(#red)"/>
    <use href="#bar" x="456" fill="url(#red)"/>
    <use href="#bar" x="468" fill="url(#red)"/>
    <use href="#bracket-r" x="476"   fill="url(#grey)"/>
  </g>

  <!-- Bottom row.  H verticals (mirror)  ·  T stem  ·  O bottom arc  ·  P leg. -->
  <g transform="translate(0,60)" fill="url(#green)">
    <use href="#bracket-l"           fill="url(#grey)"/>
    <use href="#bar" x="12"/>  <use href="#bar" x="24"/>  <use href="#bar" x="36"/>
    <use href="#bar" x="84"/>  <use href="#bar" x="96"/>  <use href="#bar" x="108"/>
    <use href="#bar" x="168"/> <use href="#bar" x="180"/> <use href="#bar" x="192"/>
    <use href="#bar" x="252"/> <use href="#bar" x="264"/> <use href="#bar" x="276"/>
    <use href="#bar" x="288"/> <use href="#bar" x="300"/> <use href="#bar" x="312"/>
    <use href="#bar" x="324"/> <use href="#bar" x="336"/> <use href="#bar" x="348"/>
    <use href="#bar" x="372" fill="url(#red)"/>
    <use href="#bar" x="384" fill="url(#red)"/>
    <use href="#bar" x="396" fill="url(#red)"/>
    <use href="#bracket-r" x="476"   fill="url(#grey)"/>
  </g>

</svg>

However, this technically has a substantial pixel-error footprint vs the canonical PNG. Only 4 of the 13,764 visible pixels match exactly; nearly half (49%) are off by more than 31 RGB units in some channel; max single-channel delta is 72. The reason is the canonical's bar gradient is non-linear — the green channel plateaus at ~197 across pixel rows 11–18, a saturated mid-tone band that no 4-stop linear interpolation can reproduce. Top and bottom of each bar match exactly (those are the named gradient stops); the middle diverges.

The accurate alternatives — pixel-perfect via per-pixel-row encoding — are larger and structurally more "data dump" than artwork:

Variant Raw size Gzipped Lines Visible pixels off canonical
htop-logo.png (canonical) 7,542 B 0
v0 — original PR gradient SVG 17,648 B ~4 K 202 13,764 (max ±113 RGB; brackets inverted)
Elegant SVG (above) 5,018 B ~2 K 100 13,760 (max ±72 RGB)
Symbol-shared RLE SVG 142 K 8.7 K 2,581 0
Full RLE SVG 570 K 36 K 9,955 0

With no clear winner found, it is difficult for me to form a strong opinion on tradeoffs between accuracy × size × elegance.

Conclusion

If I were the maintainer, I would appreciate D1 and D2 being addressed separately. For that reason, I've reduced the scope of this PR and modified the patch to use htop-logo.png in the README.

We can continue discussing the question of whether to include an htop-logo.svg in the source repository, and if so, which file to use and why.

@corygabrielsen
Copy link
Copy Markdown
Author

corygabrielsen commented May 6, 2026

The patch is updated to add and use htop-logo.png from https://github.com/htop-dev/htop-dev.github.io/blob/main/images/htop-logo.png @natoscott @BenBE

I don't think SVG was the right decision for the README and the pushback was good.

I spent about two hours trying to derive an accurate+elegant SVG from the PNG and failed. The original artist is surely the best person to ask here.

@corygabrielsen
Copy link
Copy Markdown
Author

Git-pack costs for the D2 candidates.

Packed in git
htop's existing pack 7.2 MB
Current PR (PNG + README change) 12 KB (0.17% of pack)

Adding an htop-logo.svg on top of the PR:

Variant Raw Packed % of pack Combined PR + variant Visible diff vs canonical
Elegant (100 lines) 5,018 B 1,199 B +0.016% 14 KB (0.18%) 13,760 px (max ±72 RGB)
Symbol-shared RLE 142 K 17 K +0.235% 30 KB (0.40%) 0
Full RLE 583 K 62 K +0.828% 74 KB (1.00%) 0

Repo context: largest blob 125 KB (hwloc-1.2.1/configure); mean blob ~480 B; 28 blobs >10 KB; 1 >100 KB.

@corygabrielsen
Copy link
Copy Markdown
Author

I think PNG is the way to go and SVG should be disregarded and forgotten unless an original file is discovered.

RLE SVG ≈ PNG with image-rendering: pixelated CSS

@fasterit
Copy link
Copy Markdown
Member

fasterit commented May 6, 2026

Any reason you put HTML into the markdown file instead of keeping it as a markdown image link?

Adds htop-logo.png, a byte-for-byte copy of the canonical HTOP wordmark
from htop-dev/htop-dev.github.io/images/htop-logo.png, and updates the
README header to reference it.

Application icon files (htop.png, htop.svg) are unchanged.

Assisted-by: Claude (Anthropic)
@corygabrielsen corygabrielsen force-pushed the htop-wordmark-icons branch from ae38842 to 5fdb8f5 Compare May 6, 2026 06:25
@corygabrielsen
Copy link
Copy Markdown
Author

corygabrielsen commented May 6, 2026

Any reason you put HTML into the markdown file instead of keeping it as a markdown image link?

No, this was me being confused and leaving old code smell from the SVG version, which I intuitively pursued because a) the logo has a gradient and b) htop.svg exists.

With your suggestion, the README diff is now minimal:

diff --git a/README.md b/README.md
index b8a8c2d0..612b5d4d 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# [![htop logo](htop.png)](https://htop.dev)
+# [![htop logo](htop-logo.png)](https://htop.dev)

Thanks for the push @fasterit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation 📖 Improvements or additions to documentation enhancement Extension or improvement to existing feature needs-discussion 🤔 Changes need to be discussed and require consent question ❔ Further information is requested

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants