?? bmptofiledlg.cpp
字號:
// BmptoFileDlg.cpp : implementation file
//
#include "stdafx.h"
#include "BmptoFile.h"
#include "BmptoFileDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CBmptoFileDlg dialog
CBmptoFileDlg::CBmptoFileDlg(CWnd* pParent /*=NULL*/)
: CDialog(CBmptoFileDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CBmptoFileDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CBmptoFileDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CBmptoFileDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CBmptoFileDlg, CDialog)
//{{AFX_MSG_MAP(CBmptoFileDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON_CONVERT, OnButtonConvert)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CBmptoFileDlg message handlers
BOOL CBmptoFileDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
void CBmptoFileDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CBmptoFileDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CBmptoFileDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CBmptoFileDlg::OnButtonConvert()
{
CBitmap bitmap;
if(!bitmap.LoadBitmap(IDB_BITMAP_CONVERT))
AfxMessageBox("Load bitmap error!");
char* szfile;
szfile = "bmptofile.bmp";
HANDLE hdib = DDBToDIB(bitmap, BI_RGB, NULL);
CFile file;
file.Open(szfile, CFile::modeCreate | CFile::modeWrite);
SaveDIB( hdib, file);
}
//////////////////////////////////////////////////////////////////////
//convert ddb to dib
//CBitmap -- your bitmap
//dwCompression -- see BITMAPINFOHEADER
//CPalette -- the palette of the bitmap
//return -- handle of a dib
HANDLE CBmptoFileDlg::DDBToDIB(CBitmap &bitmap, DWORD dwCompression, CPalette* pPal)
{
BITMAP bm;
BITMAPINFOHEADER bi;
LPBITMAPINFOHEADER lpbi;
DWORD dwlen;
HANDLE hdib;
HANDLE handle;
HDC hdc;
HPALETTE hpal;
ASSERT( bitmap.GetSafeHandle() );
// the function has no arg for bitfields
if( dwCompression == BI_BITFIELDS )
return NULL;
// if a palette has not been supplied use defaul palette
hpal = (HPALETTE) pPal->GetSafeHandle();
if (hpal==NULL)
hpal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);
// get bitmap information
bitmap.GetObject(sizeof(bm),(LPSTR)&bm);
// initialize the bitmapinfoheader
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bm.bmWidth;
bi.biHeight = bm.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = bm.bmPlanes * bm.bmBitsPixel;
bi.biCompression = dwCompression;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
// compute the size of the infoheader and the color table
int ncolors = (1 << bi.biBitCount );
if( ncolors> 256 )
ncolors = 0;
dwlen = bi.biSize + ncolors * sizeof(RGBQUAD);
// we need a device context to get the dib from
hdc = ::GetDC(NULL);
hpal = SelectPalette(hdc,hpal,FALSE);
RealizePalette(hdc);
// allocate enough memory to hold bitmapinfoheader and color table
hdib = GlobalAlloc(GMEM_FIXED,dwlen);
if (!hdib){
SelectPalette(hdc,hpal,FALSE);
::ReleaseDC(NULL,hdc);
return NULL;
}
lpbi = (LPBITMAPINFOHEADER)hdib;
*lpbi = bi;
// call getdibits with a NULL lpbits param, so the device driver
// will calculate the bisizeimage field
GetDIBits(hdc, (HBITMAP)bitmap.GetSafeHandle(), 0L, (DWORD)bi.biHeight,
(LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS);
bi = *lpbi;
// if the driver did not fill in the bisizeimage field, then compute it
// each scan line of the image is aligned on a dword (32bit) boundary
if (bi.biSizeImage == 0){
bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8)
* bi.biHeight;
// if a compression scheme is used the result may infact be larger
// increase the size to account for this.
if (dwCompression != BI_RGB)
bi.biSizeImage = (bi.biSizeImage * 3) / 2;
}
// realloc the buffer so that it can hold all the bits
dwlen += bi.biSizeImage;
if (handle = GlobalReAlloc(hdib, dwlen, GMEM_MOVEABLE))
hdib = handle;
else{
GlobalFree(hdib);
// reselect the original palette
SelectPalette(hdc,hpal,FALSE);
::ReleaseDC(NULL,hdc);
return NULL;
}
// get the bitmap bits
lpbi = (LPBITMAPINFOHEADER)hdib;
// finally get the dib
BOOL bgotbits = GetDIBits( hdc, (HBITMAP)bitmap.GetSafeHandle(),
0L, // start scan line
(DWORD)bi.biHeight, // # of scan lines
(LPBYTE)lpbi // address for bitmap bits
+ (bi.biSize + ncolors * sizeof(RGBQUAD)),
(LPBITMAPINFO)lpbi, // address of bitmapinfo
(DWORD)DIB_RGB_COLORS); // use rgb for color table
if( !bgotbits )
{
GlobalFree(hdib);
SelectPalette(hdc,hpal,FALSE);
::ReleaseDC(NULL,hdc);
return NULL;
}
SelectPalette(hdc,hpal,FALSE);
::ReleaseDC(NULL,hdc);
return hdib;
}
BOOL CBmptoFileDlg::SaveDIB(HANDLE hDib, CFile &file)
{
BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
LPBITMAPINFOHEADER lpBI; // Pointer to DIB info structure
DWORD dwDIBSize;
if (hDib == NULL)
return FALSE;
/*
* Get a pointer to the DIB memory, the first of which contains
* a BITMAPINFO structure
*/
lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);
if (lpBI == NULL)
return FALSE;
if (!IS_WIN30_DIB(lpBI))
{
::GlobalUnlock((HGLOBAL) hDib);
return FALSE; // It's an other-style DIB (save not supported)
}
/*
* Fill in the fields of the file header
*/
/* Fill in file type (first 2 bytes must be "BM" for a bitmap) */
bmfHdr.bfType = DIB_HEADER_MARKER; // "BM"
// Calculating the size of the DIB is a bit tricky (if we want to
// do it right). The easiest way to do this is to call GlobalSize()
// on our global handle, but since the size of our global memory may have
// been padded a few bytes, we may end up writing out a few too
// many bytes to the file (which may cause problems with some apps).
//
// So, instead let's calculate the size manually (if we can)
//
// First, find size of header plus size of color table. Since the
// first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains
// the size of the structure, let's use this.
dwDIBSize = *(LPDWORD)lpBI + PaletteSize((LPSTR)lpBI); // Partial Calculation
// Now calculate the size of the image
if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))
{
// It's an RLE bitmap, we can't calculate size, so trust the
// biSizeImage field
dwDIBSize += lpBI->biSizeImage;
}
else
{
DWORD dwBmBitsSize; // Size of Bitmap Bits only
// It's not RLE, so size is Width (DWORD aligned) * Height
dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight;
dwDIBSize += dwBmBitsSize;
// Now, since we have calculated the correct size, why don't we
// fill in the biSizeImage field (this will fix any .BMP files which
// have this field incorrect).
lpBI->biSizeImage = dwBmBitsSize;
}
// Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER)
bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
/*
* Now, calculate the offset the actual bitmap bits will be in
* the file -- It's the Bitmap file header plus the DIB header,
* plus the size of the color table.
*/
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize
+ PaletteSize((LPSTR)lpBI);
TRY
{
// Write the file header
file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
//
// Write the DIB header and the bits
//
file.WriteHuge(lpBI, dwDIBSize);
}
CATCH (CFileException, e)
{
::GlobalUnlock((HGLOBAL) hDib);
THROW_LAST();
}
END_CATCH
::GlobalUnlock((HGLOBAL) hDib);
return TRUE;
}
DWORD CBmptoFileDlg::PaletteSize(LPSTR lpBI)
{
/* calculate the size required by the palette */
if (IS_WIN30_DIB (lpBI))
return (WORD)(DIBNumColors(lpBI) * sizeof(RGBQUAD));
else
return (WORD)(DIBNumColors(lpBI) * sizeof(RGBTRIPLE));
}
WORD CBmptoFileDlg::DIBNumColors(LPSTR lpbi)
{
WORD wBitCount; // DIB bit count
/* If this is a Windows-style DIB, the number of colors in the
* color table can be less than the number of bits per pixel
* allows for (i.e. lpbi->biClrUsed can be set to some value).
* If this is the case, return the appropriate value.
*/
if (IS_WIN30_DIB(lpbi))
{
DWORD dwClrUsed;
dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed;
if (dwClrUsed != 0)
return (WORD)dwClrUsed;
}
/* Calculate the number of colors in the color table based on
* the number of bits per pixel for the DIB.
*/
if (IS_WIN30_DIB(lpbi))
wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
else
wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
/* return number of colors based on bits per pixel */
switch (wBitCount)
{
case 1:
return 2;
case 4:
return 16;
case 8:
return 256;
default:
return 0;
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -