github.com/amitbet/vnc2video@v0.0.0-20190616012314-9d50b9dab1d9/image.go (about) 1 package vnc2video 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "image" 7 "github.com/amitbet/vnc2video/logger" 8 ) 9 10 //var _ draw.Drawer = (*ServerConn)(nil) 11 //var _ draw.Image = (*ServerConn)(nil) 12 13 // Color represents a single color in a color map. 14 type Color struct { 15 pf *PixelFormat 16 cm *ColorMap 17 cmIndex uint32 // Only valid if pf.TrueColor is false. 18 R, G, B uint16 19 } 20 21 // ColorMap represent color map 22 type ColorMap [256]Color 23 24 // NewColor returns a new Color object 25 func NewColor(pf *PixelFormat, cm *ColorMap) *Color { 26 return &Color{ 27 pf: pf, 28 cm: cm, 29 } 30 } 31 32 // Rectangle represents a rectangle of pixel data 33 type Rectangle struct { 34 X, Y uint16 35 Width, Height uint16 36 EncType EncodingType 37 Enc Encoding 38 } 39 40 // String return string representation 41 func (rect *Rectangle) String() string { 42 return fmt.Sprintf("rect x: %d, y: %d, width: %d, height: %d, enc: %s", rect.X, rect.Y, rect.Width, rect.Height, rect.EncType) 43 } 44 45 // NewRectangle returns new rectangle 46 func NewRectangle() *Rectangle { 47 return &Rectangle{} 48 } 49 50 // Write marshal color to conn 51 func (clr *Color) Write(c Conn) error { 52 var err error 53 pf := c.PixelFormat() 54 order := pf.order() 55 pixel := clr.cmIndex 56 if clr.pf.TrueColor != 0 { 57 pixel = uint32(clr.R) << pf.RedShift 58 pixel |= uint32(clr.G) << pf.GreenShift 59 pixel |= uint32(clr.B) << pf.BlueShift 60 } 61 62 switch pf.BPP { 63 case 8: 64 err = binary.Write(c, order, byte(pixel)) 65 case 16: 66 err = binary.Write(c, order, uint16(pixel)) 67 case 32: 68 err = binary.Write(c, order, uint32(pixel)) 69 } 70 71 return err 72 } 73 74 // Read unmarshal color from conn 75 func (clr *Color) Read(c Conn) error { 76 order := clr.pf.order() 77 var pixel uint32 78 79 switch clr.pf.BPP { 80 case 8: 81 var px uint8 82 if err := binary.Read(c, order, &px); err != nil { 83 return err 84 } 85 pixel = uint32(px) 86 case 16: 87 var px uint16 88 if err := binary.Read(c, order, &px); err != nil { 89 return err 90 } 91 pixel = uint32(px) 92 case 32: 93 var px uint32 94 if err := binary.Read(c, order, &px); err != nil { 95 return err 96 } 97 pixel = uint32(px) 98 } 99 100 if clr.pf.TrueColor != 0 { 101 clr.R = uint16((pixel >> clr.pf.RedShift) & uint32(clr.pf.RedMax)) 102 clr.G = uint16((pixel >> clr.pf.GreenShift) & uint32(clr.pf.GreenMax)) 103 clr.B = uint16((pixel >> clr.pf.BlueShift) & uint32(clr.pf.BlueMax)) 104 } else { 105 *clr = clr.cm[pixel] 106 clr.cmIndex = pixel 107 } 108 return nil 109 } 110 111 func colorsToImage(x, y, width, height uint16, colors []Color) *image.RGBA64 { 112 rect := image.Rect(int(x), int(y), int(x+width), int(y+height)) 113 rgba := image.NewRGBA64(rect) 114 a := uint16(1) 115 for i, color := range colors { 116 rgba.Pix[4*i+0] = uint8(color.R >> 8) 117 rgba.Pix[4*i+1] = uint8(color.R) 118 rgba.Pix[4*i+2] = uint8(color.G >> 8) 119 rgba.Pix[4*i+3] = uint8(color.G) 120 rgba.Pix[4*i+4] = uint8(color.B >> 8) 121 rgba.Pix[4*i+5] = uint8(color.B) 122 rgba.Pix[4*i+6] = uint8(a >> 8) 123 rgba.Pix[4*i+7] = uint8(a) 124 } 125 return rgba 126 } 127 128 // Write marshal rectangle to conn 129 func (rect *Rectangle) Write(c Conn) error { 130 var err error 131 132 if err = binary.Write(c, binary.BigEndian, rect.X); err != nil { 133 return err 134 } 135 if err = binary.Write(c, binary.BigEndian, rect.Y); err != nil { 136 return err 137 } 138 if err = binary.Write(c, binary.BigEndian, rect.Width); err != nil { 139 return err 140 } 141 if err = binary.Write(c, binary.BigEndian, rect.Height); err != nil { 142 return err 143 } 144 if err = binary.Write(c, binary.BigEndian, rect.EncType); err != nil { 145 return err 146 } 147 148 return rect.Enc.Write(c, rect) 149 } 150 151 // Read unmarshal rectangle from conn 152 func (rect *Rectangle) Read(c Conn) error { 153 var err error 154 155 if err = binary.Read(c, binary.BigEndian, &rect.X); err != nil { 156 return err 157 } 158 if err = binary.Read(c, binary.BigEndian, &rect.Y); err != nil { 159 return err 160 } 161 if err = binary.Read(c, binary.BigEndian, &rect.Width); err != nil { 162 return err 163 } 164 if err = binary.Read(c, binary.BigEndian, &rect.Height); err != nil { 165 return err 166 } 167 if err = binary.Read(c, binary.BigEndian, &rect.EncType); err != nil { 168 return err 169 } 170 logger.Debug(rect) 171 switch rect.EncType { 172 // case EncCopyRect: 173 // rect.Enc = &CopyRectEncoding{} 174 // case EncTight: 175 // rect.Enc = c.GetEncInstance(rect.EncType) 176 // case EncTightPng: 177 // rect.Enc = &TightPngEncoding{} 178 // case EncRaw: 179 // if strings.HasPrefix(c.Protocol(), "aten") { 180 // rect.Enc = &AtenHermon{} 181 // } else { 182 // rect.Enc = &RawEncoding{} 183 // } 184 case EncDesktopSizePseudo: 185 rect.Enc = &DesktopSizePseudoEncoding{} 186 case EncDesktopNamePseudo: 187 rect.Enc = &DesktopNamePseudoEncoding{} 188 // case EncXCursorPseudo: 189 // rect.Enc = &XCursorPseudoEncoding{} 190 // case EncAtenHermon: 191 // rect.Enc = &AtenHermon{} 192 default: 193 rect.Enc = c.GetEncInstance(rect.EncType) 194 if rect.Enc == nil { 195 return fmt.Errorf("unsupported encoding %s", rect.EncType) 196 } 197 } 198 199 return rect.Enc.Read(c, rect) 200 } 201 202 // Area returns the total area in pixels of the Rectangle 203 func (rect *Rectangle) Area() int { return int(rect.Width) * int(rect.Height) }