Convert an image to grayscale in Go

huangapple go评论135阅读模式
英文:

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&#39;m trying to convert an image to grayscale using Go.

I&#39;ve found the below code, however, I&#39;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 (
        &quot;image&quot;
        _ &quot;image/jpeg&quot; // Register JPEG format
        &quot;image/png&quot;    // Register PNG  format
        &quot;image/color&quot;
        &quot;log&quot;
        &quot;os&quot;
    )
    
    // 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(&quot;Needs two arguments&quot;)}
        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 := &amp;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 := &amp;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&#39;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),后面跟着的是12等。文档中说明:

> 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(&quot;fullcolor.png&quot;)
if err != nil {
return nil, err
}
defer infile.Close()
img, _, err := image.Decode(infile) // img -&gt; 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(&quot;grayscaled.png&quot;)
defer outfile.Close()
png.Encode(outfile, grayscaledImage) // grayscaledImage -&gt; 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 &lt; bounds.Max.X; x++ {
for y := 0; y &lt; 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.

huangapple
  • 本文由 发表于 2016年12月28日 02:23:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/41350255.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定