📄 mfcview.cpp
字号:
Invalidate(TRUE);
}
}
////////////////////////////////////////////////////////////////////////////
//
// save an 8-bit GIF from our 24-bit global buffer. this requires color
// quantization of some kind.
void CMfcappView::SaveGIF(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;
}
// get quantization params
CQuantDlg theDlg;
if (theDlg.DoModal()!=IDOK) {
return;
}
// convert from DIB orientation
JpegFile::VertFlipBuf(m_buf, m_width * 3, m_height);
// swap red and blue
JpegFile::BGRFromRGB(m_buf, m_width, m_height);
///////////////////////////////////////////////////////////////
// color quantization section - make an 8-bit image that looks like
// our 24-bit image...
// the palette
RGBQUAD RGBpal[256];
BYTE *colormappedBuffer;
// color or gray?
if (theDlg.m_color) {
// color !
// allocate a buffer to colormap to
colormappedBuffer = (BYTE *) new BYTE[m_width* m_height];
if (colormappedBuffer==NULL) {
AfxMessageBox("Alloc error in SaveGIF!");
return ;
}
BYTE tmpPal[3][256];
// colormap it
if (!dl1quant(m_buf, // input
colormappedBuffer, // output
m_width,
m_height,
theDlg.m_quantColors,
TRUE,
tmpPal)) {
AfxMessageBox("Quantization error");
delete [] colormappedBuffer;
return;
}
// copy our palette
for (UINT col=0;col<256;col++) {
if (col>theDlg.m_quantColors) {
RGBpal[col].rgbRed=0;
RGBpal[col].rgbBlue=0;
RGBpal[col].rgbGreen=0;
} else {
RGBpal[col].rgbRed=tmpPal[0][col];
RGBpal[col].rgbGreen=tmpPal[1][col];
RGBpal[col].rgbBlue=tmpPal[2][col];
}
}
} else {
// convert to 8-bit grayscale
colormappedBuffer = MakeColormappedGrayscale(m_buf, // RGB
(UINT)m_width, // pixels
(UINT)m_height,
(UINT)m_width * 3, // bytes
(UINT)256, // colors
RGBpal); // palette
}
if (colormappedBuffer==NULL) {
AfxMessageBox("Failed to make 256 color image");
return;
}
// figure out the palette entries
int red[256], blue[256], green[256];
for (int i=0;i<256;i++) {
red[i] = RGBpal[i].rgbRed;
green[i]= RGBpal[i].rgbGreen;
blue[i] = RGBpal[i].rgbBlue;
}
// write it
GIFFile theGifThing;
if (!theGifThing.GIFWriteFileFrom256Color(colormappedBuffer,
filename,
m_width,
m_height,
0, // background color
red, green, blue)) {
AfxMessageBox(theGifThing.m_GIFErrorText);
} else {
// load what we just saved
LoadGIF(filename);
Invalidate(TRUE);
}
if (colormappedBuffer!=NULL)
delete [] colormappedBuffer;
}
////////////////////////////////////////////////////////////////////////////
//
// 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);
}
}
////////////////////////////////////////////////////////////////////////////
//
// save a grayscaled image
void CMfcappView::OnFileSavegrayJPGas()
{
// 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);
}
}
////////////////////////////////////////////////////////////////////////////
//
// 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");
}
}
////////////////////////////////////////////////////////////////////////////
//
// save 1,4,8 bit BMP from our 24-bit global buffer
//
// if the user chooses 8-bits per pixel, we provide the option of using
// the color quantizer.
void CMfcappView::OnFileSavecolormappedbmp()
{
if (m_buf==NULL) {
AfxMessageBox("No Image!");
return;
}
////////////////////////////////////////////////////////////////////////
// get the filename
CString fileName;
CString filt="BMP (*.BMP)|*.BMP|All files (*.*)|*.*||";
// OPENFILENAME - so i can get to its Help page easily
CFileDialog fileDlg(FALSE,"*.BMP","*.BMP",NULL,filt,this);
fileDlg.m_ofn.Flags|=OFN_FILEMUSTEXIST;
fileDlg.m_ofn.lpstrTitle="File to save as";
if (fileDlg.DoModal()!=IDOK)
return;
fileName=fileDlg.GetPathName();
////////////////////////////////////////////////////////////////////////
// fetch bits per pixel
CBMPDlg theDlg;
if (theDlg.DoModal()!=IDOK)
return;
int bitsperpixel = theDlg.m_bits;
AfxGetApp()->DoWaitCursor(1);
////////////////////////////////////////////////////////////////////////
// prepare for color-mapping
// our palette
RGBQUAD colormap[256];
// num colors
int colors = (int)pow(2,bitsperpixel);
BYTE *colorMappedBuffer = NULL;
// if we can use the color quantizer, we will
if (bitsperpixel==8) {
CQuantDlg theDlg;
if (theDlg.DoModal()!=IDOK) {
return;
}
// color or grayscale?
if (theDlg.m_color) {
// color !
// allocate a buffer to colormap to
colorMappedBuffer = (BYTE *) new BYTE[m_width* m_height];
if (colorMappedBuffer==NULL) {
AfxMessageBox("Memory Error in OnSaveColormappedbmp!");
return;
}
BYTE tmpPal[3][256];
// colormap it
// generates an 8-bit color-mapped image into colorMappedBuffer
if (!dl1quant(m_buf,
colorMappedBuffer, // buffers
m_width,
m_height,
theDlg.m_quantColors,
TRUE,
tmpPal)) { // palette
AfxMessageBox("Quantization error");
delete [] colorMappedBuffer;
return;
}
// copy our palette
for (UINT col=0;col<256;col++) {
if (col>theDlg.m_quantColors) {
colormap[col].rgbRed=0;
colormap[col].rgbBlue=0;
colormap[col].rgbGreen=0;
} else {
colormap[col].rgbRed=tmpPal[0][col];
colormap[col].rgbGreen=tmpPal[1][col];
colormap[col].rgbBlue=tmpPal[2][col];
}
}
} else {
// gray :(
// convert to 8-bit colormapped grayscale
colorMappedBuffer = MakeColormappedGrayscale(m_buf, // RGB
(UINT)m_width, // pixels
(UINT)m_height,
(UINT)m_width * 3, // bytes
(UINT)colors, // colors
colormap); // palette
}
} else { // bitsperpixel!=8
// based on bitsperpixel, create a colormapped image
colorMappedBuffer = MakeColormappedGrayscale(m_buf,
(UINT)m_width,
(UINT)m_height,
(UINT)m_width * 3,
(UINT)colors,
colormap);
}
////////////////////////////////////////////////////////////////////////
// finally, save the thing
if (colorMappedBuffer!=NULL) {
// write the BMP using our colormapped image (one byte per pixel, packed),
// number of bits, number of total colors and a colormap
// pixel values must be in the range [0...colors-1]
BMPFile theBmpFile;
theBmpFile.SaveBMP(fileName, // path
colorMappedBuffer, // image
m_width, // pixels
m_height,
bitsperpixel, // 1,4,8
colors, // num colors
colormap); // palette
if (theBmpFile.m_errorText!="OK") {
AfxMessageBox(theBmpFile.m_errorText, MB_ICONSTOP);
}else {
// load what we just saved
LoadBMP(fileName);
Invalidate(TRUE);
}
// toss our buffer...
delete [] colorMappedBuffer;
} else {
AfxMessageBox("Failed to allocate space for RGB buffer");
}
AfxGetApp()->DoWaitCursor(-1);
}
////////////////////////////////////////////////////////////////////////
// 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 + -