// 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 }
// render one row of pixels by calculating a colour for each pixel. // The image pixel row number is r. Fill the pixel colour into the // image after the colour has been calculated. func (r row) render(rt *rtrace, a, b, c lin.V3, img *image.NRGBA, seed *uint32) { rgba := color.NRGBA{0, 0, 0, 255} t, v1, v2 := lin.NewV3(), lin.NewV3(), lin.NewV3() // temp vectors. colour, orig, dir := lin.NewV3(), lin.NewV3(), lin.NewV3() for x := (rt.iw - 1); x >= 0; x-- { colour.SetS(13, 13, 13) // Use a very dark default colour. // Cast 64 rays per pixel for blur (stochastic sampling) and soft-shadows. for cnt := 0; cnt < 64; cnt++ { // Add randomness to the camera origin 17,16,8 t.Scale(&a, rnd(seed)-0.5).Scale(t, 99).Add(t, v1.Scale(&b, rnd(seed)-0.5).Scale(v1, 99)) orig.SetS(17, 16, 8).Add(orig, t) // Add randomness to the camera direction. rnda := rnd(seed) + float64(x) rndb := float64(r) + rnd(seed) dir.Scale(t, -1) dir.Add(dir, v1.Scale(&a, rnda).Add(v1, v2.Scale(&b, rndb)).Add(v1, &c).Scale(v1, 16)) dir.Unit() // accumulate the colour from each of the 64 rays. sample := rt.sample(*orig, *dir, seed) colour = sample.Scale(&sample, 3.5).Add(&sample, colour) } // set the final pixel colour in the image. rgba.R = byte(colour.X) // red rgba.G = byte(colour.Y) // green rgba.B = byte(colour.Z) // blue img.SetNRGBA(rt.iw-x, int(r), rgba) } }
func useChunk(chunk *Chunk, img *image.NRGBA, xoffset, zoffset int) error { var r, openErr = chunk.Open() if openErr != nil { return openErr } defer r.Close() var c, nbtErr = nbt.ReadChunkNbt(r) if nbtErr != nil { return nbtErr } blocks := Blocks(c.Blocks) for x := 0; x < 16; x++ { for z := 0; z < 16; z++ { column := blocks.Column(x, z) v := uint16(0) for y := 127; y > 0; y-- { if column[y] != 0 { v = column[y] break } } //fmt.Printf("%7x", color[v&0xff]) img.Set(xoffset+x, zoffset+z, rgb(color[v&0xff])) //fmt.Printf("%7x", img.At(x, z)) } //fmt.Println() } //fmt.Println() return nil }
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 }
func drawRect(img *image.NRGBA, r image.Rectangle, c color.Color) { for i := r.Min.X; i <= r.Max.X; i++ { for j := r.Min.Y; j <= r.Max.Y; j++ { img.Set(i, j, c) } } }
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 }
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 }
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 }
// 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 }
func setPixel(i *image.NRGBA, x, y int) { for zx := 1; zx < 9; zx++ { for zy := 1; zy < 9; zy++ { i.Set(x*10+zx, y*10+zy, color.RGBA{0, 0, 0, 255}) } } }
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 }
func cutImage(img *image.NRGBA) []*image.NRGBA { r := image.Rect(0, 0, 6, 11) cuts := make([]*image.NRGBA, 10) for i := 0; i < 10; i++ { cuts[i] = img.SubImage(r).(*image.NRGBA) r = r.Add(image.Pt(7, 0)) } return cuts }
func newSetFuncNRGBA(p *image.NRGBA) SetFunc { return func(x, y int, r, g, b, a uint32) { r, g, b, a = RGBAToNRGBA(r, g, b, a) i := p.PixOffset(x, y) p.Pix[i+0] = uint8(r >> 8) p.Pix[i+1] = uint8(g >> 8) p.Pix[i+2] = uint8(b >> 8) p.Pix[i+3] = uint8(a >> 8) } }
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) } } }
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 }
// 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 }
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) }
// 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 }
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 }
func render(img *image.NRGBA, startY, limitY int, c chan int) { for y := startY; y < limitY; y++ { for x := 0; x < img.Rect.Dx(); x++ { p := vec.Vec3{float32(float32(x)/float32(img.Rect.Dx()-1) - 0.5), float32(-(float32(y)/float32(img.Rect.Dy()-1) - 0.5)), -float32(0.8)} d := p.Normalized() dist, obj := distanceFieldObject(p) step := 0 for ; step < 63 && dist > -0.005*p.Z; step++ { // Error decreases 1/d, so keep min step proportional to d for constant screen-space error p = p.Add(d, math32.Maxf(-0.005*p.Z, dist)) if p.Z < -60 { break } dist, obj = distanceFieldObject(p) } if dist <= -0.01*p.Z { n := fieldNormalAt(distanceField, p) // compute ambient occlusion before doing bump mapping ao := math32.Minf(ambientOcclusion(p, n), 1.0) dnoise := fieldNormalAt(noise.Fbm, p) const N = 0.3 n = n.Vtrans(dnoise.Scale(N)).Normalized() distfade := math32.Expf(0.07 * (p.Z + 6)) /*lit := float32(1.0)*/ lit := math32.Maxf(0, n.Z) /*tex := float32(0.8)*/ tex := (0.4*(math32.Sinf(2*(p.X+1.4*p.Y)+2*noise.Fbm(p))+1) + 0.2) v := tex * (lit*0.6 + 0.3) * (ao * ao * ao) * distfade col := obj.Color() img.Set(x, y, color.NRGBA{ /*uint8(math32.Minf(float32(step)*4+255*v, 255)),*/ uint8(255 * v * col[0]), uint8(255 * v * col[1]), uint8(255 * v * col[2]), /*uint8(255*ao),*/ 255}) } else { /*img.Set(x, y, image.RGBAColor{uint8(step * 4), 0, 0, 255})*/ img.Set(x, y, color.NRGBA{0, 0, 0, 255}) } } } c <- 1 }
func setPixelBytes(img image.NRGBA, pixel LsbPixel, byt byte) { rgba := img.NRGBAAt(pixel.GetX(), pixel.GetY()) switch pixel.GetLayer() { case "r": rgba.R = byt case "g": rgba.G = byt case "b": rgba.B = byt case "a": rgba.A = byt } img.Set(pixel.GetX(), pixel.GetY(), rgba) }
func getPixelBytes(img image.NRGBA, pixel LsbPixel) byte { rgba := img.NRGBAAt(pixel.GetX(), pixel.GetY()) switch pixel.GetLayer() { case "r": return rgba.R case "g": return rgba.G case "b": return rgba.B case "a": return rgba.A } return 0 }
func Resize(src io.Reader, c *CacheContext) (io.Reader, error) { raw, err := ioutil.ReadAll(src) if err != nil { return nil, err } width := c.Width data := bytes.NewReader(raw) img, format, err := image.Decode(data) if err != nil { return nil, err } var resizedImage image.NRGBA if c.Crop { minDimension := int(math.Min(float64(img.Bounds().Size().X), float64(img.Bounds().Size().Y))) if minDimension < c.Width || c.Width == 0 { width = minDimension } resizedImage = *imaging.Fill(img, width, width, imaging.Center, imaging.Lanczos) } else { resizedImage = *imaging.Resize(img, width, 0, imaging.Lanczos) } buf := new(bytes.Buffer) var imgFormat imaging.Format switch format { case "png": imgFormat = imaging.PNG case "jpeg": imgFormat = imaging.JPEG case "tiff": imgFormat = imaging.TIFF case "bmp": imgFormat = imaging.BMP default: return nil, errors.New("unsupported image format") } err = imaging.Encode(buf, resizedImage.SubImage(resizedImage.Rect), imgFormat) if err != nil { return nil, err } return buf, err }
// Rams the head onto the base (hopefully body...) to return a Frankenstein. func (skin *mcSkin) addHead(base, head *image.NRGBA) *image.NRGBA { base.Pix = append(make([]uint8, HeadHeight*base.Stride), base.Pix...) base.Rect.Max.Y += HeadHeight fastDraw(base, head, LaWidth, 0) return base }
// Attached the legs onto the base (likely body). func (skin *mcSkin) addLegs(base, legs *image.NRGBA) *image.NRGBA { base.Pix = append(base.Pix, make([]uint8, LlHeight*base.Stride)...) base.Rect.Max.Y += LlHeight fastDraw(base, legs, LaWidth, HeadHeight+TorsoHeight) return base }
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 }
func convertNRGBA(dest *Image, src *image.NRGBA) { var x, y, i, si int var a uint16 for x = dest.Rect.Min.X; x < dest.Rect.Max.X; x++ { for y = dest.Rect.Min.Y; y < dest.Rect.Max.Y; y++ { si = src.PixOffset(x, y) i = dest.PixOffset(x, y) a = uint16(src.Pix[si+3]) dest.Pix[i+0] = uint8((uint16(src.Pix[si+2]) * a) / 0xff) dest.Pix[i+1] = uint8((uint16(src.Pix[si+1]) * a) / 0xff) dest.Pix[i+2] = uint8((uint16(src.Pix[si+0]) * a) / 0xff) dest.Pix[i+3] = src.Pix[si+3] } } }
// Takes an average of the biome colors of the surrounding area func calculateBiome(bs *blocksSnapshot, x, z int, img *image.NRGBA) (byte, byte, byte) { count := 0 var r, g, b int for xx := -2; xx <= 2; xx++ { for zz := -2; zz <= 2; zz++ { biome := bs.biome(x+xx, z+zz) ix := biome.ColorIndex & 0xFF iy := biome.ColorIndex >> 8 col := img.NRGBAAt(ix, iy) r += int(col.R) g += int(col.G) b += int(col.B) count++ } } return byte(r / count), byte(g / count), byte(b / count) }
func rotate(im image.Image, angle int) image.Image { var rotated *image.NRGBA // trigonometric (i.e counter clock-wise) switch angle { case 90: newH, newW := im.Bounds().Dx(), im.Bounds().Dy() rotated = image.NewNRGBA(image.Rect(0, 0, newW, newH)) for y := 0; y < newH; y++ { for x := 0; x < newW; x++ { rotated.Set(x, y, im.At(newH-1-y, x)) } } case -90: newH, newW := im.Bounds().Dx(), im.Bounds().Dy() rotated = image.NewNRGBA(image.Rect(0, 0, newW, newH)) for y := 0; y < newH; y++ { for x := 0; x < newW; x++ { rotated.Set(x, y, im.At(y, newW-1-x)) } } case 180, -180: newW, newH := im.Bounds().Dx(), im.Bounds().Dy() rotated = image.NewNRGBA(image.Rect(0, 0, newW, newH)) for y := 0; y < newH; y++ { for x := 0; x < newW; x++ { rotated.Set(x, y, im.At(newW-1-x, newH-1-y)) } } default: return im } return rotated }
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) } } }