📄 cpixeldepthchanger.cpp
字号:
// ARM Ltd
// Copyright 1998 All Rights reserved
// David Earlam 22.9.1998
// helper class to change the color-depth (bits per pixel) of uncompresed bitmap image bits while keeping
// the original width and height
// assumes that the first (leftmost) pixel in a row is encoded in the <srcBpp> most significant
// bits of a byte
// limitations: currently can only keep or increase effective color depth 1:1, 1:2, 1:4, not reduce it
#include <afxwin.h>
#include "CPixelDepthChanger.h"
// DR DEBUG
#define LEFT_TO_RIGHT
#define BOTTOM_TO_TOP
IMPLEMENT_SERIAL(CPixelDepthChanger, CObject, 0);
CPixelDepthChanger::CPixelDepthChanger()
{
m_pdstBits = NULL;
m_psrcBits = NULL;
m_srcSize = NULL;
m_lookup = NULL;
m_bDelete_pdstBits=FALSE;
}
CPixelDepthChanger::CPixelDepthChanger( int srcWidth, int srcHeight, int srcBpp, void *psrcBits, CDib& rDstCDib )
{
m_psrcBits = (LPBYTE)psrcBits;
m_srcSize = VolumeFromWidthHeightDepth(srcWidth, srcHeight, srcBpp);
//m_pshadowsrcBits = new BYTE[m_srcSize];
// memcpy (m_pshadowsrcBits, m_psrcBits, m_srcSize); //make a copy of the source to detect what has changed since last update
m_bDelete_pdstBits=FALSE;
DWORD dstSize;
if ((dstSize = rDstCDib.GetSizeImage() )!=0)
{
if (rDstCDib.m_lpImage == NULL)
{
rDstCDib.m_lpImage = new BYTE[dstSize];
m_bDelete_pdstBits=TRUE;
}
m_pdstBits = (LPBYTE) rDstCDib.m_lpImage;
}
CreateLookupTable(srcBpp, rDstCDib.m_lpBMIH->biBitCount);
}
void CPixelDepthChanger::CreateLookupTable(int srcBpp, int dstBpp)
{
int nLookupTableEntries = 256; // 2^ bits in a byte, we'll lookup by byte
m_magnification = dstBpp / srcBpp;
switch (m_magnification)
{
case 1: case 2: case 4: break;
default:
AfxMessageBox("Bit per pixel magnification factors of 1:1, 1:2 and 1:4 only supported");
}
m_lookup = new BYTE[nLookupTableEntries * m_magnification];
LPWORD p_lookup16bits = (LPWORD)m_lookup ;
LPDWORD p_lookup32bits = (LPDWORD)m_lookup ;
LPBYTE p_lookup8bits = (LPBYTE)m_lookup ;
int pixelmask =(1 << srcBpp) -1;
int i=0;
while ( i < nLookupTableEntries)
{
int pixel0,pixel1,pixel2,pixel3;
int bits = i;
int dst_pixel;
// DEBUG
pixelmask =(1 << srcBpp) -1;
pixel3 = bits & pixelmask;
//bits <<= srcBpp;
bits >>= srcBpp;
pixel2 = bits & pixelmask;
bits >>= srcBpp;
pixel1 = bits & pixelmask;
bits >>= srcBpp;
pixel0 = bits & pixelmask;
bits >>= srcBpp;
#ifdef LEFT_TO_RIGHT
dst_pixel = (((((pixel0 << dstBpp) | pixel1) << dstBpp) | pixel2) << dstBpp) | pixel3;
#else
dst_pixel = (((((pixel3 << dstBpp) | pixel2) << dstBpp) | pixel1) << dstBpp) | pixel0;
#endif
switch (m_magnification)
{
case 1:
*p_lookup8bits++ =dst_pixel;
break;
case 2:
*p_lookup16bits++ =dst_pixel;
break;
case 4:
*p_lookup32bits++ =dst_pixel;
}
++i;
}
}
void CPixelDepthChanger::Update(void)
{
if (m_pdstBits == NULL) return;
DWORD nByte = 0;
switch (m_magnification)
{
case 1:
{
LPBYTE p_lookup8bits = (LPBYTE)m_lookup ;
LPBYTE pdstBits8bits = (LPBYTE)m_pdstBits ;
LPBYTE psrcBits8bits = (LPBYTE)m_psrcBits ;
#ifndef BOTTOM_TO_TOP
int count = m_dwBytes;
psrcBits8bits += m_srcSize - m_dwBytes;
#endif
BYTE index;
while (nByte < m_srcSize)
{
index = *psrcBits8bits++;
//byte_lookup = p_lookup8bits[index];
//pdstBits8bits[nByte] = byte_lookup; //why use the lookup, we could just copy?
pdstBits8bits[nByte] = index;
#ifndef BOTTOM_TO_TOP
if (--count == 0) {
count = m_dwBytes;
psrcBits8bits -= 2*m_dwBytes;
}
#endif
++nByte;
}
break;
}
case 2:
{
LPWORD p_lookup16bits = (LPWORD)m_lookup ;
LPWORD pdstBits16bits = (LPWORD)m_pdstBits ;
LPBYTE psrcBits8bits = (LPBYTE)m_psrcBits ;
#ifndef BOTTOM_TO_TOP
int count = m_dwBytes;
psrcBits8bits += m_srcSize - m_dwBytes;
#endif
while (nByte < m_srcSize)
{
// char buf[30]; sprintf(buf,"%d %d",nByte,psrcBits8bits-m_psrcBits); AfxMessageBox(buf);
pdstBits16bits[nByte] = p_lookup16bits[*psrcBits8bits++];
#ifndef BOTTOM_TO_TOP
if (--count == 0) {
count = m_dwBytes;
psrcBits8bits -= 2*m_dwBytes;
}
#endif
++nByte;
}
break;
}
case 4:
{
LPDWORD p_lookup32bits = (LPDWORD)m_lookup ;
LPDWORD pdstBits32bits = (LPDWORD)m_pdstBits ;
while (nByte < m_srcSize)
{
pdstBits32bits[nByte] = p_lookup32bits[m_psrcBits[nByte]];
++nByte;
}
break;
}
}
}
CPixelDepthChanger::~CPixelDepthChanger()
{
if (m_lookup !=NULL)
{
delete[] m_lookup;
}
if (m_bDelete_pdstBits)
{
delete[] m_pdstBits;
}
delete[] m_pshadowsrcBits;
}
DWORD CPixelDepthChanger::VolumeFromWidthHeightDepth(int srcWidth, int srcHeight, int srcBpp)
{
/* DR modified - this is dodgy! */
m_srcWidth = srcWidth;
m_srcHeight = srcHeight;
m_srcBpp = srcBpp;
m_dwBytes = ((DWORD) srcWidth * srcBpp) / 32;
if(((DWORD) srcWidth * srcBpp) % 32) {
m_dwBytes++;
}
m_dwBytes *= 4; //rows are multiples of four bytes
return m_dwBytes * srcHeight; // no compression
}
#if 0
CRect CPixelDepthChanger::GetInvalidRect()
{
//compare shadow buffer with src buffer bits starting top left
// stop at the left most upper most byte that is different
// then compore staring bottom right
// returns the larget rectangle containing differences
// once the shadow buffer has been updated with those differences
CRect rectBounding;
rectBounding.SetRectEmpty();
return rectBounding;
//test memset ( m_pshadowsrcBits + 4* m_srcWidth '0', m_srcWidth); //make some lines black (actually srcbits will have been changed by other process)
// for very large unchanging screen this might return faster; slower refreshTimer interval is probably more sensible
//if (memcmp(m_psrcBits, m_pshadowsrcBits,m_srcSize)==0)
//{
// return rectBounding;
//}
DWORD nByte =0;
while (nByte < m_srcSize && m_psrcBits[nByte] == m_pshadowsrcBits[nByte])
{
++nByte;
}
if (nByte == m_srcSize)
{
return rectBounding;
}
DWORD leftmost = nByte;
CPoint pttopleft(nByte * m_srcBpp % m_srcWidth, (nByte * m_srcBpp / m_srcWidth));
nByte = m_srcSize-1;
while (nByte > 0 && m_psrcBits[nByte] == m_pshadowsrcBits[nByte])
{
--nByte;
}
DWORD rightmost = nByte;
CPoint ptbottomright(nByte * m_srcBpp % m_srcWidth, (nByte * m_srcBpp / m_srcWidth) + m_srcBpp);
rectBounding = CRect( pttopleft.x, pttopleft.y, ptbottomright.x, ptbottomright.y );
//test rectBounding= CRect (0,0,m_srcWidth/2, m_srcHeight/2) ; //will flash top left quarter of window any size if logical/device coords correct
memcpy (&m_pshadowsrcBits[leftmost] ,&m_psrcBits[leftmost], rightmost - leftmost +1 ); //validate the shadow buffer
return rectBounding;
}
#endif
CSize CPixelDepthChanger::GetSrcSize()
{
return CSize(m_srcWidth, m_srcHeight);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -