📄 mfcview.cpp
字号:
////////////////////////////////////////////////////////////////////////////
// mfcappView.cpp : implementation of the CMfcappView class
//
//
// Note : GIF code removed 9/23/97 pending Unisys licensing.
//
//
// This code copyright 1997 Chris Losinger, unless otherwise noted
//
// CHRISDL@PAGESZ.NET
//
// PLEASE!!! Tell me of any bugs you find!!!
//
// This code contains examples of using my JpegFile class, how to
// read and write 1,4,8 and 24-bit BMPs and how to read and write
// GIF87a files.
//
// I find that this code works well for my purposes. Feel free to
// use it in your own code, but I can't assume any responsibility
// if this code fails to do what you expect.
//
// If you find any problems with this code, feel free to contact
// me for help.
//
// Note : parts of the GIF specification are copyrighted. I am not
// authorized to grant license to use the GIF code (or to even use it
// myself). If you worry about such things, I suggest you find out
// how to get permission to use the GIF algorithms in your code.
// The GIF algorithms are patented by the Unisys corporation.
//
// 24-bit to 8-bit color quantization code modified from Dennis Lee's
// DL1Quant. His source is available at ...
//
#include "stdafx.h"
#include "mfcapp.h"
#include "mfcDoc.h"
#include "mfcView.h"
#include "math.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "JpegFile.h"
#include "GIFFile.h"
#include "BMPDlg.h"
#include "BMPFile.h"
#include "QuantDlg.h"
#include "dl1quant.h"
/////////////////////////////////////////////////////////////////////////////
// CMfcappView
IMPLEMENT_DYNCREATE(CMfcappView, CView)
BEGIN_MESSAGE_MAP(CMfcappView, CView)
//{{AFX_MSG_MAP(CMfcappView)
ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
ON_COMMAND(ID_FILE_SAVE_AS, OnFileSaveAs)
ON_COMMAND(ID_FILE_SAVEGRAYAS, OnFileSavegrayJPGas)
ON_COMMAND(ID_FILE_GETDIMENSIONSJPG, OnFileGetdimensionsjpg)
ON_COMMAND(ID_FILE_SAVECOLORMAPPEDBMP, OnFileSavecolormappedbmp)
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMfcappView construction/destruction
CMfcappView::CMfcappView()
{
// we keep a single global image in memory
m_buf=NULL; // where we keep our image data
m_width=0; // image dimensions
m_height=0;
m_widthDW=0;
}
CMfcappView::~CMfcappView()
{
// clean up
if (m_buf!=NULL) {
delete [] m_buf;
m_buf=NULL;
}
}
BOOL CMfcappView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CMfcappView drawing
void CMfcappView::OnDraw(CDC* pDC)
{
CMfcappDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// draw the BMP we have in memory
DrawBMP();
}
////////////////////////////////////////////////////////////////////////////
//
// shoot the global image to the screen
void CMfcappView::DrawBMP()
{
// if we don't have an image, get out of here
if (m_buf==NULL) return;
CDC *theDC = GetDC();
if (theDC!=NULL) {
CRect clientRect;
GetClientRect(clientRect);
// Center It
UINT left = (clientRect.Width() - m_width) / 2;
UINT top = (clientRect.Height() - m_height) / 2;
// a 24-bit DIB is DWORD-aligned, vertically flipped and
// has Red and Blue bytes swapped. we already did the
// RGB->BGR and the flip when we read the images, now do
// the DWORD-align
BYTE *tmp;
// DWORD-align for display
tmp = JpegFile::MakeDwordAlignedBuf(m_buf,
m_width,
m_height,
&m_widthDW);
// set up a DIB
BITMAPINFOHEADER bmiHeader;
bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmiHeader.biWidth = m_width;
bmiHeader.biHeight = m_height;
bmiHeader.biPlanes = 1;
bmiHeader.biBitCount = 24;
bmiHeader.biCompression = BI_RGB;
bmiHeader.biSizeImage = 0;
bmiHeader.biXPelsPerMeter = 0;
bmiHeader.biYPelsPerMeter = 0;
bmiHeader.biClrUsed = 0;
bmiHeader.biClrImportant = 0;
// now blast it to the CDC passed in.
// lines returns the number of lines actually displayed
int lines = StretchDIBits(theDC->m_hDC,
left, top,
bmiHeader.biWidth,
bmiHeader.biHeight,
0,0,
bmiHeader.biWidth,
bmiHeader.biHeight,
tmp,
(LPBITMAPINFO)&bmiHeader,
DIB_RGB_COLORS,
SRCCOPY);
delete [] tmp;
CString info;
info.Format("(%d x %d)", m_width, m_height);
theDC->SetBkMode(TRANSPARENT);
theDC->SetTextColor(RGB(0,0,0));
theDC->TextOut(10,5, info);
ReleaseDC(theDC);
}
}
/////////////////////////////////////////////////////////////////////////////
// CMfcappView printing
BOOL CMfcappView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CMfcappView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CMfcappView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CMfcappView diagnostics
#ifdef _DEBUG
void CMfcappView::AssertValid() const
{
CView::AssertValid();
}
void CMfcappView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CMfcappDoc* CMfcappView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMfcappDoc)));
return (CMfcappDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CMfcappView message handlers
void CMfcappView::OnFileOpen()
{
CString fileName;
CString filt="JPG File (*.JPG)|*.JPG|BMP (*.BMP)|*.BMP|GIF (*.GIF)|*.GIF|All files (*.*)|*.*||";
// OPENFILENAME - so i can get to its Help page easily
CFileDialog fileDlg(TRUE,"*.JPG","*.JPG",NULL,filt,this);
fileDlg.m_ofn.Flags|=OFN_FILEMUSTEXIST;
fileDlg.m_ofn.lpstrTitle="File to load";
if (fileDlg.DoModal()==IDOK) {
AfxGetApp()->DoWaitCursor(1);
fileName=fileDlg.GetPathName();
CString ext=fileName.Right(4);
if (!ext.CompareNoCase(".JPG"))
LoadJPG(fileName);
if (!ext.CompareNoCase(".GIF"))
LoadGIF(fileName);
if (!ext.CompareNoCase(".BMP"))
LoadBMP(fileName);
AfxGetApp()->DoWaitCursor(-1);
}
// force a redraw
Invalidate(TRUE);
}
////////////////////////////////////////////////////////////////////////////
// Save As dialog handler
//
void CMfcappView::OnFileSaveAs()
{
CString fileName;
CString filt="JPG File (*.JPG)|*.JPG|GIF File (*.GIF)|*.GIF|BMP (*.BMP)|*.BMP|All files (*.*)|*.*||";
// OPENFILENAME - so i can get to its Help page easily
CFileDialog fileDlg(FALSE,"*.JPG","*.JPG",NULL,filt,this);
fileDlg.m_ofn.Flags|=OFN_FILEMUSTEXIST;
fileDlg.m_ofn.lpstrTitle="File to save as";
if (fileDlg.DoModal()==IDOK) {
AfxGetApp()->DoWaitCursor(1);
fileName=fileDlg.GetPathName();
CString ext=fileName.Right(4);
if (!ext.CompareNoCase(".JPG"))
SaveJPG(fileName,TRUE);
if (!ext.CompareNoCase(".BMP"))
SaveBMP24(fileName);
if (!ext.CompareNoCase(".GIF"))
SaveGIF(fileName);
AfxGetApp()->DoWaitCursor(-1);
}
}
////////////////////////////////////////////////////////////////////////////
// read a JPG to our global buffer
//
void CMfcappView::LoadJPG(CString fileName)
{
// m_buf is the global buffer
if (m_buf!=NULL) {
delete [] m_buf;
m_buf=NULL;
}
// read to buffer tmp
m_buf=JpegFile::JpegFileToRGB(fileName, &m_width, &m_height);
//////////////////////
// set up for display
// do this before DWORD-alignment!!!
// this works on packed (not DWORD-aligned) buffers
// swap red and blue for display
JpegFile::BGRFromRGB(m_buf, m_width, m_height);
// vertical flip for display
JpegFile::VertFlipBuf(m_buf, m_width * 3, m_height);
}
////////////////////////////////////////////////////////////////////////////
// read a BMP to our global buffer
//
void CMfcappView::LoadBMP(CString fileName)
{
if (m_buf!=NULL) {
delete [] m_buf;
}
BMPFile theBmpFile;
m_buf=theBmpFile.LoadBMP(fileName, &m_width, &m_height);
if ((m_buf==NULL) || (theBmpFile.m_errorText!="OK")) {
AfxMessageBox(theBmpFile.m_errorText);
m_buf==NULL;
return;
}
//////////////////////
// set up for display
// do this before DWORD-alignment!!!
// this works on packed (not DWORD-aligned) buffers
// swap red and blue for display
JpegFile::BGRFromRGB(m_buf, m_width, m_height);
// vertical flip for display
JpegFile::VertFlipBuf(m_buf, m_width * 3, m_height);
}
////////////////////////////////////////////////////////////////////////////
//
// read a GIF to our global buffer
void CMfcappView::LoadGIF(CString filename)
{
if (m_buf!=NULL) {
delete [] m_buf;
m_buf=NULL;
}
GIFFile theGifThing;
// read the GIF to a packed buffer of RGB bytes
m_buf=theGifThing.GIFReadFileToRGB(filename,
&m_width,
&m_height);
if (m_buf==NULL) {
AfxMessageBox(theGifThing.m_GIFErrorText);
return;
}
//////////////////////
// set up for display
// do this before DWORD-alignment!!!
// swap red and blue for display
JpegFile::BGRFromRGB(m_buf, m_width, m_height);
// flip for display
JpegFile::VertFlipBuf(m_buf, m_width * 3, m_height);
}
////////////////////////////////////////////////////////////////////////////
// save functions are generally more complex than reading functions.
// there are many more decisions to be made for writing than for reading.
////////////////////////////////////////////////////////////////////////////
// save a JPG
void CMfcappView::SaveJPG(CString fileName, BOOL color)
{
// note, because i'm lazy, most image data in this app
// is handled as 24-bit images. this makes the DIB
// conversion easier. 1,4,8, 15/16 and 32 bit DIBs are
// significantly more difficult to handle.
if (m_buf==NULL) {
AfxMessageBox("No Image!");
return;
}
// we vertical flip for display. undo that.
JpegFile::VertFlipBuf(m_buf, m_width * 3, m_height);
// we swap red and blue for display, undo that.
JpegFile::BGRFromRGB(m_buf, m_width, m_height);
// save RGB packed buffer to JPG
BOOL ok=JpegFile::RGBToJpegFile(fileName,
m_buf,
m_width,
m_height,
color,
75); // quality value 1-100.
if (!ok) {
AfxMessageBox("Write Error");
} else {
// load what we just saved
LoadJPG(fileName);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -