Skip to content

Instantly share code, notes, and snippets.

@masukomi
Last active June 9, 2023 16:46
Show Gist options
  • Save masukomi/27b4bbb77d99213007ebce0fb1cb4c9f to your computer and use it in GitHub Desktop.
Save masukomi/27b4bbb77d99213007ebce0fb1cb4c9f to your computer and use it in GitHub Desktop.

Apple distributes their "add to wallet" images as SVGs which is great, but if you want to add it to an email or anything else that has issues with SVG files you're going to need a PNG (to maintain transparency around the rounded corners). Unfortunately there are a LOT of these images needed to support the various languages.

Converting these to PNGs is not as easy as you'd hope. Problems encountered:

  1. imagemagic produces unusably bad images (mostly just black) even though it's theoretically calling rsvg-convert under the covers and calling that directly works fine.
  2. inconsistent width and height
  3. extra transparent pixels on right and bottom edges

Here's my solution and what I learned along the way. It involves 2 scripts. The first one is in fish shell, just because that's where i started but you should be able to convert to Bash or whatever you like to use pretty easily.

#!/usr/bin/env fish

for file in (find . -name "*.svg")
  set directory (dirname $file)
  set base_filename (basename $file .svg)
  set new_filename $directory/$base_filename.png
  # -z 10 add zoom. not because we need it bigger, but because
  # it looks WAY better when you add _any_ amount of zoom.
  # -w 884 because if i don't constrain width or height then
  # the results are too varied to apply a consistent cropping
  # percentage
  rsvg-convert -z 10 --keep-aspect-ratio -w 884 -o $new_filename $file
  # convert $new_filename -gravity NorthEast -crop WIDTHxHEIGHT $new_filename
  # image_size.rb is outputting the cropped "WIDTHxHEIGHT"
  #
  convert $new_filename -gravity NorthEast -crop (image_size.rb (identify -ping -format '%w %h' $new_filename)) $new_filename

  # -crop results in foo-0.png foo-1.png foo-2.png (sometimes)
  #   and foo-3.png (sometimes)
  # what you want is in 0.png and the others are bits cropped off ?
  mv $directory/$base_filename-0.png $new_filename

  for n in (seq 1 3)
    # delete the unnecessary files. &> is redirecting STDERR to STDOUT
    # then shoving all to /dev/null because it doesn't ALWAYS generate
    # the -2  and -3 files ?!?!
    rm $directory/$base_filename-$n.png &> /dev/null
  end
  git add $new_filename

end

With a constrained initial width plus a little scratchpad math i was able to figure out that cropping 0.7% from the width & 2.8% from the height (rounded up on both) seemed to get me good results. It's not perfect. Some still have 1 or 2 pixels of transparency at the bottom, and some are cropped a little too much along the bottom (thin grey border missing).

#!/usr/bin/env ruby

# cropper for ... wallet things

initial_width, initial_height = ARGV[0].split(/\s+/).map{|x| x.to_i}
width_hundredth = (initial_width.to_f / 100)
height_hundredth = (initial_height.to_f / 100.0)

width_crop_percent = 0.7
height_crop_percent = 2.8 #2.58

new_width  = initial_width  - (width_crop_percent * width_hundredth).ceil
new_height = initial_height - (height_crop_percent * height_hundredth).ceil

puts "#{new_width}x#{new_height}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment