FramebufferAccess

De Wiki LOGre
Aller à : navigation, rechercher


But

Il n'est pas toujours facile, sur la RPI et en mode console (pas de serveur X), de savoir quelle est la resolution du Framebuffer. On peut tenter de faire confiance à l'utilitaire tvservice --status du firmware mais pas tip top. fbset est nettement plus précis.

Quoiqu'il en soit voici un petit bout de code trouvé sur le net et un peu modifié pour blitter direct dans le framebuffer via /dev/fb0

Rappel

En mode composite, la RPI n'est capable de n'envoyer que 4 types de signaux: modes PAL, PAL-60, NTSC et NTSC-J. Ensuite le GPU gère un framebuffer de taille variable et mis à l'échelle avant envoi au téléviseur. Par exemple, en mode NTSC, le signal est codé en 720x480 à 60Hz mais le Framebuffer par défaut fait 656x416 et 32 pixels d'overscan non accessible via le fb.

Code

#include<unistd.h>
#include<sys/types.h>
#include<sys/mman.h>
#include<sys/time.h>
#include<stdio.h>
#include<fcntl.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
 
/* bmptoraw: utility to convert bitmap files to raw 16 bit data
 
   Usage:
   ./bmptoraw pic.bmp > pic.raw
 
   pic.raw can then be used to blit in the fb:
 
   cat pic.raw > /dev/fb0
 
   This program assumes a 24 bit bitmap file with a 54 byte header,
   which is the most common form of bitmap.
 
   Compiled on the ARM platform:
   gcc -Wall bmptoraw.c -o bmptoraw
*/
 
int main(int argc, char **argv) 
{
  volatile unsigned char *bmp;
  int fd;
  int i, j, offset;
  int length, page;
  char red, blue, green, char1, char2;
 
  unsigned int width = 656;
  unsigned int height = 416;
 
  assert(argc = 2);
 
  page = getpagesize();
  length = (((height*width*3 + 56)/page) + 1) * page;
 
  fd = open(argv[1], O_RDONLY);
  bmp = (unsigned char *)mmap(0, length, PROT_READ, MAP_SHARED, fd, 0);
 
  // check BMP format
  assert(bmp[0] == 'B');
  assert(bmp[1] == 'M');
  assert(bmp[0xa] == 54);
 
  // retrieve file infos
 
  width = (bmp[0x13] * 256) + bmp[0x12];
  height = (bmp[0x17] * 256) + bmp[0x16];
  //printf("width : %d height : %d\n", width, height);
 
  for(i=0;i<height;i++) 
  {
    for(j=0;j<width;j++) 
    {
      offset = (3*width) * ((height - 1)- i) + 54 + j * 3;
      blue = bmp[offset];
      green = bmp[offset + 1];
      red = bmp[offset + 2];
      char2 = red & 0xf8;
      char2 |= green >> 5;
      char1 = blue >> 3;
      char1 |= (green & 0xf8) << 3;
      putchar(char1);
      putchar(char2);
    }
  }
 
  munmap((unsigned int *)bmp, length);
  close(fd);
  return 0;
 
}

Utilisation

gcc -Wall  bmptoraw.c -o bmptoraw
./bmptoraw mire656x416.bmp > mire.raw
cat mire.raw > /dev/fb0

Sources