为了账号安全,请及时绑定邮箱和手机立即绑定

从 golang image.Image 获取像素数组

从 golang image.Image 获取像素数组

Go
holdtom 2021-11-15 17:01:15
我需要以将要从/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()
查看完整描述

3 回答

?
蝴蝶刀刀

TA贡献1801条经验 获得超8个赞

您可以简单地使用img.At(x, y).RGBA()获取像素的 RBGA 值,只需将它们除以 257 即可获得 8 位表示。我建议构建您自己的二维像素阵列。这是一个可能的实现,根据需要修改它:


package main


import (

    "fmt"

    "image"

    "image/png"

    "os"

    "io"

    "net/http"

)


func main() {

    // You can register another format here

    image.RegisterFormat("png", "png", png.Decode, png.DecodeConfig)


    file, err := os.Open("./image.png")


    if err != nil {

        fmt.Println("Error: File could not be opened")

        os.Exit(1)

    }


    defer file.Close()


    pixels, err := getPixels(file)


    if err != nil {

        fmt.Println("Error: Image could not be decoded")

        os.Exit(1)

    }


    fmt.Println(pixels)

}


// Get the bi-dimensional pixel array

func getPixels(file io.Reader) ([][]Pixel, error) {

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


    if err != nil {

        return nil, err

    }


    bounds := img.Bounds()

    width, height := bounds.Max.X, bounds.Max.Y


    var pixels [][]Pixel

    for y := 0; y < height; y++ {

        var row []Pixel

        for x := 0; x < width; x++ {

            row = append(row, rgbaToPixel(img.At(x, y).RGBA()))

        }

        pixels = append(pixels, row)

    }


    return pixels, nil

}


// img.At(x, y).RGBA() returns four uint32 values; we want a Pixel

func rgbaToPixel(r uint32, g uint32, b uint32, a uint32) Pixel {

    return Pixel{int(r / 257), int(g / 257), int(b / 257), int(a / 257)}

}


// Pixel struct example

type Pixel struct {

    R int

    G int

    B int

    A int

}

查看完整回答
反对 回复 2021-11-15
?
慕斯王

TA贡献1864条经验 获得超2个赞

这就是我最终要做的。我正在使用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可能很复杂。引用文档:


    // RGBA returns the alpha-premultiplied red, green, blue and alpha values

    // for the color. Each value ranges within [0, 0xffff], but is represented

    // by a uint32 so that multiplying by a blend factor up to 0xffff will not

    // overflow.

    //

    // An alpha-premultiplied color component c has been scaled by alpha (a),

    // so has valid values 0 <= c <= a.  


查看完整回答
反对 回复 2021-11-15
?
郎朗坤

TA贡献1921条经验 获得超9个赞

在我的测试中,Pixmethod 显示比快 4 倍At,但仍然需要太长时间......


这是我的测试脚本,不确定height/width顺序,但这对我有用:


// test_image_time.go

package main


import (

    "os"

    "fmt"

    "image"

    _ "image/jpeg"

    "golang.org/x/image/draw"

    "time"

)


func main() {

    img_path:= "/path/to/image/.jpg"

    aa := time.Now()

    reader, _ := os.Open(img_path)

    m, _, _ := image.Decode(reader)

    bounds := m.Bounds()

    fmt.Println("Bounds: ", bounds.Min.Y, bounds.Max.Y, bounds.Min.X, bounds.Max.X)

    bb := time.Now()

    fmt.Println("Read file time: ", float64(bb.Nanosecond() - aa.Nanosecond()) / 1e9)


    aa = time.Now()

    _ = image_2_array_at(m)

    bb = time.Now()

    fmt.Println("At Time: ", float64(bb.Nanosecond() - aa.Nanosecond()) / 1e9)


    aa = time.Now()

    _ = image_2_array_pix(m)

    bb = time.Now()

    fmt.Println("Pix Time: ", float64(bb.Nanosecond() - aa.Nanosecond()) / 1e9)

}


func image_2_array_at(src image.Image) [][][3]float32 {

    bounds := src.Bounds()

    width, height := bounds.Max.X, bounds.Max.Y

    iaa := make([][][3]float32, height)


    for y := 0; y < height; y++ {

        row := make([][3]float32, width)

        for x := 0; x < width; x++ {

            r, g, b, _ := src.At(x, y).RGBA()

            // A color's RGBA method returns values in the range [0, 65535].

            // Shifting by 8 reduces this to the range [0, 255].

            row[x] = [3]float32{float32(r>>8), float32(g>>8), float32(b>>8)}

        }

        iaa[y] = row

    }


    return iaa

}


func image_2_array_pix(src image.Image) [][][3]float32 {

    bounds := src.Bounds()

    width, height := bounds.Max.X, bounds.Max.Y

    iaa := make([][][3]float32, height)

    src_rgba := image.NewRGBA(src.Bounds())

    draw.Copy(src_rgba, image.Point{}, src, src.Bounds(), draw.Src, nil)


    for y := 0; y < height; y++ {

        row := make([][3]float32, width)

        for x := 0; x < width; x++ {

            idx_s := (y * width + x) * 4

            pix := src_rgba.Pix[idx_s : idx_s + 4]

            row[x] = [3]float32{float32(pix[0]), float32(pix[1]), float32(pix[2])}

        }

        iaa[y] = row

    }


    return iaa

}


$ go run test_image_time.go

Bounds:  0 976 0 1920

Read file time:  0.025212067

At Time:  0.069091218

Pix Time:  0.0165787


查看完整回答
反对 回复 2021-11-15
  • 3 回答
  • 0 关注
  • 605 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信