gxLib에 PNG 이미지를 출력하는 기능을 추가하면서, 포럼 표준 코딩 ver 0.0.1에 맞추어 수정한 0.6.2입니다. 그러나 PNG와 표준 코딩뿐만 아니라 매우 많은 부분이 수정되었습니다. 작업을 완료해 놓고 포럼에 올리려니 너무 많이 바뀌어서 죄송한 마음이 앞섭니다만, 앞으로 그래픽 라이브러리 다운 라이브러리로 발전하기 위해 어쩔 수 없이 수정이 불가피했음을 양해해 주시면 감사하겠습니다.

에러 확인 방법 변경

객체 생성 에러 확인 방법

예전에는 gx_get_screen_dc(), gx_get_buffer_dc(), gx_bmp_open(), gx_png_open()를 호출하여 정상적으로 실행되었는지 확인하려면, 우선 반환된 포인터가 NULL이 아닌지 확인했습니다. NULL 이 아니면 포인터가 가르키는 에러 코드를 확인해야 했습니다.

if ( NULL == ( bmpMemory = gxBmpCreate( 200, 200, 16, 0))) 
{
   printf( "bmp 생성 에러\n");
}
else
{
   switch( bmpMemory->ErrorCode)
   {
      case  GXERR_COLOR_DEPTH :
            printf( "지원하지 않는 칼라 깊이 입니다.\n");
            break;
      case  GXERR_NONE        :
            dcMemory       = ( Tdc *)bmpMemory;

그러나 0.6.2부터는 실행 중 에러가 발생하면 무조건 NULL을 반환하도록 했습니다.

gx_error_code, gx_error_string(), gx_print_string() 추가

아울러 에러 내용을 확인할 수 있도록, 광역 변수인 gx_error_code를 따로 두었습니다.

또, 에러 코드에 대한 문자열을 구할 수 있는 gx_error_string() 과 에러 내용을 화면으로 출력해 주는 gx_print_string() 함수를 추가했습니다. 이 함수를 이용하면 프로그램 작성 시 마다 에러 내용을 확인하기 위한 문자열 출력 코드를 일부러 작성하실 필요가 없습니다.

if ( gx_init( "/dev/fb"))     gx_print_error();
else
{
   if ( !( dc_screen = gx_get_screen_dc()))   gx_print_error();
   else
   {
      if ( !( dc_buffer = gx_get_buffer_dc(-1, -1)))  gx_print_error();
      else
      {
         if ( !( png = gx_png_open( "png-24.png")))   gx_print_error();
         else

칼라 설정 방법 변경

color 변수의 변화

이전 버전까지는 pen_color나 brush_color 등은 정수 타입의 칼라값을 가졌습니다. 그러나 0.6.2부터는 아래와 같이 color_t 스트럭쳐로 변경했습니다. gx.h에 정의되어 있습니다.

typedef struct color_t_ color_t;
struct color_t_
{
   unsigned char  red;
   unsigned char  green;
   unsigned char  blue;
   unsigned char  alpha;
};

typedef struct dc_t_ dc_t;
struct dc_t_
{
					:
   color_t  pen_color;     // 현재의 펜 칼라
   color_t  brush_color;   // 현재의 브러쉬 칼라
					:
};

또한 앞으로 모든 칼라값 지정은 정수에서 color_t로 변경됩니다. 그러므로 이전까지는 color_t 값을 구한 후에, gx_color( dc, )로 정수 칼라 값을 구한 후, 다른 DC에 지정했지만, 이번 버전부터는 gx_color( dc, )을 이용하여 정수로 변환할 필요가 없습니다. 즉, 이전까지의 get_pixel()과 set_pixel()은 아래와 같았습니다.

void    gx_get_pixel   ( dc_t *dc, int coor_x, int coor_y, color_t *color); // 칼라 값을 읽어 오기
void    gx_set_pixel   ( dc_t *dc, int coor_x, int coor_y, int  color);    // dc에 점을 찍음

이런 사정으로 DC에서 DC로 복사하는 gx_bitblt()는 아래와 같이 코딩되었습니다.

dcSour->GetPixel( dcSour, xCoor+xSour, yCoor+ySour, &Color     );
ColorValue = dcDest->Color( Color.Red, Color.Green, Color.Blue );
dcDest->SetPixel( dcDest, xCoor+xDest, yCoor+yDest, ColorValue );

그러나 0.6.2부터는 gx_get_pixel()과 gx_set_pixel() 모두 color_t를 사용합니다. 그러므로 칼라를 정수 변환없이 구현할 수 있습니다.

void gx_get_pixel   ( dc_t *dc, int coor_x, int coor_y, color_t *color);// 칼라 값을 읽어 오기
void gx_set_pixel   ( dc_t *dc, int coor_x, int coor_y, color_t  color);// dc에 점을 찍음

                                 :

dc_sour->get_pixel( dc_sour, coor_x+sour_x, coor_y+sour_y, &color);
dc_dest->set_pixel( dc_dest, coor_x+dest_x, coor_y+dest_y,  color);

아울러 alpha 값에 따라 복사를 하지 않으므로서 투명 효과를 제공할 수 있습니다.

gx_color() 의 인수 변화

이제 모든 color 값은 color_t를 사용하므로 DC의 칼라 깊이에 따라 정수 칼라 값을 구할 필요가 없어 졌습니다. 그러므로 0.6.2부터 gx_color()는 정수가 아닌 color_t 값을 반환합니다. 아래는 pen_color에 백색을 지정하는 예입니다.

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

이 함수에는 alpha 값을 지정할 수 없으며, 자동으로 alpha 값은 최대 값인 255로 지정됩니다.

gx_set_alpha() 함수 추가

칼라의 alpha값을 변경합니다.

void gx_set_alpha( color_t *color, int alpha)
                           :
gx_set_alpha( dc->pen_color, 100);

물론 칼라 값의 alpha값을 바로 지정하셔도 됩니다.

dc->pen_color.alpha = 100;

그러나 gx_set_alpha()를 사용하면 0보다 작은 값인지, 255보다 큰 값인지를 확인하여, 음수일 경우 0을, 255보다 크다면 255로 지정해 줍니다.

alpha는 gx_circle()나 gx_ellipse()에 사용할 수 있습니다. 즉, pen_color이나 brush_color의 alpha값을 0 으로 설정하면 색을 출력하지 않아, 테두리만 있는 원이나 타원을 그릴 수 있고, 또는 테두리가 없고 내부만 칠한 도형을 그릴 수 있습니다.

PNG 이미지 지원

png_t 추가

gxpng.c와 gxpng.h를 추가하면서, bitmap_t와 더블어 두 번째 이미지 지원으로 png를 사용할 수 있는 png_t를 추가했습니다. PNG 이미지는 투명값을 갖는 alpha 값을 가지고 있기 때문에, alpha 값을 살려 출력하려 했습니다만, alpha 값이 0 인 완전 투명만 처리했습니다. 예로 gx_bitblt()를 보겠습니다.

void  gx_bitblt(  dc_t *dc_dest, int dest_x, .........

                               :

   else if ( DCTYPE_PNG == dc_sour->dc_type)                   // 원본이 PNG 파일이면 투명 영역을 처리
   {
      for ( coor_y = 0; coor_y < sour_h; coor_y++)
      {
         for ( coor_x = 0; coor_x < sour_w; coor_x++)
         {
            dc_sour->get_pixel( dc_sour, coor_x+sour_x, coor_y+sour_y, &color);
            if ( 0 != color.alpha)    // 여기서 alpah 값에 따라 투명 값을 계산하여 복사할 수 있습니다.
            {
               dc_dest->set_pixel( dc_dest, coor_x+dest_x, coor_y+dest_y, color);
            }
         }
      }
   }

                                     :

png 파일 사용 방법

png 파일 사용 방법은 bitmap 파일 사용과 똑 같습니다. gx_png_open()을 이용하여 파일을 open하고 사용 후에는 gx_png_close() 또는 gx_release_dc()를 이용하시면 됩니다.

int   main( void)
{
                              :
   png = gx_png_open( "png-24.png");   // PNG 파일을 오픈
   gx_bitblt( dc_buffer, 100, 60, (dc_t *)png, 0, 0, png->width, png->height);
                              :
}

png 파일 출력 예제

아래는 png 출력 예제로 bitmap과 png를 함께 출력했습니다. png는 역시 투명 영역을 살렸습니다. 아래의 다운로드는 gxLib 0.6.2와 샘플 소스를 모두 가지고 있는 파일입니다.

gxLib 내려받기           gxLib 0.6.2      4,179kb

#include    <stdio.h>
#include    <stdlib.h>
#include    <time.h>
#include    <unistd.h>                                                           // sleep
#include    <gx.h>                                                               // 기본 그래픽 라이브러리
#include    <gxbmp.h>
#include    <gxbdf.h>                                                            // 문자 출력 라이브러리
#include    <gxpng.h>

int   main( void)
// 설명: bmp 파일을 출력하고 png 파일을 그 위에 출력한다.
// 참고: png 파일의 투명한 부분이 처리되었는지 확인한다.
{
   dc_t          *dc_screen;             // 화면 Device Context
   dc_t          *dc_buffer;             // 버퍼 Device Context
   png_t         *png;                   // PNG 파일 Device Context
   bitmap_t      *bmp;                   // BMP 파일 Device Context
   int            ndx;

   if ( gx_init( "/dev/fb"))     gx_print_error();                               // 프레임 버퍼를 이용하여 gxLib를 초기화
   else
   {
      if ( !( dc_screen = gx_get_screen_dc()))   gx_print_error();               // 화면 출력을 위한 스크린 DC 구함
      else
      {
         if ( !( dc_buffer = gx_get_buffer_dc(-1, -1)))  gx_print_error();       // 빠른 출력을 위해 버퍼 DC를 구함
         else
         {
            if ( !( png = gx_png_open( "png-24.png")))   gx_print_error();       // PNG 파일을 오픈
            else
            {
               png->pen_color = gx_color( 255, 128, 0);
               for ( ndx = 210; ndx < 230; ndx++)
                  gx_line( ( dc_t *)png, ndx, 0, ndx, png->height);              // PNG에 직선 그림
               png->pen_color.alpha = 0;                                         // PNG의 pen 칼라를 투명도 0으로 설정
               for ( ndx = 35; ndx < 45; ndx++)
                  gx_line( ( dc_t *)png, 0, ndx, png->width, ndx);               // PNG에 투명 색으로 직선 그림
               if ( !( bmp = gx_bmp_open( "24.bmp")))    gx_print_error();       // BMP 파일을 오픈
               else
               {
                  /*
                   * 화면에 깜밖임 없이 출력하기 위해 버퍼 DC를 이용한다.
                   * 또한 버퍼 DC에도 PNG를 이상없이 출력할 수 있음을 아울러 확인
                   * 버퍼 DC에 BMP를 출력한 후에 PNG 파일을 출력
                   */
                  gx_clear    ( dc_buffer, gx_color(   0, 0,   0));
                  gx_bitblt   ( dc_buffer,   0,  0, (dc_t *)bmp, 0, 0, bmp->width, bmp->height);
                  gx_bitblt   ( dc_buffer, 100, 60, (dc_t *)png, 0, 0, png->width, png->height);
                  gx_to_screen_dc( dc_screen, dc_buffer);
                  gx_bmp_close( bmp);                                            // 또는 gx_release_dc( bmp);
               }
               gx_png_close( png);                                               // 또는 gx_release_dc( png);
            }
            gx_release_dc( dc_buffer);
         }
         gx_release_dc( dc_screen);
      }
      gx_close();
   }
   return   0;
}