// SubImage returns an image representing the portion of the image p visible // through r. The returned value shares pixels with the original image. func (p *Image) SubImage(r image.Rectangle) image.Image { // TODO: share code with image.NewYCbCr when this type moves into the // standard image package. r = r.Intersect(p.Rect) // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside // either r1 or r2 if the intersection is empty. Without explicitly checking for // this, the Pix[i:] expression below can panic. if r.Empty() { return &Image{ YCbCr: image.YCbCr{ SubsampleRatio: p.SubsampleRatio, }, } } yi := p.YOffset(r.Min.X, r.Min.Y) ci := p.COffset(r.Min.X, r.Min.Y) ai := p.AOffset(r.Min.X, r.Min.Y) return &Image{ YCbCr: image.YCbCr{ Y: p.Y[yi:], Cb: p.Cb[ci:], Cr: p.Cr[ci:], SubsampleRatio: p.SubsampleRatio, YStride: p.YStride, CStride: p.CStride, Rect: r, }, A: p.A[ai:], AStride: p.AStride, } }
func (buffer Image) CopyRGBA(src *image.RGBA, r image.Rectangle) { // clip r against each image's bounds and move sp accordingly (see draw.clip()) sp := image.ZP orig := r.Min r = r.Intersect(buffer.Bounds()) r = r.Intersect(src.Bounds().Add(orig.Sub(sp))) dx := r.Min.X - orig.X dy := r.Min.Y - orig.Y (sp).X += dx (sp).Y += dy i0 := (r.Min.X - buffer.Rect.Min.X) * 4 i1 := (r.Max.X - buffer.Rect.Min.X) * 4 si0 := (sp.X - src.Rect.Min.X) * 4 yMax := r.Max.Y - buffer.Rect.Min.Y y := r.Min.Y - buffer.Rect.Min.Y sy := sp.Y - src.Rect.Min.Y for ; y != yMax; y, sy = y+1, sy+1 { dpix := buffer.Pix[y*buffer.Stride:] spix := src.Pix[sy*src.Stride:] for i, si := i0, si0; i < i1; i, si = i+4, si+4 { dpix[i+0] = spix[si+2] dpix[i+1] = spix[si+1] dpix[i+2] = spix[si+0] dpix[i+3] = spix[si+3] } } }
func AverageNRGBA64(rect image.Rectangle, img *image.NRGBA64) color.NRGBA64 { // Only use the area of the rectangle that overlaps with the image bounds. rect = rect.Intersect(img.Bounds()) // Determine whether or not there's any area over which to determine an // average. d := uint64(rect.Dx() * rect.Dy()) if d == 0 { return color.NRGBA64{} } var r, g, b, a uint64 AllPointsRP( func(pt image.Point) { c := img.NRGBA64At(pt.X, pt.Y) r += uint64(c.R) g += uint64(c.G) b += uint64(c.B) a += uint64(c.A) }, )(rect) return color.NRGBA64{ R: uint16(r / d), G: uint16(g / d), B: uint16(b / d), A: uint16(a / d), } }
func (p *cropToSizeFilter) Bounds(srcBounds image.Rectangle) (dstBounds image.Rectangle) { if p.w <= 0 || p.h <= 0 { return image.Rect(0, 0, 0, 0) } pt := anchorPt(srcBounds, p.w, p.h, p.anchor) r := image.Rect(0, 0, p.w, p.h).Add(pt) b := srcBounds.Intersect(r) return b.Sub(b.Min) }
// 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 }
// A portion of p specified by r that shares underlying pixels. func (p *Image64) SubImage(r image.Rectangle) image.Image { r = r.Intersect(p.Rect) if r.Empty() { return &Image64{} } i := (r.Min.Y-p.Rect.Min.Y)*p.Stride + (r.Min.X - p.Rect.Min.X) return &Image64{ Pix: p.Pix[i:], Stride: p.Stride, Rect: r, } }
// 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 }
func (p *RGB) SubImage(r image.Rectangle) image.Image { r = r.Intersect(p.Rect) if r.Empty() { return &RGB{} } i := p.PixOffset(r.Min.X, r.Min.Y) return &RGB{ Pix: p.Pix[i:], Stride: p.Stride, Rect: r, } }
// SubImage returns an image representing the portion of the image p visible // through r. The returned value shares pixels with the original image. func (p *ycc) SubImage(r image.Rectangle) image.Image { r = r.Intersect(p.Rect) if r.Empty() { return &ycc{SubsampleRatio: p.SubsampleRatio} } i := p.PixOffset(r.Min.X, r.Min.Y) return &ycc{ Pix: p.Pix[i:], Stride: p.Stride, Rect: r, SubsampleRatio: p.SubsampleRatio, } }
// SubFrame returns a Frame bounded by the rectangle r, sharing the data with // the receiver. func (f *Frame) SubFrame(r image.Rectangle) *Frame { r = r.Intersect(f.Bounds) if r.Empty() { return new(Frame) } return &Frame{ Data: f.Data[f.CellOffset(r.Min.X, r.Min.Y):], Bounds: r, Stride: f.Stride, } }
// stolen from inferno's devdraw func (b *Background) addFlush(r image.Rectangle, drawn bool) { r = r.Intersect(b.r) if b.flushrect.Empty() { if drawn { if b.imgflush != nil { b.imgflush(r) } } else { b.flushrect = r b.waste = 0 } return } // if the new segment doesn't overlap with the // old segment and it has already been drawn, // do nothing except possible call the external flush. overlaps := b.flushrect.Overlaps(r) if !overlaps && drawn { if b.imgflush != nil { b.imgflush(r) } return } nbb := b.flushrect.Union(r) ar := r.Dx() * r.Dy() abb := b.flushrect.Dx() * b.flushrect.Dy() anbb := nbb.Dx() * nbb.Dy() // Area of new waste is area of new bb minus area of old bb, // less the area of the new segment, which we assume is not waste. // This could be negative, but that's OK. b.waste += anbb - abb - ar if b.waste < 0 { b.waste = 0 } //absorb if: // total area is small // waste is less than half total area // rectangles touch if anbb <= 1024 || b.waste*2 < anbb || b.flushrect.Overlaps(r) { b.flushrect = nbb return } // emit current state if !b.flushrect.Empty() { b.flush() } b.flushrect = r }
func (c *Canvas) Draw(dst draw.Image, clipr image.Rectangle) { clipr = clipr.Intersect(c.r) c.img = dst if c.background != nil { draw.Draw(dst, clipr, c.background, clipr.Min, draw.Over) } clipr = clipr.Intersect(c.r) for e := c.items.Front(); e != nil; e = e.Next() { it := e.Value.(Item) if it.Bbox().Overlaps(clipr) { it.Draw(dst, clipr) } } }
func (i *imageSlice) DrawMask(r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op draw.Op) bool { //debugp("imageslice draw %v; sp %v\n", r, sp) dr := r.Intersect(i.r) if dr.Empty() { //debugp("-> clipped empty (r %v)\n", i.r) return true } delta := dr.Min.Sub(r.Min) // realignment because of clipping. sp = sp.Add(delta) mp = mp.Add(delta) dr = dr.Sub(i.p) //debugp("-> draw %v; sp %v\n", dr, sp) draw.DrawMask(i.img, dr, src, sp, mask, mp, op) return true }
// SubImage returns an image representing the portion of the image p visible // through r. The returned value shares pixels with the original image. func (p *RGBImage) SubImage(r image.Rectangle) image.Image { r = r.Intersect(p.XRect) // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside // either r1 or r2 if the intersection is empty. Without explicitly checking for // this, the Pix[i:] expression below can panic. if r.Empty() { return &RGBImage{} } i := p.PixOffset(r.Min.X, r.Min.Y) return &RGBImage{ XPix: p.XPix[i:], XStride: p.XStride, XRect: r, } }
// drawAbove draws only those items above it. // func (c *Canvas) drawAbove(it Item, clipr image.Rectangle) { clipr = clipr.Intersect(c.r) drawing := false for e := c.items.Front(); e != nil; e = e.Next() { if e.Value == nil { panic("nil value - can't happen?") continue } item := e.Value.(Item) if drawing && item.Bbox().Overlaps(clipr) { item.Draw(c.img, clipr) } else if item == it { drawing = true } } }
// SubImage provides a sub image of Image without copying image data. // N.B. The standard library defines a similar function, but returns an // image.Image. Here, we return xgraphics.Image so that we can use the extra // methods defined by xgraphics on it. // // This method is cheap to call. It should be used to update only specific // regions of an X pixmap to avoid sending an entire image to the X server when // only a piece of it is updated. // // Note that if the intersection of `r` and `im` is empty, `nil` is returned. func (im *Image) SubImage(r image.Rectangle) image.Image { r = r.Intersect(im.Rect) if r.Empty() { return nil } i := im.PixOffset(r.Min.X, r.Min.Y) return &Image{ X: im.X, Pixmap: im.Pixmap, Pix: im.Pix[i:], Stride: im.Stride, Rect: r, Subimg: true, } }
//Used to determine which edge the squares are touching each other at. //the boolean is which edge(x or Y) while travelling func boundary_move(f image.Rectangle, other image.Rectangle) (image.Point, bool) { point := f.Intersect(other).Size() if point.X >= point.Y { if f.Min.Y >= other.Min.Y { return image.Point{0, -point.Y}, false } else { return image.Point{0, point.Y}, false } } else { if f.Min.X >= other.Min.X { return image.Point{-point.X, 0}, true } else { return image.Point{point.X, 0}, true } } }
func newBitmapRenderer(img draw.Image, bound image.Rectangle, padding int) (eanRenderer, error) { bound = bound.Intersect(img.Bounds()) inner := image.Rectangle{ Min: bound.Min.Add(image.Pt(padding, padding)), Max: bound.Max.Sub(image.Pt(padding, padding)), }.Canon() converter, err := newEanCoordinateConverter(inner, measureBitmapFont) if err != nil { return nil, err } return &bitmapRenderer{ img: img, bound: bound, converter: converter, }, nil }
// SubImage returns an image representing the portion of the image p visible // through r. The returned value shares pixels with the original image. func (p *RGBM64) SubImage(r image.Rectangle) image.Image { r = r.Intersect(p.Rect) // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to // be inside either r1 or r2 if the intersection is empty. Without // explicitly checking for this, the Pix[i:] expression below can // panic. if r.Empty() { return &RGBM64{} } i := p.PixOffset(r.Min.X, r.Min.Y) return &RGBM64{ Pix: p.Pix[i:], Stride: p.Stride, Rect: r, } }
// SubImage creates a *FloatImg for a region within the original image // this image is backed by the data in the original image which thus can // be manipulated by manipulating the sub image func (p *FloatImg) SubImage(r image.Rectangle) *FloatImg { r = r.Intersect(p.Rect) // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside // either r1 or r2 if the intersection is empty. Without explicitly checking for // this, the Pix[i:] expression below can panic. if r.Empty() { return NewFloatImg(r, 0) } i := p.PixOffset(r.Min.X, r.Min.Y) return &FloatImg{ Pix: p.Pix[i:], Stride: p.Stride, Rect: r, Chancnt: p.Chancnt, ColorFunc: p.ColorFunc, ColorModelFunc: p.ColorModelFunc} }
// SubImage returns an image representing the portion of the image p visible through r. // The returned value shares pixels with the original image. func (p *Grid) SubGrid(r image.Rectangle) *Grid { r = r.Intersect(p.Rect) // If r1 and r2 are image.Rectangles, r1.Intersect(r2) is not guaranteed to be inside // either r1 or r2 if the intersection is empty. Without explicitly checking for // this, the Cells[i:] expression below can panic. if r.Empty() { return &Grid{} } i := p.CellsOffset(r.Min.X, r.Min.Y) return &Grid{ Tile: p.Tile[i:], Rot: p.Rot[i:], Stride: p.Stride, Rect: r, CellSize: p.CellSize, } }
func (w *windowImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectangle) { originalSRMin := sr.Min sr = sr.Intersect(src.Bounds()) if sr.Empty() { return } dp = dp.Add(sr.Min.Sub(originalSRMin)) // TODO: keep a texture around for this purpose? t, err := w.s.NewTexture(sr.Size()) if err != nil { panic(err) } t.Upload(image.Point{}, src, sr) w.Draw(f64.Aff3{ 1, 0, float64(dp.X), 0, 1, float64(dp.Y), }, t, t.Bounds(), draw.Src, nil) t.Release() }
func (t *textureImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectangle) { buf := src.(*bufferImpl) buf.preUpload() // src2dst is added to convert from the src coordinate space to the dst // coordinate space. It is subtracted to convert the other way. src2dst := dp.Sub(sr.Min) // Clip to the source. sr = sr.Intersect(buf.Bounds()) // Clip to the destination. dr := sr.Add(src2dst) dr = dr.Intersect(t.Bounds()) if dr.Empty() { return } // Bring dr.Min in dst-space back to src-space to get the pixel buffer offset. pix := buf.rgba.Pix[buf.rgba.PixOffset(dr.Min.X-src2dst.X, dr.Min.Y-src2dst.Y):] t.w.glctxMu.Lock() defer t.w.glctxMu.Unlock() t.w.glctx.BindTexture(gl.TEXTURE_2D, t.id) width := dr.Dx() if width*4 == buf.rgba.Stride { t.w.glctx.TexSubImage2D(gl.TEXTURE_2D, 0, dr.Min.X, dr.Min.Y, width, dr.Dy(), gl.RGBA, gl.UNSIGNED_BYTE, pix) return } // TODO: can we use GL_UNPACK_ROW_LENGTH with glPixelStorei for stride in // ES 3.0, instead of uploading the pixels row-by-row? for y, p := dr.Min.Y, 0; y < dr.Max.Y; y++ { t.w.glctx.TexSubImage2D(gl.TEXTURE_2D, 0, dr.Min.X, y, width, 1, gl.RGBA, gl.UNSIGNED_BYTE, pix[p:]) p += buf.rgba.Stride } }
func AverageGray16(rect image.Rectangle, img Channel) color.Gray16 { // Only use the area of the rectangle that overlaps with the image bounds. rect = rect.Intersect(img.Bounds()) // Determine whether or not there's any area over which to determine an // average. d := uint64(rect.Dx() * rect.Dy()) if d == 0 { return color.Gray16{} } var y uint64 AllPointsRP( func(pt image.Point) { y += uint64(img.Gray16At(pt.X, pt.Y).Y) }, )(rect) return color.Gray16{ Y: uint16(y / d), } }
// Draw performs error diffusion dithering. // // This method satisfies the draw.Drawer interface, implementing a dithering // filter attributed to Frankie Sierra. It uses the kernel // // X 2 // 1 1 func (d Sierra24A) Draw(dst draw.Image, r image.Rectangle, src image.Image, sp image.Point) { pd, ok := dst.(*image.Paletted) if !ok { // dither211 currently requires a palette draw.Draw(dst, r, src, sp, draw.Src) return } // intersect r with both dst and src bounds, fix up sp. ir := r.Intersect(pd.Bounds()). Intersect(src.Bounds().Add(r.Min.Sub(sp))) if ir.Empty() { return // no work to do. } sp = ir.Min.Sub(r.Min) // get subimage of src sr := ir.Add(sp) if !sr.Eq(src.Bounds()) { s, ok := src.(interface { SubImage(image.Rectangle) image.Image }) if !ok { // dither211 currently works on whole images draw.Draw(dst, r, src, sp, draw.Src) return } src = s.SubImage(sr) } // dither211 currently returns a new image, or nil if dithering not // possible. if s := dither211(src, pd.Palette); s != nil { src = s } // this avoids any problem of src dst overlap but it would usually // work to render directly into dst. todo. draw.Draw(dst, r, src, image.Point{}, draw.Src) }
// clip clips r against each image's bounds (after translating into the // destination image's co-ordinate space) and shifts the points sp and mp by // the same amount as the change in r.Min. func clip(dst Image, r *image.Rectangle, src image.Image, sp *image.Point, mask image.Image, mp *image.Point) { orig := r.Min *r = r.Intersect(dst.Bounds()) *r = r.Intersect(src.Bounds().Add(orig.Sub(*sp))) if mask != nil { *r = r.Intersect(mask.Bounds().Add(orig.Sub(*mp))) } dx := r.Min.X - orig.X dy := r.Min.Y - orig.Y if dx == 0 && dy == 0 { return } (*sp).X += dx (*sp).Y += dy (*mp).X += dx (*mp).Y += dy }
func (cp *ControlPoint) Draw(dst draw.Image, clipr image.Rectangle) { r := clipr.Intersect(cp.Bbox()) draw.Draw(dst, r, cp.col, image.ZP) }
// IOU computes intersection over union. func IOU(a, b image.Rectangle) float64 { inter := area(a.Intersect(b)) union := area(a) + area(b) - inter return float64(inter) / float64(union) }
// Cover computes the fraction of B which is covered by A. func Cover(a, b image.Rectangle) float64 { inter := area(a.Intersect(b)) return float64(inter) / float64(area(b)) }
// DrawMask aligns r.Min in dst with sp in src and mp in mask and then replaces the rectangle r // in dst with the result of a Porter-Duff composition. A nil mask is treated as opaque. func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) { sb := src.Bounds() dx, dy := sb.Max.X-sp.X, sb.Max.Y-sp.Y if mask != nil { mb := mask.Bounds() if dx > mb.Max.X-mp.X { dx = mb.Max.X - mp.X } if dy > mb.Max.Y-mp.Y { dy = mb.Max.Y - mp.Y } } if r.Dx() > dx { r.Max.X = r.Min.X + dx } if r.Dy() > dy { r.Max.Y = r.Min.Y + dy } r = r.Intersect(dst.Bounds()) if r.Empty() { return } // Fast paths for special cases. If none of them apply, then we fall back to a general but slow implementation. if dst0, ok := dst.(*image.RGBA); ok { if op == Over { if mask == nil { if src0, ok := src.(*image.ColorImage); ok { drawFillOver(dst0, r, src0) return } if src0, ok := src.(*image.RGBA); ok { drawCopyOver(dst0, r, src0, sp) return } } else if mask0, ok := mask.(*image.Alpha); ok { if src0, ok := src.(*image.ColorImage); ok { drawGlyphOver(dst0, r, src0, mask0, mp) return } } } else { if mask == nil { if src0, ok := src.(*image.ColorImage); ok { drawFillSrc(dst0, r, src0) return } if src0, ok := src.(*image.RGBA); ok { drawCopySrc(dst0, r, src0, sp) return } } } drawRGBA(dst0, r, src, sp, mask, mp, op) return } x0, x1, dx := r.Min.X, r.Max.X, 1 y0, y1, dy := r.Min.Y, r.Max.Y, 1 if image.Image(dst) == src && r.Overlaps(r.Add(sp.Sub(r.Min))) { // Rectangles overlap: process backward? if sp.Y < r.Min.Y || sp.Y == r.Min.Y && sp.X < r.Min.X { x0, x1, dx = x1-1, x0-1, -1 y0, y1, dy = y1-1, y0-1, -1 } } var out *image.RGBA64Color sy := sp.Y + y0 - r.Min.Y my := mp.Y + y0 - r.Min.Y for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy { sx := sp.X + x0 - r.Min.X mx := mp.X + x0 - r.Min.X for x := x0; x != x1; x, sx, mx = x+dx, sx+dx, mx+dx { ma := uint32(m) if mask != nil { _, _, _, ma = mask.At(mx, my).RGBA() } switch { case ma == 0: if op == Over { // No-op. } else { dst.Set(x, y, zeroColor) } case ma == m && op == Src: dst.Set(x, y, src.At(sx, sy)) default: sr, sg, sb, sa := src.At(sx, sy).RGBA() if out == nil { out = new(image.RGBA64Color) } if op == Over { dr, dg, db, da := dst.At(x, y).RGBA() a := m - (sa * ma / m) out.R = uint16((dr*a + sr*ma) / m) out.G = uint16((dg*a + sg*ma) / m) out.B = uint16((db*a + sb*ma) / m) out.A = uint16((da*a + sa*ma) / m) } else { out.R = uint16(sr * ma / m) out.G = uint16(sg * ma / m) out.B = uint16(sb * ma / m) out.A = uint16(sa * ma / m) } dst.Set(x, y, out) } } } }