Click here to Skip to main content
15,887,434 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
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?
Posted
Comments
DaveAuld 15-Mar-11 8:22am    
There will be an element of Hardware dependency to the speed. Does you CPU max out during this operation? Have you tried a multithreaded approach, and have each core stretching an image.
Niklas L 15-Mar-11 8:43am    
Are you sure it's the stretching that limits you to 25 fps? It sounds low for modern computers. Do you read data from disk for each image or something similar?
kagelind 15-Mar-11 8:50am    
I'm taking the picture from a live HD video camera with the SampleGrabber filter. If I don't call StretchBltBits i get 60fps.

1 solution

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:
C++
//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:
C#
//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):
C++
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.
 
Share this answer
 
v2
Comments
Sergey Alexandrovich Kryukov 15-Mar-11 15:37pm    
From the first glance, should work. My 5.
--SA
Olivier Levrey 15-Mar-11 15:59pm    
Thank you SA.
mbue 15-Mar-11 16:01pm    
Good answer. This will be the best way to improve speed.
Regards.
kagelind 16-Mar-11 2:50am    
Thanks will try it. But I think my problem is that I dont want to render the picture to the screen but to the memory. Think this is the bottleneck graphic card are not optimized for writing to memory.
Olivier Levrey 16-Mar-11 4:52am    
Actually StretcthBltBits already uses a memory buffer before drawing to the screen. I tried once to use a memory bitmap and it didn't change anything.

By the way, I used this SDK: http://www.microsoft.com/downloads/en/details.aspx?FamilyID=b66e14b8-8505-4b17-bf80-edb2df5abad4&displaylang=en

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900