猿问

从 golang image.Image 获取像素数组

我需要以将要从/mobile/gl包[]byte传递给ContextexImage2D方法的形式获取像素阵列。


它需要一个像素数组,其中每个像素的 rgba 值按像素从左到右、从上到下的顺序附加。目前我有一个从文件加载的图像。


a, err := asset.Open("key.jpeg")

if err != nil {

    log.Fatal(err)

}

defer a.Close()


img, _, err := image.Decode(a)

if err != nil {

    log.Fatal(err)

}

我正在寻找类似的东西 img.Pixels()



holdtom
浏览 606回答 3
3回答

蝴蝶刀刀

您可以简单地使用img.At(x, y).RGBA()获取像素的 RBGA 值,只需将它们除以 257 即可获得 8 位表示。我建议构建您自己的二维像素阵列。这是一个可能的实现,根据需要修改它:package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "image"&nbsp; &nbsp; "image/png"&nbsp; &nbsp; "os"&nbsp; &nbsp; "io"&nbsp; &nbsp; "net/http")func main() {&nbsp; &nbsp; // You can register another format here&nbsp; &nbsp; image.RegisterFormat("png", "png", png.Decode, png.DecodeConfig)&nbsp; &nbsp; file, err := os.Open("./image.png")&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Error: File could not be opened")&nbsp; &nbsp; &nbsp; &nbsp; os.Exit(1)&nbsp; &nbsp; }&nbsp; &nbsp; defer file.Close()&nbsp; &nbsp; pixels, err := getPixels(file)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Error: Image could not be decoded")&nbsp; &nbsp; &nbsp; &nbsp; os.Exit(1)&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Println(pixels)}// Get the bi-dimensional pixel arrayfunc getPixels(file io.Reader) ([][]Pixel, error) {&nbsp; &nbsp; img, _, err := image.Decode(file)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return nil, err&nbsp; &nbsp; }&nbsp; &nbsp; bounds := img.Bounds()&nbsp; &nbsp; width, height := bounds.Max.X, bounds.Max.Y&nbsp; &nbsp; var pixels [][]Pixel&nbsp; &nbsp; for y := 0; y < height; y++ {&nbsp; &nbsp; &nbsp; &nbsp; var row []Pixel&nbsp; &nbsp; &nbsp; &nbsp; for x := 0; x < width; x++ {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; row = append(row, rgbaToPixel(img.At(x, y).RGBA()))&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; pixels = append(pixels, row)&nbsp; &nbsp; }&nbsp; &nbsp; return pixels, nil}// img.At(x, y).RGBA() returns four uint32 values; we want a Pixelfunc rgbaToPixel(r uint32, g uint32, b uint32, a uint32) Pixel {&nbsp; &nbsp; return Pixel{int(r / 257), int(g / 257), int(b / 257), int(a / 257)}}// Pixel struct exampletype Pixel struct {&nbsp; &nbsp; R int&nbsp; &nbsp; G int&nbsp; &nbsp; B int&nbsp; &nbsp; A int}

慕斯王

这就是我最终要做的。我正在使用image/draw包的 Draw 函数来重新填充image.RGBA实例rect := img.Bounds()rgba := image.NewRGBA(rect)draw.Draw(rgba, rect, img, rect.Min, draw.Src)现在rgba.Pix包含我想要的数组并且可以在TexImage2D方法中使用。glctx.TexImage2D(gl.TEXTURE_2D, 0, rect.Max.X-rect.Min.X, rect.Max.Y-rect.Min.Y, gl.RGBA, gl.UNSIGNED_BYTE, rgba.Pix)交替Image实例包含一个At返回Color的方法。因此可以遍历每个像素并收集颜色。但是从 转换返回的 rgba 值Color可能很复杂。引用文档:&nbsp; &nbsp; // RGBA returns the alpha-premultiplied red, green, blue and alpha values&nbsp; &nbsp; // for the color. Each value ranges within [0, 0xffff], but is represented&nbsp; &nbsp; // by a uint32 so that multiplying by a blend factor up to 0xffff will not&nbsp; &nbsp; // overflow.&nbsp; &nbsp; //&nbsp; &nbsp; // An alpha-premultiplied color component c has been scaled by alpha (a),&nbsp; &nbsp; // so has valid values 0 <= c <= a.&nbsp;&nbsp;

郎朗坤

在我的测试中,Pixmethod 显示比快 4 倍At,但仍然需要太长时间......这是我的测试脚本,不确定height/width顺序,但这对我有用:// test_image_time.gopackage mainimport (&nbsp; &nbsp; "os"&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "image"&nbsp; &nbsp; _ "image/jpeg"&nbsp; &nbsp; "golang.org/x/image/draw"&nbsp; &nbsp; "time")func main() {&nbsp; &nbsp; img_path:= "/path/to/image/.jpg"&nbsp; &nbsp; aa := time.Now()&nbsp; &nbsp; reader, _ := os.Open(img_path)&nbsp; &nbsp; m, _, _ := image.Decode(reader)&nbsp; &nbsp; bounds := m.Bounds()&nbsp; &nbsp; fmt.Println("Bounds: ", bounds.Min.Y, bounds.Max.Y, bounds.Min.X, bounds.Max.X)&nbsp; &nbsp; bb := time.Now()&nbsp; &nbsp; fmt.Println("Read file time: ", float64(bb.Nanosecond() - aa.Nanosecond()) / 1e9)&nbsp; &nbsp; aa = time.Now()&nbsp; &nbsp; _ = image_2_array_at(m)&nbsp; &nbsp; bb = time.Now()&nbsp; &nbsp; fmt.Println("At Time: ", float64(bb.Nanosecond() - aa.Nanosecond()) / 1e9)&nbsp; &nbsp; aa = time.Now()&nbsp; &nbsp; _ = image_2_array_pix(m)&nbsp; &nbsp; bb = time.Now()&nbsp; &nbsp; fmt.Println("Pix Time: ", float64(bb.Nanosecond() - aa.Nanosecond()) / 1e9)}func image_2_array_at(src image.Image) [][][3]float32 {&nbsp; &nbsp; bounds := src.Bounds()&nbsp; &nbsp; width, height := bounds.Max.X, bounds.Max.Y&nbsp; &nbsp; iaa := make([][][3]float32, height)&nbsp; &nbsp; for y := 0; y < height; y++ {&nbsp; &nbsp; &nbsp; &nbsp; row := make([][3]float32, width)&nbsp; &nbsp; &nbsp; &nbsp; for x := 0; x < width; x++ {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r, g, b, _ := src.At(x, y).RGBA()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // A color's RGBA method returns values in the range [0, 65535].&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Shifting by 8 reduces this to the range [0, 255].&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; row[x] = [3]float32{float32(r>>8), float32(g>>8), float32(b>>8)}&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; iaa[y] = row&nbsp; &nbsp; }&nbsp; &nbsp; return iaa}func image_2_array_pix(src image.Image) [][][3]float32 {&nbsp; &nbsp; bounds := src.Bounds()&nbsp; &nbsp; width, height := bounds.Max.X, bounds.Max.Y&nbsp; &nbsp; iaa := make([][][3]float32, height)&nbsp; &nbsp; src_rgba := image.NewRGBA(src.Bounds())&nbsp; &nbsp; draw.Copy(src_rgba, image.Point{}, src, src.Bounds(), draw.Src, nil)&nbsp; &nbsp; for y := 0; y < height; y++ {&nbsp; &nbsp; &nbsp; &nbsp; row := make([][3]float32, width)&nbsp; &nbsp; &nbsp; &nbsp; for x := 0; x < width; x++ {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; idx_s := (y * width + x) * 4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pix := src_rgba.Pix[idx_s : idx_s + 4]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; row[x] = [3]float32{float32(pix[0]), float32(pix[1]), float32(pix[2])}&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; iaa[y] = row&nbsp; &nbsp; }&nbsp; &nbsp; return iaa}跑$ go run test_image_time.goBounds:&nbsp; 0 976 0 1920Read file time:&nbsp; 0.025212067At Time:&nbsp; 0.069091218Pix Time:&nbsp; 0.0165787
随时随地看视频慕课网APP

相关分类

Go
我要回答