📄 mfcappview.cpp
字号:
}
AfxGetApp()->DoWaitCursor(-1);
}
void CMfcAppView::OnFileSavegrayas()
{
// 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.
CString fileName;
CString filt="JPG File (*.JPG)|*.JPG|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 grayscale";
if (fileDlg.DoModal()==IDOK) {
fileName=fileDlg.GetPathName();
AfxGetApp()->DoWaitCursor(1);
CString ext;
ext=fileName.Right(4);
if (!ext.CompareNoCase(".JPG"))
SaveJPG(fileName,FALSE);
AfxGetApp()->DoWaitCursor(-1);
}
}
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
int left = max(clientRect.left, ((clientRect.Width() - (int)m_width) / 2));
int top = max(clientRect.top, ((clientRect.Height() - (int)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);
}
}
////////////////////////////////////////////////////////////////////////////
// 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);
}
////////////////////////////////////////////////////////////////////////////
// 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);
Invalidate(TRUE);
}
}
////////////////////////////////////////////////////////////////////////////
//
// use the BMPFile class to write a 24-bit BMP file
//
void CMfcAppView::SaveBMP24(CString filename)
{
// 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;
}
// image in m_buf is already BGR and vertically flipped, so we don't need
// to do that for this function.
// i really should make an RGB to BMP fn.
BMPFile theBmpFile;
theBmpFile.SaveBMP(filename,
m_buf,
m_width,
m_height);
if (theBmpFile.m_errorText!="OK")
AfxMessageBox(theBmpFile.m_errorText, MB_ICONSTOP);
else {
// load what we just saved
LoadBMP(filename);
Invalidate(TRUE);
}
}
// get JPG dimensions
void CMfcAppView::OnFileGetdimensionsjpg()
{
CString fileName;
CString filt="JPG File (*.JPG)|*.JPG|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 examine";
if (fileDlg.DoModal()==IDOK) {
fileName=fileDlg.GetPathName();
UINT width, height;
if (JpegFile::GetJPGDimensions(fileName,
&width,
&height)) {
char buf[200];
sprintf(buf,"%d %d",width,height);
AfxMessageBox(buf);
} else
AfxMessageBox("JPEG Error");
}
}
////////////////////////////////////////////////////////////////////////
// instead of creating a good palette for the colormapped images
// this just graymaps them.
//
BYTE * CMfcAppView::MakeColormappedGrayscale(BYTE *inBuf,
UINT inWidth,
UINT inHeight,
UINT inWidthBytes,
UINT colors,
RGBQUAD* colormap)
{
////////////////////////////////////////////////////////////////////////
// allocate a buffer to colormap
BYTE *tmp = (BYTE *) new BYTE[inWidth * inHeight];
if (tmp==NULL)
return NULL;
// force our image to use a stupid gray scale
UINT color;
for (color = 0;color < colors; color++) {
colormap[color].rgbRed = color * 256 / colors;
colormap[color].rgbGreen = color * 256 / colors;
colormap[color].rgbBlue = color * 256 / colors;
}
UINT col, row;
for (row =0; row < inHeight; row++) {
for (col=0;col <inWidth; col++) {
BYTE inRed, inBlue, inGreen;
// src pixel
long in_offset = row * inWidthBytes + col * 3;
inRed = *(inBuf + in_offset + 0);
inGreen = *(inBuf + in_offset + 1);
inBlue = *(inBuf + in_offset + 2);
// luminance
int lum = (int)(.299 * (double)(inRed) +
.587 * (double)(inGreen) +
.114 * (double)(inBlue));
// force luminance value into our range of colors
lum = colors * lum / 256;
// dest pixel
long out_offset = row * inWidth + col;
*(tmp+out_offset) = (BYTE)lum;
}
}
return tmp;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -