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

Bra*_*cki 3 image set undefined go

我今年夏天和空闲时间一起练习Go图像包.

package main

import (

    "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})
}
Run Code Online (Sandbox Code Playgroud)

这里的问题是当我用img.Set注释掉的时候运行它我得到了这个结果

type: *image.RGBA
type: *image.RGBA
Run Code Online (Sandbox Code Playgroud)

但当它没有注释时,我得到一个错误说

img.Set undefined (type image.Image has no field or method Set)
Run Code Online (Sandbox Code Playgroud)

我假设我使用反射错误,我仍然完全掌握整个界面和Go中的类型定义.

Dav*_*e C 6

要扩展 之前的答案 答案:

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)
}
Run Code Online (Sandbox Code Playgroud)

所以你可以这样做:

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
}
Run Code Online (Sandbox Code Playgroud)

Playground(显示调用所有image.Image方法的示例Set).


Pau*_*kin 3

reflect.TypeOf(img)为您提供接口中值的反射类型img(如果它是接口)。在本例中,img 一个接口, animage.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})
Run Code Online (Sandbox Code Playgroud)

或者

type Setter interface {
    Set(x, y int, c color.Color)
}

img.(Setter).Set(0, 0, color.RGBA{136, 0, 21, 255})
Run Code Online (Sandbox Code Playgroud)

或(可能是最好的):

import "image/draw"

...

img.(draw.Image).Set(0, 0, color.RGBA{136, 0, 21, 255})
Run Code Online (Sandbox Code Playgroud)