在一般情况下,我不能优雅地将图像的像素作为数组。
f, err := os.Open(imgPath)
check(err)
defer f.Close()
img, _, err := image.Decode(bufio.NewReader(f))
check(err)
pixels, err := getPixels(img)
check(err)
// Logic with pixels.
现在函数getPixels看起来像这样:
func getPixels(img image.Image) ([]uint8, error) {
if i, ok := img.(*image.NRGBA); ok {
return i.Pix, nil
} else if i, ok := img.(*image.Alpha); ok {
return i.Pix, nil
} else if i, ok := img.(*image.Alpha16); ok {
return i.Pix, nil
} else if i, ok := img.(*image.CMYK); ok {
return i.Pix, nil
} else if i, ok := img.(*image.Gray); ok {
return i.Pix, nil
} else if i, ok := img.(*image.Gray16); ok {
return i.Pix, nil
} else if i, ok := img.(*image.NRGBA64); ok {
return i.Pix, nil
} else if i, ok := img.(*image.Paletted); ok {
return i.Pix, nil
} else if i, ok := img.(*image.RGBA); ok {
return i.Pix, nil
} else if i, ok := img.(*image.RGBA64); ok {
return i.Pix, nil
}
return nil, fmt.Errorf("unknown image type %T", img)
}
但我认为这很难看。 Golang知道图像的类型,我更喜欢这样的东西:
func getPixels(img image.Image) ([]uint8, error) {
if i, ok := img.(eval(fmt.Sprintf("%T", img))); ok {
return i.Pix, nil
}
return nil, fmt.Errorf("unknown image type %T", img)
}
我也不能断言reflect.TypeOf(img)
。也许有办法从reflect.Type
界面获取类型?
使用像这样的if ... else
可以简化你的大type switch结构:
func getPixels(img image.Image) ([]uint8, error) {
switch i := img.(type) {
case *image.NRGBA:
return i.Pix, nil
case *image.Alpha:
return i.Pix, nil
case *image.Alpha16:
return i.Pix, nil
case *image.CMYK:
return i.Pix, nil
// ...
}
return nil, fmt.Errorf("unknown image type %T", img)
}
你仍然需要列出所有可能的类型,但它更好。
由于所有图像实现都是具有名为Pix
的字段的结构指针,因此您可以使用反射来获取该字段。此实现将处理未来的图像实现而不进行任何更改(如果它们也将使用Pix
字段进行结构化)。
这是它的样子:
func getPix(img image.Image) ([]uint8, error) {
v := reflect.ValueOf(img)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() == reflect.Struct {
pv := v.FieldByName("Pix")
if pv.IsValid() {
if pix, ok := pv.Interface().([]uint8); ok {
return pix, nil
}
}
}
return nil, fmt.Errorf("unknown image type %T", img)
}
测试它:
fmt.Println(getPix(&image.NRGBA{}))
fmt.Println(getPix(&image.RGBA{}))
type unknownImage struct{ image.Image }
fmt.Println(getPix(unknownImage{}))
输出(在Go Playground上试试):
[] <nil>
[] <nil>
[] unknown image type main.unknownImage