Ric*_*nez 34 c linux framebuffer
我最近对一个奇怪的想法感到震惊,即从/ dev/urandom获取输入,将相关字符转换为随机整数,并使用这些整数作为像素的rgb/xy值绘制到屏幕上.
我做了一些研究(这里是关于StackOverflow和其他地方),许多人建议您可以直接写入/ dev/fb0,因为它是设备的文件表示.不幸的是,这似乎没有产生任何视觉上明显的结果.
我发现了一个示例C程序来自QT教程(不再可用),它使用mmap写入缓冲区.程序成功运行,但同样没有输出到屏幕.有趣的是,当我将我的笔记本电脑放入Suspend并稍后恢复时,我看到了一个瞬间闪现的图像(一个红色正方形),它被更早地写入帧缓冲区.写入帧缓冲区是否在Linux中用于绘制屏幕?理想情况下,我想写一个(ba)sh脚本,但C或类似的也可以.谢谢!
编辑:这是示例程序...兽医可能看起来很熟悉.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
int main()
{
int fbfd = 0;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
long int screensize = 0;
char *fbp = 0;
int x = 0, y = 0;
long int location = 0;
// Open the file for reading and writing
fbfd = open("/dev/fb0", O_RDWR);
if (fbfd == -1) {
perror("Error: cannot open framebuffer device");
exit(1);
}
printf("The framebuffer device was opened successfully.\n");
// Get fixed screen information
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) {
perror("Error reading fixed information");
exit(2);
}
// Get variable screen information
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
perror("Error reading variable information");
exit(3);
}
printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
// Figure out the size of the screen in bytes
screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
// Map the device to memory
fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
if ((int)fbp == -1) {
perror("Error: failed to map framebuffer device to memory");
exit(4);
}
printf("The framebuffer device was mapped to memory successfully.\n");
x = 100; y = 100; // Where we are going to put the pixel
// Figure out where in memory to put the pixel
for (y = 100; y < 300; y++)
for (x = 100; x < 300; x++) {
location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +
(y+vinfo.yoffset) * finfo.line_length;
if (vinfo.bits_per_pixel == 32) {
*(fbp + location) = 100; // Some blue
*(fbp + location + 1) = 15+(x-100)/2; // A little green
*(fbp + location + 2) = 200-(y-100)/5; // A lot of red
*(fbp + location + 3) = 0; // No transparency
//location += 4;
} else { //assume 16bpp
int b = 10;
int g = (x-100)/6; // A little green
int r = 31-(y-100)/16; // A lot of red
unsigned short int t = r<<11 | g << 5 | b;
*((unsigned short int*)(fbp + location)) = t;
}
}
munmap(fbp, screensize);
close(fbfd);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Jos*_*e_X 11
我通过以下几个实验取得了成功.
首先,找出X是否使用填充到32位的TrueColor RGB(或者假设是这种情况).然后找出你是否拥有fb0的写权限(并且它存在).如果这些是真的(并且我希望许多现代工具包/台式机/ PC可能会将这些作为默认值),那么您应该能够执行以下操作(如果这些默认设置不成立,那么您可能仍然可以取得一些成功以下测试虽然细节可能有所不同):
测试1:打开一个虚拟终端(在X中)并键入:$ echo"ddd ... ddd">/dev/fb0其中......实际上是几个屏幕满的d.结果将是屏幕顶部的一条或多条(部分)灰线,具体取决于您的回声字符串的长度以及启用的像素分辨率.你也可以选择任何字母(ascii值都小于0x80,因此产生的颜色将是深灰色......如果你想要除灰色之外的东西,可以改变字母).显然,这可以推广到shell循环,或者你可以捕获一个大文件来更清楚地看到效果:例如:$ cat /lib/libc.so.6>/dev/fb0以便看到一些真正的颜色fsf支持者;-P
如果你的大部分屏幕被覆盖,请不要担心.X仍然可以控制鼠标指针,并且仍然知道窗口的映射位置.你所要做的就是抓住任何窗口并将其拖动一点以消除噪音.
测试2:cat/dev/fb0> xxx然后更改桌面的外观(例如,打开新窗口并关闭其他窗口).最后,反过来:cat xxx>/dev/fb0,以便让你的旧桌面恢复!
哈,嗯,不太好.旧桌面的图像是一种幻觉,当您打开任何全屏窗口时,您将很快省去它.
测试3:编写一个小应用程序,抓取/ dev/fb0的先前转储并修改像素的颜色,例如,删除红色组件或增加蓝色,或翻转红色和绿色等.然后回写这些将像素转换为新文件,您可以通过测试2的简单shell方法稍后查看.另外,请注意,您可能会处理每像素BGRA 4字节数量.这意味着您要忽略每个第4个字节,并将每个集合中的第一个视为蓝色组件."ARGB"是big-endian,所以如果你通过增加C数组的索引来访问这些字节,蓝色将首先出现,然后是绿色,然后是红色......即BGRA(不是ARGB).
测试4:使用以视频速度循环的任何语言编写应用程序,将非方形图片(想想xeyes)发送到屏幕的一部分,以便创建没有任何窗口边框的动画.对于额外的点,让动画在整个屏幕上移动.在绘制一小行像素后,您必须确保跳过一个大空间(以弥补可能比动画图片宽得多的屏幕宽度).
测试5:对朋友玩耍,例如,扩展测试4,以便在他们的桌面上弹出一个动画人物的图片(可能拍摄自己以获取像素数据),然后走到他们重要的桌面之一文件夹,拿起文件夹并撕碎它,然后开始歇斯底里地笑,然后有一个火球出来并吞没他们的整个桌面.虽然这一切都是一种幻觉,但它们可能会有点奇怪......但是将它作为一种学习经验来展示Linux和开源,并展示它对于新手来说实际上是多么可怕.["病毒"在Linux上通常是无害的幻想]
如果你正在运行X11,你必须通过X11 API绘制到屏幕上.绕过X服务器非常破碎(而且,正如您所见,通常不起作用).它也可能导致崩溃,或只是一般显示损坏.
如果您希望能够在任何地方运行(控制台和X下),请查看SDL或GGI.如果你只关心X11,你可以使用GTK,QT甚至Xlib.有很多很多选择......