Go Graphics - 2D rendering in Go with a simple API.

Overview

Go Graphics

gg is a library for rendering 2D graphics in pure Go.

Stars

Installation

go get -u github.com/fogleman/gg

Alternatively, you may use gopkg.in to grab a specific major-version:

go get -u gopkg.in/fogleman/gg.v1

Documentation

Hello, Circle!

Look how easy!

package main

import "github.com/fogleman/gg"

func main() {
    dc := gg.NewContext(1000, 1000)
    dc.DrawCircle(500, 500, 400)
    dc.SetRGB(0, 0, 0)
    dc.Fill()
    dc.SavePNG("out.png")
}

Examples

There are lots of examples included. They're mostly for testing the code, but they're good for learning, too.

Examples

Creating Contexts

There are a few ways of creating a context.

NewContext(width, height int) *Context
NewContextForImage(im image.Image) *Context
NewContextForRGBA(im *image.RGBA) *Context

Drawing Functions

Ever used a graphics library that didn't have functions for drawing rectangles or circles? What a pain!

DrawPoint(x, y, r float64)
DrawLine(x1, y1, x2, y2 float64)
DrawRectangle(x, y, w, h float64)
DrawRoundedRectangle(x, y, w, h, r float64)
DrawCircle(x, y, r float64)
DrawArc(x, y, r, angle1, angle2 float64)
DrawEllipse(x, y, rx, ry float64)
DrawEllipticalArc(x, y, rx, ry, angle1, angle2 float64)
DrawRegularPolygon(n int, x, y, r, rotation float64)
DrawImage(im image.Image, x, y int)
DrawImageAnchored(im image.Image, x, y int, ax, ay float64)
SetPixel(x, y int)

MoveTo(x, y float64)
LineTo(x, y float64)
QuadraticTo(x1, y1, x2, y2 float64)
CubicTo(x1, y1, x2, y2, x3, y3 float64)
ClosePath()
ClearPath()
NewSubPath()

Clear()
Stroke()
Fill()
StrokePreserve()
FillPreserve()

It is often desired to center an image at a point. Use DrawImageAnchored with ax and ay set to 0.5 to do this. Use 0 to left or top align. Use 1 to right or bottom align. DrawStringAnchored does the same for text, so you don't need to call MeasureString yourself.

Text Functions

It will even do word wrap for you!

DrawString(s string, x, y float64)
DrawStringAnchored(s string, x, y, ax, ay float64)
DrawStringWrapped(s string, x, y, ax, ay, width, lineSpacing float64, align Align)
MeasureString(s string) (w, h float64)
MeasureMultilineString(s string, lineSpacing float64) (w, h float64)
WordWrap(s string, w float64) []string
SetFontFace(fontFace font.Face)
LoadFontFace(path string, points float64) error

Color Functions

Colors can be set in several different ways for your convenience.

SetRGB(r, g, b float64)
SetRGBA(r, g, b, a float64)
SetRGB255(r, g, b int)
SetRGBA255(r, g, b, a int)
SetColor(c color.Color)
SetHexColor(x string)

Stroke & Fill Options

SetLineWidth(lineWidth float64)
SetLineCap(lineCap LineCap)
SetLineJoin(lineJoin LineJoin)
SetDash(dashes ...float64)
SetDashOffset(offset float64)
SetFillRule(fillRule FillRule)

Gradients & Patterns

gg supports linear, radial and conic gradients and surface patterns. You can also implement your own patterns.

SetFillStyle(pattern Pattern)
SetStrokeStyle(pattern Pattern)
NewSolidPattern(color color.Color)
NewLinearGradient(x0, y0, x1, y1 float64)
NewRadialGradient(x0, y0, r0, x1, y1, r1 float64)
NewConicGradient(cx, cy, deg float64)
NewSurfacePattern(im image.Image, op RepeatOp)

Transformation Functions

Identity()
Translate(x, y float64)
Scale(x, y float64)
Rotate(angle float64)
Shear(x, y float64)
ScaleAbout(sx, sy, x, y float64)
RotateAbout(angle, x, y float64)
ShearAbout(sx, sy, x, y float64)
TransformPoint(x, y float64) (tx, ty float64)
InvertY()

It is often desired to rotate or scale about a point that is not the origin. The functions RotateAbout, ScaleAbout, ShearAbout are provided as a convenience.

InvertY is provided in case Y should increase from bottom to top vs. the default top to bottom.

Stack Functions

Save and restore the state of the context. These can be nested.

Push()
Pop()

Clipping Functions

Use clipping regions to restrict drawing operations to an area that you defined using paths.

Clip()
ClipPreserve()
ResetClip()
AsMask() *image.Alpha
SetMask(mask *image.Alpha)
InvertMask()

Helper Functions

Sometimes you just don't want to write these yourself.

Radians(degrees float64) float64
Degrees(radians float64) float64
LoadImage(path string) (image.Image, error)
LoadPNG(path string) (image.Image, error)
SavePNG(path string, im image.Image) error

Separator

Another Example

See the output of this example below.

package main

import "github.com/fogleman/gg"

func main() {
	const S = 1024
	dc := gg.NewContext(S, S)
	dc.SetRGBA(0, 0, 0, 0.1)
	for i := 0; i < 360; i += 15 {
		dc.Push()
		dc.RotateAbout(gg.Radians(float64(i)), S/2, S/2)
		dc.DrawEllipse(S/2, S/2, S*7/16, S/8)
		dc.Fill()
		dc.Pop()
	}
	dc.SavePNG("out.png")
}

Ellipses

Comments
  • Line width fine-control

    Line width fine-control

    I am trying to create the bimaps, and looks like I can't have vertical or horizontal line of width of exactly 1 px. Is there any way of making the width "strict"?

    opened by jdevelop 9
  • Draw clock with using DrawArc provide unexpected result

    Draw clock with using DrawArc provide unexpected result

    I start implement clock widget and use your 2D render. My result is

    image

    I can not understand how to draw sector. I am start drawing from 150, 150 and call DrawArc. It create path from 150, 150 to right draw arc and later I expect return back in 150, 150 but I receive wrong join path. How to draw direct line.

    opened by vit1251 6
  • dc.SavePNG() isn't working - Hello Circle example

    dc.SavePNG() isn't working - Hello Circle example

    I really like the look of this library, and I think it will be very helpful in a lot of the things that I want to do. However, I've had some trouble getting it to work, which may easily be because I've misread the documentation or am looking the wrong places.

    When I run the "Hello Circle" code (shown below), I get no errors, which is good, however I also don't see any saved image.

    package main
    
    import "github.com/fogleman/gg"
    
    func main() {
    	dc := gg.NewContext(1000, 1000)
    	dc.DrawCircle(500, 500, 400)
    	dc.SetRGB(0, 0, 0)
    	dc.Fill()
    	dc.SavePNG("out.png")
    }
    

    Am I simply looking in the wrong place for the image? For example, do they all save in a specific place on my system (I'm using Windows 10), instead of in the directory of my project? I was expecting it to create a file called "out.png" inside my directory, but that hasn't happened, so that's why I'm wondering if it may have saved elsewhere.

    In case it's helpful in debugging the issue, here is the layout of my project. As shown, it is very simple right now. Could this issue be happening because I'm not configuring my project properly?

    generate-art/
        - main.go
        - go.mod
        - go.sum
    

    Thank you for your help!

    opened by marktforsyth 5
  • SetPixel is here, but what about GetPixel ?

    SetPixel is here, but what about GetPixel ?

    Hi... I'm looking at your excellent gg package. I notice a thing (but that is maybe just me)...

    I see a SetPixel() ... but I don't see a GetPixel() ?

    When you are drawing a lot (especially overlapping), it would be nice to be able to pull back out, the color of each pixel, and see if that is the color you expected ......

    opened by einar-indrida 5
  • Subtract alpha from underlying shape

    Subtract alpha from underlying shape

    I am creating an image and filling it with black by drawing a rectangle to the context. I then want to draw circles in alpha on top of the image so that there are hole punches in it. Drawing circles to the context in alpha will just make invisible circles on to of the black rectangle, leaving me with a full black image. How do I make the drawing of the circles subtract colour from the rectangle?

    Otherwise, perhaps there is a different method to obtain an image like the following one where the white should be transparent. image

    opened by jpmeijers 5
  • concurrent use of MeasureString causes panic

    concurrent use of MeasureString causes panic

    The following program panics consistently for me:

    package main
    
    import (
    	"fmt"
    	"strconv"
    	"sync"
    
    	"golang.org/x/image/font"
    
    	"github.com/fogleman/gg"
    )
    
    var face font.Face
    
    func main() {
    	f, err := gg.LoadFontFace("/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf", 12)
    	if err != nil {
    		panic(err)
    	}
    	face = f
    
    	var wg sync.WaitGroup
    
    	for i := 0; i < 100; i++ {
    		wg.Add(1)
    		go func() {
    			drawIt(i)
    			wg.Done()
    		}()
    	}
    
    	wg.Wait()
    }
    
    func drawIt(id int) {
    	for i := 0; i < 100; i++ {
    		gctx := gg.NewContext(1000, 1000)
    		gctx.SetFontFace(face)
    
    		w, h := gctx.MeasureString(strconv.Itoa(i))
    		fmt.Printf("%02d %d %f %f\n", id, i, w, h)
    	}
    }
    

    The panic is:

    panic: runtime error: index out of range
    
    goroutine 58 [running]:
    vendor/github.com/golang/freetype/truetype.(*GlyphBuf).load(0xc42009eb00, 0x1001600000000, 0xc400000033, 0x16)
            /home/psanford/projects/nearbuy/storenet/go/src/vendor/github.com/golang/freetype/truetype/glyph.go:231 +0x70e
    vendor/github.com/golang/freetype/truetype.(*GlyphBuf).Load(0xc42009eb00, 0xc4200103c0, 0x1600000300, 0x0, 0x40bdc8, 0x4ea420)
            /home/psanford/projects/nearbuy/storenet/go/src/vendor/github.com/golang/freetype/truetype/glyph.go:102 +0xd2
    vendor/github.com/golang/freetype/truetype.(*face).GlyphAdvance(0xc42009c000, 0x33, 0x0)
            /home/psanford/projects/nearbuy/storenet/go/src/vendor/github.com/golang/freetype/truetype/face.go:345 +0x6e
    vendor/golang.org/x/image/font.MeasureString(0x579a80, 0xc42009c000, 0xc4236b8122, 0x1, 0x3)
            /home/psanford/projects/nearbuy/storenet/go/src/vendor/golang.org/x/image/font/font.go:287 +0x84
    vendor/golang.org/x/image/font.(*Drawer).MeasureString(0xc420c96eb0, 0xc4236b8122, 0x1, 0xc4236b8122)
            /home/psanford/projects/nearbuy/storenet/go/src/vendor/golang.org/x/image/font/font.go:201 +0x4c
    vendor/github.com/fogleman/gg.(*Context).MeasureString(0xc420058500, 0xc4236b8122, 0x1, 0x4, 0x4)
            /home/psanford/projects/nearbuy/storenet/go/src/vendor/github.com/fogleman/gg/context.go:696 +0x88
    main.drawIt(0x64)
            /home/psanford/projects/nearbuy/storenet/go/src/pms/fontsafe/main.go:47 +0xb1
    main.main.func1(0xc42000e3e0, 0xc42000e3d0)
            /home/psanford/projects/nearbuy/storenet/go/src/pms/fontsafe/main.go:34 +0x2e
    created by main.main
            /home/psanford/projects/nearbuy/storenet/go/src/pms/fontsafe/main.go:36 +0x108
    exit status 2
    

    According to https://godoc.org/golang.org/x/image/font#Face "A Face is not safe for concurrent use by multiple goroutines, as its methods may re-use implementation-specific caches and mask image buffers."

    At the very least it seems like the package level LoadFontFace should say that it is not safe for concurrent use.

    opened by psanford 5
  • draw two text in different rotation with accurate x, y ?

    draw two text in different rotation with accurate x, y ?

    I try to draw two text in different rotation degrees, but i found it wrong that the text is not in the exact x, y which has been given:

    func main() {
    	F := 40.0
    	dc := gg.NewContext(500, 500)
    	dc.Clear()
    
    	if err := dc.LoadFontFace("Deng.ttf", F); err != nil {
    		panic(err)
    	}
    
    	dc.SetRGB(1, 0, 0)
    	dc.SetLineWidth(4)
    
    	dc.Rotate(gg.Radians(30))
    	dc.DrawStringAnchored("Hello 1", 200, 200, 0.5, 0.5)
    	dc.Rotate(gg.Radians(30))
    	dc.DrawStringAnchored("Hello 2", 300, 300, 0.5, 0.5)
    
    	dc.Fill()
    
    	_ = dc.SavePNG("out.png")
    }
    

    The result img below:

    out

    Even the "Hello 2" is not in the image?!

    opened by JasonkayZK 4
  • DrawString isn't working

    DrawString isn't working

    DrawString does not draw anything for me, do i have to load a font? Does it have a default font? I tried loading a font but it didn't help. All i'm doing is a basic ctx.DrawString("some string", 16, 16)

    opened by ravener 4
  • Support for drawing 8bpp alpha masks.

    Support for drawing 8bpp alpha masks.

    This PR adds support for drawing to an 8bpp (greyscale) canvas, suitable for creating alpha masks.

    Somewhat related to #44, this PR may also be helpful as the basis for other "painter modes" in the future.

    I'm using this for another project and am very happy to make any required changes to see it land.

    opened by jpap 4
  • Implement PlotXY widget to draw line charts

    Implement PlotXY widget to draw line charts

    Hi,

    I've implemented a tool to easily draw line graphs with gg. For example, using something like:

    p := gg.NewPlotXY()
    c := p.AddCurve("data", []float64{1, 2, 3, 4}, []float64{1, 4, 9, 16})
    dc := gg.NewContext(400, 300)
    p.Render(dc)
    dc.SavePNG("/tmp/figure-simple.png")
    

    Here you are some output

    figure-simple

    figure

    Cheers. Dorival

    opened by cpmech 4
  • DrawArc: getting rid of the line connecting the center with the beginning.

    DrawArc: getting rid of the line connecting the center with the beginning.

    Hi! First of all thanks! for your awesome library!

    I'm using gg to create illustrations about how to do "geometric constructions" . As you can see in the attached image, drawing arcs shows always the line from the center to the beginning of the arc. frame2

    I wonder if it would be possible to get rid of that line - drawing only the arc.

    I'm asking for this becouse when the drawing becomes more complex, the result becomes confused.

    frame6

    Maybe it's already possible but I'm missing something?

    Thanks!

    opened by lucasepe 3
  • Why not add interface about return the IM

    Why not add interface about return the IM

    hi, fogleman. Thank you very much for your open source project, but I found a problem. I need a drawn 'image.Image' object and use GO's native method 'Jpeg. Encode' to convert the 'image.Image' object into an IO.Writer object,then I find that the 'context. DrawImage' method does not modify the 'image.Image' object passed in. I think you may be to ensure the security of the 'image.Image' object. However, I found that there was no function in the project to get the ‘context.im’ object, which caused me some trouble when I just wanted to get the image data for network transfer, not SaveJPG() on my disk. Perhaps adding a method to return the ‘context.im’ is more convenient and flexible to use.

    // i use code // This is a little demo that rotates a circular image // the test.jpg not rotate func defaultDrawCore(im image.Image) { w := im.Bounds().Size().X h := im.Bounds().Size().Y dc := gg.NewContext(w, h) dc.DrawRectangle(0, 0, float64(w), float64(h)) dc.SetRGBA(255, 255, 255, 0) dc.Fill() radius := math.Min(float64(w), float64(h)) / 2 dc.DrawCircle(float64(w/2), float64(h/2), radius) dc.Clip() dc.RotateAbout(gg.Radians(45), float64(w/2), float64(h/2)) dc.DrawImage(im, 0, 0) buf := new(bytes.Buffer) jpeg.Encode(buf, im, &jpeg.Options{Quality: 90}) newim, imErr := jpeg.Decode(buf) if imErr != nil { return } gg.SaveJPG("test.jpg", newim, 90) return }

    // Perhaps adding a function will solve this problem func (dc *Context) GetIM() *image.RGBA { return dc.im }

    opened by angelsmall 0
  • Check errors from Close method in SavePNG and SaveJPG

    Check errors from Close method in SavePNG and SaveJPG

    When closing the file, errors can still occur that might not be surfaced during the writes from png.Encode and jpeg.Encode. By returning the error from file.Close(), these cases can be caught.

    opened by peterstace 0
  • Context SetTransform / GetTransform / ApplyTransform

    Context SetTransform / GetTransform / ApplyTransform

    The Context struct has a matrix property and various methods to manipulate that matrix. But although you can create a new Matrix, there is no way to apply a matrix to the context in one shot. Other packages I've used in the past have had one method such as SetTransform which replaces the current transform matrix with a new matrix, and ApplyTransform which applies a full matrix as an additional transform to the current matrix. As well as a method to get the current transform.

    I believe this would be as simple as:

    func (dc *Context) SetTransform(matrix gg.Matrix) {
    	dc.matrix = matrix
    }
    
    func (dc *Context) ApplyTransform(matrix gg.Matrix) {
    	dc.matrix = dc.matrix.Multiply(matrix)
    }
    
    func (dc *Context) GetTransform() gg.Matrix {
            return dc.matrix
    }
    

    Though I might have gotten the order reversed in the second one.

    The Get and Set methods would be the most useful and if you had those, you could roll your own Apply method.

    opened by bit101 0
  • Add SetScaleStyle for zoomed images

    Add SetScaleStyle for zoomed images

    My use-case is to create an educational video where I want to explain an algorithm that works on images.

    I would like to start the video by zooming into an image until we can see the pixels. However, in gg I get a blurry image when zooming in.

    By default gg uses the draw package's BiLinear interpolation. This PR adds SetScaleStyle which I use to adjust the interpolation dynamically. While the image in my video is zoomed out, it is linearly interpolated. But once the zoom level is > 1, I switch to NearestNeighbor to show the pixels.

    I have tried to keep this in line with the rest of the code, adding SetScaleStyle with a parameter and concrete SetScaleBiLinear etc. for easier auto-completion (if that is your reasoning, makes sense to me at least).

    opened by gonutz 0
  • Added DrawStringWithOptions

    Added DrawStringWithOptions

    Similar to this issue, I needed a way to underline text. Since you mentioned looking for a generic way to include this feature in your project, I ended up submitting this PR.

    Its main goal is to provide a new function to draw strings: DrawStringWithOptions which allows more flexibility when providing options when drawing strings. Of course, other DrawString function signatures are left untouched and are using this new function.

    DrawStringOptions handles anchored, underlined and wrapped strings.

    Let me know what you think Cheers

    opened by asticode 0
Releases(v1.3.0)
Owner
Michael Fogleman
Software Engineer at Formlabs
Michael Fogleman
This is old and unmaintained code, ignore it. starfish is a simple, SDL based, 2D graphics and user input library for Go. If you intend to work on it, please fork from the 'devel' branch, not 'master'. Current release: 0.12.0

What is starfish? What starfish is: starfish is a simple 2D graphics and user input library for Go built on SDL. What starfish is not: While it is bui

Gary Talent 12 Jun 4, 2019
Simple tool for changing graphics in dbd

Config changer for Dead By Deaylight For now only for epic store version And if only installed under C:\ further updates will include support for vers

null 0 May 3, 2022
Canvas is a Go drawing library based on OpenGL or using software rendering that is very similar to the HTML5 canvas API

Go canvas Canvas is a pure Go library that provides drawing functionality as similar as possible to the HTML5 canvas API. It has nothing to do with HT

Thomas Friedel 440 Jan 3, 2023
Go binding for the cairo graphics library

go-cairo Go binding for the cairo graphics library Based on Dethe Elza's version https://bitbucket.org/dethe/gocairo but significantly extended and up

Erik Unger 125 Dec 19, 2022
A Grid based 2D Graphics library

gridder Built on top of Go Graphics github.com/fogleman/gg with the idea to simplify visualizing Grids using 2D Graphics. Dependencies gg github.com/f

Raed Shomali 59 Dec 1, 2022
a tool to output images as RGB ANSI graphics on the terminal

imgcat Tool to output images in the terminal. Built with bubbletea install homebrew brew install trashhalo/homebrew-brews/imgcat prebuilt packages Pr

Stephen Solka 469 Dec 28, 2022
Image processing library and rendering toolkit for Go.

blend Image processing library and rendering toolkit for Go. (WIP) Installation: This library is compatible with Go1. go get github.com/phrozen/blend

Guillermo Estrada 61 Nov 11, 2022
2D rendering for different output (raster, pdf, svg)

draw2d Package draw2d is a go 2D vector graphics library with support for multiple outputs such as images (draw2d), pdf documents (draw2dpdf), opengl

llgcode 954 Dec 25, 2022
An experiment in rendering images with Slack custom emojis.

emojimage An experiment in rendering images with Slack custom emojis. Example Usage 1. Initializing your workspace First, you'll need to upload 1,332

Caleb Denio 9 Mar 12, 2022
Go bindings for OpenCV / 2.x API in gocv / 1.x API in opencv

Go OpenCV binding A Golang binding for OpenCV. OpenCV 1.x C API bindings through CGO, and OpenCV 2+ C++ API (GoCV) through SWIG. Disclaimer This is a

go-opencv 1.3k Dec 21, 2022
Cgo bindings to PulseAudio's Simple API, for easily playing or capturing raw audio.

pulse-simple Cgo bindings to PulseAudio's Simple API, for easily playing or capturing raw audio. The full Simple API is supported, including channel m

Tommy 24 Dec 17, 2022
A simple API written in Go that creates badges in SVG format, based on the requested route.

A simple API written in Go that creates badges in SVG format, based on the requested route. Those graphics can be used to style README.md files, or to add tags to webpages.

Toby 3 Jul 2, 2021
geoserver is a Go library for manipulating a GeoServer instance via the GeoServer REST API.

Geoserver geoserver Is a Go Package For Manipulating a GeoServer Instance via the GeoServer REST API. How to install: go get -v gopkg.in/hishamkaram/g

Hisham waleed karam 78 Dec 22, 2022
Vulkan API bindings for Go programming language

Golang Bindings for Vulkan API Package vulkan provides Go bindings for Vulkan — a low-overhead, cross-platform 3D graphics and compute API. Updated Oc

null 665 Jan 3, 2023
Go binding to ImageMagick's MagickWand C API

Go Imagick Go Imagick is a Go bind to ImageMagick's MagickWand C API. We support two compatibility branches: master (tag v2.x.x): 6.9.1-7 <= ImageMagi

Go Graphics community 1.5k Jan 6, 2023
Use Windows API to capture a image from a Webcam in GoLANG

Windows-API-Capture-Webcam Use Windows API to capture a image from a Webcam in GoLANG Other Go is a amazing and powerful programming language. If you

SaturnsVoid 10 Aug 13, 2022
API-first image file text search 🔍

API-first image file text search ??

John Forstmeier 2 Dec 11, 2021
HTML Canvas 2D Context API for mobile, desktop and web

canvas HTML Canvas 2D Context API for mobile, desktop and web Context2D API https://www.w3.org/TR/2dcontext/ native code implement https://github.com/

GoPlus 2 Apr 22, 2022
An API which allows you to upload an image and responds with the same image, stripped of EXIF data

strip-metadata This is an API which allows you to upload an image and responds with the same image, stripped of EXIF data. How to run You need to have

Cristina Simionescu 0 Nov 25, 2021