github.com/amitbet/vnc2video@v0.0.0-20190616012314-9d50b9dab1d9/encoding_tightpng.go (about)

     1  package vnc2video
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"image"
     8  	"image/color"
     9  	"image/draw"
    10  	"image/png"
    11  	"io"
    12  	"github.com/amitbet/vnc2video/logger"
    13  )
    14  
    15  func (*TightPngEncoding) Supported(Conn) bool {
    16  	return true
    17  }
    18  func (*TightPngEncoding) Reset() error {
    19  	return nil
    20  }
    21  
    22  func (enc *TightPngEncoding) Write(c Conn, rect *Rectangle) error {
    23  	if err := writeTightCC(c, enc.TightCC); err != nil {
    24  		return err
    25  	}
    26  	cmp := enc.TightCC.Compression
    27  	switch cmp {
    28  	case TightCompressionPNG:
    29  		buf := bPool.Get().(*bytes.Buffer)
    30  		buf.Reset()
    31  		defer bPool.Put(buf)
    32  		pngEnc := &png.Encoder{CompressionLevel: png.BestSpeed}
    33  		//pngEnc := &png.Encoder{CompressionLevel: png.NoCompression}
    34  		if err := pngEnc.Encode(buf, enc.Image); err != nil {
    35  			return err
    36  		}
    37  		if err := writeTightLength(c, buf.Len()); err != nil {
    38  			return err
    39  		}
    40  
    41  		if _, err := buf.WriteTo(c); err != nil {
    42  			return err
    43  		}
    44  	case TightCompressionFill:
    45  		var tpx TightPixel
    46  		r, g, b, _ := enc.Image.At(0, 0).RGBA()
    47  		tpx.R = uint8(r)
    48  		tpx.G = uint8(g)
    49  		tpx.B = uint8(b)
    50  		if err := binary.Write(c, binary.BigEndian, tpx); err != nil {
    51  			return err
    52  		}
    53  	default:
    54  		return fmt.Errorf("unknown tight compression %d", cmp)
    55  	}
    56  	return nil
    57  }
    58  
    59  type TightPngEncoding struct {
    60  	TightCC *TightCC
    61  	Image   draw.Image
    62  }
    63  
    64  func (*TightPngEncoding) Type() EncodingType { return EncTightPng }
    65  
    66  func (enc *TightPngEncoding) Read(c Conn, rect *Rectangle) error {
    67  	tcc, err := readTightCC(c)
    68  	logger.Trace("starting to read a tight rect: %v", rect)
    69  	if err != nil {
    70  		return err
    71  	}
    72  	enc.TightCC = tcc
    73  	cmp := enc.TightCC.Compression
    74  	switch cmp {
    75  	case TightCompressionPNG:
    76  		l, err := readTightLength(c)
    77  		if err != nil {
    78  			return err
    79  		}
    80  		img, err := png.Decode(io.LimitReader(c, int64(l)))
    81  		if err != nil {
    82  			return err
    83  		}
    84  		//draw.Draw(enc.Image, enc.Image.Bounds(), img, image.Point{X: int(rect.X), Y: int(rect.Y)}, draw.Src)
    85  		DrawImage(enc.Image, img, image.Point{X: int(rect.X), Y: int(rect.Y)})
    86  	case TightCompressionFill:
    87  		var tpx TightPixel
    88  		if err := binary.Read(c, binary.BigEndian, &tpx); err != nil {
    89  			return err
    90  		}
    91  		//enc.Image = image.NewRGBA(image.Rect(0, 0, 1, 1))
    92  		col := color.RGBA{R: tpx.R, G: tpx.G, B: tpx.B, A: 1}
    93  		myRect := MakeRectFromVncRect(rect)
    94  		FillRect(enc.Image, &myRect, col)
    95  		//enc.Image.(draw.Image).Set(0, 0, color.RGBA{R: tpx.R, G: tpx.G, B: tpx.B, A: 1})
    96  	default:
    97  		return fmt.Errorf("unknown compression %d", cmp)
    98  	}
    99  	return nil
   100  }
   101  
   102  func (enc *TightPngEncoding) SetTargetImage(img draw.Image) {
   103  	enc.Image = img
   104  }