2016-08-20 11 views
0

我正在瀏覽Golang教程,我對使用片練習中的一些值做些什麼感到困惑。 https://tour.golang.org/moretypes/18Golang練習片如何處理大數值

這裏是我感到困惑的代碼:

0值是完全藍色像素和255的值是一個完全白像素。因此,當顯示的值是某種形式的x*y(我做了/20以使圖像變大一點並更容易看清)時發生了什麼。

如果你水平地跟着圖像,你會看到在過程中的某一點,不斷增加的x和y值似乎恢復爲藍色(0值)如果我在返回I中鍵入一個像256這樣的靜態值得到一個編譯錯誤。所以它顯然不允許數字go off the scale並恢復到0或任何東西。那麼它如何獲得圖片中的藍色曲線?

進口來源在這裏: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) 
} 

回答

1

想象iint類型,uint8(i)回報iLeast Significant Byte (LSB)的:

x是在範圍[0, 255],意思是:0 <= x <= 255
y是在範圍[0,255],
然後x*y是在範圍[0, 255*255] = [0, 65025]
所以x*y/20在範圍內[0, 255*255/20] = [0, 65025/20] = [0, 3251]
和值uint8(x*y/20)等於(x*y/20)%256究竟意味着低字節:
uint8(3251) = uint8(0XCB3) = 0XB3 = 179
3251 = 12*256 + 179

所以每次x*y/20時間大於255從0開始重新計數:(x*y/20) % 256這就是爲什麼你的圖像被重複的圈子。

試試這個工作示例代碼:

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

輸出:

Done. 

讓我們簡化您例如,查看運行示例代碼:

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

和輸出重定向到一個像main > b.pnggo run main.go > b.png
看到輸出文件b.png
enter image description here

+1

@deltaskelta爲什麼當你輸入'uint8(256)'時會失敗?是'uint8(256)'給出'常數256溢出uint8'但是'var i int = 256 \t fmt.Println(uint8(i))'給出'0',見:https://github.com/golang/去/問題/ 16153 – 2016-08-20 05:00:45

1

uint8(anotherIntValue)轉換將採取anotherIntValue最後一個字節。這就是爲什麼你的代碼可以產生很多藍色(0)。例如,以下代碼將打印'val = 0'。

dx, dy := 128, 2 
fmt.Println("val =", uint8(dx*dy)) 

編譯器將檢查是否存在超出範圍的錯誤。

+0

然後當我輸入'UINT8(256),它爲什麼失敗'..它說,它溢出UINT8 – deltaskelta

+0

正是因爲不斷的轉換是受不同的靜態檢查規則。可以在https://golang.org/ref/spec#Conversions找到參考。具體而言,當x是常數時,T(x)是好的,'x可以用T類型的值表示。' int8(256)失敗,因爲256超出了一個字節可以表示的值。 – zc05