diff --git a/webp/encode.go b/webp/encode.go index aa793b2..a9bc8ba 100644 --- a/webp/encode.go +++ b/webp/encode.go @@ -2,6 +2,7 @@ package webp /* #include +#include #include int writeWebP(uint8_t*, size_t, struct WebPPicture*); @@ -14,6 +15,32 @@ static void free_WebPPicture(WebPPicture* webpPicture) { free(webpPicture); } +static int webpEncodeGray(WebPConfig *config, WebPPicture *picture) { + int ok = 0; + const int c_width = (picture->width + 1) >> 1; + const int c_height = (picture->height + 1) >> 1; + const int c_stride = c_width; + const int c_size = c_stride * c_height; + const int gray = 128; + uint8_t* chroma; + + chroma = malloc(c_size); + if (!chroma) { + return 0; + } + memset(chroma, gray, c_size); + + picture->u = chroma; + picture->v = chroma; + picture->uv_stride = c_stride; + + ok = WebPEncode(config, picture); + + free(chroma); + + return ok; +} + static int webPConfigLosslessPreset(WebPConfig* webpConfig, int level) { #if WEBP_ENCODER_ABI_VERSION < 0x203 return 0; @@ -447,6 +474,40 @@ func EncodeRGBA(w io.Writer, img image.Image, c *Config) (err error) { return } +func EncodeGray(w io.Writer, p *image.Gray, c *Config) (err error) { + if err = validateConfig(c); err != nil { + return + } + + pic := C.malloc_WebPPicture() + if pic == nil { + return errors.New("Could not allocate webp picture") + } + defer C.free_WebPPicture(pic) + + makeDestinationManager(w, pic) + defer releaseDestinationManager(pic) + + if C.WebPPictureInit(pic) == 0 { + return errors.New("Could not initialize webp picture") + } + defer C.WebPPictureFree(pic) + + pic.use_argb = 0 + pic.width = C.int(p.Rect.Dx()) + pic.height = C.int(p.Rect.Dy()) + pic.y = (*C.uint8_t)(&p.Pix[0]) + pic.y_stride = C.int(p.Stride) + + pic.writer = C.WebPWriterFunction(C.writeWebP) + + if C.webpEncodeGray(&c.c, pic) == 0 { + return fmt.Errorf("Encoding error: %d", pic.error_code) + } + + return +} + // EncodeYUVA encodes and writes YUVA Image data into the writer as WebP. func EncodeYUVA(w io.Writer, img *YUVAImage, c *Config) (err error) { if err = validateConfig(c); err != nil { diff --git a/webp/webp_test.go b/webp/webp_test.go index 24a8e05..4a7ef30 100644 --- a/webp/webp_test.go +++ b/webp/webp_test.go @@ -4,6 +4,7 @@ import ( "bufio" "fmt" "image" + "image/color" "os" "testing" @@ -217,3 +218,27 @@ func TestEncodeYUVA(t *testing.T) { return } } + +func TestEncodeGray(t *testing.T) { + p := image.NewGray(image.Rect(0, 0, 1, 10)) + for i := 0; i < 10; i++ { + p.SetGray(0, i, color.Gray{uint8(float32(i) / 10 * 255)}) + } + + f := util.CreateFile("TestEncodeGray.webp") + w := bufio.NewWriter(f) + defer func() { + w.Flush() + f.Close() + }() + + config, err := webp.ConfigPreset(webp.PresetDefault, 100) + if err != nil { + t.Fatalf("got error: %v", err) + } + + if err := webp.EncodeGray(w, p, config); err != nil { + t.Errorf("Got Error: %v", err) + return + } +}