Files
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

1664 lines
37 KiB
C++

#include "stdafx.h"
#include "dibsection.hpp"
#include "dibsurf.hpp" //lint !e537
#include <stack>
#include <vector>
//*******************************************************************
//
// DESCRIPTION:Implementation file for CDIBSurface support functions
//
// AUTHOR: Andrew Farrier
//
// SourceSafe Version: $Revision: 17 $
//
//******************************************************************
extern int g_NumDibSurf;
void CDIBSurface::ClearData (void)
{
ASSERT (m_DIBData);
m_DIBData->m_UseMask = false;
m_DIBData->m_BackBits = NULL;
m_DIBData->m_SelectedDC = NULL;
m_DIBData->m_SelectedDCRefCount = 0;
m_DIBData->m_Mask = NULL;
// m_DIBData->m_OldBits=NULL;
m_DIBData->m_Data=NULL;
m_DIBData->m_UpperLeft=NULL;
m_DIBData->m_Width = m_DIBData->m_Height = m_DIBData->m_Pitch = m_DIBData->m_BitDepth = 0;
}
void CDIBSurface::HLine( int x1, int x2, int y, COLORREF crColor )
{
int nWidth = GetWidth();
int nHeight = GetHeight();
if( 0 <= x1 && nWidth > x1 &&
0 <= x2 && nWidth > x2 &&
0 <= y && nHeight > y )
{
int nPixelSize = GetBitDepth() >> 3;
BYTE *pBits = GetMem( x1, y );
switch( nPixelSize )
{
case 2: // 16-bit
{
WORD wColor = ConvertColorToWord( crColor );
WORD *pData = (WORD *)pBits;
while( x1++ <= x2 )
*pData++ = wColor;
break;
}
case 3: // 24-bit
{
RGBTRIPLE rgbColor = ConvertColorToTriple( crColor );
RGBTRIPLE *pData = (RGBTRIPLE *)pBits;
while( x1++ <= x2 )
*pData++ = rgbColor;
break;
}
case 4: // 32-bit
{
DWORD dwColor = ConvertColorToLong( crColor );
DWORD *pData = (DWORD *)pBits;
while( x1++ <= x2 )
*pData++ = dwColor;
break;
}
default:
ASSERT( false );
break;
}
}
}
bool CDIBSurface::HighlightFrame (const CRect& inrect,bool up)
{
int x,y;
union
{
COLORREF color;
BYTE value[4];
} color;
const int delta=60;
CRect therect (inrect);
--therect.right;
--therect.bottom;
for(x=therect.left+1;x<therect.right;x++)
{
color.color = GetColor (x,therect.top);
if(up)
{
color.value[1] = clamp<int> (color.value[1],color.value[1]+delta,255);
color.value[2] = clamp<int> (color.value[2],color.value[2]+delta,255);
color.value[0] = clamp<int> (color.value[0],color.value[0]+delta,255);
}
else
{
color.value[1] = clamp<int> (0,color.value[1]-delta,color.value[1]);
color.value[2] = clamp<int> (0,color.value[2]-delta,color.value[2]);
color.value[0] = clamp<int> (0,color.value[0]-delta,color.value[0]);
}
SetColor (x,therect.top,color.color);
color.color = GetColor (x,therect.bottom);
if(up)
{
color.value[1] = clamp<int> (0,color.value[1]-delta,color.value[1]);
color.value[2] = clamp<int> (0,color.value[2]-delta,color.value[2]);
color.value[0] = clamp<int> (0,color.value[0]-delta,color.value[0]);
}
else
{
color.value[1] = clamp<int> (color.value[1],color.value[1]+delta,255);
color.value[2] = clamp<int> (color.value[2],color.value[2]+delta,255);
color.value[0] = clamp<int> (color.value[0],color.value[0]+delta,255);
}
SetColor (x,therect.bottom,color.color);
}
for(y=therect.top;y<therect.bottom;y++)
{
color.color = GetColor (therect.left,y);
if(up)
{
color.value[1] = clamp<int> (color.value[1],color.value[1]+delta,255);
color.value[2] = clamp<int> (color.value[2],color.value[2]+delta,255);
color.value[0] = clamp<int> (color.value[0],color.value[0]+delta,255);
}
else
{
color.value[1] = clamp<int> (0,color.value[1]-delta,color.value[1]);
color.value[2] = clamp<int> (0,color.value[2]-delta,color.value[2]);
color.value[0] = clamp<int> (0,color.value[0]-delta,color.value[0]);
}
SetColor (therect.left,y,color.color);
color.color = GetColor (therect.right,y);
if(up)
{
color.value[1] = clamp<int> (0,color.value[1]-delta,color.value[1]);
color.value[2] = clamp<int> (0,color.value[2]-delta,color.value[2]);
color.value[0] = clamp<int> (0,color.value[0]-delta,color.value[0]);
}
else
{
color.value[1] = clamp<int> (color.value[1],color.value[1]+delta,255);
color.value[2] = clamp<int> (color.value[2],color.value[2]+delta,255);
color.value[0] = clamp<int> (color.value[0],color.value[0]+delta,255);
}
SetColor (therect.right,y,color.color);
}
return true;
}
bool CDIBSurface::SetupLoadedBitmap (HBITMAP hbm)
{
BITMAP bm;
ASSERT (m_DIBData);
Destroy ();
if(hbm == NULL)
return false;
g_NumDibSurf++;
//
// get info about the bitmap
//
if(GetObject(hbm, sizeof(bm), &bm) == 0)
return false;
m_DIBData->m_BackBits = hbm;
m_DIBData->m_Data = (unsigned char *)bm.bmBits;
m_DIBData->m_Width = (UINT) bm.bmWidth;
m_DIBData->m_Height = (UINT) abs(bm.bmHeight);
m_DIBData->m_BitDepth = bm.bmPlanes * bm.bmBitsPixel;
m_DIBData->m_Pitch = bm.bmWidthBytes;
// workaround for bug in 95 where 24 images are not quad byte aligned
OSVERSIONINFO temp;
temp.dwOSVersionInfoSize = sizeof (temp);
if(!GetVersionEx (&temp))
return false;
if((temp.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) || (m_DIBData->m_BitDepth != 24))
m_DIBData->m_Pitch += ((4-(m_DIBData->m_Pitch&0x03))&0x03);
if(bm.bmHeight > 0)
m_DIBData->m_Pitch *= -1;
if(m_DIBData->m_Pitch < 0) // only the case if we have a bottom-up section
m_DIBData->m_UpperLeft = (m_DIBData->m_Data+((-1*m_DIBData->m_Pitch)*(((int)m_DIBData->m_Height)-1)));
else
m_DIBData->m_UpperLeft = m_DIBData->m_Data;
// create a DC to use the DIB section in
// m_DIBData->m_BackDC = CreateCompatibleDC (NULL);
// select the dib section into the DC from above
// m_DIBData->m_OldBits = (HBITMAP) SelectObject (m_DIBData->m_BackDC,m_DIBData->m_BackBits);
return true;
}
//****************************************************************
//
// Function Name: CDIBSurface::CopyBitmap
//
// Description: Will copy hbm to the current DIBSection. Will perform a
// stretchblt if needed. You can pass different coordinates if needed
// User is responsible for making sure the color tables match
//
// Returns: true if successful
//
//****************************************************************
bool CDIBSurface::CopyBitmap(HBITMAP hbm,int x,int y,int dx,int dy)
{
HDC hdcImage;
BITMAP bm;
HBITMAP temp;
bool err = false;
ASSERT (m_DIBData);
ASSERT (false);
if(hbm)
{
//
// select bitmap into a memoryDC so we can use it.
//
hdcImage = CreateCompatibleDC(NULL);
if(!hdcImage)
OutputDebugString("create compatible dc failed\n");
temp = (HBITMAP) SelectObject(hdcImage, hbm);
//
// get size of the bitmap
//
if(GetObject(hbm, sizeof(bm), &bm) == 0) // get size of bitmap
return false;
dx = dx == 0 ? bm.bmWidth : dx; // use the passed size, unless zero
dy = dy == 0 ? bm.bmHeight : dy;
if(!StretchBlt(0, 0, (int) GetWidth (),(int) GetHeight (), hdcImage, x, y, dx, dy, SRCCOPY))
err = true;
SelectObject (hdcImage,temp);
DeleteDC(hdcImage);
}
return err;
}
//****************************************************************
//
// Function Name: CDIBSurface::Create1BitMask
//
// Description: Parse a 1-bit DIBSurface and create a 1-bit mask
//
// Returns: true if successful
//
//****************************************************************
bool CDIBSurface::Create1BitMask (COLORREF colorref)
{
unsigned char *inmask,*inpic;
unsigned char *maskline,*picline;
int count;
UINT x,y,i;
int red,green,blue;
int maskpitch,picpitch;
int colorindex,value;
RGBQUAD colors[2];
ASSERT (m_DIBData);
ASSERT (m_DIBData->m_Mask);
if(!m_DIBData->m_Mask)
return false;
HDC dc;
dc = GetDC ();
if(GetDIBColorTable (dc,0,2,&(colors[0])) == 0)
{
ReleaseDC (dc);
return false;
}
ReleaseDC (dc);
red = colorref & 0xff;
green = (colorref>>8)&0xff;
blue = (colorref>>16)&0xff;
colorindex = -1;
for(i=0;i<2;i++)
{
if(red != colors[i].rgbRed)
continue;
if(green != colors[i].rgbGreen)
continue;
if(blue != colors[i].rgbBlue)
continue;
colorindex = (int) i;
break;
}
if(colorindex == -1)
return false;
maskline = m_DIBData->m_Mask->GetMem ();
maskpitch = m_DIBData->m_Mask->GetPitch ();
picline = GetMem ();
picpitch = GetPitch ();
for(y=0;y<m_DIBData->m_Height;y++)
{
inmask = maskline;
inpic = picline;
*inmask = 0;
count = 7;
for(x=0;x<m_DIBData->m_Width;x++,count--)
{
if(count < 0)
{
inmask++;
*inmask = 0;
count = 7;
inpic++;
}
value = ((*inpic)>>count)&0x01;
if(value == colorindex)
{
(*inmask) += (1<<count);
(*inpic) &= ~(1<<count);
}
}
maskline += maskpitch;
picline += picpitch;
}
return true;
}
//****************************************************************
//
// Function Name: CDIBSurface::Create4BitMask
//
// Description: Parse a 4-bit DIBSurface and create a 1-bit mask
//
// Returns: true if successful
//
//****************************************************************
bool CDIBSurface::Create4BitMask (COLORREF colorref)
{
unsigned char *inmask,*inpic;
unsigned char *maskline,*picline;
int count;
UINT x,y,i;
int red,green,blue;
int maskpitch,picpitch;
int colorindex,value;
RGBQUAD colors[16];
ASSERT (m_DIBData);
ASSERT (m_DIBData->m_Mask);
if(!m_DIBData->m_Mask)
return false;
HDC dc;
dc = GetDC ();
if(GetDIBColorTable (dc,0,16,&(colors[0])) == 0)
{
ReleaseDC (dc);
return false;
}
ReleaseDC (dc);
red = colorref & 0xff;
green = (colorref>>8)&0xff;
blue = (colorref>>16)&0xff;
colorindex = -1;
for(i=0;i<16;i++)
{
if(red != colors[i].rgbRed)
continue;
if(green != colors[i].rgbGreen)
continue;
if(blue != colors[i].rgbBlue)
continue;
colorindex = (int) i;
break;
}
if(colorindex == -1)
return false;
maskline = m_DIBData->m_Mask->GetMem ();
maskpitch = m_DIBData->m_Mask->GetPitch ();
picline = GetMem ();
picpitch = GetPitch ();
for(y=0;y<m_DIBData->m_Height;y++)
{
inmask = maskline;
inpic = picline;
*inmask = 0;
count = 7;
for(x=0;x<m_DIBData->m_Width;x++,count--)
{
if(count < 0)
{
inmask++;
*inmask = 0;
count = 7;
}
if(x&0x01)
value = ((*inpic)) & 0x0f;
else
value = ((*inpic)>>4) & 0x0f;
if(value == colorindex)
{
(*inmask) += (1<<count);
if(x&0x01)
(*inpic) &= 0xf0;
else
(*inpic) &= 0x0f;
}
if(x&0x01)
inpic++;
}
maskline += maskpitch;
picline += picpitch;
}
return true;
}
//****************************************************************
//
// Function Name: CDIBSurface::Create8BitMask
//
// Description: Parse a 8-bit DIBSurface and create a 1-bit mask
//
// Returns: true if successful
//
//****************************************************************
bool CDIBSurface::Create8BitMask (COLORREF colorref)
{
unsigned char *inmask,*inpic;
unsigned char *maskline,*picline;
int count;
UINT x,y,i;
int red,green,blue;
int maskpitch,picpitch;
int colorindex,value;
RGBQUAD colors[256];
ASSERT (m_DIBData);
ASSERT (m_DIBData->m_Mask);
if(!m_DIBData->m_Mask)
return false;
HDC dc;
dc = GetDC ();
if(GetDIBColorTable (dc,0,256,&(colors[0])) == 0)
{
ReleaseDC (dc);
return false;
}
ReleaseDC (dc);
red = colorref & 0xff;
green = (colorref>>8)&0xff;
blue = (colorref>>16)&0xff;
colorindex = -1;
for(i=0;i<256;i++)
{
if(red != colors[i].rgbRed)
continue;
if(green != colors[i].rgbGreen)
continue;
if(blue != colors[i].rgbBlue)
continue;
colorindex = (int) i;
break;
}
if(colorindex == -1)
return false;
maskline = m_DIBData->m_Mask->GetMem ();
maskpitch = m_DIBData->m_Mask->GetPitch ();
picline = GetMem ();
picpitch = GetPitch ();
for(y=0;y<m_DIBData->m_Height;y++)
{
inmask = maskline;
inpic = picline;
*inmask = 0;
count = 7;
for(x=0;x<m_DIBData->m_Width;x++,count--)
{
if(count < 0)
{
inmask++;
*inmask = 0;
count = 7;
}
value = *inpic;
if(value == colorindex)
{
(*inmask) += (1<<count);
(*inpic) = 0;
}
inpic += 1;
}
maskline += maskpitch;
picline += picpitch;
}
return true;
}
//****************************************************************
//
// Function Name: CDIBSurface::Create16BitMask
//
// Description: Parse a 16-bit DIBSurface and create a 1-bit mask
//
// Returns: true if successful
//
//****************************************************************
bool CDIBSurface::Create16BitMask (COLORREF colorref)
{
unsigned char *inmask,*inpic;
unsigned char *maskline,*picline;
int count;
UINT x,y;
int maskpitch,picpitch;
DWORD value,red,green,blue;
DWORD color;
ASSERT (m_DIBData);
ASSERT (m_DIBData->m_Mask);
if(!m_DIBData->m_Mask)
return false;
red = colorref & 0xff;
green = (colorref>>8)&0xff;
blue = (colorref>>16)&0xff;
red >>= 3;
green >>= 3;
blue >>= 3;
color = (red<<10)+(green<<5)+blue;
maskline = m_DIBData->m_Mask->GetMem ();
maskpitch = m_DIBData->m_Mask->GetPitch ();
picline = GetMem ();
picpitch = GetPitch ();
for(y=0;y<m_DIBData->m_Height;y++)
{
inmask = maskline;
inpic = picline;
*inmask = 0;
count = 7;
for(x=0;x<m_DIBData->m_Width;x++,count--)
{
if(count < 0)
{
inmask++;
*inmask = 0;
count = 7;
}
value = (*(inpic+1)<<8) + *(inpic);
if(value == color)
{
(*inmask) += (1<<count);
(*inpic) = 0;
(*(inpic+1)) = 0;
}
inpic += 2;
}
maskline += maskpitch;
picline += picpitch;
}
return true;
}
//****************************************************************
//
// Function Name: CDIBSurface::Create24BitMask
//
// Description: Parse a 24-bit DIBSurface and create a 1-bit mask
//
// Returns: true if successful
//
//****************************************************************
bool CDIBSurface::Create24BitMask (COLORREF colorref)
{
unsigned char *inmask,*inpic;
unsigned char *maskline,*picline;
int count;
UINT x,y;
int maskpitch,picpitch;
COLORREF curcolor;
ASSERT (m_DIBData);
ASSERT (m_DIBData->m_Mask);
if(!m_DIBData->m_Mask)
return false;
maskline = m_DIBData->m_Mask->GetMem ();
maskpitch = m_DIBData->m_Mask->GetPitch ();
picline = GetMem ();
picpitch = GetPitch ();
for(y=0;y<m_DIBData->m_Height;y++)
{
inmask = maskline;
inpic = picline;
*inmask = 0;
count = 7;
for(x=0;x<m_DIBData->m_Width;x++,count--)
{
if(count < 0)
{
inmask++;
*inmask = 0;
count = 7;
}
curcolor = ((*inpic)<<16) + ((*(inpic+1))<<8) + ((*(inpic+2)));
if(curcolor == colorref)
{
(*inmask) += (1<<count);
(*inpic) = 0;
(*(inpic+1)) = 0;
(*(inpic+2)) = 0;
}
inpic += 3;
}
maskline += maskpitch;
picline += picpitch;
}
return true;
}
int CDIBSurface::FloodFill24 (const CPoint& start,const COLORREF color)
{
COLORREF srccolor,intcolor;
FloodData temp (0,0);
std::stack<FloodData> data;
int count=0;
int pitch;
int red,green,blue;
unsigned char *mem;
ASSERT (m_DIBData);
intcolor = color;
srccolor = GetColor (start.x,start.y);
if(srccolor == intcolor)
return 0;
mem = GetMem () + GetLocation (start.x,start.y);
pitch = GetPitch ();
data.push (FloodData (mem,start));
while(!data.empty ())
{
temp = data.top ();
data.pop ();
intcolor = ((*temp.mem)<<16)+ ((*(temp.mem+1))<<8) + (*(temp.mem+2));
if(intcolor==srccolor)
{
red = color&0xff;
green = (color>>8) & 0xff;
blue = (color>>16) & 0xff;
mem = temp.mem;
(*mem) = blue;
mem++;
(*mem) = green;
mem++;
(*mem) = red;
mem++;
count++;
if(temp.where.y != 0)
data.push (FloodData (temp.mem-pitch,CPoint(temp.where.x,temp.where.y-1)));
if(temp.where.y != (m_DIBData->m_Height-1))
data.push (FloodData (temp.mem+pitch,CPoint(temp.where.x,temp.where.y+1)));
if(temp.where.x != 0)
data.push (FloodData (temp.mem-3,CPoint(temp.where.x-1,temp.where.y)));
if(temp.where.x != (m_DIBData->m_Width-1))
data.push (FloodData (temp.mem+3,CPoint(temp.where.x+1,temp.where.y)));
}
}
return count;
}
bool CDIBSurface::AlphaBlt16 (const int x,const int y,const int width,const int height,const CDIBSurface *srcdib,const CDIBSurface *alphadib,const int srcx,const int srcy,const int alphasrcx,const int alphasrcy)
{
float red,green,blue;
float sred,sgreen,sblue;
float dred,dgreen,dblue;
int ired,igreen,iblue;
float avalue;
int cx,cy;
int iaval;
int dpitch,spitch,apitch;
WORD *dest,*dline;
const WORD *src,*sline;
const unsigned char *alpha,*aline;
dline = (WORD *) (GetMem ()+GetLocation (x,y));
sline = (const WORD *) (srcdib->GetMem () + srcdib->GetLocation (srcx,srcy));
aline = (alphadib->GetMem () + alphadib->GetLocation (alphasrcx,alphasrcy));
dpitch = GetPitch ();
dpitch >>= 1;
spitch = srcdib->GetPitch ();
spitch >>=1;
apitch = alphadib->GetPitch ();
for(cy = 0;cy < height;cy++)
{
dest = dline;
src = sline;
alpha = aline;
for(cx = 0;cx < width;cx++)
{
iaval = *alpha;
if(iaval == 0)
{
}
else if(iaval == 255)
{
*dest = *src;
}
else
{
avalue = iaval;
dblue = (*dest)&0x001f;
dgreen = ((*dest)>>5)&0x001f;
dred = ((*dest)>>10)&0x001f;
sblue = (*src)&0x001f;
sgreen = ((*src)>>5)&0x001f;
sred = ((*src)>>10)&0x001f;
avalue /= 255.0;
red = (sred * avalue) + (dred*(1.0-avalue));
green = (sgreen * avalue) + (dgreen*(1.0-avalue));
blue = (sblue * avalue) + (dblue*(1.0-avalue));
ired = red;
igreen = green;
iblue = blue;
*dest = (ired<<10) + (igreen<<5) + iblue;
}
dest++;
src++;
alpha++;
}
dline += dpitch;
sline += spitch;
aline += apitch;
}
return true;
}
bool CDIBSurface::AlphaBlt24 (const int x,const int y,const int width,const int height,const CDIBSurface *srcdib,const CDIBSurface *alphadib,const int srcx,const int srcy,const int alphasrcx,const int alphasrcy)
{
float red,green,blue;
float sred,sgreen,sblue;
float dred,dgreen,dblue;
float avalue;
int cx,cy;
int iaval;
int dpitch,spitch,apitch;
unsigned char *dest,*dline;
const unsigned char *src,*sline;
const unsigned char *alpha,*aline;
dline = GetMem ()+GetLocation (x,y);
sline = srcdib->GetMem () + srcdib->GetLocation (srcx,srcy);
aline = alphadib->GetMem () + alphadib->GetLocation (alphasrcx,alphasrcy);
dpitch = GetPitch ();
spitch = srcdib->GetPitch ();
apitch = alphadib->GetPitch ();
for(cy = 0;cy < height;cy++)
{
dest = dline;
src = sline;
alpha = aline;
for(cx = 0;cx < width;cx++)
{
iaval = *alpha;
if(iaval == 0)
{
}
else if(iaval == 255)
{
*dest = *src;
*(dest+1) = *(src+1);
*(dest+2) = *(src+2);
}
else
{
avalue = iaval;
dblue = *dest;
dgreen = *(dest+1);
dred = *(dest+2);
sblue = *src;
sgreen = *(src+1);
sred = *(src+2);
avalue /= 255.0;
red = (sred * avalue) + (dred*(1.0-avalue));
green = (sgreen * avalue) + (dgreen*(1.0-avalue));
blue = (sblue * avalue) + (dblue*(1.0-avalue));
*dest = blue;
*(dest+1) = green;
*(dest+2) = red;
}
dest += 3;
src += 3;
alpha++;
}
dline += dpitch;
sline += spitch;
aline += apitch;
}
return true;
}
bool CDIBSurface::Convert24to16 (void)
{
ASSERT (m_DIBData);
CDIBSurface surf;
if(GetBitDepth () == 16)
return true;
ASSERT (GetBitDepth () == 24);
if(GetBitDepth () != 24)
return false;
if (!surf.Create (GetWidth (),GetHeight (),16))
return false;
BYTE *pDestMem = surf.GetMem();
ASSERT (pDestMem);
WORD *pDestLine = (WORD *) pDestMem;
BYTE *pSrcMem = GetMem ();
ASSERT (pSrcMem);
BYTE *pSrcLine = pSrcMem;
int SrcPitch = GetPitch ();
int DestPitch = surf.GetPitch ();
DWORD red,green,blue;
DWORD rederror=0,greenerror=0,blueerror=0;
for (int y = 0; y < GetHeight(); ++y)
{
rederror = greenerror = blueerror = 0;
for (int x=0;x<GetWidth ();x++)
{
blue = *pSrcLine;
green = *(pSrcLine+1);
red = *(pSrcLine+2);
pSrcLine += 3;
rederror += (red & 0x07);
greenerror += (green & 0x07);
blueerror += (blue & 0x07);
if (rederror > 8)
{
red += 8;
if (red > 255)
red = 255;
rederror -= 8;
}
if (greenerror > 8)
{
green += 8;
if (green > 255)
green = 255;
greenerror -= 8;
}
if (blueerror > 8)
{
blue += 8;
if (blue > 255)
blue = 255;
blueerror -= 8;
}
red >>= 3;
green >>= 3;
blue >>= 3;
*pDestLine++ = (red << 10) | (green << 5) | (blue);
}
pDestMem += DestPitch;
pSrcMem += SrcPitch;
pDestLine = (WORD *) pDestMem;
pSrcLine = pSrcMem;
}
if(m_DIBData->m_Mask)
{
if(!surf.CalcMask ())
return false;
HDC dc1,dc2;
dc1 = surf.m_DIBData->m_Mask->GetDC ();
dc2 = m_DIBData->m_Mask->GetDC ();
BitBlt (dc1,0,0,m_DIBData->m_Width,m_DIBData->m_Height,dc2,0,0,SRCCOPY);
surf.m_DIBData->m_Mask->ReleaseDC (dc1);
m_DIBData->m_Mask->ReleaseDC (dc2);
}
(*surf.m_RefCount)++;
Destroy ();
memcpy (m_DIBData,surf.m_DIBData,sizeof (DIBData));
delete surf.m_DIBData;
delete surf.m_RefCount;
surf.m_DIBData = NULL;
surf.m_RefCount = NULL;
return true;
}
namespace
{
inline BYTE GetIntensity (COLORREF c)
{
int r = GetRValue (c);
int g = GetGValue (c);
int b = GetBValue (c);
return (299 * r + 587 * g + 114 * b) / 1000;
}
}
bool CDIBSurface::ConvertToGray (void)
{
ASSERT (m_DIBData);
CDIBSurface surf;
if(GetBitDepth () == 8)
return true;
if (!surf.Create (GetWidth (),GetHeight (),8))
return false;
BYTE *pDestMem = surf.GetMem();
ASSERT (pDestMem);
BYTE *pDestLine = pDestMem;
int DestPitch = surf.GetPitch ();
for (int y = 0; y < GetHeight(); ++y)
{
for (int x=0;x<GetWidth ();x++)
{
COLORREF color = GetColor (x, y);
*pDestLine++ = GetIntensity (color);
}
pDestMem += DestPitch;
pDestLine = pDestMem;
}
if(m_DIBData->m_Mask)
{
if(!surf.CalcMask ())
return false;
HDC dc1,dc2;
dc1 = surf.m_DIBData->m_Mask->GetDC ();
dc2 = m_DIBData->m_Mask->GetDC ();
BitBlt (dc1,0,0,m_DIBData->m_Width,m_DIBData->m_Height,dc2,0,0,SRCCOPY);
surf.m_DIBData->m_Mask->ReleaseDC (dc1);
m_DIBData->m_Mask->ReleaseDC (dc2);
}
(*surf.m_RefCount)++;
Destroy ();
memcpy (m_DIBData,surf.m_DIBData,sizeof (DIBData));
delete surf.m_DIBData;
delete surf.m_RefCount;
surf.m_DIBData = NULL;
surf.m_RefCount = NULL;
return true;
}
bool CDIBSurface::ColorBlt16 (const int x,const int y,const int width,const int height,const CDIBSurface* srcdib,const int srcx,const int srcy,const COLORREF color,bool addred,bool addgreen,bool addblue,CDIBSurface *altmask)
{
int red,green,blue;
int reddiff,greendiff,bluediff;
int cx,cy;
int mindex;
CDIBSurface *maskdib = NULL;
int dpitch,spitch,mpitch;
WORD *dest;
unsigned char *dline;
unsigned char *mask,*mline;
const WORD *src;
const unsigned char *sline;
reddiff = (color & 0xff);
greendiff = ((color>>8) & 0xff);
bluediff = ((color>>16) & 0xff);
if(!addred)
reddiff *= -1;
if(!addgreen)
greendiff *= -1;
if(!addblue)
bluediff *= -1;
if(altmask)
maskdib = altmask;
else if (srcdib->UseMask())
maskdib = srcdib->m_DIBData->m_Mask;
dline = GetMem ()+GetLocation (x,y);
sline = srcdib->GetMem () + srcdib->GetLocation (srcx,srcy);
if(maskdib)
{
mline = maskdib->GetMem () + maskdib->GetLocation (srcx,srcy);
mpitch = maskdib->GetPitch ();
}
dpitch = GetPitch ();
spitch = srcdib->GetPitch ();
if(maskdib)
{
#if 1
/* faster version */
int red_map[32];
int green_map[32];
int blue_map[32];
int i;
for (i = 0; i < 32; i += 1) {
red_map[i] = clamp<int> (0,reddiff + i,31);
green_map[i] = clamp<int> (0,greendiff + i,31);
blue_map[i] = clamp<int> (0,bluediff + i,31);
}
for(cy = 0;cy < height;cy++)
{
dest = (WORD *) dline;
src = (WORD *) sline;
mask = mline;
mindex = 7-(srcx & 0x07);
for(cx = 0;cx < width;cx++)
{
if(mindex < 0)
{
mindex = 7;
mask++;
}
if(!((*mask) & (1<<mindex)))
{
blue = blue_map[((*src)&0x001f)];
green = green_map[((*src)>>5)&0x001f];
red = red_map[((*src)>>10)&0x001f];
*dest = (red << 10) | (green << 5) | (blue);
}
mindex--;
dest++;
src++ ;
}
dline += dpitch;
sline += spitch;
mline += mpitch;
}
#else
for(cy = 0;cy < height;cy++)
{
dest = (WORD *) dline;
src = (WORD *) sline;
mask = mline;
mindex = 7-(srcx & 0x07);
for(cx = 0;cx < width;cx++)
{
if(mindex < 0)
{
mindex = 7;
mask++;
}
if(!((*mask) & (1<<mindex)))
{
blue = clamp<int> (0,((*src)&0x001f)+bluediff,31);
green = clamp<int> (0,(((*src)>>5)&0x001f)+greendiff,31);
red = clamp<int> (0,(((*src)>>10)&0x001f)+reddiff,31);
*dest = (red << 10) | (green << 5) | (blue);
}
mindex--;
dest++;
src++ ;
}
dline += dpitch;
sline += spitch;
mline += mpitch;
}
#endif
}
else
{
for(cy = 0;cy < height;cy++)
{
dest = (WORD *) dline;
src = (WORD *) sline;
for(cx = 0;cx < width;cx++)
{
blue = clamp<int> (0,((*src)&0x001f)+bluediff,31);
green = clamp<int> (0,(((*src)>>5)&0x001f)+greendiff,31);
red = clamp<int> (0,(((*src)>>10)&0x001f)+reddiff,31);
*dest = (red << 10) | (green << 5) | (blue);
dest++;
src++;
}
dline += dpitch;
sline += spitch;
}
}
return true;
}
bool CDIBSurface::ColorBlt24 (const int x,const int y,const int width,const int height,const CDIBSurface* srcdib,const int srcx,const int srcy,const COLORREF color,bool addred,bool addgreen,bool addblue,CDIBSurface *altmask)
{
int reddiff,greendiff,bluediff;
int cx,cy;
int mindex;
CDIBSurface *maskdib = NULL;
int dpitch,spitch,mpitch;
unsigned char *dest,*dline;
unsigned char *mask,*mline;
const unsigned char *src,*sline;
reddiff = (color & 0xff);
greendiff = ((color>>8) & 0xff);
bluediff = ((color>>16) & 0xff);
if(!addred)
reddiff *= -1;
if(!addgreen)
greendiff *= -1;
if(!addblue)
bluediff *= -1;
if(altmask)
maskdib = altmask;
else if (srcdib->UseMask())
maskdib = srcdib->m_DIBData->m_Mask;
dline = GetMem ()+GetLocation (x,y);
sline = srcdib->GetMem () + srcdib->GetLocation (srcx,srcy);
if(maskdib)
{
mline = maskdib->GetMem () + maskdib->GetLocation (srcx,srcy);
mpitch = maskdib->GetPitch ();
}
dpitch = GetPitch ();
spitch = srcdib->GetPitch ();
if(maskdib)
{
for(cy = 0;cy < height;cy++)
{
dest = dline;
src = sline;
mask = mline;
mindex = 7-(srcx & 0x07);
for(cx = 0;cx < width;cx++)
{
if(mindex < 0)
{
mindex = 7;
mask++;
}
if(!((*mask) & (1<<mindex)))
{
*dest = clamp<int> (0,(*src)+bluediff,255);
*(dest+1) = clamp<int> (0,(*src+1)+greendiff,255);
*(dest+2) = clamp<int> (0,(*src+2)+reddiff,255);
}
mindex--;
dest += 3;
src += 3;
}
dline += dpitch;
sline += spitch;
mline += mpitch;
}
}
else
{
for(cy = 0;cy < height;cy++)
{
dest = dline;
src = sline;
for(cx = 0;cx < width;cx++)
{
*dest = clamp<int> (0,(*src)+bluediff,255);
*(dest+1) = clamp<int> (0,(*src+1)+greendiff,255);;
*(dest+2) = clamp<int> (0,(*src+2)+reddiff,255);;
dest += 3;
src += 3;
}
dline += dpitch;
sline += spitch;
}
}
return true;
}
bool CDIBSurface::GrayBlt16 (const int x,const int y,const int width,const int height,const CDIBSurface* srcdib,const int srcx,const int srcy,CDIBSurface *altmask)
{
int red,green,blue;
int cx,cy;
int mindex;
CDIBSurface *maskdib = NULL;
int dpitch,spitch,mpitch;
WORD *dest;
unsigned char *dline;
unsigned char *mask,*mline;
const WORD *src;
const unsigned char *sline;
if(altmask)
maskdib = altmask;
else if (srcdib->UseMask())
maskdib = srcdib->m_DIBData->m_Mask;
dline = GetMem ()+GetLocation (x,y);
sline = srcdib->GetMem () + srcdib->GetLocation (srcx,srcy);
if(maskdib)
{
mline = maskdib->GetMem () + maskdib->GetLocation (srcx,srcy);
mpitch = maskdib->GetPitch ();
}
dpitch = GetPitch ();
spitch = srcdib->GetPitch ();
if(maskdib)
{
for(cy = 0;cy < height;cy++)
{
dest = (WORD *) dline;
src = (WORD *) sline;
mask = mline;
mindex = 7-(srcx & 0x07);
for(cx = 0;cx < width;cx++)
{
if(mindex < 0)
{
mindex = 7;
mask++;
}
if(!((*mask) & (1<<mindex)))
{
blue = clamp<int> (0,(((int)(*src)&0x001f) * 86) >> 10,31); // blue
green = clamp<int> (0,((((int)(*src)>>5)&0x001f) * 273) >> 10,31); // green
red = clamp<int> (0,((((int)(*src)>>10)&0x001f) * 156) >> 10,31); // red
*dest = ((red+green+blue) << 10) | ((red+green+blue) << 5) | (red+green+blue);
}
mindex--;
dest++;
src++ ;
}
dline += dpitch;
sline += spitch;
mline += mpitch;
}
}
else
{
#ifdef USE_DITHERING
CFloydSteinberg<CDitherIntensity> dither;
if (!dither.Create (width, height))
{
ASSERT (0);
return false;
}
dither.Begin();
#endif
for(cy = 0;cy < height;cy++)
{
#ifdef USE_DITHERING
dither.BeginScanLine();
#endif
dest = (WORD *) dline;
src = (WORD *) sline;
for(cx = 0;cx < width;cx++)
{
const int brightness = 100;
const int rmult = (428 * brightness / 100);
const int gmult = (1008 * brightness / 100);
const int bmult = (612 * brightness / 100);
red = rmult * (((*src)>>10)&0x001f);
green = gmult * (((*src)>>5)&0x001f);
blue = bmult * ((*src)&0x001f);
int intensity = (red + green + blue) >> 8;
ASSERT (intensity >= 0);
ASSERT (intensity < 256);
#ifdef USE_DITHERING
CDitherIntensity dithintensity (intensity);
dither.Dither (dithintensity);
dithintensity.i &= (0x1f << 3);
dither.Achieved (dithintensity);
intensity = dithintensity.i;
#endif
intensity >>= 3; // convert to 5 bits
*dest = (intensity << 10) | (intensity << 5) | intensity;
dest++;
src++;
}
dline += dpitch;
sline += spitch;
}
#ifdef USE_DITHERING
dither.End();
#endif
}
return true;
}
bool CDIBSurface::GrayBlt24 (const int x,const int y,const int width,const int height,const CDIBSurface* srcdib,const int srcx,const int srcy,CDIBSurface *altmask)
{
int cx,cy;
int mindex;
CDIBSurface *maskdib = NULL;
int red,green,blue,color;
int dpitch,spitch,mpitch;
unsigned char *dest,*dline;
unsigned char *mask,*mline;
const unsigned char *src,*sline;
if(altmask)
maskdib = altmask;
else if (srcdib->UseMask())
maskdib = srcdib->m_DIBData->m_Mask;
dline = GetMem ()+GetLocation (x,y);
sline = srcdib->GetMem () + srcdib->GetLocation (srcx,srcy);
if(maskdib)
{
mline = maskdib->GetMem () + maskdib->GetLocation (srcx,srcy);
mpitch = maskdib->GetPitch ();
}
dpitch = GetPitch ();
spitch = srcdib->GetPitch ();
if(maskdib)
{
for(cy = 0;cy < height;cy++)
{
dest = dline;
src = sline;
mask = mline;
mindex = 7-(srcx & 0x07);
for(cx = 0;cx < width;cx++)
{
if(mindex < 0)
{
mindex = 7;
mask++;
}
if(!((*mask) & (1<<mindex)))
{
blue = clamp<int> (0,(*src) * 64.0/255.0,255); // blue
green = clamp<int> (0,(*src+1) * 204.0/255.0,255); // green
red = clamp<int> (0,(*src+2) * 117.0/255.0,255); // red
color = (red + green + blue) / 3;
*dest = color;
*(dest+1) = color;
*(dest+2) = color;
}
mindex--;
dest += 3;
src += 3;
}
dline += dpitch;
sline += spitch;
mline += mpitch;
}
}
else
{
for(cy = 0;cy < height;cy++)
{
dest = dline;
src = sline;
for(cx = 0;cx < width;cx++)
{
blue = clamp<int> (0,(*src) * 64.0/255.0, 255); // blue
green = clamp<int> (0,(*src+1) * 204.0/255.0,255); // green
red = clamp<int> (0,(*src+2) * 117.0/255.0,255); // red
color = (red + green + blue) / 3;
*dest = color;
*(dest+1) = color;
*(dest+2) = color;
dest += 3;
src += 3;
}
dline += dpitch;
sline += spitch;
}
}
return true;
}
bool CDIBSurface::MultBlt16 (const int x,const int y,const int width,const int height,const CDIBSurface* srcdib,const int srcx,const int srcy,const float red,const float green,const float blue,CDIBSurface *altmask)
{
int dred,dgreen,dblue;
int cx,cy;
int mindex;
CDIBSurface *maskdib = NULL;
int dpitch,spitch,mpitch;
WORD *dest;
unsigned char *dline;
unsigned char *mask,*mline;
const WORD *src;
const unsigned char *sline;
if(altmask)
maskdib = altmask;
else if (srcdib->UseMask())
maskdib = srcdib->m_DIBData->m_Mask;
dline = GetMem ()+GetLocation (x,y);
sline = srcdib->GetMem () + srcdib->GetLocation (srcx,srcy);
if(maskdib)
{
mline = maskdib->GetMem () + maskdib->GetLocation (srcx,srcy);
mpitch = maskdib->GetPitch ();
}
dpitch = GetPitch ();
spitch = srcdib->GetPitch ();
if(maskdib)
{
#if 1
/* faster version */
int red_map[32];
int green_map[32];
int blue_map[32];
int i;
for (i = 0; i < 32; i += 1) {
red_map[i] = clamp<int> (0,red * i,31);
green_map[i] = clamp<int> (0,green * i,31);
blue_map[i] = clamp<int> (0,blue * i,31);
}
for(cy = 0;cy < height;cy++)
{
dest = (WORD *) dline;
src = (WORD *) sline;
mask = mline;
mindex = 7-(srcx & 0x07);
for(cx = 0;cx < width;cx++)
{
if(mindex < 0)
{
mindex = 7;
mask++;
}
if(!((*mask) & (1<<mindex)))
{
dblue = blue_map[((*src)&0x001f)];
dgreen = green_map[((*src)>>5)&0x001f];
dred = red_map[((*src)>>10)&0x001f];
*dest = (dred << 10) | (dgreen << 5) | (dblue);
}
mindex--;
dest++;
src++ ;
}
dline += dpitch;
sline += spitch;
mline += mpitch;
}
#else
for(cy = 0;cy < height;cy++)
{
dest = (WORD *) dline;
src = (WORD *) sline;
mask = mline;
mindex = 7-(srcx & 0x07);
for(cx = 0;cx < width;cx++)
{
if(mindex < 0)
{
mindex = 7;
mask++;
}
if(!((*mask) & (1<<mindex)))
{
dblue = clamp<int> (0,((*src)&0x001f)*blue,31);
dgreen = clamp<int> (0,(((*src)>>5)&0x001f)*green,31);
dred = clamp<int> (0,(((*src)>>10)&0x001f)*red,31);
*dest = (dred << 10) | (dgreen << 5) | (dblue);
}
mindex--;
dest++;
src++ ;
}
dline += dpitch;
sline += spitch;
mline += mpitch;
}
#endif
}
else
{
for(cy = 0;cy < height;cy++)
{
dest = (WORD *) dline;
src = (WORD *) sline;
for(cx = 0;cx < width;cx++)
{
dblue = clamp<int> (0,((*src)&0x001f)*blue,31);
dgreen = clamp<int> (0,(((*src)>>5)&0x001f)*green,31);
dred = clamp<int> (0,(((*src)>>10)&0x001f)*red,31);
*dest = (dred << 10) | (dgreen << 5) | (dblue);
dest++;
src++;
}
dline += dpitch;
sline += spitch;
}
}
return true;
}
bool CDIBSurface::MultBlt24 (const int x,const int y,const int width,const int height,const CDIBSurface* srcdib,const int srcx,const int srcy,const float red,const float green,const float blue,CDIBSurface *altmask)
{
int cx,cy;
int mindex;
CDIBSurface *maskdib = NULL;
int dpitch,spitch,mpitch;
unsigned char *dest,*dline;
unsigned char *mask,*mline;
const unsigned char *src,*sline;
if(altmask)
maskdib = altmask;
else if (srcdib->UseMask())
maskdib = srcdib->m_DIBData->m_Mask;
dline = GetMem ()+GetLocation (x,y);
sline = srcdib->GetMem () + srcdib->GetLocation (srcx,srcy);
if(maskdib)
{
mline = maskdib->GetMem () + maskdib->GetLocation (srcx,srcy);
mpitch = maskdib->GetPitch ();
}
dpitch = GetPitch ();
spitch = srcdib->GetPitch ();
if(maskdib)
{
for(cy = 0;cy < height;cy++)
{
dest = dline;
src = sline;
mask = mline;
mindex = 7-(srcx & 0x07);
for(cx = 0;cx < width;cx++)
{
if(mindex < 0)
{
mindex = 7;
mask++;
}
if(!((*mask) & (1<<mindex)))
{
*dest = clamp<int> (0,(*src)*blue,255);
*(dest+1) = clamp<int> (0,(*src+1)*green,255);
*(dest+2) = clamp<int> (0,(*src+2)*red,255);
}
mindex--;
dest += 3;
src += 3;
}
dline += dpitch;
sline += spitch;
mline += mpitch;
}
}
else
{
for(cy = 0;cy < height;cy++)
{
dest = dline;
src = sline;
for(cx = 0;cx < width;cx++)
{
*dest = clamp<int> (0,(*src)*blue,255);
*(dest+1) = clamp<int> (0,(*src+1)*green,255);;
*(dest+2) = clamp<int> (0,(*src+2)*red,255);;
dest += 3;
src += 3;
}
dline += dpitch;
sline += spitch;
}
}
return true;
}