Added optional buffer for image Read()
This commit is contained in:
parent
9f884aeec1
commit
84476c3206
4 changed files with 63 additions and 6 deletions
|
@ -136,7 +136,13 @@ For the `SetFrameBuffer()` method, the `buffer` parameter must have a length of
|
||||||
|
|
||||||
## Images
|
## Images
|
||||||
|
|
||||||
Vidio provides some convenience functions for reading and writing to images using an array of bytes. Currently, only `png` and `jpeg` formats are supported.
|
Vidio provides some convenience functions for reading and writing to images using an array of bytes. Currently, only `png` and `jpeg` formats are supported. When reading images, an optional `buffer` can be passed in to avoid array reallocation.
|
||||||
|
|
||||||
|
```go
|
||||||
|
Read(filename string, buffer ...[]byte) (int, int, []byte, error)
|
||||||
|
Write(filename string, width, height int, buffer []byte) error
|
||||||
|
```
|
||||||
|
```
|
||||||
|
|
||||||
```go
|
```go
|
||||||
w, h, img, err := vidio.Read("input.png")
|
w, h, img, err := vidio.Read("input.png")
|
||||||
|
|
20
imageio.go
20
imageio.go
|
@ -1,6 +1,8 @@
|
||||||
package vidio
|
package vidio
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -13,7 +15,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reads an image from a file. Currently only supports png and jpeg.
|
// Reads an image from a file. Currently only supports png and jpeg.
|
||||||
func Read(filename string) (int, int, []byte, error) {
|
func Read(filename string, buffer ...[]byte) (int, int, []byte, error) {
|
||||||
f, err := os.Open(filename)
|
f, err := os.Open(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, nil, err
|
return 0, 0, nil, err
|
||||||
|
@ -28,7 +30,16 @@ func Read(filename string) (int, int, []byte, error) {
|
||||||
bounds := image.Bounds().Max
|
bounds := image.Bounds().Max
|
||||||
size := bounds.X * bounds.Y * 3
|
size := bounds.X * bounds.Y * 3
|
||||||
|
|
||||||
data := make([]byte, size)
|
var data []byte
|
||||||
|
if len(buffer) > 0 {
|
||||||
|
if len(buffer[0]) < size {
|
||||||
|
errmsg := fmt.Sprintf("Buffer size (%d) is smaller than image size (%d)", len(buffer[0]), size)
|
||||||
|
return 0, 0, nil, errors.New(errmsg)
|
||||||
|
}
|
||||||
|
data = buffer[0]
|
||||||
|
} else {
|
||||||
|
data = make([]byte, size, size)
|
||||||
|
}
|
||||||
|
|
||||||
index := 0
|
index := 0
|
||||||
for h := 0; h < bounds.Y; h++ {
|
for h := 0; h < bounds.Y; h++ {
|
||||||
|
@ -47,17 +58,18 @@ func Read(filename string) (int, int, []byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes an image to a file. Currently only supports png and jpeg.
|
// Writes an image to a file. Currently only supports png and jpeg.
|
||||||
func Write(filename string, width, height int, data []byte) error {
|
func Write(filename string, width, height int, buffer []byte) error {
|
||||||
f, err := os.Create(filename)
|
f, err := os.Create(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
image := image.NewRGBA(image.Rect(0, 0, width, height))
|
image := image.NewRGBA(image.Rect(0, 0, width, height))
|
||||||
index := 0
|
index := 0
|
||||||
for h := 0; h < height; h++ {
|
for h := 0; h < height; h++ {
|
||||||
for w := 0; w < width; w++ {
|
for w := 0; w < width; w++ {
|
||||||
r, g, b := data[index], data[index+1], data[index+2]
|
r, g, b := buffer[index], buffer[index+1], buffer[index+2]
|
||||||
image.Set(w, h, color.RGBA{r, g, b, 255})
|
image.Set(w, h, color.RGBA{r, g, b, 255})
|
||||||
index += 3
|
index += 3
|
||||||
}
|
}
|
||||||
|
|
BIN
test/bananas.jpg
Normal file
BIN
test/bananas.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
|
@ -6,7 +6,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func assertEquals(expected, actual interface{}) {
|
func assertEquals(actual, expected interface{}) {
|
||||||
if expected != actual {
|
if expected != actual {
|
||||||
panic(fmt.Sprintf("Expected %v, got %v", expected, actual))
|
panic(fmt.Sprintf("Expected %v, got %v", expected, actual))
|
||||||
}
|
}
|
||||||
|
@ -226,3 +226,42 @@ At least one output file must be specified`,
|
||||||
|
|
||||||
fmt.Println("Webcam Parsing Test Passed")
|
fmt.Println("Webcam Parsing Test Passed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestImageRead(t *testing.T) {
|
||||||
|
w, h, img, err := Read("test/bananas.jpg")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(w, 200)
|
||||||
|
assertEquals(h, 133)
|
||||||
|
assertEquals(len(img), 200*133*3)
|
||||||
|
// [255 221 189 255 221 189 255 222 186 255]
|
||||||
|
assertEquals(img[0], uint8(255))
|
||||||
|
assertEquals(img[1], uint8(221))
|
||||||
|
assertEquals(img[2], uint8(189))
|
||||||
|
assertEquals(img[3], uint8(255))
|
||||||
|
assertEquals(img[4], uint8(221))
|
||||||
|
assertEquals(img[5], uint8(189))
|
||||||
|
assertEquals(img[6], uint8(255))
|
||||||
|
assertEquals(img[7], uint8(222))
|
||||||
|
assertEquals(img[8], uint8(186))
|
||||||
|
assertEquals(img[9], uint8(255))
|
||||||
|
|
||||||
|
fmt.Println("Image Reading Test Passed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestImageWrite(t *testing.T) {
|
||||||
|
w, h, img, err := Read("test/bananas.jpg")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = Write("test/bananas-out.png", w, h, img)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Remove("test/bananas-out.png")
|
||||||
|
|
||||||
|
fmt.Println("Image Writing Test Passed")
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue