moved image data code into backend
This commit is contained in:
parent
e7d0b1a7ee
commit
fc4d3dbd9e
5 changed files with 116 additions and 99 deletions
|
@ -19,6 +19,9 @@ type Backend interface {
|
|||
Fill(style *FillStyle, pts [][2]float64)
|
||||
DrawImage(dimg Image, sx, sy, sw, sh, dx, dy, dw, dh float64, alpha float64)
|
||||
FillImageMask(style *FillStyle, mask *image.Alpha, pts [][2]float64) // pts must have four points
|
||||
|
||||
GetImageData(x, y, w, h int) *image.RGBA
|
||||
PutImageData(img *image.RGBA, x, y int)
|
||||
}
|
||||
|
||||
// FillStyle is the color and other details on how to fill
|
||||
|
|
|
@ -20,6 +20,7 @@ type GoGLBackend struct {
|
|||
buf uint32
|
||||
shadowBuf uint32
|
||||
alphaTex uint32
|
||||
|
||||
sr solidShader
|
||||
lgr linearGradientShader
|
||||
rgr radialGradientShader
|
||||
|
@ -32,11 +33,16 @@ type GoGLBackend struct {
|
|||
gauss15r gaussianShader
|
||||
gauss63r gaussianShader
|
||||
gauss127r gaussianShader
|
||||
offscr1 offscreenBuffer
|
||||
offscr2 offscreenBuffer
|
||||
glChan chan func()
|
||||
|
||||
offscr1 offscreenBuffer
|
||||
offscr2 offscreenBuffer
|
||||
|
||||
imageBufTex uint32
|
||||
imageBuf []byte
|
||||
|
||||
ptsBuf []float32
|
||||
|
||||
glChan chan func()
|
||||
}
|
||||
|
||||
type offscreenBuffer struct {
|
||||
|
|
94
backend/gogl/imagedata.go
Normal file
94
backend/gogl/imagedata.go
Normal file
|
@ -0,0 +1,94 @@
|
|||
package goglbackend
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"unsafe"
|
||||
|
||||
"github.com/go-gl/gl/v3.2-core/gl"
|
||||
)
|
||||
|
||||
// GetImageData returns an RGBA image of the current image
|
||||
func (b *GoGLBackend) GetImageData(x, y, w, h int) *image.RGBA {
|
||||
// cv.activate()
|
||||
|
||||
if x < 0 {
|
||||
w += x
|
||||
x = 0
|
||||
}
|
||||
if y < 0 {
|
||||
h += y
|
||||
y = 0
|
||||
}
|
||||
if w > b.w {
|
||||
w = b.w
|
||||
}
|
||||
if h > b.h {
|
||||
h = b.h
|
||||
}
|
||||
if len(b.imageBuf) < w*h*3 {
|
||||
b.imageBuf = make([]byte, w*h*3)
|
||||
}
|
||||
|
||||
gl.ReadPixels(int32(x), int32(y), int32(w), int32(h), gl.RGB, gl.UNSIGNED_BYTE, gl.Ptr(&b.imageBuf[0]))
|
||||
rgba := image.NewRGBA(image.Rect(x, y, x+w, y+h))
|
||||
bp := 0
|
||||
for cy := y; cy < y+h; cy++ {
|
||||
for cx := x; cx < x+w; cx++ {
|
||||
rgba.SetRGBA(cx, y+h-1-cy, color.RGBA{R: b.imageBuf[bp], G: b.imageBuf[bp+1], B: b.imageBuf[bp+2], A: 255})
|
||||
bp += 3
|
||||
}
|
||||
}
|
||||
return rgba
|
||||
}
|
||||
|
||||
// PutImageData puts the given image at the given x/y coordinates
|
||||
func (b *GoGLBackend) PutImageData(img *image.RGBA, x, y int) {
|
||||
// cv.activate()
|
||||
|
||||
gl.ActiveTexture(gl.TEXTURE0)
|
||||
if b.imageBufTex == 0 {
|
||||
gl.GenTextures(1, &b.imageBufTex)
|
||||
gl.BindTexture(gl.TEXTURE_2D, b.imageBufTex)
|
||||
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)
|
||||
} else {
|
||||
gl.BindTexture(gl.TEXTURE_2D, b.imageBufTex)
|
||||
}
|
||||
|
||||
w, h := img.Bounds().Dx(), img.Bounds().Dy()
|
||||
|
||||
if img.Stride == img.Bounds().Dx()*4 {
|
||||
gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(w), int32(h), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(&img.Pix[0]))
|
||||
} else {
|
||||
data := make([]uint8, 0, w*h*4)
|
||||
for cy := 0; cy < h; cy++ {
|
||||
start := cy * img.Stride
|
||||
end := start + w*4
|
||||
data = append(data, img.Pix[start:end]...)
|
||||
}
|
||||
gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(w), int32(h), 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.Ptr(&data[0]))
|
||||
}
|
||||
|
||||
dx, dy := float32(x), float32(y)
|
||||
dw, dh := float32(w), float32(h)
|
||||
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, b.buf)
|
||||
data := [16]float32{dx, dy, dx + dw, dy, dx + dw, dy + dh, dx, dy + dh,
|
||||
0, 0, 1, 0, 1, 1, 0, 1}
|
||||
gl.BufferData(gl.ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl.STREAM_DRAW)
|
||||
|
||||
gl.UseProgram(b.ir.ID)
|
||||
gl.Uniform1i(b.ir.Image, 0)
|
||||
gl.Uniform2f(b.ir.CanvasSize, float32(b.fw), float32(b.fh))
|
||||
gl.Uniform1f(b.ir.GlobalAlpha, 1)
|
||||
gl.VertexAttribPointer(b.ir.Vertex, 2, gl.FLOAT, false, 0, nil)
|
||||
gl.VertexAttribPointer(b.ir.TexCoord, 2, gl.FLOAT, false, 0, gl.PtrOffset(8*4))
|
||||
gl.EnableVertexAttribArray(b.ir.Vertex)
|
||||
gl.EnableVertexAttribArray(b.ir.TexCoord)
|
||||
gl.DrawArrays(gl.TRIANGLE_FAN, 0, 4)
|
||||
gl.DisableVertexAttribArray(b.ir.Vertex)
|
||||
gl.DisableVertexAttribArray(b.ir.TexCoord)
|
||||
}
|
96
imagedata.go
96
imagedata.go
|
@ -1,96 +0,0 @@
|
|||
package canvas
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var imageBufTex uint32
|
||||
var imageBuf []byte
|
||||
|
||||
// GetImageData returns an RGBA image of the currently displayed image. The
|
||||
// alpha channel is always opaque
|
||||
func (cv *Canvas) GetImageData(x, y, w, h int) *image.RGBA {
|
||||
cv.activate()
|
||||
|
||||
if x < 0 {
|
||||
w += x
|
||||
x = 0
|
||||
}
|
||||
if y < 0 {
|
||||
h += y
|
||||
y = 0
|
||||
}
|
||||
if w > cv.w {
|
||||
w = cv.w
|
||||
}
|
||||
if h > cv.h {
|
||||
h = cv.h
|
||||
}
|
||||
if len(imageBuf) < w*h*3 {
|
||||
imageBuf = make([]byte, w*h*3)
|
||||
}
|
||||
|
||||
gli.ReadPixels(int32(x), int32(y), int32(w), int32(h), gl_RGB, gl_UNSIGNED_BYTE, gli.Ptr(&imageBuf[0]))
|
||||
rgba := image.NewRGBA(image.Rect(x, y, x+w, y+h))
|
||||
bp := 0
|
||||
for cy := y; cy < y+h; cy++ {
|
||||
for cx := x; cx < x+w; cx++ {
|
||||
rgba.SetRGBA(cx, y+h-1-cy, color.RGBA{R: imageBuf[bp], G: imageBuf[bp+1], B: imageBuf[bp+2], A: 255})
|
||||
bp += 3
|
||||
}
|
||||
}
|
||||
return rgba
|
||||
}
|
||||
|
||||
// PutImageData puts the given image at the given x/y coordinates
|
||||
func (cv *Canvas) PutImageData(img *image.RGBA, x, y int) {
|
||||
cv.activate()
|
||||
|
||||
gli.ActiveTexture(gl_TEXTURE0)
|
||||
if imageBufTex == 0 {
|
||||
gli.GenTextures(1, &imageBufTex)
|
||||
gli.BindTexture(gl_TEXTURE_2D, imageBufTex)
|
||||
gli.TexParameteri(gl_TEXTURE_2D, gl_TEXTURE_MIN_FILTER, gl_LINEAR)
|
||||
gli.TexParameteri(gl_TEXTURE_2D, gl_TEXTURE_MAG_FILTER, gl_LINEAR)
|
||||
gli.TexParameteri(gl_TEXTURE_2D, gl_TEXTURE_WRAP_S, gl_CLAMP_TO_EDGE)
|
||||
gli.TexParameteri(gl_TEXTURE_2D, gl_TEXTURE_WRAP_T, gl_CLAMP_TO_EDGE)
|
||||
} else {
|
||||
gli.BindTexture(gl_TEXTURE_2D, imageBufTex)
|
||||
}
|
||||
|
||||
w, h := img.Bounds().Dx(), img.Bounds().Dy()
|
||||
|
||||
if img.Stride == img.Bounds().Dx()*4 {
|
||||
gli.TexImage2D(gl_TEXTURE_2D, 0, gl_RGBA, int32(w), int32(h), 0, gl_RGBA, gl_UNSIGNED_BYTE, gli.Ptr(&img.Pix[0]))
|
||||
} else {
|
||||
data := make([]uint8, 0, w*h*4)
|
||||
for cy := 0; cy < h; cy++ {
|
||||
start := cy * img.Stride
|
||||
end := start + w*4
|
||||
data = append(data, img.Pix[start:end]...)
|
||||
}
|
||||
gli.TexImage2D(gl_TEXTURE_2D, 0, gl_RGBA, int32(w), int32(h), 0, gl_RGBA, gl_UNSIGNED_BYTE, gli.Ptr(&data[0]))
|
||||
}
|
||||
|
||||
dx, dy := float32(x), float32(y)
|
||||
dw, dh := float32(w), float32(h)
|
||||
|
||||
gli.BindBuffer(gl_ARRAY_BUFFER, buf)
|
||||
data := [16]float32{dx, dy, dx + dw, dy, dx + dw, dy + dh, dx, dy + dh,
|
||||
0, 0, 1, 0, 1, 1, 0, 1}
|
||||
gli.BufferData(gl_ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl_STREAM_DRAW)
|
||||
|
||||
gli.UseProgram(ir.id)
|
||||
gli.Uniform1i(ir.image, 0)
|
||||
gli.Uniform2f(ir.canvasSize, float32(cv.fw), float32(cv.fh))
|
||||
gli.Uniform1f(ir.globalAlpha, 1)
|
||||
gli.VertexAttribPointer(ir.vertex, 2, gl_FLOAT, false, 0, 0)
|
||||
gli.VertexAttribPointer(ir.texCoord, 2, gl_FLOAT, false, 0, 8*4)
|
||||
gli.EnableVertexAttribArray(ir.vertex)
|
||||
gli.EnableVertexAttribArray(ir.texCoord)
|
||||
gli.DrawArrays(gl_TRIANGLE_FAN, 0, 4)
|
||||
gli.DisableVertexAttribArray(ir.vertex)
|
||||
gli.DisableVertexAttribArray(ir.texCoord)
|
||||
}
|
10
images.go
10
images.go
|
@ -172,3 +172,13 @@ func (cv *Canvas) DrawImage(image interface{}, coords ...float64) {
|
|||
|
||||
cv.b.DrawImage(img.img, sx, sy, sw, sh, dx, dy, dw, dh, cv.state.globalAlpha)
|
||||
}
|
||||
|
||||
// GetImageData returns an RGBA image of the current image
|
||||
func (cv *Canvas) GetImageData(x, y, w, h int) *image.RGBA {
|
||||
return cv.b.GetImageData(x, y, w, h)
|
||||
}
|
||||
|
||||
// PutImageData puts the given image at the given x/y coordinates
|
||||
func (cv *Canvas) PutImageData(img *image.RGBA, x, y int) {
|
||||
cv.b.PutImageData(img, x, y)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue