Решение на Картинки от Симеон Тотев

Обратно към всички решения

Към профила на Симеон Тотев

Резултати

  • 10 точки от тестове
  • 0 бонус точки
  • 10 точки общо
  • 10 успешни тест(а)
  • 0 неуспешни тест(а)

Код

package main
import (
"fmt"
"strings"
)
type Stringer interface {
String() string
}
type Image struct {
Pixels []Pixel
Header Header
}
type Header struct {
Format string
LineWidth int
}
type Pixel struct {
PixelColor Color
}
type Color struct {
Red, Green, Blue byte
}
func (pixel *Pixel) Color() Color {
return pixel.PixelColor
}
func (color Color) String() string {
return fmt.Sprintf("Red: %v, Green: %v, Blue: %v", color.Red, color.Green, color.Blue)
}
// Правим проверката дали X надвишава броя колони. Ако е така, става паника.
func (image Image) InspectPixel(x, y int) Pixel {
if x >= image.Header.LineWidth {
panic("Invalid dimensions!")
}
return image.Pixels[y*image.Header.LineWidth+x]
}
// Тук става малко по-интересно
func ParseImage(data []byte, header Header) *Image {
image := new(Image)
var r, g, b, a float32
formatLength := len(strings.Split(header.Format, ""))
if formatLength == 0 {
panic("Please enter a format!")
}
r, g, b, a = 0.0, 0.0, 0.0, 255.0
image.Header = header
// Идеята е, че разделяме пикселите на групички, номерирани със step. Броя на цветовете на всяка стъпка зависи от броя на символите въф формата на картинката. Ако форматът е RGB, тогава броя цветове в съответната стъпка е 3.
for step := 0; step < len(data)/formatLength; step++ {
for index, value := range strings.Split(header.Format, "") {
byteIndex := step*formatLength + index
// Итерираме през възможните буквички и записваме в r, g, b, a съответния цвят. В случая се оказва, че формати като GRAB, BRA и BAR също са валидни, което май не вреди... Кастваме цветовете към float32, защото ще ни трябват малко по-късно за сметки.
switch value {
case "R":
r = float32(data[byteIndex])
case "G":
g = float32(data[byteIndex])
case "B":
b = float32(data[byteIndex])
case "A":
a = float32(data[byteIndex])
default:
panic("Wrong header format. Please use a format with the letters R,G,B,A!")
}
}
// Очевидно всеки цвят се пресмята по формулата Color * Alpha / 255. Готовият резултат кастваме обратно към byte и си създаваме пиксела, който после добавяме в слайса с пиксели.
pixel := Pixel{PixelColor: Color{Red: byte(r * a / 255), Green: byte(g * a / 255), Blue: byte(b * a / 255)}}
image.Pixels = append(image.Pixels, pixel)
}
return image
}
func main() {
// В този случай имаме 3 реда и 2 колони, като цветовете на пикселите са по формата RG. Синият цвят по подразбиране се сетва на 0. Казваме да върне долния десен пиксел. (R: 17, G: 67, B: 0)
data := []byte{0, 12, 244, 13, 26, 52, 31, 33, 41, 33, 17, 67}
header := Header{"RG", 2}
pixel := ParseImage(data, header).InspectPixel(1, 2)
fmt.Println(pixel.Color())
}

Лог от изпълнението

PASS
ok  	_/tmp/d20131125-20161-hh81u6	0.013s
PASS
ok  	_/tmp/d20131125-20161-hh81u6	0.011s
PASS
ok  	_/tmp/d20131125-20161-hh81u6	0.012s
PASS
ok  	_/tmp/d20131125-20161-hh81u6	0.011s
PASS
ok  	_/tmp/d20131125-20161-hh81u6	0.014s
PASS
ok  	_/tmp/d20131125-20161-hh81u6	0.012s
PASS
ok  	_/tmp/d20131125-20161-hh81u6	0.011s
PASS
ok  	_/tmp/d20131125-20161-hh81u6	0.011s
PASS
ok  	_/tmp/d20131125-20161-hh81u6	0.011s
PASS
ok  	_/tmp/d20131125-20161-hh81u6	0.014s

История (1 версия и 0 коментара)

Симеон обнови решението на 07.11.2013 02:11 (преди над 4 години)

+package main
+
+import (
+ "fmt"
+ "strings"
+)
+
+type Stringer interface {
+ String() string
+}
+
+type Image struct {
+ Pixels []Pixel
+ Header Header
+}
+
+type Header struct {
+ Format string
+ LineWidth int
+}
+
+type Pixel struct {
+ PixelColor Color
+}
+
+type Color struct {
+ Red, Green, Blue byte
+}
+
+func (pixel *Pixel) Color() Color {
+ return pixel.PixelColor
+}
+
+func (color Color) String() string {
+ return fmt.Sprintf("Red: %v, Green: %v, Blue: %v", color.Red, color.Green, color.Blue)
+}
+
+// Правим проверката дали X надвишава броя колони. Ако е така, става паника.
+func (image Image) InspectPixel(x, y int) Pixel {
+ if x >= image.Header.LineWidth {
+ panic("Invalid dimensions!")
+ }
+ return image.Pixels[y*image.Header.LineWidth+x]
+}
+
+// Тук става малко по-интересно
+func ParseImage(data []byte, header Header) *Image {
+ image := new(Image)
+ var r, g, b, a float32
+ formatLength := len(strings.Split(header.Format, ""))
+
+ if formatLength == 0 {
+ panic("Please enter a format!")
+ }
+
+ r, g, b, a = 0.0, 0.0, 0.0, 255.0
+ image.Header = header
+
+ // Идеята е, че разделяме пикселите на групички, номерирани със step. Броя на цветовете на всяка стъпка зависи от броя на символите въф формата на картинката. Ако форматът е RGB, тогава броя цветове в съответната стъпка е 3.
+ for step := 0; step < len(data)/formatLength; step++ {
+ for index, value := range strings.Split(header.Format, "") {
+ byteIndex := step*formatLength + index
+
+ // Итерираме през възможните буквички и записваме в r, g, b, a съответния цвят. В случая се оказва, че формати като GRAB, BRA и BAR също са валидни, което май не вреди... Кастваме цветовете към float32, защото ще ни трябват малко по-късно за сметки.
+ switch value {
+ case "R":
+ r = float32(data[byteIndex])
+ case "G":
+ g = float32(data[byteIndex])
+ case "B":
+ b = float32(data[byteIndex])
+ case "A":
+ a = float32(data[byteIndex])
+ default:
+ panic("Wrong header format. Please use a format with the letters R,G,B,A!")
+ }
+ }
+
+ // Очевидно всеки цвят се пресмята по формулата Color * Alpha / 255. Готовият резултат кастваме обратно към byte и си създаваме пиксела, който после добавяме в слайса с пиксели.
+ pixel := Pixel{PixelColor: Color{Red: byte(r * a / 255), Green: byte(g * a / 255), Blue: byte(b * a / 255)}}
+
+ image.Pixels = append(image.Pixels, pixel)
+ }
+
+ return image
+}
+
+func main() {
+ // В този случай имаме 3 реда и 2 колони, като цветовете на пикселите са по формата RG. Синият цвят по подразбиране се сетва на 0. Казваме да върне долния десен пиксел. (R: 17, G: 67, B: 0)
+ data := []byte{0, 12, 244, 13, 26, 52, 31, 33, 41, 33, 17, 67}
+ header := Header{"RG", 2}
+ pixel := ParseImage(data, header).InspectPixel(1, 2)
+ fmt.Println(pixel.Color())
+}