Beispiel #1
1
// Draw renders the given cpu cores on img.
func (app *App) Draw(img draw.Image, cpus []CPU) {
	rect := img.Bounds()
	bg := app.Background
	if bg == nil {
		bg = image.Black
	}
	draw.Draw(img, rect, bg, bg.Bounds().Min, draw.Over)

	if len(cpus) == 0 {
		return
	}

	cpuDx := rect.Dx() / len(cpus)
	ptIncr := image.Point{X: cpuDx}
	ptDelta := image.Point{}
	rectDx := image.Rectangle{
		Min: rect.Min,
		Max: rect.Max,
	}
	rectDx.Max.X = rect.Min.X + cpuDx
	for _, cpu := range cpus {
		irect := image.Rectangle{
			Min: rectDx.Min.Add(ptDelta),
			Max: rectDx.Max.Add(ptDelta),
		}
		subimg := SubImage(img, irect)
		app.renderCPU(subimg, cpu)

		ptDelta = ptDelta.Add(ptIncr)
	}
}
Beispiel #2
0
// 翻转函数,要求两个图像大小契合,act&1 == 0则左右翻转,否则垂直翻转。
func Overturn(dst draw.Image, src image.Image, act int) error {
	var to func(int, int) (int, int)
	sr := src.Bounds()
	dr := dst.Bounds()
	W := dr.Max.X - dr.Min.X
	H := dr.Max.Y - dr.Min.Y
	if H <= 0 || W <= 0 {
		return errors.New("target image is empty or noncanonical")
	}
	if sr.Min.X >= sr.Max.X || sr.Min.Y >= sr.Max.Y {
		return errors.New("source image is empty or noncanonical")
	}
	if sr.Max.X-sr.Min.X != W || sr.Max.Y-sr.Min.Y != H {
		return errors.New("target and source must be same size!")
	}
	if act&1 == 0 {
		to = func(x, y int) (int, int) {
			return W - 1 - x, y
		}
	} else {
		to = func(x, y int) (int, int) {
			return x, H - 1 - y
		}
	}
	for i := 0; i < W; i++ {
		for j := 0; j < H; j++ {
			x, y := to(i, j)
			dst.Set(dr.Min.X+x, dr.Min.Y+y, src.At(sr.Min.X+i, sr.Min.Y+j))
		}
	}
	return nil
}
Beispiel #3
0
func (ff *FontFace) GetImage(text string) (img draw.Image, err error) {
	var (
		src image.Image
		bg  image.Image
		dst draw.Image
		pt  fixed.Point26_6
		w   int
		h   int
	)
	src = image.NewUniform(ff.fg)
	bg = image.NewUniform(ff.bg)
	w = int(float32(len(text)) * ff.charw)
	h = int(ff.charh)
	dst = image.NewRGBA(image.Rect(0, 0, w, h))
	draw.Draw(dst, dst.Bounds(), bg, image.ZP, draw.Src)
	ff.context.SetSrc(src)
	ff.context.SetDst(dst)
	ff.context.SetClip(dst.Bounds())
	pt = freetype.Pt(0, int(ff.charh+ff.offy))
	if pt, err = ff.context.DrawString(text, pt); err != nil {
		return
	}
	img = image.NewRGBA(image.Rect(0, 0, int(pt.X/64), int(pt.Y/64)))
	draw.Draw(img, img.Bounds(), dst, image.Pt(0, -int(ff.offy)), draw.Src)
	return
}
Beispiel #4
0
func (p *Drawer) PasteAt(img draw.Image, pt P) {
	flr := pt.Floor()
	bounds := img.Bounds()
	dp := image.Point{flr[0], flr[1]}
	rec := bounds.Sub(bounds.Min).Add(dp)
	draw.Draw(p.Img, rec, img, bounds.Min, draw.Over)
}
Beispiel #5
0
// Transform applies the affine transform to src and produces dst.
func (a Affine) Transform(dst draw.Image, src image.Image, i interp.Interp) error {
	if dst == nil {
		return errors.New("graphics: dst is nil")
	}
	if src == nil {
		return errors.New("graphics: src is nil")
	}

	// RGBA fast path.
	dstRGBA, dstOk := dst.(*image.RGBA)
	srcRGBA, srcOk := src.(*image.RGBA)
	interpRGBA, interpOk := i.(interp.RGBA)
	if dstOk && srcOk && interpOk {
		return a.transformRGBA(dstRGBA, srcRGBA, interpRGBA)
	}

	srcb := src.Bounds()
	b := dst.Bounds()
	for y := b.Min.Y; y < b.Max.Y; y++ {
		for x := b.Min.X; x < b.Max.X; x++ {
			sx, sy := a.pt(x, y)
			if inBounds(srcb, sx, sy) {
				dst.Set(x, y, i.Interp(src, sx, sy))
			}
		}
	}
	return nil
}
Beispiel #6
0
func warm(out, in draw.Image, opacity uint8, colors []color.Color) {
	draw.Draw(out, out.Bounds(), image.Transparent, image.ZP, draw.Src)
	bounds := in.Bounds()
	collen := float64(len(colors))
	wg := &sync.WaitGroup{}
	for x := bounds.Min.X; x < bounds.Max.X; x++ {
		wg.Add(1)
		go func(x int) {
			defer wg.Done()
			for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
				col := in.At(x, y)
				_, _, _, alpha := col.RGBA()
				if alpha > 0 {
					percent := float64(alpha) / float64(0xffff)
					template := colors[int((collen-1)*(1.0-percent))]
					tr, tg, tb, ta := template.RGBA()
					ta /= 256
					outalpha := uint8(float64(ta) *
						(float64(opacity) / 256.0))
					outcol := color.NRGBA{
						uint8(tr / 256),
						uint8(tg / 256),
						uint8(tb / 256),
						uint8(outalpha)}
					out.Set(x, y, outcol)
				}
			}
		}(x)
	}
	wg.Wait()
}
Beispiel #7
0
// Thumbnail scales and crops src so it fits in dst.
func Thumbnail(dst draw.Image, src image.Image) error {
	// Scale down src in the dimension that is closer to dst.
	sb := src.Bounds()
	db := dst.Bounds()
	rx := float64(sb.Dx()) / float64(db.Dx())
	ry := float64(sb.Dy()) / float64(db.Dy())
	var b image.Rectangle
	if rx < ry {
		b = image.Rect(0, 0, db.Dx(), int(float64(sb.Dy())/rx))
	} else {
		b = image.Rect(0, 0, int(float64(sb.Dx())/ry), db.Dy())
	}

	buf := image.NewRGBA(b)
	if err := Scale(buf, src); err != nil {
		return err
	}

	// Crop.
	// TODO(crawshaw): improve on center-alignment.
	var pt image.Point
	if rx < ry {
		pt.Y = (b.Dy() - db.Dy()) / 2
	} else {
		pt.X = (b.Dx() - db.Dx()) / 2
	}
	draw.Draw(dst, db, buf, pt, draw.Src)
	return nil
}
Beispiel #8
0
// NewImage returns a new image canvas
// that draws to the given image.  The
// minimum point of the given image
// should probably be 0,0.
func NewImage(img draw.Image, name string) (*Canvas, error) {
	w := float64(img.Bounds().Max.X - img.Bounds().Min.X)
	h := float64(img.Bounds().Max.Y - img.Bounds().Min.Y)

	X, err := xgbutil.NewConn()
	if err != nil {
		return nil, err
	}
	keybind.Initialize(X)
	ximg := xgraphics.New(X, image.Rect(0, 0, int(w), int(h)))
	err = ximg.CreatePixmap()
	if err != nil {
		return nil, err
	}
	painter := NewPainter(ximg)
	gc := draw2d.NewGraphicContextWithPainter(ximg, painter)
	gc.SetDPI(dpi)
	gc.Scale(1, -1)
	gc.Translate(0, -h)

	wid := ximg.XShowExtra(name, true)
	go func() {
		xevent.Main(X)
	}()

	c := &Canvas{
		Canvas: vgimg.NewWith(vgimg.UseImageWithContext(img, gc)),
		x:      X,
		ximg:   ximg,
		wid:    wid,
	}
	vg.Initialize(c)
	return c, nil
}
Beispiel #9
0
// Convolve produces dst by applying the convolution kernel k to src.
func Convolve(dst draw.Image, src image.Image, k Kernel) (err error) {
	if dst == nil || src == nil || k == nil {
		return nil
	}

	b := dst.Bounds()
	dstRgba, ok := dst.(*image.RGBA)
	if !ok {
		dstRgba = image.NewRGBA(b)
	}

	switch k := k.(type) {
	case *SeparableKernel:
		err = convolveRGBASep(dstRgba, src, k)
	default:
		err = convolveRGBA(dstRgba, src, k)
	}

	if err != nil {
		return err
	}

	if !ok {
		draw.Draw(dst, b, dstRgba, b.Min, draw.Src)
	}
	return nil
}
Beispiel #10
0
func warm(out, in draw.Image, opacity uint8, colors []color.Color) {
	bounds := in.Bounds()
	collen := float64(len(colors))
	wg := sync.WaitGroup{}
	wg.Add(bounds.Dx())
	for x := bounds.Min.X; x < bounds.Max.X; x++ {
		go func(x int) {
			defer wg.Done()
			for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
				col := in.At(x, y)
				_, _, _, alpha := col.RGBA()
				percent := float64(alpha) / float64(0xffff)
				var outcol color.Color
				if percent == 0 {
					outcol = color.Transparent
				} else {
					template := colors[int((collen-1)*(1.0-percent))]
					tr, tg, tb, ta := template.RGBA()
					ta /= 256
					outalpha := uint8(float64(ta) *
						(float64(opacity) / 256.0))
					outcol = color.NRGBA{
						uint8(tr / 256),
						uint8(tg / 256),
						uint8(tb / 256),
						uint8(outalpha)}
				}
				out.Set(x, y, outcol)
			}
		}(x)
	}
	wg.Wait()
}
Beispiel #11
0
// NewFromImage uses the given image as the destination for all calls to Add.
// It is assumed to be empty at the beginning so all the available space will be
// used for sub-images.
func NewFromImage(atlas draw.Image) *Atlas {
	packer := binpacker.New(atlas.Bounds().Dx(), atlas.Bounds().Dy())
	return &Atlas{
		Image:  atlas,
		packer: packer,
	}
}
Beispiel #12
0
// RenderCPU implements the Renderer interface.
func (b *Border) RenderCPU(img draw.Image, cpu CPU) {
	rect := img.Bounds()
	interior := geometry.Contract(rect, b.Size)
	mask := MaskInside(interior)
	draw.DrawMask(img, rect, image.NewUniform(b.Color), image.ZP, mask, rect.Min, draw.Over)
	sub := SubImage(img, interior)
	b.Renderer.RenderCPU(sub, cpu)
}
Beispiel #13
0
func newImageDimentions(img draw.Image, angle float64) (int, int) {
	bounds := img.Bounds()
	width := float64(bounds.Max.X - bounds.Min.X)
	height := float64(bounds.Max.Y - bounds.Min.Y)

	w, h := newDimentions(width, height, angle)
	return int(w), int(h)
}
Beispiel #14
0
func testDrawRandom(p draw.Image) {
	bd := p.Bounds()
	for y, yEnd := bd.Min.Y, bd.Max.Y; y < yEnd; y++ {
		for x, xEnd := bd.Min.X, bd.Max.X; x < xEnd; x++ {
			p.Set(x, y, testRandomColor())
		}
	}
}
Beispiel #15
0
// Apply the given color mapping to the specified image buffers.
func Apply(from, to *Rule, src, dst draw.Image) {
	var x, y int
	var r, g, b, a uint32
	var sc color.Color
	var dc color.RGBA
	var pix pixel

	rect := src.Bounds()

	for y = 0; y < rect.Dy(); y++ {
		for x = 0; x < rect.Dx(); x++ {
			sc = src.At(x, y)

			r, g, b, a = sc.RGBA()
			pix.r = uint8(r >> 8)
			pix.g = uint8(g >> 8)
			pix.b = uint8(b >> 8)
			pix.a = uint8(a >> 8)

			// Check if the pixel matches the filter rule.
			if !(match(pix.r, from.R) && match(pix.g, from.G) && match(pix.b, from.B) && match(pix.a, from.A)) {
				dst.Set(x, y, sc)
				continue
			}

			// Compute three different types of grayscale conversion.
			// These can be applied by named references.
			pix.average = uint8(((r + g + b) / 3) >> 8)
			pix.lightness = uint8(((min(min(r, g), b) + max(max(r, g), b)) / 2) >> 8)

			// For luminosity it is necessary to apply an inverse of the gamma
			// function for the color space before calculating the inner product.
			// Then you apply the gamma function to the reduced value. Failure to
			// incorporate the gamma function can result in errors of up to 20%.
			//
			// For typical computer stuff, the color space is sRGB. The right
			// numbers for sRGB are approx. 0.21, 0.72, 0.07. Gamma for sRGB
			// is a composite function that approximates exponentiation by 1/2.2
			//
			// This is a rather expensive operation, but gives a much more accurate
			// and satisfactory result than the average and lightness versions.
			pix.luminosity = gammaSRGB(
				0.212655*invGammaSRGB(pix.r) +
					0.715158*invGammaSRGB(pix.g) +
					0.072187*invGammaSRGB(pix.b))

			// Transform color.
			dc.R = transform(&pix, pix.r, to.R)
			dc.G = transform(&pix, pix.g, to.G)
			dc.B = transform(&pix, pix.b, to.B)
			dc.A = transform(&pix, pix.a, to.A)

			// Set new pixel.
			dst.Set(x, y, dc)
		}
	}
}
Beispiel #16
0
// Blends src image (top layer) into dst image (bottom layer) using
// the BlendFunc provided by mode. BlendFunc is applied to each pixel
// where the src image overlaps the dst image and the result is stored
// in the original dst image, src image is unmutable.
func BlendImage(dst draw.Image, src image.Image, mode BlendFunc) {
	// Obtain the intersection of both images.
	inter := dst.Bounds().Intersect(src.Bounds())
	// Apply BlendFuc to each pixel in the intersection.
	for y := inter.Min.Y; y < inter.Max.Y; y++ {
		for x := inter.Min.X; x < inter.Max.X; x++ {
			dst.Set(x, y, mode(dst.At(x, y), src.At(x, y)))
		}
	}
}
// Like PixelSizeChanger, but instead of the pixel size the new image
// is given.
func DimensionChanger(img draw.Image, w, h int) draw.Image {
	b := img.Bounds().Canon()
	return &dimensionChanger{
		Image:    img,
		paddingX: b.Dx() % w,
		paddingY: b.Dy() % h,
		pixel:    image.Rect(0, 0, b.Dx()/w, b.Dy()/h),
		bounds:   image.Rect(0, 0, w, h),
	}
}
Beispiel #18
0
// TransformCenter applies the affine transform to src and produces dst.
// Equivalent to
//   a.CenterFit(dst, src).Transform(dst, src, i).
func (a Affine) TransformCenter(dst draw.Image, src image.Image, i interp.Interp) error {
	if dst == nil {
		return errors.New("graphics: dst is nil")
	}
	if src == nil {
		return errors.New("graphics: src is nil")
	}

	return a.CenterFit(dst.Bounds(), src.Bounds()).Transform(dst, src, i)
}
Beispiel #19
0
// NewBackground creates a new Background object that
// draws to img, and draws the actual background with bg.
// The flush function, if non-nil, will be called to
// whenever changes are to be made visible externally
// (for example when Flush() is called.
//
// Note that bg is drawn with the draw.Src operation,
// so it is possible to create images with a transparent
// background.
//
func NewBackground(img draw.Image, bg image.Image, flush func(r image.Rectangle)) *Background {
	r := img.Bounds()
	return &Background{
		img:       img,
		bg:        bg,
		r:         r,
		flushrect: r,
		imgflush:  flush,
	}
}
Beispiel #20
0
// SliceImage returns an image which is a view onto a portion of img.
// The returned image has the specified width and height,
// but all draw operations are clipped to r.
// The origin of img is aligned with p. Where img
// overlaps with r, it will be used for drawing operations.
//
func SliceImage(width, height int, r image.Rectangle, img draw.Image, p image.Point) draw.Image {
	// TODO: detect when img is itself a SliceImage and
	// use the underlying image directly.
	i := new(imageSlice)
	i.img = img
	i.r = r.Intersect(image.Rectangle{p, p.Add(img.Bounds().Size())})
	//debugp("actual sliced rectangle %v\n", i.r)
	i.p = p
	return i
}
Beispiel #21
0
// DrawLinear draws a linear gradient to dst. If the gradient vector (as
// defined by x0, y0, x1, and y1) is found to be purely horizontal or purely
// vertical, the appropriate optimized functions will be called.
func DrawLinear(dst draw.Image, x0, y0, x1, y1 float64, stops []Stop) {
	if y0 == y1 && x0 != x1 {
		drawHLinear(dst, x0, x1, stops)
		return
	}

	if x0 == x1 && y0 != y1 {
		drawVLinear(dst, y0, y1, stops)
		return
	}

	if len(stops) == 0 {
		return
	}

	if y0 > y1 {
		panic(fmt.Sprintf("invalid bounds y0(%f)>y1(%f)", y0, y1))
	}
	if x0 > x1 {
		panic(fmt.Sprintf("invalid bounds x0(%f)>x1(%f)", x0, x1))
	}

	bb := dst.Bounds()
	width, height := bb.Dx(), bb.Dy()

	x0, y0 = x0*float64(width), y0*float64(height)
	x1, y1 = x1*float64(width), y1*float64(height)

	dx, dy := x1-x0, y1-y0
	px0, py0 := x0-dy, y0+dx
	mag := math.Hypot(dx, dy)

	var col color.Color
	for y := 0; y < width; y++ {
		fy := float64(y)

		for x := 0; x < width; x++ {
			fx := float64(x)
			// is the pixel before the start of the gradient?
			s0 := (px0-x0)*(fy-y0) - (py0-y0)*(fx-x0)
			if s0 > 0 {
				col = stops[0].Col
			} else {
				// calculate the distance of the pixel from the first stop line
				u := ((fx-x0)*(px0-x0) + (fy-y0)*(py0-y0)) /
					(mag * mag)
				x2, y2 := x0+u*(px0-x0), y0+u*(py0-y0)
				d := math.Hypot(fx-x2, fy-y2) / mag

				col = getColour(d, stops)
			}
			dst.Set(x+bb.Min.X, y+bb.Min.Y, col)
		}
	}
}
Beispiel #22
0
// RenderCPU implements the Renderer interface.
func (frac *FractionRenderer) RenderCPU(img draw.Image, cpu CPU) {
	rect := img.Bounds()

	utilized := cpu.FracUtil()
	utilizedHeight := int(float64(rect.Dy()) * utilized)
	yoffset := rect.Dy() - utilizedHeight
	rect.Min = rect.Min.Add(image.Pt(0, yoffset))
	img = SubImage(img, rect)

	frac.Renderer.RenderCPU(img, cpu)
}
Beispiel #23
0
func (p *Drawer) NoAddMerge(img draw.Image) {
	dest := p.Img
	srcBounds := img.Bounds()
	destB := dest.Bounds()
	destRect := srcBounds.Sub(srcBounds.Min).Add(destB.Min)
	source := img
	sourcePt := srcBounds.Min
	maskPt := destRect.Min
	mask := p.Img
	draw.DrawMask(dest, destRect, source, sourcePt, mask, maskPt, draw.Over)
}
Beispiel #24
0
func (l limits) translate(p DataPoint, i draw.Image, dotsize int) (rv image.Point) {
	// Normalize to 0-1
	x := float64(p.X()-l.Min.X()) / float64(l.Dx())
	y := float64(p.Y()-l.Min.Y()) / float64(l.Dy())

	// And remap to the image
	rv.X = int(x * float64((i.Bounds().Max.X - dotsize)))
	rv.Y = int((1.0 - y) * float64((i.Bounds().Max.Y - dotsize)))

	return
}
Beispiel #25
0
func drawImg(dst draw.Image, asset string, err error) error {
	if err != nil {
		return err
	}
	src, _, err := image.Decode(bytes.NewReader(MustAsset(asset)))
	if err != nil {
		return err
	}
	draw.Draw(dst, dst.Bounds(), src, image.Point{0, 0}, draw.Over)
	return nil
}
Beispiel #26
0
// clip clips r against each image's bounds (after translating into
// the destination image's co-ordinate space) and shifts the point
// sp by the same amount as the change in r.Min.
func clip(dst draw.Image, r *image.Rectangle, src image.Image, sp *image.Point) {
	orig := r.Min
	*r = r.Intersect(dst.Bounds())
	*r = r.Intersect(src.Bounds().Add(orig.Sub(*sp)))
	dx := r.Min.X - orig.X
	dy := r.Min.Y - orig.Y
	if dx == 0 && dy == 0 {
		return
	}
	(*sp).X += dx
	(*sp).Y += dy
}
Beispiel #27
0
// Copy copies src to dst.
func Copy(dst draw.Image, src image.Image) {
	bd := src.Bounds().Intersect(dst.Bounds())
	at := NewAtFunc(src)
	set := NewSetFunc(dst)
	Parallel(bd, func(bd image.Rectangle) {
		for y := bd.Min.Y; y < bd.Max.Y; y++ {
			for x := bd.Min.X; x < bd.Max.X; x++ {
				r, g, b, a := at(x, y)
				set(x, y, r, g, b, a)
			}
		}
	})
}
Beispiel #28
0
func noise(src draw.Image) {
	orig := src.Bounds()
	numToMod := (orig.Max.X * orig.Max.Y) / 2
	for i := 0; i < numToMod; i++ {
		x := rand.Intn(orig.Max.X)
		y := rand.Intn(orig.Max.Y)
		origColor := src.At(x, y).(color.RGBA)
		origColor.R += 30
		origColor.B += 30
		origColor.G += 30
		src.Set(x, y, origColor)
	}
}
Beispiel #29
0
// NewGraphicContextWithPainter creates a new Graphic context from an image and a Painter (see Freetype-go)
func NewGraphicContextWithPainter(img draw.Image, painter Painter) *ImageGraphicContext {
	width, height := img.Bounds().Dx(), img.Bounds().Dy()
	dpi := 92
	gc := &ImageGraphicContext{
		NewStackGraphicContext(),
		img,
		painter,
		raster.NewRasterizer(width, height),
		raster.NewRasterizer(width, height),
		truetype.NewGlyphBuf(),
		dpi,
	}
	return gc
}
Beispiel #30
0
// SubImage extracts a rectangular subset of img as a separate image.
// If present, the `SubImage()` method will be used. Otherwise, the
// behaviour will be emulated.
func SubImage(img draw.Image, r image.Rectangle) draw.Image {
	if di, ok := img.(subimager); ok {
		si := di.SubImage(r)
		dsi, ok := si.(draw.Image)
		if !ok {
			panic("Image is drawable, subimage is not.")
		}
		return dsi
	}
	return &subimage{
		Image:  img,
		bounds: img.Bounds().Intersect(r),
	}
}