Browse Source

Support RGB tuples for palette input

pull/3/head
makeworld 5 years ago
parent
commit
97d78f9de3
  1. 2
      README.md
  2. 4
      main.go
  3. 39
      subcommand_helpers.go

2
README.md

@ -34,7 +34,7 @@ It does not support images that make use of the alpha channel (transparency), bu
More methods of dithering are being worked on, such as Riemersma, Yuliluoma, and blue noise. If you'd like to help out with development of those methods, or request a new one, please make an issue in my [dither](https://github.com/makeworld-the-better-one/dither) library repo, not this one. More methods of dithering are being worked on, such as Riemersma, Yuliluoma, and blue noise. If you'd like to help out with development of those methods, or request a new one, please make an issue in my [dither](https://github.com/makeworld-the-better-one/dither) library repo, not this one.
## Features ## Features
- Set palette using hex codes, number 0-255 (grayscale), or [SVG color names](https://www.w3.org/TR/SVG11/types.html#ColorKeywords) - Set palette using RGB tuples, hex codes, number 0-255 (grayscale), or [SVG color names](https://www.w3.org/TR/SVG11/types.html#ColorKeywords)
- All colors are interpreted in the sRGB colorspace - All colors are interpreted in the sRGB colorspace
- Optionally recolor image with a different palette after dithering - Optionally recolor image with a different palette after dithering
- Set dithering strength - Set dithering strength

4
main.go

@ -31,8 +31,8 @@ func main() {
description = ` description = `
Colors (for --palette and --recolor) are entered as a single quoted argument. Colors (for --palette and --recolor) are entered as a single quoted argument.
They can be separated by spaces and commas. Colors can be formatted as hex They can be separated by spaces and commas. Colors can be formatted as RGB tuples,
codes (case-insensitive, with or without the '#'), a single number from 0-255 hex codes (case-insensitive, with or without the '#'), a single number from 0-255
for grayscale, or a color name from the SVG 1.1 spec (aka the HTML or W3C for grayscale, or a color name from the SVG 1.1 spec (aka the HTML or W3C
color names). All colors are interpreted in the sRGB colorspace. color names). All colors are interpreted in the sRGB colorspace.

39
subcommand_helpers.go

@ -66,7 +66,7 @@ func globalFlag(flag string, c *cli.Context) interface{} {
func globalIsSet(flag string, c *cli.Context) bool { func globalIsSet(flag string, c *cli.Context) bool {
ancestor := c.Lineage()[len(c.Lineage())-1] ancestor := c.Lineage()[len(c.Lineage())-1]
if len(ancestor.Args().Slice()) == 0 { if len(ancestor.Args().Slice()) == 0 {
// See globalFlag // See globalFlag for why this if statement exists
return c.Lineage()[len(c.Lineage())-2].IsSet(flag) return c.Lineage()[len(c.Lineage())-2].IsSet(flag)
} }
return ancestor.IsSet(flag) return ancestor.IsSet(flag)
@ -88,8 +88,11 @@ func parseArgs(args []string, splitRunes string) []string {
return finalArgs return finalArgs
} }
func hex2Color(hex string) (color.RGBA, error) { func hexToColor(hex string) (color.RGBA, error) {
// Modified from https://github.com/lucasb-eyer/go-colorful/blob/v1.2.0/colors.go#L333 // Modified from https://github.com/lucasb-eyer/go-colorful/blob/v1.2.0/colors.go#L333
hex = strings.TrimPrefix(hex, "#")
format := "%02x%02x%02x" format := "%02x%02x%02x"
var r, g, b uint8 var r, g, b uint8
n, err := fmt.Sscanf(strings.ToLower(hex), format, &r, &g, &b) n, err := fmt.Sscanf(strings.ToLower(hex), format, &r, &g, &b)
@ -97,7 +100,20 @@ func hex2Color(hex string) (color.RGBA, error) {
return color.RGBA{}, err return color.RGBA{}, err
} }
if n != 3 { if n != 3 {
return color.RGBA{}, fmt.Errorf("%v is not a hex color", hex) return color.RGBA{}, fmt.Errorf("%s is not a hex color", hex)
}
return color.RGBA{r, g, b, 255}, nil
}
func rgbToColor(s string) (color.RGBA, error) {
format := "%d,%d,%d"
var r, g, b uint8
n, err := fmt.Sscanf(s, format, &r, &g, &b)
if err != nil {
return color.RGBA{}, err
}
if n != 3 {
return color.RGBA{}, fmt.Errorf("%s is not an RGB tuple", s)
} }
return color.RGBA{r, g, b, 255}, nil return color.RGBA{r, g, b, 255}, nil
} }
@ -105,13 +121,22 @@ func hex2Color(hex string) (color.RGBA, error) {
// parseColors takes args and turns them into a color slice. All returned // parseColors takes args and turns them into a color slice. All returned
// colors are guaranteed to only be color.RGBA. // colors are guaranteed to only be color.RGBA.
func parseColors(flag string, c *cli.Context) ([]color.Color, error) { func parseColors(flag string, c *cli.Context) ([]color.Color, error) {
args := parseArgs([]string{globalFlag(flag, c).(string)}, " ,#") args := parseArgs([]string{globalFlag(flag, c).(string)}, " ")
colors := make([]color.Color, len(args)) colors := make([]color.Color, len(args))
for i, arg := range args { for i, arg := range args {
// Try to parse as hex, then grayscale, then HTML colors, then fail // Try to parse as RGB numbers, then hex, then grayscale, then SVG colors, then fail
if strings.Count(arg, ",") == 2 {
rgbColor, err := rgbToColor(arg)
if err != nil {
return nil, fmt.Errorf("%s: %s is not a valid RGB tuple. Example: 25,200,150", flag, arg)
}
colors[i] = rgbColor
continue
}
hexColor, err := hex2Color(arg) hexColor, err := hexToColor(arg)
if err == nil { if err == nil {
colors[i] = hexColor colors[i] = hexColor
continue continue
@ -132,7 +157,7 @@ func parseColors(flag string, c *cli.Context) ([]color.Color, error) {
continue continue
} }
return nil, fmt.Errorf("%s: %s not recognized as a hex code, number 0-255, or HTML color name", flag, arg) return nil, fmt.Errorf("%s: %s not recognized as an RGB tuple, hex code, number 0-255, or SVG color name", flag, arg)
} }
return colors, nil return colors, nil

Loading…
Cancel
Save