123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- package gg
- import (
- "fmt"
- "image"
- "image/draw"
- "image/jpeg"
- _ "image/jpeg"
- "image/png"
- "io/ioutil"
- "math"
- "os"
- "strings"
- "github.com/golang/freetype/truetype"
- "golang.org/x/image/font"
- "golang.org/x/image/math/fixed"
- )
- func Radians(degrees float64) float64 {
- return degrees * math.Pi / 180
- }
- func Degrees(radians float64) float64 {
- return radians * 180 / math.Pi
- }
- func LoadImage(path string) (image.Image, error) {
- file, err := os.Open(path)
- if err != nil {
- return nil, err
- }
- defer file.Close()
- im, _, err := image.Decode(file)
- return im, err
- }
- func LoadPNG(path string) (image.Image, error) {
- file, err := os.Open(path)
- if err != nil {
- return nil, err
- }
- defer file.Close()
- return png.Decode(file)
- }
- func SavePNG(path string, im image.Image) error {
- file, err := os.Create(path)
- if err != nil {
- return err
- }
- defer file.Close()
- return png.Encode(file, im)
- }
- func LoadJPG(path string) (image.Image, error) {
- file, err := os.Open(path)
- if err != nil {
- return nil, err
- }
- defer file.Close()
- return jpeg.Decode(file)
- }
- func SaveJPG(path string, im image.Image, quality int) error {
- file, err := os.Create(path)
- if err != nil {
- return err
- }
- defer file.Close()
- var opt jpeg.Options
- opt.Quality = quality
- return jpeg.Encode(file, im, &opt)
- }
- func imageToRGBA(src image.Image) *image.RGBA {
- bounds := src.Bounds()
- dst := image.NewRGBA(bounds)
- draw.Draw(dst, bounds, src, bounds.Min, draw.Src)
- return dst
- }
- func parseHexColor(x string) (r, g, b, a int) {
- x = strings.TrimPrefix(x, "#")
- a = 255
- if len(x) == 3 {
- format := "%1x%1x%1x"
- fmt.Sscanf(x, format, &r, &g, &b)
- r |= r << 4
- g |= g << 4
- b |= b << 4
- }
- if len(x) == 6 {
- format := "%02x%02x%02x"
- fmt.Sscanf(x, format, &r, &g, &b)
- }
- if len(x) == 8 {
- format := "%02x%02x%02x%02x"
- fmt.Sscanf(x, format, &r, &g, &b, &a)
- }
- return
- }
- func fixp(x, y float64) fixed.Point26_6 {
- return fixed.Point26_6{fix(x), fix(y)}
- }
- func fix(x float64) fixed.Int26_6 {
- return fixed.Int26_6(x * 64)
- }
- func unfix(x fixed.Int26_6) float64 {
- const shift, mask = 6, 1<<6 - 1
- if x >= 0 {
- return float64(x>>shift) + float64(x&mask)/64
- }
- x = -x
- if x >= 0 {
- return -(float64(x>>shift) + float64(x&mask)/64)
- }
- return 0
- }
- // LoadFontFace is a helper function to load the specified font file with
- // the specified point size. Note that the returned `font.Face` objects
- // are not thread safe and cannot be used in parallel across goroutines.
- // You can usually just use the Context.LoadFontFace function instead of
- // this package-level function.
- func LoadFontFace(path string, points float64) (font.Face, error) {
- fontBytes, err := ioutil.ReadFile(path)
- if err != nil {
- return nil, err
- }
- f, err := truetype.Parse(fontBytes)
- if err != nil {
- return nil, err
- }
- face := truetype.NewFace(f, &truetype.Options{
- Size: points,
- // Hinting: font.HintingFull,
- })
- return face, nil
- }
|