func Example() { // As usual in examples, this ignores all errors. Don't do this in your program. // setup and find start point for centering s := "Hello, World!" size := image.Rect(0, 0, 120, 20) dst := image.NewRGBA(size) c := freetype.NewContext() c.SetFont(font) c.SetFontSize(14.0) c.SetSrc(image.NewUniform(color.Black)) c.SetDst(dst) start, _ := fontutil.CenterX(c, s, size) // CenterX calls c.SetClip(size) // perform draw at start.X + y 16 c.DrawString(s, start.Add(freetype.Pt(0, 16))) // write the image out to a file // out, _ := os.Create("helloworld.png") // defer out.Close() // write image to hash for testing purposes out := fnv.New64() _ = png.Encode(out, dst) fmt.Printf("Hash of compressed image: %x", out.Sum64()) // Output: Hash of compressed image: fa83a1b8d8abf5f2 }
func (this *Signer) drawStringImage(text string) (image.Image, error) { fontBytes, err := ioutil.ReadFile(this.fontPath) if err != nil { fmt.Println(err) } font, err := freetype.ParseFont(fontBytes) if err != nil { fmt.Println(err) } rgba := image.NewRGBA(image.Rect(0, 0, 900, 900)) draw.Draw(rgba, rgba.Bounds(), image.Black, image.ZP, draw.Src) c := freetype.NewContext() c.SetDPI(this.dpi) c.SetFontSize(this.fontSize) c.SetClip(rgba.Bounds()) c.SetDst(rgba) c.SetSrc(image.White) c.SetFont(font) pt := freetype.Pt(100, 100+int(c.PointToFixed(this.fontSize)>>8)) for _, s := range strings.Split(text, "\r\n") { _, err = c.DrawString(s, pt) pt.Y += c.PointToFixed(12 * 1.5) } return rgba, nil }
func (f *Font) Render(text string) *Texture { width, height, yBearing := f.TextDimensions(text) font := f.ttf size := f.Size // Colors fg := image.NewUniform(color.NRGBA{f.FG.R, f.FG.G, f.FG.B, f.FG.A}) bg := image.NewUniform(color.NRGBA{f.BG.R, f.BG.G, f.BG.B, f.BG.A}) // Create the font context c := freetype.NewContext() nrgba := image.NewNRGBA(image.Rect(0, 0, width, height)) draw.Draw(nrgba, nrgba.Bounds(), bg, image.ZP, draw.Src) c.SetDPI(dpi) c.SetFont(font) c.SetFontSize(size) c.SetClip(nrgba.Bounds()) c.SetDst(nrgba) c.SetSrc(fg) // Draw the text. pt := freetype.Pt(0, int(yBearing)) _, err := c.DrawString(text, pt) if err != nil { log.Println(err) return nil } // Create texture imObj := &ImageObject{nrgba} return NewTexture(imObj) }
func (a *Annotator) init() error { // load the font fontBytes, err := resources.Asset(fontfile) if err != nil { return err } luxisr, err := freetype.ParseFont(fontBytes) if err != nil { return err } // Initialize the context. fg := image.White a.context = freetype.NewContext() a.context.SetDPI(dpi) a.context.SetFont(luxisr) a.context.SetFontSize(size) a.context.SetClip(a.image.Bounds()) a.context.SetDst(a.image) a.context.SetSrc(fg) switch hinting { default: a.context.SetHinting(font.HintingNone) case "full": a.context.SetHinting(font.HintingFull) } return nil }
func NewFontFace(path string, size float64, fg, bg color.Color) (fontface *FontFace, err error) { var ( font *truetype.Font fontbytes []byte bounds truetype.Bounds context *freetype.Context scale float32 ) if fontbytes, err = ioutil.ReadFile(path); err != nil { return } if font, err = freetype.ParseFont(fontbytes); err != nil { return } bounds = font.Bounds(1) fmt.Printf("bounds %v\n", bounds) context = freetype.NewContext() context.SetFont(font) context.SetFontSize(size) context.SetDPI(72) scale = float32(context.PointToFixed(size) / 64) fontface = &FontFace{ font: font, charw: scale * float32(bounds.XMax-bounds.XMin), charh: scale * float32(bounds.YMax-bounds.YMin), fg: fg, bg: bg, context: context, } return }
func NewFontFace(path string, pixels float32, fg, bg color.Color) (fontface *FontFace, err error) { var ( font *truetype.Font fontbytes []byte bounds fixed.Rectangle26_6 context *freetype.Context points float32 dpi float32 = 96 ) if fontbytes, err = ioutil.ReadFile(path); err != nil { return } if font, err = freetype.ParseFont(fontbytes); err != nil { return } points = pixels * 72 / dpi bounds = font.Bounds(fixed.I(int(pixels))) context = freetype.NewContext() context.SetFont(font) context.SetFontSize(float64(points)) context.SetDPI(float64(dpi)) fontface = &FontFace{ font: font, charw: float32(bounds.Max.X-bounds.Min.X) / 64, charh: float32(bounds.Max.Y-bounds.Min.Y) / 64, offy: float32(bounds.Min.Y) / 64, fg: fg, bg: bg, context: context, } return }
// initLayout constructs two masks for drawing the battery and the remaining // energy as well as sets the pixel bounds for drawing energy capacity. the // masks allow for simplified space-fills and reduced chance of pixel gaps. func (app *App) initLayout() { var zeropt image.Point rectOutTop := image.Rectangle{Min: app.Layout.battRect.Min, Max: app.Layout.battRect.Min.Add(image.Point{2, 2})} rectOutBottom := rectOutTop.Add(image.Point{Y: app.Layout.battRect.Size().Y - rectOutTop.Size().Y}) capRect := image.Rectangle{ Min: image.Point{X: rectOutTop.Min.X, Y: rectOutTop.Max.Y}, Max: image.Point{X: rectOutBottom.Max.X, Y: rectOutBottom.Min.Y}, } bodyRect := app.Layout.battRect bodyRect.Min.X = capRect.Max.X // energy will be drawn under the battery shell. The only place where it // is not safe to draw energy is outside the battery on the positive end. energyMask := image.NewAlpha(app.Layout.battRect) draw.Draw(energyMask, app.Layout.battRect, opaque, zeropt, draw.Over) draw.Draw(energyMask, rectOutTop, transparent, zeropt, draw.Src) draw.Draw(energyMask, rectOutBottom, transparent, zeropt, draw.Src) app.maskEnergy = energyMask // the body uses the same mask as the energy with additional transparency // inside the battery's shell. the mask construction is complex because // area inside the cap may be exposed. bodyMask := image.NewAlpha(app.Layout.battRect) draw.Draw(bodyMask, app.Layout.battRect, energyMask, app.Layout.battRect.Min, draw.Over) bodyMaskRect := shrinkRect(bodyRect, app.Layout.thickness) draw.Draw(bodyMask, bodyMaskRect, transparent, zeropt, draw.Src) capMaskRect := shrinkRect(capRect, app.Layout.thickness) capMaskRect.Max.X += 2 * app.Layout.thickness draw.Draw(bodyMask, capMaskRect, transparent, zeropt, draw.Src) app.maskBattery = bodyMask // create a freetype.Context to render text. each time the context is used // it must have its SetDst method called. app.tt = freetype.NewContext() app.tt.SetSrc(black) app.tt.SetClip(app.Layout.textRect) app.tt.SetDPI(app.Layout.DPI) app.tt.SetFont(app.Layout.font) app.tt.SetFontSize(app.Layout.fontSize) ttopt := &truetype.Options{ Size: app.Layout.fontSize, DPI: app.Layout.DPI, } ttface := truetype.NewFace(app.Layout.font, ttopt) app.font = &font.Drawer{ Src: black, Face: ttface, } // the rectangle in which energy is drawn needs to account for thickness to // make the visible percentage more accurate. after adjustment reduce the // energy rect to account for the account of energy drained. the energy // mask makes computing Y bounds largely irrelevant. app.minEnergy = capMaskRect.Min.X app.maxEnergy = bodyMaskRect.Max.X }
func main() { fontBytes, err := ioutil.ReadFile("luxisr.ttf") if err != nil { log.Fatal(err) } font, err := freetype.ParseFont(fontBytes) if err != nil { log.Fatal(err) } fg, bg := image.White, image.Black rgba := image.NewRGBA(image.Rect(0, 0, width, height)) draw.Draw(rgba, rgba.Bounds(), bg, image.ZP, draw.Src) c := freetype.NewContext() c.SetDPI(dpi) c.SetFont(font) c.SetFontSize(size) c.SetClip(rgba.Bounds()) c.SetDst(rgba) c.SetSrc(fg) c.SetHinting(freetype.FullHinting) count := 0 l := NewLife(width, height) for { if count%10 == 0 { count = 0 pt := freetype.Pt(rand.Intn(width-width/4), height/4+rand.Intn(height-height/4)) c.DrawString("NOPE", pt) for x := 0; x < width; x++ { for y := 0; y < height; y++ { c := rgba.RGBAAt(x, y) l.a.Set(x, y, c.R > 0 || c.B > 0 || c.G > 0) } } } count++ for x := 0; x < width; x++ { for y := 0; y < height; y++ { var c color.Color = color.Black if l.a.Alive(x, y) { c = rainbow(y) } rgba.Set(x, y, c) } } //fmt.Println(l) sendImage(rgba) l.Step() time.Sleep(time.Second / 8) } }
// Write a text inside the image func WriteText(text string, f *truetype.Font, img *image.Paletted) { // Initialize the context. fg := image.Black c := freetype.NewContext() c.SetDPI(72) c.SetFont(f) c.SetFontSize(64) c.SetClip(img.Bounds()) c.SetDst(img) c.SetSrc(fg) // Draw the text. pt := freetype.Pt(40, 120) c.DrawString(text, pt) }
func (ig *ImageGraphics) TextLen(s string, font chart.Font) int { c := freetype.NewContext() c.SetDPI(dpi) c.SetFont(ig.font) fontsize := ig.relFontsizeToPixel(font.Size) c.SetFontSize(fontsize) // really draw it width, err := c.DrawString(s, freetype.Pt(0, 0)) if err != nil { return 10 * len(s) // BUG } return int(width.X+32)>>6 + 1 }
func MakeTextLine(font_name, text string, width int, r, g, b, a float64) *TextLine { var w TextLine w.EmbeddedWidget = &BasicWidget{CoreWidget: &w} font, ok := basic_fonts[font_name] if !ok { panic(fmt.Sprintf("Unable to find a font registered as '%s'.", font_name)) } w.font = font w.glyph_buf = &truetype.GlyphBuf{} w.next_text = text w.context = freetype.NewContext() w.context.SetDPI(132) w.context.SetFontSize(12) w.SetColor(r, g, b, a) w.Request_dims = Dims{width, 35} return &w }
func (f *Font) RenderNRGBA(text string) *image.NRGBA { width, height, yBearing := f.TextDimensions(text) font := f.TTF size := f.Size if size <= 0 { panic("Font size cannot be <= 0") } // Default colors if f.FG == nil { f.FG = color.NRGBA{0, 0, 0, 0} } if f.BG == nil { f.BG = color.NRGBA{0, 0, 0, 0} } // Colors fg := image.NewUniform(f.FG) bg := image.NewUniform(f.BG) // Create the font context c := freetype.NewContext() nrgba := image.NewNRGBA(image.Rect(0, 0, width, height)) draw.Draw(nrgba, nrgba.Bounds(), bg, image.ZP, draw.Src) c.SetDPI(dpi) c.SetFont(font) c.SetFontSize(size) c.SetClip(nrgba.Bounds()) c.SetDst(nrgba) c.SetSrc(fg) // Draw the text. pt := fixed.P(0, int(yBearing)) _, err := c.DrawString(text, pt) if err != nil { log.Println(err) return nil } return nrgba }
func main() { imgcounter := 123 imgfile, _ := os.Create(fmt.Sprintf("%03d.png", imgcounter)) defer imgfile.Close() img := image.NewNRGBA(image.Rect(0, 0, dx, dy)) for y := 0; y < dy; y++ { for x := 0; x < dx; x++ { img.Set(x, y, color.RGBA{uint8(x), uint8(y), 0, 255}) } } fontBytes, err := ioutil.ReadFile(fontFile) //读取字体数据 if err != nil { fmt.Println(err) return } font, err := freetype.ParseFont(fontBytes) if err != nil { fmt.Print(err) return } c := freetype.NewContext() c.SetDPI(fontDPI) c.SetFont(font) c.SetFontSize(fontSize) c.SetClip(img.Bounds()) c.SetDst(img) c.SetSrc(image.White) pt := freetype.Pt(10, 10+int(c.PointToFixed(fontSize)>>8)) // 字出现的位置 _, err = c.DrawString("ABCDE", pt) if err != nil { fmt.Println(err) return } err = png.Encode(imgfile, img) if err != nil { fmt.Println(err) } }
func (t *Text) getMaxHeight() int { w, h := t.GetStringSize("|") bounds := image.Rect(0, 0, int(w>>6), int(h>>6)) img := image.NewRGBA(bounds) ctx := freetype.NewContext() ctx.SetFont(t.font) ctx.SetFontSize(t.fontSize) ctx.SetSrc(&image.Uniform{t.fillColor}) ctx.SetDst(img) ctx.SetClip(bounds) ctx.DrawString("|", freetype.Pt(0, int(t.fontSize))) var i = len(img.Pix) - 1 for ; img.Pix[i] == 0; i-- { } return (i / img.Stride) + 1 }
func (this *Signer) mark(text string) (image.Image, error) { fontBytes, err := ioutil.ReadFile(this.fontPath) if err != nil { fmt.Println(err) } font, err := freetype.ParseFont(fontBytes) if err != nil { fmt.Println(err) } //读取图片 file, err := os.Open(this.srcImage) if err != nil { fmt.Println(err) } defer file.Close() img, err := jpeg.Decode(file) if err != nil { fmt.Println(err) } bounds := img.Bounds() nrgba := image.NewNRGBA(bounds) draw.Draw(nrgba, img.Bounds(), img, image.ZP, draw.Over) c := freetype.NewContext() c.SetDPI(this.dpi) c.SetFont(font) c.SetDst(nrgba) c.SetFontSize(this.fontSize) c.SetClip(nrgba.Bounds()) c.SetSrc(image.White) pt := freetype.Pt(100, 100+int(c.PointToFixed(this.fontSize)>>8)) for _, s := range strings.Split(text, "\r\n") { _, err = c.DrawString(s, pt) pt.Y += c.PointToFixed(12 * 1.5) } return nrgba, nil }
func createTextImage(text string, fontSize int, color color.Color, f *truetype.Font) (*image.RGBA, float32, float32, error) { // 1 pt = 1/72 in, 72 dpi = 1 in const dpi = 72 fg, bg := image.NewUniform(color), image.Transparent c := freetype.NewContext() c.SetFont(f) c.SetDPI(dpi) c.SetFontSize(float64(fontSize)) // points c.SetSrc(fg) c.SetHinting(font.HintingFull) // 1. Figure out maximum height so all text lines are the same height. // 2. Draw within small bounds to figure out bounds. // 3. Draw within final bounds. scale := c.PointToFixed(float64(fontSize)) // point to pixels rect := f.Bounds(scale) // scale is pixels of 1 em maxHeight := int(rect.Max.Y>>6) - int(rect.Min.Y>>6) var rgba *image.RGBA w, h := 10, maxHeight for i := 0; i < 2; i++ { rgba = image.NewRGBA(image.Rect(0, 0, w, h)) draw.Draw(rgba, rgba.Bounds(), bg, image.ZP, draw.Src) c.SetClip(rgba.Bounds()) c.SetDst(rgba) pt := freetype.Pt(0, int(scale>>6)) end, err := c.DrawString(text, pt) if err != nil { return nil, 0, 0, err } w = int(end.X >> 6) } return rgba, float32(w), float32(h), nil }
func drawText(img *image.RGBA, font *truetype.Font, color color.Color, x, y int, s string) error { var ptSize float64 = 12 ctx := freetype.NewContext() ctx.SetDPI(72) ctx.SetFont(font) ctx.SetFontSize(ptSize) ctx.SetClip(img.Bounds()) ctx.SetDst(img) ctx.SetSrc(image.NewUniform(color)) ctx.SetHinting(img_font.HintingFull) width := int(widthOfString(font, ptSize, s)) pt := freetype.Pt(x-width/2, y+int(int32(ctx.PointToFixed(ptSize))>>8)/2) _, err := ctx.DrawString(s, pt) if err != nil { return err } return nil }
func (font *Font) createTexture(text string, width int, height int, size float64, dpi float64, rgba color.Color) (uint32, int, int) { context := freetype.NewContext() context.SetFont(font.ttf) img := image.NewRGBA(image.Rect(0, 0, width, height)) r, g, b, _ := rgba.RGBA() draw.Draw(img, img.Bounds(), image.NewUniform(color.RGBA{uint8(r), uint8(g), uint8(b), 0}), image.ZP, draw.Src) context.SetDst(img) context.SetClip(img.Bounds()) context.SetSrc(image.NewUniform(rgba)) context.SetFontSize(size) context.SetDPI(dpi) pixelBounds, _ := context.DrawString(text, freetype.Pt(0, height/2)) var tex uint32 gl.GenTextures(1, &tex) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, tex) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, tex) gl.TexImage2D( gl.TEXTURE_2D, 0, gl.RGBA, int32(img.Rect.Size().X), int32(img.Rect.Size().Y), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(img.Pix)) return tex, int26_6Ceiling(pixelBounds.X + 0x3f), int26_6Ceiling(pixelBounds.Y + 0x3f) }
func TextToImage(text string, fontSize float64, fontFile string, fontColor color.Color) (image.Image, error) { lines := len(strings.Split(text, "\n")) maxLen := getMaxLen(text) margin := 10 width := maxLen*int(fontSize) + margin*2 height := int(fontSize)*lines + margin*2 var fontDPI float64 = 72 fontBytes, err := ioutil.ReadFile(fontFile) if err != nil { return nil, err } font, err := freetype.ParseFont(fontBytes) if err != nil { return nil, err } bg := image.Transparent newImg := image.NewRGBA(image.Rect(0, 0, width, height)) draw.Draw(newImg, newImg.Bounds(), bg, image.ZP, draw.Src) c := freetype.NewContext() c.SetDPI(fontDPI) c.SetFont(font) c.SetFontSize(fontSize) c.SetClip(newImg.Bounds()) c.SetDst(newImg) c.SetSrc(image.NewUniform(fontColor)) // Draw the text. for i, s := range strings.Split(text, "\n") { Y := int(fontSize) + i*int(fontSize) pt := freetype.Pt(margin, Y) _, err := c.DrawString(s, pt) if err != nil { return nil, err } } return newImg, nil }
func NewFontAtlas(filename string, dpi, fontSize float64) (*FontAtlas, error) { atlas := &FontAtlas{} atlas.Rendered = make(map[rune]Glyph, 256) content, err := ioutil.ReadFile(filename) if err != nil { return nil, err } atlas.drawPadding = float32(fontSize * 0.5) atlas.lineHeight = float32(fontSize * 1.2) atlas.TTF, err = truetype.Parse(content) if err != nil { return nil, err } atlas.Image = image.NewRGBA(image.Rect(0, 0, 1024, 1024)) atlas.Context = freetype.NewContext() atlas.Context.SetDPI(dpi) atlas.Context.SetFont(atlas.TTF) atlas.Context.SetFontSize(fontSize) atlas.Context.SetClip(atlas.Image.Bounds()) atlas.Context.SetSrc(image.White) atlas.Context.SetDst(atlas.Image) atlas.maxBounds = atlas.TTF.Bounds(fixed.I(int(fontSize))) opts := &truetype.Options{} opts.Size = fontSize opts.Hinting = font.HintingFull atlas.Face = truetype.NewFace(atlas.TTF, opts) return atlas, nil }
func NewContext(font string) (*Context, error) { fh, err := os.Open(font) if err != nil { return nil, err } defer fh.Close() data, err := ioutil.ReadAll(fh) if err != nil { return nil, err } fnt, err := freetype.ParseFont(data) if err != nil { return nil, err } ctx := freetype.NewContext() ctx.SetFont(fnt) /* XXX: get appropriate DPI for current display */ ctx.SetDPI(96) return &Context{ctx, fnt}, nil }
func NewSquare(glctx gl.Context, inc, x, y float32) (*Square, error) { images := glutil.NewImages(glctx) img1 := images.NewImage(800, 200) ftctx := freetype.NewContext() ftFont, err := freetype.ParseFont(font.Default()) if err != nil { return nil, err } ftctx.SetFont(ftFont) ftctx.SetDPI(312) ftctx.SetSrc(image.NewUniform(colornames.Map["black"])) ftctx.SetDst(img1.RGBA) ftctx.SetClip(img1.RGBA.Bounds()) ftctx.SetHinting(ifont.HintingFull) sq := &Square{ images: images, img1: img1, ftctx: ftctx, } return sq, nil }
func (a Annotator) annotate(upperText string, lowerText string) []byte { fontColor, _ := colorful.Hex("#000000") fontMask := image.NewUniform(fontColor) templateFile, _ := ioutil.ReadFile("./static/template.jpg") srcImage, _ := jpeg.Decode(bytes.NewBuffer(templateFile)) srcBounds := srcImage.Bounds() srcHeight := srcBounds.Max.Y imageMask := image.NewRGBA(srcBounds) imageMaskClip := imageMask.Bounds() draw.Draw(imageMask, imageMaskClip, srcImage, image.ZP, draw.Src) c := freetype.NewContext() c.SetFont(font) c.SetFontSize(60) c.SetDPI(60) c.SetSrc(fontMask) c.SetDst(imageMask) c.SetClip(imageMaskClip) drawLines := func(line string, point fixed.Point26_6) { c.DrawString(line, point) } upperPoint := freetype.Pt(10, 40) lowerPoint := freetype.Pt(10, srcHeight-10) drawLines(upperText, upperPoint) drawLines(lowerText, lowerPoint) dataBuffer := bytes.NewBuffer([]byte("")) jpeg.Encode(dataBuffer, imageMask, nil) return dataBuffer.Bytes() }
// textBox renders t into a tight fitting image func (ig *ImageGraphics) textBox(t string, font chart.Font, textCol color.Color) image.Image { // Initialize the context. bg := image.NewUniform(color.Alpha{0}) fg := image.NewUniform(textCol) width := ig.TextLen(t, font) size := ig.relFontsizeToPixel(font.Size) c := freetype.NewContext() c.SetDPI(dpi) c.SetFont(ig.font) c.SetFontSize(size) bb := ig.font.Bounds(c.PointToFixed(float64(size))) bbDelta := bb.Max.Sub(bb.Min) height := int(bbDelta.Y+32) >> 6 canvas := image.NewRGBA(image.Rect(0, 0, width, height)) draw.Draw(canvas, canvas.Bounds(), bg, image.ZP, draw.Src) c.SetDst(canvas) c.SetSrc(fg) c.SetClip(canvas.Bounds()) // Draw the text. extent, err := c.DrawString(t, fixed.Point26_6{X: 0, Y: bb.Max.Y}) if err != nil { log.Println(err) return nil } // Ugly heuristic hack: font bounds are pretty high resulting in white top border: Trim. topskip := 1 if size > 15 { topskip = 2 } else if size > 20 { topskip = 3 } return canvas.SubImage(image.Rect(0, topskip, int(extent.X)>>6, height)) }
func createProfileImage(username string, userId string) ([]byte, *model.AppError) { colors := []color.NRGBA{ {197, 8, 126, 255}, {227, 207, 18, 255}, {28, 181, 105, 255}, {35, 188, 224, 255}, {116, 49, 196, 255}, {197, 8, 126, 255}, {197, 19, 19, 255}, {250, 134, 6, 255}, {227, 207, 18, 255}, {123, 201, 71, 255}, {28, 181, 105, 255}, {35, 188, 224, 255}, {116, 49, 196, 255}, {197, 8, 126, 255}, {197, 19, 19, 255}, {250, 134, 6, 255}, {227, 207, 18, 255}, {123, 201, 71, 255}, {28, 181, 105, 255}, {35, 188, 224, 255}, {116, 49, 196, 255}, {197, 8, 126, 255}, {197, 19, 19, 255}, {250, 134, 6, 255}, {227, 207, 18, 255}, {123, 201, 71, 255}, } h := fnv.New32a() h.Write([]byte(userId)) seed := h.Sum32() initial := string(strings.ToUpper(username)[0]) fontBytes, err := ioutil.ReadFile(utils.FindDir("web/static/fonts") + utils.Cfg.FileSettings.InitialFont) if err != nil { return nil, model.NewAppError("createProfileImage", "Could not create default profile image font", err.Error()) } font, err := freetype.ParseFont(fontBytes) if err != nil { return nil, model.NewAppError("createProfileImage", "Could not create default profile image font", err.Error()) } width := int(utils.Cfg.FileSettings.ProfileWidth) height := int(utils.Cfg.FileSettings.ProfileHeight) color := colors[int64(seed)%int64(len(colors))] dstImg := image.NewRGBA(image.Rect(0, 0, width, height)) srcImg := image.White draw.Draw(dstImg, dstImg.Bounds(), &image.Uniform{color}, image.ZP, draw.Src) size := float64((width + height) / 4) c := freetype.NewContext() c.SetFont(font) c.SetFontSize(size) c.SetClip(dstImg.Bounds()) c.SetDst(dstImg) c.SetSrc(srcImg) pt := freetype.Pt(width/6, height*2/3) _, err = c.DrawString(initial, pt) if err != nil { return nil, model.NewAppError("createProfileImage", "Could not add user initial to default profile picture", err.Error()) } buf := new(bytes.Buffer) if imgErr := png.Encode(buf, dstImg); imgErr != nil { return nil, model.NewAppError("createProfileImage", "Could not encode default profile image", imgErr.Error()) } else { return buf.Bytes(), nil } }
func tryLoadFont(fontFilePath string) (Font, error) { defer tlog.FuncLog(tlog.Func("LoadFont")) var data []byte { fd, err := os.Open(fontFilePath) if err != nil { return Font{}, err } defer fd.Close() data, err = ioutil.ReadAll(fd) if err != nil { return Font{}, err } } texsdfpath := filepath.Join(os.TempDir(), filepath.Base(fontFilePath)+".sdf") texsdf, err := LoadPng(texsdfpath) sdfLoaded := err == nil if err != nil { texsdf = image.NewGray(image.Rect(0, 0, texSize, texSize)) } name := filepath.Base(fontFilePath) name = name[:len(name)-len(filepath.Ext(name))] var f = Font{ SdfTex: texsdf, Glyphs: make([]Glyph, int(highRune-lowRune+1)), FirstRune: lowRune, Name: name, Height: 0, Leading: 0, } { // Read the truetype font. ttf, err := truetype.Parse(data) if err != nil { return Font{}, err } var baseline = 3 * sdfSize / 4 var targetGlyphExtentPxs = float64(sdfSize) * 3.0 / 4.0 var fontHeight float64 // maximum height, in renormalized EMs var renormalizeEM float64 // (real max glyph size / em) { // the real max glyph extent in EMs var maxGlyphExtentEMs float64 { var max fixed.Int26_6 // = 0; max extent(height or width) of a glyph in FontUnits var height fixed.Int26_6 // = 0; max height of a glyph in FontUnits { scale := fixed.I(int(ttf.FUnitsPerEm())) b := ttf.Bounds(scale) max = b.Max.X - b.Min.X height = b.Max.Y - b.Min.Y if max < height { max = height } for ch := lowRune; ch <= highRune; ch++ { hmetric := ttf.HMetric(scale, ttf.Index(ch)) vmetric := ttf.VMetric(scale, ttf.Index(ch)) if max < hmetric.AdvanceWidth { max = hmetric.AdvanceWidth } if height < vmetric.AdvanceHeight { height = vmetric.AdvanceHeight } if max < height { max = height } } } maxGlyphExtentEMs = float64(max) / float64(ttf.FUnitsPerEm()) fontHeight = float64(height) / float64(ttf.FUnitsPerEm()) } renormalizeEM = 1 / maxGlyphExtentEMs fontHeight *= renormalizeEM } f.Height = em(fontHeight) f.Leading = em(leadingFactor * fontHeight) scale := fixed.I(int(ttf.FUnitsPerEm())) graphicIdx := 0 for ch := lowRune; ch <= highRune; ch++ { // fmt.Printf("%c", ch) idx := int(ch - lowRune) var aw float64 { hmetric := ttf.HMetric(scale, ttf.Index(ch)) aw = float64(hmetric.AdvanceWidth) / float64(ttf.FUnitsPerEm()) * renormalizeEM f.Glyphs[idx].AdvanceWidth = em(aw) } if !unicode.IsGraphic(ch) || unicode.IsSpace(ch) { f.Glyphs[idx].Cell = image.ZR continue } x0 := cellSize * (graphicIdx % texNCells) y0 := cellSize * (graphicIdx / texNCells) graphicIdx++ f.Glyphs[idx].Cell = image.Rect(x0, y0, x0+cellSize, y0+cellSize) sdfTargetWidth := targetGlyphExtentPxs * aw sdfTargetHeight := targetGlyphExtentPxs * fontHeight if !sdfLoaded { img := image.NewGray(image.Rect(0, 0, sdfSize, sdfSize)) c := freetype.NewContext() c.SetFont(ttf) c.SetDPI(72) // so that one Pt == one Pixel c.SetFontSize(targetGlyphExtentPxs * renormalizeEM) // how many Pt the max glyph has c.SetClip(img.Bounds()) c.SetDst(img) c.SetSrc(image.White) sdfX := (sdfSize - int(sdfTargetWidth)) / 2 c.DrawString(string(ch), freetype.Pt(sdfX, baseline)) sdfize(img) scaleDownTo(f.SdfTex, f.Glyphs[idx].Cell, img) } dx := (sdfSize - int(sdfTargetWidth)) / 2 * cellSize / sdfSize cellHeight := sdfTargetHeight * float64(cellSize) / float64(sdfSize) dy := (cellSize - int(cellHeight)) / 4 f.Glyphs[idx].Cell = image.Rect(x0+dx, y0+3*dy, x0+cellSize-dx, y0+cellSize-dy) // drawRect(f.SdfTex, f.Glyphs[idx].Cell, color.Gray{255}) } } if !sdfLoaded { SavePng(texsdfpath, f.SdfTex) tlog.Println("sdf ", texsdfpath, " saved") } // ShowImage(f.SdfTex) tlog.Println(fontFilePath, " loaded") return f, nil }
func transformCropAndResize(img image.Image, transformation *Transformation) (imgNew image.Image) { parameters := transformation.params width := parameters.width height := parameters.height gravity := parameters.gravity scale := parameters.scale imgWidth := img.Bounds().Dx() imgHeight := img.Bounds().Dy() // Scaling factor if parameters.cropping != CroppingModeKeepScale { width *= scale height *= scale } // Resize and crop switch parameters.cropping { case CroppingModeExact: imgNew = resize.Resize(uint(width), uint(height), img, resize.Bilinear) case CroppingModeAll: if float32(width)*(float32(imgHeight)/float32(imgWidth)) > float32(height) { // Keep height imgNew = resize.Resize(0, uint(height), img, resize.Bilinear) } else { // Keep width imgNew = resize.Resize(uint(width), 0, img, resize.Bilinear) } case CroppingModePart: var croppedRect image.Rectangle if float32(width)*(float32(imgHeight)/float32(imgWidth)) > float32(height) { // Whole width displayed newHeight := int((float32(imgWidth) / float32(width)) * float32(height)) croppedRect = image.Rect(0, 0, imgWidth, newHeight) } else { // Whole height displayed newWidth := int((float32(imgHeight) / float32(height)) * float32(width)) croppedRect = image.Rect(0, 0, newWidth, imgHeight) } topLeftPoint := calculateTopLeftPointFromGravity(gravity, croppedRect.Dx(), croppedRect.Dy(), imgWidth, imgHeight) imgDraw := image.NewRGBA(croppedRect) draw.Draw(imgDraw, croppedRect, img, topLeftPoint, draw.Src) imgNew = resize.Resize(uint(width), uint(height), imgDraw, resize.Bilinear) case CroppingModeKeepScale: // If passed in dimensions are bigger use those of the image if width > imgWidth { width = imgWidth } if height > imgHeight { height = imgHeight } croppedRect := image.Rect(0, 0, width, height) topLeftPoint := calculateTopLeftPointFromGravity(gravity, width, height, imgWidth, imgHeight) imgDraw := image.NewRGBA(croppedRect) draw.Draw(imgDraw, croppedRect, img, topLeftPoint, draw.Src) imgNew = imgDraw.SubImage(croppedRect) } // Filters if parameters.filter == FilterGrayScale { bounds := imgNew.Bounds() w, h := bounds.Max.X, bounds.Max.Y gray := image.NewGray(bounds) for x := 0; x < w; x++ { for y := 0; y < h; y++ { oldColor := imgNew.At(x, y) grayColor := color.GrayModel.Convert(oldColor) gray.Set(x, y, grayColor) } } imgNew = gray } if transformation.watermark != nil { w := transformation.watermark var watermarkSrcScaled image.Image var watermarkBounds image.Rectangle // Try to load a scaled watermark first if scale > 1 { scaledPath, err := constructScaledPath(w.imagePath, scale) if err != nil { log.Println("Error:", err) return } watermarkSrc, _, err := loadImage(scaledPath) if err != nil { log.Println("Error: could not load a watermark", err) } else { watermarkBounds = watermarkSrc.Bounds() watermarkSrcScaled = watermarkSrc } } if watermarkSrcScaled == nil { watermarkSrc, _, err := loadImage(w.imagePath) if err != nil { log.Println("Error: could not load a watermark", err) return } watermarkBounds = image.Rect(0, 0, watermarkSrc.Bounds().Max.X*scale, watermarkSrc.Bounds().Max.Y*scale) watermarkSrcScaled = resize.Resize(uint(watermarkBounds.Max.X), uint(watermarkBounds.Max.Y), watermarkSrc, resize.Bilinear) } bounds := imgNew.Bounds() // Make sure we have a transparent watermark if possible watermark := image.NewRGBA(watermarkBounds) draw.Draw(watermark, watermarkBounds, watermarkSrcScaled, watermarkBounds.Min, draw.Src) pt := calculateTopLeftPointFromGravity(w.gravity, watermarkBounds.Dx(), watermarkBounds.Dy(), bounds.Dx(), bounds.Dy()) pt = pt.Add(getTranslation(w.gravity, w.x*scale, w.y*scale)) wX := pt.X wY := pt.Y watermarkRect := image.Rect(wX, wY, watermarkBounds.Dx()+wX, watermarkBounds.Dy()+wY) finalImage := image.NewRGBA(bounds) draw.Draw(finalImage, bounds, imgNew, bounds.Min, draw.Src) draw.Draw(finalImage, watermarkRect, watermark, watermarkBounds.Min, draw.Over) imgNew = finalImage.SubImage(bounds) } if transformation.texts != nil { bounds := imgNew.Bounds() rgba := image.NewRGBA(bounds) draw.Draw(rgba, bounds, imgNew, image.ZP, draw.Src) dpi := float64(72) // Multiply this by scale for a baaad time c := freetype.NewContext() c.SetDPI(dpi) c.SetClip(rgba.Bounds()) c.SetDst(rgba) for _, text := range transformation.texts { size := float64(text.size * scale) c.SetSrc(image.NewUniform(text.color)) c.SetFont(text.font) c.SetFontSize(size) fontMetrics := text.getFontMetrics(scale) width := int(c.PointToFix32(fontMetrics.width) >> 8) height := int(c.PointToFix32(fontMetrics.height) >> 8) pt := calculateTopLeftPointFromGravity(text.gravity, width, height, bounds.Dx(), bounds.Dy()) pt = pt.Add(getTranslation(text.gravity, text.x*scale, text.y*scale)) x := pt.X y := pt.Y + int(c.PointToFix32(fontMetrics.ascent)>>8) _, err := c.DrawString(text.content, freetype.Pt(x, y)) if err != nil { log.Println("Error adding text:", err) return } } imgNew = rgba } return }
func main() { rightFile, err := os.Open("p1.jpg") if err != nil { panic(err) } rightPortrait, err := jpeg.Decode(rightFile) if err != nil { panic(err) } leftFile, err := os.Open("p2.jpg") if err != nil { panic(err) } leftPortrait, err := jpeg.Decode(leftFile) if err != nil { panic(err) } rightImage := resize.Resize(400, 600, rightPortrait, resize.Bilinear) leftImage := resize.Resize(400, 600, leftPortrait, resize.Bilinear) t, err := os.Open("template.png") if err != nil { panic(err) } mask, err := png.Decode(t) if err != nil { panic(err) } newImage := image.NewRGBA(rightImage.Bounds()) draw.Draw(newImage, rightImage.Bounds(), rightImage, image.ZP, draw.Src) draw.DrawMask(newImage, leftImage.Bounds(), leftImage, image.ZP, mask, image.ZP, draw.Over) ctx := freetype.NewContext() ctx.SetFont(strokeFont) ctx.SetFontSize(84) ctx.SetSrc(image.Black) ctx.SetDst(newImage) ctx.SetClip(newImage.Bounds()) _, err = ctx.DrawString("TOGETHER", freetype.Pt(40, 200)) if err != nil { panic(err) } ctx.SetFont(posterFont) ctx.SetFontSize(12) ctx.SetSrc(image.White) ctx.SetDst(newImage) ctx.SetClip(newImage.Bounds()) _, err = ctx.DrawString("#VOTETOGETHER", freetype.Pt(150, 580)) if err != nil { panic(err) } f, err := os.Create("newimage.png") if err != nil { panic(err) } defer f.Close() err = png.Encode(f, newImage) if err != nil { panic(err) } }
func (font *Font) updateTexture(texture uint32, text string, width int, height int, size float64, dpi float64, rgba color.Color) (int, int) { context := freetype.NewContext() context.SetFont(font.ttf) img := image.NewRGBA(image.Rect(0, 0, width, height)) r, g, b, _ := rgba.RGBA() draw.Draw(img, img.Bounds(), image.NewUniform(color.RGBA{uint8(r), uint8(g), uint8(b), 0}), image.ZP, draw.Src) context.SetDst(img) context.SetClip(img.Bounds()) context.SetSrc(image.NewUniform(rgba)) context.SetFontSize(size) context.SetDPI(dpi) pixelBounds, _ := context.DrawString(text, freetype.Pt(0, height/2)) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, texture) gl.TexSubImage2D( gl.TEXTURE_2D, 0, 0, 0, int32(img.Rect.Size().X), int32(img.Rect.Size().Y), gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(img.Pix)) return int26_6Ceiling(pixelBounds.X + 0x3f), int26_6Ceiling(pixelBounds.Y + 0x3f) }
func makeImage(req *http.Request, caption, font string, pt, size, border, scale int, f func(x, y int) uint32) *image.RGBA { d := (size + 2*border) * scale csize := 0 if caption != "" { if pt == 0 { pt = 11 } csize = pt * 2 } c := image.NewRGBA(image.Rect(0, 0, d, d+csize)) // white u := &image.Uniform{C: color.White} draw.Draw(c, c.Bounds(), u, image.ZP, draw.Src) for y := 0; y < size; y++ { for x := 0; x < size; x++ { r := image.Rect((x+border)*scale, (y+border)*scale, (x+border+1)*scale, (y+border+1)*scale) rgba := f(x, y) u.C = color.RGBA{byte(rgba >> 24), byte(rgba >> 16), byte(rgba >> 8), byte(rgba)} draw.Draw(c, r, u, image.ZP, draw.Src) } } if csize != 0 { if font == "" { font = "data/luxisr.ttf" } ctxt := fs.NewContext(req) dat, _, err := ctxt.Read(font) if err != nil { panic(err) } tfont, err := freetype.ParseFont(dat) if err != nil { panic(err) } ft := freetype.NewContext() ft.SetDst(c) ft.SetDPI(100) ft.SetFont(tfont) ft.SetFontSize(float64(pt)) ft.SetSrc(image.NewUniform(color.Black)) ft.SetClip(image.Rect(0, 0, 0, 0)) wid, err := ft.DrawString(caption, freetype.Pt(0, 0)) if err != nil { panic(err) } p := freetype.Pt(d, d+3*pt/2) p.X -= wid.X p.X /= 2 ft.SetClip(c.Bounds()) ft.DrawString(caption, p) } return c }