Example #1
0
File: font.go Project: nsf/gotris
func uploadTexture_NRGBA32(img *image.NRGBA) gl.Texture {
	b := img.Bounds()
	data := make([]uint8, b.Max.X*b.Max.Y*4)
	for y := 0; y < b.Max.Y; y++ {
		for x := 0; x < b.Max.X; x++ {
			p := img.At(x, y)
			offset := y*b.Max.X*4 + x*4
			r, g, b, a := p.RGBA()
			data[offset+0] = uint8(r)
			data[offset+1] = uint8(g)
			data[offset+2] = uint8(b)
			data[offset+3] = uint8(a)
		}
	}

	id := gl.GenTexture()
	id.Bind(gl.TEXTURE_2D)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE)
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, b.Max.X, b.Max.Y, 0, gl.RGBA, gl.UNSIGNED_BYTE, data)

	if gl.GetError() != gl.NO_ERROR {
		id.Delete()
		panic(errors.New("Failed to load a texture"))
		return 0
	}
	return id
}
Example #2
0
func Resized(ext string, data []byte, width, height int) (resized []byte, w int, h int) {
	if width == 0 && height == 0 {
		return data, 0, 0
	}
	srcImage, _, err := image.Decode(bytes.NewReader(data))
	if err == nil {
		bounds := srcImage.Bounds()
		var dstImage *image.NRGBA
		if bounds.Dx() > width && width != 0 || bounds.Dy() > height && height != 0 {
			if width == height && bounds.Dx() != bounds.Dy() {
				dstImage = imaging.Thumbnail(srcImage, width, height, imaging.Lanczos)
				w, h = width, height
			} else {
				dstImage = imaging.Resize(srcImage, width, height, imaging.Lanczos)
			}
		} else {
			return data, bounds.Dx(), bounds.Dy()
		}
		var buf bytes.Buffer
		switch ext {
		case ".png":
			png.Encode(&buf, dstImage)
		case ".jpg", ".jpeg":
			jpeg.Encode(&buf, dstImage, nil)
		case ".gif":
			gif.Encode(&buf, dstImage, nil)
		}
		return buf.Bytes(), dstImage.Bounds().Dx(), dstImage.Bounds().Dy()
	} else {
		glog.Error(err)
	}
	return data, 0, 0
}
Example #3
0
func resizeHorizontal(src *image.NRGBA, width int, filter ResampleFilter) *image.NRGBA {
	srcBounds := src.Bounds()
	srcW := srcBounds.Max.X
	srcH := srcBounds.Max.Y

	dstW := width
	dstH := srcH

	dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))

	weights := precomputeWeights(dstW, srcW, filter)

	parallel(dstH, func(partStart, partEnd int) {
		for dstY := partStart; dstY < partEnd; dstY++ {
			for dstX := 0; dstX < dstW; dstX++ {
				var c [4]int32
				for _, iw := range weights[dstX].iwpairs {
					i := dstY*src.Stride + iw.i*4
					c[0] += int32(src.Pix[i+0]) * iw.w
					c[1] += int32(src.Pix[i+1]) * iw.w
					c[2] += int32(src.Pix[i+2]) * iw.w
					c[3] += int32(src.Pix[i+3]) * iw.w
				}
				j := dstY*dst.Stride + dstX*4
				sum := weights[dstX].wsum
				dst.Pix[j+0] = clampint32(int32(float32(c[0])/float32(sum) + 0.5))
				dst.Pix[j+1] = clampint32(int32(float32(c[1])/float32(sum) + 0.5))
				dst.Pix[j+2] = clampint32(int32(float32(c[2])/float32(sum) + 0.5))
				dst.Pix[j+3] = clampint32(int32(float32(c[3])/float32(sum) + 0.5))
			}
		}
	})

	return dst
}
Example #4
0
// fast nearest-neighbor resize, no filtering
func resizeNearest(src *image.NRGBA, width, height int) *image.NRGBA {
	dstW, dstH := width, height

	srcBounds := src.Bounds()
	srcW := srcBounds.Max.X
	srcH := srcBounds.Max.Y

	dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))

	dx := float64(srcW) / float64(dstW)
	dy := float64(srcH) / float64(dstH)

	Parallel(dstH, func(partStart, partEnd int) {

		for dstY := partStart; dstY < partEnd; dstY++ {
			fy := (float64(dstY)+0.5)*dy - 0.5

			for dstX := 0; dstX < dstW; dstX++ {
				fx := (float64(dstX)+0.5)*dx - 0.5

				srcX := int(math.Min(math.Max(math.Floor(fx+0.5), 0.0), float64(srcW)))
				srcY := int(math.Min(math.Max(math.Floor(fy+0.5), 0.0), float64(srcH)))

				srcOff := srcY*src.Stride + srcX*4
				dstOff := dstY*dst.Stride + dstX*4

				copy(dst.Pix[dstOff:dstOff+4], src.Pix[srcOff:srcOff+4])
			}
		}

	})

	return dst
}
Example #5
0
func Resize(context *common.AppContext, source *image.NRGBA, width, height int) *image.NRGBA {
	//Naive nn resize.
	destinationW, destinationH := width, height

	sourceBounds := source.Bounds()
	sourceW := sourceBounds.Max.X
	sourceH := sourceBounds.Max.Y

	destination := image.NewNRGBA(image.Rect(0, 0, destinationW, destinationH))

	dx := float64(sourceW) / float64(destinationW)
	dy := float64(sourceH) / float64(destinationH)

	for destinationY := 0; destinationY < destinationH; destinationY++ {
		fy := (float64(destinationY)+0.5)*dy - 0.5

		for destinationX := 0; destinationX < destinationW; destinationX++ {
			fx := (float64(destinationX)+0.5)*dx - 0.5

			sourceX := int(math.Min(math.Max(math.Floor(fx+0.5), 0.0), float64(sourceW)))
			sourceY := int(math.Min(math.Max(math.Floor(fy+0.5), 0.0), float64(sourceH)))

			sourceOff := sourceY*source.Stride + sourceX*4
			destinationOff := destinationY*destination.Stride + destinationX*4

			copy(destination.Pix[destinationOff:destinationOff+4], source.Pix[sourceOff:sourceOff+4])
		}
	}

	return destination
}
Example #6
0
func uploadTexture_NRGBA32(img *image.NRGBA) gl.Texture {
	b := img.Bounds()
	data := make([]uint8, b.Max.X*b.Max.Y*4)
	for y := 0; y < b.Max.Y; y++ {
		for x := 0; x < b.Max.X; x++ {
			p := &img.Pix[y*img.Stride+x]
			offset := y*b.Max.X*4 + x*4
			data[offset+0] = p.R
			data[offset+1] = p.G
			data[offset+2] = p.B
			data[offset+3] = p.A
		}
	}

	id := gl.GenTexture()
	id.Bind(gl.TEXTURE_2D)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE)
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, b.Max.X, b.Max.Y, 0, gl.RGBA, data)

	if gl.GetError() != gl.NO_ERROR {
		id.Delete()
		panic(os.NewError("Failed to load a texture"))
		return 0
	}
	return id
}
Example #7
0
// Interpolate 4 interleaved uint8 per pixel images.
func interpolate4x8(src *image.NRGBA, dstW, dstH int) image.Image {
	srcRect := src.Bounds()
	srcW := srcRect.Dx()
	srcH := srcRect.Dy()

	ww, hh := uint64(dstW), uint64(dstH)
	dx, dy := uint64(srcW), uint64(srcH)

	n, sum := dx*dy, make([]uint64, 4*dstW*dstH)
	for y := 0; y < srcH; y++ {
		pixOffset := src.PixOffset(0, y)
		for x := 0; x < srcW; x++ {
			// Get the source pixel.
			r64 := uint64(src.Pix[pixOffset+0])
			g64 := uint64(src.Pix[pixOffset+1])
			b64 := uint64(src.Pix[pixOffset+2])
			a64 := uint64(src.Pix[pixOffset+3])
			pixOffset += 4
			// Spread the source pixel over 1 or more destination rows.
			py := uint64(y) * hh
			for remy := hh; remy > 0; {
				qy := dy - (py % dy)
				if qy > remy {
					qy = remy
				}
				// Spread the source pixel over 1 or more destination columns.
				px := uint64(x) * ww
				index := 4 * ((py/dy)*ww + (px / dx))
				for remx := ww; remx > 0; {
					qx := dx - (px % dx)
					if qx > remx {
						qx = remx
					}
					qxy := qx * qy
					sum[index+0] += r64 * qxy
					sum[index+1] += g64 * qxy
					sum[index+2] += b64 * qxy
					sum[index+3] += a64 * qxy
					index += 4
					px += qx
					remx -= qx
				}
				py += qy
				remy -= qy
			}
		}
	}
	dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
	for y := 0; y < dstH; y++ {
		pixOffset := dst.PixOffset(0, y)
		for x := 0; x < dstW; x++ {
			dst.Pix[pixOffset+0] = uint8(sum[pixOffset+0] / n)
			dst.Pix[pixOffset+1] = uint8(sum[pixOffset+1] / n)
			dst.Pix[pixOffset+2] = uint8(sum[pixOffset+2] / n)
			dst.Pix[pixOffset+3] = uint8(sum[pixOffset+3] / n)
			pixOffset += 4
		}
	}
	return dst
}
Example #8
0
func resizeRGBA(in *image.RGBA, out *image.NRGBA, scale float64, coeffs []int16, offset []int, filterLength int) {
	newBounds := out.Bounds()
	maxX := in.Bounds().Dx() - 1

	for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
		row := in.Pix[x*in.Stride:]
		for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
			var rgba [4]int32
			var sum int32
			start := offset[y]
			ci := y * filterLength
			for i := 0; i < filterLength; i++ {
				coeff := coeffs[ci+i]
				if coeff != 0 {
					xi := start + i
					switch {
					case uint(xi) < uint(maxX):
						xi *= 4
					case xi >= maxX:
						xi = 4 * maxX
					default:
						xi = 0
					}

					r := uint32(row[xi+0])
					g := uint32(row[xi+1])
					b := uint32(row[xi+2])
					a := uint32(row[xi+3])

					// reverse alpha-premultiplication.
					if a != 0 {
						r *= 0xffff
						r /= a
						g *= 0xffff
						g /= a
						b *= 0xffff
						b /= a
					}

					rgba[0] += int32(coeff) * int32(r)
					rgba[1] += int32(coeff) * int32(g)
					rgba[2] += int32(coeff) * int32(b)
					rgba[3] += int32(coeff) * int32(a)
					sum += int32(coeff)
				}
			}

			xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*4
			out.Pix[xo+0] = clampUint8(rgba[0] / sum)
			out.Pix[xo+1] = clampUint8(rgba[1] / sum)
			out.Pix[xo+2] = clampUint8(rgba[2] / sum)
			out.Pix[xo+3] = clampUint8(rgba[3] / sum)
		}
	}
}
Example #9
0
func blurVertical(src *image.NRGBA, kernel []float64) *image.NRGBA {
	radius := len(kernel) - 1
	width := src.Bounds().Max.X
	height := src.Bounds().Max.Y

	dst := image.NewNRGBA(image.Rect(0, 0, width, height))

	parallel(height, func(partStart, partEnd int) {
		for y := partStart; y < partEnd; y++ {
			start := y - radius
			if start < 0 {
				start = 0
			}

			end := y + radius
			if end > height-1 {
				end = height - 1
			}

			weightSum := 0.0
			for iy := start; iy <= end; iy++ {
				weightSum += kernel[absint(y-iy)]
			}

			for x := 0; x < width; x++ {

				r, g, b, a := 0.0, 0.0, 0.0, 0.0
				for iy := start; iy <= end; iy++ {
					weight := kernel[absint(y-iy)]
					i := iy*src.Stride + x*4
					wa := float64(src.Pix[i+3]) * weight
					r += float64(src.Pix[i+0]) * wa
					g += float64(src.Pix[i+1]) * wa
					b += float64(src.Pix[i+2]) * wa
					a += wa
				}

				r = math.Min(math.Max(r/a, 0.0), 255.0)
				g = math.Min(math.Max(g/a, 0.0), 255.0)
				b = math.Min(math.Max(b/a, 0.0), 255.0)
				a = math.Min(math.Max(a/weightSum, 0.0), 255.0)

				j := y*dst.Stride + x*4
				dst.Pix[j+0] = uint8(r + 0.5)
				dst.Pix[j+1] = uint8(g + 0.5)
				dst.Pix[j+2] = uint8(b + 0.5)
				dst.Pix[j+3] = uint8(a + 0.5)

			}
		}
	})

	return dst
}
Example #10
0
// Interpolate uint32/pixel images.
func interpolate1x32(src *image.NRGBA, dstW, dstH int) image.Image {
	srcRect := src.Bounds()
	srcW := srcRect.Dx()
	srcH := srcRect.Dy()

	ww, hh := uint64(dstW), uint64(dstH)
	dx, dy := uint64(srcW), uint64(srcH)

	n, sum := dx*dy, make([]uint64, dstW*dstH)
	for y := 0; y < srcH; y++ {
		pixOffset := src.PixOffset(0, y)
		for x := 0; x < srcW; x++ {
			// Get the source pixel.
			val64 := uint64(binary.BigEndian.Uint32([]byte(src.Pix[pixOffset+0 : pixOffset+4])))
			pixOffset += 4

			// Spread the source pixel over 1 or more destination rows.
			py := uint64(y) * hh
			for remy := hh; remy > 0; {
				qy := dy - (py % dy)
				if qy > remy {
					qy = remy
				}
				// Spread the source pixel over 1 or more destination columns.
				px := uint64(x) * ww
				index := (py/dy)*ww + (px / dx)
				for remx := ww; remx > 0; {
					qx := dx - (px % dx)
					if qx > remx {
						qx = remx
					}
					qxy := qx * qy
					sum[index] += val64 * qxy
					index++
					px += qx
					remx -= qx
				}
				py += qy
				remy -= qy
			}
		}
	}
	dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
	index := 0
	for y := 0; y < dstH; y++ {
		pixOffset := dst.PixOffset(0, y)
		for x := 0; x < dstW; x++ {
			binary.BigEndian.PutUint32(dst.Pix[pixOffset+0:pixOffset+4], uint32(sum[index]/n))
			pixOffset += 4
			index++
		}
	}
	return dst
}
Example #11
0
func DrawTextOnImage(text string, font *truetype.Font, img *image.NRGBA, size, x, y int) {
	c := freetype.NewContext()
	c.SetDPI(120)
	c.SetFont(font)
	c.SetFontSize(float64(size))
	c.SetClip(img.Bounds())
	c.SetDst(img)
	c.SetSrc(image.Black)
	pt := freetype.Pt(x, y+int(c.PointToFix32(float64(size))>>8))
	c.DrawString(text, pt)
}
Example #12
0
func invertImageNrgba(nrgba *image.NRGBA) {
	bounds := nrgba.Bounds()
	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
		for x := bounds.Min.X; x < bounds.Max.X; x++ {
			c := nrgba.At(x, y).(color.NRGBA)
			c.R = 255 - c.R
			c.G = 255 - c.G
			c.B = 255 - c.B
			nrgba.SetNRGBA(x, y, c)
		}
	}
}
Example #13
0
func blurHorizontal(src *image.NRGBA, kernel []float64) *image.NRGBA {
	radius := len(kernel) - 1
	width := src.Bounds().Max.X
	height := src.Bounds().Max.Y

	dst := image.NewNRGBA(image.Rect(0, 0, width, height))

	parallel(width, func(partStart, partEnd int) {
		for x := partStart; x < partEnd; x++ {
			start := x - radius
			if start < 0 {
				start = 0
			}

			end := x + radius
			if end > width-1 {
				end = width - 1
			}

			weightSum := 0.0
			for ix := start; ix <= end; ix++ {
				weightSum += kernel[absint(x-ix)]
			}

			for y := 0; y < height; y++ {

				r, g, b, a := 0.0, 0.0, 0.0, 0.0
				for ix := start; ix <= end; ix++ {
					weight := kernel[absint(x-ix)]
					i := y*src.Stride + ix*4
					r += float64(src.Pix[i+0]) * weight
					g += float64(src.Pix[i+1]) * weight
					b += float64(src.Pix[i+2]) * weight
					a += float64(src.Pix[i+3]) * weight
				}

				r = math.Min(math.Max(r/weightSum, 0.0), 255.0)
				g = math.Min(math.Max(g/weightSum, 0.0), 255.0)
				b = math.Min(math.Max(b/weightSum, 0.0), 255.0)
				a = math.Min(math.Max(a/weightSum, 0.0), 255.0)

				j := y*dst.Stride + x*4
				dst.Pix[j+0] = uint8(r + 0.5)
				dst.Pix[j+1] = uint8(g + 0.5)
				dst.Pix[j+2] = uint8(b + 0.5)
				dst.Pix[j+3] = uint8(a + 0.5)

			}
		}
	})

	return dst
}
Example #14
0
// MakeImage makes an image from an image.NRGBA.
func MakeImage(i *image.NRGBA) (img Image) {
	img.Width, img.Height = i.Bounds().Dx(), i.Bounds().Dy()

	img.tex = gl.GenTexture()
	img.tex.Bind(gl.TEXTURE_2D)
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)

	gl.TexImage2D(gl.TEXTURE_2D, 0, 4, img.Width, img.Height,
		0, gl.RGBA, gl.UNSIGNED_BYTE, i.Pix)
	return
}
Example #15
0
File: canvas.go Project: velour/ui
func texFromImage(rend *C.SDL_Renderer, img *image.NRGBA) *C.SDL_Texture {
	b := img.Bounds()
	w, h := b.Dx(), b.Dy()
	fmt := C.SDL_PIXELFORMAT_ABGR8888
	acc := C.SDL_TEXTUREACCESS_STATIC
	tex := C.SDL_CreateTexture(rend, C.Uint32(fmt), C.int(acc), C.int(w), C.int(h))
	if tex == nil {
		panic(sdlError())
	}
	if C.SDL_UpdateTexture(tex, nil, unsafe.Pointer(&img.Pix[0]), C.int(img.Stride)) < 0 {
		panic(sdlError())
	}
	if C.SDL_SetTextureBlendMode(tex, C.SDL_BLENDMODE_BLEND) < 0 {
		panic(sdlError())
	}
	return tex
}
Example #16
0
func calculateImg(img *image.NRGBA, pointX, pointY, zoom float64, julia bool, maxIter int) {
	minCx := -2.
	minCy := -2.
	if !julia {
		minCx = pointX
		minCy = pointY
	}
	bounds := img.Bounds()
	stepX := math.Abs(minCx-2.) / float64(bounds.Dx()) / zoom
	stepY := math.Abs(minCy-2.) / float64(bounds.Dy()) / zoom
	pal := paletteToNRGBA(palette.Rainbow(maxIter, 0, 1, 1, 1, 1))
	for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
		cy := minCy + float64(y)*stepY
		for x := bounds.Min.X; x < bounds.Max.X; x++ {
			img.SetNRGBA(x, y, pal[pointIteration(minCx+float64(x)*stepX, cy, pointX, pointY, julia, maxIter)])
		}
	}
}
Example #17
0
func (s *Scene) Render(img *image.NRGBA) {
	rect := img.Bounds()
	w, h := float64(rect.Dx()), float64(rect.Dy())
	i_max, j_max := rect.Dx(), rect.Dy()
	for i := 0; i < i_max; i++ {
		u := (float64(i) - w/2.0) / (w / 2.0)
		for j := 0; j < j_max; j++ {
			// (h / w) term is needed to correct for nonunity aspect ratios
			v := (float64(j) - h/2.0) / (h / 2.0) * (h / w)

			if *debug {
				//fmt.Printf("%d/%d\n", i * j_max + j, i_max * j_max)
			}

			s.SetColor(i, j, u, v, img)
		}
	}
}
Example #18
0
func skewVertical(src *image.NRGBA, degrees float64) *image.NRGBA {
	bounds := src.Bounds()
	maxY := bounds.Max.Y
	maxX := bounds.Max.X * 4
	distance := float64(bounds.Max.X) * math.Tan(degrees)
	shouldFlip := false
	if distance < 0 {
		distance = -distance
		shouldFlip = true
	}

	newHeight := maxY + int(1+distance)
	dst := image.NewNRGBA(image.Rect(0, 0, bounds.Max.X, newHeight))

	step := distance
	for x := 0; x < maxX; x += 4 {
		for row := 0; row < maxY; row += 1 {
			srcPx := row*src.Stride + x
			dstLower := (int(step)+row)*dst.Stride + x
			dstUpper := dstLower + dst.Stride
			_, delta := math.Modf(step)

			if src.Pix[srcPx+3] != 0 {
				dst.Pix[dstLower+0] += uint8(float64(src.Pix[srcPx+0]) * (1 - delta))
				dst.Pix[dstLower+1] += uint8(float64(src.Pix[srcPx+1]) * (1 - delta))
				dst.Pix[dstLower+2] += uint8(float64(src.Pix[srcPx+2]) * (1 - delta))
				dst.Pix[dstLower+3] += uint8(float64(src.Pix[srcPx+3]) * (1 - delta))

				dst.Pix[dstUpper+0] += uint8(float64(src.Pix[srcPx+0]) * delta)
				dst.Pix[dstUpper+1] += uint8(float64(src.Pix[srcPx+1]) * delta)
				dst.Pix[dstUpper+2] += uint8(float64(src.Pix[srcPx+2]) * delta)
				dst.Pix[dstUpper+3] += uint8(float64(src.Pix[srcPx+3]) * delta)
			}
		}

		step -= distance / float64(bounds.Max.X)
	}

	if shouldFlip {
		return imaging.FlipH(dst)
	} else {
		return dst
	}
}
Example #19
0
func mergeTextures(normalTexture, litTexture *image.NRGBA) {
	normSize := normalTexture.Bounds().Size()
	litSize := litTexture.Bounds().Size()
	if normSize.X != litSize.X || normSize.Y != litSize.Y {
		//Größen sind unterschiedlich --> normale Textur auf Größe der Nachttextur skalieren
		normalTexture = imaging.Resize(normalTexture, litSize.X, litSize.Y, imaging.Linear)
	}
	for x := 0; x < litSize.X; x++ {
		for y := 0; y < litSize.Y; y++ {
			i := y*normalTexture.Stride + x*4
			j := y*litTexture.Stride + x*4

			litTexture.Pix[j+0] = mergePixel(normalTexture.Pix[i+0], litTexture.Pix[j+0], 1.0)
			litTexture.Pix[j+1] = mergePixel(normalTexture.Pix[i+1], litTexture.Pix[j+1], 1.0)
			litTexture.Pix[j+2] = mergePixel(normalTexture.Pix[i+2], litTexture.Pix[j+2], 0.7)
			litTexture.Pix[j+3] = normalTexture.Pix[i+3]
		}
	}
}
Example #20
0
// Draws the "src" onto the "dst" image at the given x/y bounds, maintaining
// the original size. Pixels with have an alpha of 0x00 are not draw, and
// all others are drawn with an alpha of 0xFF
func fastDraw(dst *image.NRGBA, src *image.NRGBA, x, y int) {
	bounds := src.Bounds()
	maxY := bounds.Max.Y
	maxX := bounds.Max.X * 4

	pointer := dst.PixOffset(x, y)
	for row := 0; row < maxY; row += 1 {
		for i := 0; i < maxX; i += 4 {
			srcPx := row*src.Stride + i
			dstPx := row*dst.Stride + i + pointer
			if src.Pix[srcPx+3] != 0 {
				dst.Pix[dstPx+0] = src.Pix[srcPx+0]
				dst.Pix[dstPx+1] = src.Pix[srcPx+1]
				dst.Pix[dstPx+2] = src.Pix[srcPx+2]
				dst.Pix[dstPx+3] = 0xFF
			}
		}
	}
}
Example #21
0
// Encode encoded the image in SKTEXT format.
func Encode(w io.Writer, m *image.NRGBA) error {
	fmt.Fprintf(w, "%s%d %d\n", skTextHeader, m.Rect.Dx(), m.Rect.Dy())
	height := m.Bounds().Dy()
	for i := 0; i < len(m.Pix); i += 4 {
		_, err := fmt.Fprintf(w, "0x%02x%02x%02x%02x", m.Pix[i+0], m.Pix[i+1], m.Pix[i+2], m.Pix[i+3])
		if err != nil {
			return err
		}
		// Add whitespace.
		if (i > 0 || m.Stride == 4) && (i+4)%m.Stride == 0 {
			// Don't add a trailing \n to the very last line.
			if (i+4)/m.Stride < height {
				fmt.Fprintln(w)
			}
		} else {
			fmt.Fprint(w, " ")
		}
	}
	return nil
}
Example #22
0
func resize32(src *image.NRGBA, dstW, dstH int) image.Image {
	srcRect := src.Bounds()
	srcW := srcRect.Dx()
	srcH := srcRect.Dy()

	dstW64, dstH64 := uint64(dstW), uint64(dstH)
	srcW64, srcH64 := uint64(srcW), uint64(srcH)

	dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))
	var x, y uint64
	dstI := 0
	for y = 0; y < dstH64; y++ {
		srcY := int(y * srcH64 / dstH64)
		for x = 0; x < dstW64; x++ {
			srcX := int(x * srcW64 / dstW64)
			srcI := 4 * (srcY*srcW + srcX)
			copy(dst.Pix[dstI:dstI+4], src.Pix[srcI:srcI+4])
			dstI += 4
		}
	}
	return dst
}
Example #23
0
func resizeVertical(src *image.NRGBA, height int, filter ResampleFilter) *image.NRGBA {
	srcBounds := src.Bounds()
	srcW := srcBounds.Max.X
	srcH := srcBounds.Max.Y

	dstW := srcW
	dstH := height

	dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))

	weights := precomputeWeights(dstH, srcH, filter)

	parallel(dstW, func(partStart, partEnd int) {

		for dstX := partStart; dstX < partEnd; dstX++ {
			for dstY := 0; dstY < dstH; dstY++ {
				var c [4]int64
				for _, iw := range weights[dstY].iwpairs {
					i := iw.i*src.Stride + dstX*4
					a := int64(src.Pix[i+3]) * int64(iw.w)
					c[0] += int64(src.Pix[i+0]) * a
					c[1] += int64(src.Pix[i+1]) * a
					c[2] += int64(src.Pix[i+2]) * a
					c[3] += a
				}
				j := dstY*dst.Stride + dstX*4
				sum := weights[dstY].wsum
				dst.Pix[j+0] = clampint32(int32(float64(c[0])/float64(c[3]) + 0.5))
				dst.Pix[j+1] = clampint32(int32(float64(c[1])/float64(c[3]) + 0.5))
				dst.Pix[j+2] = clampint32(int32(float64(c[2])/float64(c[3]) + 0.5))
				dst.Pix[j+3] = clampint32(int32(float64(c[3])/float64(sum) + 0.5))
			}
		}

	})

	return dst
}
Example #24
0
func nearestNRGBA(in *image.NRGBA, out *image.NRGBA, scale float64, coeffs []bool, offset []int, filterLength int) {
	newBounds := out.Bounds()
	maxX := in.Bounds().Dx() - 1

	for x := newBounds.Min.X; x < newBounds.Max.X; x++ {
		row := in.Pix[x*in.Stride:]
		for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ {
			var rgba [4]float32
			var sum float32
			start := offset[y]
			ci := y * filterLength
			for i := 0; i < filterLength; i++ {
				if coeffs[ci+i] {
					xi := start + i
					switch {
					case uint(xi) < uint(maxX):
						xi *= 4
					case xi >= maxX:
						xi = 4 * maxX
					default:
						xi = 0
					}
					rgba[0] += float32(row[xi+0])
					rgba[1] += float32(row[xi+1])
					rgba[2] += float32(row[xi+2])
					rgba[3] += float32(row[xi+3])
					sum++
				}
			}

			xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*4
			out.Pix[xo+0] = floatToUint8(rgba[0] / sum)
			out.Pix[xo+1] = floatToUint8(rgba[1] / sum)
			out.Pix[xo+2] = floatToUint8(rgba[2] / sum)
			out.Pix[xo+3] = floatToUint8(rgba[3] / sum)
		}
	}
}
Example #25
0
func (l *windowsAssetloader) loadResources() {
	resourceData, err := payload.Read()
	check(err)
	l.resources, err = blob.Read(bytes.NewBuffer(resourceData))

	// load the texture atlas
	atlas, found := l.resources.GetByID("atlas")
	if !found {
		panic("texture atlas not found in resources")
	}

	ping, err := png.Decode(bytes.NewReader(atlas))
	check(err)

	var nrgba *image.NRGBA
	if asNRGBA, ok := ping.(*image.NRGBA); ok {
		nrgba = asNRGBA
	} else {
		nrgba = image.NewNRGBA(ping.Bounds())
		draw.Draw(nrgba, nrgba.Bounds(), ping, image.ZP, draw.Src)
	}

	texture, err := l.device.CreateTexture(
		uint(nrgba.Bounds().Dx()),
		uint(nrgba.Bounds().Dy()),
		1,
		d3d9.USAGE_SOFTWAREPROCESSING,
		d3d9.FMT_A8R8G8B8,
		d3d9.POOL_MANAGED,
		nil,
	)
	check(err)
	lockedRect, err := texture.LockRect(0, nil, d3d9.LOCK_DISCARD)
	check(err)
	lockedRect.SetAllBytes(nrgba.Pix, nrgba.Stride)
	check(texture.UnlockRect(0))

	l.textureAtlas = texture
	l.textureAtlasBounds = nrgba.Bounds()
}
Example #26
0
func resizeHorizontal(src *image.NRGBA, width int, filter ResampleFilter) *image.NRGBA {
	srcBounds := src.Bounds()
	srcW := srcBounds.Max.X
	srcH := srcBounds.Max.Y

	dstW := width
	dstH := srcH

	dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))

	dX := float64(srcW) / float64(dstW)
	scaleX := math.Max(dX, 1.0)
	rX := math.Ceil(scaleX * filter.Support)

	Parallel(dstW, func(partStart, partEnd int) {

		weights := make([]float64, int(rX+2)*2)

		for dstX := partStart; dstX < partEnd; dstX++ {

			fX := (float64(dstX)+0.5)*dX - 0.5

			startX := int(math.Ceil(fX - rX))
			if startX < 0 {
				startX = 0
			}
			endX := int(math.Floor(fX + rX))
			if endX > srcW-1 {
				endX = srcW - 1
			}

			// cache weights
			weightSum := 0.0
			for x := startX; x <= endX; x++ {
				w := filter.Kernel((float64(x) - fX) / scaleX)
				weightSum += w
				weights[x-startX] = w
			}

			for dstY := 0; dstY < dstH; dstY++ {
				r, g, b, a := 0.0, 0.0, 0.0, 0.0
				for x := startX; x <= endX; x++ {
					weight := weights[x-startX]
					i := dstY*src.Stride + x*4
					r += float64(src.Pix[i+0]) * weight
					g += float64(src.Pix[i+1]) * weight
					b += float64(src.Pix[i+2]) * weight
					a += float64(src.Pix[i+3]) * weight
				}

				r = math.Min(math.Max(r/weightSum, 0.0), 255.0)
				g = math.Min(math.Max(g/weightSum, 0.0), 255.0)
				b = math.Min(math.Max(b/weightSum, 0.0), 255.0)
				a = math.Min(math.Max(a/weightSum, 0.0), 255.0)

				j := dstY*dst.Stride + dstX*4
				dst.Pix[j+0] = uint8(r + 0.5)
				dst.Pix[j+1] = uint8(g + 0.5)
				dst.Pix[j+2] = uint8(b + 0.5)
				dst.Pix[j+3] = uint8(a + 0.5)
			}
		}

	})

	return dst
}
Example #27
0
func resizeVertical(src *image.NRGBA, height int, filter ResampleFilter) *image.NRGBA {
	srcBounds := src.Bounds()
	srcW := srcBounds.Max.X
	srcH := srcBounds.Max.Y

	dstW := srcW
	dstH := height

	dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))

	dY := float64(srcH) / float64(dstH)
	scaleY := math.Max(dY, 1.0)
	rY := math.Ceil(scaleY * filter.Support)

	Parallel(dstH, func(partStart, partEnd int) {

		weights := make([]float64, int(rY+2)*2)

		for dstY := partStart; dstY < partEnd; dstY++ {

			fY := (float64(dstY)+0.5)*dY - 0.5

			startY := int(math.Ceil(fY - rY))
			if startY < 0 {
				startY = 0
			}
			endY := int(math.Floor(fY + rY))
			if endY > srcH-1 {
				endY = srcH - 1
			}

			// cache weights
			weightSum := 0.0
			for y := startY; y <= endY; y++ {
				w := filter.Kernel((float64(y) - fY) / scaleY)
				weightSum += w
				weights[y-startY] = w
			}

			for dstX := 0; dstX < dstW; dstX++ {
				r, g, b, a := 0.0, 0.0, 0.0, 0.0
				for y := startY; y <= endY; y++ {
					weight := weights[y-startY]
					i := y*src.Stride + dstX*4
					r += float64(src.Pix[i+0]) * weight
					g += float64(src.Pix[i+1]) * weight
					b += float64(src.Pix[i+2]) * weight
					a += float64(src.Pix[i+3]) * weight
				}

				r = math.Min(math.Max(r/weightSum, 0.0), 255.0)
				g = math.Min(math.Max(g/weightSum, 0.0), 255.0)
				b = math.Min(math.Max(b/weightSum, 0.0), 255.0)
				a = math.Min(math.Max(a/weightSum, 0.0), 255.0)

				j := dstY*dst.Stride + dstX*4
				dst.Pix[j+0] = uint8(r + 0.5)
				dst.Pix[j+1] = uint8(g + 0.5)
				dst.Pix[j+2] = uint8(b + 0.5)
				dst.Pix[j+3] = uint8(a + 0.5)
			}
		}

	})

	return dst
}
Example #28
0
func makeImg(s string, b string, h int, qx int, qy int, u int) (*image.NRGBA, error) {
	var (
		width  int
		height int
		canvas *image.NRGBA
		k      int
		v      rune
	)

	if u <= 0 {
		u = 1
	}

	if qx <= 0 {
		qx = 5
	}

	if qy <= 0 {
		qy = 3
	}

	if h <= 0 {
		h = 100
	}

	width = qx*2 + len(b)*u
	height = qy*2 + h

	fontSize := 16

	canvas = image.NewNRGBA(image.Rect(0, 0, width, height+fontSize+5))

	drawRect(canvas, image.Rect(0, 0, width, height+fontSize+5), color.RGBA{255, 255, 255, 255})

	for k, v = range b {
		if v == 49 {
			drawRect(canvas, image.Rect(qx+k*u, qy, qx+k*u+u, qy+h), color.RGBA{0, 0, 0, 255})
		}
	}

	data, err := ioutil.ReadFile("./fonts/luxisr.ttf")

	if err != nil {
		return nil, err
	}

	font, err := freetype.ParseFont(data)
	if err != nil {
		return nil, err
	}

	c := freetype.NewContext()
	c.SetDst(canvas)
	c.SetClip(canvas.Bounds())
	c.SetSrc(image.Black)
	c.SetFont(font)
	c.SetFontSize(float64(fontSize))

	s = expandStr(s)

	p, _ := c.DrawString(s, freetype.Pt(0, height+fontSize+5))
	drawRect(canvas, image.Rect(0, height, width, height+fontSize+5), color.RGBA{255, 255, 255, 255})

	p, _ = c.DrawString(s, freetype.Pt(width/2-int(p.X)/256/2, height+fontSize))

	return canvas, nil
}
Example #29
0
func resizeVertical(src *image.NRGBA, height int, filter resamplingFilter) *image.NRGBA {
	srcBounds := src.Bounds()
	srcW := srcBounds.Dx()
	srcH := srcBounds.Dy()
	srcMinX := srcBounds.Min.X
	srcMinY := srcBounds.Min.Y
	srcMaxY := srcBounds.Max.Y

	dstW := srcW
	dstH := height

	dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))

	dY := float64(srcH) / float64(dstH)
	scaleY := math.Max(dY, 1.0)
	rY := math.Ceil(scaleY * filter.Support)

	// divide image to parts for parallel processing
	numGoroutines := runtime.NumCPU()
	goMaxProcs := runtime.GOMAXPROCS(0)
	if numGoroutines > goMaxProcs {
		numGoroutines = goMaxProcs
	}
	if numGoroutines > dstH {
		numGoroutines = dstH
	}
	partSize := dstH / numGoroutines

	doneChan := make(chan bool, numGoroutines)

	for part := 0; part < numGoroutines; part++ {
		partStart := part * partSize
		partEnd := (part + 1) * partSize
		if part == numGoroutines-1 {
			partEnd = dstH
		}

		go func(partStart, partEnd int) {

			for dstY := partStart; dstY < partEnd; dstY++ {
				fY := float64(srcMinY) + (float64(dstY)+0.5)*dY - 0.5

				startY := int(math.Ceil(fY - rY))
				if startY < srcMinY {
					startY = srcMinY
				}
				endY := int(math.Floor(fY + rY))
				if endY > srcMaxY-1 {
					endY = srcMaxY - 1
				}

				// cache weights
				weightSum := 0.0
				weights := make([]float64, int(rY+2)*2)
				for y := startY; y <= endY; y++ {
					w := filter.Kernel((float64(y) - fY) / scaleY)
					weightSum += w
					weights[y-startY] = w
				}

				for dstX := 0; dstX < dstW; dstX++ {
					srcX := srcMinX + dstX

					r, g, b, a := 0.0, 0.0, 0.0, 0.0
					for y := startY; y <= endY; y++ {
						weight := weights[y-startY]
						i := src.PixOffset(srcX, y)
						r += float64(src.Pix[i+0]) * weight
						g += float64(src.Pix[i+1]) * weight
						b += float64(src.Pix[i+2]) * weight
						a += float64(src.Pix[i+3]) * weight
					}

					r = math.Min(math.Max(r/weightSum, 0.0), 255.0)
					g = math.Min(math.Max(g/weightSum, 0.0), 255.0)
					b = math.Min(math.Max(b/weightSum, 0.0), 255.0)
					a = math.Min(math.Max(a/weightSum, 0.0), 255.0)

					j := dst.PixOffset(dstX, dstY)
					dst.Pix[j+0] = uint8(r + 0.5)
					dst.Pix[j+1] = uint8(g + 0.5)
					dst.Pix[j+2] = uint8(b + 0.5)
					dst.Pix[j+3] = uint8(a + 0.5)
				}
			}

			doneChan <- true
		}(partStart, partEnd)

	}

	// wait for goroutines to finish
	for part := 0; part < numGoroutines; part++ {
		<-doneChan
	}

	return dst
}
Example #30
0
// fast nearest-neighbor resize, no filtering
func resizeNearest(src *image.NRGBA, width, height int) *image.NRGBA {
	dstW, dstH := width, height

	srcBounds := src.Bounds()
	srcW := srcBounds.Dx()
	srcH := srcBounds.Dy()
	srcMinX := srcBounds.Min.X
	srcMinY := srcBounds.Min.Y
	srcMaxX := srcBounds.Max.X
	srcMaxY := srcBounds.Max.Y

	dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH))

	dx := float64(srcW) / float64(dstW)
	dy := float64(srcH) / float64(dstH)

	// divide image to parts for parallel processing
	numGoroutines := runtime.NumCPU()
	goMaxProcs := runtime.GOMAXPROCS(0)
	if numGoroutines > goMaxProcs {
		numGoroutines = goMaxProcs
	}
	if numGoroutines > dstH {
		numGoroutines = dstH
	}
	partSize := dstH / numGoroutines

	doneChan := make(chan bool, numGoroutines)

	for part := 0; part < numGoroutines; part++ {
		partStart := part * partSize
		partEnd := (part + 1) * partSize
		if part == numGoroutines-1 {
			partEnd = dstH
		}

		go func(partStart, partEnd int) {

			for dstY := partStart; dstY < partEnd; dstY++ {
				fy := float64(srcMinY) + (float64(dstY)+0.5)*dy - 0.5

				for dstX := 0; dstX < dstW; dstX++ {
					fx := float64(srcMinX) + (float64(dstX)+0.5)*dx - 0.5

					srcX := int(math.Min(math.Max(math.Floor(fx+0.5), float64(srcMinX)), float64(srcMaxX)))
					srcY := int(math.Min(math.Max(math.Floor(fy+0.5), float64(srcMinY)), float64(srcMaxY)))

					srcOffset := src.PixOffset(srcX, srcY)
					dstOffset := dst.PixOffset(dstX, dstY)

					dst.Pix[dstOffset+0] = src.Pix[srcOffset+0]
					dst.Pix[dstOffset+1] = src.Pix[srcOffset+1]
					dst.Pix[dstOffset+2] = src.Pix[srcOffset+2]
					dst.Pix[dstOffset+3] = src.Pix[srcOffset+3]
				}
			}

			doneChan <- true
		}(partStart, partEnd)
	}

	// wait for goroutines to finish
	for part := 0; part < numGoroutines; part++ {
		<-doneChan
	}

	return dst
}