Simon Willison’s Weblog

Subscribe
Atom feed for images

14 items tagged “images”

2024

SVG to JPG/PNG. The latest in my ongoing series of interactive HTML and JavaScript tools written almost entirely by LLMs. This one lets you paste in (or open-from-file, or drag-onto-page) some SVG and then use that to render a JPEG or PNG image of your desired width.

Screenshot of the SVG to JPEG/PNG tool. It starts with a Browse... option for selecting a file, next to a Load example image link, above a textarea full of SVG code. Then a radio box to select between JPEG and PNG, plus a background color color picker widget next to a checkbox labelled transparent. Then Output width, a number field set to 300. Then a convert SVG button. Below is the classic SVG tiger image, with a Download image link that says 47.38BK. Under that is a Base 64 image tag header with a copy image tag button and some visible HTML for a data:image/jpeg image element.

I built this using Claude 3.5 Sonnet, initially as an Artifact and later in a code editor since some of the features (loading an example image and downloading the result) cannot run in the sandboxed iframe Artifact environment.

Here's the full transcript of the Claude conversation I used to build the tool, plus a few commits I later made by hand to further customize it.

The code itself is mostly quite simple. The most interesting part is how it renders the SVG to an image, which (simplified) looks like this:

// First extract the viewbox to get width/height
const svgElement = new DOMParser().parseFromString(
    svgInput, 'image/svg+xml'
).documentElement;
let viewBox = svgElement.getAttribute('viewBox');
[, , width, height] = viewBox.split(' ').map(Number);

// Figure out the width/height of the output image
const newWidth = parseInt(widthInput.value) || 800;
const aspectRatio = width / height;
const newHeight = Math.round(newWidth / aspectRatio);

// Create off-screen canvas
const canvas = document.createElement('canvas');
canvas.width = newWidth;
canvas.height = newHeight;

// Draw SVG on canvas
const svgBlob = new Blob([svgInput], {type: 'image/svg+xml;charset=utf-8'});
const svgUrl = URL.createObjectURL(svgBlob);
const img = new Image();
const ctx = canvas.getContext('2d');
img.onload = function() {
    ctx.drawImage(img, 0, 0, newWidth, newHeight);
    URL.revokeObjectURL(svgUrl);
    // Convert that to a JPEG
    const imageDataUrl = canvas.toDataURL("image/jpeg");
    const convertedImg = document.createElement('img');
    convertedImg.src = imageDataUrl;
    imageContainer.appendChild(convertedImg);
};
img.src = svgUrl;

Here's the MDN explanation of that revokeObjectURL() method, which I hadn't seen before.

Call this method when you've finished using an object URL to let the browser know not to keep the reference to the file any longer.

# 6th October 2024, 7:57 pm / claude-3-5-sonnet, images, claude, ai, llms, svg, claude-artifacts, javascript, ai-assisted-programming, generative-ai

2022

Simple, Fast, and Scalable Reverse Image Search Using Perceptual Hashes and DynamoDB. Christopher Bong provides a clear explanation of how perceptual hashes can be used to create a string representing the visual content of an image, such that similar images can be identified by calculating a hamming distance between those hashes. He then explains how they built a large-scale system for this at Canva on top of DynamoDB, by splitting those strings into smaller hash windows and using those for efficient bulk lookups of similar candidates.

# 19th October 2022, 3:04 pm / images, search

2021

Making GitHub’s new homepage fast and performant. A couple of really clever tricks in this article by Tobias Ahlin. The first is using IntersectionObserver in conjunction with the video preload=“none” attribute to lazily load a video when it scrolls into view. The second is an ingenious trick to create an efficiently encoded transparent JPEG image: embed the image in a SVG file twice, once as the image and once as a transparency mask.

# 29th January 2021, 7:05 pm / images, performance, svg, javascript, github

2020

AVIF has landed. AVIF support landed in Chrome 85 a few weeks ago. It’s a new lossy royalty-free image format derived from AV1 video and it’s really impressive—it can achieve similar results to JPEG using a quarter of the file size! Jake digs into AVIF in detail, providing lots of illustrative examples created using the Squoosh online compressor, which now supports AVIF encoding. Jake used the same WebAssembly encoder from Squoosh to decode AVIF images in a web worker so that the demos in his article would work even for browsers that don’t yet support AVIF natively.

# 9th September 2020, 4:49 pm / images, webassembly, jake-archibald, webworkers

datasette-media 0.4. datasette-media is my Datasette plugin for serving media (e.g. images) directly from Datasette. The first version used file paths saved in a column and served the data from disk—this new version adds the ability to serve content from BLOB columns, such as those created by the new “sqlite-utils insert-files” command. It also adds configurable support for resizing images based on querystring parameters like ?w=100.

# 28th July 2020, 2:22 am / projects, datasette, plugins, images

2018

Squoosh. This is by far the most useful example of web assembly I’ve seen so far: Squoosh is a progressive web app for image optimization (JPEG, PNG, GIF, SVG and more) which uses emscripten-compiled versions of best in breed image codec implementations to provide a browser interface for applying and previewing those optimizations.

# 12th November 2018, 11:15 pm / web-performance, images, webassembly

2017

dhash (via) Python library to calculate the perceptual difference hash for an image. Delightfully simple algorithm that’s fully explained in the README—it works by scaling the image to 8x8 grayscale and then creating a bitmap representing of each pixel is lighter or darker than the previous one.

# 9th November 2017, 5:44 pm / images, python

2010

I pushed 20 more of my projects to GitHub. Some great Node.js stuff here from Peteris Krumins, including modules for processing PNG, JPEG and animated GIFs.

# 23rd September 2010, 1:18 am / images, jpeg, node, peteris-krumins, png, recovered

Placehold.it. Useful dynamic image generator for layout mockups—just drop an image in to a page pointing at http://placehold.it/300x200. Takes optional arguments for text, colour and format as well.

# 20th March 2010, 2:32 pm / images, layout, design

2009

moddims (via) Apache 2 module which exposes ImageMagick as a URL-driven service, allowing you to request an image from a whitelisted host server and resize, thumbnail or alter the quality of it.

# 21st July 2009, 6:18 pm / moddims, apache, imagemagick, images, resizing, thumbnails

The GIF Pronunciation Page. It’s jiff. Here’s evidence.

# 11th June 2009, 10:50 pm / gif, images, pronunciation

Load Windows ICO files. Apparently PIL has trouble with the most recent versions of the windows .ico format (Vista now embeds PNG images in them)—this clever function deals with the differences and gives back a PIL Image object.

# 17th January 2009, 9:48 pm / pil, python, vista, windows, ico, images, png

2007

VectorMagic. Neat online tool (with a Flex frontend) for tracing bitmap images in to vectors, based on research at the Stanford AI lab.

# 28th October 2007, 11:46 am / stanford, images, vectors, graphics, flex, flash, vectormagic

Return of the HTTP overhead delay. Christian proposes a neat way of improving page performance, by delaying non-essential images such as avatars until after the rest of the page has loaded.

# 11th July 2007, 3:12 pm / christian-heilmann, performance, http, images, avatars, onload, javascript