正文

光栅图形显示模拟2006-12-29 18:11:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/tonyhu/22057.html

分享到:

为了学图形学方便,用SDL写了个光栅显示的模拟,
还花了几个下午来研究了下,主要就是坐标之间的
转换着实让人烦,开始写的一个因为烦透了,删了又重写过……
这个写得还算满意了,坐标之间的转换关系蛮方便地,
也可以从象素级别上刷写一张图象,作一堆杂七杂八的变换,
达到什么效果就看自己写的程序了……
这只是个学习的工具,自己写的图形程序可以直接用来试验,
没什么其它功能,就一个操作伪象素有点用……
呵呵,模拟的就是伪象素嘛……

两张图片:

//raster.h头文件

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

#define SetR 100
#define SetG 255
#define SetB 255

#define FrameR 255
#define FrameG 0
#define FrameB 0

void init ();
void loop ();
void drawjay ();
void setpixel (int x, int y, Uint8 R = SetR, Uint8 G = SetG, Uint8 B = SetB);
void setpixel (int x, int y, Uint32 pixel);
void drawframe (int x, int y, Uint8 R = FrameR, Uint8 G = FrameG, Uint8 B =
  FrameB);
void drawframe (int x, int y, Uint32 pixel);
int maxx ();
int minx ();
int maxy ();
int miny ();

//raster.cc程序文件

#include "raster.h"

#define HW 800   //hardware width
#define HH 600   //hardware hight
#define PIXEL_H 4  //minimum
#define PIXEL_W 4
#define OO 1  //是否用一到四象限坐标

#define CUTR 255  //切割颜色
#define CUTG 255
#define CUTB 255

#define OOR 255   //坐标线颜色
#define OOG 0
#define OOB 0

SDL_Surface *screen, *jay;

//对屏幕的象素级操作
void
putpixel (SDL_Surface * img, int x, int y, Uint32 pixel)
{
 int bpp = img->format->BytesPerPixel;
 Uint8 *p = (Uint8 *) img->pixels + y * img->pitch + x * bpp;
 switch (bpp)
 {
 case 1:
  *p = pixel;
  break;
 case 2:
  *(Uint16 *) p = pixel;
  break;
 case 3:
  if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
  {
   p[0] = (pixel >> 16) & 0xff;
   p[1] = (pixel >> 8) & 0xff;
   p[2] = pixel & 0xff;
  }
  else
  {
   p[0] = pixel & 0xff;
   p[1] = (pixel >> 8) & 0xff;
   p[2] = (pixel >> 16) & 0xff;
  }
  break;
 case 4:
  *(Uint32 *) p = pixel;
  break;
 };
}

Uint32
returnpixel (SDL_Surface * img, int x, int y)
{
 int bpp = img->format->BytesPerPixel;
 Uint8 *p = (Uint8 *) img->pixels + y * img->pitch + x * bpp;
 switch (bpp)
 {
 case 1:
  return *p;
 case 2:
  return *(Uint16 *) p;
 case 3:
  if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
   return p[0] << 16 | p[1] << 8 | p[2];
  else
   return p[0] | p[1] << 8 | p[2] << 16;
 case 4:
  return *(Uint32 *) p;
 default:
  return 0;
 };
}

void
drawooline ()  //画十字线坐标,只有打开四个象限(OO)才用到,
{
 if (OO)
 {
  Uint32 pixel = SDL_MapRGB (screen->format, OOR,
        OOG, OOB);
  int i;
  for (i = 0; i < HW; i++)
   putpixel (screen, i, HH / 2, pixel);
  for (i = 0; i < HH; i++)
   putpixel (screen, HW / 2, i, pixel);
  SDL_UpdateRect (screen, 0, HH / 2, HW, 1);
  SDL_UpdateRect (screen, HW / 2, 0, 1, HH);
 }
}
void
drawcut ()  //画屏幕切割线,如果只用到第一象限就不画十字线坐标了
{
 int i, j;
 Uint32 pixel = SDL_MapRGB (screen->format, CUTR,
       CUTG, CUTB);
 for (i = 0; i < HH; i++)
  for (j = 0; j < HW; j++)
  {
   if (i % PIXEL_H != 0 && j % PIXEL_W == 0)
    putpixel (screen, j, i, pixel);
   else if (i % PIXEL_H == 0)
    putpixel (screen, j, i, pixel);
  }
 SDL_ShowCursor (0);
 SDL_WM_SetCaption ("Computer raster display emulation", "");
 if (OO)
  drawooline ();
 SDL_Flip (screen);
}

void
init ()
{
 if ((SDL_Init (SDL_INIT_VIDEO)) < 0)
  fprintf (stderr, "init error\n");
 atexit (SDL_Quit);
 if ((screen =
      SDL_SetVideoMode (HW, HH, 32,
          SDL_HWSURFACE | SDL_DOUBLEBUF)) == NULL)
  fprintf (stderr, "set video mode error\n");
 drawcut ();
 if ((jay = SDL_LoadBMP ("jay.bmp")) == NULL)
  fprintf (stderr, "load jay error\n");
}

void
drawjay ()  //画图片(jay)
{
 int i, j;
 if (OO)
 {
  int mx = minx (), my = miny ();
  for (i = mx; i <= maxx (); i++)
   for (j = my; j <= maxy (); j++)
    setpixel (i, maxy () - j - abs (my),
       returnpixel (jay, i + abs (mx),
             j + abs (my)));
 }
 else
 {
  for (i = minx (); i <= maxx (); i++)
   for (j = miny (); j <= maxy (); j++)
    setpixel (i, maxy () - j,
       returnpixel (jay, i, j));
 }
}

int
maxx ()  //伪象素系统的最大的X值,
{
 if (OO)
  return (HW - 1) / PIXEL_W - HW / 2 / PIXEL_W;
 else
  return (HW - 1) / PIXEL_W;
}

int
minx ()
{
 if (OO)
  return -HW / 2 / PIXEL_W;
 else
  return 0;
}

int
maxy ()
{
 if (OO)
  return (HH - 1) / PIXEL_H - HH / 2 / PIXEL_H;
 else
  return (HH - 1) / PIXEL_H;
}

int
miny ()
{
 if (OO)
  return -HH / 2 / PIXEL_H;
 else
  return 0;
}

//真实坐标系统到伪象素系统的坐标转换
void
changecoor (int a, int b, int &x, int &y) 
{
 if (a < 0 || a >= HW || b < 0 || b >= HH)
  return;
 if (OO)
 {
  int ox = HW / 2;
  int oy = HH / 2;
  x = a / PIXEL_W - ox / PIXEL_W;
  y = (HH - 1 - b) / PIXEL_H - oy / PIXEL_H;

 }
 else
 {
  x = a / PIXEL_W;
  y = (HH - 1 - b) / PIXEL_H;
 }
}

//伪象素坐标系统到真实坐标的坐标转换
void
changebackcoor (int x, int y, int &a, int &b) //oo to sdl
{
 if (x > maxx () || x < minx () || y > maxy () || y < miny ())
  return;
 if (OO)
 {
  a = HW / 2 + x * PIXEL_W;
  b = HH / 2 - y * PIXEL_H;
 }
 else
 {
  a = x * PIXEL_W;
  b = HH - y * PIXEL_H;
 }
}

//画一个伪象素点的边框,鼠标移动到一个伪象素点上时有用
void
drawframe (int x, int y, Uint8 R, Uint8 G, Uint8 B) //oo坐标
{
 if (x > maxx () || x < minx () || y > maxy () || y < miny ())
  return;
 Uint32 pixel = SDL_MapRGB (screen->format, R, G, B);
 changebackcoor (x, y, x, y);
 int i;
 for (i = 1; i < PIXEL_W; i++)
 {
  putpixel (screen, x + i, y - 1, pixel);
  putpixel (screen, x + i, y - PIXEL_H + 1, pixel);
 }
 for (i = 1; i < PIXEL_H; i++)
 {
  putpixel (screen, x + 1, y - i, pixel);
  putpixel (screen, x + PIXEL_W - 1, y - i, pixel);
 }
 SDL_UpdateRect (screen, x + 1, y - PIXEL_H + 1, PIXEL_W - 1,
   PIXEL_H - 1);
}

//重载一下
void
drawframe (int x, int y, Uint32 pixel)
{
 if (x > maxx () || x < minx () || y > maxy () || y < miny ())
  return;
 changebackcoor (x, y, x, y);
 int i;
 for (i = 1; i < PIXEL_W; i++)
 {
  putpixel (screen, x + i, y - 1, pixel);
  putpixel (screen, x + i, y - PIXEL_H + 1, pixel);
 }
 for (i = 1; i < PIXEL_H; i++)
 {
  putpixel (screen, x + 1, y - i, pixel);
  putpixel (screen, x + PIXEL_W - 1, y - i, pixel);
 }
 SDL_UpdateRect (screen, x + 1, y - PIXEL_H + 1, PIXEL_W - 1,
   PIXEL_H - 1);
}

//主loop
void
loop ()
{
 SDL_Event event;
 Uint32 oldpixel = SDL_MapRGB (screen->format, 0, 0, 0);
 int run = 1, bx, by, oldx = minx () - 1, oldy = miny () - 1, x, y;
 int tmpx, tmpy;
 while (run)
 {
  SDL_Delay (50);
  while (SDL_PollEvent (&event))
  {
   switch (event.type)
   {
   case SDL_QUIT:
    run = 0;
    break;
   case SDL_MOUSEBUTTONDOWN:
    changecoor (event.
         button.x, event.button.y, bx, by);
    fprintf (stdout, "X:%d\tY:%d\n", bx, by);
    break;
   };
  }
  SDL_GetMouseState (&x, &y);
  changecoor (x, y, x, y);
  if (oldx != x || oldy != y) //鼠标移动后的还原
   drawframe (oldx, oldy, oldpixel);
  changebackcoor (x, y, tmpx, tmpy);
  oldpixel = returnpixel (screen, tmpx + 2, tmpy - 2);
  drawframe (x, y);
  oldx = x;
  oldy = y;
 }
}

//操作伪象素点
void
setpixel (int x, int y, Uint8 R, Uint8 G, Uint8 B)
{
 if (x > maxx () || x < minx () || y > maxy () || y < miny ())
  return;
 changebackcoor (x, y, x, y);
 Uint32 pixel = SDL_MapRGB (screen->format, R, G, B);
 int i, j;
 for (i = 1; i < PIXEL_W; i++)
  for (j = 1; j < PIXEL_H; j++)
   putpixel (screen, x + i, y - j, pixel);
 SDL_UpdateRect (screen, x + 1, y - PIXEL_H + 1, PIXEL_W - 1,
   PIXEL_H - 1);
}

void
setpixel (int x, int y, Uint32 pixel)
{
 if (x > maxx () || x < minx () || y > maxy () || y < miny ())
  return;
 changebackcoor (x, y, x, y);
 int i, j;
 for (i = 1; i < PIXEL_W; i++)
  for (j = 1; j < PIXEL_H; j++)
   putpixel (screen, x + i, y - j, pixel);
 SDL_UpdateRect (screen, x + 1, y - PIXEL_H + 1, PIXEL_W - 1,
   PIXEL_H - 1);
}

阅读(4328) | 评论(2)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册