2012-01-02 18 views

Respuesta

12

El siguiente programa toma un nombre de archivo de entrada y un nombre de archivo de salida. Abre el archivo de entrada, lo decodifica, lo convierte a escala de grises y luego lo codifica en el archivo de salida.

Este programa no es específico para PNG, pero para admitir otros formatos de archivo, usted tendría que importar el paquete de imágenes correcto. Por ejemplo, para agregar compatibilidad con JPEG, puede agregar a la lista de importaciones _ "image/jpeg".

Si solamente quiere apoyar PNG, entonces se puede utilizar directamente en lugar de image/png.Decodeimage.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) 
} 
+0

Agradezco su respuesta rápida, sin embargo, esto abre una imagen como RGBA, por lo que yo sé. Lo que necesito es una imagen en escala de grises, donde cada píxel tiene un valor de 8 bits. – mlbright

+0

Si el PNG está codificado como una imagen en escala de grises, creo que el paquete png lo decodificará en una imagen. Gris. Si ese no es el caso, creo que hay un error en la imagen o un error en el paquete. –

+0

La imagen no está codificada como escala de grises: deseo eliminar el color. Quiero convertir RGBA en el archivo png, a escala de grises en el objeto Imagen en Ir. De hecho, quiero perder información, lo siento si no estaba claro. – mlbright

-4

La manera fácil es usar la biblioteca de Intel OpenCV (opensource) .Google cómo usar opencv para leer imágenes. Obtendrás detalles.

9

Tuve este problema yo mismo y se me ocurrió una solución ligeramente diferente. Introduje un nuevo tipo, Converted, que implementa image.Image. Converted consiste en la imagen original y color.Model.

Converted realiza la conversión cada vez que se accede, lo que podría dar un rendimiento ligeramente peor a , pero por otro lado es genial y 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) 
} 
+4

Este es de lejos el enfoque más versátil y apropiado de todos ellos. – ZorleQ

+1

Esta debería ser la respuesta aceptada. Es la forma de hacerlo de Go – arainone

0

fragmento @EvanShaw 's no funciona ahora, (puede haber alguna API golang tiene modificar) Me adapto como abajo. tristemente saca una imagen en escala de grises pero el contenido es complicado, actualmente no sé por qué. Lo proporciono aquí para su referencia.

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

y por cierto, no habría golang capaz de decodificar automáticamente archivo de imagen, tenemos que utilizar directamente el método de tipo de imagen Decode.

+0

Creo que su gris de cálculo está desactivado por 0xff, el rango de r, g, b es [0-0xffff]. Simplemente use 'gray.Set (x, y, img.At (x, y))' es suficiente, manejará la conversión de color internamente. Prueba este '' 'límites: = img.Bounds() \t \t \t gris: = image.NewGray (límites) \t \t \t para x: = bounds.Min.X; x

0

Afortunadamente encontré esto, ¡y funciona! https://godoc.org/github.com/harrydb/go/img/grayscale#Convert

Un ejemplo completamente de trabajo de la siguiente manera:

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