问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

在MFC中,如何读取外部的位图文件,让它显示在图片控件(Picture Control...

发布网友 发布时间:2022-05-07 09:46

我来回答

5个回答

热心网友 时间:2022-04-23 08:14

告诉你一个最简单的方法,你一定可以的,弄好了记得给我加分.

1.在你的对话框添一个按钮和一个图片控件(Picture Control).
2.添加一个类,我这里上传不了,只能将.h和.cpp复制过来,你再将拷贝到txt里,改一下扩展名就可以了。
这是Picture.h
#if !defined(AFX_PICTURE_H__COPYFREE_BY_YOVAV_GAD__SOURCES_AT_SUPERMAIN_DOT_COM__INCLUDED_)
#define AFX_PICTURE_H__COPYFREE_BY_YOVAV_GAD__SOURCES_AT_SUPERMAIN_DOT_COM__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CPicture
{
public:
void FreePictureData();
BOOL Load(CString sFilePathName);
BOOL Load(UINT ResourceName, LPCSTR ResourceType);
BOOL LoadPictureData(BYTE* pBuffer, int nSize);
BOOL SaveAsBitmap(CString sFilePathName);
BOOL Show(CDC* pDC, CPoint LeftTop, CPoint WidthHeight, int MagnifyX, int MagnifyY);
BOOL Show(CDC* pDC, CRect DrawRect);
BOOL ShowBitmapResource(CDC* pDC, const int BMPResource, CPoint LeftTop);
BOOL UpdateSizeOnDC(CDC* pDC);

CPicture();
virtual ~CPicture();

IPicture* m_IPicture; // Same As LPPICTURE (typedef IPicture __RPC_FAR *LPPICTURE)

LONG m_Height; // Height (In Pixels Ignor What Current Device Context Uses)
LONG m_Weight; // Size Of The Image Object In Bytes (File OR Resource)
LONG m_Width; // Width (In Pixels Ignor What Current Device Context Uses)
};

#endif
这是Picture.cpp
#include "stdafx.h"
#include "Picture.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define HIMETRIC_INCH 2540
#define ERROR_TITLE "CPicture Error" // Error Title (Related To This Class)...

//-----------------------------------------------------------------------------
// Does: Constructor - Create a New CPicture Object To Hold Picture Data
// ~~~~
//
//-----------------------------------------------------------------------------
CPicture::CPicture()
//=============================================================================
{
m_IPicture = NULL;
m_Height = 0;
m_Weight = 0;
m_Width = 0;
}

//-----------------------------------------------------------------------------
// Does: Destructor - Free Data And Information From The CPicture Object
// ~~~~
//
//-----------------------------------------------------------------------------
CPicture::~CPicture()
//=============================================================================
{
if(m_IPicture != NULL) FreePictureData(); // Important - Avoid Leaks...
}

//-----------------------------------------------------------------------------
// Does: Free The Allocated Memory That Holdes The IPicture Interface Data
// ~~~~ And Clear Picture Information
//
// Note: This Might Also Be Useful If U Only Need To Show The Picture Once
// ~~~~~ Or If U Copy The Picture To The Device Context, So It Can Still
// Remain On Screen - But IPicture Data Is Not Needed No More
//
//-----------------------------------------------------------------------------
void CPicture::FreePictureData()
//=============================================================================
{
if(m_IPicture != NULL)
{
m_IPicture->Release();
m_IPicture = NULL;
m_Height = 0;
m_Weight = 0;
m_Width = 0;
}
}

//-----------------------------------------------------------------------------
// Does: Open a Resource And Load It Into IPicture (Interface)
// ~~~~ (.BMP .DIB .EMF .GIF .ICO .JPG .WMF)
//
// Note: When Adding a Bitmap Resource It Would Automatically Show On "Bitmap"
// ~~~~ This NOT Good Coz We Need To Load It From a Custom Resource "BMP"
// To Add a Custom Rresource: Import Resource -> Open As -> Custom
// (Both .BMP And .DIB Should Be Found Under "BMP")
//
// InPut: ResourceName - As a UINT Defined (Example: IDR_PICTURE_RESOURCE)
// ~~~~~ ResourceType - Type Name (Example: "JPG")
//
// OutPut: TRUE If Succeeded...
// ~~~~~~
//-----------------------------------------------------------------------------
BOOL CPicture::Load(UINT ResourceName, LPCSTR ResourceType)
//=============================================================================
{
BOOL bResult = FALSE;

HGLOBAL hGlobal = NULL;
HRSRC hSource = NULL;
LPVOID lpVoid = NULL;
int nSize = 0;

if(m_IPicture != NULL) FreePictureData(); // Important - Avoid Leaks...

hSource = FindResource(AfxGetResourceHandle(), MAKEINTRESOURCE(ResourceName), ResourceType);

if(hSource == NULL)
{
HWND hWnd = AfxGetApp()->GetMainWnd()->m_hWnd;
MessageBoxEx(hWnd, "FindResource() Failed\t", ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
return(FALSE);
}

hGlobal = LoadResource(AfxGetResourceHandle(), hSource);
if(hGlobal == NULL)
{
HWND hWnd = AfxGetApp()->GetMainWnd()->m_hWnd;
MessageBoxEx(hWnd, "LoadResource() Failed\t", ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
return(FALSE);
}

lpVoid = LockResource(hGlobal);
if(lpVoid == NULL)
{
HWND hWnd = AfxGetApp()->GetMainWnd()->m_hWnd;
MessageBoxEx(hWnd, "LockResource() Failed\t", ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
return(FALSE);
}

nSize = (UINT)SizeofResource(AfxGetResourceHandle(), hSource);
if(LoadPictureData((BYTE*)hGlobal, nSize)) bResult = TRUE;

UnlockResource(hGlobal); // 16Bit Windows Needs This
FreeResource(hGlobal); // 16Bit Windows Needs This (32Bit - Automatic Release)

m_Weight = nSize; // Update Picture Size Info...

if(m_IPicture != NULL) // Do Not Try To Read From Memory That Is Not Exist...
{
m_IPicture->get_Height(&m_Height);
m_IPicture->get_Width(&m_Width);
// Calculate Its Size On a "Standard" (96 DPI) Device Context
m_Height = MulDiv(m_Height, 96, HIMETRIC_INCH);
m_Width = MulDiv(m_Width, 96, HIMETRIC_INCH);
}
else // Picture Data Is Not a Known Picture Type
{
m_Height = 0;
m_Width = 0;
bResult = FALSE;
}

return(bResult);
}

//-----------------------------------------------------------------------------
// Does: Open a File And Load It Into IPicture (Interface)
// ~~~~ (.BMP .DIB .EMF .GIF .ICO .JPG .WMF)
//
// InPut: sFilePathName - Path And FileName Target To Save
// ~~~~~
//
// OutPut: TRUE If Succeeded...
// ~~~~~~
//-----------------------------------------------------------------------------
BOOL CPicture::Load(CString sFilePathName)
//=============================================================================
{
BOOL bResult = FALSE;
CFile PictureFile;
CFileException e;
int nSize = 0;

if(m_IPicture != NULL) FreePictureData(); // Important - Avoid Leaks...

if(PictureFile.Open(sFilePathName, CFile::modeRead | CFile::typeBinary, &e))
{
nSize = PictureFile.GetLength();
BYTE* pBuffer = new BYTE[nSize];

if (PictureFile.Read(pBuffer, nSize) > 0 ) //从文件读到pBuffer
{ if(LoadPictureData(pBuffer, nSize)) bResult = TRUE; }//接作调用函数读pBuffer

PictureFile.Close();

delete [] pBuffer;
}
else // Open Failed...
{
TCHAR szCause[255];
e.GetErrorMessage(szCause, 255, NULL);
HWND hWnd = AfxGetApp()->GetMainWnd()->m_hWnd;
MessageBoxEx(hWnd, szCause, ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
bResult = FALSE;
}

m_Weight = nSize; // Update Picture Size Info...

if(m_IPicture != NULL) // Do Not Try To Read From Memory That Is Not Exist...
{
m_IPicture->get_Height(&m_Height);
m_IPicture->get_Width(&m_Width);
// Calculate Its Size On a "Standard" (96 DPI) Device Context
m_Height = MulDiv(m_Height, 96, HIMETRIC_INCH);
m_Width = MulDiv(m_Width, 96, HIMETRIC_INCH);
}
else // Picture Data Is Not a Known Picture Type
{
m_Height = 0;
m_Width = 0;
bResult = FALSE;
}

return(bResult);
}

//-----------------------------------------------------------------------------
// Does: Read The Picture Data From a Source (File / Resource)
// ~~~~ And Load It Into The Current IPicture Object In Use
//
// InPut: Buffer Of Data Source (File / Resource) And Its Size
// ~~~~~
//
// OutPut: Feed The IPicture Object With The Picture Data
// ~~~~~~ (Use Draw Functions To Show It On a Device Context)
// TRUE If Succeeded...
//-----------------------------------------------------------------------------
BOOL CPicture::LoadPictureData(BYTE *pBuffer, int nSize)
//=============================================================================
{
BOOL bResult = FALSE;

HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, nSize);

if(hGlobal == NULL)
{
HWND hWnd = AfxGetApp()->GetMainWnd()->m_hWnd;
MessageBoxEx(hWnd, "Can not allocate enough memory\t", ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
return(FALSE);
}

void* pData = GlobalLock(hGlobal);
memcpy(pData, pBuffer, nSize);
GlobalUnlock(hGlobal);

IStream* pStream = NULL;

if(CreateStreamOnHGlobal(hGlobal, TRUE, &pStream) == S_OK)
{
HRESULT hr;
if((hr = OleLoadPicture(pStream, nSize, FALSE, IID_IPicture, (LPVOID *)&m_IPicture)) == E_NOINTERFACE)
{
HWND hWnd = AfxGetApp()->GetMainWnd()->m_hWnd;
MessageBoxEx(hWnd, "IPicture interface is not supported\t", ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
return(FALSE);
}
else // S_OK
{
pStream->Release();
pStream = NULL;
bResult = TRUE;
}
}

FreeResource(hGlobal); // 16Bit Windows Needs This (32Bit - Automatic Release)

return(bResult);
}

//-----------------------------------------------------------------------------
// Does: Draw The Loaded Picture Direct To The Client DC
// ~~~~
//
// Note: Bigger OR Smaller Dimentions Than The Original Picture Size
// ~~~~ Will Draw The Picture Streached To Its New Given NEW Dimentions...
//
// InPut: pDC - Given DC To Draw On
// ~~~~~ DrawRect - Dimentions Of The Picture To Draw (As a Rectangle)
//
// OutPut: TRUE If Succeeded...
// ~~~~~~
//-----------------------------------------------------------------------------
BOOL CPicture::Show(CDC *pDC, CRect DrawRect)
//=============================================================================
{
if (pDC == NULL || m_IPicture == NULL) return FALSE;

long Width = 0;
long Height = 0;
m_IPicture->get_Width(&Width);
m_IPicture->get_Height(&Height);

HRESULT hrP = NULL;

hrP = m_IPicture->Render(pDC->m_hDC,
DrawRect.left, // Left
DrawRect.top, // Top
DrawRect.right - DrawRect.left, // Right
DrawRect.bottom - DrawRect.top, // Bottom
0,
Height,
Width,
-Height,
&DrawRect);

if (SUCCEEDED(hrP)) return(TRUE);

HWND hWnd = AfxGetApp()->GetMainWnd()->m_hWnd;
MessageBoxEx(hWnd, "Can not allocate enough memory\t", ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
return(FALSE);
}

//-----------------------------------------------------------------------------
// Does: Draw The Loaded Picture Direct To The Client DC
// ~~~~
//
// Note: Bigger OR Smaller Dimentions Than The Original Picture Size
// ~~~~ Will Draw The Picture Streached To Its New Given Dimentions...
//
// InPut: pDC - Given DC To Draw On
// ~~~~~ LeftTop - Opening Point To Start Drawing (Left,Top)
// WidthHeight - Dimentions Of The Picture To Draw (Width,Height)
// MagnifyX - Magnify Pixel Width, 0 = Default (No Magnify)
// MagnifyY - Magnify Pixel Height, 0 = Default (No Magnify)
//
// OutPut: TRUE If Succeeded...
// ~~~~~~
//-----------------------------------------------------------------------------
BOOL CPicture::Show(CDC *pDC, CPoint LeftTop, CPoint WidthHeight, int MagnifyX, int MagnifyY)
//=============================================================================
{
if (pDC == NULL || m_IPicture == NULL) return FALSE;

long Width = 0;
long Height = 0;
m_IPicture->get_Width(&Width);
m_IPicture->get_Height(&Height);
if(MagnifyX == NULL) MagnifyX = 0;
if(MagnifyY == NULL) MagnifyY = 0;
MagnifyX = int(MulDiv(Width, pDC->GetDeviceCaps(LOGPIXELSX), HIMETRIC_INCH) * MagnifyX);
MagnifyY = int(MulDiv(Height,pDC->GetDeviceCaps(LOGPIXELSY), HIMETRIC_INCH) * MagnifyY);

CRect DrawRect(LeftTop.x, LeftTop.y, MagnifyX, MagnifyY);

HRESULT hrP = NULL;

hrP = m_IPicture->Render(pDC->m_hDC,
LeftTop.x, // Left
LeftTop.y, // Top
WidthHeight.x +MagnifyX, // Width
WidthHeight.y +MagnifyY, // Height
0,
Height,
Width,
-Height,
&DrawRect);

if(SUCCEEDED(hrP)) return(TRUE);

HWND hWnd = AfxGetApp()->GetMainWnd()->m_hWnd;
MessageBoxEx(hWnd, "Can not allocate enough memory\t", ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
return(FALSE);
}

//-----------------------------------------------------------------------------
// Does: Saves The Picture That Is Stored In The IPicture Object As a Bitmap
// ~~~~ (Converts From Any Known Picture Type To a Bitmap / Icon File)
//
// InPut: sFilePathName - Path And FileName Target To Save
// ~~~~~
//
// OutPut: TRUE If Succeeded...
// ~~~~~~
//-----------------------------------------------------------------------------
BOOL CPicture::SaveAsBitmap(CString sFilePathName)
//=============================================================================
{
BOOL bResult = FALSE;
ILockBytes *Buffer = 0;
IStorage *pStorage = 0;
IStream *FileStream = 0;
BYTE *BufferBytes;
STATSTG BytesStatistics;
DWORD OutData;
long OutStream;
CFile BitmapFile; CFileException e;
double SkipFloat = 0;
DWORD ByteSkip = 0;
_ULARGE_INTEGER RealData;

CreateILockBytesOnHGlobal(NULL, TRUE, &Buffer); // Create ILockBytes Buffer

HRESULT hr = ::StgCreateDocfileOnILockBytes(Buffer,
STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 0, &pStorage);

hr = pStorage->CreateStream(L"PICTURE",
STGM_SHARE_EXCLUSIVE | STGM_CREATE | STGM_READWRITE, 0, 0, &FileStream);

m_IPicture->SaveAsFile(FileStream, TRUE, &OutStream); // Copy Data Stream
FileStream->Release();
pStorage->Release();
Buffer->Flush();

// Get Statistics For Final Size Of Byte Array
Buffer->Stat(&BytesStatistics, STATFLAG_NONAME);

// Cut UnNeeded Data Coming From SaveAsFile() (Leave Only "Pure" Picture Data)
SkipFloat = (double(OutStream) / 512); // Must Be In a 512 Blocks...
if(SkipFloat > DWORD(SkipFloat)) ByteSkip = (DWORD)SkipFloat + 1;
else ByteSkip = (DWORD)SkipFloat;
ByteSkip = ByteSkip * 512; // Must Be In a 512 Blocks...

// Find Difference Between The Two Values
ByteSkip = (DWORD)(BytesStatistics.cbSize.QuadPart - ByteSkip);

// Allocate Only The "Pure" Picture Data
RealData.LowPart = 0;
RealData.HighPart = 0;
RealData.QuadPart = ByteSkip;
BufferBytes = (BYTE*)malloc(OutStream);
if(BufferBytes == NULL)
{
Buffer->Release();
HWND hWnd = AfxGetApp()->GetMainWnd()->m_hWnd;
MessageBoxEx(hWnd, "Can not allocate enough memory\t", ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
}

Buffer->ReadAt(RealData, BufferBytes, OutStream, &OutData);

if(BitmapFile.Open(sFilePathName, CFile::typeBinary | CFile::modeCreate | CFile::modeWrite, &e))
{
BitmapFile.Write(BufferBytes, OutData);
BitmapFile.Close();
bResult = TRUE;
}
else // Write File Failed...
{
TCHAR szCause[255];
e.GetErrorMessage(szCause, 255, NULL);
HWND hWnd = AfxGetApp()->GetMainWnd()->m_hWnd;
MessageBoxEx(hWnd, szCause, ERROR_TITLE, MB_OK | MB_ICONSTOP, LANG_ENGLISH);
bResult = FALSE;
}

Buffer->Release();
free(BufferBytes);

return(bResult);
}

//-----------------------------------------------------------------------------
// Does: Draw a Bitmap Resource To The Client DC (Using Bitblt())
// ~~~~ It Will Use The Bitmap Resource Original Size (Width And Height)
// (.BMP .DIB)
//
// Note: This Function Is Just Another Simple Way Of Displaying a Bitmap Resource,
// ~~~~ It Is Not Connected With The IPicture Interface And Can Be Used
// As a StandAlone On Any Device Context (Directly)
//
// InPut: BMPResource - Resource Name As Defined In The Resources
// ~~~~~ pDC - Given DC To Draw On
// LeftTop - Opening Point To Start Drawing (Left,Top)
//
// OutPut: TRUE If Succeeded...
// ~~~~~~
//-----------------------------------------------------------------------------
BOOL CPicture::ShowBitmapResource(CDC *pDC, const int BMPResource, CPoint LeftTop)
//=============================================================================
{
if (pDC == NULL) return(FALSE);

CBitmap BMP;
if(BMP.LoadBitmap(BMPResource))
{
// Get Bitmap Details
BITMAP BMPInfo;
BMP.GetBitmap(&BMPInfo);

// Create An In-Memory DC Compatible With The Display DC We R Gonna Paint On
CDC DCMemory;
DCMemory.CreateCompatibleDC(pDC);

// Select The Bitmap Into The In-Memory DC
CBitmap* pOldBitmap = DCMemory.SelectObject(&BMP);

// Copy Bits From The In-Memory DC Into The On-Screen DC
pDC->BitBlt(LeftTop.x, LeftTop.y, BMPInfo.bmWidth, BMPInfo.bmHeight, &DCMemory, 0, 0, SRCCOPY);

DCMemory.SelectObject(pOldBitmap); // (As Shown In MSDN Example...)
}
else
{
TRACE0("ERROR: Can Not Find The Bitmap Resource\n");
return(FALSE);
}

return(TRUE);
}

//-----------------------------------------------------------------------------
// Does: Get The Original Picture Pixel Size (Ignor What Current DC Is Using)
// ~~~~ Pointer To a Device Context Is Needed For Pixel Calculation,
//
// Also Updates The Class's Height And Width Properties,
// (Coz Till Now We Had No Device Context To Work With...96 DPI Assumed)
//
// InPut: The Client DC (Needed To Check The Size Of The Pixels)
// ~~~~~
//
// OutPut: TRUE If Succeeded...
// ~~~~~~
//-----------------------------------------------------------------------------
BOOL CPicture::UpdateSizeOnDC(CDC *pDC)
//=============================================================================
{
if(pDC == NULL || m_IPicture == NULL) { m_Height = 0; m_Width = 0; return(FALSE); };

m_IPicture->get_Height(&m_Height);
m_IPicture->get_Width(&m_Width);

// Get Current DPI - Dot Per Inch
int CurrentDPI_X = pDC->GetDeviceCaps(LOGPIXELSX);
int CurrentDPI_Y = pDC->GetDeviceCaps(LOGPIXELSY);

// Use a "Standard" Print (When Printing)
if(pDC->IsPrinting())
{
CurrentDPI_X = 96;
CurrentDPI_Y = 96;
}

m_Height = MulDiv(m_Height, CurrentDPI_Y, HIMETRIC_INCH);
m_Width = MulDiv(m_Width, CurrentDPI_X, HIMETRIC_INCH);

return(TRUE);
}

3.在对话框头文件定义:
先包含头文件#include "Picture.h"
再定义
CPicture m_Pic;
4.给按钮的函数里写上:(注意,这个IDC_SHOWPIC)是你那个显示控件的ID号.
CRect rect;
GetDlgItem(IDC_SHOWPIC)->GetWindowRect(&rect);
ScreenToClient(&rect);

CFile f;
CString FilePathName;
CFileException e;
CFileDialog dlg(TRUE,NULL,NULL,0,_T("All Files (*.*)|*.*|BMP (*.bmp)|*.bmp|DIB (*.dib)|*.dib|EMF (*.emf)|*.emf|GIF (*.gif)|*.gif|ICO (*.ico)|*.ico|JPG (*.jpg)|*.jpg|WMF (*.wmf)|*.wmf||"),NULL);
if(dlg.DoModal()==IDOK)
{
FilePathName=dlg.GetPathName();
if(m_Pic.m_IPicture != NULL) m_Pic.FreePictureData();
m_Pic.Load(FilePathName);
CClientDC dc(this);
m_Pic.UpdateSizeOnDC(&dc);
m_Pic.Show(&dc, &rect);
}

热心网友 时间:2022-04-23 09:32

---- 用普通方法显示BMP位图,占内存大,速度慢,在图形缩小时,失真严重,在低颜色位数的设备上显示高颜色位数的图形图形时失真大。本文采用视频函数显示BMP位图,可以消除以上的缺点。

---- 一、BMP文件结构

---- 1. BMP文件组成

---- BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。

---- 2. BMP文件头

---- BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。

---- 其结构定义如下:

typedef struct tagBITMAPFILEHEADER

{

WORDbfType; // 位图文件的类型,必须为BM

DWORD bfSize; // 位图文件的大小,以字节为单位

WORDbfReserved1; // 位图文件保留字,必须为0

WORDbfReserved2; // 位图文件保留字,必须为0

DWORD bfOffBits; // 位图数据的起始位置,以相对于位图

// 文件头的偏移量表示,以字节为单位

} BITMAPFILEHEADER;

---- 3. 位图信息头

BMP位图信息头数据用于说明位图的尺寸等信息。

typedef struct tagBITMAPINFOHEADER{

DWORD biSize; // 本结构所占用字节数

LONGbiWidth; // 位图的宽度,以像素为单位

LONGbiHeight; // 位图的高度,以像素为单位

WORD biPlanes; // 目标设备的级别,必须为1

WORD biBitCount// 每个像素所需的位数,必须是1(双色),

// 4(16色),8(256色)或24(真彩色)之一

DWORD biCompression; // 位图压缩类型,必须是 0(不压缩),

// 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一

DWORD biSizeImage; // 位图的大小,以字节为单位

LONGbiXPelsPerMeter; // 位图水平分辨率,每米像素数

LONGbiYPelsPerMeter; // 位图垂直分辨率,每米像素数

DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数

DWORD biClrImportant;// 位图显示过程中重要的颜色数

} BITMAPINFOHEADER;

---- 4. 颜色表

---- 颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下:

typedef struct tagRGBQUAD {

BYTErgbBlue;// 蓝色的亮度(值范围为0-255)

BYTErgbGreen; // 绿色的亮度(值范围为0-255)

BYTErgbRed; // 红色的亮度(值范围为0-255)

BYTErgbReserved;// 保留,必须为0

} RGBQUAD;

颜色表中RGBQUAD结构数据的个数有biBitCount来确定:

当biBitCount=1,4,8时,分别有2,16,256个表项;

当biBitCount=24时,没有颜色表项。

位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:

typedef struct tagBITMAPINFO {

BITMAPINFOHEADER bmiHeader; // 位图信息头

RGBQUAD bmiColors[1]; // 颜色表

} BITMAPINFO;

---- 5. 位图数据

---- 位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。位图的一个像素值所占的字节数:

当biBitCount=1时,8个像素占1个字节;

当biBitCount=4时,2个像素占1个字节;

当biBitCount=8时,1个像素占1个字节;

当biBitCount=24时,1个像素占3个字节;

Windows规定一个扫描行所占的字节数必须是 4的倍数(即以long为单位),不足的以0填充,

一个扫描行所占的字节数计算方法: DataSizePerLine= (biWidth* biBitCount+31)/8;

// 一个扫描行所占的字节数 DataSizePerLine= DataSizePerLine/4*4; // 字节数必须是4的倍数

位图数据的大小(不压缩情况下): DataSize= DataSizePerLine* biHeight;

---- 二、BMP位图一般显示方法

---- 1. 申请内存空间用于存放位图文件

---- GlobalAlloc(GHND,FileLength);

---- 2. 位图文件读入所申请内存空间中

---- LoadFileToMemory( mpBitsSrc,mFileName);

---- 3. 在OnPaint等函数中用创建显示用位图

---- 用CreateDIBitmap()创建显示用位图,用CreateCompatibleDC()创建兼容DC,

---- 用SelectBitmap()选择显示位图。

---- 4. 用BitBlt或StretchBlt等函数显示位图

---- 5. 用DeleteObject()删除所创建的位图

---- 以上方法的缺点是: 1)显示速度慢; 2) 内存占用大; 3) 位图在缩小显示时图形失真大,(可通过安装字体平滑软件来解决); 4) 在低颜色位数的设备上(如256显示模式)显示高颜色位数的图形(如真彩色)图形失真严重。

---- 三、BMP位图缩放显示

---- 用DrawDib视频函数来显示位图,内存占用少,速度快,而且还可以对图形进行淡化(Dithering )处理。淡化处理是一种图形算法,可以用来在一个支持比图像所用颜色要少的设备上显示彩色图像。BMP位图显示方法如下:

---- 1. 打开视频函数DrawDibOpen(),一般放在在构造函数中

---- 2. 申请内存空间用于存放位图文件

---- GlobalAlloc(GHND,FileLength);

---- 3. 位图文件读入所申请内存空间中

---- LoadFileToMemory( mpBitsSrc,mFileName);

---- 4. 在OnPaint等函数中用DrawDibRealize(),DrawDibDraw()显示位图

---- 5. 关闭视频函数DrawDibClose(),一般放在在析构函数中

---- 以上方法的优点是: 1)显示速度快; 2) 内存占用少; 3) 缩放显示时图形失真小,4) 在低颜色位数的设备上显示高颜色位数的图形图形时失真小; 5) 通过直接处理位图数据,可以制作简单动画。

---- 四、CViewBimap类编程要点

---- 1. 在CViewBimap类中添加视频函数等成员

HDRAWDIB m_hDrawDib; // 视频函数

HANDLEmhBitsSrc; // 位图文件句柄(内存)

LPSTR mpBitsSrc; // 位图文件地址(内存)

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

---- 2. 在CViewBimap类构造函数中添加打开视频函数

---- m_hDrawDib= DrawDibOpen();

---- 3. 在CViewBimap类析构函数中添加关闭视频函数

if( m_hDrawDib != NULL)

{

DrawDibClose( m_hDrawDib);

m_hDrawDib = NULL;

}

---- 4. 在CViewBimap类图形显示函数OnPaint中添加GraphicDraw()

voidCViewBitmap::OnPaint()

{

CPaintDC dc(this); // device context for painting

GraphicDraw( );

}

voidCViewBitmap::GraphicDraw( void )

{

CClientDC dc(this); // device context for painting

BITMAPFILEHEADER *pBitmapFileHeader;

ULONG bfoffBits= 0;

CPoint Wid;

// 图形文件名有效 (=0 BMP)

if( mBitmapFileType < ID_BITMAP_BMP ) return;

// 图形文件名有效 (=0 BMP)

// 准备显示真彩位图

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

bfoffBits= pBitmapFileHeader->bfOffBits;

// 使用普通函数显示位图

if( m_hDrawDib == NULL || mDispMethod == 0)

{

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

// 建立位图

HDC hMemDC=::CreateCompatibleDC(dc.m_hDC);// 建立内存

HBITMAP hBitmapOld= SelectBitmap(hMemDC, hBitmap); // 选择对象

// 成员CRect mDispR用于指示图形显示区域的大小.

// 成员CPoint mPos用于指示图形显示起始位置坐标.

if( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() ))

mPos.x= mpBitmapInfo->biWidth - mDispR.Width() ;

if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height()))

mPos.y= mpBitmapInfo- >biHeight- mDispR.Height();

if( mPos.x < 0 ) mPos.x= 0;

if( mPos.y < 0 ) mPos.y= 0;

if( mFullViewTog == 0)

{

// 显示真彩位图

::BitBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(),

hMemDC,mPos.x,mPos.y, SRCCOPY);

} else {

::StretchBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(),

hMemDC,0,0, mpBitmapInfo- >biWidth, mpBitmapInfo-

>biHeight, SRCCOPY);

}

// 结束显示真彩位图

::DeleteObject(SelectObject(hMemDC,hBitmapOld));

// 删 除 位 图

} else {

// 使用视频函数显示位图

if( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() ))

mPos.x= mpBitmapInfo- >biWidth - mDispR.Width() ;

if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height()))

mPos.y= mpBitmapInfo- >biHeight- mDispR.Height();

if( mPos.x < 0 ) mPos.x= 0;

if( mPos.y < 0 ) mPos.y= 0;

热心网友 时间:2022-04-23 11:06

HBITMAP *hBitmap; // 定义位图对象句柄
BITMAP BM;
CDC MemDC;

CClientDC ClientDC(this);
MemDC.CreateCompatibleDC(&ClientDC);

hBitmap=(HBITMAP*)::LoadImage(
AfxGetInstanceHandle(), // 取得应用程序句柄
"demo1.bmp", // 位图文件名
IMAGE_BITMAP, // 类型为Windows位图
0,0,
LR_LOADFROMFILE
);

// 从文件中取位图数据
MemDC.SelectObject(hBitmap);
::GetObject(hBitmap,sizeof(BM), &BM);
ClientDC.BitBlt(
X,Y, // 目标设备逻辑横、纵坐标
BM.bmWidth, BM.bmHeight, // 显示位图的像素宽、高度
&MemDC, // 待显示位图数据的设备情境对象
0,0, // 源数据中的横、纵坐标
SRCCOPY // 位操作方式
);

热心网友 时间:2022-04-23 12:58

关键是两个步骤
1 读取文件,转换成位图对象
2 获得空间的hdc,在hdc上绘制这个位图

www.codeproject.com 上面有大量的例子可以看

热心网友 时间:2022-04-23 15:06

这个程序就可以

参考资料:http://www.vckbase.com/code/downcode.asp?id=1972

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
邮寄35公斤冰箱多少钱 一个冰箱的物流多少钱 快递一个小冰箱多少钱 冰箱发物流怎么收费 冰箱能发物流多少钱 快递个冰箱大概多少钱 物流冰箱回家不知道费用要多少喔 为什么打开猎豹浏览器以后,系统显示占用了很多内存? 猎豹浏览器手机版视频缓存占手机空间吗 猎豹浏览器隐藏功能有哪些? 诺基亚5300怎么上网和听收音机啊 诺基亚5300怎么上网? malloc和free的问题 诺基亚 5300手机怎么申请上网? 跪求翻译一段英语 谢谢!! 诺基亚5300上网连接怎么设置 诺基亚5300手机怎样连接电脑上网?答案要详细点.. 电脑被绑定安装了一个名叫freecopy的软件,我点卸载,一直卸载不了,请问这是什么?该怎么办? 诺基亚5300怎样设置上网?为什么会出现设置后不能上网的现象? Free copy是什么意思啊? 诺基亚手机5300上网设置 诺基亚5300怎么上网啊?? CopyFree什么意思 怎么看ocr软件 诺基亚5300联通卡上网怎么设置 OCR识别什么时候能开放给开发者 诺基亚5300的手机如何进行上网设置 云脉OCR的表格识别系统可以通过关键词、日期等进行文档检索吗?、 在ocr识别中,如果训练模型中增加生僻字,会影响响应时间吗? 工程审计的结果对谁产生法律效力 诺基亚5300用移动的卡上网功能该怎么设置? i will even send you a free copy 诺基亚5300怎么上网 诺基亚5300怎么设置手机上网? - 信息提示 c语言中malloc与free机制问题 诺基亚5300怎么样进行上网配置上网最好 this free copy is yours no matter you buy any of our books错在哪 诺基亚5300怎么上网啊 诺基亚5300怎么设置才能上网 C语言 指针的copy问题 海鲜头孢可以一起吃吗 C语言复制文件时怎样跳过 &quot;循环冗余&quot;的文件? 诺基亚5300怎么连接上网的?数据是什么 如何实现WINDOWS风格的文件拷贝功能?(显示拷贝进度) 请教个关于copy 电脑开机时不是欢迎屏幕怎么办 C语言free的时候程序出错 一般备孕体温是多少? 电脑开机后一直在欢迎界面