ying32 / govcl

Cross-platform Go/Golang GUI library.
https://z-kit.cc
Apache License 2.0
2.25k stars 227 forks source link

怎么将go image包的Image转换成vcl.IGraphic实例? #189

Open skyqvn opened 10 months ago

skyqvn commented 10 months ago

怎么将go image包的Image转换成vcl.IGraphic实例?

skyqvn commented 10 months ago

不是说把Image以Png Decode到内存流,再从内存流Load到vcl。 vcl.IGraphic有没有类似于At、Set之类的方法读取、更改。

skyqvn commented 10 months ago

我现在需要做一个库,在Canvas上绘制图片,我已经用go Image写了一个旋转图片的代码,现在怎么在转换到vcl.IGraphic。每秒20帧,所以效率要求很高。

skyqvn commented 10 months ago

顺便问一句,作者你是怎么上Github的?我这里特别不稳定,都要被逼疯了 0A5A9F82 0A5A9F82 0A5A9F82

ying32 commented 10 months ago

vcl/bitmap包里面有,另外有几个draw开头的例子,里面有相关用法。至于github……经常访问不了呗,还能怎么办,只能说习惯了这种无奈感…

skyqvn commented 10 months ago

这是我封装的Bitmap,实现了go Image接口,还没写完,你看能不能用

skyqvn commented 10 months ago
package rotate

import (
    "github.com/ying32/govcl/vcl"
    "github.com/ying32/govcl/vcl/types"
    "image"
    "image/color"
    "unsafe"
)

type rgba struct {
    B, G, R, A uint8
}

type GoBitmap32 struct {
    bmp   *vcl.TBitmap
    cache []uintptr
}

func (b *GoBitmap32) ColorModel() color.Model {
    return color.RGBAModel
}

func (b *GoBitmap32) Bounds() image.Rectangle {
    return image.Rectangle{
        Min: image.Point{
            X: 0,
            Y: 0,
        },
        Max: image.Point{
            X: int(b.bmp.Width()),
            Y: int(b.bmp.Height()),
        },
    }
}

func (b *GoBitmap32) At(x, y int) color.Color {
    var l uintptr
    if b.cache[y] == 0 {
        l = b.bmp.ScanLine(int32(y))
        b.cache[y] = l
    } else {
        l = b.cache[y]
    }
    p := *(*rgba)(unsafe.Pointer(l + uintptr(x*4)))
    rgbaC := color.RGBA{
        R: p.R,
        G: p.G,
        B: p.B,
        A: 255 - p.A,
    }
    return rgbaC
}

func (b *GoBitmap32) Set(x, y int, c color.Color) {
    b.bmp.BeginUpdate(false)
    defer b.bmp.EndUpdate(false)
    var l uintptr
    if b.cache[y] == 0 {
        l = b.bmp.ScanLine(int32(y))
        b.cache[y] = l
    } else {
        l = b.cache[y]
    }
    cp := (*rgba)(unsafe.Pointer(l + uintptr(x*4)))
    c1 := color.RGBAModel.Convert(c).(color.RGBA)
    cp.R = c1.R
    cp.G = c1.G
    cp.B = c1.B
    cp.A = 255 - c1.A
}

func (b *GoBitmap32) Bitmap() *vcl.TBitmap {
    return b.bmp
}

//Free can free the vcl.TBitmap object.
//You can also use 'bmp.Bitmap().Free()' to free the vcl.TBitmap object.
func (b *GoBitmap32) Free() {
    b.bmp.Free()
}

func NewGoBitmap32(bmp *vcl.TBitmap) (goBmp32 *GoBitmap32) {
    goBmp32 = new(GoBitmap32)

    if bmp.PixelFormat() != types.Pf32bit {
        panic("not 32 bit bitmap")
    }
    bmp.SetHandleType(types.BmDIB)

    goBmp32.bmp = bmp
    goBmp32.cache = make([]uintptr, bmp.Height())
    return
}
skyqvn commented 10 months ago

问一下,Bitmap的A通道是透明度还是不透明度?为什么我一张Bitmap全部像素的A都是255? GO好像是255为不透明,但VCL的Bitmap好像255是透明。

ying32 commented 10 months ago

你那个写的我也不知道……只能你自己试试了。至于bmp透明必须要32位的,有一位是透明度,255就是不透明,0就是透明

skyqvn commented 10 months ago

哦,但我一张好好的位图怎么A通道全是0?导致转换出来的图片是透明的。我改成255 - A之后就好了。

skyqvn commented 10 months ago

简化代码:

l = b.ScanLine(int32(y))
p := *(*rgba)(unsafe.Pointer(l + uintptr(x*4)))
rgbaC := color.RGBA{
    R: p.R,
    G: p.G,
    B: p.B,
    A: p.A,
}
return rgbaC

这样得到的不透明部分的A是0,改成

rgbaC := color.RGBA{
    R: p.R,
    G: p.G,
    B: p.B,
    A: 255-p.A,
}

之后就好了 Set也是一样的问题

skyqvn commented 9 months ago

是我错了,不透明的确是255,但bmp.LoadFromFile("test.bmp")的结果A通道总是0,这是什么问题? 它其他通道颜色正常,只有A通道为0,这导致我认为要用255减A通道,是不是我bmp文件的问题?

skyqvn commented 9 months ago

请问怎么在画布上绘制部分透明的位图?

skyqvn commented 9 months ago

SetTransparent SetTransparentMode 怎么使用

skyqvn commented 9 months ago

TransparentMode如果为TmAuto,就根据透明度确定是否要透明是吗?

ying32 commented 9 months ago

你的图片是透明的绘制出来就是的,一般不需要设置什么