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
}
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.
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
- 3 回答
- 0 关注
- 605 浏览
添加回答
举报