Как прочитать PNG-файл в цвете и вывести в виде серой шкалы, используя язык программирования Go? - PullRequest
8 голосов
/ 02 января 2012

Как мне прочитать цветной файл .png на языке программирования Go и вывести его в виде 8-битного изображения в градациях серого?

Ответы [ 5 ]

13 голосов
/ 02 января 2012

Программа ниже принимает имя входного файла и имя выходного файла.Он открывает входной файл, декодирует его, преобразует его в оттенки серого, затем кодирует его в выходной файл.

Эта программа не относится только к PNG, но для поддержки других форматов файлов вам придется импортироватьправильный пакет изображений.Например, чтобы добавить поддержку JPEG, вы можете добавить в список импорта _ "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)
}
10 голосов
/ 13 июня 2013

Я сам столкнулся с этой проблемой и придумал немного другое решение.Я ввел новый тип 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)
}
1 голос
/ 17 ноября 2014

@ Фрагмент 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 типа изображения.

0 голосов
/ 17 ноября 2014

К счастью, я нашел это, и это работает! 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)
}
0 голосов
/ 02 января 2012

Простой способ - использовать библиотеку Intel OpenCV (с открытым исходным кодом). Google, как использовать opencv для чтения изображений. Вы получите подробности.

...