英文:
Convert an image to grayscale in Go
问题
我正在尝试使用Go将图像转换为灰度图像。
我找到了下面的代码,但是我很难理解它。
如果您能解释每个函数的作用以及在哪里定义输入和输出文件,那将非常有帮助。
package main
import (
"image"
_ "image/jpeg" // 注册JPEG格式
"image/png" // 注册PNG格式
"image/color"
"log"
"os"
)
// Converted 实现了image.Image接口,所以您可以将其视为转换后的图像。
type Converted struct {
Img image.Image
Mod color.Model
}
// 我们返回新的颜色模型...
func (c *Converted) ColorModel() color.Model{
return c.Mod
}
// ...但保留原始边界
func (c *Converted) Bounds() image.Rectangle{
return c.Img.Bounds()
}
// At将调用转发到原始图像,然后要求颜色模型进行转换。
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("需要两个参数")}
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)
}
// 由于Converted实现了image,现在这是一张灰度图像
gr := &Converted{img, color.GrayModel}
// 或者像这样将其转换为黑白图像。
// 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)
}
我对Go还不太熟悉,所以任何建议或帮助都将不胜感激。
<details>
<summary>英文:</summary>
I'm trying to convert an image to grayscale using Go.
I've found the below code, however, I'm struggling to understand it.
It would be extremely helpful if you could explain what each function is doing and where to define the incoming and outgoing file.
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)
}
I'm quite new to Go so any suggestions or help would be appreciated.
</details>
# 答案1
**得分**: 2
正如Atomic_alarm指出的那样,https://maxhalford.github.io/blog/halftoning-1/简明地解释了如何做到这一点。
但是,如果我理解正确,你的问题是关于文件的打开和创建?
第一步是使用`image`包将打开的文件解码为`image.Image`结构:
```go
infile, err := os.Open("fullcolor.png")
if err != nil {
return nil, err
}
defer infile.Close()
img, _, err := image.Decode(infile) // img -> image.Image
if err != nil {
return nil, err
}
有了这个Go的image.Image
结构,你可以将其转换为灰度图像image.Gray
,然后最后将图像写入或编码到磁盘上的输出文件中:
outfile, _ := os.Create("grayscaled.png")
defer outfile.Close()
png.Encode(outfile, grayscaledImage) // grayscaledImage -> image.Gray
在打开输入文件和创建输出文件之间,你当然需要将图像转换为灰度图像。再次尝试上面的链接,你会找到这个函数,它接受一个image.Image
并返回一个指向image.Gray
的指针:
func rgbaToGray(img image.Image) *image.Gray {
var (
bounds = img.Bounds()
gray = image.NewGray(bounds)
)
for x := 0; x < bounds.Max.X; x++ {
for y := 0; y < bounds.Max.Y; y++ {
var rgba = img.At(x, y)
gray.Set(x, y, rgba)
}
}
return gray
}
关于你提供的代码(和你的注释),你使用os.Args[1]
打开一个文件,并创建文件os.Args[2]
。os.Args
是在运行程序时传递的参数的切片,0
始终是程序本身(main
),后面跟着的是1
,2
等。文档中说明:
> Args保存命令行参数,从程序名称开始。
> var Args []string
所以你可以像这样运行你上面的代码:
$ go run main.go infile.png outfile.png
infile.png
必须是磁盘上的文件(在你运行代码的目录中,或者是文件的完整路径)。
我上面提供的内容没有使用os.Args
,而是将文件名硬编码到程序中。
英文:
So as Atomic_alarm pointed out, https://maxhalford.github.io/blog/halftoning-1/ explains how to do this succinctly.
But you're question, if I understand correctly, is about the file opening and creation?
The first step is to use the image
package to Decode
the opened file
into an image.Image
struct:
infile, err := os.Open("fullcolor.png")
if err != nil {
return nil, err
}
defer infile.Close()
img, _, err := image.Decode(infile) // img -> image.Image
if err != nil {
return nil, err
}
With this Go image.Image
struct, you can convert it to a grayscaled image, image.Gray
and then, finally, write or encode the image onto an outgoing file on the disk:
outfile, _ := os.Create("grayscaled.png")
defer outfile.Close()
png.Encode(outfile, grayscaledImage) // grayscaledImage -> image.Gray
Inbetween the infile opening and outfile creating, you have to, of course, convert the image to grayscale. Again, try the link above, and you'll find this function, which takes an image.Image
and returns a pointer to a image.Gray
:
func rgbaToGray(img image.Image) *image.Gray {
var (
bounds = img.Bounds()
gray = image.NewGray(bounds)
)
for x := 0; x < bounds.Max.X; x++ {
for y := 0; y < bounds.Max.Y; y++ {
var rgba = img.At(x, y)
gray.Set(x, y, rgba)
}
}
return gray
}
Concerning the code you provided (and your comment), you were opening a file with os.Args[1]
, and creating the file os.Args[2]
. os.Args
is a slice of arguments passed when running the program, 0
will always be the program itself (main
), and whatever follows will with 1
, 2
, etc. The docs states:
> Args hold the command-line arguments, starting with the program name.
> var Args []string
so you would run your code above like this:
$ go run main.go infile.png outfile.png
infile.png must to be a file on disk (inside the directory you are running the code from, or the complete path to file).
What I have provide above doesn't use os.Args
but rather hard codes the file names into the program.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论