hitzl 发表于 2007-8-31 15:30

求重写putpixel函数

<P>郁闷了,画图都要靠这个函数,NEO SDK画点也是调用了这个函数,<BR>可是在linux上没有这个函数,<BR>现在想重写这个函数,却不知道如何写.<BR><BR>斑竹,大虾们来开动一下你们脑筋<BR><BR></P>

hitzl 发表于 2007-8-31 17:56

<P>帮帮忙拉</P>

一笔苍穹 发表于 2007-8-31 23:06

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

hitzl 发表于 2007-9-3 09:29

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

一笔苍穹 发表于 2007-9-3 09:30

你在哪个平台上写啊,不是说LINUX吗?怎么又成TC了

hjj1123 发表于 2007-9-3 09:39

找ROCKCARRY,他肯定能解决。论坛里关于VESA的东西看看有用的。

hjj1123 发表于 2007-9-3 09:45

#include&lt;dos.h&gt;   <br>  #include&lt;conio.h&gt;   <br>  #include&lt;stdio.h&gt;   <br>  #include&lt;stdlib.h&gt;   <br>  #include&lt;process.h&gt;   <br>  #define   VGA256   0x13   <br>  #define   TEXT_MODE   0x03   <br>    <br>  unsigned   char   far   *video_buffer=(char   far   *)0xA0000000L;   <br>    <br>  unsigned   char   bit[8]={128,64,32,16,8,4,2,1};   <br>    <br>  void   Delay(int   clicks)   <br>  {   <br>  unsigned   int   far   *clock=(unsigned   int   far   *)0x0000046CL;   <br>  unsigned   int   now;   <br>  now=*clock;   <br>  while(abs(*clock-now)&lt;clicks){}   <br>  }   <br>    <br>    <br>  void   Plot_Pixel_Fast(int   x,int   y,char   color)   <br>  {   <br>  video_buffer[((y&lt;&lt;8)+(y&lt;&lt;6))+x]=color;   <br>  }   <br>    <br>  void   GetHzBit(char   ch0,char   ch1,char   *bitdata)   <br>  {   <br>  FILE   *stream;   <br>  long   fpos;   <br>  fpos=32L*(((unsigned   char)ch0-161)*94+((unsigned   char)ch1-161));   <br>  if((stream=fopen("hzk16","rb"))==NULL){   <br>  printf("Open   hzk16   error!\\n");   <br>  exit(0);   <br>  }   <br>  fseek(stream,   fpos,   SEEK_SET);   <br>  fread(   bitdata,   32,   1,   stream);   <br>  fclose(stream);   <br>  }   <br>    <br>  void   WriteHz(char   ch0,char   ch1,int   x,int   y,int   color)   <br>  {   <br>  register   int   i,j,k;   <br>  unsigned   vpos;   <br>  char   bitdata[32];   <br>  GetHzBit(ch0,ch1,bitdata);   <br>  for(i=0;i&lt;16;i++)   <br>  for(j=0;j&lt;8;j++){   <br>  if(bitdata[2*i]&amp;bit[j])   <br>  Plot_Pixel_Fast(x+j,i+y,color);   <br>  if(bitdata[2*i+1]&amp;bit[j])   <br>  Plot_Pixel_Fast(x+8+j,i+y,color);   <br>  }   <br>  }   <br>  void   WriteHzStr(char   *str,int   x,int   y,int   color)   <br>  {   <br>  int   num,i,j,xx;   <br>  unsigned   char   s0,s1;   <br>  num=strlen(str);   <br>  xx=x;   <br>  for(i=0;i&lt;num;i+=2){   <br>  WriteHz(str[i],str[i+1],xx,y,color);   <br>  xx+=16;   <br>  }   <br>  }   <br>    <br>  void   Words_Step(char   *str,int   x,int   y,int   color,int   speed)   <br>  {   <br>  int   num,i,j,xx;   <br>  unsigned   char   s0,s1;   <br>  num=strlen(str);   <br>  xx=x;   <br>  for(i=0;i&lt;num;i+=2){   <br>  WriteHz(str[i],str[i+1],xx,y,color);   <br>  Delay(speed);   <br>  xx+=16;   <br>  }   <br>  }   <br>    <br>  void   Set_Video_Mode(int   mode)   <br>  {   <br>  union   REGS   inregs,outregs;   <br>  inregs.h.ah=0;   <br>  inregs.h.al=(unsigned   char)mode;   <br>  int86(0x10,&amp;inregs,&amp;outregs);   <br>  }   <br>    <br>  void   main(void)   <br>  {   <br>  Set_Video_Mode(VGA256);   <br>  WriteHzStr("按任意键进入中文渐显:",10,100,WHITE);   <br>  getch();   <br>  Words_Step("现在文字处于渐显状态。",10,130,WHITE,4);   <br>  getch();   <br>  Set_Video_Mode(TEXT_MODE);   <br>  }  <br>这是别人在这个论坛里贴出来的,它已经包括了你需要的东西。<br>

hjj1123 发表于 2007-9-3 09:46

发贴前最好把论坛里的帖子看一遍。

hjj1123 发表于 2007-9-3 09:47

http://bbs.bc-cn.net/viewthread.php?tid=151828<br><br>

hitzl 发表于 2007-9-3 12:59

<P>谢谢 hjj1123 的回复。但是问题仍没有解决。<BR>开始我没有把问题说清楚,再重新说明一下这个问题<BR><BR>问题:我在Linux上需要调用一个画点函数。<BR><BR>由于在linux平台没有的画点函数,因此我看完一笔苍穹斑竹的文章后,开始尝试重写Tubro C的putpixel画点函数。但是我参考的“库函数源码大全”并没有给出putpixel的源代码(“大全”基本上对graphic.h里声明函数都没有给出函数的定义,只是说明了一下使用方法)。而我又不懂汇编编程,因此不知道如何在Linux下重写这个函数。<BR><BR>之所以在Tubro C里库函数里要查找putpixel,就是想借鉴一下Tubro C里怎么写的该函数。<BR><BR>hjj1123贴出来的内容似乎也和画点函数不相关,呵。不过还是很感谢hjj1123的关注。<BR></P>

一笔苍穹 发表于 2007-9-3 13:20

你用的是哪个LINUX的发行版,你先确认一下你的LINUX是否内置了对SDL的支持?如果支持的话就很好办。

hitzl 发表于 2007-9-3 16:55

我使用的是fedora,目前还不知道这个版本的Linux是否支持SDL。过会我查一下是否支持。现在有另外一个想法,利用Linux自带的curses.h库<BR><BR>#include "curses.h"<BR>void putpixeles(int x, int y, char color)<BR>{<BR>    move(x, y);<BR>    fputchar(color);    <BR><BR>}<BR><BR>找到所有的颜色对应的16进制码,将它们列出各种颜色的预定义。<BR>这样做可否<BR><BR><BR><BR><BR><BR>

一笔苍穹 发表于 2007-9-3 17:38

Fedora有,我装的也是Fedora<BR>明天接着聊吧

hitzl 发表于 2007-9-3 18:17

回复:(hitzl)求重写putpixel函数

<P>我的那个方法不可行,混淆了象素坐标和字符坐标的含义。<BR><BR>呵呵,看来还是要期待斑竹的方法了</P>

hjj1123 发表于 2007-9-4 08:42

<P>无语.难得解释...............<BR></P>

一笔苍穹 发表于 2007-9-4 09:54

<P>#include &lt;stdlib.h&gt;<BR>#include &lt;SDL/SDL.h&gt;</P>
<P><BR>/* 无字序无关的颜色掩码,用于跨平台 */<BR>#if SDL_BYTEORDER != SDL_BIG_ENDIAN<BR>Uint32 g_rmask = 0x00ff0000;<BR>Uint32 g_gmask = 0x0000ff00;<BR>Uint32 g_bmask = 0x000000ff;<BR>Uint32 g_amask = 0x00000000;<BR>#else<BR>Uint32 g_rmask = 0x000000ff;<BR>Uint32 g_gmask = 0x0000ff00;<BR>Uint32 g_bmask = 0x00ff0000;<BR>Uint32 g_amask = 0xff000000;<BR>#endif</P>
<P>/* 程序的分辨率和色深 */<BR>const int  SCREEN_W  =  640;<BR>const int  SCREEN_H  =  480;<BR>const int  SCREEN_BPP = 32;</P>
<P>/* 用于组合颜色分量成一个颜色值 */ <BR>#define  XRGB(r, g, b) SDL_MapRGB(screen-&gt;format, r, g, b)</P>
<P>/* 全局屏幕表面 */<BR>SDL_Surface *screen  = NULL;</P>
<P>void  DrawPixel(SDL_Surface *, int, int, Uint32);<BR>void  PutPixel(int, int, Uint32);</P>
<P>/* 向表面上的(x, y)画一个颜色为color的点 */<BR>void  DrawPixel(SDL_Surface *surface, int x, int y, Uint32 color)<BR>{<BR>    int bpp = surface-&gt;format-&gt;BytesPerPixel;<BR>    SDL_Surface *pixel = SDL_CreateRGBSurface(SDL_HWSURFACE, 1, 1, bpp &lt;&lt; 3, g_rmask,<BR>                                              g_gmask, g_bmask, g_amask);<BR>    SDL_Rect rect;<BR>    rect.x = x;<BR>    rect.y = y;<BR>    rect.w = rect.h = 1;</P>
<P>    SDL_FillRect(pixel, NULL, color);<BR>    SDL_BlitSurface(pixel, NULL, surface, &amp;rect);<BR>    SDL_FreeSurface(pixel); <BR>}</P>
<P>/* 将DrawPixel封装成类似于TC的 putpixel 函数,即直接向屏幕指定位置画点 */<BR>void  PutPixel(int x, int y, Uint32 color)<BR>{<BR>    DrawPixel(screen, x, y, color);<BR>}</P>
<P><BR>/* 测试函数 */<BR>int main (int argc, char *argv[])<BR>{<BR>    SDL_Event event;<BR>    int done = 0; /* 主循环退出标志 */<BR>    <BR>    /* 初始化 SDL */<BR>    if (SDL_Init (SDL_INIT_VIDEO) &lt; 0)<BR>    {<BR>        exit (1);<BR>    }<BR>    atexit (SDL_Quit);</P>
<P>    /* 设置图形模式 */<BR>    screen = SDL_SetVideoMode (SCREEN_W, SCREEN_H, SCREEN_BPP, SDL_HWSURFACE | SDL_DOUBLEBUF);<BR>    if (screen == NULL)<BR>    {<BR>        exit (2);<BR>    }<BR>    SDL_WM_SetCaption ("SDL Put Pixel", NULL);  /* 设置窗口标题 */</P>
<P>    while (!done) /* 主循环 */<BR>    {      <BR>        /* 检查事件 */<BR>        while (SDL_PollEvent (&amp;event))<BR>        {<BR>            switch (event.type)<BR>            {<BR>                case SDL_KEYDOWN:  /* 按任意键退出 */<BR>                done = 1;<BR>                break;<BR>                case SDL_QUIT:<BR>                done = 1;<BR>                break;<BR>                default:break;<BR>            }<BR>        }<BR>        <BR>        /* 在屏幕上的随机位置画白色的点 */<BR>        PutPixel(rand() &amp; 511, rand() &amp; 511, XRGB(255, 255, 255));<BR>        /* 将后台页显示到前台页 */<BR>        SDL_Flip (screen);<BR>        /* 延时 */<BR>        SDL_Delay (1);<BR>    }</P>
<P>    return 0;<BR>}<BR></P>

一笔苍穹 发表于 2007-9-4 10:06

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

hitzl 发表于 2007-9-4 11:22

<P>拜谢一笔苍穹斑竹!<BR><BR>讲授的非常细致。连编译过程和测试代码都写来了。呵呵,斑竹真是侠肠骨道。<BR></P>
<P>我这样的初哥very受益啊</P>

hitzl 发表于 2007-9-4 15:28

<P><BR>/* 初始化 SDL */<BR>    if (SDL_Init (SDL_INIT_VIDEO) &lt; 0)<BR>    {<BR>        printf("SDL_Init is failed"); //加了一条打印<BR>        exit (1);<BR>       <BR>    }<BR><BR>编译通过了。</P>
<P>调试时,初始化的过程出现了一个问题。<BR>我加了这条打印。发现是SDL初始化过程失败了。<BR>(在编译过程中,我确实加了-lSDL的参数)<BR><BR></P>

hitzl 发表于 2007-9-4 16:11

<P><BR>。。。<BR>/* 初始化 SDL */<BR>    if (SDL_Init (SDL_INIT_VIDEO) &lt; 0)<BR>    {<BR>        <U>printf("could not initialize SDL: %s\n",SDL_GetError()); //修改一次提示信息<BR></U>        exit (1);       <BR>    }<BR>。。。。<BR><BR>root\&gt; gcc main.c -o main -lSDL<BR>root\&gt; ./main<BR>root\&gt; could not initialize SDL: No available video device<BR><BR><BR><U>初始化失败,不能找到可用的视频设备。<BR>我又从google找了一个最简单初始化SDL的例子来调试SDL初始化过程,结果是仍然不能初始化。那么这个视频设备到底是指什么呢?是不是我的显示器。为何我在本地不能初始化呢.<BR></U><BR><BR>测试初始化SDL的例子附下:<BR>#include &lt;SDL/SDL.h&gt;   <BR>#include &lt;stdio.h&gt;</P>
<P>int main() {<BR>    <BR>    printf("Initializing SDL.\n");<BR>    <BR>    /* Initialize defaults, Video and Audio */<BR>    if((SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO)==-1)) { <BR>        printf("Could not initialize SDL: %s.\n", SDL_GetError());<BR>        exit(-1);<BR>    }</P>
<P>    printf("SDL initialized.\n");</P>
<P>    printf("Quiting SDL.\n");<BR>    <BR>    /* Shutdown all subsystems */<BR>    SDL_Quit();<BR>    <BR>    printf("Quiting....\n");</P>
<P>    exit(0);<BR>}<BR><BR><BR><BR></P>

页: [1] 2

编程论坛