📄 image.cpp
字号:
/***************************************************************/
/*文件名: image.cpp */
/*文件描述: */
/*相关文件: global.h, global.cpp, image.h */
/*主要函数: */
/*提交日期: 作 者:刘岩、山世光 */
/*编 辑 器: Visual C++ */
/*版权:哈尔滨工业大学智能接口实验室 中科院计算所数字媒体实验室*/
/*版权说明:任何使用必须保留版权信息和历史纪录信息 */
/*修改纪录: */
/*日 期 版本 修改人 修改内容 */
/*03/22/1999 2.0 山世光 --------- */
/*05/22/2000 3.0 山世光 --------- */
/***************************************************************/
#include "stdafx.h"
#include "math.h"
#include "ijl.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);
m_pDib = new BYTE[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();
}
///////////////////////////////////////////////////////////////////
CImage::CImage(CImage& img, CPoint start, CSize size)
{
int bpp;
int bytepp;
long hdlen;/*size of the DIB header info*/
LPBITMAPINFOHEADER pBMIH;
ASSERT(img.m_pDib);
WORD dww=img.Width();
WORD dwh=img.Height();
if(( (size.cx+start.x)>dww )||( (size.cy+start.y)>dwh )){
AfxMessageBox("Image size is too large!");
return;
}
img.Data();
m_bIsDIB = FALSE;
hdlen = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * img.NumColors();
bpp = img.Bits();
bytepp = bpp / 8;
ASSERT(bpp != 16 && bpp != 32);
DWORD bypeinoneline = ByteNumForOneLine((WORD)size.cx, bpp);//Bytes per line
m_dwLength = hdlen + bypeinoneline * size.cy;
if (!AllocateMemory( )){
return;
}
memcpy(m_pDib, img.m_pDib, hdlen);
pBMIH = BMInfoHdPtr();
pBMIH->biWidth = size.cx;
pBMIH->biHeight = size.cy;
pBMIH->biSizeImage = size.cx * size.cy * bytepp;
m_pData = (BYTE*)(m_pDib + hdlen);
BYTE* p1, *p2;
long t1, t2;
t1 = dww * bytepp;
t2 = size.cx * bytepp;
p1 = ( BYTE* ) ( img.m_pData + (start.y * dww + start.x) * bytepp);
p2 = m_pData;
for(int i=0 ; i<(int)size.cy; i++)
{
memcpy(p2 , p1 , t2);
p1 += t1;
p2 += t2;
}
Dib();
img.Dib();
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);*/
delete []m_pDib;
m_pDib = new BYTE[m_dwLength];
}else
{
//m_pDib=(BYTE*) GlobalAllocPtr(GHND, m_dwLength);
m_pDib = new BYTE[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);
m_pDib = new BYTE[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(CImage & img, CSize newSize)
{
int bpp, byteperline;
WORD scrw, scrh, destw, desth;
DWORD dwDIBHeadLength;
img.Data();
m_bIsDIB = img.m_bIsDIB;
bpp = img.Bits();
if(bpp != 8)
return;
destw = (WORD) newSize.cx;
desth = (WORD) newSize.cy;
scrw = img.Width();
scrh = img.Height();
if((destw-scrw)*(desth-scrh) < 0)
{
//AfxMessageBox("Current version only support!");
//return;
}
byteperline = ByteNumForOneLine(destw, bpp);
dwDIBHeadLength = sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * img.NumColors();
m_dwLength = dwDIBHeadLength + (DWORD) byteperline * desth;
m_pDib = NULL;
if(img.m_pDib)
{
// m_pDib=(BYTE*) GlobalAllocPtr(GHND, m_dwLength);
m_pDib = new BYTE[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();
}
Data();
ResizeImage(img.Data(), scrw, scrh, m_pData, destw, desth);
LPBITMAPINFOHEADER pBMIH;
pBMIH=BMInfoHdPtr();
pBMIH->biWidth = destw;
pBMIH->biHeight = desth;
Dib(); img.Dib();
m_pPal=new CPalette; CreateDIBPalette();
}
///////////////////////////////////////////////////////////////////
CImage::~CImage()
{
if(m_dwLength != 0L)
// delete []m_pDib; // free the DIB memory
delete []m_pDib;
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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -