0

I'm currently working on writing a program to convert an RGBA image to grayscale. I know there are much simpler ways of doing this however I'm trying to do it this way do to this method being more suitable for the work I'm doing in the future.

I'm trying to step through each pixel one by one using two for loops. Then convert the RGBA value of the pixel to gray and then save the new image.

Below is my code:

package main

import (
    "image/color"
    "image/jpeg"
    "log"
    "os"
)

type ImageSet interface {
    Set(x, y int, c color.Color)
}

func main() {
    file, err := os.Open("biden.jpg")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()

    img, err := jpeg.Decode(file)
    if err != nil {
        log.Fatal(os.Stderr, "%s: %v\n", "biden.jpg", err)
    }

    b := img.Bounds()

  imgSet = img.(ImageSet)
    for y := b.Min.Y; y < b.Max.Y; y++ {
        for x := b.Min.X; x < b.Max.X; x++ {
            oldPixel := img.At(x, y)
            r, g, b, a := oldPixel.RGBA()
            //fmt.Println(r, g, b, a)
            r = (r+g+b)/3
        //  g = (r+g+b)/3
            //b = (r+g+b)/3
            pixel := color.RGBA{uint8(r), uint8(r), uint8(r), uint8(a)}
            imgSet.Set(x, y, pixel)
        }
    }

    fd, err := os.Create("gray.jpg")
    if err != nil {
        log.Fatal(err)
    }

    err = jpeg.Encode(fd, img)
    if err != nil {
        log.Fatal(err)
    }

    err = fd.Close()
    if err != nil {
        log.Fatal(err)
    }

}

I get the following errors when trying to run this code.

   # command-line-arguments
.\rgbtogray.go:28: undefined: imgSet
.\rgbtogray.go:38: undefined: imgSet in imgSet.Set
.\rgbtogray.go:47: not enough arguments in call to jpeg.Encode
    have (*os.File, image.Image)
    want (io.Writer, image.Image, *jpeg.Options)
[Finished in 4.002s]

Can anyone see where these errors are coming from and why the code does not work?

Edit:

Made a couple of changes -

    package main

import (
    "image/color"
    "image/jpeg"
  "image/png"
    "log"
    "os"
)

type ImageSet interface {
    Set(x, y int, c color.Color)
}

func main() {
    file, err := os.Open("biden.jpg")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()

    img, err := jpeg.Decode(file)
    if err != nil {
        log.Fatal(os.Stderr, "%s: %v\n", "biden.jpg", err)
    }

    b := img.Bounds()

    imgSet := img.(ImageSet)
    for y := b.Min.Y; y < b.Max.Y; y++ {
        for x := b.Min.X; x < b.Max.X; x++ {
      oldPixel := img.At(x, y)
           r, g, b, a := oldPixel.RGBA()
           //fmt.Println(r, g, b, a)
           g = (r+g+b)/3
           pixel := color.RGBA{uint8(g), uint8(g), uint8(g), uint8(a)}
           imgSet.Set(x, y, pixel)
        }
    }

    fd, err := os.Create("gray.jpg")
  defer fd.Close()
    png.Encode(fd, img)

}

The error I now get is -

 panic: interface conversion: *image.YCbCr is not main.ImageSet: missing method Set

I know using png.Encode at the bottom is strange but this is how someone I know fixed their issues.

benjano
  • 369
  • 1
  • 5
  • 17
  • There is no guarantee that the implementation of `image.Image` you get back from `jpeg.Decode()` has a `Set()` method. See this answer for workarounds and alternatives: [Change color of a single pixel - Go lang image](http://stackoverflow.com/questions/36573413/change-color-of-a-single-pixel-go-lang-image/36577076#36577076). – icza Feb 28 '17 at 16:21
  • The errors are pretty self explanatory. If not: Take the tour of Go once more. – Volker Feb 28 '17 at 16:31
  • I've made a number of changes, the error I get now is - panic: interface conversion: *image.YCbCr is not main.ImageSet: missing method Set – benjano Feb 28 '17 at 16:33
  • To correct the compile time errors in your code: use short variable declaration: `imgSet := img.(ImageSet)`, and pass an additional argument to `jpeg.Encode()` like: `err = jpeg.Encode(fd, img, nil)`. But even after that it won't work, for reasoning see my linked answer. – icza Feb 28 '17 at 16:38
  • I'm looking at your other answer and trying to understand it now - should I ask questions relating to it on this question or the one with your answer on? – benjano Feb 28 '17 at 17:01
  • Actually your question is a duplicate of the other, and should be closed. So I guess ask in the other if it's related to the answer. Or post a new question if you encountered new problems while trying to use ideas from it. – icza Feb 28 '17 at 17:10
  • Okay will do, thanks – benjano Feb 28 '17 at 17:11

0 Answers0