// Load an image from a PNG file func Load(path string) (*Image, error) { var img Image file, err := os.Open(path) if err != nil { fmt.Println("ERROR: Cannot open file", path) return nil, err } defer func() { if err := file.Close(); err != nil { panic(err) } }() pngImage, err := png.Decode(file) if err != nil { fmt.Println("ERROR: Cannot decode PNG file", path) return nil, err } // Copy to surface b := pngImage.Bounds() img.Surf = image.NewRGBA(image.Rect(0, 0, b.Max.X-b.Min.X, b.Max.Y-b.Min.Y)) draw.Draw(img.Surf, img.Surf.Bounds(), pngImage, pngImage.Bounds().Min, draw.Src) img.Ctx = draw2dimg.NewGraphicContext(img.Surf) br := img.Surf.Bounds() img.W, img.H = br.Max.X-br.Min.X, br.Max.Y-br.Min.Y return &img, nil }
// DrawClosedLine draws the line represented by the Points and closes it. func DrawClosedLine(p Points, width, height float64, name string) { // Initialize the graphic context on an RGBA image dest := image.NewRGBA(image.Rect(0, 0, int(width), int(height))) gc := draw2dimg.NewGraphicContext(dest) // Set some properties gc.SetStrokeColor(color.RGBA{0x44, 0x44, 0x44, 0xff}) gc.SetLineWidth(5) paths := []*draw2d.Path{} // Draw a path for idx, point := range p[:len(p)] { path := new(draw2d.Path) path.MoveTo(float64(point.X), height-float64(point.Y)) if idx < len(p)-1 { path.LineTo(float64(p[idx+1].X), height-float64(p[idx+1].Y)) } else { path.LineTo(float64(p[0].X), height-float64(p[0].Y)) } paths = append(paths, path) } gc.Stroke(paths...) gc.FillStroke() // Save to file draw2dimg.SaveToPngFile(name, dest) }
func faceDetect(settings CropSettings, i image.Image, o image.Image) error { cvImage := opencv.FromImage(i) _, err := os.Stat(settings.FaceDetectionHaarCascadeFilepath) if err != nil { return err } cascade := opencv.LoadHaarClassifierCascade(settings.FaceDetectionHaarCascadeFilepath) faces := cascade.DetectObjects(cvImage) gc := draw2dimg.NewGraphicContext((o).(*image.RGBA)) if settings.DebugMode == true { log.Println("Faces detected:", len(faces)) } for _, face := range faces { if settings.DebugMode == true { log.Printf("Face: x: %d y: %d w: %d h: %d\n", face.X(), face.Y(), face.Width(), face.Height()) } draw2dkit.Ellipse( gc, float64(face.X()+(face.Width()/2)), float64(face.Y()+(face.Height()/2)), float64(face.Width()/2), float64(face.Height())/2) gc.SetFillColor(color.RGBA{255, 0, 0, 255}) gc.Fill() } return nil }
func render(fr ani.Frame, fnum int) image.Image { w, h := fr.SurfaceDims() // Blank white image bounds := image.Rect(0, 0, int(w), int(h)) dest := image.NewRGBA(bounds) draw.Draw(dest, bounds, &image.Uniform{white}, image.ZP, draw.Src) shapes := []string{ "circle", "square", } plts := []plot{} for _, sh := range shapes { plts = append(plts, plotShape(sh, fr)) } plts = append(plts, plotExplode(fr)) gc := dimg.NewGraphicContext(dest) gc.SetStrokeColor(black) gc.SetFillColor(black) for _, plot := range plts { plot.draw(gc) } return dest }
func newImg(filename string, w, h, levels int) img { // Leave a 5% buffer on the sides so that the image doesn't cut right up to // the edge bw, bh := float64(w)*0.95, float64(h)*0.95 var levelWidth float64 if w > h { levelWidth = bh / 2 / float64(levels) } else { levelWidth = bw / 2 / float64(levels) } if levelWidth < 1 { log.Fatalf("level width is too small! %f", levelWidth) } rgba := image.NewRGBA(image.Rect(0, 0, w, h)) ctx := draw2dimg.NewGraphicContext(rgba) return img{ filename: filename, w: w, h: h, centerX: float64(w) / 2, centerY: float64(h) / 2, levelWidth: int(levelWidth), rgba: rgba, ctx: ctx, } }
func drawLines(src image.Image, lines []polarLine) image.Image { dst := image.NewRGBA(src.Bounds()) gc := draw2dimg.NewGraphicContext(dst) gc.SetFillColor(color.RGBA{0x0, 0x0, 0x0, 0xff}) gc.SetStrokeColor(color.RGBA{0x0, 0xff, 0x0, 0xff}) gc.SetLineWidth(2) gc.Clear() gc.DrawImage(src) for _, line := range lines { a := math.Cos(line.Theta) b := math.Sin(line.Theta) x0 := a * float64(line.Distance) y0 := b * float64(line.Distance) x1 := (x0 + 10000*(-b)) y1 := (y0 + 10000*(a)) x2 := (x0 - 10000*(-b)) y2 := (y0 - 10000*(a)) gc.MoveTo(x1, y1) gc.LineTo(x2, y2) gc.Close() } gc.FillStroke() return dst }
// Create an image of the given size func Create(w, h int, mode ColorSpace) *Image { var img Image img.Surf = image.NewRGBA(image.Rect(0, 0, w, h)) img.Ctx = draw2dimg.NewGraphicContext(img.Surf) img.W, img.H = w, h return &img }
func main() { // Initialize the graphic context on an RGBA image dest := image.NewRGBA(image.Rect(0, 0, 1300, 1200)) gc := draw2dimg.NewGraphicContext(dest) gb := draw2dimg.NewGraphicContext(dest) n := draw2d.NewRotationMatrix(math.Pi / 2) n.Translate(100, -100) gb.SetMatrixTransform(n) Draw(gb, "My Text") // Set some properties gc.SetFillColor(color.RGBA{0x44, 0xff, 0x44, 0xff}) gc.SetStrokeColor(color.RGBA{0x00, 0x00, 0x00, 0xff}) gc.SetLineWidth(3) m := draw2d.NewRotationMatrix(-0.3) // m.TransformRectangle(40, 40, 100, 500) m.Translate(75, 75) gc.SetMatrixTransform(m) // Draw a closed shape gc.MoveTo(39, 39) // should always be called first for a new path gc.LineTo(39, 512) gc.LineTo(512, 512) gc.LineTo(512, 39) gc.LineTo(39, 39) //gc.LineTo(100, 50) //gc.QuadCurveTo(100, 10, 10, 10) gc.Close() gc.FillStroke() gc.SetFillColor(color.RGBA{0xff, 0xff, 0x44, 0x77}) gc.SetMatrixTransform(draw2d.NewRotationMatrix(0)) gc.MoveTo(47, 47) // should always be called first for a new path gc.LineTo(47, 617) gc.LineTo(617, 617) gc.LineTo(617, 47) gc.LineTo(47, 47) gc.Close() gc.FillStroke() g1 := []Point{{1, 2}, {2, 3}, {3, 4}, {4, 3}} Plot(gb, g1) // Save to file draw2dimg.SaveToPngFile("hello.png", dest) }
func NewCanvas(c *Canvas) *Canvas { dest := image.NewRGBA(c.Rect()) ctx := dwg.NewGraphicContext(dest) c.Dest = dest c.GraphicContext = ctx return c }
func NewContext() *Context { img := image.NewRGBA(image.Rect(0, 0, 640, 360)) ctx := &Context{ img, draw2dimg.NewGraphicContext(img), StyleDefault, } ctx.SetFontData(draw2d.FontData{Name: "Default"}) return ctx }
func (r *Renderer) Draw() image.Image { pixelsX, pixelsY := int(r.width), int(r.height) dest := image.NewRGBA(image.Rect(0, 0, pixelsX, pixelsY)) draw.Draw(dest, dest.Bounds(), &image.Uniform{r.m.BgColor}, image.ZP, draw.Src) draw2d.SetFontFolder("/Library/Fonts/") draw2d.SetFontNamer(func(fontData draw2d.FontData) string { return fontData.Name + ".ttf" }) gc := draw2dimg.NewGraphicContext(dest) // gc.DPI = 300 gc.SetLineCap(draw2d.RoundCap) gc.SetFillColor(r.m.BgColor) gc.SetStrokeColor(r.m.Stroke) gc.SetFontData(draw2d.FontData{Name: "Georgia", Family: draw2d.FontFamilySerif, Style: draw2d.FontStyleNormal}) dx := math.Abs(r.bbox[2] - r.bbox[0]) dy := math.Abs(r.bbox[3] - r.bbox[1]) pxf, pyf := float64(pixelsX), float64(pixelsY) r1, r2 := (pxf / dx), (pyf / dy) r0 := math.Min(r1, r2) w, h := dx*r0, dy*r0 ox, oy := (pxf-w)/2, (pyf-h)/2 img_box := [4]float64{ox, oy, ox + w, oy + h} r.matrix = draw2d.NewMatrixFromRects(r.bbox, img_box) for _, layer := range r.m.Layers { q := query.NewQuery(r.m.Bounds()).Select(layer.SourceQuery()) if ds := layer.LoadSource(); ds != nil { defer ds.Close() for shp := range ds.Query(q) { var symbolizerType util.SymbolizerType switch shp.(type) { case geom.LineShape, geom.MultiLineShape: symbolizerType = util.PathType case geom.PolygonShape: symbolizerType = util.PolygonType } for _, symbolizer := range r.findSymbolizers(layer, symbolizerType) { symbolizer.Draw(gc, shp) } for _, symbolizer := range r.findSymbolizers(layer, util.TextType) { symbolizer.Draw(gc, shp) } } } } return dest }
func NewPlotter(height, width float64) *Plotter { pl := Plotter{lineWidth: 3, height: height, width: width, border: 10, xSteps: 10, ySteps: 5} pl.image = image.NewRGBA(image.Rect(0, 0, int(width), int(height))) pl.g = draw2dimg.NewGraphicContext(pl.image) // Set some properties pl.g.SetFillColor(color.RGBA{0x44, 0xff, 0x44, 0xff}) pl.g.SetStrokeColor(color.Black) return &pl }
func main() { i := image.NewRGBA(image.Rect(0, 0, 200, 200)) gc := draw2dimg.NewGraphicContext(i) gc.Save() gc.SetStrokeColor(color.Black) gc.SetFillColor(color.Black) draw2d.Rect(gc, 10, 10, 100, 100) gc.FillStroke() gc.Restore() draw2dimg.SaveToPngFile("yay-rectangle.png", i) }
func DrawTest() { // Initialize the graphic context on an RGBA image dest := image.NewRGBA(image.Rect(0, 0, 297, 210.0)) gc := draw2dimg.NewGraphicContext(dest) DrawHello(gc, "Hello World") // Save to png err := draw2dimg.SaveToPngFile("_testHello.png", dest) if err != nil { log.Fatalln("Saving failed:", err) } }
func drawPolyLine(img *image.RGBA, color color.Color, coords [][]float64) { path := new(draw2d.Path) for i, coord := range coords { if i == 0 { path.MoveTo(coord[0], coord[1]) } else { path.LineTo(coord[0], coord[1]) } } gc := draw2dimg.NewGraphicContext(img) gc.SetStrokeColor(color) gc.Stroke(path) }
func GenerateImage(size int, cube gocube.StickerCube) image.Image { dest := image.NewRGBA(image.Rect(0, 0, size, size)) ctx := draw2dimg.NewGraphicContext(dest) scale := float64(size) / 500 ctx.Scale(-1, 1) ctx.Translate(-float64(size), 0) drawBackground(ctx, scale) drawTopFace(ctx, scale, mirrorDiagonally(colorsForStickers(cube[:9]))) drawRightFace(ctx, scale, mirrorHorizontally(colorsForStickers(cube[9*4:9*5]))) drawFrontFace(ctx, scale, mirrorHorizontally(colorsForStickers(cube[9*2:9*3]))) return dest }
func test(t *testing.T, draw sample) { // Initialize the graphic context on an RGBA image dest := image.NewRGBA(image.Rect(0, 0, 297, 210.0)) gc := draw2dimg.NewGraphicContext(dest) // Draw Android logo output, err := draw(gc, "png") if err != nil { t.Errorf("Drawing %q failed: %v", output, err) return } // Save to png err = draw2dimg.SaveToPngFile(output, dest) if err != nil { t.Errorf("Saving %q failed: %v", output, err) } }
// AddTo returns a new ImageGraphics which will write to (width x height) sized // area starting at (x,y) on the provided image img. The rest of the parameters // are the same as in New(). func AddTo(img *image.RGBA, x, y, width, height int, bgcol color.RGBA, font *truetype.Font, fontsize map[chart.FontSize]float64) *ImageGraphics { gc := draw2dimg.NewGraphicContext(img) gc.SetLineJoin(draw2d.BevelJoin) gc.SetLineCap(draw2d.SquareCap) gc.SetStrokeColor(image.Black) gc.SetFillColor(bgcol) gc.Translate(float64(x)+0.5, float64(y)+0.5) gc.ClearRect(x, y, x+width, y+height) if font == nil { font = defaultFont } if len(fontsize) == 0 { fontsize = ConstructFontSizes(13) } return &ImageGraphics{Image: img, x0: x, y0: y, w: width, h: height, bg: bgcol, gc: gc, font: font, fs: fontsize} }
func imgPng(w http.ResponseWriter, r *http.Request) *appError { w.Header().Set("Content-type", "image/png") // Initialize the graphic context on an RGBA image dest := image.NewRGBA(image.Rect(0, 0, 297, 210.0)) gc := draw2dimg.NewGraphicContext(dest) // Draw sample android.Draw(gc, 65, 0) err := png.Encode(w, dest) if err != nil { return &appError{err, fmt.Sprintf("Can't encode: %s", err), 500} } return nil }
func GenerateCaptionedImage(size int, fontSize float64, caption string, cube gocube.StickerCube) image.Image { dest := image.NewRGBA(image.Rect(0, 0, size, size)) ctx := draw2dimg.NewGraphicContext(dest) captionImage := generateCaptionImage(size, fontSize, caption) captionHeight := float64(captionImage.Bounds().Dy()) remainingSize := float64(size) - captionHeight ctx.DrawImage(captionImage) cubeImage := GenerateImage(int(remainingSize), cube) ctx.Translate((float64(size)-remainingSize)/2, captionHeight) ctx.DrawImage(cubeImage) return dest }
// New creates a new ImageGraphics including an image.RGBA of dimension w x h // with background bgcol. If font is nil it will use a builtin font. // If fontsize is empty useful default are used. func New(width, height int, bgcol color.RGBA, font *truetype.Font, fontsize map[chart.FontSize]float64) *ImageGraphics { img := image.NewRGBA(image.Rect(0, 0, width, height)) gc := draw2dimg.NewGraphicContext(img) gc.SetLineJoin(draw2d.BevelJoin) gc.SetLineCap(draw2d.SquareCap) gc.SetStrokeColor(image.Black) gc.SetFillColor(bgcol) gc.Translate(0.5, 0.5) gc.Clear() if font == nil { font = defaultFont } if len(fontsize) == 0 { fontsize = ConstructFontSizes(13) } return &ImageGraphics{Image: img, x0: 0, y0: 0, w: width, h: height, bg: bgcol, gc: gc, font: font, fs: fontsize} }
func measureText(fontSize float64, text string) (width, height float64) { dest := image.NewRGBA(image.Rect(0, 0, 1, 1)) ctx := draw2dimg.NewGraphicContext(dest) fontData := draw2d.FontData{ Name: "Roboto", Family: draw2d.FontFamilySans, Style: draw2d.FontStyleNormal, } draw2d.SetFontFolder(fontFolder()) ctx.SetFontData(fontData) ctx.SetFontSize(fontSize) left, top, right, bottom := ctx.GetStringBounds(text) width = right - left height = bottom - top return }
func faceDetect(settings CropSettings, i image.Image, o image.Image, scale float64) ([]Face, error) { cvImage := opencv.FromImage(i) _, err := os.Stat(settings.FaceDetectionHaarCascadeFilepath) if err != nil { return []Face{}, err } cascade := opencv.LoadHaarClassifierCascade(settings.FaceDetectionHaarCascadeFilepath) faces := cascade.DetectObjects(cvImage) gc := draw2dimg.NewGraphicContext((o).(*image.RGBA)) if settings.DebugMode == true { log.Println("Faces detected:", len(faces)) } if len(faces) == 0 { return []Face{}, ErrNoFacesFound } resultFaces := []Face{} for _, face := range faces { if settings.DebugMode == true { log.Printf("Face: x: %d y: %d w: %d h: %d\n", face.X(), face.Y(), face.Width(), face.Height()) } draw2dkit.Ellipse( gc, float64(face.X()+(face.Width()/2)), float64(face.Y()+(face.Height()/2)), float64(face.Width()/2), float64(face.Height())/2) gc.SetFillColor(color.RGBA{255, 0, 0, 255}) gc.Fill() x := int(float64(face.X()) * scale) y := int(float64(face.Y()) * scale) width := int(float64(face.Width()) * scale) height := int(float64(face.Height()) * scale) resultFaces = append(resultFaces, Face{X: x, Y: y, Width: width, Height: height}) } return resultFaces, nil }
func TestCircle(t *testing.T) { width := 200 height := 200 img := image.NewRGBA(image.Rect(0, 0, width, height)) gc := draw2dimg.NewGraphicContext(img) gc.SetStrokeColor(color.NRGBA{255, 255, 255, 255}) gc.SetFillColor(color.NRGBA{255, 255, 255, 255}) gc.Clear() gc.SetStrokeColor(color.NRGBA{255, 0, 0, 255}) gc.SetLineWidth(1) // Draw a circle Circle(gc, 100, 100, 50) gc.Stroke() draw2dimg.SaveToPngFile("../output/draw2dkit/TestCircle.png", img) }
// NewWith returns a new image canvas created according to the specified // options. The currently accepted options are UseWH, // UseDPI, UseImage, and UseImageWithContext. // Each of the options specifies the size of the canvas (UseWH, UseImage), // the resolution of the canvas (UseDPI), or both (useImageWithContext). // If size or resolution are not specified, defaults are used. // It panics if size and resolution are overspecified (i.e., too many options are // passed). func NewWith(o ...option) *Canvas { c := new(Canvas) var g uint32 for _, opt := range o { f := opt(c) if g&f != 0 { panic("incompatible options") } g |= f } if c.dpi == 0 { c.dpi = DefaultDPI } if c.w == 0 { // h should also == 0. if c.img == nil { c.w = DefaultWidth c.h = DefaultHeight } else { w := float64(c.img.Bounds().Max.X - c.img.Bounds().Min.X) h := float64(c.img.Bounds().Max.Y - c.img.Bounds().Min.Y) c.w = vg.Length(w/float64(c.dpi)) * vg.Inch c.h = vg.Length(h/float64(c.dpi)) * vg.Inch } } if c.img == nil { w := c.w / vg.Inch * vg.Length(c.dpi) h := c.h / vg.Inch * vg.Length(c.dpi) c.img = draw.Image(image.NewRGBA(image.Rect(0, 0, int(w+0.5), int(h+0.5)))) } if c.gc == nil { h := float64(c.img.Bounds().Max.Y - c.img.Bounds().Min.Y) c.gc = draw2dimg.NewGraphicContext(c.img) c.gc.SetDPI(c.dpi) c.gc.Scale(1, -1) c.gc.Translate(0, -h) } draw.Draw(c.img, c.img.Bounds(), image.White, image.ZP, draw.Src) c.color = []color.Color{color.Black} vg.Initialize(c) return c }
// Draw uses the parameters in the hilbertImage and returns a Image func (h *spaceFillingImage) Draw() (draw.Image, error) { img, err := h.createImage() if err != nil { return nil, err } gc := draw2dimg.NewGraphicContext(img) snake := &draw2d.Path{} width, height := h.Algo.GetDimensions() for t := 0; t < width*height; t++ { // Map the 1D number into the 2D space x, y, err := h.Algo.Map(t) if err != nil { return nil, err } px1, py1 := h.toPixel(x, y) px2, py2 := h.toPixel(x+1, y+1) // Draw the grid for t h.drawRectange(gc, px1, py1, px2, py2) h.drawText(gc, px1, py1, t) // Move the snake along centerX, centerY := px1+h.SquareWidth/2, py1+h.SquareHeight/2 if t == 0 { snake.MoveTo(centerX, centerY) } else { snake.LineTo(centerX, centerY) } } // Draw the snake at the end, to form one continuous line. h.drawSnake(gc, snake) return img, nil }
func drawLineFragments(src image.Image, fragments []lineFragment) image.Image { dst := image.NewRGBA(src.Bounds()) gc := draw2dimg.NewGraphicContext(dst) gc.SetFillColor(color.RGBA{0x0, 0x0, 0x0, 0xff}) gc.SetStrokeColor(color.RGBA{0x0, 0xff, 0x0, 0xff}) gc.SetLineWidth(2) gc.Clear() gc.DrawImage(src) for _, fragment := range fragments { x1, y1 := float64(fragment.Start.X), float64(fragment.Start.Y) x2, y2 := float64(fragment.End.X), float64(fragment.End.Y) gc.MoveTo(x1, y1) gc.LineTo(x2, y2) gc.Close() } gc.FillStroke() return dst }
func (r Record) generateImage() image.Image { img := image.NewRGBA(image.Rect(0, 0, r.Width, r.Height)) _, fileName := r.getDirFile(r.Path) var src image.Image switch { case "icon" == r.pattern: size := r.Width if size > r.Height { size = r.Height } sqSize := int(size / 8) borderX := int((r.Width - (sqSize * 7)) / 2) borderY := int((r.Height - (sqSize * 7)) / 2) icon := New7x7Size(sqSize, r.Width, r.Height, borderX, borderY, sipHashKey[:]) data := []byte(fileName) src = icon.Render(data) case "warm" == r.pattern: src = &image.Uniform{colorful.WarmColor()} case "happy" == r.pattern: src = &image.Uniform{colorful.HappyColor()} case "rand" == r.pattern: src = &image.Uniform{colorful.LinearRgb(rand.Float64(), rand.Float64(), rand.Float64())} case r.isHex(): hc, _ := colorful.Hex(r.pattern) src = &image.Uniform{hc} default: src = &image.Uniform{colorful.FastWarmColor()} } draw.Draw(img, img.Bounds(), src, image.ZP, draw.Src) if r.allowDrawText { gc := draw2dimg.NewGraphicContext(img) drawText(gc, fileName, 2, float64(r.Height)) } return img }
// DrawPolygon draws the polygon represented by Points on the canvas func DrawPolygon(p Points, width, height float64, name string) { // Initialize the graphic context on an RGBA image dest := image.NewRGBA(image.Rect(0, 0, int(width), int(height))) gc := draw2dimg.NewGraphicContext(dest) // Set some properties gc.SetFillColor(color.RGBA{0x44, 0xff, 0x44, 0xff}) gc.SetStrokeColor(color.RGBA{0x44, 0x44, 0x44, 0xff}) gc.SetLineWidth(5) // Draw a closed shape gc.MoveTo(float64(p[0].X), height-float64(p[0].Y)) for _, point := range p[1:] { gc.LineTo(float64(point.X), height-float64(point.Y)) gc.MoveTo(float64(point.X), height-float64(point.Y)) } gc.Close() gc.FillStroke() // Save to file draw2dimg.SaveToPngFile(name, dest) }
func generateCaptionImage(width int, fontSize float64, caption string) image.Image { lines := wrapText(fontSize, caption, float64(width)*(1-captionSideMargin*2)) height := wrappedTextHeight(fontSize, lines) dest := image.NewRGBA(image.Rect(0, 0, width, int(height))) ctx := draw2dimg.NewGraphicContext(dest) draw2d.SetFontFolder(fontFolder()) ctx.SetFontData(defaultFontData) ctx.SetFontSize(fontSize) ctx.SetFillColor(color.RGBA{0, 0, 0, 255}) var y float64 for _, line := range lines { lineWidth, lineHeight := measureText(fontSize, line) lineMargin := lineHeight * (lineHeightRatio - 1) / 2 y += lineHeight + lineMargin ctx.FillStringAt(line, (float64(width)-lineWidth)/2, y) y += lineMargin } return dest }