func checkPsnrs(t *testing.T, ref, img image.Image, sub image.Rectangle, min []float64) { var a, b image.Image a, b = ref, img if !sub.Empty() { switch a.(type) { case *image.RGBA: a = a.(*image.RGBA).SubImage(sub) b = b.(*image.RGBA).SubImage(sub) case *image.NRGBA: a = a.(*image.NRGBA).SubImage(sub) b = b.(*image.NRGBA).SubImage(sub) case *image.YCbCr: a = a.(*image.YCbCr).SubImage(sub) b = b.(*image.YCbCr).SubImage(sub) case *image.Gray: a = a.(*image.Gray).SubImage(sub) b = b.(*image.Gray).SubImage(sub) } } psnrs, err := Psnr(a, b) expect(t, err, nil) for i, v := range psnrs { if v < min[i] { t.Fatalf("invalid psnr %v < %v\n", v, min[i]) } } }
func (a *area) Repaint(r image.Rectangle) { r = image.Rect(0, 0, a.width, a.height).Intersect(r) if r.Empty() { return } C.gtk_widget_queue_draw_area(a.widget, C.gint(r.Min.X), C.gint(r.Min.Y), C.gint(r.Dx()), C.gint(r.Dy())) }
// 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 (floydSteinberg) Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point) { clip(dst, &r, src, &sp, nil, nil) if r.Empty() { return } drawPaletted(dst, r, src, sp, true) }
//MapImage returns an image surface that is the most efficient mechanism //for modifying the backing store of this surface. // //If r is Empty, the entire surface is mapped, otherwise, just the region //described by r is mapped. // //Note that r is an image.Rectangle and not a cairo.Rectangle. // //It is the callers responsibility to all Close on the returned surface //in order to upload the content of the mapped image to this surface and //destroys the image surface. // //The returned surface is an ImageSurface with a special Close method. // //Warning // //Using this surface as a target or source while mapped is undefined. // //The result of mapping a surface multiple times is undefined. // //Changing the device transform of either surface before the image surface //is unmapped is undefined. // //Originally cairo_surface_map_to_image. func (e *XtensionSurface) MapImage(r image.Rectangle) (MappedImageSurface, error) { var rect C.cairo_rectangle_int_t rect.x, rect.y = C.int(r.Min.X), C.int(r.Min.Y) rect.width, rect.height = C.int(r.Dx()), C.int(r.Dy()) rp := &rect if r.Empty() { //use entire image rp = nil } return newMappedImageSurface(C.cairo_surface_map_to_image(e.s, rp), e.s) }
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, } }
// FillRect sets each Cell in the Frame within the rectangle r to Cell c. func (f *Frame) FillRect(r image.Rectangle, c Cell) { r = f.Bounds.Intersect(r) if r.Empty() { return } for y := r.Min.Y; y < r.Max.Y; y++ { for x := r.Min.X; x < r.Max.X; x++ { f.Set(x, y, c) } } }
// 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, } }
// 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, } }
func (a *area) Repaint(r image.Rectangle) { var s C.struct_xrect r = image.Rect(0, 0, a.width, a.height).Intersect(r) if r.Empty() { return } s.x = C.intptr_t(r.Min.X) s.y = C.intptr_t(r.Min.Y) s.width = C.intptr_t(r.Dx()) s.height = C.intptr_t(r.Dy()) C.areaRepaint(a.id, s) }
// 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, } }
// 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, } }
// 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, } }
func (a *area) Repaint(r image.Rectangle) { var hscroll, vscroll C.int var rect C.RECT C.SendMessageW(a.hwnd, C.msgAreaGetScroll, C.WPARAM(uintptr(unsafe.Pointer(&hscroll))), C.LPARAM(uintptr(unsafe.Pointer(&vscroll)))) r = r.Add(image.Pt(int(hscroll), int(vscroll))) // adjust by scroll position r = image.Rect(0, 0, a.width, a.height).Intersect(r) if r.Empty() { return } rect.left = C.LONG(r.Min.X) rect.top = C.LONG(r.Min.Y) rect.right = C.LONG(r.Max.X) rect.bottom = C.LONG(r.Max.Y) C.SendMessageW(a.hwnd, C.msgAreaRepaint, 0, C.LPARAM(uintptr(unsafe.Pointer(&rect)))) }
// 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, } }
// 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 (hw *HostWindow) Init(bounds image.Rectangle) { host_window_class := fmt.Sprintf("www.ustc.edu.cn/gwk/host_window/%p", hw) var wc WNDCLASSEX wc.Size = uint32(unsafe.Sizeof(wc)) wc.Style = CS_HREDRAW | CS_VREDRAW wc.FnWndProc = syscall.NewCallback(host_window_wnd_proc) wc.ClassExtra = 0 wc.WindowExtra = 0 wc.HInstance = NULL wc.HIcon, _ = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION)) wc.HCursor, _ = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)) wc.HbrBackground = COLOR_WINDOWFRAME wc.MenuName = nil wc.ClassName = syscall.StringToUTF16Ptr(host_window_class) if _, err := RegisterClassEx(&wc); err != nil { log.Panicf("RegisterClassEx Failed %v", err) } var x, y, width, height int if bounds.Empty() { x, y = CW_USEDEFAULT, CW_USEDEFAULT width, height = CW_USEDEFAULT, CW_USEDEFAULT } else { x, y = bounds.Min.X, bounds.Min.Y width, height = bounds.Dx(), bounds.Dy() } hwnd, err := CreateWindowEx(WS_OVERLAPPED, syscall.StringToUTF16Ptr(host_window_class), nil, WS_OVERLAPPEDWINDOW, x, y, width, height, NULL, NULL, 0, uintptr(unsafe.Pointer(hw))) if err != nil { log.Panicf("CreateWindowEx Failed: %v", err) } hw.hwnd = hwnd hw.bounds = bounds }
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 (r *Renderer) stateScissor(rect image.Rectangle) { // Only if the (final) scissor rectangle has changed do we need to make the // OpenGL call. bounds := r.Bounds() // If the rectangle is empty use the entire area. if rect.Empty() { rect = bounds } else { // Intersect the rectangle with the renderer's bounds. rect = bounds.Intersect(rect) } if r.last.scissor != rect { // Store the new scissor rectangle. r.last.scissor = rect x, y, width, height := convertRect(rect, bounds) r.render.Scissor(x, y, width, height) } }
// Parallel dispatches tasks concurrently for a Rectangle. func Parallel(r image.Rectangle, f func(r image.Rectangle)) { p := runtime.GOMAXPROCS(0) wg := new(sync.WaitGroup) h := r.Dy() for y := 0; y < p; y++ { r := image.Rect( r.Min.X, r.Min.Y+(h*y/p), r.Max.X, r.Min.Y+(h*(y+1)/p), ) if !r.Empty() { wg.Add(1) go func(r image.Rectangle) { f(r) wg.Done() }(r) } } wg.Wait() }
func (q *MedianCutQuantizer) Quantize(dst *image.Paletted, r image.Rectangle, src image.Image, sp image.Point) { clip(dst, &r, src, &sp) if r.Empty() { return } points := make([]point, r.Dx()*r.Dy()) colorSet := make(map[uint32]color.Color, q.NumColor) i := 0 for y := r.Min.Y; y < r.Max.Y; y++ { for x := r.Min.X; x < r.Max.X; x++ { c := src.At(x, y) r, g, b, _ := c.RGBA() colorSet[(r>>8)<<16|(g>>8)<<8|b>>8] = c points[i][0] = int(r) points[i][1] = int(g) points[i][2] = int(b) i++ } } if len(colorSet) <= q.NumColor { // No need to quantize since the total number of colors // fits within the palette. dst.Palette = make(color.Palette, len(colorSet)) i := 0 for _, c := range colorSet { dst.Palette[i] = c i++ } } else { dst.Palette = q.medianCut(points) } for y := 0; y < r.Dy(); y++ { for x := 0; x < r.Dx(); x++ { // TODO: this should be done more efficiently. dst.Set(sp.X+x, sp.Y+y, src.At(r.Min.X+x, r.Min.Y+y)) } } }
func thumbnailRez(imgSrc image.Image, size image.Point, trimmedBounds image.Rectangle) image.Image { img := ConvertToRGBAIfNecessary(imgSrc) if !trimmedBounds.Empty() && !trimmedBounds.Eq(img.Bounds()) { img = img.SubImage(trimmedBounds).(*image.RGBA) } b := img.Bounds() imgSize := image.Point{b.Dx(), b.Dy()} thumbSize, downscaling := SizePreservingAspect(imgSize, size) resizedImg := img if downscaling { resizedImg = CreateRGBAImageOfSize(thumbSize) convert(resizedImg, img, false, rez.NewBicubicFilter()) } dstImg := CreateRGBAImageOfSize(size) // paint the background //draw.Draw(dstImg, dstImg.Bounds(), &image.Uniform{bgColor}, image.ZP, draw.Src) drawCentered(dstImg, resizedImg) return dstImg }
func thumbnailNfnt(imgSrc image.Image, size image.Point, trimmedBounds image.Rectangle) image.Image { img := ConvertToRGBAIfNecessary(imgSrc) if !trimmedBounds.Empty() && !trimmedBounds.Eq(img.Bounds()) { img = img.SubImage(trimmedBounds).(*image.RGBA) } b := img.Bounds() imgSize := image.Point{b.Dx(), b.Dy()} thumbSize, downscaling := SizePreservingAspect(imgSize, size) var resizedImg image.Image = img if downscaling { // resize.Resize returns *image.RGBA64 resizedImg = resize.Resize(uint(thumbSize.X), uint(thumbSize.Y), img, resize.Bilinear) } dstImg := CreateRGBAImageOfSize(size) // paint the background //draw.Draw(dstImg, dstImg.Bounds(), &image.Uniform{bgColor}, image.ZP, draw.Src) drawCentered(dstImg, resizedImg) return dstImg }
// 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) { clip(dst, &r, src, &sp, mask, &mp) if r.Empty() { return } // Fast paths for special cases. If none of them apply, then we fall back to a general but slow implementation. switch dst0 := dst.(type) { case *image.RGBA: if op == Over { if mask == nil { switch src0 := src.(type) { case *image.Uniform: drawFillOver(dst0, r, src0) return case *image.RGBA: drawCopyOver(dst0, r, src0, sp) return case *image.NRGBA: drawNRGBAOver(dst0, r, src0, sp) return case *image.YCbCr: if drawYCbCr(dst0, r, src0, sp) { return } } } else if mask0, ok := mask.(*image.Alpha); ok { switch src0 := src.(type) { case *image.Uniform: drawGlyphOver(dst0, r, src0, mask0, mp) return } } } else { if mask == nil { switch src0 := src.(type) { case *image.Uniform: drawFillSrc(dst0, r, src0) return case *image.RGBA: drawCopySrc(dst0, r, src0, sp) return case *image.NRGBA: drawNRGBASrc(dst0, r, src0, sp) return case *image.YCbCr: if drawYCbCr(dst0, r, src0, sp) { return } } } } drawRGBA(dst0, r, src, sp, mask, mp, op) return case *image.Paletted: if op == Src && mask == nil && !processBackward(dst, r, src, sp) { drawPaletted(dst0, r, src, sp, false) } } x0, x1, dx := r.Min.X, r.Max.X, 1 y0, y1, dy := r.Min.Y, r.Max.Y, 1 if processBackward(dst, r, src, sp) { x0, x1, dx = x1-1, x0-1, -1 y0, y1, dy = y1-1, y0-1, -1 } var out color.RGBA64 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, color.Transparent) } case ma == m && op == Src: dst.Set(x, y, src.At(sx, sy)) default: sr, sg, sb, sa := src.At(sx, sy).RGBA() 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) } // The third argument is &out instead of out (and out is // declared outside of the inner loop) to avoid the implicit // conversion to color.Color here allocating memory in the // inner loop if sizeof(color.RGBA64) > sizeof(uintptr). dst.Set(x, y, &out) } } } }
// 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) { clip(dst, &r, src, &sp, mask, &mp) 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 { switch src0 := src.(type) { case *image.ColorImage: drawFillOver(dst0, r, src0) return case *image.RGBA: drawCopyOver(dst0, r, src0, sp) return case *image.NRGBA: drawNRGBAOver(dst0, r, src0, sp) return case *ycbcr.YCbCr: drawYCbCr(dst0, r, src0, sp) return } } else if mask0, ok := mask.(*image.Alpha); ok { switch src0 := src.(type) { case *image.ColorImage: drawGlyphOver(dst0, r, src0, mask0, mp) return } } } else { if mask == nil { switch src0 := src.(type) { case *image.ColorImage: drawFillSrc(dst0, r, src0) return case *image.RGBA: drawCopySrc(dst0, r, src0, sp) return case *image.NRGBA: drawNRGBASrc(dst0, r, src0, sp) return case *ycbcr.YCbCr: drawYCbCr(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) } } } }
func drawMask(d drawer, dst draw.Image, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, protectAlpha bool) { clip(dst, &r, src, &sp, mask, &mp) if r.Empty() { return } switch dst0 := dst.(type) { case *image.RGBA: if mask == nil { switch src0 := src.(type) { case *image.RGBA: d.drawRGBAToRGBAUniform(dst0, r, src0, sp, nil, protectAlpha) return case *image.NRGBA: d.drawNRGBAToRGBAUniform(dst0, r, src0, sp, nil, protectAlpha) return } } else { switch mask0 := mask.(type) { case *image.Uniform: switch src0 := src.(type) { case *image.RGBA: d.drawRGBAToRGBAUniform(dst0, r, src0, sp, mask0, protectAlpha) return case *image.NRGBA: d.drawNRGBAToRGBAUniform(dst0, r, src0, sp, mask0, protectAlpha) return } } } case *image.NRGBA: if mask == nil { switch src0 := src.(type) { case *image.RGBA: d.drawRGBAToNRGBAUniform(dst0, r, src0, sp, nil, protectAlpha) return case *image.NRGBA: d.drawNRGBAToNRGBAUniform(dst0, r, src0, sp, nil, protectAlpha) return } } else { switch mask0 := mask.(type) { case *image.Uniform: switch src0 := src.(type) { case *image.RGBA: d.drawRGBAToNRGBAUniform(dst0, r, src0, sp, mask0, protectAlpha) return case *image.NRGBA: d.drawNRGBAToNRGBAUniform(dst0, r, src0, sp, mask0, protectAlpha) return } } } } if ad, ok := d.(alphaDrawer); ok { switch dst0 := dst.(type) { case *image.RGBA: if mask == nil { switch src0 := src.(type) { case *image.Alpha: ad.drawAlphaToRGBAUniform(dst0, r, src0, sp, nil, protectAlpha) return } } else { switch mask0 := mask.(type) { case *image.Uniform: switch src0 := src.(type) { case *image.Alpha: ad.drawAlphaToRGBAUniform(dst0, r, src0, sp, mask0, protectAlpha) return } } } case *image.NRGBA: if mask == nil { switch src0 := src.(type) { case *image.Alpha: ad.drawAlphaToNRGBAUniform(dst0, r, src0, sp, nil, protectAlpha) return } } else { switch mask0 := mask.(type) { case *image.Uniform: switch src0 := src.(type) { case *image.Alpha: ad.drawAlphaToNRGBAUniform(dst0, r, src0, sp, mask0, protectAlpha) return } } } } } d.drawFallback(dst, r, src, sp, mask, mp, protectAlpha) }
func (m *markedImage) Transform(crop image.Rectangle, width, height uint, dontenlarge bool, format string, resample resize.InterpolationFunction) (Image, error) { novaFoto, err := m.Copy() if err != nil { return nil, e.Forward(err) } img, err := novaFoto.Image() if err != nil { return nil, e.Forward(err) } if width > math.MaxInt32 { return nil, e.New("width is big") } if height > math.MaxInt32 { return nil, e.New("height is big") } bounds, err := m.Bounds() if err != nil { return nil, e.Forward(err) } w := bounds.Dx() h := bounds.Dy() f, err := m.Format() if err != nil { return nil, e.Forward(err) } if crop.Empty() && ((width == 0 && height == 0) || (int(width) == w && int(height) == h)) && (format == "" || format == f) { return novaFoto, nil } if !crop.Empty() { sub, ok := img.(SubImager) if !ok { return nil, e.New("this image type don't support cropping") } img = sub.SubImage(crop) } imgResized := img if !(width == 0 && height == 0) { rect := img.Bounds() w := uint(rect.Max.X - rect.Min.X) h := uint(rect.Max.Y - rect.Min.Y) imgRatio := img if width > 0 && height > 0 { ratio := round.RoundDec32(float32(w)/float32(h), 1) newRatio := round.RoundDec32(float32(width)/float32(height), 1) if ratio != newRatio { //TODO: se imagem tem largura menor que 10px não vai funcionar imgRatio, err = cutter.Crop(img, cutter.Config{ Width: int(newRatio * 10.0), Height: 10, Mode: cutter.Centered, Options: cutter.Ratio, }) if err != nil { return nil, e.Push(err, "can't crop the image") } rect = imgRatio.Bounds() w = uint(rect.Max.X - rect.Min.X) h = uint(rect.Max.Y - rect.Min.Y) } } imgResized = imgRatio if (width >= w || height >= h) && !dontenlarge { imgResized = resize.Resize(width, height, imgRatio, resample) } else if width < w && height < h { imgResized = resize.Resize(width, height, imgRatio, resample) } } // rect := imgResized.Bounds() // novaFoto.Width_ = rect.Max.X - rect.Min.X // novaFoto.Height_ = rect.Max.Y - rect.Min.Y b := make([]byte, 0, 1024*1024*5) buf := bytes.NewBuffer(b) // if format == "" { // format = novaFoto.Mime_ // } switch format { // case "image/bmp", "image/x-windows-bmp": // err := bmp.Encode(buf, imgResized) // if err != nil { // return nil, e.Forward(err) // } // novaFoto.Format_ = "bmp" // case "image/gif": // opt := &gif.Options{ // NumColors: 256, // } // err := gif.Encode(buf, imgResized, opt) // if err != nil { // return nil, e.Forward(err) // } // novaFoto.Format_ = "gif" case "image/jpeg": opt := &jpeg.Options{ Quality: Quality, } err := jpeg.Encode(buf, imgResized, opt) if err != nil { return nil, e.Forward(err) } //novaFoto.Format_ = "jpeg" // case "image/png": // err := png.Encode(buf, imgResized) // if err != nil { // return nil, e.Forward(err) // } // novaFoto.Format_ = "png" // case "image/tiff", "image/x-tiff": // opt := &tiff.Options{ // Compression: tiff.Deflate, // Predictor: true, // } // err := tiff.Encode(buf, imgResized, opt) // if err != nil { // return nil, e.Forward(err) // } // novaFoto.Format_ = "tiff" default: return nil, e.New("image format isn't supported") } // novaFoto.Mime_ = format // novaFoto.FileSize_ = int64(buf.Len()) // novaFoto.Data = buf.Bytes() return novaFoto, nil }
func DrawMask(dst draw.Image, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op draw.Op) { clip(dst, &r, src, &sp, mask, &mp) if r.Empty() { return } if dst0, ok := dst.(*BGRA); ok { if op == draw.Over { if mask == nil { switch src0 := src.(type) { case *image.Uniform: drawFillOver(dst0, r, src0) return case *image.RGBA: drawRGBAOver(dst0, r, src0, sp) return case *BGRA: drawCopyOver(dst0, r, src0, sp) return } } else if mask0, ok := mask.(*image.Alpha); ok { switch src0 := src.(type) { case *image.Uniform: drawGlyphOver(dst0, r, src0, mask0, mp) return } } } else { if mask == nil { switch src0 := src.(type) { case *image.Uniform: drawFillSrc(dst0, r, src0) return case *image.RGBA: drawRGBASrc(dst0, r, src0, sp) return case *BGRA: drawCopySrc(dst0, r, src0, sp) return } } } drawBGRA(dst0, r, src, sp, mask, mp, op) return } else if dst0, ok := dst.(*image.RGBA); ok { if src0, ok := dst.(*BGRA); ok { if op == draw.Over { if mask == nil { drawRGBADstOver(dst0, r, src0, sp) return } } else { if mask == nil { drawRGBADst(dst0, r, src0, sp) return } } } } draw.DrawMask(dst, r, src, sp, mask, mp, op) }
func Paint(w wde.Window, rect image.Rectangle) { xOffset, yOffset := GetTopLeft() center := layout.Coord{ViewportWidth/2 - xOffset, ViewportHeight/2 - yOffset} if center != oldCenter || layout.Version() != oldVersion { oldCenter = center oldVersion = layout.Version() for x := 0; x <= ViewportWidth; x++ { for y := 0; y <= ViewportHeight; y++ { if layout.Visible(center, layout.Coord{x - xOffset, y - yOffset}) { res.Tile(terrain, res.Terrain, uint16(layout.GetSpace(x-xOffset, y-yOffset)), x, y) draw.Draw(terrain, image.Rect(x<<res.TileSize, y<<res.TileSize, (x+1)<<res.TileSize, (y+1)<<res.TileSize), image.Transparent, image.ZP, draw.Src) for _, t := range layout.Get(x-xOffset, y-yOffset) { if !t.NoClient() { res.Tile(terrain, res.Terrain, uint16(t), x, y) } } } else { res.Tile(terrain, image.Black, 0, x, y) } } } switch GetPlayerFlags() & packet.FlagSpriteMask { case packet.FlagEngineer: for x := 0; x <= ViewportWidth; x++ { for y := 0; y <= ViewportHeight; y++ { dx, dy := x-ViewportWidth/2, y-ViewportHeight/2 dist := dx*dx + dy*dy if dist <= 3*3 && layout.Visible(center, layout.Coord{x - xOffset, y - yOffset}) { for _, t := range layout.Get(x-xOffset, y-yOffset) { if t >= layout.WireW && t <= layout.WireS { res.Tile(terrain, res.Terrain, uint16(t), x, y) } } } } } } } minX, maxX := rect.Min.X>>res.TileSize, (rect.Max.X-1)>>res.TileSize+1 minY, maxY := rect.Min.Y>>res.TileSize, (rect.Max.Y-1)>>res.TileSize+1 draw.Draw(sprites, sprites.Bounds(), image.Transparent, image.ZP, draw.Src) var pixOffset image.Point var hasAnimation image.Rectangle paintLock.Lock() for _, p := range paintContexts { if layout.Visible(center, p.To) { x1, y1 := p.From.X+xOffset, p.From.Y+yOffset x2, y2 := p.To.X+xOffset, p.To.Y+yOffset if minX <= x2 && x2 <= maxX && minY <= y2 && y2 <= maxY { interp := float32(time.Since(p.Changed)*5) / float32(time.Second) if interp >= 1 { res.Tile(sprites, res.Actors, p.Sprite, x2, y2) } else { toInvalidate := image.Rect(x1, y1, x1+1, y1+1).Union(image.Rect(x2, y2, x2+1, y2+1)) if hasAnimation.Empty() { hasAnimation = toInvalidate } else { hasAnimation = hasAnimation.Union(toInvalidate) } if p == thePlayer.paint { pixOffset.X = int(float32((x1-x2)<<res.TileSize) * (1 - interp)) pixOffset.Y = int(float32((y1-y2)<<res.TileSize) * (1 - interp)) hasAnimation = viewport.Bounds() } res.TileFloat(sprites, res.Actors, p.Sprite, x1, y1, x2, y2, interp) } } } } paintLock.Unlock() draw.Draw(viewport, rect, terrain, rect.Min.Add(pixOffset), draw.Src) draw.Draw(viewport, rect, sprites, rect.Min.Add(pixOffset), draw.Over) draw.DrawMask(viewport, rect, image.Black, image.ZP, light.Image(-xOffset, -yOffset), rect.Min.Add(light.Origin(-xOffset, -yOffset)).Add(pixOffset), draw.Over) if image.Rect(0, 0, 1, 1).Overlaps(rect) { mouseTileLock.Lock() res.DrawString(viewport, mouseTileString, color.White, res.FontSmall, 1, 1) mouseTileLock.Unlock() } if !hasAnimation.Empty() { Invalidate(image.Rectangle{hasAnimation.Min.Mul(1 << res.TileSize), hasAnimation.Max.Mul(1 << res.TileSize)}) } paints++ /* // For debugging paints res.DrawString(viewport, strconv.FormatUint(paints, 10), color.White, res.FontSmall, 300, 1) draw.Draw(viewport, image.Rectangle{rect.Min, image.Pt(rect.Max.X+1, rect.Min.Y+1)}, image.White, image.ZP, draw.Src) draw.Draw(viewport, image.Rectangle{image.Pt(rect.Min.X-1, rect.Max.Y-1), rect.Max}, image.White, image.ZP, draw.Src) draw.Draw(viewport, image.Rectangle{rect.Min, image.Pt(rect.Min.X+1, rect.Max.Y+1)}, image.White, image.ZP, draw.Src) draw.Draw(viewport, image.Rectangle{image.Pt(rect.Max.X-1, rect.Min.Y-1), rect.Max}, image.White, image.ZP, draw.Src) //*/ w.Screen().CopyRGBA(viewport, viewport.Bounds()) w.FlushImage(rect) }