Пример #1
0
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])
		}
	}
}
Пример #2
0
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()))
}
Пример #3
0
// 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,
	}
}
Пример #4
0
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)
}
Пример #5
0
//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)
}
Пример #6
0
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,
	}
}
Пример #7
0
// 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)
		}
	}
}
Пример #8
0
// 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,
	}
}
Пример #9
0
// 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,
	}
}
Пример #10
0
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)
}
Пример #11
0
// 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,
	}
}
Пример #12
0
// 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,
	}
}
Пример #13
0
// 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,
	}
}
Пример #14
0
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))))
}
Пример #15
0
// 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,
	}
}
Пример #16
0
// 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}
}
Пример #17
0
// 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,
	}
}
Пример #18
0
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
}
Пример #19
0
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()
}
Пример #20
0
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)
	}
}
Пример #21
0
// 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()
}
Пример #22
0
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))
		}
	}
}
Пример #23
0
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
}
Пример #24
0
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
}
Пример #25
0
// 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)
			}
		}
	}
}
Пример #26
0
// 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)
			}
		}
	}
}
Пример #27
0
Файл: draw.go Проект: oov/psd
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)
}
Пример #28
0
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
}
Пример #29
0
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)
}
Пример #30
0
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)
}