본문 바로가기

Developement/C/C++

FLTK Fl_Group 을 blur 된 배경 이미지로 만들기.

 FLTK 1.3.4-1 부터 좀 더 강력 해 진 영역이 있다면, 바로 Offscreen surface 에 특정 FLTK widget 을 그려 이것을 Fl_RGB_Image 로 만들 수 있다는 것 입니다.

 그래서 아래 처럼 빨간 점선 안의 특정 영역 (Fl_Group* grpViewer 영역) 을 Fl_RGB_Image 로 만들고, 이를 fl_smimg 를 이용하여 burred 된 이미지로 간단히 만들 수 있습니다.


21세기 셜록인 역시 이분! 컴버배치!




 이 방법은 다음과 같은 원리로 진행 됩니다. (필요 사항, fl_smimg)


bool Fl_GroupAniSwitch::generate_blurred_img( Fl_Group* src, Fl_RGB_Image* &dst )
{
    if ( src != NULL )
    {
        Fl_Image_Surface* imgsurf = new Fl_Image_Surface( src->w(), src->h(), 0 );

        if ( imgsurf != NULL )
        {
            imgsurf->set_current();
            imgsurf->draw( src );
            Fl_RGB_Image* tmpimg = imgsurf->image();

            Fl_Display_Device::display_device()->set_current();

            if ( tmpimg != NULL )
            {
                ⁄⁄ Make it blurred ...

                int rsw = tmpimg->w() ⁄ 10;
                int rsh = src->h() ⁄ 10;

                if ( rsw < 1 )
                    rsw = 1;

                if ( rsh < 1 )
                    rsw = 1;

                BilinearFilter* filterBL = new BilinearFilter();
                ResizeEngine* rse1 = new ResizeEngine( filterBL );

                Fl_RGB_Image* smimg = rse1->scale( tmpimg, rsw, rsh );

                delete rse1;
                delete filterBL;

                if ( smimg != NULL )
                {
                    BicubicFilter* filterBC = new BicubicFilter();
                    ResizeEngine* rse2 = new ResizeEngine( filterBC );

                    dst = rse2->scale( smimg, src->w(), src->h() );

                    discard_rgb_image( smimg );
                    delete rse2;
                    delete filterBC;
                }

                discard_rgb_image( tmpimg );
            }

            delete imgsurf;

            if ( dst != NULL )
                return true;
        }
    }

    return false;
}

void Fl_GroupAniSwitch::discard_rgb_image( Fl_RGB_Image* &img )
{
    if( img != NULL )
    {
        if ( ( img->array != NULL ) && ( img->alloc_array == 0 ) )
        {
            delete[] img->array;
        }

        delete img;
        img = NULL;
    }
}

 위 코드를 보면, BiLinear 로 이미지를 10% 크기로 줄인다음, 이를 다시 원래 이미지 크기로 BiCubic 을 이용해서 늘립니다. 물론 이런 경우 Gaussian 보단 빠르지만 품질은 약간 떨어 지게 되는 단점이 있지만, GUI 내에서 빠르게 배경 이미지로 뭔가를 구현 하는데 있어서는 나쁘지 않은 결과물을 얻을 수 있습니다.


 여기서 주목해야 하는 것은 Fl_Image_Surface 라는 FLTK widget 을 Fl_RGB_Image 에 그릴 수 있는 offscreen render 방법 입니다. 간단한 방법으로 여러 응용을 할 수 있으며, 현재 그려지는 윈도우 전체를 blur 된 이미지로 처리하고, 이 위에 다른걸 그리는 방법을 생각 해 보는 아이디어를 구현할 수 있습니다.


 마침 가칭 Fl_GroupAniSwitch() 의 메모리 누수가 해결 되었으므로, 이를 다음 post 로 올려 공개 해 보도록 하겠습니다.