Живко обнови решението на 06.11.2013 19:01 (преди над 4 години)
+package main
+
+type Header struct {
+ Format string
+ LineWidth int
+}
+
+type Pixel struct {
+ red byte
+ green byte
+ blue byte
+ alphaRatio float32
+}
+
+type RGB struct {
+ Red byte
+ Green byte
+ Blue byte
+}
+
+type pixelBytes []byte
+
+type Image struct {
+ pixelsMatrix [][]pixelBytes
+ format format
+}
+
+type format struct {
+ numberOfBytesPerPixel int
+ redByteId int
+ greenByteId int
+ blueByteId int
+ alphaByteId int
+}
+
+func ParseImage(bytes []byte, header Header) (img Image) {
+ img.format.set(header)
+
+ numberOfCols := header.LineWidth
+ numberOfRows := len(bytes) / (img.format.numberOfBytesPerPixel * numberOfCols)
+ img.pixelsMatrix = make([][]pixelBytes, numberOfRows)
+ for rowId := 0; rowId < numberOfRows; rowId++ {
+ img.pixelsMatrix[rowId] = make([]pixelBytes, numberOfCols)
+ for colId := 0; colId < numberOfCols; colId++ {
+ firstByteId := (rowId*numberOfCols + colId) * img.format.numberOfBytesPerPixel
+ outerLimitByteId := firstByteId + img.format.numberOfBytesPerPixel
+ img.pixelsMatrix[rowId][colId] = bytes[firstByteId:outerLimitByteId]
+ }
+ }
+ return
+}
+
+func (imageFormat *format) set(header Header) {
+ imageFormat.numberOfBytesPerPixel = len(header.Format)
+ for byteId, letter := range header.Format {
+ switch {
+ case letter == 'R':
+ imageFormat.redByteId = byteId
+ case letter == 'G':
+ imageFormat.greenByteId = byteId
+ case letter == 'B':
+ imageFormat.blueByteId = byteId
+ case letter == 'A':
+ imageFormat.alphaByteId = byteId
+ default:
+ panic("Undefined Header.Format: " + string(letter))
+ }
+ }
+}
+
+func (img Image) InspectPixel(y int, x int) Pixel {
+ pixelBytes := img.pixelsMatrix[x][y]
+
+ var alphaRatio float32
+ if img.hasAlpha() {
+ alphaRatio = float32(pixelBytes[img.format.alphaByteId]) / 255
+ } else {
+ alphaRatio = 1
+ }
+ return Pixel{
+ pixelBytes[img.format.redByteId],
+ pixelBytes[img.format.greenByteId],
+ pixelBytes[img.format.blueByteId],
+ alphaRatio,
+ }
+}
+
+func (img Image) hasAlpha() bool {
+ if img.format.numberOfBytesPerPixel == 4 {
+ return true
+ }
+ return false
+}
+
+func (px Pixel) Color() (rgb RGB) {
+ rgb.Red = px.red
+ rgb.Green = px.green
+ rgb.Blue = px.blue
+
+ ApplyAlpha := func(the_byte *byte) { *the_byte = byte(float32(*the_byte) * px.alphaRatio) }
+ ApplyAlpha(&rgb.Red)
+ ApplyAlpha(&rgb.Green)
+ ApplyAlpha(&rgb.Blue)
+ return
+}