如何在 Go 编程语言中读取彩色 .png 文件,并将其输出为 8 位灰度图像?
5 回答
下面的程序采用输入文件名和输出文件名。它打开输入文件,对其进行解码,将其转换为灰度,然后将其编码为输出文件。
该程序并非特定于 PNG,但要支持其他文件格式,您必须导入正确的图像包。例如,要添加 JPEG 支持,您可以添加到 imports list _ "image/jpeg"
。
如果你只想支持 PNG,那么你可以直接使用image/png.Decode代替image.Decode。
package main
import (
"image"
"image/png" // register the PNG format with the image package
"os"
)
func main() {
infile, err := os.Open(os.Args[1])
if err != nil {
// replace this with real error handling
panic(err.String())
}
defer infile.Close()
// Decode will figure out what type of image is in the file on its own.
// We just have to be sure all the image packages we want are imported.
src, _, err := image.Decode(infile)
if err != nil {
// replace this with real error handling
panic(err.String())
}
// Create a new grayscale image
bounds := src.Bounds()
w, h := bounds.Max.X, bounds.Max.Y
gray := image.NewGray(w, h)
for x := 0; x < w; x++ {
for y := 0; y < h; y++ {
oldColor := src.At(x, y)
grayColor := image.GrayColorModel.Convert(oldColor)
gray.Set(x, y, grayColor)
}
}
// Encode the grayscale image to the output file
outfile, err := os.Create(os.Args[2])
if err != nil {
// replace this with real error handling
panic(err.String())
}
defer outfile.Close()
png.Encode(outfile, gray)
}
我自己也遇到了这个问题,并提出了一个稍微不同的解决方案。我介绍了一种新类型Converted
,它实现了image.Image
. Converted
由原始图像和color.Model
.
Converted
每次访问时都会进行转换,这可能会导致性能稍差,但另一方面它很酷且可组合。
package main
import (
"image"
_ "image/jpeg" // Register JPEG format
"image/png" // Register PNG format
"image/color"
"log"
"os"
)
// Converted implements image.Image, so you can
// pretend that it is the converted image.
type Converted struct {
Img image.Image
Mod color.Model
}
// We return the new color model...
func (c *Converted) ColorModel() color.Model{
return c.Mod
}
// ... but the original bounds
func (c *Converted) Bounds() image.Rectangle{
return c.Img.Bounds()
}
// At forwards the call to the original image and
// then asks the color model to convert it.
func (c *Converted) At(x, y int) color.Color{
return c.Mod.Convert(c.Img.At(x,y))
}
func main() {
if len(os.Args) != 3 { log.Fatalln("Needs two arguments")}
infile, err := os.Open(os.Args[1])
if err != nil {
log.Fatalln(err)
}
defer infile.Close()
img, _, err := image.Decode(infile)
if err != nil {
log.Fatalln(err)
}
// Since Converted implements image, this is now a grayscale image
gr := &Converted{img, color.GrayModel}
// Or do something like this to convert it into a black and
// white image.
// bw := []color.Color{color.Black,color.White}
// gr := &Converted{img, color.Palette(bw)}
outfile, err := os.Create(os.Args[2])
if err != nil {
log.Fatalln(err)
}
defer outfile.Close()
png.Encode(outfile,gr)
}
@EvanShaw 的片段现在不起作用,(可能是一些 golang API 发生了变化)我将其改编如下。可悲的是确实输出了灰度图像,但内容很乱,目前我不知道为什么。我在这里提供给你参考。
package main
import (
"image"
"image/color"
"image/png"
"math"
"os"
)
func main() {
filename := "dir/to/myfile/somefile.png"
infile, err := os.Open(filename)
if err != nil {
// replace this with real error handling
panic(err.Error())
}
defer infile.Close()
// Decode will figure out what type of image is in the file on its own.
// We just have to be sure all the image packages we want are imported.
src, _, err := image.Decode(infile)
if err != nil {
// replace this with real error handling
panic(err.Error())
}
// Create a new grayscale image
bounds := src.Bounds()
w, h := bounds.Max.X, bounds.Max.Y
gray := image.NewGray(image.Rectangle{image.Point{0, 0}, image.Point{w, h}})
for x := 0; x < w; x++ {
for y := 0; y < h; y++ {
oldColor := src.At(x, y)
r, g, b, _ := oldColor.RGBA()
avg := 0.2125*float64(r) + 0.7154*float64(g) + 0.0721*float64(b)
grayColor := color.Gray{uint8(math.Ceil(avg))}
gray.Set(x, y, grayColor)
}
}
// Encode the grayscale image to the output file
outfilename := "result.png"
outfile, err := os.Create(outfilename)
if err != nil {
// replace this with real error handling
panic(err.Error())
}
defer outfile.Close()
png.Encode(outfile, gray)
}
顺便说一句,golang不能自动解码图像文件,我们需要直接使用图像类型的Decode
方法。
幸运的是,我找到了这个,并且它有效! https://godoc.org/github.com/harrydb/go/img/grayscale#Convert
一个完整的工作示例如下:
package main
import (
"github.com/harrydb/go/img/grayscale"
"image/jpeg"
"image/png"
"os"
)
func main() {
filename := "dir/to/myfile/afile.jpg"
infile, err := os.Open(filename)
if err != nil {
panic(err.Error())
}
defer infile.Close()
// Must specifically use jpeg.Decode() or it
// would encounter unknown format error
src, err := jpeg.Decode(infile)
if err != nil {
panic(err.Error())
}
gray := grayscale.Convert(src, grayscale.ToGrayLuminance)
outfilename := "result.png"
outfile, err := os.Create(outfilename)
if err != nil {
panic(err.Error())
}
defer outfile.Close()
png.Encode(outfile, gray)
}
简单的方法是使用英特尔 OpenCV 库(开源)。谷歌如何使用 opencv 读取图像。您将获得详细信息。