如何使用Go编程语言读取颜色的png文件并输出为灰度?

mlb*_*ght 8 png image go grayscale

如何在Go编程语言中读取颜色.png文件,并将其输出为8位灰度图像?

Eva*_*haw 13

下面的程序采用输入文件名和输出文件名.它打开输入文件,对其进行解码,将其转换为灰度,然后将其编码为输出文件.

该程序不是特定于PNG,但为了支持其他文件格式,您必须导入正确的图像包.例如,要添加JPEG支持,您可以添加到导入列表_ "image/jpeg".

如果你只是想支持PNG,那么你可以使用图像/ 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)
}
Run Code Online (Sandbox Code Playgroud)

  • 内部循环可以转换为`gray.Set(x,y,src.At(x,y))`,因为`Set`会自动进行转换. (2认同)

Hju*_*lle 10

我自己遇到了这个问题,并提出了一个略有不同的解决方案.我介绍了一个新的类型,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)
}
Run Code Online (Sandbox Code Playgroud)

  • 到目前为止,这是所有这些方法中最通用和最合适的方法. (4认同)