zoukankan      html  css  js  c++  java
  • 一个简单的能处理MIPMAP的类

    //-------------------------------------------------------------------------
    eiTexture::eiTexture(eiBool instance_type, eiBool mip_map_filter)
    {
        format        
    = NONE;
        type        
    = SRC;
        m_width        
    = 0;
        m_height    
    = 0;
        instance    
    = instance_type;
        use_mip_map    
    = mip_map_filter;
        bits        
    = NULL;
    }

    //-------------------------------------------------------------------------
    eiTexture::~eiTexture()
    {
    }

    //-------------------------------------------------------------------------
    eiBool eiTexture::load(eiChar *file_name)
    {
        CFile file;

        
    if!file.Open( file_name, CFile::modeRead | CFile::shareDenyWrite ) )
        
    {
            msger.print(
    "Load texture failed.");    
            
    return false;
        }


        BITMAPFILEHEADER bfhHeader;

        file.Read( 
    &bfhHeader, sizeof(BITMAPFILEHEADER) );

        
    if( bfhHeader.bfType != 0x4d42 )
        
    {
            msger.print(
    "Load texture failed.");
            
    return false;
        }

        
        eiUInt uBmpInfoLen 
    = (eiUInt) bfhHeader.bfOffBits - sizeof(BITMAPFILEHEADER);

        LPBITMAPINFOHEADER m_lpBMPHdr 
    = (LPBITMAPINFOHEADER) new eiByte [ uBmpInfoLen ];

        eiUInt counts 
    = file.Read(m_lpBMPHdr, uBmpInfoLen);

        
    if(m_lpBMPHdr->biSize != sizeof(BITMAPINFOHEADER))
        
    {
            msger.print(
    "Texture format error.");
            
    return false;
        }


        DWORD m_dwImageSize 
    = m_lpBMPHdr->biSizeImage;

        
    if(m_dwImageSize == 0)
        
    {
            DWORD dwBytes 
    = ((DWORD) m_lpBMPHdr->biWidth * m_lpBMPHdr->biBitCount) / 32;
            
            
    if(((DWORD) m_lpBMPHdr->biWidth * m_lpBMPHdr->biBitCount) % 32)
            
    {
                dwBytes
    ++;
            }


            dwBytes 
    *= 4;

            m_dwImageSize 
    = dwBytes * m_lpBMPHdr->biHeight; 
        }


        bits 
    = (eiByte*new eiByte [ m_dwImageSize ];

        counts 
    = file.Read(bits, m_dwImageSize);

        file.Close();

        m_width  
    = m_lpBMPHdr->biWidth;
        m_height 
    = m_lpBMPHdr->biHeight;

        delete []m_lpBMPHdr;

        format 
    = BMP;

        normalize();

        inv_width    
    = 1.0 / m_width;
        inv_height    
    = 1.0 / m_height;

        
    if(use_mip_map)
        
    {
            make_mip_map();
        }


        
    return true;
    }

    //-------------------------------------------------------------------------
    eiVoid eiTexture::normalize()
    {
        eiByte    
    *pbits;
        eiInt    n_width,n_height;
        eiFloat dx,dy;
        eiColor color;

        pbits 
    = bits;
        n_width 
    = (eiInt) powf( 2, (eiInt) log2f( m_width ) + 1 );
        n_height 
    = (eiInt) powf( 2, (eiInt) log2f( m_height ) + 1 );

        dx 
    = (eiFloat) m_width / (eiFloat) n_width;
        dy 
    = (eiFloat) m_height / (eiFloat) n_height;

        src.resize( n_width 
    * n_height * 3 );

        std::vector
    <eiByte>::iterator pbyPtr = src.begin();

        
    for(eiInt j = 0 ; j < n_height ; j++)
        
    {
            
    for(eiInt i = 0 ; i < n_width ; i++)
            
    {
                color 
    = get_bilinear_color( pbits, i * dx, j * dy );

                pbyPtr[
    0= (eiByte) ( color.b * 255 );
                pbyPtr[
    1= (eiByte) ( color.g * 255 );
                pbyPtr[
    2= (eiByte) ( color.r * 255 );

                pbyPtr 
    += 3;
            }

        }

        
        delete []pbits;
        bits 
    = NULL;

        m_width 
    = n_width;
        m_height 
    = n_height;
    }

    //-------------------------------------------------------------------------
    eiInt eiTexture::get_width()
    {
        
    return m_width;
    }

    //-------------------------------------------------------------------------
    eiInt eiTexture::get_height()
    {
        
    return m_height;
    }

    //-------------------------------------------------------------------------
    eiColorB eiTexture::get_color(eiByte *dibbits, eiInt x, eiInt y)
    {
        eiColorB color;

        color.r 
    = color.g = color.b = 0;

        
    if(dibbits == NULL)
            
    return color;

        
    if(x < 0)
            x 
    = 0;
        
    if(x >= m_width)
            x 
    = m_width - 1;
        
    if(y < 0)
            y 
    = 0;
        
    if(y >= m_height)
            y 
    = m_height - 1;

        eiByte 
    *pbyPtr;

        pbyPtr 
    = dibbits + (y * m_width + x) * 3;

        color.b 
    = pbyPtr[0];
        color.g 
    = pbyPtr[1];
        color.r 
    = pbyPtr[2];

        
    return color;
    }

    //-------------------------------------------------------------------------
    eiColor eiTexture::get_bilinear_color(eiByte *dibbits, eiFloat x, eiFloat y)
    {
        eiInt        u,v;

        u 
    = (eiInt) x;
        v 
    = (eiInt) y;

        
    if( (eiFloat) u == x && (eiFloat) v == y )
        
    {
            eiColorB clr 
    = get_color(dibbits,u,v);
            
            
    return newclr(    clr.r * EI_BYTE_2_FLOAT,
                            clr.g 
    * EI_BYTE_2_FLOAT,
                            clr.b 
    * EI_BYTE_2_FLOAT    );
        }


        eiFloat        du,dv,r1,g1,b1,r2,g2,b2;
        eiColorB    c1,c2,c3,c4;

        du 
    = curve( x - u );
        dv 
    = curve( y - v );

        c1 
    = get_color(dibbits,u,v);
        c2 
    = get_color(dibbits,u+1,v);
        c3 
    = get_color(dibbits,u+1,v+1);
        c4 
    = get_color(dibbits,u,v+1);

        r1 
    = c1.r + (c2.r - c1.r) * du;
        g1 
    = c1.g + (c2.g - c1.g) * du;
        b1 
    = c1.b + (c2.b - c1.b) * du;

        r2 
    = c4.r + (c3.r - c4.r) * du;
        g2 
    = c4.g + (c3.g - c4.g) * du;
        b2 
    = c4.b + (c3.b - c4.b) * du;

        r1 
    = r1 + (r2 - r1) * dv;
        g1 
    = g1 + (g2 - g1) * dv;
        b1 
    = b1 + (b2 - b1) * dv;

        r1 
    *= EI_BYTE_2_FLOAT;
        g1 
    *= EI_BYTE_2_FLOAT;
        b1 
    *= EI_BYTE_2_FLOAT;

        
    return newclr(r1,g1,b1);
    }

    //-------------------------------------------------------------------------
    eiColorB eiTexture::get_src_color(eiInt x, eiInt y)
    {
        eiColorB color;

        color.r 
    = color.g = color.b = 0;

        
    if(src.empty())
            
    return color;

        
    if(x < 0)
            x 
    = 0;
        
    if(x >= m_width)
            x 
    = m_width - 1;
        
    if(y < 0)
            y 
    = 0;
        
    if(y >= m_height)
            y 
    = m_height - 1;

        std::vector
    <eiByte>::iterator pbyPtr;

        pbyPtr 
    = src.begin() + (y * m_width + x) * 3;

        color.b 
    = pbyPtr[0];
        color.g 
    = pbyPtr[1];
        color.r 
    = pbyPtr[2];

        
    return color;
    }

    //-------------------------------------------------------------------------
    eiColor eiTexture::get_src_bilinear_color(eiFloat x, eiFloat y)
    {
        eiInt        u,v;

        u 
    = (eiInt) x;
        v 
    = (eiInt) y;

        
    if( (eiFloat) u == x && (eiFloat) v == y )
        
    {
            eiColorB clr 
    = get_src_color(u,v);
            
            
    return newclr(    clr.r * EI_BYTE_2_FLOAT,
                            clr.g 
    * EI_BYTE_2_FLOAT,
                            clr.b 
    * EI_BYTE_2_FLOAT    );
        }


        eiFloat        du,dv,r1,g1,b1,r2,g2,b2;
        eiColorB    c1,c2,c3,c4;

        du 
    = curve( x - u );
        dv 
    = curve( y - v );

        c1 
    = get_src_color(u,v);
        c2 
    = get_src_color(u+1,v);
        c3 
    = get_src_color(u+1,v+1);
        c4 
    = get_src_color(u,v+1);

        r1 
    = c1.r + (c2.r - c1.r) * du;
        g1 
    = c1.g + (c2.g - c1.g) * du;
        b1 
    = c1.b + (c2.b - c1.b) * du;

        r2 
    = c4.r + (c3.r - c4.r) * du;
        g2 
    = c4.g + (c3.g - c4.g) * du;
        b2 
    = c4.b + (c3.b - c4.b) * du;

        r1 
    = r1 + (r2 - r1) * dv;
        g1 
    = g1 + (g2 - g1) * dv;
        b1 
    = b1 + (b2 - b1) * dv;

        r1 
    *= EI_BYTE_2_FLOAT;
        g1 
    *= EI_BYTE_2_FLOAT;
        b1 
    *= EI_BYTE_2_FLOAT;

        
    return newclr(r1,g1,b1);
    }

    //-------------------------------------------------------------------------
    eiVoid eiTexture::blt(eiInt x1,eiInt y1,eiInt x2,eiInt y2,
                            eiInt width,eiInt height)
    {
        eiInt    c1,c2,c3,c4;
        std::vector
    <eiByte>::iterator    pbyPtr;

        
    for( eiInt j = y1, mj = y2 ; j < (y1 + height) ; j += 2, mj++ )
        
    {
            
    for( eiInt i = x1, mi = x2 ; i < (x1 + width) ; i += 2, mi++ )
            
    {
                pbyPtr 
    = mip_map.begin() + j * m_width + i;
                c1 
    = pbyPtr[0];
                c2 
    = pbyPtr[1];

                pbyPtr 
    += m_width;
                c3 
    = pbyPtr[0];
                c4 
    = pbyPtr[1];

                pbyPtr 
    = mip_map.begin() + mj * m_width + mi;
                pbyPtr[
    0= (eiByte) ( (eiFloat) ( c1 + c2 + c3 + c4 ) * 0.25 );
            }

        }

    }

    //-------------------------------------------------------------------------
    eiVoid eiTexture::bltB(eiInt x1,eiInt y1,eiInt x2,eiInt y2,
                            eiInt width,eiInt height)
    {
        
    if(width == 0 || height == 0)
            
    return;

        eiInt width2,height2;

        width2 
    = width / 2;
        height2 
    = height / 2;

        blt( x1, y1, x2, y2, width, height);

        bltB( x2, y2, x2 
    / 2, y2 / 2, width2, height2 );
    }

    //-------------------------------------------------------------------------
    eiVoid eiTexture::bltG(eiInt x1,eiInt y1,eiInt x2,eiInt y2,
                            eiInt width,eiInt height)
    {
        
    if(width == 0 || height == 0)
            
    return;

        eiInt width2,height2;

        width2 
    = width / 2;
        height2 
    = height / 2;

        blt( x1, y1, x2, y2, width, height);

        bltG( x2, y2, x2 
    / 2, y2, width2, height2 );
    }

    //-------------------------------------------------------------------------
    eiVoid eiTexture::bltR(eiInt x1,eiInt y1,eiInt x2,eiInt y2,
                            eiInt width,eiInt height)
    {
        
    if(width == 0 || height == 0)
            
    return;

        eiInt width2,height2;

        width2 
    = width / 2;
        height2 
    = height / 2;

        blt( x1, y1, x2, y2, width, height);

        bltR( x2, y2, x2, y2 
    / 2, width2, height2 );
    }

    //-------------------------------------------------------------------------
    eiBool eiTexture::make_mip_map()
    {
        
    if(format == NONE || type == MIP_MAP)
            
    return false;

        mip_map.resize( m_width 
    * m_height );

        eiColorB                        c1,c2,c3,c4;
        eiFloat                            r,g,b;
        std::vector
    <eiByte>::iterator    pbyPtr;
        eiInt                            width2,height2;

        width2 
    = m_width / 2;
        height2 
    = m_height / 2;

        
    for( eiInt j = 0, mj = 0 ; j < m_height ; j += 2, mj++ )
        
    {
            
    for( eiInt i = 0, mi = 0 ; i < m_width ; i += 2, mi++ )
            
    {
                c1 
    = get_src_color( i , j );
                c2 
    = get_src_color( i + 1 , j );
                c3 
    = get_src_color( i + 1 , j + 1 );
                c4 
    = get_src_color( i , j + 1 );

                b 
    = (eiFloat) ( (eiInt) c1.b + (eiInt) c2.b + (eiInt) c3.b + (eiInt) c4.b ) * 0.25;
                g 
    = (eiFloat) ( (eiInt) c1.g + (eiInt) c2.g + (eiInt) c3.g + (eiInt) c4.g ) * 0.25;
                r 
    = (eiFloat) ( (eiInt) c1.r + (eiInt) c2.r + (eiInt) c3.r + (eiInt) c4.r ) * 0.25;

                
    // i have not considered efficiency problem in precomputing progress

                
    /* mip-map is built as follow :

                NEXT GREEN
                RED  BLUE    
    */


                pbyPtr 
    = mip_map.begin() + ( mj + height2 ) * m_width + mi + width2;
                pbyPtr[
    0= (eiByte) b;

                pbyPtr 
    = mip_map.begin() + mj * m_width + mi + width2;
                pbyPtr[
    0= (eiByte) g;

                pbyPtr 
    = mip_map.begin() + ( mj + height2 ) * m_width + mi;
                pbyPtr[
    0= (eiByte) r;
            }

        }


        bltB( width2, height2, m_width 
    / 4, m_height / 4, width2, height2 );
        bltG( width2, 
    0, m_width / 40, width2, height2 );
        bltR( 
    0, height2, 0, m_height / 4, width2, height2 );

        type 
    = MIP_MAP;

        
    return true;
    }

    //-------------------------------------------------------------------------
    eiFloat eiTexture::get_bilinear(eiFloat x, eiFloat y)
    {
        eiInt                            u,v;
        std::vector
    <eiByte>::iterator    pbyPtr;

        u 
    = (eiInt) x;
        v 
    = (eiInt) y;

        
    if( (eiFloat) u == x && (eiFloat) v == y )
        
    {
            pbyPtr 
    = mip_map.begin() + m_width * v + u;

            
    return pbyPtr[0* EI_BYTE_2_FLOAT;
        }


        eiFloat        du,dv,r1,r2;
        eiByte        f1,f2,f3,f4;

        du 
    = curve( x - u );
        dv 
    = curve( y - v );

        pbyPtr 
    = mip_map.begin() + m_width * v + u;
        f1 
    = pbyPtr[0];
        f2 
    = pbyPtr[1];

        pbyPtr 
    += m_width;
        f3 
    = pbyPtr[1];
        f4 
    = pbyPtr[0];

        r1 
    = f1 + (f2 - f1) * du;

        r2 
    = f4 + (f3 - f4) * du;

        r1 
    = r1 + (r2 - r1) * dv;

        
    return r1 * EI_BYTE_2_FLOAT;
    }

    //-------------------------------------------------------------------------
    eiColor eiTexture::get_pixel(eiFloat x, eiFloat y, eiInt d)
    {
        
    if(src.empty() || ( type == MIP_MAP && mip_map.empty() ) )
            
    return newclr();

        
    if(d == 0)
        
    {
            
    return get_src_bilinear_color( x, y );
        }


        eiFloat b,g,r,scale;

        scale 
    = 1 / powf( 2 , d );

        eiFloat mx,my,width2,height2;

        width2 
    = m_width * scale;
        height2 
    = m_height * scale;
        mx 
    = x * scale;
        my 
    = y * scale;

        b 
    = get_bilinear( width2 + mx , height2 + my );

        g 
    = get_bilinear( width2 + mx , my );

        r 
    = get_bilinear( mx , height2 + my );

        
    return newclr(r,g,b);
    }

    //-------------------------------------------------------------------------
    eiColor eiTexture::lookup(const eiPlane& uv)
    {
        
    return get_pixel(uv.x, uv.y, uv.z, uv.w);
    }

    //-------------------------------------------------------------------------
    eiColor eiTexture::get_pixel(eiFloat x, eiFloat y, eiFloat dx, eiFloat dy)
    {
        x 
    *= m_width;
        y 
    *= m_height;

        
    if( type == SRC || ( dx == 0.0 && dy == 0.0 ) )
        
    {
            
    //maybe shading for raytracing, do not use mip-map

            
    return get_src_bilinear_color( x, y );
        }


        dx 
    *= m_width;
        dy 
    *= m_height;

        eiFloat d;
        eiInt    di;
        eiColor    c1,c2;

        d 
    = max(dx,dy);

        d 
    = log2f(d);
        di 
    = (eiInt) d;
        d 
    = d - (eiFloat) di;

        c1 
    = get_pixel( x, y, di );
        c2 
    = get_pixel( x, y, di + 1 );

        
    return mixclr( c1, c2, d );
    }

    //-------------------------------------------------------------------------
  • 相关阅读:
    关于Windows窗口框架
    如何获取桌面截图
    浅析Windows安全相关的一些概念
    怎样才算会一门编程语言
    COM思想的背后
    XP之后Windows的一些变化
    智能指针与库
    SOUI开发应用展示2
    在SOUI中支持高分屏显示
    SOUI Editor使用教程
  • 原文地址:https://www.cnblogs.com/len3d/p/188838.html
Copyright © 2011-2022 走看看