一般情况下,我无法优雅地获取图像像素作为数组。
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接口获取类型?
reflect.TypeOf(img)
reflect.Type
if ... else通过使用如下所示的类型开关,可以简化大型结构:
if ... else
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字段的结构)。
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