📄 image.cpp
字号:
#include "stdafx.h"
#include "math.h"
#include "image.h"
#include "globalfunc.h"
#include <math.h> // for sqrt()
#include <windowsx.h> // for GlobalAllocPtr
#define MAXIMAGESIZE (3 * 65536) //
const int CImage::GREY=256;
IMPLEMENT_SERIAL(CImage, CObject, 0)
///////////////////////////////////////////////////////////////////
CImage::CImage(): m_bIsDIB(TRUE),m_dwLength(0L),
m_pDib (NULL),m_pData(NULL)
{
m_pPal =new CPalette;
}
///////////////////////////////////////////////////////////////////
CImage::CImage(const CImage& img)//copy constructor
{
m_bIsDIB=img.m_bIsDIB;
m_dwLength=img.m_dwLength;
m_pDib=0;
if(img.m_pDib){
m_pDib=(BYTE*) GlobalAllocPtr(GHND, m_dwLength);
if(!m_pDib)
{
AfxMessageBox("Unable to allocate DIB memory");
return;
}
memcpy(m_pDib,img.m_pDib,m_dwLength);
m_pData = (BYTE*) m_pDib + sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * img.NumColors();
}
m_pPal=new CPalette;
CreateDIBPalette();
}
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////
/*the constructor used to create a DIB of size 'size'
with no initializing image data*/
CImage::CImage(CSize size,int NumColor,int Bits)
{
LPBITMAPINFOHEADER pBMIH;
m_dwLength = sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * NumColor;
if (!AllocateMemory()) return;
DWORD dwBytes = Transform((WORD)size.cx);
m_dwLength += dwBytes * size.cy * Bits / 8;
if (!AllocateMemory(TRUE)){
return;
}
pBMIH=BMInfoHdPtr();
pBMIH->biSize = sizeof(BITMAPINFOHEADER);
pBMIH->biWidth = size.cx;
pBMIH->biHeight = size.cy;
pBMIH->biSizeImage = size.cx*size.cy;
pBMIH->biPlanes = 1;
pBMIH->biBitCount = Bits; // 1, 4, 8, or 24
pBMIH->biCompression = BI_RGB;
pBMIH->biXPelsPerMeter = 0;
pBMIH->biYPelsPerMeter = 0;
pBMIH->biClrUsed = 0;
pBMIH->biClrImportant = 0;
m_pData = (BYTE*)(m_pDib + sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * NumColor);
SetDIB();
m_pPal=new CPalette;
CreateGreyPalette();
}
///////////////////////////////////////////////////////////////////
//part copy constructor
CImage& CImage::operator=(const CImage& img)
{
m_bIsDIB=img.m_bIsDIB;
m_dwLength=img.m_dwLength;
if(img.m_pDib){
TRY {
if(m_pDib){
m_pDib = (BYTE*) GlobalReAllocPtr(m_pDib,
m_dwLength, GHND);
}else
{
m_pDib=(BYTE*) GlobalAllocPtr(GHND, m_dwLength);
}
}
CATCH (CMemoryException, e) {
AfxMessageBox("Unable to allocate DIB memory");
return *this;
}
END_CATCH
memcpy(m_pDib,img.m_pDib,m_dwLength);
m_pData = (BYTE*)((BYTE*) m_pDib + sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * img.NumColors());
}else
{
GlobalFree(m_pDib);
m_pDib=0;
}
if(m_pPal) delete m_pPal;
m_pPal=new CPalette;
CreateDIBPalette();
return *this;
}
///////////////////////////////////////////////////////////////////
CImage::CImage(CDC* pDC, int nBt, BOOL bCompr):m_bIsDIB(TRUE)
/* pDC is memory DC ptr and Cbitmap object has been selected into it
nBt is color bits per pixel (default = 0)
bCompr is compression (default = TRUE)
*/
{
// constructs a DIB from the contents of a bitmap
BITMAP bm;
int nPaletteSize,wBits;
LPBITMAPINFOHEADER pBMIH;
LPBITMAPINFO pBMI;
CBitmap* pEmptyBitmap = new CBitmap;
pEmptyBitmap->CreateCompatibleBitmap(pDC, 0, 0);
CBitmap* pBitmap = (CBitmap*) (pDC->SelectObject(pEmptyBitmap));
pBitmap->GetObject(sizeof(bm), &bm);
if ((nBt == 1) || (nBt == 4) || (nBt == 8) || (nBt == 24)) {
wBits = nBt;
}
else { // nBt = 0
wBits = bm.bmPlanes * bm.bmBitsPixel; // color bits per pixel
}
if (wBits == 1) {
nPaletteSize = 2;
}
else {
if (wBits == 4) {
nPaletteSize = 16;
}
else {
if (wBits == 8) {
nPaletteSize = 256;
}
else {
nPaletteSize = 0; // no palette for 24-bit display
}
}
}
// fills out row to 4-byte boundary
DWORD dwBytes = ((DWORD) bm.bmWidth * wBits) / 32;
if (((DWORD) bm.bmWidth * wBits) % 32) {
dwBytes ++;
}
dwBytes *= 4;//pixels per line
m_dwLength = sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * nPaletteSize;
if (!AllocateMemory()) return;
pBMIH=BMInfoHdPtr();
pBMIH->biSize = sizeof(BITMAPINFOHEADER);
pBMIH->biWidth = bm.bmWidth;
pBMIH->biHeight = bm.bmHeight;
pBMIH->biPlanes = 1;
pBMIH->biBitCount = wBits; // 1, 4, 8, or 24
if (bCompr && (wBits == 4)) {
pBMIH->biCompression = BI_RLE4;
}
else {
if (bCompr && (wBits == 8)) {
pBMIH->biCompression = BI_RLE8;
}
else {
pBMIH->biCompression = BI_RGB;
}
}
pBMIH->biSizeImage = 0;
pBMIH->biXPelsPerMeter = 0;
pBMIH->biYPelsPerMeter = 0;
pBMIH->biClrUsed = 0;
pBMIH->biClrImportant = 0;
// calls GetDIBits with null data pointer to get size of DIB
pBMI=BMInfoPtr();
::GetDIBits(pDC->GetSafeHdc(), (HBITMAP) pBitmap->GetSafeHandle(),
0, (WORD) bm.bmHeight, NULL, pBMI, DIB_RGB_COLORS);
if (pBMIH->biSizeImage == 0) {//pBMIH????orpBMI
m_dwLength += dwBytes * bm.bmHeight;
pBMIH->biCompression = BI_RGB;
// escape route for device drivers that don't do compression
TRACE("Can't do compression\n");
}
else {
m_dwLength += pBMIH->biSizeImage;
}
if (!AllocateMemory(TRUE)) {
return;
}
pBMIH=BMInfoHdPtr();
pBMI=BMInfoPtr();
m_pData = (BYTE*) pBMIH + sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * nPaletteSize;
// second GetDIBits call to make DIB
if (!::GetDIBits(pDC->GetSafeHdc(), (HBITMAP)
pBitmap->GetSafeHandle(), 0, (WORD) bm.bmHeight, m_pData,
pBMI, DIB_RGB_COLORS)) {
m_dwLength = 0L;
}
delete pDC->SelectObject(pBitmap); // delete pEmptyBitmap
Dib();
m_pPal=new CPalette;
CreateDIBPalette();
}
///////////////////////////////////////////////////////////////////
CImage::CImage(CImage& img, float scale)
{
WORD scrw,scrh,destw,desth;
DWORD dwDIBHeadLength;
img.Data();
m_bIsDIB = img.m_bIsDIB;
scrw = img.Width();
scrh = img.Height();
destw = (WORD) (scrw * scale);
desth = (WORD) (scrh * scale);
dwDIBHeadLength = sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * img.NumColors();
DWORD dwBytes = Transform(destw);
m_dwLength = dwDIBHeadLength + (DWORD) dwBytes * desth;
m_pDib = NULL;
if(img.m_pDib)
{
m_pDib=(BYTE*) GlobalAllocPtr(GHND, m_dwLength);
if(!m_pDib){
AfxMessageBox("Unable to allocate DIB memory");
return;
}
memcpy(m_pDib, img.m_pDib, dwDIBHeadLength);
m_pData = (BYTE*) m_pDib + sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * img.NumColors();
}
//shrink the image
ResizeImage(img.m_pData, scrw, scrh, m_pData, destw, desth);
LPBITMAPINFOHEADER pBMIH;
pBMIH=BMInfoHdPtr();
pBMIH->biWidth = destw;
pBMIH->biHeight = desth;
Dib(); img.Dib();
m_pPal=new CPalette; CreateDIBPalette();
}
///////////////////////////////////////////////////////////////////
//before usere call this construction,
//must guarentee img.Bits() == 8
///////////////////////////////////////////////////////////////////
CImage::~CImage()
{
if(m_dwLength != 0L)
GlobalFreePtr(m_pDib); // free the DIB memory
if(m_pPal)
delete m_pPal;
}
///////////////////////////////////////////////////////////////////
void CImage::Serialize(CArchive& ar)
{
ar.Flush();
if (ar.IsStoring())
{
WriteToFile(ar.GetFile());
}
else
{
ReadFromFile(ar.GetFile());
}
}
///////////////////////////////////////////////////////////////////
BOOL CImage::WriteAsBMP(CFile* pFile)
{
Dib();
BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
LPBITMAPINFOHEADER pBMIH=BMInfoHdPtr(); // Pointer to DIB info structure
if (m_pDib == NULL)
return FALSE;
/* Fill in file type (first 2 bytes must be "BM" for a bitmap) */
bmfHdr.bfType = 0x4d42; // "BM"
// Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER)
bmfHdr.bfSize = m_dwLength + sizeof(BITMAPFILEHEADER);
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + pBMIH->biSize
+ NumColors()*sizeof(RGBQUAD);
WORD hdLength=sizeof(BITMAPINFOHEADER)
+ NumColors()*sizeof(RGBQUAD);
TRY {
// Write the file header
pFile->Write((BYTE*)&bmfHdr, sizeof(BITMAPFILEHEADER));
// Write the DIB header
pFile->Write(m_pDib, hdLength);
// Write the DIB bits
pFile->Write(m_pData, m_dwLength-hdLength);
}
CATCH (CFileException, e) {
AfxMessageBox("Write error--possible disk full condition");
return FALSE;
}
END_CATCH
return TRUE;
}
///////////////////////////////////////////////////////////////////
/* The MakeBitmap()
CDC* pDoc : Device Context
bmSize : Change the parameter and return it
Function: Replaces the DC's old existing bitmap
with the new one construced from this DIB
Return Value: the old bitmap in DC
*/
////////////////////////////////////////////////////////
CBitmap* CImage::MakeBitmap(CDC* pDC, CSize& bmSize)
{
BITMAP bm;
DWORD dwFore, dwBack;
LPBITMAPINFOHEADER pBMIH = BMInfoHdPtr();
LPBITMAPINFO pBMI = BMInfoPtr();
// checks to see whether DIB buffer is properly loaded
if (m_dwLength == 0L) {
bmSize.cx = bmSize.cy = 0;
return NULL;
}
// this code conditions the DC for mono or color
SetPalette(pDC);
int nPlanes = pDC->GetDeviceCaps(PLANES);
int nBitsPixel = pDC->GetDeviceCaps(BITSPIXEL);
CBitmap* pConfigBitmap = new CBitmap;
char bits[100];
if (pBMIH->biBitCount == 1) {
pConfigBitmap->CreateBitmap(1, 1, 1, 1, bits);
}
else {
pConfigBitmap->CreateBitmap(1, 1, nPlanes, nBitsPixel, bits);
}
CBitmap* pOriginalBitmap =
(CBitmap*) pDC->SelectObject(pConfigBitmap);
// CreateDIBitmap "switches bits" for mono bitmaps, depending on colors,
// so we'll fool it
if (GetMonoColors(dwFore, dwBack)) {
SetMonoColors(0L, 0xFFFFFFL);
}
//the following CreateDIBitmap() creates a DDB from this DIB
//#ifdef _WIN32
HBITMAP hBitmap = ::CreateDIBitmap(pDC->GetSafeHdc(), pBMIH,
CBM_INIT, (CONST BYTE*) m_pData, pBMI, DIB_RGB_COLORS);
//#else
// HBITMAP hBitmap = ::CreateDIBitmap(pDC->GetSafeHdc(), pBMIH,
// CBM_INIT, (BYTE*) m_pData, pBMI, DIB_RGB_COLORS);
//#endif
if (hBitmap == NULL) {
TRACE("null bitmap\n");
delete pDC->SelectObject(pOriginalBitmap); // delete config bitmap
return NULL; // untested error logic
}
SetMonoColors(dwFore, dwBack);
// Can't use CBitmap::FromHandle here because we need to
// delete the object later
CBitmap* pBitmap = new CBitmap;
pBitmap->Attach(hBitmap);
pBitmap->GetObject(sizeof(bm), &bm);
bmSize.cx = bm.bmWidth;
bmSize.cy = bm.bmHeight;
delete pDC->SelectObject(pBitmap); // delete configuration bitmap
return pOriginalBitmap;
}
///////////////////////////////////////////////////////////////////
//create a DIBpalette according to the palette info in the inforhead of object
BOOL CImage::CreateDIBPalette()
{
LPLOGPALETTE lpPal; // pointer to a logical palette
LPBITMAPINFO pBMI = BMInfoPtr();
int i; // loop index
WORD wNumColors; // number of colors in color table
BOOL bResult=FALSE;
/* if handle to DIB is invalid, return FALSE */
if (!m_pDib) return FALSE;
/* get the number of colors in the DIB */
Dib();
wNumColors = NumColors();
if (wNumColors != 0)
{
/* allocate memory block for logical palette */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -