Image.At возвращает ноль - PullRequest
       14

Image.At возвращает ноль

0 голосов
/ 16 марта 2019

У меня проблема.Вот мой код:

package main

import (
    "math/rand"
    "image/draw"
    "image/png"
    "image/color"
    "strconv"
    "os"
    "time"
    "fmt"
)

func genSites(width, height int) ([][]int) {
    rand.Seed(time.Now().Unix())
    l, err := strconv.Atoi(os.Args[len(os.Args)-2])
    if err != nil {
        panic(err)
    }
    sites := make([][]int, l)
    for i := range sites {
        sites[i] = make([]int, 2)
        sites[i][0] = rand.Intn(width)
        sites[i][1] = rand.Intn(height)
    }
    return sites
}

func main() {
    inputF, err := os.Open(os.Args[len(os.Args)-3])
    if err != nil {
        panic(err)
    }
    defer inputF.Close()

    inputR, err := png.Decode(inputF)
    if err != nil {
        panic(err)
    }
    input := inputR.(draw.Image)
    minx, miny := input.Bounds().Min.X, input.Bounds().Min.Y
    maxx, maxy := input.Bounds().Max.X-1, input.Bounds().Max.Y-1
    sites := genSites(maxx-minx, maxy-miny)
    siteColors := make([][]color.Color, len(sites))
    //todo: figure out something better than this
    for i := range siteColors {
        siteColors[i] = make([]color.Color, (maxx-minx)*(maxy-miny))
    }
    siteBelongs := make([][]int, maxx - minx)
    for x := range siteBelongs {
        siteBelongs[x] = make([]int, maxy - miny)
        for y := range siteBelongs[x] {
            dmin := (maxx-minx)*(maxx-minx) + (maxy-miny)*(maxy-miny)
            var smin int
            for i, s := range sites {
                d := (s[0]-x)*(s[0]-x) + (s[1]-y)*(s[1]-y)
                if d > dmin {
                    smin = i
                    dmin = d
                }
            }
            siteBelongs[x][y] = smin
            siteColors[smin] = append(siteColors[smin], input.At(x+minx, y+miny))
        }
    }
    siteAvgColors := make([]color.Color, len(sites))
    for i := range siteAvgColors {
        var sR, sG, sB, sA int
        for _, val := range siteColors[i] {
            fmt.Println(val)
            r, g, b, a := val.RGBA()
            sR += int(r)
            sG += int(g)
            sB += int(b)
            sA += int(a)
        }
        siteAvgColors[i] = color.RGBA{
            uint8(sR/len(siteColors[i])),
            uint8(sG/len(siteColors[i])),
            uint8(sB/len(siteColors[i])),
            uint8(sA/len(siteColors[i]))}
    }
    for x := range siteBelongs {
        for y := range siteBelongs[x] {
            input.Set(minx + x, miny + y, siteAvgColors[siteBelongs[x][y]])
        }
    }
    output, err := os.Create(os.Args[len(os.Args)-1])
    if err != nil {
        panic(err)
    }
    defer output.Close()
    err = png.Encode(output, input)
    if err != nil {
        panic(err)
    }
}

Ошибка заключается в следующем:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x4b46e1]

goroutine 1 [running]:
main.main()
    /home/victor/programs/goprograms/src/v/imagerandvornoi/main.go:71 +0x7a1

В строке 71 указано r, g, b, a := val.RGBA().Это значение вставляется в строку 63 или siteColors[smin] = append(siteColors[smin], input.At(x+minx, y+miny)), что означает, что input.At возвращает nil.Зачем?Как я могу это исправить?

1 Ответ

2 голосов
/ 16 марта 2019

Это связано с семантикой встроенного в Go make(). make отличается тем, что может принимать два или три аргумента:

make(Type, length) или make(Type, length, capacity). Для первых length и capacity установлены на одно и то же значение. Если вы собираетесь присваивать значения срезу с помощью команды добавления, вам нужно использовать последнюю форму. Это происходит потому, что форма с двумя аргументами (make(Type, 10)) создает срез с 10 элементами в нем уже с нулевым значением, когда вы используете append(), он становится 11-м элементом.

Здесь вы используете разыменование nil, потому что вы используете версию make с двумя аргументами с добавлением, и поэтому первый элемент в срезе - nil.

...