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

时间:2015-05-14 01:42:44

标签: image go set undefined

今年夏天我和空闲时间一起练习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})
}

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

type: *image.RGBA
type: *image.RGBA

但是如果没有注释,我会收到错误消息

img.Set undefined (type image.Image has no field or method Set)

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

3 个答案:

答案 0 :(得分:6)

要扩展 a previous answer answer

png.Decode可能会创建多种不同的基础图像类型之一(*image.Gray*image.RGBA*image.Paletted*image.NRGBA等。 它会将其创建的任何图片作为image.Image界面返回,为数据提供只读访问

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

// 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)的示例。

答案 1 :(得分:2)

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

您可以通过将img转换为*image.RGBA来修复代码,或者更加健壮,使用正确的Set方法定义接口类型,并将img转换为(draw.Image中的"image/draw"接口完美地适用于此,如@DaveC所述。如果您不确定png.Decode将始终为您提供{。{1}} .png文件,则最好使用界面类型。

*image.RGBA

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})

答案 2 :(得分:0)

编译器正确image.Image类型是不包含Set()函数的接口。

我不是图片库的专家,但我粗略看一下这些类型似乎建议您可以使用图片类型并使用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})

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