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:
m_pDirect3D9 = Direct3DCreate9(D3D_SDK_VERSION);
if (!m_pDirect3D9)
return FALSE;
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;
presentParameters.BackBufferFormat = D3DFMT_A8R8G8B8;
presentParameters.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
presentParameters.BackBufferWidth = imageWidth;
presentParameters.BackBufferHeight = imageHeight;
HRESULT res = m_pDirect3D9->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE,
&presentParameters,
&m_pDirect3DDevice9
);
if (m_pDirect3DDevice9 == NULL)
return FALSE;
D3DXCreateSprite(m_pDirect3DDevice9, &m_pSprite);
if (m_pSprite == NULL)
return FALSE;
m_pDirect3DDevice9->CreateTexture(
imageWidth, imageHeight,
1,
0,
D3DFMT_L8,
D3DPOOL_MANAGED,
&m_pTexture,
NULL
);
if (!m_pTexture)
return FALSE;
Updating the texture:
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);
m_pSprite->Begin(0);
m_pSprite->Draw(
m_pTexture, NULL, NULL, NULL,
D3DCOLOR_ARGB(255, 255, 255, 255) );
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.