Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CSS4() and JSON() methods to Palette. #5

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions palette.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package vibrant

import (
"encoding/json"
"errors"
"image"
"math"
"strings"
)

// These constants are taken directly from the Android Palette source code,
Expand Down Expand Up @@ -36,6 +38,107 @@ type Palette struct {
selected []*Swatch
}

// CSS4
//
// Export as CSS4 variables. Use in your CSS with var()
// e.g. html { background-color: var(--vibrant); }
//
// FIXME(day): variable names not final
// FIXME(day): variable names not final
// FIXME(day): variable names not final
// --vibrant:#123456;
// --vibrantText:#ffffff;
// --darkvibrant:#123456;
// --darkvibrantText:#ffffff;
// --lightvibrant:#123456;
// --lightvibrantText:#ffffff;
// --muted:#123456;
// --mutedText:#ffffff;
// --darkmuted:#123456;
// --darkmutedText:#ffffff;
// --lightmuted:#123456;
// --lightmutedText:#ffffff;
func (p *Palette) CSS4() string {
out := ""
for k, sw := range p.ExtractAwesome() {
// @consistency these variable names should match JSON output
// @consistency these variable names should match JSON output
// @consistency these variable names should match JSON output
out += "--" + strings.ToLower(k) + ":" + sw.Color.String() + ";"
out += "--" + strings.ToLower(k) + "Text:" + sw.Color.TitleTextColor().String() + ";"
}
return out
}

// JSON
//
// err should always be nil unless something catastrophic is happening.
//
// JSON structure:
//
// {
// "vibrant": 0x123456,
// "dark-vibrant": 0x123456,
// "light-vibrant": 0x123456,
// "muted": 0x123456,
// "dark-muted": 0x123456,
// "light-muted": 0x123456,
// "vibrant-text": 0x123456,
// "dark-vibrant-text": 0x123456,
// "light-vibrant-text": 0x123456,
// "muted-text": 0x123456,
// "dark-muted-text": 0x123456,
// "light-muted-text": 0x123456
// }
//
// Please note that encoding/json encodes hex numbers as decimal integers
// Please note that encoding/json encodes hex numbers as decimal integers
// Please note that encoding/json encodes hex numbers as decimal integers
func (p *Palette) JSON() ([]byte, error) {
// NOTE(day): As I type this I realize a more elegant data structure might look like
// {
// "vibrant": {"color": 0x99ccff, "text": 0xffffff},
// "dark-vibrant": {"color": 0x00007f, "text": 0xffffff},
// ...
// }
// also using PascalCase camelCase or snake_case instead of kebab-case
// might yield a more pleasurable user experience.
// this library was designed for CSS webdev stuff (that's why vibrant.Color.String() returns #abcdef oh. Oh. I just realized something...
// -day Sun 11 Jun 2023 10:28:06 PM EDT
// email me@dayvonjersen if you disagree =)
// -day Sun 11 Jun 2023 09:57:57 PM EDT
type vibrantJSON struct {
Vibrant int `json:"vibrant"`
DarkVibrant int `json:"dark-vibrant"`
LightVibrant int `json:"light-vibrant"`
Muted int `json:"muted"`
DarkMuted int `json:"dark-muted"`
LightMuted int `json:"light-muted"`
VibrantText int `json:"vibrant-text"`
DarkVibrantText int `json:"dark-vibrant-text"`
LightVibrantText int `json:"light-vibrant-text"`
MutedText int `json:"muted-text"`
DarkMutedText int `json:"dark-muted-text"`
LightMutedText int `json:"light-muted-text"`
}
this := p.ExtractAwesome()
choose := func(sw *Swatch, defaultColor int, defaultText int) (primary, text int) {
if sw == nil {
return defaultColor, defaultText
}
return int(sw.Color), int(sw.Color.TitleTextColor())
}
// NOTE(day): sensible fallback colors (greyscale)
data := &vibrantJSON{}
data.Vibrant, data.VibrantText = choose(this["Vibrant"], 0xacaaaa, 0x0)
data.LightVibrant, data.LightVibrantText = choose(this["LightVibrant"], 0xffffff, 0x0)
data.DarkVibrant, data.DarkVibrantText = choose(this["DarkVibrant"], 0x2b2b2b, 0xffffff)
data.LightMuted, data.LightMutedText = choose(this["LightMuted"], 0xdad5d5, 0x0)
data.DarkMuted, data.DarkMutedText = choose(this["DarkMuted"], 0x32312f, 0xffffff)
data.Muted, data.MutedText = choose(this["Muted"], 0x6d6a6a, 0xffffff)
return json.Marshal(data)
}

// Calls NewPalette with DEFAULT_CALCULATE_NUMBER_COLORS as a default value for numColors.
func NewPaletteFromImage(img image.Image) (Palette, error) {
return NewPalette(img, DEFAULT_CALCULATE_NUMBER_COLORS)
Expand Down
22 changes: 14 additions & 8 deletions webapp.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
//go:build ignore
// +build ignore

/*
sample webapp to demo the functionality of github.com/dayvonjersen/vibrant
sample webapp to demo the functionality of github.com/dayvonjersen/vibrant

base64 encoding the images provides the benefit of not having to manage
uploaded files or do any javascript fanciness but comes with a performance penalty
base64 encoding the images provides the benefit of not having to manage
uploaded files or do any javascript fanciness but comes with a performance penalty

DO NOT USE THIS IN A PRODUCTION ENVIRONMENT
DO NOT USE THIS IN A PRODUCTION ENVIRONMENT
*/
package main

Expand All @@ -17,6 +18,7 @@ import (
"io"
"log"
"net/http"
"sorbet/vibrant"
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I knew there was a reason to check the diff. Have to add a go.mod file or merge #4

"strconv"
"time"

Expand All @@ -25,8 +27,6 @@ import (
_ "image/png"

"text/template"

"github.com/dayvonjersen/vibrant"
)

func index(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -56,6 +56,7 @@ func index(w http.ResponseWriter, r *http.Request) {
Benchmark time.Duration
DefaultMaxColors int
MaxColors int
JSON, CSS4 string
}{DefaultMaxColors: vibrant.DEFAULT_CALCULATE_NUMBER_COLORS,
MaxColors: vibrant.DEFAULT_CALCULATE_NUMBER_COLORS}

Expand Down Expand Up @@ -133,6 +134,9 @@ func index(w http.ResponseWriter, r *http.Request) {
}
}
data.Stylesheet = stylesheet
j, _ := palette.JSON()
data.JSON = string(j)
data.CSS4 = palette.CSS4()
data.Missing = len(awesome) != 6
setStatus(200)
data.Response = true
Expand All @@ -141,8 +145,8 @@ func index(w http.ResponseWriter, r *http.Request) {

func main() {
http.HandleFunc("/", index)
log.Println("Listening on :8080...")
log.Fatalln(http.ListenAndServe(":8080", nil))
log.Println("Listening on :9999...")
log.Fatalln(http.ListenAndServe(":9999", nil))
}

const tpl = `
Expand Down Expand Up @@ -264,6 +268,8 @@ h2 {
</figcaption>
</figure>
<textarea readonly onclick='this.select()'>{{.Stylesheet}}</textarea>
<textarea readonly onclick='this.select()'>{{.JSON}}</textarea>
<textarea readonly onclick='this.select()'>{{.CSS4}}</textarea>
{{ if .Missing }}
<h3>If color swatches are missing, try increasing <code>maxColors</code> in the text field above.</h3>
{{ end }}
Expand Down