• 13
• 18
• 19
• 27
• 10

# How to filter out common color around object within rectangle?

This topic is 2057 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I am currently working on a 2D game where spritesheets are obtained through memory in .pak files. The images are .bmp files and the sprites render correctly, except for the fact the background/unused color/pixels around the sprite appears, as expected; however, I want to be able to remove the background pixels like such:

Rendered sprite without removing surrounding pixels:

This is the output I would like to achieve:

Thanks for any suggestions or help. Edited by kamal7

##### Share on other sites
It sounds like you should be using the alpha channel instead of a solid background color. This also allows nicely antialiased sprite edges.

##### Share on other sites
It would be good to have alpha based sprites, however I am currently working on an old mmorpg and converting everything to Direct X 9. The game achieves this through their own procedure with DirectDraw7 to render the finalized sprites. I was just wondering if there was any simpler way to do this in Direct X 9 instead of following the same procedure as the old game code. If I can find the code where they do this I will post it, but for now does anyone have any other alternatives other than creating an alpha channel in all the sprites? (because there is about 1000 sprite sheets and I want to refrain from creating alpha channels for them all for obvious reasons).

##### Share on other sites
I was thinking of using texture filtering but I am unsure if this will achieve what I am looking for. Can someone verify?

On a side note: all the sprites have no anti-aliasing with the background color so it can be easily separated from the object within the sprite, but I am unsure of a procedure at the moment. Edited by kamal7

##### Share on other sites
Legacy code/assets. Sounds fun. ;) I guess you could filter out that specific background color on a per-pixel basis, but... why? My suggestion would be write a quick conversion tool that loops through a directory, loads each file, replaces that color with transparent, then saves the file in a new location.

##### Share on other sites
Use chroma-keying, it's supported by DX 9

##### Share on other sites

Legacy code/assets. Sounds fun. ;) I guess you could filter out that specific background color on a per-pixel basis, but... why? My suggestion would be write a quick conversion tool that loops through a directory, loads each file, replaces that color with transparent, then saves the file in a new location.

Its not only one specific color... because a sprite can have any color. So the background color must be always completely different than the objects that a sprite contains in order for the background to be easily filtered out which limits that approach.

I will look into chroma-keying as LancerSolurus suggested. Edited by kamal7

##### Share on other sites

Use chroma-keying, it's supported by DX 9

This appears to be a very reliable option especially since the background is only one color per sprite. I am doing my research now, but if you have any resources you can link to me, that would speed things up a lot for me. Thanks!

I also think this is performance-friendly since the gpu loads all the sprites before the game starts, I will be able to create an alpha channel for all the pixels processed through chroma-keying. But for now, like I said, I will be doing some research and if you have any links to site(s) that explain the process or any approaches to accomplish this that would be great! Edited by kamal7

##### Share on other sites
Here is some code that I promised (I am not sure if this will achieve what I want, I tried to show all the highlights from the old source code that I am converting to Direct X 9... hopefully I got the right stuff):

If anything highlights what I am trying to achieve, please let me know as I am unfimiliar with the functions processed with all this code. I am sorry and hate to just pile stuff on everyone but I am sure an experienced coder can just schim through without even reading to recognize when pixels are being removed or replaced that would most likely be removing a background color around an object within a sprite.

This is where all the bitmap image data is read:
 IDirectDrawSurface7 * CSprite::_pMakeSpriteSurface() { IDirectDrawSurface7 * pdds4; HDC hDC; WORD * wp; m_bOnCriticalSection = TRUE; if( m_stBrush == NULL ) return NULL; CMyDib mydib(m_cPakFileName, m_dwBitmapFileStartLoc); // Reads bitmap data/info m_wBitmapSizeX = mydib.m_wWidthX; // image width m_wBitmapSizeY = mydib.m_wHeightY; // image height pdds4 = m_pDDraw->pCreateOffScreenSurface(m_wBitmapSizeX, m_wBitmapSizeY); if (pdds4 == NULL) return NULL; pdds4->GetDC(&hDC); mydib.PaintImage(hDC); pdds4->ReleaseDC(hDC); DDSURFACEDESC2 ddsd; ddsd.dwSize = 124; if (pdds4->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) != DD_OK) return NULL; pdds4->Unlock(NULL); wp = (WORD *)ddsd.lpSurface; m_wColorKey = *wp; m_bOnCriticalSection = FALSE; return pdds4; } 

This is where the Off Screen Surface is created:
 IDirectDrawSurface7 * DXC_ddraw::pCreateOffScreenSurface(WORD wSzX, WORD wSzY) { DDSURFACEDESC2 ddsd; IDirectDrawSurface7 * pdds4; ZeroMemory(&ddsd, sizeof(ddsd)); if ((wSzX % 4) != 0) wSzX += 4 - (wSzX % 4); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; ddsd.dwWidth = (DWORD)wSzX; ddsd.dwHeight = (DWORD)wSzY; if (m_lpDD4->CreateSurface(&ddsd, &pdds4, NULL) != DD_OK) return NULL; return pdds4; } 

Before the sprite(surface) is rendered, this is called:
 bool CSprite::_iOpenSprite() { if (m_lpSurface != NULL) return FALSE; m_lpSurface = _pMakeSpriteSurface(); // image data read and surface created if (m_lpSurface == NULL) return FALSE; m_pDDraw->iSetColorKey(m_lpSurface, m_wColorKey); m_bIsSurfaceEmpty = FALSE; DDSURFACEDESC2 ddsd; ddsd.dwSize = 124; if (m_lpSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) != DD_OK) return FALSE; m_pSurfaceAddr = (WORD *)ddsd.lpSurface; m_sPitch = (short)ddsd.lPitch >> 1; m_lpSurface->Unlock(NULL); return TRUE; } HRESULT DXC_ddraw::iSetColorKey(IDirectDrawSurface7 * pdds4, WORD wColorKey) { DDCOLORKEY ddck; ddck.dwColorSpaceLowValue = _dwColorMatch(pdds4, wColorKey); ddck.dwColorSpaceHighValue = ddck.dwColorSpaceLowValue; return pdds4->SetColorKey(DDCKEY_SRCBLT, &ddck); } DWORD DXC_ddraw::_dwColorMatch(IDirectDrawSurface7 * pdds4, WORD wColorKey) { DWORD dw = CLR_INVALID, * dwp; DDSURFACEDESC2 ddsd2; HRESULT hres; ddsd2.dwSize = sizeof(ddsd2); while ((hres = pdds4->Lock(NULL, &ddsd2, 0, NULL)) == DDERR_WASSTILLDRAWING); if (hres == DD_OK) { dwp = (DWORD *)ddsd2.lpSurface; *dwp = (DWORD)wColorKey; dw = *(DWORD *)ddsd2.lpSurface; dw &= (1 << ddsd2.ddpfPixelFormat.dwRGBBitCount)-1; pdds4->Unlock(NULL); } return dw; } 

This renders the sprite in the end:
 m_pDDraw->m_lpBackB4->BltFast( dX, dY, m_lpSurface, &rcRect, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT ); 

Thanks for your patience and support. Edited by kamal7

##### Share on other sites
I believe the solution I need to achieve this is through color keying hense all the variations of (colorkey) variable names in the code I just posted, lol. Heres is a similar thread I found here on these forums; however, it is based on OpenGL: http://www.gamedev.net/topic/419337-opengl-and-sprites/

Any suggestions or guidance is appreciated as I continue to research color keying.

Thanks a lot for all your help.