github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/fb/fb.go (about) 1 // Copyright 2019-2019 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package fb 6 7 import ( 8 "fmt" 9 "image" 10 "os" 11 12 "github.com/orangecms/go-framebuffer/framebuffer" 13 ) 14 15 const fbdev = "/dev/fb0" 16 17 func DrawOnBufAt( 18 buf []byte, 19 img image.Image, 20 posx int, 21 posy int, 22 stride int, 23 bpp int, 24 ) { 25 for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ { 26 for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ { 27 r, g, b, a := img.At(x, y).RGBA() 28 offset := bpp * ((posy+y)*stride + posx + x) 29 // framebuffer is BGR(A) 30 buf[offset+0] = byte(b) 31 buf[offset+1] = byte(g) 32 buf[offset+2] = byte(r) 33 if bpp >= 4 { 34 buf[offset+3] = byte(a) 35 } 36 } 37 } 38 } 39 40 // FbInit initializes a frambuffer by querying ioctls and returns the width and 41 // height in pixels, the stride, and the bytes per pixel 42 func FbInit() (int, int, int, int, error) { 43 fbo, err := framebuffer.Init(fbdev) 44 if err != nil { 45 return 0, 0, 0, 0, err 46 } 47 width, height := fbo.Size() 48 stride := fbo.Stride() 49 bpp := fbo.Bpp() 50 fmt.Fprintf(os.Stdout, "Framebuffer resolution: %v %v %v %v\n", width, height, stride, bpp) 51 return width, height, stride, bpp, nil 52 } 53 54 func DrawImageAt(img image.Image, posx int, posy int) error { 55 width, height, stride, bpp, err := FbInit() 56 if err != nil { 57 fmt.Fprintf(os.Stderr, "Framebuffer init error: %v\n", err) 58 // fallback values, probably a bad assumption 59 width, height, stride, bpp = 1920, 1080, 1920*4, 4 60 } 61 buf := make([]byte, width*height*bpp) 62 DrawOnBufAt(buf, img, posx, posy, stride, bpp) 63 err = os.WriteFile(fbdev, buf, 0o600) 64 if err != nil { 65 return fmt.Errorf("Error writing to framebuffer: %v", err) 66 } 67 return nil 68 } 69 70 func DrawScaledOnBufAt( 71 buf []byte, 72 img image.Image, 73 posx int, 74 posy int, 75 factor int, 76 stride int, 77 bpp int, 78 ) { 79 for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ { 80 for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ { 81 r, g, b, a := img.At(x, y).RGBA() 82 for sx := 1; sx <= factor; sx++ { 83 for sy := 1; sy <= factor; sy++ { 84 offset := bpp * ((posy+y*factor+sy)*stride + posx + x*factor + sx) 85 buf[offset+0] = byte(b) 86 buf[offset+1] = byte(g) 87 buf[offset+2] = byte(r) 88 if bpp == 4 { 89 buf[offset+3] = byte(a) 90 } 91 } 92 } 93 } 94 } 95 } 96 97 func DrawScaledImageAt(img image.Image, posx int, posy int, factor int) error { 98 width, height, stride, bpp, err := FbInit() 99 if err != nil { 100 fmt.Fprintf(os.Stderr, "Framebuffer init error: %v\n", err) 101 } 102 buf := make([]byte, width*height*bpp) 103 DrawScaledOnBufAt(buf, img, posx, posy, factor, stride, bpp) 104 err = os.WriteFile(fbdev, buf, 0o600) 105 if err != nil { 106 return fmt.Errorf("Error writing to framebuffer: %v", err) 107 } 108 return nil 109 }