为了账号安全,请及时绑定邮箱和手机立即绑定

使用 image.Image 或 *image.RGBA 的 Set() 方法

使用 image.Image 或 *image.RGBA 的 Set() 方法

Go
手掌心 2021-10-04 17:37:56
今年夏天的空闲时间,我正在用 Go 图像包做一些练习。package mainimport (    "os"    "image"    "image/png"    "image/color"    "log"    "fmt"    "reflect")func main(){    file , err := os.OpenFile("C:/Sources/go3x3.png", os.O_RDWR, os.FileMode(0777))    if err != nil {        log.Fatal(err)    }    img , err := png.Decode(file)    if err != nil {        log.Fatal(err)    }    img.At(0,0).RGBA()    fmt.Println("type:", reflect.TypeOf(img))    m := image.NewRGBA(image.Rect(0, 0, 640, 480))    fmt.Println("type:", reflect.TypeOf(m))    m.Set(5, 5, color.RGBA{255, 0, 0, 255})    img.Set(0, 0, color.RGBA{136, 0, 21, 255})}这里的问题是当我用img.Set注释掉运行它时,我得到了这个结果type: *image.RGBAtype: *image.RGBA但是当它取消注释时,我收到一条错误消息img.Set undefined (type image.Image has no field or method Set)我假设我使用的是反射错误,我仍然完全掌握了 Go 中的整个接口和类型定义。
查看完整描述

3 回答

?
四季花海

TA贡献1811条经验 获得超5个赞

png.Decode可以创建多个不同的基础图像类型中的一种(*image.Gray,*image.RGBA,*image.Paletted,*image.NRGBA,等等)。它返回它作为image.Image接口创建的任何图像,该接口提供对数据的只读访问。


但是,它返回的所有(大多数?)实际图像类型都实现了Set简单写访问的方法。您可以安全地测试和使用此方法的方法是通过包中的现有draw.Image接口image/draw。就是这样:


// From image/draw:

// Image is an image.Image with a Set method to change a single pixel.

type Image interface {

        image.Image

        Set(x, y int, c color.Color)

}

所以你可以这样做:


func drawablePNGImage(r io.Reader) (draw.Image, error) {

    img, err := png.Decode(r)

    if err != nil {

        return nil, err

    }

    dimg, ok := img.(draw.Image)

    if !ok {

        return nil, fmt.Errorf("%T is not a drawable image type", img)

    }

    return dimg, nil

}

Playground(显示了一个调用所有image.Image方法以及的示例Set)。


查看完整回答
反对 回复 2021-10-04
?
神不在的星期二

TA贡献1963条经验 获得超6个赞

reflect.TypeOf(img)img如果它是一个接口,则为您提供 interface 中值的反射类型。在这种情况下,img 是一个接口,image.Image其中包含一个*image.RGBA.


您可以通过转换img为来修复代码*image.RGBA,或者更健壮地使用正确的Set方法定义接口类型,然后转换img为该类型(正如@DaveC 所指出的,该draw.Image接口"image/draw"非常适合于此)。如果您不确定接口类型是否png.Decode总是为您*image.RGBA提供的 .png 文件,则接口类型更可取。


img.(*image.RGBA).Set(0, 0, color.RGBA{136, 0, 21, 255})

或者


type Setter interface {

    Set(x, y int, c color.Color)

}


img.(Setter).Set(0, 0, color.RGBA{136, 0, 21, 255})

或(可能是最好的):


import "image/draw"


...


img.(draw.Image).Set(0, 0, color.RGBA{136, 0, 21, 255})


查看完整回答
反对 回复 2021-10-04
?
暮色呼如

TA贡献1853条经验 获得超9个赞

所述编译器是正确时,image.Image类型是不包括集()函数的接口。


我不是图像库的专家,但我对类型的粗略观察似乎表明您可以采用 Image 类型并使用该Bounds()方法获取image.Rectangle以创建新的 RGBA 类型,如之前在示例代码中所做的那样。


// Your current image manipulation

m := image.NewRGBA(image.Rect(0, 0, 640, 480))

fmt.Println("type:", reflect.TypeOf(m))

m.Set(5, 5, color.RGBA{255, 0, 0, 255})


// You can create a image.RGBA type by passing the image.Rectangle

// returned from image.Image.Bounds()

m = image.NewRGBA(img.Bounds())

m.Set(0, 0, color.RGBA{136, 0, 21, 255})

这是对您的类型问题的严格回答,但我没有任何保证它可以实现您的最终目标。


查看完整回答
反对 回复 2021-10-04
  • 3 回答
  • 0 关注
  • 255 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信