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  }