注册 登录
编程论坛 C图形专区

求重写putpixel函数

hitzl 发布于 2007-08-31 15:30, 5792 次点击

郁闷了,画图都要靠这个函数,NEO SDK画点也是调用了这个函数,
可是在linux上没有这个函数,
现在想重写这个函数,却不知道如何写.

斑竹,大虾们来开动一下你们脑筋

29 回复
#2
hitzl2007-08-31 17:56

帮帮忙拉

#3
一笔苍穹2007-08-31 23:06

自己实现也行,使用SDL或SVGALIB也行,一千个WIN程序员可能只有一个画点函数,但一千个LINUX程序员就能有一千中画点函数——虽然有些夸张了~

#4
hitzl2007-09-03 09:29

斑竹,目前我查过TUbro C库函数,仍没有找到putpixel函数的源码。由于本人不懂汇编,因此写不出来这个函数的实现。斑竹,帮帮忙吧,搞了好久也搞不掂这个画点东东

#5
一笔苍穹2007-09-03 09:30
你在哪个平台上写啊,不是说LINUX吗?怎么又成TC了
#6
hjj11232007-09-03 09:39
找ROCKCARRY,他肯定能解决。论坛里关于VESA的东西看看有用的。
#7
hjj11232007-09-03 09:45
#include<dos.h>
#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
#include<process.h>
#define VGA256 0x13
#define TEXT_MODE 0x03

unsigned char far *video_buffer=(char far *)0xA0000000L;

unsigned char bit[8]={128,64,32,16,8,4,2,1};

void Delay(int clicks)
{
unsigned int far *clock=(unsigned int far *)0x0000046CL;
unsigned int now;
now=*clock;
while(abs(*clock-now)<clicks){}
}


void Plot_Pixel_Fast(int x,int y,char color)
{
video_buffer[((y<<8)+(y<<6))+x]=color;
}

void GetHzBit(char ch0,char ch1,char *bitdata)
{
FILE *stream;
long fpos;
fpos=32L*(((unsigned char)ch0-161)*94+((unsigned char)ch1-161));
if((stream=fopen("hzk16","rb"))==NULL){
printf("Open hzk16 error!\\n");
exit(0);
}
fseek(stream, fpos, SEEK_SET);
fread( bitdata, 32, 1, stream);
fclose(stream);
}

void WriteHz(char ch0,char ch1,int x,int y,int color)
{
register int i,j,k;
unsigned vpos;
char bitdata[32];
GetHzBit(ch0,ch1,bitdata);
for(i=0;i<16;i++)
for(j=0;j<8;j++){
if(bitdata[2*i]&bit[j])
Plot_Pixel_Fast(x+j,i+y,color);
if(bitdata[2*i+1]&bit[j])
Plot_Pixel_Fast(x+8+j,i+y,color);
}
}
void WriteHzStr(char *str,int x,int y,int color)
{
int num,i,j,xx;
unsigned char s0,s1;
num=strlen(str);
xx=x;
for(i=0;i<num;i+=2){
WriteHz(str[i],str[i+1],xx,y,color);
xx+=16;
}
}

void Words_Step(char *str,int x,int y,int color,int speed)
{
int num,i,j,xx;
unsigned char s0,s1;
num=strlen(str);
xx=x;
for(i=0;i<num;i+=2){
WriteHz(str[i],str[i+1],xx,y,color);
Delay(speed);
xx+=16;
}
}

void Set_Video_Mode(int mode)
{
union REGS inregs,outregs;
inregs.h.ah=0;
inregs.h.al=(unsigned char)mode;
int86(0x10,&inregs,&outregs);
}

void main(void)
{
Set_Video_Mode(VGA256);
WriteHzStr("按任意键进入中文渐显:",10,100,WHITE);
getch();
Words_Step("现在文字处于渐显状态。",10,130,WHITE,4);
getch();
Set_Video_Mode(TEXT_MODE);
}
这是别人在这个论坛里贴出来的,它已经包括了你需要的东西。
#8
hjj11232007-09-03 09:46
发贴前最好把论坛里的帖子看一遍。
#9
hjj11232007-09-03 09:47
#10
hitzl2007-09-03 12:59

谢谢 hjj1123 的回复。但是问题仍没有解决。
开始我没有把问题说清楚,再重新说明一下这个问题

问题:我在Linux上需要调用一个画点函数。

由于在linux平台没有的画点函数,因此我看完一笔苍穹斑竹的文章后,开始尝试重写Tubro C的putpixel画点函数。但是我参考的“库函数源码大全”并没有给出putpixel的源代码(“大全”基本上对graphic.h里声明函数都没有给出函数的定义,只是说明了一下使用方法)。而我又不懂汇编编程,因此不知道如何在Linux下重写这个函数。

之所以在Tubro C里库函数里要查找putpixel,就是想借鉴一下Tubro C里怎么写的该函数。

hjj1123贴出来的内容似乎也和画点函数不相关,呵。不过还是很感谢hjj1123的关注。

#11
一笔苍穹2007-09-03 13:20
你用的是哪个LINUX的发行版,你先确认一下你的LINUX是否内置了对SDL的支持?如果支持的话就很好办。
#12
hitzl2007-09-03 16:55
我使用的是fedora,目前还不知道这个版本的Linux是否支持SDL。过会我查一下是否支持。现在有另外一个想法,利用Linux自带的curses.h库

#include "curses.h"
void putpixeles(int x, int y, char color)
{
move(x, y);
fputchar(color);

}

找到所有的颜色对应的16进制码,将它们列出各种颜色的预定义。
这样做可否





#13
一笔苍穹2007-09-03 17:38
Fedora有,我装的也是Fedora
明天接着聊吧
#14
hitzl2007-09-03 18:17
回复:(hitzl)求重写putpixel函数

我的那个方法不可行,混淆了象素坐标和字符坐标的含义。

呵呵,看来还是要期待斑竹的方法了

#15
hjj11232007-09-04 08:42

无语.难得解释...............

#16
一笔苍穹2007-09-04 09:54

#include <stdlib.h>
#include <SDL/SDL.h>


/* 无字序无关的颜色掩码,用于跨平台 */
#if SDL_BYTEORDER != SDL_BIG_ENDIAN
Uint32 g_rmask = 0x00ff0000;
Uint32 g_gmask = 0x0000ff00;
Uint32 g_bmask = 0x000000ff;
Uint32 g_amask = 0x00000000;
#else
Uint32 g_rmask = 0x000000ff;
Uint32 g_gmask = 0x0000ff00;
Uint32 g_bmask = 0x00ff0000;
Uint32 g_amask = 0xff000000;
#endif

/* 程序的分辨率和色深 */
const int SCREEN_W = 640;
const int SCREEN_H = 480;
const int SCREEN_BPP = 32;

/* 用于组合颜色分量成一个颜色值 */
#define XRGB(r, g, b) SDL_MapRGB(screen->format, r, g, b)

/* 全局屏幕表面 */
SDL_Surface *screen = NULL;

void DrawPixel(SDL_Surface *, int, int, Uint32);
void PutPixel(int, int, Uint32);

/* 向表面上的(x, y)画一个颜色为color的点 */
void DrawPixel(SDL_Surface *surface, int x, int y, Uint32 color)
{
int bpp = surface->format->BytesPerPixel;
SDL_Surface *pixel = SDL_CreateRGBSurface(SDL_HWSURFACE, 1, 1, bpp << 3, g_rmask,
g_gmask, g_bmask, g_amask);
SDL_Rect rect;
rect.x = x;
rect.y = y;
rect.w = rect.h = 1;

SDL_FillRect(pixel, NULL, color);
SDL_BlitSurface(pixel, NULL, surface, &rect);
SDL_FreeSurface(pixel);
}

/* 将DrawPixel封装成类似于TC的 putpixel 函数,即直接向屏幕指定位置画点 */
void PutPixel(int x, int y, Uint32 color)
{
DrawPixel(screen, x, y, color);
}


/* 测试函数 */
int main (int argc, char *argv[])
{
SDL_Event event;
int done = 0; /* 主循环退出标志 */

/* 初始化 SDL */
if (SDL_Init (SDL_INIT_VIDEO) < 0)
{
exit (1);
}
atexit (SDL_Quit);

/* 设置图形模式 */
screen = SDL_SetVideoMode (SCREEN_W, SCREEN_H, SCREEN_BPP, SDL_HWSURFACE | SDL_DOUBLEBUF);
if (screen == NULL)
{
exit (2);
}
SDL_WM_SetCaption ("SDL Put Pixel", NULL); /* 设置窗口标题 */

while (!done) /* 主循环 */
{
/* 检查事件 */
while (SDL_PollEvent (&event))
{
switch (event.type)
{
case SDL_KEYDOWN: /* 按任意键退出 */
done = 1;
break;
case SDL_QUIT:
done = 1;
break;
default:break;
}
}

/* 在屏幕上的随机位置画白色的点 */
PutPixel(rand() & 511, rand() & 511, XRGB(255, 255, 255));
/* 将后台页显示到前台页 */
SDL_Flip (screen);
/* 延时 */
SDL_Delay (1);
}

return 0;
}

#17
一笔苍穹2007-09-04 10:06
以上代码在Fedora 7下通过,另外在WINDOWS下的DEV-CPP + SDL也可以使用。
基本的SDL库没有带画点或画线之类的函数,但扩展库中提供了。这里是假设你只有基本库,而且这个方法与SDL官方文档中提到的锁表面直接写显存再解锁不同,这个方法是通过表面之间的直接Blit实现的,不需要锁表面,如果有心对其优化的话,效率会很高。
在Fedora下找个文本编辑器粘贴进去保存为一个.C文件(这里假设是mian.c),再打开控制台,进入该文件所在路径,敲入gcc main.c -lSDL回车(注意大小写)就可以在同目录下看到一个a.out输出文件了,当然也可以通过“-o”参数指定输出文件名。再在控制台中敲入./a.out或者直接双击a.out文件都可以执行它,按任意键退出运行。
现在给你画点的方案了,这也仅仅是LINUX下画点的方案之一,由于在LINUX下进行游戏开发SDL比较常用,所以介绍了此法,如果你有兴趣,可以到我的主页http://www.ds0101.com/找到一些关于SDL的资料。
#18
hitzl2007-09-04 11:22

拜谢一笔苍穹斑竹!

讲授的非常细致。连编译过程和测试代码都写来了。呵呵,斑竹真是侠肠骨道。

我这样的初哥very受益啊

#19
hitzl2007-09-04 15:28


/* 初始化 SDL */
if (SDL_Init (SDL_INIT_VIDEO) < 0)
{
printf("SDL_Init is failed"); //加了一条打印
exit (1);

}

编译通过了。

调试时,初始化的过程出现了一个问题。
我加了这条打印。发现是SDL初始化过程失败了。
(在编译过程中,我确实加了-lSDL的参数)

#20
hitzl2007-09-04 16:11


。。。
/* 初始化 SDL */
if (SDL_Init (SDL_INIT_VIDEO) < 0)
{
printf("could not initialize SDL: %s\n",SDL_GetError()); //修改一次提示信息
exit (1);
}
。。。。

root\> gcc main.c -o main -lSDL
root\> ./main
root\> could not initialize SDL: No available video device


初始化失败,不能找到可用的视频设备。
我又从google找了一个最简单初始化SDL的例子来调试SDL初始化过程,结果是仍然不能初始化。那么这个视频设备到底是指什么呢?是不是我的显示器。为何我在本地不能初始化呢.


测试初始化SDL的例子附下:
#include <SDL/SDL.h>
#include <stdio.h>

int main() {

printf("Initializing SDL.\n");

/* Initialize defaults, Video and Audio */
if((SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO)==-1)) {
printf("Could not initialize SDL: %s.\n", SDL_GetError());
exit(-1);
}

printf("SDL initialized.\n");

printf("Quiting SDL.\n");

/* Shutdown all subsystems */
SDL_Quit();

printf("Quiting....\n");

exit(0);
}



#21
一笔苍穹2007-09-04 16:22

你在图形窗口下吗,系统中别的图形程序运行没问题吧?Framebuffer加载配置了没?

#22
hitzl2007-09-05 12:27

运行curses.h库调试过程没有问题。

Framebuffer没有配置,需要如何配置呢

#23
hitzl2007-09-05 12:39

我在Linux字符命令行模式下,写程序和调试程序的。

如同下面的这个测试例子,这里面也同样没有设置Framebuffer啊。可结果一样的,仍不能初始化成功。
我在本地机器加载linux自带的curses.h库,写程序调试过程没有出现任何问题。

难道配置Framebuffer是加载SDL.h库必须的一个步骤吗,应该怎么做呢

#include <SDL/SDL.h>
#include <stdio.h>

int main() {

printf("Initializing SDL.\n");

/* Initialize defaults, Video and Audio */
if((SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO)==-1)) {
printf("Could not initialize SDL: %s.\n", SDL_GetError());
exit(-1);
}

printf("SDL initialized.\n");

printf("Quiting SDL.\n");

/* Shutdown all subsystems */
SDL_Quit();

printf("Quiting....\n");

exit(0);
}

#24
一笔苍穹2007-09-05 13:42

如果你不是在XWINDOW下面,而且没开启framebuffer,就需要手动进行配置。配置完了才能运行基于SVGA的图形程序,根据启动管理器的不同,会有两种配置方法:
如果你用的 grub来引导系统,要修改 /etc/grub.conf文件,打开此文件找到类似这样的一行(这里的例子是Fedara core4的):
kernel /boot/vmlinuz-2.6.11-1.1369_FC4 ro root=LABEL=/1 rhgb quiet
在最后加上个VGA的显示模式,例如1024X768,256色的773号模式:
kernel /boot/vmlinuz-2.6.11-1.1369_FC4 ro root=LABEL=/1 rhgb quiet vga=773
改过保存后,重启系统,进入Linux ,就能看出是否起作用了。

如果你用 lilo引导,就要改 /etc/lilo.conf这个文件 ;lilo的配置比较简单,因为vga=xxx是独立的一行。并且lilo.conf中有详细的配置参数,也就是我下面列出的那些模式号,就是来自 lilo.conf的。想打开哪个参数,就把vga=xxx前面的注释“#”号去掉就行,当然不能同时打开多个(要注意的是:如果改了lilo.conf后,得执行 lilo -v):
# Normal VGA console
# vga = normal
# VESA framebuffer console @ 1024x768x64k
# vga=791
# VESA framebuffer console @ 1024x768x32k
# vga=790
# VESA framebuffer console @ 1024x768x256
# vga=773
# VESA framebuffer console @ 800x600x64k
# vga=788
# VESA framebuffer console @ 800x600x32k
# vga=787
# VESA framebuffer console @ 800x600x256
# vga=771
# VESA framebuffer console @ 640x480x64k
# vga=785
# VESA framebuffer console @ 640x480x32k
# vga=784
# VESA framebuffer console @ 640x480x256
# vga=769

#25
hitzl2007-09-05 16:12
确认用的是grub来引导系统。

并且我在本地的文件里添加下面的划线部分的参数。
kernel /boot/vmlinuz-2.6.11-1.1369_FC4 ro root=LABEL=/1 rhgb quiet vga=773

但重新启动系统后,问题依旧。。。哭了

root\> could not initialize SDL: No available video device
#26
hitzl2007-09-06 11:27

SDL的初始化还是有问题。如之奈何?

#27
一笔苍穹2007-09-06 16:37
你的机器是什么配置啊?能进XWINDOW不?命令是startx
#28
hitzl2007-09-10 19:08

startx不能启动图形化界面,因为我是用SSH远程登陆服务器。

服务器已经是图形化界面了,我的本地不能启动图形化界面

#29
wangxy2006962007-09-11 01:57
想写一个点,应孩先了解显卡寄存器和你想用那一个显示模式
#30
maqingqin2010-08-17 13:35
void dian(int x,int y,int color)
{union REGS r;
 r.h.ah=0x0c;
 r.h.al=color;
 r.h.bh=0;
 r.x.cx=x;
 r.x.dx=y;
 int86(0x10,&r,&r);
}
1