mirror of
https://github.com/talgo-cloud/talgo-libwebp.git
synced 2026-03-07 21:48:16 -08:00
Merge pull request #8 from saturday06/feature/rgb_encode
Enable encode RGB image
This commit is contained in:
commit
b8bf24acf4
3 changed files with 161 additions and 0 deletions
|
|
@ -116,6 +116,8 @@ func EncodeRGBA(w io.Writer, img image.Image, c Config) (err error) {
|
|||
pic.writer = C.WebPWriterFunction(C.writeWebP)
|
||||
|
||||
switch p := img.(type) {
|
||||
case *RGBImage:
|
||||
C.WebPPictureImportRGB(pic, (*C.uint8_t)(&p.Pix[0]), C.int(p.Stride))
|
||||
case *image.RGBA:
|
||||
C.WebPPictureImportRGBA(pic, (*C.uint8_t)(&p.Pix[0]), C.int(p.Stride))
|
||||
case *image.NRGBA:
|
||||
|
|
|
|||
79
webp/rgb_image.go
Normal file
79
webp/rgb_image.go
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
package webp
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
)
|
||||
|
||||
// RGBImage represent image data which has RGB colors.
|
||||
// RGBImage is compatible with image.RGBA, but does not have alpha channel to reduce using memory.
|
||||
type RGBImage struct {
|
||||
// Pix holds the image's stream, in R, G, B order.
|
||||
Pix []uint8
|
||||
// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
|
||||
Stride int
|
||||
// Rect is the image's bounds.
|
||||
Rect image.Rectangle
|
||||
}
|
||||
|
||||
// NewRGBImage allocates and returns RGB image
|
||||
func NewRGBImage(r image.Rectangle) *RGBImage {
|
||||
w, h := r.Dx(), r.Dy()
|
||||
return &RGBImage{Pix: make([]uint8, 3*w*h), Stride: 3 * w, Rect: r}
|
||||
}
|
||||
|
||||
// ColorModel returns RGB color model.
|
||||
func (p *RGBImage) ColorModel() color.Model {
|
||||
return RGBModel
|
||||
}
|
||||
|
||||
// Bounds implements image.Image.At
|
||||
func (p *RGBImage) Bounds() image.Rectangle {
|
||||
return p.Rect
|
||||
}
|
||||
|
||||
// At implements image.Image.At
|
||||
func (p *RGBImage) At(x, y int) color.Color {
|
||||
return p.RGBAAt(x, y)
|
||||
}
|
||||
|
||||
// RGBAAt returns the color of the pixel at (x, y) as RGBA.
|
||||
func (p *RGBImage) RGBAAt(x, y int) color.RGBA {
|
||||
if !(image.Point{x, y}.In(p.Rect)) {
|
||||
return color.RGBA{}
|
||||
}
|
||||
i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*3
|
||||
return color.RGBA{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], 0xFF}
|
||||
}
|
||||
|
||||
// RGBModel is RGB color model instance
|
||||
var RGBModel = color.ModelFunc(rgbModel)
|
||||
|
||||
func rgbModel(c color.Color) color.Color {
|
||||
if _, ok := c.(RGB); ok {
|
||||
return c
|
||||
}
|
||||
r, g, b, _ := c.RGBA()
|
||||
return RGB{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8)}
|
||||
}
|
||||
|
||||
// RGB color
|
||||
type RGB struct {
|
||||
R, G, B uint8
|
||||
}
|
||||
|
||||
// RGBA implements Color.RGBA
|
||||
func (c RGB) RGBA() (r, g, b, a uint32) {
|
||||
r = uint32(c.R)
|
||||
r |= r << 8
|
||||
g = uint32(c.G)
|
||||
g |= g << 8
|
||||
b = uint32(c.B)
|
||||
b |= b << 8
|
||||
a = uint32(0xFFFF)
|
||||
return
|
||||
}
|
||||
|
||||
// Make sure RGBImage implements image.Image.
|
||||
// See https://golang.org/doc/effective_go.html#blank_implements.
|
||||
var _ image.Image = new(RGBImage)
|
||||
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"github.com/harukasan/go-libwebp/test/util"
|
||||
"github.com/harukasan/go-libwebp/webp"
|
||||
"image/color"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
|
@ -170,6 +171,28 @@ func TestEncodeRGBA(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestEncodeRGB(t *testing.T) {
|
||||
img := util.ReadPNG("yellow-rose-3.png")
|
||||
|
||||
config := webp.Config{
|
||||
Preset: webp.PresetDefault,
|
||||
Quality: 100,
|
||||
Method: 6,
|
||||
}
|
||||
|
||||
f := util.CreateFile("TestEncodeRGB.webp")
|
||||
w := bufio.NewWriter(f)
|
||||
defer func() {
|
||||
w.Flush()
|
||||
f.Close()
|
||||
}()
|
||||
|
||||
if err := webp.EncodeRGBA(w, img, config); err != nil {
|
||||
t.Errorf("Got Error: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeYUVA(t *testing.T) {
|
||||
data := util.ReadFile("cosmos.webp")
|
||||
options := &webp.DecoderOptions{}
|
||||
|
|
@ -198,3 +221,60 @@ func TestEncodeYUVA(t *testing.T) {
|
|||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestImageInterface(t *testing.T) {
|
||||
rect := image.Rect(0, 0, 100, 100)
|
||||
img := webp.NewRGBImage(rect)
|
||||
|
||||
if got := img.ColorModel(); got != webp.RGBModel {
|
||||
t.Errorf("ColorModel() should return rgb.ColorModel, got: %v", got)
|
||||
}
|
||||
|
||||
if got := img.Bounds(); got != rect {
|
||||
t.Errorf("Bounds() should return %v, got: %v", rect, got)
|
||||
}
|
||||
|
||||
black := color.RGBA{0x00, 0x00, 0x00, 0xFF}
|
||||
if got := img.At(0, 0); got != black {
|
||||
t.Errorf("At(0, 0) should return %v, got: %v", black, got)
|
||||
}
|
||||
|
||||
blank := color.RGBA{}
|
||||
if got := img.At(-1, -1); got != blank {
|
||||
t.Errorf("At(0, 0) should return %v, got: %v", blank, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertFromRGBA(t *testing.T) {
|
||||
rgba := color.RGBA{0x11, 0x22, 0x33, 0xFF}
|
||||
expect := webp.RGB{0x11, 0x22, 0x33}
|
||||
if got := webp.RGBModel.Convert(rgba); got != expect {
|
||||
t.Errorf("got: %v, expect: %v", got, expect)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertFromRGB(t *testing.T) {
|
||||
c := webp.RGB{0x11, 0x22, 0x33}
|
||||
if got := webp.RGBModel.Convert(c); got != c {
|
||||
t.Errorf("got: %v, expect: %v", got, c)
|
||||
}
|
||||
}
|
||||
|
||||
func TestColorRGBA(t *testing.T) {
|
||||
c := webp.RGB{0x11, 0x22, 0x33}
|
||||
r, g, b, a := uint32(0x1111), uint32(0x2222), uint32(0x3333), uint32(0xFFFF)
|
||||
|
||||
gotR, gotG, gotB, gotA := c.RGBA()
|
||||
if gotR != r {
|
||||
t.Errorf("got R: %v, expect R: %v", gotR, r)
|
||||
}
|
||||
if gotG != g {
|
||||
t.Errorf("got G: %v, expect G: %v", gotG, g)
|
||||
}
|
||||
if gotB != b {
|
||||
t.Errorf("got B: %v, expect B: %v", gotB, b)
|
||||
}
|
||||
if gotA != a {
|
||||
t.Errorf("got A: %v, expect A: %v", gotA, a)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue