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

发布于 2024-12-24 00:59:21 字数 47 浏览 3 评论 0原文

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

How do I read in a color .png file in the Go programming language, and output it as an 8-bit grayscale image?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

梦情居士 2024-12-31 00:59:21

我自己也遇到了这个问题,并提出了一个稍微不同的解决方案。我引入了一种新类型 Converted,它实现了 image.ImageConverted 由原始图像和 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)
}

I had this problem myself and came up with a slightly different solution. I introduced a new type, Converted, which implements image.Image. Converted consists of the original image and the color.Model.

Converted does the conversion every time it is accessed, which could give
slightly worse performance if the image will be viewed multiple times, but on the other hand it is cool and composable.

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)
}
哭了丶谁疼 2024-12-31 00:59:21

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

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

如果您只想支持PNG,那么您可以使用image/png直接解码而不是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)
}

The program below takes an input file name and an output file name. It opens the input file, decodes it, converts it to grayscale, then encodes it to the output file.

Thie program isn't specific to PNGs, but to support other file formats you'd have to import the correct image package. For example, to add JPEG support you could add to the imports list _ "image/jpeg".

If you only want to support PNG, then you can use image/png.Decode directly instead of 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)
}
风苍溪 2024-12-31 00:59:21

@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 方法。

@EvanShaw 's snippet does not work now,(may be some golang API has change) I adapt it as below. sadly does output a grayscale image but the content is messy, currently I don't know why. I provide it here for your reference.

    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)
    }

and by the way, golang wouldn't able to automatically decode image file, we need to directly use image type's Decode method.

筱果果 2024-12-31 00:59:21

幸运的是我发现了这个,而且它有效!
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)
}

Luckily I found this, and it works!
https://godoc.org/github.com/harrydb/go/img/grayscale#Convert

A fully working example as follows:

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)
}
烟燃烟灭 2024-12-31 00:59:21

简单的方法是使用 Intel OpenCV 库(开源)。Google 如何使用 opencv 读取图像。您将获得详细信息。

Easy way is use Intel OpenCV library (opensource).Google how to use opencv to read images. You will get details.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文