1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
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
}
|