-
-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ev3dev/fb: add support for XRGB #78
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// Copyright ©2016 The ev3go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package fb | ||
|
||
import ( | ||
"errors" | ||
"image" | ||
"image/color" | ||
"image/draw" | ||
) | ||
|
||
// NewXRGB returns a new XRGB image with the given bounds. | ||
func NewXRGB(r image.Rectangle) *XRGB { | ||
w, h := r.Dx(), r.Dy() | ||
stride := 4 * w | ||
pix := make([]uint8, stride*h) | ||
return &XRGB{Pix: pix, Stride: stride, Rect: r} | ||
} | ||
|
||
// NewXRGBWith returns a new XRGB image with the given bounds, | ||
// backed by the []byte, pix. If stride is zero, a working stride | ||
// is computed. If the length of pix is less than stride*h, an | ||
// error is returned. | ||
func NewXRGBWith(pix []byte, r image.Rectangle, stride int) (draw.Image, error) { | ||
w, h := r.Dx(), r.Dy() | ||
if stride == 0 { | ||
stride = 4 * w | ||
} | ||
if len(pix) < stride*h { | ||
return nil, errors.New("ev3dev: bad pixel buffer length") | ||
} | ||
return &XRGB{Pix: pix, Stride: stride, Rect: r}, nil | ||
} | ||
|
||
// XRGB is an in-memory image whose At method returns PixelXRGB values. | ||
type XRGB struct { | ||
// Pix holds the image's pixels, as 32 bit XRGB | ||
// values stored in little-endian order. | ||
// The pixel at (x, y) is the four bytes at | ||
// Pix[4*(x-Rect.Min.X) + (y-Rect.Min.Y)*Stride]. | ||
Pix []uint8 | ||
// Stride is the Pix stride (in bytes) between | ||
// vertically adjacent pixels. | ||
Stride int | ||
// Rect is the image's bounds. | ||
Rect image.Rectangle | ||
} | ||
|
||
// ColorModel returns the XRGB color model. | ||
func (p *XRGB) ColorModel() color.Model { return RGB565Model } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is RGB565Model correct? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, The only difference between an |
||
|
||
// Bounds returns the bounding rectangle for the image. | ||
func (p *XRGB) Bounds() image.Rectangle { return p.Rect } | ||
|
||
// At returns the color of the pixel at (x, y). | ||
func (p *XRGB) At(x, y int) color.Color { | ||
if !(image.Point{x, y}.In(p.Rect)) { | ||
return color.RGBA{} | ||
} | ||
i := p.pixOffset(x, y) | ||
return PixelXRGB{R: p.Pix[i+2], G: p.Pix[i+1], B: p.Pix[i]} | ||
} | ||
|
||
// Set sets the color of the pixel at (x, y) to c. | ||
func (p *XRGB) Set(x, y int, c color.Color) { | ||
if !(image.Point{x, y}.In(p.Rect)) { | ||
return | ||
} | ||
i := p.pixOffset(x, y) | ||
xrgb := XRGBModel.Convert(c).(PixelXRGB) | ||
p.Pix[i+2] = xrgb.R | ||
p.Pix[i+1] = xrgb.G | ||
p.Pix[i] = xrgb.B | ||
} | ||
|
||
// pixOffset returns the index into p.Pix for the first byte | ||
// containing the pixel at (x, y). | ||
func (p *XRGB) pixOffset(x, y int) int { | ||
return 4*(x-p.Rect.Min.X) + (y-p.Rect.Min.Y)*p.Stride | ||
} | ||
|
||
// PixelXRGB is an XRGB pixel. | ||
type PixelXRGB struct { | ||
R, G, B byte | ||
} | ||
|
||
// RGBA returns the RGBA values for the receiver. | ||
func (c PixelXRGB) 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 | ||
return r, g, b, 0xffff | ||
} | ||
|
||
// XRGBModel is the color model for XRGB images. | ||
var XRGBModel color.Model = color.ModelFunc(xrgbModel) | ||
|
||
func xrgbModel(c color.Color) color.Color { | ||
if _, ok := c.(PixelXRGB); ok { | ||
return c | ||
} | ||
r, g, b, _ := c.RGBA() | ||
return PixelXRGB{R: uint8(r >> 8), G: uint8(g >> 8), B: uint8(b >> 8)} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
// Copyright ©2016 The ev3go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE file. | ||
|
||
package fb | ||
|
||
import ( | ||
"image/draw" | ||
"image/png" | ||
"os" | ||
"path/filepath" | ||
"reflect" | ||
"testing" | ||
) | ||
|
||
func TestXRGB(t *testing.T) { | ||
for _, test := range testImages { | ||
golden := filepath.FromSlash("testdata/" + test + "-xrgb.png") | ||
|
||
src, err := decodeImage(filepath.FromSlash("testdata/" + test + ".png")) | ||
if err != nil { | ||
t.Fatalf("failed to read src image file %v.png: %v", test, err) | ||
} | ||
|
||
got := NewXRGB(src.Bounds()) | ||
draw.Draw(got, got.Bounds(), src, src.Bounds().Min, draw.Src) | ||
|
||
if *genGolden { | ||
f, err := os.Create(golden) | ||
if err != nil { | ||
t.Fatalf("failed to create golden image file %v-xrgb.png: %v", test, err) | ||
} | ||
defer f.Close() | ||
err = png.Encode(f, got) | ||
if err != nil { | ||
t.Fatalf("failed to encode golden image %v-xrgb.png: %v", test, err) | ||
} | ||
continue | ||
} | ||
|
||
gol, err := decodeImage(golden) | ||
if err != nil { | ||
t.Fatalf("failed to read golden image file %v-xrgb.png: %v", test, err) | ||
} | ||
want := NewXRGB(gol.Bounds()) | ||
draw.Draw(want, want.Bounds(), gol, gol.Bounds().Min, draw.Src) | ||
|
||
if !reflect.DeepEqual(got, want) { | ||
t.Errorf("XRGB from source does not match expected image for %v test", test) | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2018? Also in the test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As attested by the horrific level of copy-paste errorism, the code was originally the 565 code.