gen.mx raw

   1  // Copyright 2013 The Go Authors. All rights reserved.
   2  // Use of this source code is governed by a BSD-style
   3  // license that can be found in the LICENSE file.
   4  
   5  //go:build ignore
   6  
   7  package main
   8  
   9  // This program generates palette.go. Invoke it as
  10  //	go run gen.go -output palette.go
  11  
  12  import (
  13  	"bytes"
  14  	"flag"
  15  	"fmt"
  16  	"go/format"
  17  	"io"
  18  	"log"
  19  	"os"
  20  )
  21  
  22  var filename = flag.String("output", "palette.go", "output file name")
  23  
  24  func main() {
  25  	flag.Parse()
  26  
  27  	var buf bytes.Buffer
  28  
  29  	fmt.Fprintln(&buf, `// Copyright 2013 The Go Authors. All rights reserved.
  30  // Use of this source code is governed by a BSD-style
  31  // license that can be found in the LICENSE file.`)
  32  	fmt.Fprintln(&buf)
  33  	fmt.Fprintln(&buf, "// Code generated by go run gen.go -output palette.go; DO NOT EDIT.")
  34  	fmt.Fprintln(&buf)
  35  	fmt.Fprintln(&buf, "package palette")
  36  	fmt.Fprintln(&buf)
  37  	fmt.Fprintln(&buf, `import "image/color"`)
  38  	fmt.Fprintln(&buf)
  39  	printPlan9(&buf)
  40  	printWebSafe(&buf)
  41  
  42  	data, err := format.Source(buf.Bytes())
  43  	if err != nil {
  44  		log.Fatal(err)
  45  	}
  46  	err = os.WriteFile(*filename, data, 0644)
  47  	if err != nil {
  48  		log.Fatal(err)
  49  	}
  50  }
  51  
  52  func printPlan9(w io.Writer) {
  53  	c, lines := [3]int{}, [256][]byte{}
  54  	for r, i := 0, 0; r != 4; r++ {
  55  		for v := 0; v != 4; v, i = v+1, i+16 {
  56  			for g, j := 0, v-r; g != 4; g++ {
  57  				for b := 0; b != 4; b, j = b+1, j+1 {
  58  					den := r
  59  					if g > den {
  60  						den = g
  61  					}
  62  					if b > den {
  63  						den = b
  64  					}
  65  					if den == 0 {
  66  						c[0] = 0x11 * v
  67  						c[1] = 0x11 * v
  68  						c[2] = 0x11 * v
  69  					} else {
  70  						num := 17 * (4*den + v)
  71  						c[0] = r * num / den
  72  						c[1] = g * num / den
  73  						c[2] = b * num / den
  74  					}
  75  					lines[i+(j&0x0f)] =
  76  						fmt.Sprintf("\tcolor.RGBA{0x%02x, 0x%02x, 0x%02x, 0xff},", c[0], c[1], c[2])
  77  				}
  78  			}
  79  		}
  80  	}
  81  	fmt.Fprintln(w, "// Plan9 is a 256-color palette that partitions the 24-bit RGB space")
  82  	fmt.Fprintln(w, "// into 4×4×4 subdivision, with 4 shades in each subcube. Compared to the")
  83  	fmt.Fprintln(w, "// [WebSafe], the idea is to reduce the color resolution by dicing the")
  84  	fmt.Fprintln(w, "// color cube into fewer cells, and to use the extra space to increase the")
  85  	fmt.Fprintln(w, "// intensity resolution. This results in 16 gray shades (4 gray subcubes with")
  86  	fmt.Fprintln(w, "// 4 samples in each), 13 shades of each primary and secondary color (3")
  87  	fmt.Fprintln(w, "// subcubes with 4 samples plus black) and a reasonable selection of colors")
  88  	fmt.Fprintln(w, "// covering the rest of the color cube. The advantage is better representation")
  89  	fmt.Fprintln(w, "// of continuous tones.")
  90  	fmt.Fprintln(w, "//")
  91  	fmt.Fprintln(w, "// This palette was used in the Plan 9 Operating System, described at")
  92  	fmt.Fprintln(w, "// https://9p.io/magic/man2html/6/color")
  93  	fmt.Fprintln(w, "var Plan9 = []color.Color{")
  94  	for _, line := range lines {
  95  		fmt.Fprintln(w, line)
  96  	}
  97  	fmt.Fprintln(w, "}")
  98  	fmt.Fprintln(w)
  99  }
 100  
 101  func printWebSafe(w io.Writer) {
 102  	lines := [6 * 6 * 6][]byte{}
 103  	for r := 0; r < 6; r++ {
 104  		for g := 0; g < 6; g++ {
 105  			for b := 0; b < 6; b++ {
 106  				lines[36*r+6*g+b] =
 107  					fmt.Sprintf("\tcolor.RGBA{0x%02x, 0x%02x, 0x%02x, 0xff},", 0x33*r, 0x33*g, 0x33*b)
 108  			}
 109  		}
 110  	}
 111  	fmt.Fprintln(w, "// WebSafe is a 216-color palette that was popularized by early versions")
 112  	fmt.Fprintln(w, "// of Netscape Navigator. It is also known as the Netscape Color Cube.")
 113  	fmt.Fprintln(w, "//")
 114  	fmt.Fprintln(w, "// See https://en.wikipedia.org/wiki/Web_colors#Web-safe_colors for details.")
 115  	fmt.Fprintln(w, "var WebSafe = []color.Color{")
 116  	for _, line := range lines {
 117  		fmt.Fprintln(w, line)
 118  	}
 119  	fmt.Fprintln(w, "}")
 120  	fmt.Fprintln(w)
 121  }
 122