如何进行快速位图拉伸? [英] How to do fast bitmap stretching?

查看:158
本文介绍了如何进行快速位图拉伸?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试尽可能快地拉伸位图.
我需要每秒拉伸60个位图.

我正在使用StretchBltBits,但是当我使用HALFTONE BltMode时,我每秒只能得到24-25帧.

位图可以是16bpp,24bppor和32bpp 1024x576.

解决方案

如果真的想改善图像的显示效果,那么可以考虑使用硬件加速功能.使用DirectX或OpenGL库.

一次,我使用DirectX和Sprite来显示2D图像(还有其他一些东西).我将复制对我有用的代码,但是请注意我不是Direct3D专家,并且我使用了 DirectX9 ,因此您可能会找到更好,最新的代码.

初始化代码:

 // 创建Direct3D对象(类型:IDirect3D9 *)
m_pDirect3D9 = Direct3DCreate9(D3D_SDK_VERSION);
如果(!m_pDirect3D9)
     返回为假;

// 设置显示模式(根据需要更改所需的内容)
D3DDISPLAYMODE displayMode;
m_pDirect3D9-> GetAdapterDisplayMode(D3DADAPTER_DEFAULT,& displayMode);
displayMode.Format = D3DFMT_A8R8G8B8;

D3DPRESENT_PARAMETERS presentParameters;
ZeroMemory(& presentParameters, sizeof (D3DPRESENT_PARAMETERS));
presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
// 别忘了这个
presentParameters.Windowed = TRUE;
presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
presentParameters.EnableAutoDepthStencil = TRUE;
presentParameters.AutoDepthStencilFormat = D3DFMT_D24X8;
presentParameters.BackBufferCount =  1 ;
// 格式=每像素32位(ARGB)
presentParameters.BackBufferFormat = D3DFMT_A8R8G8B8;
presentParameters.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
// 在此处放置图片大小
presentParameters.BackBufferWidth = imageWidth;
presentParameters.BackBufferHeight = imageHeight;

// 创建设备(类型:IDirect3DDevice9 *)
HRESULT res = m_pDirect3D9-> CreateDevice(
    D3DADAPTER_DEFAULT,
    // 使用视频卡
    D3DDEVTYPE_HAL,
    // 窗口句柄(您将在其中显示图像的窗口句柄)
    hWnd,
    // 这对我来说很重要
    // 尤其是第二个:浮点运算可能会给出
    如果不使用FPU_PRESERVE,则// 不同的结果将导致另一个线程!
    // ,但在大多数情况下,我认为您可以删除此
    D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE,
    & presentParameters,
    & m_pDirect3DDevice9
);
如果(m_pDirect3DDevice9 == NULL)
    返回为假;

// 创建用于显示图像的精灵(m_pSprite的ID3DXSprite *类型)
D3DXCreateSprite(m_pDirect3DDevice9,& m_pSprite);
如果(m_pSprite == NULL)
    返回为假;

// 创建将由精灵使用的纹理
//  m_pTexture的类型为IDirect3DTexture9 * 
m_pDirect3DDevice9-> CreateTexture(
    imageWidth,imageHeight,
     1  0 // 像素格式:在我的情况下,我想显示8位/像素的图像
    D3DFMT_L8,
    D3DPOOL_MANAGED,
    & m_pTexture,
    无效的
);
如果(!m_pTexture)
    返回为假; 



更新纹理:

 // 在我的情况下,图像为8位/像素
无效 YourClass :: UpdateTexture( const  BYTE *图片)
{
    如果(m_pTexture == NULL)
        返回;

    D3DLOCKED_RECT已锁定;
    m_pTexture-> LockRect(
         0 ,
        & lockedRect,
        无效的,
        D3DLOCK_DISCARD
    );
     for ( int  y =  0 ; y <  m_imageHeight; y ++)
    {
        复制内存(
            (BYTE *)lockedRect.pBits + y * lockedRect.Pitch,
            图片+ y * m_imageWidth,
            m_imageWidth
        );
    }
    m_pTexture-> UnlockRect( 0 );
} 



绘图代码(从OnPaint调用):

  void  YourClass :: Draw()
{
    如果(!m_pDirect3DDevice9)
        返回;

    m_pDirect3DDevice9-> BeginScene();
    m_pDirect3DDevice9-> Clear( 0 ,NULL,D3DCLEAR_TARGET,D3DCOLOR_ARGB( 255  0  1  .0f,// 绘制纹理
    m_pSprite-> Begin( 0 );
    m_pSprite-> Draw(
        m_pTexture,// 纹理
        NULL,NULL,NULL,
        D3DCOLOR_ARGB( 255  255  255  255 )// 使用alpha +颜色
    );
    m_pSprite-> End();

    m_pDirect3DDevice9-> EndScene();
    m_pDirect3DDevice9-> Present(NULL,NULL,NULL,NULL);
} 



您可以在OpenGL中执行类似的操作.不幸的是,我无法在本机OpenGL中提供代码.


Hi I am trying to stretch a bitmapas fast as possible.
I need to stretch 60 bitmaps per second.

I am using StretchBltBits but when I use HALFTONE BltMode I only get 24-25 frames per second.

The bitmap can be 16bpp, 24bppor and 32bpp 1024x576.

is ther a faster way to strech the bitmap then StretchBltBits?

解决方案

If you want to really improve your image display, then consider using hardware accelerated functions. Use DirectX or OpenGL libraries.

Once, I used DirectX and sprites to display a 2D image (and a few more things). I will copy the code that worked for me, but please note I am not a Direct3D expert and I used DirectX9 so you can probably find better and more up to date code.

Initialization code:

//creates the Direct3D object (type: IDirect3D9*)
m_pDirect3D9 = Direct3DCreate9(D3D_SDK_VERSION);
if (!m_pDirect3D9)
     return FALSE;

//setup the display mode (change whatever you want depending on your requirements)
D3DDISPLAYMODE displayMode;
m_pDirect3D9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &displayMode);
displayMode.Format = D3DFMT_A8R8G8B8;

D3DPRESENT_PARAMETERS presentParameters;
ZeroMemory(&presentParameters, sizeof(D3DPRESENT_PARAMETERS));
presentParameters.MultiSampleType           = D3DMULTISAMPLE_NONE;
//don't forget this
presentParameters.Windowed                  = TRUE;
presentParameters.SwapEffect                = D3DSWAPEFFECT_DISCARD;
presentParameters.EnableAutoDepthStencil    = TRUE;
presentParameters.AutoDepthStencilFormat    = D3DFMT_D24X8;
presentParameters.BackBufferCount           = 1;
//format = 32 bits per pixel (ARGB)
presentParameters.BackBufferFormat          = D3DFMT_A8R8G8B8;
presentParameters.Flags                     = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
//put the size of your image here
presentParameters.BackBufferWidth           = imageWidth;
presentParameters.BackBufferHeight          = imageHeight;

//create the device (type: IDirect3DDevice9*)
HRESULT res = m_pDirect3D9->CreateDevice(
    D3DADAPTER_DEFAULT,
    // use video card
    D3DDEVTYPE_HAL,
    // window handle (the one into which you will display the image)
    hWnd,
    //this was important in my case
    //especially the second one: floating point operations may give
    //different results in another thread if you don't use FPU_PRESERVE!!
    //but in most case I think you can remove this
    D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE,
    &presentParameters,
    &m_pDirect3DDevice9
);
if (m_pDirect3DDevice9 == NULL)
    return FALSE;

//create the sprite used to display the image (m_pSprite is of type ID3DXSprite*)
D3DXCreateSprite(m_pDirect3DDevice9, &m_pSprite);
if (m_pSprite == NULL)
    return FALSE;

//create the texture that will be used by the sprite
//m_pTexture is of type IDirect3DTexture9*
m_pDirect3DDevice9->CreateTexture(
    imageWidth, imageHeight,
    1,
    0,
    //pixel format: in my case I wanted to display a 8 bits/pixel image
    D3DFMT_L8,       
    D3DPOOL_MANAGED,
    &m_pTexture,
    NULL
);
if (!m_pTexture)
    return FALSE;



Updating the texture:

//in my case, the image is 8 bits/pixel
void YourClass::UpdateTexture(const BYTE* image)
{
    if (m_pTexture == NULL)
        return;

    D3DLOCKED_RECT lockedRect;
    m_pTexture->LockRect(
        0,
        &lockedRect,
        NULL,
        D3DLOCK_DISCARD
    );
    for (int y = 0; y < m_imageHeight; y++)
    {
        CopyMemory(
            (BYTE*)lockedRect.pBits + y * lockedRect.Pitch,
            image + y * m_imageWidth,
            m_imageWidth
        );
    }
    m_pTexture->UnlockRect(0);
}



Drawing code (to be called from OnPaint):

void YourClass::Draw()
{
    if (!m_pDirect3DDevice9)
        return;

    m_pDirect3DDevice9->BeginScene();
    m_pDirect3DDevice9->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(255, 0, 0, 0), 1.0f, 0);

    // draw the texture
    m_pSprite->Begin(0);
    m_pSprite->Draw(
        m_pTexture,  // texture
        NULL, NULL, NULL,
        D3DCOLOR_ARGB(255, 255, 255, 255)   // use alpha + colors
    );
    m_pSprite->End();

    m_pDirect3DDevice9->EndScene();
    m_pDirect3DDevice9->Present(NULL, NULL, NULL, NULL);
}



You can do something similar in OpenGL. Unfortunately, I can''t provide code in native OpenGL.


这篇关于如何进行快速位图拉伸?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆