Fixed image lists on Windows being NON-premultiplied.
This commit is contained in:
parent
432a210726
commit
4f16b94388
17
redo/area.go
17
redo/area.go
|
@ -5,6 +5,7 @@ package ui
|
|||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
"image/draw"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
@ -331,7 +332,7 @@ func pixelData(img *image.RGBA) *uint8 {
|
|||
// some platforms require pixels in ARGB order in their native endianness (because they treat the pixel array as an array of uint32s)
|
||||
// this does the conversion
|
||||
// you need to convert somewhere (Windows and cairo give us memory to use; Windows has stride==width but cairo might not)
|
||||
func toARGB(i *image.RGBA, memory uintptr, memstride int) {
|
||||
func toARGB(i *image.RGBA, memory uintptr, memstride int, toNRGBA bool) {
|
||||
var realbits []byte
|
||||
|
||||
rbs := (*reflect.SliceHeader)(unsafe.Pointer(&realbits))
|
||||
|
@ -340,14 +341,20 @@ func toARGB(i *image.RGBA, memory uintptr, memstride int) {
|
|||
rbs.Cap = rbs.Len
|
||||
p := pixelDataPos(i)
|
||||
q := 0
|
||||
iPix := i.Pix
|
||||
if toNRGBA { // for Windows image lists
|
||||
j := image.NewNRGBA(i.Rect)
|
||||
draw.Draw(j, j.Rect, i, i.Rect.Min, draw.Src)
|
||||
iPix = j.Pix
|
||||
}
|
||||
for y := i.Rect.Min.Y; y < i.Rect.Max.Y; y++ {
|
||||
nextp := p + i.Stride
|
||||
nextq := q + memstride
|
||||
for x := i.Rect.Min.X; x < i.Rect.Max.X; x++ {
|
||||
argb := uint32(i.Pix[p+3]) << 24 // A
|
||||
argb |= uint32(i.Pix[p+0]) << 16 // R
|
||||
argb |= uint32(i.Pix[p+1]) << 8 // G
|
||||
argb |= uint32(i.Pix[p+2]) // B
|
||||
argb := uint32(iPix[p+3]) << 24 // A
|
||||
argb |= uint32(iPix[p+0]) << 16 // R
|
||||
argb |= uint32(iPix[p+1]) << 8 // G
|
||||
argb |= uint32(iPix[p+2]) // B
|
||||
// the magic of conversion
|
||||
native := (*[4]byte)(unsafe.Pointer(&argb))
|
||||
realbits[q+0] = native[0]
|
||||
|
|
|
@ -223,7 +223,7 @@ func our_area_draw_callback(widget *C.GtkWidget, cr *C.cairo_t, data C.gpointer)
|
|||
// the flush and mark_dirty calls are required; see the cairo docs and https://git.gnome.org/browse/gtk+/tree/gdk/gdkcairo.c#n232 (thanks desrt in irc.gimp.net/#gtk+)
|
||||
C.cairo_surface_flush(surface)
|
||||
toARGB(i, uintptr(unsafe.Pointer(C.cairo_image_surface_get_data(surface))),
|
||||
int(C.cairo_image_surface_get_stride(surface)))
|
||||
int(C.cairo_image_surface_get_stride(surface)), false) // not NRGBA
|
||||
C.cairo_surface_mark_dirty(surface)
|
||||
C.cairo_set_source_surface(cr,
|
||||
surface,
|
||||
|
|
|
@ -101,7 +101,7 @@ static void paintArea(HWND hwnd, void *data)
|
|||
// first, we need to load the bitmap memory, because Windows makes it for us
|
||||
// the pixels are arranged in RGBA order, but GDI requires BGRA
|
||||
// this turns out to be just ARGB in little endian; let's convert into this memory
|
||||
dotoARGB(i, (void *) ppvBits);
|
||||
dotoARGB(i, (void *) ppvBits, FALSE); // FALSE = not NRGBA
|
||||
|
||||
// the second thing is... make a device context for the bitmap :|
|
||||
// Ninjifox just makes another compatible DC; we'll do the same
|
||||
|
|
|
@ -118,10 +118,11 @@ func doPaint(xrect *C.RECT, hscroll C.int, vscroll C.int, data unsafe.Pointer, d
|
|||
}
|
||||
|
||||
//export dotoARGB
|
||||
func dotoARGB(img unsafe.Pointer, ppvBits unsafe.Pointer) {
|
||||
func dotoARGB(img unsafe.Pointer, ppvBits unsafe.Pointer, toNRGBA C.BOOL) {
|
||||
i := (*image.RGBA)(unsafe.Pointer(img))
|
||||
t := toNRGBA != C.FALSE
|
||||
// the bitmap Windows gives us has a stride == width
|
||||
toARGB(i, uintptr(ppvBits), i.Rect.Dx() * 4)
|
||||
toARGB(i, uintptr(ppvBits), i.Rect.Dx() * 4, t)
|
||||
}
|
||||
|
||||
//export areaWidthLONG
|
||||
|
|
|
@ -37,7 +37,7 @@ func (i *imagelist) Append(img *image.RGBA) {
|
|||
}
|
||||
C.cairo_surface_flush(surface)
|
||||
toARGB(img, uintptr(unsafe.Pointer(C.cairo_image_surface_get_data(surface))),
|
||||
int(C.cairo_image_surface_get_stride(surface)))
|
||||
int(C.cairo_image_surface_get_stride(surface)), false) // not NRGBA
|
||||
C.cairo_surface_mark_dirty(surface)
|
||||
basepixbuf := C.gdk_pixbuf_get_from_surface(surface, 0, 0, C.gint(img.Rect.Dx()), C.gint(img.Rect.Dy()))
|
||||
if basepixbuf == nil {
|
||||
|
|
|
@ -22,7 +22,9 @@ HBITMAP unscaledBitmap(void *i, intptr_t dx, intptr_t dy)
|
|||
bitmap = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, &ppvBits, 0, 0);
|
||||
if (bitmap == NULL)
|
||||
xpanic("error creating HBITMAP for unscaled ImageList image copy", GetLastError());
|
||||
dotoARGB(i, (void *) ppvBits);
|
||||
// image lists use non-premultiplied RGBA - see http://stackoverflow.com/a/25578789/3408572
|
||||
// the TRUE here does the conversion
|
||||
dotoARGB(i, (void *) ppvBits, TRUE);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue