ReadFrames updated to return RGBA image slice
This commit is contained in:
parent
a1d63d0f9f
commit
f6a2909ea3
3 changed files with 10 additions and 15 deletions
|
@ -16,7 +16,7 @@ go get github.com/AlexEidt/Vidio
|
||||||
|
|
||||||
The `Video` struct stores data about a video file you give it. The code below shows an example of sequentially reading the frames of the given video.
|
The `Video` struct stores data about a video file you give it. The code below shows an example of sequentially reading the frames of the given video.
|
||||||
|
|
||||||
Calling the `Read()` function will fill in the `Video` struct `framebuffer` with the next frame data as 8-bit RGBA data, stored in a flattened byte array in row-major order where each pixel is represented by four consecutive bytes representing the R, G, B and A components of that pixel. Note that the A (alpha) component will always be 255. When iteration over the entire video file is not required, we can lookup a specific frame by calling `ReadFrame(n int)`. By calling `ReadFrames(n ...int)`, we can immediately access multiple frames as `[][]byte` and skip the `framebuffer`.
|
Calling the `Read()` function will fill in the `Video` struct `framebuffer` with the next frame data as 8-bit RGBA data, stored in a flattened byte array in row-major order where each pixel is represented by four consecutive bytes representing the R, G, B and A components of that pixel. Note that the A (alpha) component will always be 255. When iteration over the entire video file is not required, we can lookup a specific frame by calling `ReadFrame(n int)`. By calling `ReadFrames(n ...int)`, we can immediately access multiple frames as a slice of RGBA images and skip the `framebuffer`.
|
||||||
|
|
||||||
```go
|
```go
|
||||||
vidio.NewVideo(filename string) (*vidio.Video, error)
|
vidio.NewVideo(filename string) (*vidio.Video, error)
|
||||||
|
@ -39,7 +39,7 @@ SetFrameBuffer(buffer []byte) error
|
||||||
|
|
||||||
Read() bool
|
Read() bool
|
||||||
ReadFrame(n int) error
|
ReadFrame(n int) error
|
||||||
ReadFrames(n ...int) ([][]byte, error)
|
ReadFrames(n ...int) ([]*image.RGBA, error)
|
||||||
Close()
|
Close()
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -208,12 +208,9 @@ video, _ := vidio.NewVideo("video.mp4")
|
||||||
|
|
||||||
frames, _ := video.ReadFrames(0, video.Frames() - 1)
|
frames, _ := video.ReadFrames(0, video.Frames() - 1)
|
||||||
|
|
||||||
img := image.NewRGBA(image.Rect(0, 0, video.Width(), video.Height()))
|
|
||||||
for index, frame := range frames {
|
for index, frame := range frames {
|
||||||
copy(img.Pix, frame)
|
|
||||||
|
|
||||||
f, _ := os.Create(fmt.Sprintf("%d.jpg", index))
|
f, _ := os.Create(fmt.Sprintf("%d.jpg", index))
|
||||||
jpeg.Encode(f, img, nil)
|
jpeg.Encode(f, frame, nil)
|
||||||
f.Close()
|
f.Close()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
11
video.go
11
video.go
|
@ -2,6 +2,7 @@ package vidio
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"image"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
@ -305,9 +306,9 @@ func (video *Video) ReadFrame(n int) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the N-amount of frames with the given indexes and return them as a slice of buffers. If one of
|
// Read the N-amount of frames with the given indexes and return them as a slice of RGBA image pointers. If one of
|
||||||
// the indexes is out of range, the function will return an error. The frames are indexes from 0.
|
// the indexes is out of range, the function will return an error. The frames are indexes from 0.
|
||||||
func (video *Video) ReadFrames(n ...int) ([][]byte, error) {
|
func (video *Video) ReadFrames(n ...int) ([]*image.RGBA, error) {
|
||||||
if len(n) == 0 {
|
if len(n) == 0 {
|
||||||
return nil, fmt.Errorf("vidio: no frames indexes specified")
|
return nil, fmt.Errorf("vidio: no frames indexes specified")
|
||||||
}
|
}
|
||||||
|
@ -358,11 +359,11 @@ func (video *Video) ReadFrames(n ...int) ([][]byte, error) {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
frames := make([][]byte, len(n))
|
frames := make([]*image.RGBA, len(n))
|
||||||
for frameIndex := range frames {
|
for frameIndex := range frames {
|
||||||
frames[frameIndex] = make([]byte, video.width*video.height*video.depth)
|
frames[frameIndex] = image.NewRGBA(image.Rect(0, 0, video.width, video.height))
|
||||||
|
|
||||||
if _, err := io.ReadFull(stdoutPipe, frames[frameIndex]); err != nil {
|
if _, err := io.ReadFull(stdoutPipe, frames[frameIndex].Pix); err != nil {
|
||||||
return nil, fmt.Errorf("vidio: failed to read the ffmpeg cmd result to the image buffer: %w", err)
|
return nil, fmt.Errorf("vidio: failed to read the ffmpeg cmd result to the image buffer: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -410,11 +410,8 @@ func TestReadFramesShouldReturnCorrectFrames(t *testing.T) {
|
||||||
t.Errorf("Failed to read frames: %s", err)
|
t.Errorf("Failed to read frames: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for index, buffer := range frames {
|
for index, actualFrame := range frames {
|
||||||
expectedFrame := expectedFrames[index]
|
expectedFrame := expectedFrames[index]
|
||||||
actualFrame := image.NewRGBA(image.Rect(0, 0, 480, 270))
|
|
||||||
copy(actualFrame.Pix, buffer)
|
|
||||||
|
|
||||||
for xIndex := 0; xIndex < expectedFrame.Bounds().Dx(); xIndex += 1 {
|
for xIndex := 0; xIndex < expectedFrame.Bounds().Dx(); xIndex += 1 {
|
||||||
for yIndex := 0; yIndex < expectedFrame.Bounds().Dy(); yIndex += 1 {
|
for yIndex := 0; yIndex < expectedFrame.Bounds().Dy(); yIndex += 1 {
|
||||||
eR, eG, eB, eA := expectedFrame.At(xIndex, yIndex).RGBA()
|
eR, eG, eB, eA := expectedFrame.At(xIndex, yIndex).RGBA()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue