フレームバッファとGD

フレームバッファの使い方。
備忘録としてサンプルプログラム。
gd経由で画像ファイル開いてフレームバッファに表示する。


...ところでvinfo->bits_per_pixel == 32の時ってR,G,BそれぞれのMAXって255でいいのかな?
キニシナイ。

#include <stdio.h>
#include <stdlib.h>
#include <gd.h>
#include <string.h>

#include <unistd.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>

#define MIN(aa,bb) (((aa)<(bb))?(aa):(bb))
#define MAX(aa,bb) (((aa)>(bb))?(aa):(bb))

void pset( char* fbp, struct fb_fix_screeninfo* finfo, struct fb_var_screeninfo* vinfo, int x, int y, int r, int g, int b ) {
	long int location = (x + vinfo->xoffset) * (vinfo->bits_per_pixel / 8) + (y + vinfo->yoffset) * finfo->line_length;
	if ( vinfo->bits_per_pixel == 16 ) {
		unsigned short int t = (32 * r / 256) << 11 | (64 * g / 256) << 5 | (32 * b / 256);
		*((unsigned short int*)(fbp + location)) = t;
	} else if ( vinfo->bits_per_pixel == 32 ) {
		*(fbp + location) = b;
		*(fbp + location + 1) = g;
		*(fbp + location + 2) = b;
		*(fbp + location + 3) = 0;
	}
}

int main( int argc, char** argv )
{
	if( argc < 2 ) {
		fprintf( stderr, "usage: %s file\n", argv[0] );
		exit( 1 );
	}
	FILE* fp = fopen( argv[1], "r" );
	if( !fp ) {
		exit( 1 );
	}

	gdImagePtr im = NULL;
	if( strcasestr( argv[1], ".jpeg" ) || strcasestr( argv[1], ".jpe" ) || strcasestr( argv[1], ".jpg" ) ) {
		im = gdImageCreateFromJpeg( fp );
	} else if( strcasestr( argv[1], ".png" ) ) {
		im = gdImageCreateFromPng( fp );
	} else if( strcasestr( argv[1], ".gif" ) ) {
		im = gdImageCreateFromGif( fp );
	}
	if( !im ) {
		fprintf( stderr, "Could NOT create image\n" );
		exit( 1 );
	}

	int fbfd;
	struct fb_var_screeninfo vinfo;
	struct fb_fix_screeninfo finfo;
	long int screensize;
	char* fbp;

	fbfd = open( "/dev/fb0", O_RDWR );
	if( !fbfd ) {
		perror( "open" );
		exit( 1 );
	}
	if( ioctl( fbfd, FBIOGET_FSCREENINFO, &finfo ) ) {
		perror( "ioctl" );
		exit( 1 );
	}
	if( ioctl( fbfd, FBIOGET_VSCREENINFO, &vinfo ) ) {
		perror( "ioctl" );
		exit( 1 );
	}
	
	screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
	fbp = (char *)mmap( 0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0 );
	if( (int)fbp == -1 ) {
		perror( "mmap" );
		exit( 1 );
	}

	for( unsigned int y = 0; y < MIN((unsigned)gdImageSY( im ), vinfo.yres); y++ ) {
		for( unsigned int x = 0; x < MIN((unsigned)gdImageSX( im ), vinfo.xres); x ++ ) {
			int index = gdImageGetPixel( im, x, y );
			int rr = gdImageRed( im, index );
			int gg = gdImageGreen( im, index );
			int bb = gdImageBlue( im, index );
			pset( fbp, &finfo, &vinfo, x, y, rr, gg, bb );
		}
	}

	if( munmap( fbp, screensize ) == -1 ) {
		perror( "munmap" );
	}
	close( fbfd );

	gdImageDestroy( im );
	fclose( fp );
}