// New allocates and initializes a new DockApp. NewDockApp does not initialize // the window contents and does not map the window to the display screen. The // window is mapped to the screen when the Main method is called on the // returned DockApp. func New(x *xgbutil.XUtil, rect image.Rectangle) (*DockApp, error) { win, err := xwindow.Generate(x) if err != nil { log.Fatalf("generate window: %v", err) } win.Create(x.RootWin(), 0, 0, rect.Size().X, rect.Size().Y, 0) // Set WM hints so that Openbox puts the window into the dock. hints := &icccm.Hints{ Flags: icccm.HintState | icccm.HintIconWindow, InitialState: icccm.StateWithdrawn, IconWindow: win.Id, WindowGroup: win.Id, } err = icccm.WmHintsSet(x, win.Id, hints) if err != nil { win.Destroy() return nil, fmt.Errorf("wm hints: %v", err) } img := xgraphics.New(x, rect) err = img.XSurfaceSet(win.Id) if err != nil { img.Destroy() win.Destroy() return nil, fmt.Errorf("xsurface set: %v", err) } app := &DockApp{ x: x, img: img, win: win, } return app, nil }
func imfilter(filter [][]float32, rect image.Rectangle, rgbFunc func(xpos, ypos int) (r0, g0, b0, a0 uint8), mergFunc func(a, b float32) float32) *image.RGBA { wg := sync.WaitGroup{} size := rect.Size() imgGrey := image.NewRGBA(rect) fX := len(filter) fY := len(filter[0]) xoffset := fX / 2 yoffset := fY / 2 threadCount := (fX + fY) / 2 sizeoffset := (size.X - fX) / threadCount timeStart := time.Now() wg.Add(threadCount) for i := 0; i < threadCount; i++ { go func(i int) { for x := xoffset + i*sizeoffset; x < xoffset+(i+1)*sizeoffset; x++ { for y := yoffset; y < size.Y-yoffset; y++ { newColor := imfilterMerg(filter, fX, fY, x, y, xoffset, yoffset, rgbFunc, mergFunc) imgGrey.SetRGBA(x, y, newColor) } } wg.Done() }(i) } wg.Wait() fmt.Println("Filt Time", time.Now().Sub(timeStart)) return imgGrey }
func (v *platformView) drawScene(r image.Rectangle) { //log.Printf("platformView.drawScene %v\n", r) x, y, w, h := r.Min.X, r.Min.Y, r.Size().X, r.Size().Y v.area.QueueDrawArea(v.parent.ScaleCoord(x, false), v.parent.ScaleCoord(y, false), v.parent.ScaleCoord(w, true)+1, v.parent.ScaleCoord(h, true)+1) return }
// // Private functions // func ContainerFit(outer, inner image.Rectangle) image.Rectangle { borderTop := image.Point{-18, -30} borderBottom := image.Point{18, 18} test := image.Rectangle{inner.Min.Add(borderTop), inner.Max.Add(borderBottom)} if outer.Size().X == 0 { return test } return outer.Union(test) }
func crop(src image.Image, r image.Rectangle) draw.Image { target := image.Rectangle{image.Point{0, 0}, r.Size()} cropped := image.NewRGBA(target) draw.Draw(cropped, target, src, r.Min, draw.Over) return cropped }
// 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 (w *windowImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectangle, sender screen.Sender) { // TODO: adjust if dp is outside dst bounds, or sr is outside src bounds. // TODO: keep a texture around for this purpose? t, err := w.s.NewTexture(sr.Size()) if err != nil { panic(err) } t.Upload(dp, src, sr, sender) w.Draw(f64.Aff3{1, 0, 0, 0, 1, 0}, t, sr, draw.Src, nil) t.Release() }
// LinearCollider is O(N) collision checker. Inefficient but simple and accurate. func LinearCollider(bounds image.Rectangle) Collider { size := bounds.Size() collider := &linearCollider{ bounds: Boundary{float32(bounds.Min.X), float32(bounds.Min.Y), float32(bounds.Max.X), float32(bounds.Max.Y)}, width: size.X, height: size.Y, } collider.Reset() return collider }
func GridCollider(bounds image.Rectangle) Collider { size := bounds.Size() grid := &gridCollider{ bounds: Boundary{float32(bounds.Min.X), float32(bounds.Min.Y), float32(bounds.Max.X), float32(bounds.Max.Y)}, width: size.X, height: size.Y, } grid.Reset() return grid }
func Rect(src image.Image, r image.Rectangle, at At) image.Image { dst := image.NewRGBA64(image.Rectangle{image.ZP, r.Size()}) b := dst.Bounds() for x := r.Min.X; x < r.Max.X; x++ { for y := r.Min.Y; y < r.Max.Y; y++ { p := image.Pt(x, y).Sub(r.Min).Add(b.Min) dst.Set(p.X, p.Y, at(src, image.Pt(x, y))) } } return dst }
func (w *windowImpl) vertexAff3(r image.Rectangle) f64.Aff3 { w.mu.Lock() sz := w.sz w.mu.Unlock() size := r.Size() tx, ty := float64(size.X), float64(size.Y) wx, wy := float64(sz.WidthPx), float64(sz.HeightPx) rx, ry := tx/wx, ty/wy // We are drawing the texture src onto the window's framebuffer. // The texture is (0,0)-(tx,ty). The window is (0,0)-(wx,wy), which // in vertex shader space is // // (-1, +1) (+1, +1) // (-1, -1) (+1, -1) // // A src2dst unit affine transform // // 1 0 0 // 0 1 0 // 0 0 1 // // should result in a (tx,ty) texture appearing in the upper-left // (tx, ty) pixels of the window. // // Setting w.s.texture.mvp to a unit affine transform results in // mapping the 2-unit square (-1,+1)-(+1,-1) given by quadXYCoords // in texture.go to the same coordinates in vertex shader space. // Thus, it results in the whole texture ((tx, ty) in texture // space) occupying the whole window ((wx, wy) in window space). // // A scaling affine transform // // rx 0 0 // 0 ry 0 // 0 0 1 // // results in a (tx, ty) texture occupying (tx, ty) pixels in the // center of the window. // // For upper-left alignment, we want to translate by // (-(1-rx), 1-ry), which is the affine transform // // 1 0 -1+rx // 0 1 +1-ry // 0 0 1 // // These multiply to give: return f64.Aff3{ rx, 0, -1 + rx, 0, ry, +1 - ry, } }
func NewCamera(rect image.Rectangle) Camera { sz := rect.Size() r := image.Rect(0, 0, sz.X, sz.Y) c := Camera{ Pos: image.ZP, SizeRect: r, Rect: r, } return c }
func imfilterMid(filter [][]float32, rect image.Rectangle, rgbFunc func(xpos, ypos int) (r0, g0, b0, a0 uint8)) *image.RGBA { size := rect.Size() imgGrey := image.NewRGBA(rect) fX := len(filter) fY := len(filter[0]) for x := fX / 2; x < size.X-fX/2; x++ { for y := fY / 2; y < size.Y-fY/2; y++ { _, _, _, a := rgbFunc(x, y) newColor := color.RGBA{R: 0, G: 0, B: 0, A: a} imgGrey.SetRGBA(x, y, newColor) } } return imgGrey }
//Returns the aspect ratio of a rectangle. func aspectRatio(r image.Rectangle) float64 { size := r.Size() var min, max int if size.X < size.Y { min = size.X max = size.Y } else { min = size.Y max = size.X } return float64(max) / float64(min) }
func cropImage(i image.Image, d image.Rectangle) (image.Image, error) { bounds := i.Bounds() if bounds.Min.X > d.Min.X || bounds.Min.Y > d.Min.Y || bounds.Max.X < d.Max.X || bounds.Max.Y < d.Max.Y { return nil, errors.New("Bounds invalid for crop") } dims := d.Size() outIm := image.NewRGBA(image.Rect(0, 0, dims.X, dims.Y)) for x := 0; x < dims.X; x++ { for y := 0; y < dims.Y; y++ { outIm.Set(x, y, i.At(d.Min.X+x, d.Min.Y+y)) } } return outIm, nil }
// 返回sub BinaryImage func (bi BinaryImage) SubBinaryImage(rect image.Rectangle) BinaryImage { binimg := BinaryImage(bi) h, w := rect.Size().Y+1, rect.Size().X+1 // init newbi := make([][]int, h, h) for y := 0; y < h; y++ { newbi[y] = make([]int, w, w) } // copy for y := 0; y < h; y++ { copy(newbi[y], binimg[rect.Min.Y+y][rect.Min.X:rect.Max.X+1]) } return BinaryImage(newbi) }
func TestHOG_boundary(t *testing.T) { const ( sbin = 4 frac = 3 fname = "000084.jpg" ) // Load image. file, err := os.Open(fname) if err != nil { t.Fatal(err) } im, _, err := image.Decode(file) // Take top-left part which is divisible by sbin and frac. im = ensureDivis(im, sbin*frac) // Make a rectangle of the top-left part of the image. // Not the most top-left window but the second-most. size := im.Bounds().Size() rect := image.Rectangle{size.Div(frac), size.Div(frac).Mul(2)} // Sub-sample image subim := image.NewRGBA(image.Rectangle{image.ZP, rect.Size()}) draw.Draw(subim, subim.Bounds(), im, rect.Min, draw.Src) // Convert to real values. f := HOG(rimg64.FromColor(im), FGMRConfig(sbin)) g := HOG(rimg64.FromColor(subim), FGMRConfig(sbin)) // Take rectangle in f of same size as g. min := rect.Min.Div(sbin) subf := f.SubImage(image.Rectangle{min, min.Add(g.Size())}) const prec = 1e-9 // Skip last element because of a slight difference. // (Not using cell outside image.) for x := 0; x < g.Width; x++ { for y := 0; y < g.Height; y++ { for d := 0; d < g.Channels; d++ { want := g.At(x, y, d) got := subf.At(x, y, d) if math.Abs(want-got) > prec { t.Errorf("wrong value: at %d, %d, %d: want %g, got %g", x, y, d, want, got) } } } } }
func (w *windowImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectangle, sender screen.Sender) { // TODO: adjust if dp is outside dst bounds, or sr is outside src bounds. // TODO: keep a texture around for this purpose? t, err := w.s.NewTexture(sr.Size()) if err != nil { panic(err) } t.(*textureImpl).upload(dp, src, sr) if sender != nil { sender.Send(screen.UploadedEvent{Buffer: src, Uploader: w}) } w.Draw(f64.Aff3{ 1, 0, float64(dp.X), 0, 1, float64(dp.Y), }, t, sr, draw.Src, nil) t.Release() }
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 CountColor(reader io.Reader) int { var count = map[string]int{} decodedPng, error := png.Decode(reader) if error == nil { var rect image.Rectangle = decodedPng.Bounds() for i := 0; i < rect.Size().X; i++ { for j := 0; j < rect.Size().Y; j++ { var pixel image.Color = decodedPng.At(i, j) var r, g, b, _ uint32 = pixel.RGBA() var key uint = (uint)((r << 16) + (g << 8) + (b)) if _, ok := count[strconv.Uitoa(key)]; ok { count[strconv.Uitoa(key)]++ } else { count[strconv.Uitoa(key)] = 1 } } } } return len(count) }
func imenhance(enhanceDegress float32, enhanceOffset float32, enhanceChannel [3]bool, withFunc bool, rect image.Rectangle, rgbFunc func(xpos, ypos int) (r0, g0, b0, a0 uint8)) *image.RGBA { timeOld := time.Now() wg := sync.WaitGroup{} newImage := image.NewRGBA(rect) size := rect.Size() fX := size.X fY := size.Y threadCount := 8 sizeoffset := fX / threadCount wg.Add(threadCount) for i := 0; i < threadCount; i++ { go func(i int) { for x := sizeoffset * i; x < sizeoffset*(i+1); x++ { for y := 0; y < fY; y++ { r, g, b, a := rgbFunc(x, y) if !withFunc { if enhanceChannel[0] { r = oneColorCorrect(float32(r)*enhanceDegress + enhanceOffset) } if enhanceChannel[1] { g = oneColorCorrect(float32(g)*enhanceDegress + enhanceOffset) } if enhanceChannel[2] { b = oneColorCorrect(float32(b)*enhanceDegress + enhanceOffset) } } newColor := color.RGBA{R: r, G: g, B: b, A: a} newImage.SetRGBA(x, y, newColor) } } wg.Done() }(i) } wg.Wait() fmt.Println("Enhance Time:", time.Now().Sub(timeOld)) return newImage }
func Rotate(s image.Image, deg int) (image.Image, error) { src := toRGBA(s) var d image.Rectangle switch deg { default: return nil, errors.New("Unsupported angle (90, 180, 270).") case 90, 270: d = image.Rect(0, 0, src.Bounds().Size().Y, src.Bounds().Size().X) case 180: d = image.Rect(0, 0, src.Bounds().Size().X, src.Bounds().Size().Y) } rv := image.NewRGBA(d) b := src.Bounds() /* switch outside of loops for performance reasons */ switch deg { case 270: for y := 0; y < b.Size().Y; y++ { for x := 0; x < b.Size().X; x++ { s := x*rv.Stride + 4*(d.Size().X-y-1) p := y*src.Stride + x*4 copy(rv.Pix[s:s+4], src.Pix[p:p+4]) } } case 180: for y := 0; y < b.Size().Y; y++ { for x := 0; x < b.Size().X; x++ { s := (d.Size().Y-y-1)*rv.Stride + 4*d.Size().X - (x+1)*4 p := y*src.Stride + x*4 copy(rv.Pix[s:s+4], src.Pix[p:p+4]) } } case 90: for y := 0; y < b.Size().Y; y++ { for x := 0; x < b.Size().X; x++ { s := (d.Size().Y-x-1)*rv.Stride + y*4 p := y*src.Stride + x*4 copy(rv.Pix[s:s+4], src.Pix[p:p+4]) } } } return rv, nil }
func nonMaxSupp(scoreImgs []cv.RealImage, scales imgpyr.GeoSeq, size image.Point, maxRelOverlap float64) []PyrPos { // Put every window into a list. all := allDetections(scoreImgs, scales) // Sort this list by score. sort.Sort(sort.Reverse(byScore{scoreImgs, all})) // List of remaining detections. remain := list.New() // Look-up of list elements by position. elems := make([][][]*list.Element, len(scoreImgs)) for k, img := range scoreImgs { elems[k] = make([][]*list.Element, img.Width) for x := 0; x < img.Width; x++ { elems[k][x] = make([]*list.Element, img.Height) } } // Populate both. for _, det := range all { elems[det.Level][det.Pos.X][det.Pos.Y] = remain.PushBack(det) } // Select best detection, remove those which overlap with it. var dets []PyrPos for remain.Len() > 0 { // Remove from remaining and add to detections. e := remain.Front() det, ok := e.Value.(PyrPos) if !ok { panic("unexpected type in list") } remain.Remove(e) dets = append(dets, det) // Get bounds of detection in its scale. r := image.Rectangle{det.Pos, det.Pos.Add(size)} // Scale back into frame of original (feature) image. r = scaleRect(1/scales.At(det.Level), r) for k, img := range scoreImgs { // Scale top-left corner into current level. p := scalePoint(scales.At(k), r.Min) // Calculate bounds on range (exclusive). a := p.Sub(size) b := p.Add(size) ax, bx := max(a.X+1, 0), min(b.X, img.Width) ay, by := max(a.Y+1, 0), min(b.Y, img.Height) for x := ax; x < bx; x++ { for y := ay; y < by; y++ { if elems[k][x][y] == nil { // Element already removed. continue } // Candidate rectangle in its scale. p := image.Pt(x, y) q := image.Rectangle{p, p.Add(size)} // Scale back into frame of original (feature) image. q = scaleRect(1/scales.At(k), q) // Compute overlap. overlap := q.Intersect(r) relR := float64(area(overlap.Size())) / float64(area(r.Size())) relQ := float64(area(overlap.Size())) / float64(area(q.Size())) if relR <= maxRelOverlap && relQ <= maxRelOverlap { // Maximum relative overlap is not exceeded. continue } // Remove from the list. remain.Remove(elems[k][x][y]) elems[k][x][y] = nil } } } } return dets }
func RotateRect(r image.Rectangle) image.Rectangle { s := r.Size() return image.Rectangle{r.Min, image.Point{s.Y, s.X}} }
// Returns a blocking channel of Step. // // Once Step.Done() is true, the calculation has finished and the channel is closed. // You can use this to abort calculating larger image resamples or to show percentage // done indicators. // // The filter F is the resampling function used. See the provided samplers for examples. // Additionally X- and YWrap functions are used to define how image boundaries are // treated. See the provided Clamp function for examples. func ResizeToChannelWithFilter(dst image.Image, dstRect image.Rectangle, src image.Image, srcRect image.Rectangle, F Filter, XWrap, YWrap WrapFunc) (<-chan Step, chan<- bool, error) { if src == nil { return nil, nil, ErrSourceImageIsInvalid } if F.Apply == nil || F.Support <= 0 { return nil, nil, ErrMissingFilter } if XWrap == nil || YWrap == nil { return nil, nil, ErrMissingWrapFunc } var dstBounds image.Rectangle if dst == nil { dstBounds.Max = srcRect.Size() } else { dstBounds = dst.Bounds() } newSize := dstRect.Size() if newSize.X < 0 || newSize.Y < 0 { return nil, nil, ErrTargetSizeIsInvalid } resultChannel := make(chan Step) doneChannel := make(chan bool) // Code for the KeepAlive closure used to // break the calulculation into blocks. // Sends on the channel only happen every opIncrement // operations. For now this is hardcoded to a reasonable value. var opCount, totalOps, lastOps, opIncrement int opIncrement = 200 * 1000 keepAlive := func(ops int) bool { opCount += ops if opCount >= lastOps { select { case <-doneChannel: return false case resultChannel <- step{image: nil, total: totalOps, done: opCount}: lastOps += opIncrement return true } } return true } sendImage := func(img image.Image) { select { case resultChannel <- step{image: img, total: totalOps, done: opCount}: case <-doneChannel: } } if newSize.X == 0 || newSize.Y == 0 { go sendImage(image.NewNRGBA64(image.Rect(0, 0, newSize.X, newSize.Y))) return resultChannel, doneChannel, nil } go func() { // Send first empty step before we do any real work. keepAlive(0) xFilter, xOps := makeDiscreteFilter(F, XWrap, dstRect.Dx(), srcRect.Dx()) yFilter, yOps := makeDiscreteFilter(F, YWrap, dstRect.Dy(), srcRect.Dy()) if dst == nil { dst = image.NewNRGBA64(dstRect) } dst := dst.(*image.NRGBA64) xy_ops := yOps*srcRect.Dx() + xOps*dstRect.Dy() yx_ops := xOps*srcRect.Dy() + yOps*dstRect.Dx() if xy_ops < yx_ops { totalOps = xy_ops tmpBounds := image.Rect(0, 0, srcRect.Dx(), dstRect.Dy()) var tmp *image.NRGBA64 if tmpBounds.Dx() < dstRect.Dx() { tmp = image.NewNRGBA64(tmpBounds) } else { tmp = dst } resampleAxisNRGBA64(yAxis, keepAlive, tmp, tmpBounds, src, srcRect, yFilter) resampleAxisNRGBA64(xAxis, keepAlive, dst, dstRect, tmp, tmpBounds, xFilter) } else { totalOps = yx_ops tmpBounds := image.Rect(0, 0, dstRect.Dx(), srcRect.Dy()) var tmp *image.NRGBA64 if tmpBounds.Dy() < dstRect.Dy() { tmp = image.NewNRGBA64(tmpBounds) } else { tmp = dst } resampleAxisNRGBA64(xAxis, keepAlive, tmp, tmpBounds, src, srcRect, xFilter) resampleAxisNRGBA64(yAxis, keepAlive, dst, dstRect, tmp, tmpBounds, yFilter) } //log.Printf("Resize %v -> %v %d kOps (xy =%d,yx =%d)",src.Bounds().Max, newSize,opCount/1000, xy_ops/1000, yx_ops/1000) sendImage(dst) }() return resultChannel, doneChannel, nil }
// CropTo returns a copy of this image that has been cropped // to the given dimensions func (self Image) CropTo(bounds image.Rectangle) Image { dst := image.NewRGBA(bounds.Sub(bounds.Min)) r := image.Rectangle{dst.Rect.Min, dst.Rect.Min.Add(bounds.Size())} draw.Draw(dst, r, self.Img, bounds.Min, draw.Src) return Image{Img: dst, Format: self.Format} }
func (v *mappingView) drawScene(r image.Rectangle) { x, y, w, h := r.Min.X, r.Min.Y, r.Size().X, r.Size().Y v.area.QueueDrawArea(v.parent.ScaleCoord(x, false), v.parent.ScaleCoord(y, false), v.parent.ScaleCoord(w, true)+1, v.parent.ScaleCoord(h, true)+1) return }
// CenterOrigin returns the screen coordinates where a game tile that shows up // at the center of the rectangle should be drawn. func CenterOrigin(screenArea image.Rectangle) (screenPos image.Point) { return screenArea.Min.Add(screenArea.Size().Div(2)).Sub(image.Pt(TileW/2, TileH/2)) }