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