diff --git a/imagedata.go b/imagedata.go new file mode 100644 index 0000000..7d789a3 --- /dev/null +++ b/imagedata.go @@ -0,0 +1,95 @@ +package canvas + +import ( + "image" + "image/color" + "unsafe" +) + +var imageBufTex uint32 +var imageBuf []byte + +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 +} + +func (cv *Canvas) PutImageData(img *image.RGBA, x, y int) { + cv.activate() + + if imageBufTex == 0 { + gli.GenTextures(1, &imageBufTex) + } + gli.ActiveTexture(gl_TEXTURE0) + 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) + + 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) + + dx0, dy0 := dx*2/cv.fw-1, -dy*2/cv.fh+1 + dx1, dy1 := dx0, -(dy+dh)*2/cv.fh+1 + dx2, dy2 := (dx+dw)*2/cv.fw-1, dy1 + dx3, dy3 := dx2, dy0 + + gli.UseProgram(tr.id) + gli.Uniform1i(tr.image, 0) + + gli.BindBuffer(gl_ARRAY_BUFFER, buf) + data := [16]float32{dx0, dy0, dx1, dy1, dx2, dy2, dx3, dy3, + 0, 0, 0, 1, 1, 1, 1, 0} + gli.BufferData(gl_ARRAY_BUFFER, len(data)*4, unsafe.Pointer(&data[0]), gl_STREAM_DRAW) + + gli.VertexAttribPointer(tr.vertex, 2, gl_FLOAT, false, 0, nil) + gli.VertexAttribPointer(tr.texCoord, 2, gl_FLOAT, false, 0, gli.PtrOffset(8*4)) + gli.EnableVertexAttribArray(tr.vertex) + gli.EnableVertexAttribArray(tr.texCoord) + gli.DrawArrays(gl_TRIANGLE_FAN, 0, 4) + gli.DisableVertexAttribArray(tr.vertex) + gli.DisableVertexAttribArray(tr.texCoord) +}