//downsamples a source image as close as possible to a desired size, while also //maintaining a linear downsampling ratio. func downsample(img *image.RGBA, size image.Rectangle) *image.RGBA { xratio := int(img.Bounds().Max.X / size.Max.X) yratio := int(img.Bounds().Max.Y / size.Max.Y) minratio := xratio if yratio < xratio { minratio = yratio } xoffset := int((img.Bounds().Max.X - size.Max.X*minratio) / 2) yoffset := int((img.Bounds().Max.Y - size.Max.Y*minratio) / 2) out := image.NewRGBA(size) pixels := out.Pix for i := 0; i < size.Max.X; i++ { for j := 0; j < size.Max.Y; j++ { offset := 4 * (j*size.Max.X + i) r := image.Rect(i*minratio+xoffset, j*minratio+yoffset, (i+1)*minratio+xoffset, (j+1)*minratio+yoffset) c := averageColor(img, r) pixels[offset] = c.R pixels[offset+1] = c.G pixels[offset+2] = c.B pixels[offset+3] = 255 } } return out }
func (sgImage *SgImage) writeTransparentImage(img *image.RGBA, buffer []byte, length int) { width := img.Bounds().Dx() var i, x, y int for i < length { c := int(buffer[i]) i++ if c == 255 { // The next byte is the number of pixels to skip x += int(buffer[i]) i++ for x >= width { y++ x -= width } } else { // 'c' is the number of image data bytes for j := 0; j < c; j++ { sgImage.set555Pixel(img, x, y, uint16(buffer[i+1]<<8)|uint16(buffer[i])) x++ if x >= width { y++ x = 0 } i += 2 } } } }
func tileProcessor( subsampleF int, img *image.RGBA, in <-chan [2]int, wg *sync.WaitGroup, threadNum int, algo algos.AlgoFunc, ) { fmt.Fprintf(os.Stderr, "goroutine %d starting\n", threadNum) imgBounds := img.Bounds() yDelta := (constants.YMax - constants.YMin) / float64(imgBounds.Max.Y) xDelta := (constants.XMax - constants.XMin) / float64(imgBounds.Max.X) for d := range in { //fmt.Fprintf(os.Stderr, "Processing tile ((`%d`,`%d`),(`%d`,`%d`))\n", //py, px, py+constants.TileSize, px+constants.TileSize) //py, px := d[0], d[1] calculateTile(yDelta, xDelta, d[0], d[1], subsampleF, img, algo) } fmt.Fprintf(os.Stderr, "goroutine %d terminating\n", threadNum) wg.Done() }
func gaussianBlur(dst, src *image.RGBA, radius int) { boxes := determineBoxes(float64(radius), 3) tmp := image.NewRGBA(dst.Bounds()) boxBlur3(dst, tmp, src, (boxes[0]-1)/2) boxBlur3(dst, tmp, dst, (boxes[1]-1)/2) boxBlur3(dst, tmp, dst, (boxes[2]-1)/2) }
func (sgImage *SgImage) loadAlphaMask(img *image.RGBA, buffer []byte) { width := img.Bounds().Dx() length := int(sgImage.workRecord.AlphaLength) var i, x, y int for i < length { c := int(buffer[i]) i++ if c == 255 { // The next byte is the number of pixels to skip x += int(buffer[i]) i++ for x >= width { y++ x -= width } } else { // 'c' is the number of image data bytes for j := 0; j < c; j++ { sgImage.setAlphaPixel(img, x, y, buffer[i]) x++ if x >= width { y++ x = 0 } i += 2 } } } }
// 将图片绘制到图片 func ImageDrawRGBA(img *image.RGBA, imgcode image.Image, x, y int) { // 绘制图像 // image.Point A点的X,Y坐标,轴向右和向下增加{0,0} // image.ZP ZP is the zero Point // image.Pt Pt is shorthand for Point{X, Y} draw.Draw(img, img.Bounds(), imgcode, image.Pt(x, y), draw.Over) }
func (sgImage *SgImage) writeIsometricBase(img *image.RGBA, buffer []byte) error { width := img.Bounds().Dx() height := (width + 2) / 2 /* 58 -> 30, 118 -> 60, etc */ heightOffset := img.Bounds().Dy() - height var size int size = int(sgImage.workRecord.Flags[3]) yOffset := heightOffset var xOffset, tileBytes, tileHeight, tileWidth int if size == 0 { /* Derive the tile size from the height (more regular than width) * Note that this causes a problem with 4x4 regular vs 3x3 large: * 4 * 30 = 120; 3 * 40 = 120 -- give precedence to regular */ if height%ISOMETRIC_TILE_HEIGHT == 0 { size = height / ISOMETRIC_TILE_HEIGHT } else if height%ISOMETRIC_LARGE_TILE_HEIGHT == 0 { size = height / ISOMETRIC_LARGE_TILE_HEIGHT } } // Determine whether we should use the regular or large (emperor) tiles if ISOMETRIC_TILE_HEIGHT*size == height { // Regular tile tileBytes = ISOMETRIC_TILE_BYTES tileHeight = ISOMETRIC_TILE_HEIGHT tileWidth = ISOMETRIC_TILE_WIDTH } else if ISOMETRIC_LARGE_TILE_HEIGHT*size == height { // Large (emperor) tile tileBytes = ISOMETRIC_LARGE_TILE_BYTES tileHeight = ISOMETRIC_LARGE_TILE_HEIGHT tileWidth = ISOMETRIC_LARGE_TILE_WIDTH } else { return fmt.Errorf("Unknown tile size: %d (height %d, width %d, size %d)", 2*height/size, height, width, size) } // Check if buffer length is enough: (width + 2) * height / 2 * 2bpp if (width+2)*height != int(sgImage.workRecord.UncompressedLength) { return fmt.Errorf("Data length doesn't match footprint size: %d vs %d (%d) %d", (width+2)*height, sgImage.workRecord.UncompressedLength, sgImage.workRecord.Length, sgImage.workRecord.InvertOffset) } i := 0 for y := 0; y < (size + (size - 1)); y++ { var xRange int if y < size { xOffset = size - y - 1 xRange = y + 1 } else { xOffset = y - size + 1 xRange = 2*size - y - 1 } xOffset *= tileHeight for x := 0; x < xRange; x++ { sgImage.writeIsometricTile(img, buffer[i*tileBytes:], xOffset, yOffset, tileWidth, tileHeight) xOffset += tileWidth + 2 i++ } yOffset += tileHeight / 2 } return nil }
// loadFont loads the given font data. This does not deal with font scaling. // Scaling should be handled by the independent Bitmap/Truetype loaders. // We therefore expect the supplied image and charset to already be adjusted // to the correct font scale. // // The image should hold a sprite sheet, defining the graphical layout for // every glyph. The config describes font metadata. func loadFont(img *image.RGBA, config *FontConfig) (f *Font, err error) { f = new(Font) f.Config = config // Resize image to next power-of-two. img = glh.Pow2Image(img).(*image.RGBA) ib := img.Bounds() f.Width = ib.Dx() f.Height = ib.Dy() // Create the texture itself. It will contain all glyphs. // Individual glyph-quads display a subset of this texture. f.Texture = gl.GenTexture() f.Texture.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.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, ib.Dx(), ib.Dy(), 0, gl.RGBA, gl.UNSIGNED_BYTE, img.Pix) // file, err := os.Create("font.png") // if err != nil { // log.Fatal(err) // } // err = png.Encode(file, img) // if err != nil { // log.Fatal(err) // } return }
func drawGradient(m *image.RGBA) { b := m.Bounds() for y := b.Min.Y; y < b.Max.Y; y++ { for x := b.Min.X; x < b.Max.X; x++ { if x%64 == 0 || y%64 == 0 { m.SetRGBA(x, y, color.RGBA{0xff, 0xff, 0xff, 0xff}) } else if x%64 == 63 || y%64 == 63 { m.SetRGBA(x, y, color.RGBA{0x00, 0x00, 0xff, 0xff}) } else { m.SetRGBA(x, y, color.RGBA{uint8(x), uint8(y), 0x00, 0xff}) } } } // Round off the corners. const radius = 64 lox := b.Min.X + radius - 1 loy := b.Min.Y + radius - 1 hix := b.Max.X - radius hiy := b.Max.Y - radius for y := 0; y < radius; y++ { for x := 0; x < radius; x++ { if x*x+y*y <= radius*radius { continue } m.SetRGBA(lox-x, loy-y, color.RGBA{}) m.SetRGBA(hix+x, loy-y, color.RGBA{}) m.SetRGBA(lox-x, hiy+y, color.RGBA{}) m.SetRGBA(hix+x, hiy+y, color.RGBA{}) } } }
//func loadSize(ctxt *fs.Context, name string, max int) *image.RGBA func loadSize(name string, max int) *image.RGBA { //data, _, err := ctxt.Read("qr/upload/" + name + ".png") f1, err := os.Open(name + ".png") fmt.Println(name + ".png") if err != nil { panic(err) } i, err := png.Decode(f1) if err != nil { panic(err) } b := i.Bounds() fmt.Printf("%v, %v,max%v", b.Dx(), b.Dy(), max) dx, dy := max, max if b.Dx() > b.Dy() { dy = b.Dy() * dx / b.Dx() } else { dx = b.Dx() * dy / b.Dy() } fmt.Printf("%v, %v,", dx, dy) var irgba *image.RGBA switch i := i.(type) { case *image.RGBA: irgba = resize.ResizeRGBA(i, i.Bounds(), dx, dy) case *image.NRGBA: irgba = resize.ResizeNRGBA(i, i.Bounds(), dx, dy) default: fmt.Println("default") } fmt.Println("prereturnload") fmt.Printf("%v, %v,", irgba.Bounds().Dx(), irgba.Bounds().Dy()) return irgba }
func (t *Texture) FromImageRGBA(rgba *image.RGBA, level int) { With(t, func() { gl.TexImage2D(gl.TEXTURE_2D, level, gl.RGBA, rgba.Bounds().Dx(), rgba.Bounds().Dy(), 0, gl.RGBA, gl.UNSIGNED_BYTE, rgba.Pix) }) }
//accepts a source image and a sub-rectangle, and returns the average of //the rgb colors within this rectangle func averageColor(img *image.RGBA, rect image.Rectangle) color.RGBA { var rSum float64 var gSum float64 var bSum float64 var count float64 pixels := img.Pix stride := img.Bounds().Max.X for i := rect.Min.X; i < rect.Max.X; i++ { for j := rect.Min.Y; j < rect.Max.Y; j++ { offset := 4 * (j*stride + i) rSum += sRGBtoLinear(pixels[offset]) gSum += sRGBtoLinear(pixels[offset+1]) bSum += sRGBtoLinear(pixels[offset+2]) count++ } } return color.RGBA{lineartosRGB(rSum / count), lineartosRGB(gSum / count), lineartosRGB(bSum / count), 255} }
// Image builds an image.RGBA type with 6 by 6 quadrants of alternate colors. func Image(m *image.RGBA, key string, colors []color.RGBA) { size := m.Bounds().Size() squares := 6 quad := size.X / squares middle := math.Ceil(float64(squares) / float64(2)) colorMap := make(map[int]color.RGBA) var currentYQuadrand = 0 for y := 0; y < size.Y; y++ { yQuadrant := y / quad if yQuadrant != currentYQuadrand { // when y quadrant changes, clear map colorMap = make(map[int]color.RGBA) currentYQuadrand = yQuadrant } for x := 0; x < size.X; x++ { xQuadrant := x / quad if _, ok := colorMap[xQuadrant]; !ok { if float64(xQuadrant) < middle { colorMap[xQuadrant] = draw.PickColor(key, colors, xQuadrant+3*yQuadrant) } else if xQuadrant < squares { colorMap[xQuadrant] = colorMap[squares-xQuadrant-1] } else { colorMap[xQuadrant] = colorMap[0] } } m.Set(x, y, colorMap[xQuadrant]) } } }
func NewTiledImage(img *image.RGBA, tileSize image.Point) *TiledImage { b := img.Bounds() nx := b.Dx() / tileSize.X ny := b.Dy() / tileSize.Y tiles := make([]TileInfo, nx*ny) for j := 0; j < ny; j++ { y := b.Min.Y + j*tileSize.Y for i := 0; i < nx; i++ { x := b.Min.X + i*tileSize.X rect := image.Rect(x, y, x+tileSize.X, y+tileSize.Y) k := i + j*nx tiles[k].subImage = img.SubImage(rect).(*image.RGBA) tiles[k].dist2 = math.MaxFloat32 } } return &TiledImage{ data: tiles, nx: nx, ny: ny, sx: tileSize.X, sy: tileSize.Y, } }
func getRGBA(src *image.RGBA, x, y, borderMethod int) (r, g, b, a uint8) { bound := src.Bounds() if x < 0 { switch borderMethod { case BORDER_COPY: x = 0 default: return 0, 0, 0, 0 } } else if x >= bound.Max.X { switch borderMethod { case BORDER_COPY: x = bound.Max.X - 1 default: return 0, 0, 0, 0 } } if y < 0 { switch borderMethod { case BORDER_COPY: y = 0 default: return 0, 0, 0, 0 } } else if y >= bound.Max.Y { switch borderMethod { case BORDER_COPY: y = bound.Max.Y - 1 default: return 0, 0, 0, 0 } } i := (y-bound.Min.Y)*src.Stride + (x-bound.Min.X)*4 return src.Pix[i], src.Pix[i+1], src.Pix[i+2], src.Pix[i+3] }
func constructPixelArray(img *image.RGBA) []Rgb { rgbaImg := image.NewRGBA(img.Bounds()) draw.Draw(rgbaImg, rgbaImg.Bounds(), img, image.ZP, draw.Src) pixelArray := make([]Rgb, 0, 50) var rgbVal = Rgb{} for i, pix := range rgbaImg.Pix { switch i % 4 { case 0: rgbVal.R = pix case 1: rgbVal.G = pix case 2: rgbVal.B = pix case 3: if pix >= minTransparency && isOpaque(rgbVal) { pixelArray = append(pixelArray, rgbVal) rgbVal = Rgb{} } } } return pixelArray }
func (buffer Image) CopyRGBA(src *image.RGBA, r image.Rectangle) { // clip r against each image's bounds and move sp accordingly (see draw.clip()) sp := image.ZP orig := r.Min r = r.Intersect(buffer.Bounds()) r = r.Intersect(src.Bounds().Add(orig.Sub(sp))) dx := r.Min.X - orig.X dy := r.Min.Y - orig.Y (sp).X += dx (sp).Y += dy i0 := (r.Min.X - buffer.Rect.Min.X) * 4 i1 := (r.Max.X - buffer.Rect.Min.X) * 4 si0 := (sp.X - src.Rect.Min.X) * 4 yMax := r.Max.Y - buffer.Rect.Min.Y y := r.Min.Y - buffer.Rect.Min.Y sy := sp.Y - src.Rect.Min.Y for ; y != yMax; y, sy = y+1, sy+1 { dpix := buffer.Pix[y*buffer.Stride:] spix := src.Pix[sy*src.Stride:] for i, si := i0, si0; i < i1; i, si = i+4, si+4 { dpix[i+0] = spix[si+2] dpix[i+1] = spix[si+1] dpix[i+2] = spix[si+0] dpix[i+3] = spix[si+3] } } }
func drawGradient(m *image.RGBA) { b := m.Bounds() for y := b.Min.Y; y < b.Max.Y; y++ { for x := b.Min.X; x < b.Max.X; x++ { m.SetRGBA(x, y, color.RGBA{uint8(x), uint8(y), 0x00, 0xff}) } } }
// draw src centered within dst func drawCentered(dst *image.RGBA, src image.Image) { srcDx := src.Bounds().Dx() srcDy := src.Bounds().Dy() x := (dst.Bounds().Dx() - srcDx) / 2 y := (dst.Bounds().Dy() - srcDy) / 2 dstRect := image.Rect(x, y, x+srcDx, y+srcDy) draw.Draw(dst, dstRect, src, src.Bounds().Min, draw.Src) }
func RGBAToMatrix(img *image.RGBA) mat64.Matrix { bounds := img.Bounds() imgSize := bounds.Size() rows := imgSize.X * imgSize.Y imgMatrix := mat64.NewDense(rows, 4, convertPixToFloat64(img.Pix)) return imgMatrix }
func drawPoint(m *image.RGBA, x float32, y float32) { b := m.Bounds() height := float32(b.Max.Y) width := float32(b.Max.X) scale := float32(height / 11) y = (height - 25) - (scale * y) x = (width / 2) + (scale * x) m.Set(int(x), int(y), color.RGBA{0, 255, 0, 255}) }
// Make a new canvas of size w x h. func NewCanvas(img *image.RGBA) *Canvas { c := new(Canvas) c.RGBA = img c.RGBAPainter = raster.NewRGBAPainter(c.RGBA) c.rasterizer = raster.NewRasterizer(img.Bounds().Max.X, img.Bounds().Max.Y) c.rasterizer.UseNonZeroWinding = true c.SetColor(color.RGBA{0, 0, 0, 100}) return c }
func (t *Tiler) newTypeContext(im *image.RGBA, color color.RGBA) *freetype.Context { c := freetype.NewContext() c.SetDPI(72) c.SetFont(t.font) c.SetFontSize(t.FontSize) c.SetClip(im.Bounds()) c.SetDst(im) c.SetSrc(image.NewUniform(color)) return c }
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 NewPictureFromRGBA(img *image.RGBA) *Picture { p := NewPicture(img.Bounds()) p.Each(func(x, y int) { c := img.RGBAAt(x, y) l := p.Luma(c) p.Set(x, y, l) }) return p }
func (w *World) UploadRGBAImage(img *image.RGBA) gltext.Texture { t := new(texture) ib := img.Bounds() t.bounds = ib gl.GenTextures(1, &t.id) gl.BindTexture(gl.TEXTURE_2D, t.id) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.Sizei(ib.Dx()), gl.Sizei(ib.Dy()), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Void(&img.Pix[0])) return t }
func uploadTexture(img *image.RGBA) gl.Texture { gl.Enable(gl.TEXTURE_2D) tex := gl.GenTexture() tex.Bind(gl.TEXTURE_2D) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) gl.TexImage2D(gl.TEXTURE_2D, 0, 4, img.Bounds().Max.X, img.Bounds().Max.Y, 0, gl.RGBA, gl.UNSIGNED_BYTE, img.Pix) gl.Disable(gl.TEXTURE_2D) return tex }
// Palette builds an JPEG image with all the colors present in the theme color array. func Palette(m *image.RGBA, theme []color.RGBA) { size := m.Bounds().Size() numColors := len(theme) quadrant := size.X / numColors for x := 0; x < size.X; x++ { currentQuadrant := (x / quadrant) % numColors for y := 0; y < size.Y; y++ { m.Set(x, y, theme[currentQuadrant]) } } }
func Raytracer(scene *Scene, img *image.RGBA) { var c color.RGBA b := img.Bounds() for y := b.Min.Y; y < b.Max.Y; y++ { for x := b.Min.X; x < b.Max.X; x++ { c = calc(x, y) img.Set(x, y, c) } } }
func (wf *WindowFoundation) handleWindowDrawing() { waitingForRepaint := false newStuff := false var scrBuf *image.RGBA var invalidRects RectSet for { select { case pane := <-wf.paneCh: wf.setPane(pane) case inv := <-wf.Invalidations: invalidRects = append(invalidRects, inv.Bounds...) if waitingForRepaint { newStuff = true } else { waitingForRepaint = true newStuff = true time.AfterFunc(FrameDelay, func() { wf.doRepaintWindow <- true }) } case <-wf.doRepaintWindow: waitingForRepaint = false if !newStuff { break } scr := wf.W.Screen() if scrBuf == nil || scr.Bounds() != scrBuf.Bounds() { scrBuf = image.NewRGBA(scr.Bounds()) invalidRects = RectSet{wf.Bounds()} } // Report("window drawing starting") wf.Drawer.Draw(scrBuf, invalidRects) // Report("window drawing done") var srs []image.Rectangle for _, ir := range invalidRects { sr := RectangleForRect(ir) si := scrBuf.SubImage(sr) srs = append(srs, sr) draw.Draw(scr, scr.Bounds(), si, image.Point{}, draw.Src) } invalidRects = invalidRects[:0] wf.W.FlushImage(srs...) newStuff = false } } }