<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Hacker News: nigeltao</title><link>https://news.ycombinator.com/user?id=nigeltao</link><description>Hacker News RSS</description><docs>https://hnrss.org/</docs><generator>hnrss v2.1.1</generator><lastBuildDate>Fri, 31 Jul 2026 10:59:08 +0000</lastBuildDate><atom:link href="https://hnrss.org/user?id=nigeltao" rel="self" type="application/rss+xml"></atom:link><item><title><![CDATA[New comment by nigeltao in "Handsum: An LQIP Image File Format"]]></title><description><![CDATA[
<p>Hi, author here. Thanks for the "check your HTML" bug report.</p>
]]></description><pubDate>Mon, 13 Jul 2026 01:22:20 +0000</pubDate><link>https://news.ycombinator.com/item?id=48886728</link><dc:creator>nigeltao</dc:creator><comments>https://news.ycombinator.com/item?id=48886728</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=48886728</guid></item><item><title><![CDATA[New comment by nigeltao in "Handsum: An LQIP Image File Format"]]></title><description><![CDATA[
<p>Handsum is intrinsically 16x16. Decoding to 32x32 is a two step process:<p>1. Decode to 16x16. This is done by the Handsum library.<p>2. Upscale 2x. This is done by the caller of the Handsum library (or, for the Wasm demo, by the HTML renderer).<p>If you want 48x48 or 64x64, just raise the 2x, in step 2, to 3x or 4x.</p>
]]></description><pubDate>Mon, 13 Jul 2026 01:21:47 +0000</pubDate><link>https://news.ycombinator.com/item?id=48886722</link><dc:creator>nigeltao</dc:creator><comments>https://news.ycombinator.com/item?id=48886722</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=48886722</guid></item><item><title><![CDATA[Show HN: Handsum: An LQIP Image File Format]]></title><description><![CDATA[
<p>Article URL: <a href="https://nigeltao.github.io/blog/2026/handsum.html">https://nigeltao.github.io/blog/2026/handsum.html</a></p>
<p>Comments URL: <a href="https://news.ycombinator.com/item?id=48837153">https://news.ycombinator.com/item?id=48837153</a></p>
<p>Points: 11</p>
<p># Comments: 0</p>
]]></description><pubDate>Wed, 08 Jul 2026 20:40:50 +0000</pubDate><link>https://nigeltao.github.io/blog/2026/handsum.html</link><dc:creator>nigeltao</dc:creator><comments>https://news.ycombinator.com/item?id=48837153</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=48837153</guid></item><item><title><![CDATA[New comment by nigeltao in "Floating-Point Printing and Parsing Can Be Simple and Fast"]]></title><description><![CDATA[
<p>> Russ Cox should make a C version of his code.<p><a href="https://github.com/rsc/fpfmt/blob/main/bench/uscalec/ftoa.c" rel="nofollow">https://github.com/rsc/fpfmt/blob/main/bench/uscalec/ftoa.c</a></p>
]]></description><pubDate>Sat, 24 Jan 2026 00:07:23 +0000</pubDate><link>https://news.ycombinator.com/item?id=46739648</link><dc:creator>nigeltao</dc:creator><comments>https://news.ycombinator.com/item?id=46739648</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=46739648</guid></item><item><title><![CDATA[New comment by nigeltao in "Kaitai Struct: declarative binary format parsing language"]]></title><description><![CDATA[
<p>It's a great idea. Chromium uses Wuffs to parse GIF data from the untrusted network.<p>There's also a "wget some JSON and pipe that to what Wuffs calls example/jsonptr" example at <a href="https://nigeltao.github.io/blog/2020/jsonptr.html#sandboxing" rel="nofollow">https://nigeltao.github.io/blog/2020/jsonptr.html#sandboxing</a></p>
]]></description><pubDate>Fri, 24 Oct 2025 03:39:50 +0000</pubDate><link>https://news.ycombinator.com/item?id=45690513</link><dc:creator>nigeltao</dc:creator><comments>https://news.ycombinator.com/item?id=45690513</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=45690513</guid></item><item><title><![CDATA[New comment by nigeltao in "Kaitai Struct: declarative binary format parsing language"]]></title><description><![CDATA[
<p>The top-level README has a link called "Getting Started".</p>
]]></description><pubDate>Thu, 23 Oct 2025 23:10:20 +0000</pubDate><link>https://news.ycombinator.com/item?id=45688638</link><dc:creator>nigeltao</dc:creator><comments>https://news.ycombinator.com/item?id=45688638</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=45688638</guid></item><item><title><![CDATA[New comment by nigeltao in "Kaitai Struct: declarative binary format parsing language"]]></title><description><![CDATA[
<p>See <a href="https://github.com/google/wuffs/blob/main/doc/related-work.md" rel="nofollow">https://github.com/google/wuffs/blob/main/doc/related-work.m...</a><p>> Kaitai Struct is in a similar space, generating safe parsers for multiple target programming languages from one declarative specification. Again, Wuffs differs in that it is a complete (and performant) end to end implementation, not just for the structured parts of a file format. Repeating a point in the previous paragraph, the difficulty in decoding the GIF format isn't in the regularly-expressible part of the format, it's in the LZW compression. Kaitai's GIF parser returns the compressed LZW data as an opaque blob.<p>Taking PNG as an example, Kaitai will tell you the image's metadata (including width and height) and that the compressed pixels are in the such-and-such part of the file. But unlike Wuffs, Kaitai doesn't actually decode the compressed pixels.<p>---<p>Wuffs' generated C code also doesn't need any <i>capabilities</i>, including the ability to malloc or free. Its example/mzcat program (equivalent to /bin/bzcat or /bin/zcat, for decoding BZIP2 or GZIP) self-imposes a SECCOMP_MODE_STRICT sandbox, which is so restrictive (and secure!) that it prohibits any syscalls other than read, write, _exit and sigreturn.<p>(I am the Wuffs author.)</p>
]]></description><pubDate>Thu, 23 Oct 2025 22:57:26 +0000</pubDate><link>https://news.ycombinator.com/item?id=45688488</link><dc:creator>nigeltao</dc:creator><comments>https://news.ycombinator.com/item?id=45688488</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=45688488</guid></item><item><title><![CDATA[New comment by nigeltao in "Why do we keep gravitating toward complexity?"]]></title><description><![CDATA[
<p>I like my colleague Simon Morris's observation about software complexity:<p>> Software has a Peter Principle. If a piece of code is comprehensible, someone will extend it, so they can apply it to their own problem. If it’s incomprehensible, they’ll write their own code instead. Code tends to be extended to its level of incomprehensibility.</p>
]]></description><pubDate>Tue, 16 Sep 2025 03:55:02 +0000</pubDate><link>https://news.ycombinator.com/item?id=45257871</link><dc:creator>nigeltao</dc:creator><comments>https://news.ycombinator.com/item?id=45257871</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=45257871</guid></item><item><title><![CDATA[New comment by nigeltao in "Consider using Zstandard and/or LZ4 instead of Deflate"]]></title><description><![CDATA[
<p>> Compressing QOI with something like LZ4 would generally outperform PNG.<p><a href="https://github.com/nigeltao/qoir" rel="nofollow">https://github.com/nigeltao/qoir</a> has some numbers comparing QOIR (which is QOI-inspired-with-LZ4) vs PNG.<p>QOIR has better decode speed and comparable compression ratio (depending on which PNG encoder you use).<p>QOIR's numbers are also roughly similar to ZPNG.</p>
]]></description><pubDate>Wed, 06 Aug 2025 00:25:51 +0000</pubDate><link>https://news.ycombinator.com/item?id=44806235</link><dc:creator>nigeltao</dc:creator><comments>https://news.ycombinator.com/item?id=44806235</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=44806235</guid></item><item><title><![CDATA[New comment by nigeltao in "Access Control Syntax"]]></title><description><![CDATA[
<p>For Wuffs, top level declarations start with either pub or pri (and both keywords have the same width, in a monospace font).<p><pre><code>    pub status "#blah"
    pub struct foo(etc etc)
    pri func foo.bar(etc etc)
</code></pre>
Since code is also auto-formatted, you can do things like "show me a structural overview of a package's source code" with a simple grep:<p><pre><code>    rg -N ^p   std/jpeg/*.wuffs
</code></pre>
If you want just the exported API, change p to pub:<p><pre><code>    rg -N ^pub std/jpeg/*.wuffs</code></pre></p>
]]></description><pubDate>Tue, 27 May 2025 00:30:26 +0000</pubDate><link>https://news.ycombinator.com/item?id=44102896</link><dc:creator>nigeltao</dc:creator><comments>https://news.ycombinator.com/item?id=44102896</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=44102896</guid></item><item><title><![CDATA[New comment by nigeltao in "Dithering in Colour"]]></title><description><![CDATA[
<p>Might be relevant to your interests:<p><a href="https://nigeltao.github.io/blog/2022/gamma-aware-ordered-dithering.html" rel="nofollow">https://nigeltao.github.io/blog/2022/gamma-aware-ordered-dit...</a></p>
]]></description><pubDate>Thu, 13 Mar 2025 23:28:17 +0000</pubDate><link>https://news.ycombinator.com/item?id=43358270</link><dc:creator>nigeltao</dc:creator><comments>https://news.ycombinator.com/item?id=43358270</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=43358270</guid></item><item><title><![CDATA[New comment by nigeltao in "JSON parsers that can accept comments"]]></title><description><![CDATA[
<p>You might like JWCC, which literally stands for JSON With Commas and Comments.<p><a href="https://nigeltao.github.io/blog/2021/json-with-commas-comments.html" rel="nofollow">https://nigeltao.github.io/blog/2021/json-with-commas-commen...</a></p>
]]></description><pubDate>Mon, 09 Dec 2024 00:06:50 +0000</pubDate><link>https://news.ycombinator.com/item?id=42361893</link><dc:creator>nigeltao</dc:creator><comments>https://news.ycombinator.com/item?id=42361893</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=42361893</guid></item><item><title><![CDATA[New comment by nigeltao in "JSON5 – JSON for Humans"]]></title><description><![CDATA[
<p>JWCC literally stands for JSON With Commas and Comments.<p>JWCC is also what Tailscale call HuJSON, as in "JSON for Humans", which as amusingly also what json5 claims to be.<p><a href="https://github.com/tailscale/hujson">https://github.com/tailscale/hujson</a></p>
]]></description><pubDate>Sun, 08 Dec 2024 23:47:03 +0000</pubDate><link>https://news.ycombinator.com/item?id=42361771</link><dc:creator>nigeltao</dc:creator><comments>https://news.ycombinator.com/item?id=42361771</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=42361771</guid></item><item><title><![CDATA[New comment by nigeltao in "Jpegli: A new JPEG coding library"]]></title><description><![CDATA[
<p>> I believe the standard does not specify what the intermediate progressive renderings should look like.<p>This is possibly getting too academic, but IIUC for a progressive JPEG, e.g. encoded by cjpeg to have 10 0xDA Start Of Scan markers, it's actually legitimate to post-process the file, truncating to fewer scans (but re-appending the 0xD9 End Of Image marker). The shorter file is still a valid JPEG, and so still relevant for discussing whether all decoders will render the same pixels.<p>I might be wrong about validity, though. It's been a while since I've studied the JPEG spec.</p>
]]></description><pubDate>Fri, 05 Apr 2024 01:42:35 +0000</pubDate><link>https://news.ycombinator.com/item?id=39937879</link><dc:creator>nigeltao</dc:creator><comments>https://news.ycombinator.com/item?id=39937879</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=39937879</guid></item><item><title><![CDATA[New comment by nigeltao in "Jpegli: A new JPEG coding library"]]></title><description><![CDATA[
<p>> all decoders will render the same pixels<p>Not true. Even just within libjpeg, there are three different IDCT implementations (jidctflt.c, jidctfst.c, jidctint.c) and they produce different pixels (it's a classic speed vs quality trade-off). It's spec-compliant to choose any of those.<p>A few years ago, in libjpeg-turbo, they changed the smoothing kernel used for decoding (incomplete) progressive JPEGs, from a 3x3 window to 5x5. This meant the decoder produced different pixels, but again, that's still valid:<p><a href="https://github.com/libjpeg-turbo/libjpeg-turbo/commit/6d91e950c871103a11bac2f10c63bf998796c719">https://github.com/libjpeg-turbo/libjpeg-turbo/commit/6d91e9...</a></p>
]]></description><pubDate>Thu, 04 Apr 2024 02:42:25 +0000</pubDate><link>https://news.ycombinator.com/item?id=39926004</link><dc:creator>nigeltao</dc:creator><comments>https://news.ycombinator.com/item?id=39926004</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=39926004</guid></item><item><title><![CDATA[New comment by nigeltao in "Jpegli: A new JPEG coding library"]]></title><description><![CDATA[
<p>You're right that Wuffs' memory-safety isn't relevant for this attack.<p>Still, Wuffs doesn't use autotools, and if you're pulling the library from the <a href="https://github.com/google/wuffs-mirror-release-c">https://github.com/google/wuffs-mirror-release-c</a> repository then that repo doesn't even contain any binary-data test files.</p>
]]></description><pubDate>Thu, 04 Apr 2024 02:21:41 +0000</pubDate><link>https://news.ycombinator.com/item?id=39925864</link><dc:creator>nigeltao</dc:creator><comments>https://news.ycombinator.com/item?id=39925864</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=39925864</guid></item><item><title><![CDATA[New comment by nigeltao in "Jpegli: A new JPEG coding library"]]></title><description><![CDATA[
<p>Yeah, it's just a coincidence (†), but I started working on Wuffs' LZMA and XZ decoders last December. It works well enough to decode the Linux source code tarball correctly (producing the same output as /usr/bin/xz).<p><pre><code>    $ git clone --quiet --depth=1 https://github.com/google/wuffs.git
    $ gcc -O3 wuffs/example/mzcat/mzcat.c -o my-mzcat
    $ ./my-mzcat     < linux-6.8.2.tar.xz | sha256sum 
    d53c712611ea6cb5acaf6627a84d5226692ae90ce41ee599fcc3203e7f8aa359  -
    $ /usr/bin/xz -d < linux-6.8.2.tar.xz | sha256sum 
    d53c712611ea6cb5acaf6627a84d5226692ae90ce41ee599fcc3203e7f8aa359  -
</code></pre>
(†) Also, I'm not "Jia Tan"! You're just going to have to trust me on both of those claims. :-/</p>
]]></description><pubDate>Thu, 04 Apr 2024 02:17:43 +0000</pubDate><link>https://news.ycombinator.com/item?id=39925841</link><dc:creator>nigeltao</dc:creator><comments>https://news.ycombinator.com/item?id=39925841</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=39925841</guid></item><item><title><![CDATA[New comment by nigeltao in "Jpegli: A new JPEG coding library"]]></title><description><![CDATA[
<p>Encoding is definitely in Wuffs' long term objectives (it's issue #2 and literally in its doc/roadmap.md file). It's just that decoding has been a higher priority. It's also a simpler problem. There's often only <i>one</i> valid decoding for any given input.<p>Decoding takes a compressed image file as input, which have complicated formats. Roughly speaking, encoding just takes a width x height x 4 pixel buffer, with very regular structure. It's much easier to hide something malicious in a complicated format.<p>Higher priority means that, when deciding whether to work on a Wuffs PNG encoder or a Wuffs JPEG decoder next, when neither existed at the time, I chose to have more decoders.<p>(I work at Google, and am the Wuffs author, but have nothing to do with Jpegli. Google is indeed a big company.)</p>
]]></description><pubDate>Wed, 03 Apr 2024 22:52:48 +0000</pubDate><link>https://news.ycombinator.com/item?id=39924365</link><dc:creator>nigeltao</dc:creator><comments>https://news.ycombinator.com/item?id=39924365</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=39924365</guid></item><item><title><![CDATA[New comment by nigeltao in "Jpegli: A new JPEG coding library"]]></title><description><![CDATA[
<p>Yeah, you're right. It's not as easy to write Wuffs code during the research phase, since you don't just have to write the code, you also have to help the compiler prove that the code is safe, and sometimes refactor the code to make that tractable.<p>Wuffs doesn't support global variables, but when I'm writing my own research phase code, sometimes I like to just tweak some global state (without checking the code in) just to get some experimental data: hey, how do the numbers change if I disable the blahblah phase when the such-and-such condition (best evaluated in some other part of the code) holds?<p>Also, part of Wuffs' safety story is that Wuffs code <i>cannot make any syscalls at all</i>, which implies that it cannot allocate or free memory, or call printf. Wuffs is a language for writing libraries, not whole programs, and the library caller (not callee) is responsible for e.g. allocating pixel buffers. That also makes it harder to use during the research phase.</p>
]]></description><pubDate>Wed, 03 Apr 2024 22:49:26 +0000</pubDate><link>https://news.ycombinator.com/item?id=39924339</link><dc:creator>nigeltao</dc:creator><comments>https://news.ycombinator.com/item?id=39924339</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=39924339</guid></item><item><title><![CDATA[New comment by nigeltao in "What even is a JSON number?"]]></title><description><![CDATA[
<p>When I wrote my jsonptr tool a few years ago, I noticed that some JSON libraries (in both C++ and Rust) don't even do "parse a string of decimal digits as a float64" properly. I don't mean that in the "0.3 isn't exactly representable; have 0.30000000000000004 instead" sense.<p>I mean that rapidjson (C++) parsed the string "0.99999999999999999" as the number 1.0000000000000003. Apart from just looking weird, it's a different float64 bit-pattern: 0x3FF0000000000000 vs 0x3FF0000000000001.<p>Similarly, serde-json (Rust) parsed "122.416294033786585" as 122.4162940337866. This isn't as obvious a difference, but the bit-patterns differ by one: 0x405E9AA48FBB2888 vs 0x405E9AA48FBB2889. Serde-json does have an "float_roundtrip" feature flag, but it's opt-in, not enabled by default.<p>For details, look for "rapidjson issue #1773" and "serde_json issue #707" at <a href="https://nigeltao.github.io/blog/2020/jsonptr.html" rel="nofollow">https://nigeltao.github.io/blog/2020/jsonptr.html</a></p>
]]></description><pubDate>Mon, 01 Apr 2024 22:11:04 +0000</pubDate><link>https://news.ycombinator.com/item?id=39900007</link><dc:creator>nigeltao</dc:creator><comments>https://news.ycombinator.com/item?id=39900007</comments><guid isPermaLink="false">https://news.ycombinator.com/item?id=39900007</guid></item></channel></rss>