func hexToRGB(h string) (uint8, uint8, uint8) {
	if len(h) > 0 && h[0] == '#' {
		h = h[1:]
	}
	if len(h) == 3 {
		h = h[:1] + h[:1] + h[1:2] + h[1:2] + h[2:] + h[2:]
	}
	if len(h) == 6 {
		if rgb, err := strconv.ParseUint(string(h), 16, 32); err == nil {
			return uint8(rgb >> 16), uint8((rgb >> 8) & 0xFF), uint8(rgb & 0xFF)
		}
	}
	return 0, 0, 0
}
hexToRGB converts a hex string to a RGB triple.
Credit: https://code.google.com/p/gorilla/source/browse/color/hex.go?r=ef489f63418265a7249b1d53bdc358b09a4a2ea0
package main
import (
	"flag"
	"fmt"
	"image/color"
	"image/png"
	"log"
	"os"
	"strconv"
	"github.com/mdlayher/waveform"
)
const (
	app = "waveform"
	fnChecker  = "checker"
	fnFuzz     = "fuzz"
	fnGradient = "gradient"
	fnSolid    = "solid"
	fnStripe   = "stripe"
)
var (
	strBGColor = flag.String("bg", "#FFFFFF", "hex background color of output waveform image")
	strFGColor = flag.String("fg", "#000000", "hex foreground color of output waveform image")
	strAltColor = flag.String("alt", "", "hex alternate color of output waveform image")
	resolution = flag.Uint("resolution", 1, "number of times audio is read and drawn per second of audio")
	scaleX = flag.Uint("x", 1, "scaling factor for image X-axis")
	scaleY = flag.Uint("y", 1, "scaling factor for image Y-axis")
	sharpness = flag.Uint("sharpness", 1, "sharpening factor used to add curvature to a scaled image")
	strFn = flag.String("fn", fnSolid, "function used to color output waveform image "+fnOptions)
)
var fnOptions = fmt.Sprintf("[options: %s, %s, %s, %s, %s]", fnChecker, fnFuzz, fnGradient, fnSolid, fnStripe)
func main() {
	flag.Parse()
	log.SetOutput(os.Stderr)
	log.SetPrefix(app + ": ")
	colorR, colorG, colorB := hexToRGB(*strBGColor)
	bgColor := color.RGBA{colorR, colorG, colorB, 255}
	colorR, colorG, colorB = hexToRGB(*strFGColor)
	fgColor := color.RGBA{colorR, colorG, colorB, 255}
	altColor := fgColor
	if *strAltColor != "" {
		colorR, colorG, colorB = hexToRGB(*strAltColor)
		altColor = color.RGBA{colorR, colorG, colorB, 255}
	}
	fnSet := map[string]waveform.ColorFunc{
		fnChecker:  waveform.CheckerColor(fgColor, altColor, 10),
		fnFuzz:     waveform.FuzzColor(fgColor, altColor),
		fnGradient: waveform.GradientColor(fgColor, altColor),
		fnSolid:    waveform.SolidColor(fgColor),
		fnStripe:   waveform.StripeColor(fgColor, altColor),
	}
	colorFn, ok := fnSet[*strFn]
	if !ok {
		log.Fatalf("unknown function: %q %s", *strFn, fnOptions)
	}
	img, err := waveform.Generate(os.Stdin,
		waveform.BGColorFunction(waveform.SolidColor(bgColor)),
		waveform.FGColorFunction(colorFn),
		waveform.Resolution(*resolution),
		waveform.Scale(*scaleX, *scaleY),
		waveform.ScaleClipping(),
		waveform.Sharpness(*sharpness),
	)
	if err != nil {
		knownErr := map[error]struct{}{
			waveform.ErrFormat:        struct{}{},
			waveform.ErrInvalidData:   struct{}{},
			waveform.ErrUnexpectedEOS: struct{}{},
		}
		if _, ok := knownErr[err]; ok {
			log.Fatal(err)
		}
		panic(err)
	}
	if err := png.Encode(os.Stdout, img); err != nil {
		panic(err)
	}
}