The following code errors with index out of range. I tried modifying main to
pic.Show(Pic(500, 500)) but that changes the argument from function to the return type and it fails to compile. How do I pass in integers if the pic.Show is expecting a function as an argument.
package main
import "golang.org/x/tour/pic"
func Pic(dx, dy int) [][]uint8 {
mypic := [][]uint8{}
for y := 0; y < dy; y++ {
mypic[y] = []uint8{}
for x := 0; x < dx; x++ {
mypic[y][x] = uint8((x + y) / 2)
}
}
return mypic
}
func main() {
pic.Show(Pic)
}
You don't. The Go Tour program will pass Pic test values to your program. Your problem is in your code: panic: runtime error: index out of range. [][]uint8{} and []uint8{} allocate zero y and zero x slice elements. Use make to allocate your y and x slices. For example,
package main
import "golang.org/x/tour/pic"
func Pic(dx, dy int) [][]uint8 {
pixels := make([][]uint8, dy)
for y := 0; y < dy; y++ {
pixels[y] = make([]uint8, dx)
for x := 0; x < dx; x++ {
pixels[y][x] = uint8((x + y) / 2)
}
}
return pixels
}
func main() {
pic.Show(Pic)
}
Reference: Making slices, maps and channels, The Go Programming Language Specification
Related
I've been learning golang using tour.golang.org.
In the following code, when I print the value of dx and dy which are both of type integer, the value comes out to be 256.
package main
import ("golang.org/x/tour/pic"
"fmt"
)
func Pic(dx, dy int) [][]uint8 {
fmt.Printf("%T\n",dx)
fmt.Println(dx)
ret := make([][]uint8, dy)
for i := range(ret){
ret[i] = make([]uint8, dx)
}
return ret
}
func main() {
pic.Show(Pic)
}
How does the golang compiler know the value of those two integers declared in the function Pic?
From main, you're calling pic.Show with your function, Pic. Looking at the source code for pic.Show, it calls the function it's given with 256 for each dimension.
I'm going through the Golang tutorial and I'm a little bit confused as to what it is doing with some of the values in the slices exercise. https://tour.golang.org/moretypes/18
Here is the code that I am confused with:
A value of 0 is a perfectly blue pixel and a value of 255 is a perfectly white pixel. So what is happening here when the value displayed is some form of x*y (I did /20 to make the image a little bit bigger and easier to see).
If you follow the image horizontally, you will see that at some point in the process, the ever increasing x and y values seem to revert to blue (0 value) If I type a static value like 256 in the return I get a compile error. So it obviously does not allow the numbers to go off the scale and revert to 0 or anything. So how does it get the blue curves in the picture?
imported source here: https://github.com/golang/tour/blob/master/pic/pic.go#L15
package main
import "golang.org/x/tour/pic"
func Pic(dx, dy int) [][]uint8 {
//First, the array has to be made so we can put some values in it later
//This only makes the second dimension of the array ([[uint8 dy]])?
image := make([][]uint8, dy)
//The inputs into the function are Int's, so it is ok to have a non uint8
//loop initializer
for x := 0; x < dy; x++ {
//once we are in the loop we have to make the first dimension of the array
//based on the dx values
image[x] = make([]uint8, dx)
for y := 0; y < dx; y++ {
//This is a function +to assign the pixel values to the array
image[x][y] = uint8((x * y) /20)
}
}
return image
}
func main() {
pic.Show(Pic)
}
Imagine i is of type int, uint8(i) returns Least Significant Byte (LSB) of i:
When x is in range [0, 255] , meaning: 0 <= x <= 255
and y is in range [0, 255],
then x*y is in range [0, 255*255] = [0, 65025]
so x*y/20 is in range [0, 255*255/20] = [0, 65025/20] = [0, 3251]
and value of uint8(x*y/20) is equal to (x*y/20)%256 meaning exactly LSB byte:
uint8(3251) = uint8(0XCB3) = 0XB3 = 179
3251 = 12*256 + 179
So every time the x*y/20 is bigger than 255 it counts from 0 again: (x*y/20) % 256 this is why your image is repeated circles.
Try this working sample code:
package main
import "fmt"
func main() {
for y := 0; y <= 255; y++ {
for x := 0; x <= 255; x++ {
v := x * y / 20
if int(uint8(v)) != v%256 {
fmt.Println(v, v%256)
}
}
}
fmt.Println("Done.")
}
output:
Done.
Let's simplify you example, see this working sample code:
package main
import (
"bytes"
"image"
"image/png"
"os"
)
func main() {
const dx = 256
const dy = 256
m := image.NewNRGBA(image.Rect(0, 0, dx, dy))
for y := 0; y < dy; y++ {
for x := 0; x < dx; x++ {
v := uint8(x * y / 20)
i := y*m.Stride + x*4
m.Pix[i] = v //R
m.Pix[i+1] = v //G
m.Pix[i+2] = 255 //B
m.Pix[i+3] = 255 //A
}
}
var buf bytes.Buffer
err := png.Encode(&buf, m)
if err != nil {
panic(err)
}
os.Stdout.Write(buf.Bytes())
}
And redirect the output to a file like main > b.png or, go run main.go > b.png
see output file b.png:
uint8(anotherIntValue) conversion will take the last byte of anotherIntValue. That is why your code can produce many blue (0). For example, following code would print 'val = 0'.
dx, dy := 128, 2
fmt.Println("val =", uint8(dx*dy))
Constant conversion will be checked by compiler for out of range errors.
I'm drawing a section of an image, however I'd like to apply rounded corners to it. I can't find any way of doing this.
In the draw() method:
img_section = img.get(gaze_x, gaze_y, gaze_size_x, gaze_size_y);
image(img_section, gaze_x, gaze_y);
You could copy the image and then manually set the corner pixels using the set() function.
You could just draw a rounded rectangle around the image- if the image will be placed on a background with a single color, just draw a rounded rectangle with the same color as the image.
Or you could come up with an image mask and draw that on top of your image.
package utils
import (
"ddkt365-poster/library/log"
"image"
"image/color"
"math"
)
// Settable Settable
type Settable interface {
Set(x, y int, c color.Color)
}
var empty = color.RGBA{255, 255, 255, 0}
// Convert Convert
func Convert(m *image.Image, rate float64) {
b := (*m).Bounds()
w, h := b.Dx(), b.Dy()
r := (float64(min(w, h)) / 2) * rate
log.Error("bounds:%v", r)
sm, ok := (*m).(Settable)
if !ok {
// Check if image is YCbCr format.
ym, ok := (*m).(*image.YCbCr)
if !ok {
log.Error("errInvalidFormat")
return
}
*m = yCbCrToRGBA(ym)
sm = (*m).(Settable)
}
// Parallelize?
for y := 0.0; y <= r; y++ {
l := math.Round(r - math.Sqrt(2*y*r-y*y))
for x := 0; x <= int(l); x++ {
sm.Set(x-1, int(y)-1, empty)
}
for x := 0; x <= int(l); x++ {
sm.Set(w-x, int(y)-1, empty)
}
for x := 0; x <= int(l); x++ {
sm.Set(x-1, h-int(y), empty)
}
for x := 0; x <= int(l); x++ {
sm.Set(w-x, h-int(y), empty)
}
}
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func yCbCrToRGBA(m image.Image) image.Image {
b := m.Bounds()
nm := image.NewRGBA(b)
for y := 0; y < b.Dy(); y++ {
for x := 0; x < b.Dx(); x++ {
nm.Set(x, y, m.At(x, y))
}
}
return nm
}
// Image with rounded corners (Go image/draw package)
if i.BorderRadius > 0 {
utils.Convert(&img, (float64(i.BorderRadius) / 100))
}
draw.Draw(canvs, img.Bounds().Add(image.Pt(i.X, i.Y)), img, image.ZP, draw.Over)
I get this error saying that I'm not using a variable… but to my noob eyes, it looks like I am:
func Sqrt(x float64) float64 {
z := float64(x);
for i := 0; i < 10; i++ {
z := z - (z*z - x) / (2 * z);
}
return z;
}
Can anyone point out what I'm missing about the language? I think it has to do with = vs. := and scoping, but I'm not sure.
The := in your for-loop declares a new variable z which shadows the outer z. Turn it into a plain = to fix the problem.
func Sqrt(x float64) float64 {
z := x
for i := 0; i < 10; i++ {
z = z - (z*z - x) / (2 * z);
}
return z;
}
By the way, for equal precision and a bit more speed you could try the following implementation which does two of your steps at once:
func Sqrt(x float64) float64 {
z := x
for i := 0; i < 5; i++ {
a := z + x/z
z = a/4 + x/a
}
return z
}
Here is another way to look at the function
func Sqrt(x float64) (z float64) {
z = x
for i := 0; i < 10; i++ {
z = z - (z*z - x)/(2*z);
}
return
}
I was having some trouble with step 35 in the tour of Go exercise.
Here's what my code looks like:
package main
import "code.google.com/p/go-tour/pic"
func Pic(dx, dy int) [][]uint8 {
var pic = make([][]uint8, dy)
for y := 0; y < dy; y++ {
pic[y] = make([]uint8, dx)
for x := 0; y < dx; x++ {
pic[y][x] = uint8(x*y)
}
}
return pic
}
When looking for a solution, I found PeterSO's code which works perfectly
func main() {
pic.Show(Pic)
}
func Pic(dx, dy int) [][]uint8 {
pixels := make([][]uint8, dy)
for y := 0; y < dy; y++ {
pixels[y] = make([]uint8, dx)
for x := 0; x < dx; x++ {
pixels[y][x] = uint8(x * y)
}
}
return pixels
}
The only difference I can see, is that I'm defining the pic variable using the var keyword whereas his code is using the := assignment. Now, why does my code not work?
You wrote
for x := 0; y < dx; x++ {
pic[y][x] = uint8(x * y)
}
in particular: y < dx, which causes,
panic: runtime error: index out of range
I wrote
for x := 0; x < dx; x++ {
pixels[y][x] = uint8(x * y)
}
in particular: x < dx. Therefore, change your y to x.
package main
import "code.google.com/p/go-tour/pic"
func Pic(dx, dy int) [][]uint8 {
var pic = make([][]uint8, dy)
for y :=0; y < dy; y++ {
pic[y] = make([]uint8, dx)
for x :=0; x<dx; x++ {
pic[y][x] = uint8(x*y)
}
}
return pic
}
func main() {
pic.Show(Pic)
}
http://play.golang.org/p/UvGgszFhl-
Variable declarations
A variable declaration creates a variable, binds an identifier to it
and gives it a type and optionally an initial value.
VarDecl = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) .
VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) .
Short variable declarations
A short variable declaration uses the syntax:
ShortVarDecl = IdentifierList ":=" ExpressionList .
It is a shorthand for a regular variable declaration with initializer
expressions but no types:
"var" IdentifierList = ExpressionList .
Unlike regular variable declarations, a short variable declaration may
redeclare variables provided they were originally declared earlier in
the same block with the same type, and at least one of the non-blank
variables is new.
In your code var pic = make([][]uint8, dy) and the short form pic := make([][]uint8, dy) will both work.
If you use the :=, the type of the variable is implied from the expression on the right of the sign. If you use =, no assumption is made and you need to specify the type yourself.
In this case, you should write it like this:
var pic [][]uint8 = make([][]uint8, dy)
but this is indeed better because shorter and as clear:
pic := make([][]uint8, dy)