i got a camera

🔗 posted

🔙 back to index

I’m gonna take more photos this year so I got a camera! here are some photos I took with that camera to start learning how to take photos.

it’s nice, taking photos. forces me to get out of my own dang head and 👁️observe👁️ what’s going on around me. I also want to take more & better show photos!

the images lazy load and I put a big scroll zone in case you wanted to bail before loading any of the images, no worries.

if you’re still here, scroll down a bunch if you want to see several photos of a cat and a park.

ᛞ

pico (a cat)

fort greene park (a park)

ᛞ

if you’ve made it this far, 🎉congratulations🎉! you are rewarded with more words.

as you might tell, I stress about using images because I want to be sure they’re worth your bandwidth. to absolve some of my guilt, I try to squish files small as possible using Squoosh, preferring AVIF since it squooshes the smallest with the least perceptual damage.

annoying thing about AVIF, though: it doesn’t do any progressive loading, straight blankness until it’s good and ready. I’m using smallest images I can but for slower connections having nothing to indicate an image is loading is not a good experience.

also annoying, generally speaking, not specific to AVIF: content layout shift. gonna wanna statically set the width and height, which is tedious to do manually since not all the images have the same geometry!

I wrote a script that solves both problems and generates the image tags for me:

<img
  loading="lazy"
  src="/static/20250103/2024-12-31T233223_01.31ef7a37602fee9777d46e21cae48e5f.avif"
  width="2048"
  height="1365"
  style="background: url('data:image/avif;base64,AAAAHGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZgAAANZtZXRhAAAAAAAAACFoZGxyAAAAAAAAAABwaWN0AAAAAAAAAAAAAAAAAAAAAA5waXRtAAAAAAABAAAAImlsb2MAAAAAREAAAQABAAAAAAD6AAEAAAAAAAABCwAAACNpaW5mAAAAAAABAAAAFWluZmUCAAAAAAEAAGF2MDEAAAAAVmlwcnAAAAA4aXBjbwAAAAxhdjFDgQAMAAAAABRpc3BlAAAAAAAAAGYAAABEAAAAEHBpeGkAAAAAAwgICAAAABZpcG1hAAAAAAAAAAEAAQOBAgMAAAETbWRhdBIACgkYGbLDYICGg0Iy+wESAAKKKKEAtmmELaEyfsyfa/FK949D3bdOU+wyGwLap9ONFch1ws+gxlO14WshlmebwmGmAO9u3bapZLRCgG0ee/WnrfAvYKnjOwx0vpEjI7ZT0jOKAe88s/7/GaF9gJ1I0aNbC2dhq10HznJhkCdoYrZ3Vz2U4lt8SCPT9deGtzR1RourCJIB0KrxEyKjAyBAJ31bEtJZBxnipI9L1gCvH442LsfyXbWa2qxZwfNMT59zg3aoy6EdikSbddjYoVmaMC3XtS7Xl0G1AQrwXy1mBO4pLbGYJUNhl+tv1yfdp4NywrNJXtHIXd+M1yb4zSCOBi5T0lezHLGqew==');"
/>

I use imagemagick to get the width and height and that data URL is a blurry 5% sized version of the image to stick as the background while the real deal loads:

magick "$file" -resize 5% -blur 0x3 - | base64

I have a different script that renames the files to include a content hash so I can cache them forever.

it’s all a little jankily thrown together right now but the workflow is not bad:

  • throw images in a new folder under static/
  • run scripts/hashname.sh static/$folder/*
  • run scripts/gengallery.sh static/$folder/* | pbcopy
  • paste into the page

appendix a: gengallery.sh

#!/bin/bash

main() {
  # check if at least one argument (file) is provided
  if [ "$#" -lt 1 ]; then
    echo "Usage: $0 <file1> [file2 ...]"
    exit 1
  fi

  # base URL for the `src` attribute in the HTML
  BASE_URL="/"

  # loop through all provided files
  for file in "$@"; do
    # ensure the file exists
    if [ ! -f "$file" ]; then
      echo "File $file does not exist, skipping." >&2
      continue
    fi

    # get the dimensions of the image
    dimensions=$(magick identify -format "%wx%h" "$file" 2>/dev/null)
    if [ $? -ne 0 ]; then
      echo "Failed to get dimensions for $file, skipping." >&2
      continue
    fi

    # extract width and height
    width=$(echo "$dimensions" | cut -dx -f1)
    height=$(echo "$dimensions" | cut -dx -f2)

    # remove leading "public/" from the file path
    relative_path=${file#public/}

    # generate the base64-encoded data URL for the background
    data=$(magick "$file" -resize 5% -blur 0x3 - | base64)
    if [ -z "$data" ]; then
      echo "Failed to generate data URL for $file, skipping." >&2
      continue
    fi

    # output the HTML <img> tag with the data URL in the background style
    echo "<img loading=lazy src=\"$BASE_URL$relative_path\" width=\"$width\" height=\"$height\" style=\"background: url('data:image/avif;base64,$data');\">"
  done
}

main "$@"

appendix b: hashname.sh

#!/bin/bash
set -eu

usage() {
    echo "Usage: $0 [--undo] <file1> [file2] ... [fileN]"
    exit 1
}

# parse arguments
undo_mode=false

if [ "$#" -lt 1 ]; then
    usage
fi

if [ "$1" == "--undo" ]; then
    undo_mode=true
    shift
fi

main() {
    for file in "$@"; do
        # skip if the file does not exist or is not a regular file
        if [ ! -f "$file" ]; then
            echo "Skipping $file (not a valid file)"
            continue
        fi

        if $undo_mode; then
            # undo mode: remove hash from filename
            filename=$(basename -- "$file")
            extension="${filename##*.}"
            name="${filename%.*}"

            # check for hash-like pattern (32 hexadecimal characters) in the name
            new_name=$(echo "$name" | sed -E 's/\.[a-f0-9]{32}$//')

            if [ "$new_name" != "$name" ]; then
                # rename to remove the hash
                new_filename="${new_name}.${extension}"
                mv "$file" "$(dirname "$file")/$new_filename"
                echo "Renamed $filename to $new_filename"
            else
                echo "Skipping $file (no hash found)"
            fi
        else
            # normal mode: Add hash to the filename
            # extract file name and extension
            filename=$(basename -- "$file")
            extension="${filename##*.}"
            name="${filename%.*}"

            # check if the file already has a hash suffix
            if [[ "$name" =~ \.[a-f0-9]{32}$ ]]; then
                echo "Skipping $file (already has hash suffix)"
                continue
            fi

            # calculate MD5 hash of the file content
            md5_hash=$(md5 -q "$file")

            # create the new filename with MD5 hash
            new_filename="${name}.${md5_hash}.${extension}"
            mv "$file" "$(dirname "$file")/$new_filename"
            echo "Renamed $filename to $new_filename"
        fi
    done
}

main "$@"