diff options
| author | Lizzy Fleckenstein <lizzy@vlhl.dev> | 2026-04-03 17:45:39 +0200 |
|---|---|---|
| committer | Lizzy Fleckenstein <lizzy@vlhl.dev> | 2026-04-03 17:45:39 +0200 |
| commit | 3faaa5afa1d7031c8cb50762719ea04250873646 (patch) | |
| tree | 14c910a76cffffdc0fbdb9a889bf6d04383a42b3 | |
| parent | 2b38df821262b09ff6e3e44107fa15dc48fd71a7 (diff) | |
| download | usermoji-3faaa5afa1d7031c8cb50762719ea04250873646.tar.xz | |
add balls
| -rw-r--r-- | Makefile | 12 | ||||
| -rwxr-xr-x | tools/spherize | 411 |
2 files changed, 419 insertions, 4 deletions
@@ -1,25 +1,29 @@ USERS != ls plain | xargs basename -s .png -all: cube thoughts petpet +all: cube thoughts pets ball out/cube/%cube.gif: plain/%.png mkcube tools/Vulkan-Tools/ | out/cube/ ./mkcube $< $@ -out/petpet/%pets.gif: plain/%.png tools/petpet/ | out/petpet/ +out/pets/%pets.gif: plain/%.png tools/petpet/ | out/pets/ ./tools/petpet/init.js $< $@ out/thoughts/%thoughts.png: plain/%.png mkthoughts thoughts/ | out/thoughts/ ./mkthoughts $< $@ $$(grep "^$$(basename -s .png $<) " thoughts/colors.txt | cut -d' ' -f 2) +out/ball/%ball.png: plain/%.png tools/spherize | out/ball/ + ./tools/spherize -b none $< $@ + out/%/: mkdir -p $@ cube: $(patsubst %, out/cube/%cube.gif, $(USERS)) -petpet: $(patsubst %, out/petpet/%pets.gif, $(USERS)) +pets: $(patsubst %, out/pets/%pets.gif, $(USERS)) thoughts: $(patsubst %, out/thoughts/%thoughts.png, $(USERS)) +ball: $(patsubst %, out/ball/%ball.png, $(USERS)) clean: rm -rf out -.PHONY: all cube thoughts petpet +.PHONY: all cube thoughts pets ball .NOTPARALLEL: cube diff --git a/tools/spherize b/tools/spherize new file mode 100755 index 00000000..f4108fa2 --- /dev/null +++ b/tools/spherize @@ -0,0 +1,411 @@ +#!/bin/bash +# +# Developed by Fred Weinhaus 6/20/2009 .......... revised 4/25/2015 +# +# ------------------------------------------------------------------------------ +# +# Licensing: +# +# Copyright © Fred Weinhaus +# +# My scripts are available free of charge for non-commercial use, ONLY. +# +# For use of my scripts in commercial (for-profit) environments or +# non-free applications, please contact me (Fred Weinhaus) for +# licensing arrangements. My email address is fmw at alink dot net. +# +# If you: 1) redistribute, 2) incorporate any of these scripts into other +# free applications or 3) reprogram them in another scripting language, +# then you must contact me for permission, especially if the result might +# be used in a commercial or for-profit environment. +# +# My scripts are also subject, in a subordinate manner, to the ImageMagick +# license, which can be found at: http://www.imagemagick.org/script/license.php +# +# ------------------------------------------------------------------------------ +# +#### +# +# USAGE: spherize [-d diameter(s)] [-a amp] [-z zoom] [-b bcolor ] [-s] [-t] infile outfile +# USAGE: spherize [-h or -help] +# +# OPTIONS: +# +# -d diameter(s) diameters; comma separate x and y diameters; +# integers>0 and less than or equal to image +# dimensions; if only one value provided, +# it will be used for both; default is the +# image "width,height" +# -a amp distortion amplification factor; float>=0; +# default=0 +# -z zoom zoom factor; scales the input image on the +# sphere; float>=0; default=1 +# -b bcolor background color; any valid IM color or +# "none" for transparent or "image" for input +# image background; default=black +# -s make result with both diameters equal to the +# smaller of the x or y diameters +# -t trim image to diameters +# +### +# +# NAME: SPHERIZE +# +# PURPOSE: To warp an image onto a (hemi-)sphere. +# +# DESCRIPTION: UNROTATE warps an image onto a (hemi-)sphere and views it +# orthographically. The x and y diameters can be specified along with the +# distortion amplification and input image zoom. The background around +# the sphere is also user controlled. This is a limited version of my +# bubblewarp script that is not limited by the use of the IM -fx function +# and therefore is very fast. +# +# +# Arguments: +# +# -d diameter(s) --- DIAMETER(S) is a comma separate list of the desired +# x and y diameters of the sphere. If only one value is provided, then it +# will be used for both diameters. Values are integers greater than zero +# and equal to or smaller than the dimensions of the image. The default +# values are the size of the image. Thus if the image is square, then a +# spherical effect will be produced. But if the image is not square, then +# elliptical effect will be produced. +# +# -a amp --- AMP is the distortion amplification factor. Values are floats +# greater than or equal to zero. The default=1. Values larger than one will +# make more distortion and values less than one will make less distortion. +# +# -z zoom --- ZOOM is the zoom factor for the input image before warping it +# onto the sphere. Values are floats greater than or equal to zero. The +# default=1. Values larger than one will magnify the input image on the sphere. +# Values less than one will minify the input image on the sphere. +# +# -b bcolor ... BCOLOR is the color for the background outside the sphere. +# Any valid IM color is allowed or one may specify "none" for a transparent +# background or "image" to have the input image as the background. The default +# is black. +# +# -s ... Make the result with both diameters equal to the smaller of the +# x or y diameters. +# +# -t ... Trim the output image to the diameters. +# +# NOTE: This script is a limited version of my bubblewarp script, but is +# much faster, since it does not use -fx. +# +# NOTE: This script requires IM 6.5.3-9 or higher due to the use of +# -compose distort. Many thanks to Anthony Thyssen for his hard work +# developing it. +# +# CAVEAT: No guarantee that this script will work on all platforms, +# nor that trapping of inconsistent parameters is complete and +# foolproof. Use At Your Own Risk. +# +###### +# +# set default values; +dx="" # x diameter +dy="" # y diameter +amp=1 # distortion amplification +zoom=1 # input image zoom factor +bcolor="black" # background color; none for transparency; or "image" +symmetry="no" # sphere with both diameters equal to min of x and y diameters +trim="no" # trim output to diameters + +# set directory for temporary files +dir="." # suggestions are dir="." or dir="/tmp" + +# set up functions to report Usage and Usage with Description +PROGNAME=`type $0 | awk '{print $3}'` # search for executable on path +PROGDIR=`dirname $PROGNAME` # extract directory of program +PROGNAME=`basename $PROGNAME` # base name of program +usage1() + { + echo >&2 "" + echo >&2 "$PROGNAME:" "$@" + sed >&2 -e '1,/^####/d; /^###/g; /^#/!q; s/^#//; s/^ //; 4,$p' "$PROGDIR/$PROGNAME" + } +usage2() + { + echo >&2 "" + echo >&2 "$PROGNAME:" "$@" + sed >&2 -e '1,/^####/d; /^######/g; /^#/!q; s/^#*//; s/^ //; 4,$p' "$PROGDIR/$PROGNAME" + } + +# function to report error messages +errMsg() + { + echo "" + echo $1 + echo "" + usage1 + exit 1 + } + +# function to test for minus at start of value of second part of option 1 or 2 +checkMinus() + { + test=`echo "$1" | grep -c '^-.*$'` # returns 1 if match; 0 otherwise + [ $test -eq 1 ] && errMsg "$errorMsg" + } + +# test for correct number of arguments and get values +if [ $# -eq 0 ] + then + # help information + echo "" + usage2 + exit 0 +elif [ $# -gt 12 ] + then + errMsg "--- TOO MANY ARGUMENTS WERE PROVIDED ---" +else + while [ $# -gt 0 ] + do + # get parameters + case "$1" in + -h|-help) # help information + echo "" + usage2 + ;; + -d) # diameters + shift # to get the next parameter + # test if parameter starts with minus sign + errorMsg="--- INVALID DIAMETERS SPECIFICATION ---" + checkMinus "$1" + diameters=$1 + test=`echo "$1" | tr "," " " | wc -w` + [ $test -eq 1 -o $test -gt 2 ] && errMsg "--- INCORRECT NUMBER OF DIAMETERS SUPPLIED ---" + diameters=`expr "$1" : '\([0-9]*,[0-9]*\)'` + [ "$diameters" = "" ] && errMsg "--- DIAMETERS=$diameters MUST BE A PAIR OF NON-NEGATIVE INTEGERS SEPARATED BY A COMMA ---" + diameters="$1," + dx=`echo "$diameters" | cut -d, -f1` + dy=`echo "$diameters" | cut -d, -f2` + # further testing done later + ;; + -a) # amp + shift # to get the next parameter + # test if parameter starts with minus sign + errorMsg="--- INVALID AMPLIFICATION SPECIFICATION ---" + checkMinus "$1" + amp=`expr "$1" : '\([.0-9]*\)'` + [ "$amp" = "" ] && errMsg "--- AMPLIFICATION=$amp MUST BE A NON-NEGATIVE FLOATING POINT VALUE (with no sign) ---" + ;; + -z) # zoom + shift # to get the next parameter + # test if parameter starts with minus sign + errorMsg="--- INVALID ZOOM SPECIFICATION ---" + checkMinus "$1" + zoom=`expr "$1" : '\([.0-9]*\)'` + [ "$zoom" = "" ] && errMsg "--- ZOOM=$zoom MUST BE A NON-NEGATIVE FLOATING POINT VALUE (with no sign) ---" + ;; + -b) # get bcolor + shift # to get the next parameter + # test if parameter starts with minus sign + errorMsg="--- INVALID BACKGROUND COLOR SPECIFICATION ---" + checkMinus "$1" + bcolor="$1" + ;; + -s) # set symmetry + symmetry="yes" + ;; + -t) # set trim + trim="yes" + ;; + -) # STDIN and end of arguments + break + ;; + -*) # any other - argument + errMsg "--- UNKNOWN OPTION ---" + ;; + *) # end of arguments + break + ;; + esac + shift # next option + done + # + # get infile and outfile + infile="$1" + outfile="$2" +fi + +# test that infile provided +[ "$infile" = "" ] && errMsg "NO INPUT FILE SPECIFIED" + +# test that outfile provided +[ "$outfile" = "" ] && errMsg "NO OUTPUT FILE SPECIFIED" + +# setup temporaries +tmpA1="$dir/spherize_A_$$.mpc" +tmpA2="$dir/spherize_A_$$.cache" +tmpB1="$dir/spherize_B_$$.mpc" +tmpB2="$dir/spherize_B_$$.cache" +tmpF1="$dir/spherize_T_$$.mpc" +tmpF2="$dir/spherize_T_$$.cache" +tmpM1="$dir/spherize_M_$$.mpc" +tmpM2="$dir/spherize_M_$$.cache" +tmpX1="$dir/spherize_X_$$.mpc" +tmpX2="$dir/spherize_X_$$.cache" +tmpY1="$dir/spherize_Y_$$.mpc" +tmpY2="$dir/spherize_Y_$$.cache" +trap "rm -f $tmpA1 $tmpA2 $tmpB1 $tmpB2 $tmpF1 $tmpF2 $tmpM1 $tmpM2 $tmpX1 $tmpX2 $tmpY1 $tmpY2;" 0 +trap "rm -f $tmpA1 $tmpA2 $tmpB1 $tmpB2 $tmpM1 $tmpM2 $tmpX1 $tmpX2 $tmpY1 $tmpY2; exit 1" 1 2 3 15 +trap "rm -f $tmpA1 $tmpA2 $tmpB1 $tmpB2 $tmpM1 $tmpM2 $tmpX1 $tmpX2 $tmpY1 $tmpY2; exit 1" ERR + + +# read the input image into the TMP cached image. +convert -quiet "$infile" +repage "$tmpA1" || + errMsg "--- FILE $infile NOT READABLE OR HAS ZERO SIZE ---" + +# test for minimum IM version required +# IM 6.5.3.9 or higher to conform to new -compose distort +im_version=`convert -list configure | \ + sed '/^LIB_VERSION_NUMBER */!d; s//,/; s/,/,0/g; s/,0*\([0-9][0-9]\)/\1/g' | head -n 1` +[ "$im_version" -lt "06050309" ] && errMsg "--- REQUIRES IM VERSION 6.5.3-9 OR HIGHER ---" + +# get image dimensions +ww=`convert $tmpA1 -ping -format "%w" info:` +hh=`convert $tmpA1 -ping -format "%h" info:` + +# set default diameters +if [ "$dx" = "" ]; then + dx=$ww +fi +if [ "$dy" = "" ]; then + dy=$hh +fi + +# compute min diameter +dm=`convert xc: -format "%[fx:min($dx,$dy)]" info:` +if [ "$symmetry" = "yes" ]; then + dx=$dm + dy=$dm +fi + +# test diameters +[ $dx -eq 0 -o $dx -gt $ww ] && errMsg "--- X DIAMETER MUST BE GREATER THAN 0 AND LESS OR EQUAL TO IMAGE WIDTH ---" +[ $dy -eq 0 -o $dy -gt $hh ] && errMsg "--- Y DIAMETER MUST BE GREATER THAN 0 AND LESS OR EQUAL TO IMAGE HEIGHT ---" + + +# scale radius so that that image fits circle or ellipse at any diameter with zoom=1 +# invert zoom so increases with larger values +# use absolute coord displacement +# xamount=(rx/zoom)*(ww/dx)=ww/(2*zoom); where rx = x radius +xamount=`convert xc: -format "%[fx:$ww/(2*$zoom+quantumscale)]" info:` +yamount=`convert xc: -format "%[fx:$hh/(2*$zoom+quantumscale)]" info:` + + +# create radial gradient +convert -size ${dm}x${dm} radial-gradient: -negate $tmpF1 + +# convert circular gradient to elliptical +if [ $dx -ne $dy ]; then + convert $tmpF1 -resize ${dx}x${dy}! $tmpF1 +fi + +# create mask +convert $tmpF1 -negate -gravity center -background black -extent ${ww}x${hh} -threshold 0 $tmpM1 + +# set up amplify for distortion +if [ "$amp" = "1" ]; then + amplify="" +else + amplify="-evaluate pow $amp" +fi + +# compute spherize function F=(2/pi)*asin(rd)/rd +convert $tmpF1 \( +clone -function arcsin '2,0,2,0' $amplify \) \ + -compose divide -composite $tmpF1 + +# set up x displacement +# compute x gradient increasing with i +convert -size ${dy}x${dx} gradient: -rotate 90 $tmpX1 + +# compute u*v=xd*asin(rd)/rd; u=gradient 0,1; v=asin(rd)/rd +# but where want xd in range -1,1; so must use (2*u-1) +# then modify to 0.5*u*v+0.5 to recenter at mid gray +# old fx method: 0.5*((2*u-1)*v)+0.5 = u*v - 0.5*v + 0.5 +# convert $tmpX1 $tmpF1 -monitor -fx "u*v-0.5*v+0.5" $tmpX1 + +if [ "$im_version" -ge "06050403" ]; then + convert $tmpX1 $tmpF1 +swap \ + -compose Mathematics -set option:compose:args "1,0,-0.5,0.5" \ + -composite $tmpX1 +else + + # multiply arcsin(r)/(r) by abs of gradient relative to midgray as zero + # abs is computed as -solarize 50% -level 50,0% + # abs has V shape and ranges 0 to 1 + # then scale so that range is 0.5 to 1 + # + # convert gradient to sign of gradient + # sign is computed as -threshold 50% + # thus zero (for neg) on left and one (for pos) on right + # use sign as mask to separate the right (pos) side, + # then negate mask and arcsin-absgrad product + # to get the left (neg) side and then combine with right side + convert $tmpX1 $tmpF1 \ + \( -clone 0 -solarize 50% -level 50,0% \) \ + \( -clone 1,2 -compose multiply -composite -function polynomial "0.5,0.5" \) \ + \( -clone 0 -threshold 50% \) \ + \( -clone 3,4 -compose multiply -composite \) \ + \( -clone 3,4 -negate -compose multiply -composite \) \ + -delete 0-4 -compose plus -composite \ + $tmpX1 +fi + +# y displacement +if [ $dx -eq $dy ]; then + # map is symmetric so just rotate x displacement + convert $tmpX1 -rotate 90 $tmpY1 +else + # compute y gradient increasing with j + convert -size ${dx}x${dy} gradient: -negate $tmpY1 + + if [ "$im_version" -ge "06050403" ]; then + convert $tmpY1 $tmpF1 +swap \ + -compose Mathematics -set option:compose:args "1,0,-0.5,0.5" \ + -composite $tmpY1 + else + convert $tmpY1 $tmpF1 \ + \( -clone 0 -solarize 50% -level 50,0% \) \ + \( -clone 1,2 -compose multiply -composite -function polynomial "0.5,0.5" \) \ + \( -clone 0 -threshold 50% \) \ + \( -clone 3,4 -compose multiply -composite \) \ + \( -clone 3,4 -negate -compose multiply -composite \) \ + -delete 0-4 -compose plus -composite \ + $tmpY1 + fi +fi + +# displace image (center relative) +# absolute coord displacement +convert $tmpA1 $tmpX1 $tmpY1 \ + -gravity center -compose distort \ + -set option:compose:args ${xamount}x${yamount} -composite \ + $tmpB1 + +# set up trim +if [ "$trim" = "yes" ]; then + trimming="-gravity center -crop ${dx}x${dy}+0+0 +repage" +else + trimming="" +fi + +# composite mask +if [ "$bcolor" = "none" ]; then + convert $tmpB1 $tmpM1 \ + -alpha off -compose copy_opacity -composite $trimming "$outfile" +elif [ "$bcolor" = "image" -a "$symmetry" = "no" ]; then + convert $tmpB1 $trimming "$outfile" +elif [ "$bcolor" = "image" -a "$symmetry" = "yes" ]; then + convert $tmpA1 $tmpB1 $tmpM1 -compose over -composite $trimming "$outfile" +else + convert \( $tmpB1 $tmpM1 \ + -gravity center -alpha off -compose copy_opacity -composite \) \ + \( -size ${ww}x${hh} xc:"$bcolor" \) +swap \ + -gravity center -compose over -composite $trimming "$outfile" +fi + +exit 0 |
