NB6_Hazards/GDE_3_hazard/Graphics/Dib.cpp
gaeltp3 7a52e186d9 Verbindung von GDE mit unserem Projekt Hazard
im Ordner GDE_3_Hazard. Ab nun koennen wir weiter in diesem Ordner
programmieren.
2013-11-28 16:08:16 +01:00

331 lines
9 KiB
C++

// Dib.cpp: implementation of the CDib class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Dib.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
CDib::CDib() throw()
{
m_pBmpFileHeader = NULL;
m_pBmpInfo = NULL;
m_pBmpInfoHeader = NULL;
m_pRGBTable = NULL;
m_pDibBits = NULL;
m_uiNumColors = 0;
}
CDib::~CDib()
{
Clear();
}
BOOL CDib::DibLoaded() const throw()
{
return (m_pBmpInfoHeader!=NULL);
}
CSize CDib::GetDimensions() const throw()
{
if (!DibLoaded()) return CSize(0,0);
return CSize((int)m_pBmpInfoHeader->biWidth,(int)m_pBmpInfoHeader->biHeight);
}
void CDib::Clear() throw()
{
if(m_pBmpFileHeader != NULL) {
delete[] m_pBmpFileHeader;
m_pBmpFileHeader = NULL;
}
if(m_pBmpInfo != NULL) {
delete[] m_pBmpInfo;
m_pBmpInfo = NULL;
}
if(m_pDibBits != NULL) {
delete[] m_pDibBits;
m_pDibBits = NULL;
}
}
void CDib::Load(CString fileName) throw(CImageException)
{
CFile file(fileName, CFile::modeRead | CFile::shareDenyNone);
Load(&file);
}
void CDib::Load(CFile* pFile) throw(CImageException)
{
Clear();
m_pBmpFileHeader = new BITMAPFILEHEADER;
pFile->Read(static_cast<void*>(m_pBmpFileHeader), sizeof(BITMAPFILEHEADER));
if(m_pBmpFileHeader->bfType != 0x4d42) {
Clear();
pFile->Close();
throw CImageException(_T("Failed to load document"));
} else {
DWORD dwLength;
dwLength = m_pBmpFileHeader->bfOffBits - sizeof(BITMAPFILEHEADER);
m_pBmpInfo = reinterpret_cast<LPBITMAPINFO>(new BYTE[dwLength]);
pFile->Read(static_cast<void*>(m_pBmpInfo), dwLength);
m_pBmpInfoHeader = reinterpret_cast<LPBITMAPINFOHEADER>(m_pBmpInfo);
if((m_pBmpInfoHeader->biClrUsed == 0))
m_uiNumColors = 1 << m_pBmpInfoHeader->biBitCount;
else
m_uiNumColors = m_pBmpInfoHeader->biClrUsed;
if(m_pBmpInfoHeader->biClrUsed == 0)
m_pBmpInfoHeader->biClrUsed = m_uiNumColors;
if(m_uiNumColors <= 256)
m_pRGBTable = reinterpret_cast<RGBQUAD*>(reinterpret_cast<BYTE*>(m_pBmpInfo) + m_pBmpInfoHeader->biSize);
unsigned int dwDibLength = (unsigned int)pFile->GetLength() - m_pBmpFileHeader->bfOffBits / 4;
m_pDibBits = new BYTE[dwDibLength];
pFile->Read(static_cast<void*>(m_pDibBits), dwDibLength);
}
}
void CDib::Create(CBitmap* pBitmap) throw(CImageException)
{
BITMAP Bitmap;
int rc = pBitmap->GetBitmap(&Bitmap);
if(rc == 0)
throw CImageException(_T("Can't get BITMAP from CBitmap*"));
int iWidthBytes = ((Bitmap.bmWidth * Bitmap.bmBitsPixel + 15) & ~15) >> 3 ;
DWORD dwImgSize = iWidthBytes * Bitmap.bmHeight;
// File header
m_pBmpFileHeader = new BITMAPFILEHEADER;
m_pBmpFileHeader->bfType = 0x4d42;
m_pBmpFileHeader->bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO) + dwImgSize;
m_pBmpFileHeader->bfReserved1 = 0;
m_pBmpFileHeader->bfReserved2 = 0;
m_pBmpFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO) + sizeof(RGBQUAD);
// Bitmap Info header - no support for palette mode
m_pBmpInfo = new BITMAPINFO;
m_pBmpInfoHeader = reinterpret_cast<LPBITMAPINFOHEADER>(m_pBmpInfo);
::ZeroMemory(m_pBmpInfoHeader, sizeof(BITMAPINFOHEADER));
m_pBmpInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
m_pBmpInfoHeader->biWidth = Bitmap.bmWidth;
m_pBmpInfoHeader->biHeight = Bitmap.bmHeight;
m_pBmpInfoHeader->biPlanes = 1;
m_pBmpInfoHeader->biBitCount = Bitmap.bmPlanes * Bitmap.bmBitsPixel;
m_pBmpInfoHeader->biSizeImage = dwImgSize;
// Color Table
if((m_pBmpInfoHeader->biClrUsed == 0))
m_uiNumColors = 1 << (m_pBmpInfoHeader->biBitCount-1);
else
m_uiNumColors = m_pBmpInfoHeader->biClrUsed;
if(m_pBmpInfoHeader->biClrUsed == 0)
m_pBmpInfoHeader->biClrUsed = m_uiNumColors;
if(m_uiNumColors <= 256) {
Clear();
throw CImageException("Palette mode is not supported");
}
// Data bits
m_pDibBits = new BYTE[dwImgSize];
pBitmap->GetBitmapBits(dwImgSize, m_pDibBits);
LPBYTE pTemp = new BYTE[iWidthBytes];
for(int i=0; i<Bitmap.bmHeight/2; i++) {
::memcpy(pTemp, m_pDibBits+i*iWidthBytes, iWidthBytes);
::memcpy(m_pDibBits+i*iWidthBytes, m_pDibBits+iWidthBytes*(Bitmap.bmHeight-1-i), iWidthBytes);
::memcpy(m_pDibBits+iWidthBytes*(Bitmap.bmHeight-1-i), pTemp, iWidthBytes);
}
delete[] pTemp;
}
void CDib::Create(int width, int height, LPBYTE pData, int bitCount) throw(CImageException)
{
ASSERT(pData);
ASSERT(bitCount > 8);
Clear();
int iWidthBytes = ((width * bitCount + 15) & ~15) >> 3 ;
DWORD dwImgSize = iWidthBytes * height;
// File header
m_pBmpFileHeader = new BITMAPFILEHEADER;
m_pBmpFileHeader->bfType = 0x4d42;
m_pBmpFileHeader->bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO) + dwImgSize;
m_pBmpFileHeader->bfReserved1 = 0;
m_pBmpFileHeader->bfReserved2 = 0;
m_pBmpFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO) + sizeof(RGBQUAD);
// Bitmap Info header - no support for palette mode
m_pBmpInfo = new BITMAPINFO;
m_pBmpInfoHeader = reinterpret_cast<LPBITMAPINFOHEADER>(m_pBmpInfo);
::ZeroMemory(m_pBmpInfoHeader, sizeof(BITMAPINFOHEADER));
m_pBmpInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
m_pBmpInfoHeader->biWidth = width;
m_pBmpInfoHeader->biHeight = height;
m_pBmpInfoHeader->biPlanes = 1;
m_pBmpInfoHeader->biBitCount = bitCount;
m_pBmpInfoHeader->biSizeImage = dwImgSize;
// Color Table
if((m_pBmpInfoHeader->biClrUsed == 0))
m_uiNumColors = 1 << m_pBmpInfoHeader->biBitCount;
else
m_uiNumColors = m_pBmpInfoHeader->biClrUsed;
if(m_pBmpInfoHeader->biClrUsed == 0)
m_pBmpInfoHeader->biClrUsed = m_uiNumColors;
if(m_uiNumColors <= 256) {
Clear();
throw CImageException("Palette mode is not supported");
}
// data bits
m_pDibBits = pData;
}
void CDib::Save(CString fileName) throw(CImageException)
{
CFile file;
if(file.Open(fileName, CFile::modeWrite | CFile::modeCreate) == 0)
throw CImageException(_T("Cannot open a file"));
Save(&file);
}
void CDib::Save(CFile* pFile) throw(CImageException)
{
pFile->Write(static_cast<void*>(m_pBmpFileHeader), sizeof(BITMAPFILEHEADER));
DWORD dwLength;
if(m_uiNumColors <= 256)
dwLength = sizeof(BITMAPINFOHEADER) + m_uiNumColors*sizeof(RGBQUAD);
else
dwLength = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD);
pFile->Write(static_cast<void*>(m_pBmpInfo), dwLength);
DWORD dwImgSize = (((GetWidth() * m_pBmpInfoHeader->biBitCount + 15) & ~15) >> 3) * GetHeight() ;
pFile->Write(static_cast<void*>(m_pDibBits), dwImgSize);
}
void CDib::Draw(CDC* pdc, int x, int y, double scale, DWORD dwROPCode) const throw(CImageException) {
if (!this->DibLoaded() ) return;
if(!m_pBmpInfo)
throw CImageException();
int nScanLines = ::StretchDIBits(pdc->GetSafeHdc(), x, y, (int)(GetWidth()*scale) , (int)(GetHeight()*scale), 0, 0, GetWidth(), GetHeight(),
m_pDibBits, m_pBmpInfo, DIB_RGB_COLORS, dwROPCode);
if(nScanLines == GDI_ERROR)
throw CImageException(_T("CDib::Draw exception"));
}
void CDib::Draw(CDC* pdc, int x, int y, int width, int height, DWORD dwROPCode) const throw(CImageException) {
if(!m_pBmpInfo)
throw CImageException();
int nScanLines = ::StretchDIBits(pdc->GetSafeHdc(), x, y, width , height, 0, 0, GetWidth(), GetHeight(),
m_pDibBits, m_pBmpInfo, DIB_RGB_COLORS, dwROPCode);
if(nScanLines == GDI_ERROR)
throw CImageException(_T("CDib::Draw exception"));
}
COLORREF CDib::GetPixel(int x, int y) const throw() {
int width = GetWidth();
int height = GetHeight();
BYTE* pDibBits = m_pDibBits;
BYTE Red;
BYTE Green;
BYTE Blue;
int offset;
SHORT* psDibBits; // for 16 bit
BYTE Index;
RGBQUAD* prgb;
int bpp = GetBPP();
switch(bpp) {
case 1:
case 2:
case 4:
case 8:
offset = width * (height - 1 - y) + x + 1;
pDibBits += offset;
Index = *pDibBits;
prgb = m_pRGBTable + Index;
Red = prgb->rgbRed;
Green = prgb->rgbGreen;
Blue = prgb->rgbBlue;
break;
case 16: // assuming 565
offset = width * 2 * (height - 1 - y) + (x + 1) * 2;
pDibBits += offset;
psDibBits = (SHORT*)pDibBits;
Blue = *psDibBits >> 11;
Green = (*psDibBits >> 5) & 63;
Red = *psDibBits & 127;
break;
case 24:
offset = width * 3 * (height -1 - y) + (x + 1) * 3;
pDibBits += offset;
Blue = *pDibBits;
++pDibBits;
Green = *pDibBits;
++pDibBits;
Red = *pDibBits;
break;
case 32:
offset = width * 4 * (height -1 - y) + (x + 1) * 4;
pDibBits += offset;
Blue = *pDibBits;
++pDibBits;
Green = *pDibBits;
++pDibBits;
Red = *pDibBits;
break;
default:
break;
}
return RGB(Red, Green, Blue);
}
void CDib::SetPixel(int x, int y, COLORREF col) throw() {
int width = GetWidth();
int height = GetHeight();
BYTE* pDibBits = m_pDibBits;
int offset;
int bpp = GetBPP();
switch(bpp) {
case 1:
case 2:
case 4:
case 8:
case 16:
break; // no support for these modes... yet.
case 24:
offset = width * 3 * (height -1 - y) + (x + 1) * 3;
pDibBits += offset;
*pDibBits = GetBValue(col);
++pDibBits;
*pDibBits = GetGValue(col);
++pDibBits;
*pDibBits = GetRValue(col);
break;
case 32:
offset = width * 4 * (height -1 - y) + (x + 1) * 4;
pDibBits += offset;
*pDibBits = GetBValue(col);
++pDibBits;
*pDibBits = GetGValue(col);
++pDibBits;
*pDibBits = GetRValue(col);
break;
default:
break;
}
}