gx 라이브러리 기본 구조에 맞추어 선을 그리는 루틴을 완셩해 보았습니다. 작업 시작이 얼마 되지 않아서 소스는 16비트 칼라에 대해서 직선을 그리는 부분까지 완성했습니다.

*** 참고로 선을 그리는 루틴은 이전에 브레슨햄을 소개하면서 만든 코드와는 달리 조금더 빠르게 실행이 되도록 최적화 했습니다. 역시 수학하시는 분들의 힘은 대단합니다. 선을 그리는 루틴도 함께 봐 주십시오. ^^ ***

파일 구조

앞으로 파일 구조는 아래와 같은 형식으로 만들어져 갈 것입니다.

파일 이름 파일 설명
gx.***

전체 그래픽 라이브러리, 사용자는 이 파일만 참조하여 사용합니다.

gx8.*** 8bit 칼라, 즉 256 칼라에 대해서만 처리합니다.
gx15.*** 15bit 칼라에 대해서만 처리합니다.
gx16.*** 16bit 칼라에 대해서만 처리합니다.
gx24.*** 24bit 칼라에 대해서만 처리합니다.
gx32.*** 32bit 칼라에 대해서만 처리합니다.

아래의 소스를 보시면 아시겠습니다만, gx[NNN] .h gx[NNN] .c 는 칼라 계산, 좌표에 맞추어 점을 찍거나 조금 더 빠르게 선을 그리기 위한 수직 및 수직선을 그리는 등의 칼라 깊이에 종속이 되는 함수를 모아 놓은 것입니다. 그리고 gx.h 와 gx.c 에서는 이들 함수를 캡슐화하듯 대신 호출하는 식으로 구현하는 것입니다.

프로그램 구성

그래픽 라이브러리 초기화 부분은 앞서서 많이 말씀을 드렸기 때문에 생략하겠습니다. 우선 gx16.h 와 gx16.c를 봐 주십시오. 아래와 같이 16bit 칼라 전용 함수가 선언 및 구현되어 있습니다.

int   gx16_color  ( int red, int green, int blue);
void  gx16_clear  ( dc_t *dc, int color);
void  gx16_dot    ( dc_t *dc, int coor_x, int coor_y, int color );
void  gx16_hline  ( dc_t *dc, int fst_x , int snd_x , int coor_y);
void  gx16_vline  ( dc_t *dc, int coor_x, int fst_y , int snd_y );

앞으로 8bit, 24bit, 32bit 도 이와 같은 모습으로 만들어질 것입니다.

또한 이 함수들은 인수를 보시면 아시겠지만 그래픽이 출력되는 목적지는 dc 입니다. dc 가 화면이면 화면으로, dc가 가상 캔버스면 캔버스, 비트맵이면 비트맵으로 방향이 선택되게 됩니다.

우선 공개되는 함수에서는 화면의 dc를 구하는 gx_screen_dc() 가 구현되어 있습니다.

dc_t *gx_screen_dc( void)
{
   dc_t  *dc;

   dc = malloc( sizeof( dc_t));
   if ( NULL != dc)
   {
      dc->width      = gx_fb.width;
      dc->height     = gx_fb.height;
      dc->dots       = gx_fb.dots;
      dc->mapped     = gx_fb.mapped;
      dc->coor_x     = 0;
      dc->coor_y     = 0;
      dc->pen_color  = clr_black;
      dc->brush_color= clr_black;

      printf( "colors=%dn", gx_fb.colors);

      switch( gx_fb.colors)     // 칼라 깊이별 처리가 다른 함수를 지정
      {
      case 16  :
                     dc->color = gx16_color;
                     dc->clear = gx16_clear;
                     dc->dot   = gx16_dot;
                     dc->hline = gx16_hline;
                     dc->vline = gx16_vline;
                     break;
      default  :
                     free( dc);
                     dc = NULL;
      }
   }
   return dc;
}

switch( gx_fb.colors) 문을 보시면 아시겠지만 칼라 깊이에 맞추어 dc에 대해 전문적으로 처리할 전용 함수를 지정해 주며, 앞으로 gx_****( dc, ...) 에 대해서는 모두 dc 안에 있는 전문 함수가 처리하므로, 라이브러리를 사용하는 사용자는 gx.h 에 선언된 함수만 사용하셔도 모든 그래픽 해상도에 대한 프로그램을 처리할 수 있습니다.

라이브러리 사용 방법

그래픽 라이브러리에 대해서는 gx.h만 사용하시면 됩니다.

#include             // graphic library

제일 먼저 그래픽 라이브러리를 초기화해서 시스템에 맞추어 출력을 준비할 수 있도록 합니다.

switch( gx_init( "/dev/fb") )
{
   case  GXERR_NO_DEVICE      :  printf( "프레임 버퍼 장치가 없습니다.n"              ); return -1;
   case  GXERR_ACCESS_DEVICE  :  printf( "프레임 버퍼 장치 접근 권한이 없습니다.n"    ); return -1;
   case  GXERR_VSCREENINFO    :  printf( "FBIOGET_VSCREENINFO를 실행하지 못했습니다.n"); return -1;
   case  GXERR_FSCREENINFO    :  printf( "FBIOGET_FSCREENINFO를 실행하지 못했습니다.n"); return -1;
   case  GXERR_MEMORYMAPPING  :  printf( "메모리 메핑을 못했습니다.n"                 ); return -1;
   default                    :  test();
}

gx_init() 호출 후에 GXERR_NONE 일 경우 그래픽 작업을 수행합니다. 화면에 무엇인가를 출력하기 위해서는 Device Context 를 구해야 합니다. gx_screen_dc()입니다.

if ( NULL != ( dc = gx_screen_dc()))
{
   // 화면에 출력 작업
}
else
{
   printf( "스크린 dc를 얻지 못했습니다.n");
} 

이후로는 dc를 이용하여 그래픽을 출력합니다.

sample.c

gx_clear( dc, gx_color( dc, 0, 0, 0));
dc->pen_color  = gx_color( dc, 255, 255, 255);
gx_line( dc, 0  , 0  , ndx, 200);
gx_lineto( dc, 200+rand() % offset_x, 200+rand() % offset_y); 

이제 gx.h부터 소스를 보시겠습니다.

gx.h

#ifndef _GX_H_
#define _GX_H_

#define  GXERR_NONE              0                   // 에러 없음
#define  GXERR_NO_DEVICE         -1                  // 장치가 없음
#define  GXERR_ACCESS_DEVICE     -2                  // 접근 권한이 없음
#define  GXERR_VSCREENINFO       -3                  // FBIOGET_VSCREENINFO를 구하지 못함
#define  GXERR_FSCREENINFO       -4                  // FBIOGET_FSCREENINFO를 구하지 못함
#define  GXERR_MEMORYMAPPING     -5                  // 프레임 버퍼 메모리 매핑에 실패

#define  clr_clear               0x8000000           // 출력하지 않는 색상
#define  clr_black               0x00                // 검은 색

typedef struct framebuffer_t_ framebuffer_t;
struct framebuffer_t_
{
   int      fd;                                      // 프레임 버퍼에 대한 파일 디스크립터
   int      width;
   int      height;
   int      bytes;                                   // 메모리 전체 크기
   int      dots;
   int      colors;

   unsigned short *mapped;                           // 메모리 매핑된 포인터
};

typedef struct dc_t_ dc_t;
struct dc_t_
{
   int      width;
   int      height;
   int      dots;
   int      coor_x;
   int      coor_y;
   int      pen_color;
   int      brush_color;
   void    *mapped;                                  // 메모리 매핑된 포인터

   int  (*color)( int red, int green, int blue);
   void (*clear)( dc_t *dc, int color);
   void (*dot  )( dc_t *dc, int coor_x, int coor_y, int color);
   void (*hline)( dc_t *dc, int fst_x , int snd_x , int coor_y);
   void (*vline)( dc_t *dc, int coor_x, int fst_y , int snd_y);
};

extern         framebuffer_t  gx_fb;                 // 프레임 버퍼 정보

extern int     gx_init        ( char *dev_name);     // 그래픽 라이브러리 초기화
extern void    gx_close       ( void);               // 그래픽 라이브러리 사용 종료
extern dc_t   *gx_screen_dc   ( void);               // 화면 dc를 구함
extern void    gx_release_dc  ( dc_t *dc);           // dc 를 소멸

extern int     gx_color ( dc_t *dc, int red, int green, int blue);      // 칼라 값을 구함
extern void    gx_clear ( dc_t *dc, int color);                         // dc를 지정한 색으로 모두 채움
extern void    gx_dot   ( dc_t *dc, int coor_x, int coor_y, int color); // dc에 점을 찍음
extern void    gx_moveto( dc_t *dc, int coor_x, int coor_y);            // dc의 좌표를 이동
extern void    gx_lineto( dc_t *dc, int coor_x, int coor_y);            // dc의 좌표에 새 좌표까지 선을 그림
extern void    gx_line  ( dc_t *dc, int x1, int y1, int x2, int y2);    // dc에 선을 그림

#endif

gx.c

#include 
#include         // malloc srand
#include         // abs

#include         // open/close
#include          // O_RDWR
#include      // ioctl
#include       // mmap PROT_
#include 
#include 
#include 

framebuffer_t  gx_fb;      // 프레임 버퍼 정보

//--------------------------------------------------------------------
// 설명: dc에 맞추어 칼라 값을 구한다.
// 인수: dc       Device Context
//       red      0~255 사이의 빨강색 비율
//       green    0~255 사이의 녹색   비율
//       blue     0~255 사이의 파랑색 비율
//--------------------------------------------------------------------
int   gx_color( dc_t *dc, int red, int green, int blue)
{
   return dc->color( red, green, blue);
}
//--------------------------------------------------------------------
// 설명: dc에 인수로 받은 색상으로 전체 칠함
// 인수: dc       Device Context
//       color    칠할 색상
//--------------------------------------------------------------------
void  gx_clear( dc_t *dc, int color)
{
   dc->clear( dc, color);
}
//--------------------------------------------------------------------
// 설명: dc에 점을 찍습니다.
// 인수: dc       Device Context
//       coor_x   x 좌표
//       coor_y   y 좌표
//       color    점 색상
//--------------------------------------------------------------------
void  gx_dot  ( dc_t *dc, int coor_x, int coor_y, int color)
{
   dc->dot( dc, coor_x, coor_y, color);
}
//--------------------------------------------------------------------
// 설명: dc의 좌표를 이동
// 인수: dc       Device Context
//       coor_x   x 좌표
//       coor_y   y 좌표
//--------------------------------------------------------------------
void  gx_moveto( dc_t *dc, int coor_x, int coor_y)
{
   dc->coor_x  = coor_x;
   dc->coor_y  = coor_y;
}
//--------------------------------------------------------------------
// 설명: dc의 좌표와 새로 인수로 받은 좌표와 선을 그림
// 인수: dc       Device Context
//       coor_x   x 좌표
//       coor_y   y 좌표
// 참고: 인수로 받은 좌료를 dc 좌료로 대입
//--------------------------------------------------------------------
void  gx_lineto( dc_t *dc, int coor_x, int coor_y)
{
   int      rx, ry;
   int      dx, dy;
   int      inc_x;
   int      inc_y;
   int      offset;
   int      color;

   rx = dc->coor_x;                          // dc 좌료 값
   ry = dc->coor_y;

   dc->coor_x  = coor_x;                     // dc 좌료를 인수로 받은 값으로 대입
   dc->coor_y  = coor_y;

   dx = coor_x -rx;                          // x 좌표에 대한 delta 값
   if ( 0 == dx)                             // 수식선을 그린다면
   {
      dc->vline( dc, rx, ry, coor_y);
      return;
   }
   else if ( 0 < dx)    inc_x = 1;           // x 좌표가 우측으로 증가하는 직선이라면
   else                                      // x 좌표가 좌측으로 감소하는 직선이라면
   {
      dx    = -dx;
      inc_x = -1;
   }

   dy = coor_y -ry;                          // y 좌표에 대한 delta 값
   if ( 0 == dy)                             // 수평선을 그린다면
   {
      dc->hline( dc, rx, coor_x, ry);
      return;
   }
   else if ( 0 < dy)    inc_y = 1;           // y 좌료가 밑으로 증가하는 직선이라면
   else                                      // y 좌료가 위로   감소하는 직선이라면
   {
      dy    = -dy;
      inc_y = -1;
   }

   color = dc->pen_color;                    // 선의 색깍을 구함
   gx_dot( dc, rx, ry, color);               // 첫번째 좌표를 찍음
   if ( dy <= dx)                            // x 좌료 변도이 더 큼, x 좌표는 1씩 변화
   {
      offset   = dx / 2;

      for (; rx != coor_x; rx += inc_x)
      {
         offset   += dy;
         if ( dx <= offset)
         {
            offset   -= dx;
            ry       += inc_y;
         }
         gx_dot( dc, rx, ry, color);
      }
   }
   else                                      // y 좌료 변동이 더 큼, y 좌표는 1씩 변화
   {
      offset   = dy /2;

      for (; ry != coor_y; ry += inc_y)
      {
         offset   += dx;
         if ( dy <= offset)
         {
            offset   -= dy;
            rx       += inc_x;
         }
         gx_dot( dc, rx, ry, color);
      }

   }
}
//--------------------------------------------------------------------
// 설명: 선을 그린다.
// 인수: x1, y1, x2, y2    선을 그리기 위한 좌표
// 참고: x2, y2는 dc 좌표가 dc 좌료가 된다.
//--------------------------------------------------------------------
void  gx_line( dc_t *dc, int x1, int y1, int x2, int y2)
{
   gx_moveto( dc, x1, y1);
   gx_lineto( dc, x2, y2);
}
//--------------------------------------------------------------------
// 설명: Device Context 자원을 반환
//--------------------------------------------------------------------
void  gx_release_dc( dc_t *dc)
{
   if ( NULL != dc)     free( dc);
}

//--------------------------------------------------------------------
// 설명: 화면에 그래픽을 출력하기 위한 Device Context를 구합니다.
// 반환: 정상 -> dc_t *, 오류 -> NULL
// 참고: 프레임 버퍼에서 화면에 대한 모든 정보를 구합니다.
//--------------------------------------------------------------------
dc_t *gx_screen_dc( void)
{
   dc_t  *dc;

   dc = malloc( sizeof( dc_t));
   if ( NULL != dc)
   {
      dc->width      = gx_fb.width;
      dc->height     = gx_fb.height;
      dc->dots       = gx_fb.dots;
      dc->mapped     = gx_fb.mapped;
      dc->coor_x     = 0;
      dc->coor_y     = 0;
      dc->pen_color  = clr_black;
      dc->brush_color= clr_black;

      printf( "colors=%dn", gx_fb.colors);

      switch( gx_fb.colors)                  // 칼라 깊이별 처리가 다른 함수를 지정
      {
      case 16  :
                     dc->color = gx16_color;
                     dc->clear = gx16_clear;
                     dc->dot   = gx16_dot;
                     dc->hline = gx16_hline;
                     dc->vline = gx16_vline;
                     break;
      default  :
                     free( dc);
                     dc = NULL;
      }
   }
   return dc;
}
//--------------------------------------------------------------------
// 설명: 그래픽 라이브러리 종료
// 참고: 메모리 매핑 포인터와 프레임 버퍼 디스크립터를 소멸하고,
//       변수를 초기화 한다.
//--------------------------------------------------------------------
void  gx_close( void)
{
   if ( 0 <= gx_fb.mapped)                   // 메모리가 메핑 되어 있다면
   {
      munmap( gx_fb.mapped, gx_fb.bytes);    // 메모리 메핑 자원 반환
      gx_fb.mapped      = MAP_FAILED;
   }
   if ( 0 <= gx_fb.fd)                       // 파일 디스크립터가 만들어 졌다면
   {
      close( gx_fb.fd);                      // 파일 디스크립터 자원 반환
      gx_fb.fd = -1;
   }
}

//--------------------------------------------------------------------
// 설명: 그래픽 라이브러리를 초기화
// 인수: dev_name    장치 이름
// 반환: 0 =         에러 없음
//       0 >         에러 발생
//--------------------------------------------------------------------
int   gx_init( char *dev_name)
{
   struct   fb_var_screeninfo  fbvar;
   struct   fb_fix_screeninfo  fbfix;
   int      bytes_per_line;
   int      bits_per_pixel;

   gx_fb.fd       = -1;                      // 초기값을 대입
   gx_fb.mapped   = MAP_FAILED;              // 초기값을 대입

   if ( access( dev_name, F_OK))                            return GXERR_NO_DEVICE;
   if ( 0 >  ( gx_fb.fd = open( dev_name, O_RDWR))   )      return GXERR_ACCESS_DEVICE;
   if ( ioctl( gx_fb.fd, FBIOGET_VSCREENINFO, &fbvar))
   {
      gx_close();
      return GXERR_VSCREENINFO;
   }
   if ( ioctl( gx_fb.fd, FBIOGET_FSCREENINFO, &fbfix))
   {
      gx_close();
      return GXERR_FSCREENINFO;
   }

   gx_fb.width       = fbvar.xres;                     // 스크린의 픽셀 폭
   gx_fb.height      = fbvar.yres;                     // 스크린의 픽셀 높이
   gx_fb.dots        = gx_fb.width * gx_fb.height;     // 스크린 도트 개수
   bits_per_pixel    = fbvar.bits_per_pixel;           // 스크린의 칼라 깊이
   bytes_per_line    = fbfix.line_length;              // 한개 라인 당 바이트 개수

   gx_fb.bytes       = bytes_per_line * gx_fb.height;  // 스크린의 총 메모리 바이트 수
   gx_fb.mapped      = ( void *)mmap( 0,
                                      gx_fb.bytes,
                                      PROT_READ|PROT_WRITE,
                                      MAP_SHARED,
                                      gx_fb.fd,
                                      0);


                              // 칼라 깊이 정보를 구합니다.
                              // 16 bit에서 각 R,G,B의 비트 개수를 합해
                              // 정확히 구합니다.
   switch( bits_per_pixel)
   {
   case 16  :  gx_fb.colors   =  fbvar.red.length
                                +fbvar.green.length
                                +fbvar.blue.length;
               break;
   default  :  gx_fb.colors   =  bits_per_pixel;
   }


   if ( 0 > gx_fb.mapped)
   {
      gx_close();
      return   GXERR_MEMORYMAPPING;
   }

   return   GXERR_NONE;
}

gx16.h

#ifndef _GX_16_H_
#define _GX_16_H_

#include 
                              // 16 bit 칼라 함수를 선언

extern int  gx16_color  ( int red, int green, int blue);                // 색상을 구함
extern void gx16_clear  ( dc_t *dc, int color);                         // 인수로 받은 색상으로 전체 칠하기
extern void gx16_dot    ( dc_t *dc, int coor_x, int coor_y, int color );// 점 찍기
extern void gx16_hline  ( dc_t *dc, int fst_x , int snd_x , int coor_y);// 수평선 그리기
extern void gx16_vline  ( dc_t *dc, int coor_x, int fst_y , int snd_y );// 수직선 그리기

#endif

gx16.c

#include 
#include 
#include         // abs

#include         // open/close
#include          // O_RDWR
#include      // ioctl
#include       // mmap PROT_
#include 
#include 

//--------------------------------------------------------------------
// 설명: 칼라 값을 구한다.
// 인수: red         0부터 255 사이의 red   값
//       green       0부터 255 사이의 green 값
//       blue        0부터 255 사이의 blue  값
// 참고: 16 bit 환경에 따라 shift=0:5:6:5, shift=0:11:5:0
//--------------------------------------------------------------------
int   gx16_color( int red, int green, int blue)
{
   red   >>= 3;                           // 8bit 인수 값을 칼라 bit 크기 만큼 축소
   green >>= 2;                           // 8bit 인수 값을 칼라 bit 크기 만큼 축소
   blue  >>= 3;                           // 8bit 인수 값을 칼라 bit 크기 만큼 축소

   return   ( red << 11) | ( green << 5) | blue;
}

//--------------------------------------------------------------------
// 설명: 스크린을 특정 칼라로 채움
// 인수: color       칼라
//--------------------------------------------------------------------
void  gx16_clear( dc_t *dc, int color)
{
   int             ndx;
   unsigned short *ptr;

   if (clr_clear > color)
   {
      ptr = (unsigned short *)dc->mapped;

      for ( ndx = 0; ndx < dc->dots; ndx++)
         *ptr++ = color;
   }
}

//--------------------------------------------------------------------
// 설명: 점을 찍는다.
// 인수: coor_x         x 좌표
//       coor_y         y 좌표
//       color          점 색상
// 참고: 좌표 값을 확인하여 엉뚱한 좌료가 입력되도
//       실행 에러가 발생하지 않도록 한다.
//--------------------------------------------------------------------
void  gx16_dot( dc_t *dc, int coor_x, int coor_y, int color)
{
   unsigned short *ptr;

   if ( 0 > coor_x || dc->width  <= coor_x)     return;
   if ( 0 > coor_y || dc->height <= coor_y)     return;

   ptr   = (unsigned short *)dc->mapped +dc->width * coor_y + coor_x;
   *ptr  = color;
}
//--------------------------------------------------------------------
// 설명: 수평선을 그린다.
// 인수: fst_x, snd_x   x 좌표
//       coor_y         y 좌표
//       color          선 색상
// 반환:
//--------------------------------------------------------------------
void  gx16_hline( dc_t *dc, int fst_x, int snd_x, int coor_y)
{
   unsigned short *ptr;
   int            color;
   int            ndx;

   if ( 0 > coor_y || dc->height <= coor_y)              // y 좌료가 스크린 영역을 벗어나면 복귀
      return;

   if ( snd_x < fst_x)                                   // x 좌표가 다음 좌표보다 작게 수정
   {
      ndx      = fst_x;
      fst_x    = snd_x;
      snd_x    = ndx;
   }

   if       ( 0         >  fst_x)  fst_x   = 0;          // 좌측 화면 밖의 좌표이면 0부터 그린다.
   else if  ( dc->width <= fst_x)  fst_x   = dc->width-1;// 우측 화면 밖의 좌표이면 우측 화면까지만 그린다.

   if       ( 0         >  snd_x)  snd_x   = 0;
   else if  ( dc->width <= snd_x)  snd_x   = dc->width-1;

   color = dc->pen_color;
   ptr   = (unsigned short *)dc->mapped + dc->width * coor_y +fst_x;
   for ( ndx = fst_x; ndx <= snd_x; ndx++)
     *ptr++ = color;
}
//--------------------------------------------------------------------
// 설명: 수직선을 그린다.
// 인수: coor_x         x 좌표
//       fst_y, snd_y   y 좌표
//       color          선 색상
// 반환:
//--------------------------------------------------------------------
void  gx16_vline( dc_t *dc, int coor_x, int fst_y, int snd_y)
{
   unsigned short *ptr;
   int            color;
   int            ndx;

   if ( 0 > coor_x || dc->width <= coor_x)               // x 좌료가 스크린 영역을 벗어나면 복귀
      return;

   if ( snd_y < fst_y)                                   // y 좌표가 다음 좌표보다 작게 수정
   {
      ndx      = fst_y;
      fst_y    = snd_y;
      snd_y    = ndx;
   }

   if       ( 0          >  fst_y)  fst_y   = 0;            // 화면 상단 밖의 좌표이면 0부터 그린다.
   else if  ( dc->height <= fst_y)  fst_y   = dc->height-1; // 화면 하단 밖의 좌표이면 우측 화면까지만 그린다.

   if       ( 0          >  snd_y)  snd_y   = 0;
   else if  ( dc->height <= snd_y)  snd_y   = dc->height-1;

   color = dc->pen_color;
   ptr   = (unsigned short *)dc->mapped + dc->width * fst_y +coor_x;
   for ( ndx = fst_y; ndx <= snd_y; ndx++)
   {
     *ptr   = color;
      ptr  += dc->width;
   }
}

sample.c

#include    
#include    
#include    
#include             // graphic library
#include         // sleep

void test( void)
{
   dc_t    *dc;
   int      offset_x, offset_y;
   int      ndx;

   srand( (unsigned)time(NULL));

   if ( NULL != ( dc = gx_screen_dc()))
   {
      gx_clear( dc, gx_color( dc, 0, 0, 0));

      dc->pen_color  = gx_color( dc, 255, 255, 255);

      for( ndx = 0; ndx < dc->height; ndx +=10){
         gx_line( dc, 0  , 0  , ndx, 200);
         gx_line( dc, 0  , 0  , 200, ndx);
         gx_line( dc, ndx, 0  , ndx, 200);
         gx_line( dc, 0  , ndx, 200, ndx);
      }

      offset_x = dc->width  -200;
      offset_y = dc->height -200;
      gx_moveto( dc, 200+rand() % offset_x, 200+rand() % offset_y);
      for ( ndx= 0; ndx < 100; ndx++)
      {
         dc->pen_color  = gx_color( dc, rand() %128 +128, rand() %128 +128, rand() %128 +128);
         gx_lineto( dc, 200+rand() % offset_x, 200+rand() % offset_y);
      }
   }
   else
   {
      printf( "스크린 dc를 얻지 못했습니다.n");
   }
}

int   main( void)
{
   switch( gx_init( "/dev/fb") )
   {
      case  GXERR_NO_DEVICE      :  printf( "프레임 버퍼 장치가 없습니다.n"              ); return -1;
      case  GXERR_ACCESS_DEVICE  :  printf( "프레임 버퍼 장치 접근 권한이 없습니다.n"    ); return -1;
      case  GXERR_VSCREENINFO    :  printf( "FBIOGET_VSCREENINFO를 실행하지 못했습니다.n"); return -1;
      case  GXERR_FSCREENINFO    :  printf( "FBIOGET_FSCREENINFO를 실행하지 못했습니다.n"); return -1;
      case  GXERR_MEMORYMAPPING  :  printf( "메모리 메핑을 못했습니다.n"                 ); return -1;
      default                    :  test();
   }

   gx_close();
   return   0;
}

실행하면 아래와 같은 화면이 출력됩니다.

 태그: *그래픽 *라이브러리 *그래픽라이브러리