打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
截屏保存为Jpg文件的MFC代码

上次讲到了最常见的C++截屏代码 ,有个问题一般bmp文件压缩率很低,一屏1024×768大概要好几M,根本无法传输,网上提供了很多种方案,最后找了jpglib集成到应用里,而且jpglib是开源项目,需要的朋友可以参考一下 ,时间仓促没做什么注释,下次再介绍一下这个抓到的文件http上传代码
//————– 捕捉 当前桌面 到jpg
void CEditBoxDlg::OnCapScreenJpg()
{
CDC dc,tdc;
CBitmap bm;
BITMAP btm;
BITMAPINFOHEADER bih;
BITMAPFILEHEADER bfh;
CString m_strTempBmp;
DWORD size;
LPSTR lpData;

int Width=GetSystemMetrics(SM_CXSCREEN);
int Height=GetSystemMetrics(SM_CYSCREEN);

dc.CreateDC(“DISPLAY”,NULL,NULL,NULL);
bm.CreateCompatibleBitmap(&dc,Width,Height);
tdc.CreateCompatibleDC(&dc);

CBitmap *pOld=tdc.SelectObject(&bm);
tdc.BitBlt(0,0,Width,Height,&dc,0,0,SRCCOPY);
tdc.SelectObject(pOld);
bm.GetBitmap(&btm);
size=btm.bmWidthBytes*btm.bmHeight;
lpData=(LPSTR)GlobalAlloc(GPTR,size);

bih.biBitCount=btm.bmBitsPixel;
bih.biClrImportant=0;
bih.biClrUsed=0;
bih.biCompression=0;
bih.biHeight=btm.bmHeight;
bih.biPlanes=1;
bih.biSize=sizeof(BITMAPINFOHEADER);
bih.biSizeImage=size;
bih.biWidth=btm.bmWidth;
bih.biXPelsPerMeter=0;
bih.biYPelsPerMeter=0;
GetDIBits(dc,bm,0,bih.biHeight,lpData,(BITMAPINFO*)&bih,DIB_RGB_COLORS);

bfh.bfReserved1=bfh.bfReserved2=0;
bfh.bfType=((WORD)(‘M’<< 8)|’B'); bfh.bfSize=54+size; bfh.bfOffBits=54; // Create logical palette if device support a palette CPalette pal; if( dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE ) { UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * 256); LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize]; pLP->palVersion = 0×300;

pLP->palNumEntries = GetSystemPaletteEntries( dc, 0, 255, pLP->palPalEntry );

// Create the palette
pal.CreatePalette( pLP );

delete[] pLP;
}

// Convert the bitmap to a DIB
HANDLE hDIB = DDBToDIB( bm, BI_RGB, &pal );
m_strTempBmp.Format(“%s%s”,”c:\\”,”temp11.jpg”);
CString strError;
JpegFromDib(hDIB, 100, m_strTempBmp, &strError);

// Free the memory allocated by DDBToDIB for the DIB
GlobalFree( hDIB );

/*
CFile bf;
if(bf.Open(m_strTempBmp,CFile::modeCreate|CFile::modeWrite))
{
bf.WriteHuge(&bfh,sizeof(BITMAPFILEHEADER));
bf.WriteHuge(&bih,sizeof(BITMAPINFOHEADER));
bf.WriteHuge(lpData,size);
bf.Close();
}*/
GlobalFree(lpData);

MessageBox(“save current screen to c:\\temp.bmp”);
}

// DDBToDIB – Creates a DIB from a DDB
// bitmap – Device dependent bitmap
// dwCompression – Type of compression – see BITMAPINFOHEADER
// pPal – Logical palette
HANDLE CEditBoxDlg::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; //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) /


* 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 CEditBoxDlg::JpegFromDib( HANDLE hDib, //Handle to DIB
int nQuality, //JPEG quality (0-100)
CString csJpeg, //Pathname to jpeg file
CString* pcsMsg) //Error msg to return
{
//Basic sanity checks…
if (nQuality < 0 || nQuality > 100 ||
hDib == NULL ||
pcsMsg == NULL ||
csJpeg == “”)
{
if (pcsMsg != NULL)
*pcsMsg = “Invalid input data”;

return FALSE;
}

*pcsMsg = “”;

byte *buf2 = 0;

//Use libjpeg functions to write scanlines to disk in JPEG format
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;

FILE* pOutFile; //Target file
int nSampsPerRow; //Physical row width in image buffer
JSAMPARRAY jsmpArray; //Pixel RGB buffer for JPEG file

cinfo.err = jpeg_std_error(&jerr); //Use default error handling (ugly!)

jpeg_create_compress(&cinfo);

if ((pOutFile = fopen(csJpeg, “wb”)) == NULL)
{
*pcsMsg = “Cannot open “;
*pcsMsg += csJpeg;
jpeg_destroy_compress(&cinfo);
return FALSE;
}

jpeg_stdio_dest(&cinfo, pOutFile);

LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)hDib;

cinfo.image_width = lpbi->biWidth; //Image width and height, in pixels
cinfo.image_height = lpbi->biHeight;
cinfo.input_components = 3; //Color components per pixel
//(RGB_PIXELSIZE – see jmorecfg.h)
cinfo.in_color_space = JCS_RGB; //Colorspace of input image

jpeg_set_defaults(&cinfo);

jpeg_set_quality(&cinfo,
nQuality, //Quality: 0-100 scale
TRUE); //Limit to baseline-JPEG values

jpeg_start_compress(&cinfo, TRUE);

//JSAMPLEs per row in output buffer
nSampsPerRow = cinfo.image_width * cinfo.input_components;

//Allocate array of pixel RGB values
jsmpArray = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo,
JPOOL_IMAGE,
nSampsPerRow,
cinfo.image_height);

if (DibToSamps(hDib,
nSampsPerRow,
cinfo,
jsmpArray,
pcsMsg))
{
//Write the array of scan lines to the JPEG file
(void)jpeg_write_scanlines(&cinfo,
jsmpArray,
cinfo.image_height);
}

jpeg_finish_compress(&cinfo); //Always finish

fclose(pOutFile);

jpeg_destroy_compress(&cinfo); //Free resources

if (*pcsMsg != “”)
return FALSE;

else
return TRUE;
}

////////////////////////////////////////////////////////////////
//This function fills a jsmpArray with the RGB values
//for the CBitmap.
//
//It has been improved to handle all legal bitmap formats.
//
//A jsmpArray is a big array of RGB values, 3 bytes per value.
//
//Note that rows of pixels are processed bottom to top:
//The data in the jsamp array must be arranged top to bottom.
////////////////////////////////////////////////////////////////
BOOL CEditBoxDlg::DibToSamps(HANDLE hDib,
int nSampsPerRow,
struct jpeg_compress_struct cinfo,
JSAMPARRAY jsmpPixels,
CString* pcsMsg)
{
//Sanity…
if (hDib == NULL ||
nSampsPerRow <= 0 || pcsMsg == NULL) { if (pcsMsg !=NULL) *pcsMsg=”Invalid input data”; return FALSE; } int r=0, p=0, q=0, b=0, n=0, nUnused=0, nBytesWide=0, nUsed=0, nLastBits=0, nLastNibs=0, nCTEntries=0, nRow=0, nByte=0, nPixel=0; BYTE bytCTEnt=0; LPBITMAPINFOHEADER pbBmHdr= (LPBITMAPINFOHEADER)hDib; //The bit count tells you the format of the bitmap: //Decide how many entries will be in the color table (if any) switch (pbBmHdr->biBitCount)
{
case 1:
nCTEntries = 2; //Monochrome
break;

case 4:
nCTEntries = 16; //16-color
break;

case 8:
nCTEntries = 256; //256-color
break;

case 16:
case 24:
case 32:
nCTEntries = 0; //No color table needed
break;

default:
*pcsMsg = “Invalid bitmap bit count”;
return FALSE; //Unsupported format
}

//Point to the color table and pixels
DWORD dwCTab = (DWORD)pbBmHdr + pbBmHdr->biSize;
LPRGBQUAD pCTab = (LPRGBQUAD)(dwCTab);
LPSTR lpBits = (LPSTR)pbBmHdr +
(WORD)pbBmHdr->biSize +
(WORD)(nCTEntries * sizeof(RGBQUAD));

//Different formats for the image bits
LPBYTE lpPixels = (LPBYTE) lpBits;
RGBQUAD* pRgbQs = (RGBQUAD*)lpBits;
WORD* wPixels = (WORD*) lpBits;

//Set up the jsamps according to the bitmap’s format.
//Note that rows are processed bottom to top, because
//that’s how bitmaps are created.
switch (pbBmHdr->biBitCount)
{
case 1:
nUsed = (pbBmHdr->biWidth + 7) / 8;
nUnused = (((nUsed + 3) / 4) * 4) – nUsed;
nBytesWide = nUsed + nUnused;
nLastBits = 8 – ((nUsed *

– pbBmHdr->biWidth);

for (r=0; r < pbBmHdr->biHeight; r++)
{
for (p=0, q=0; p < nUsed; p++) { nRow=(pbBmHdr->biHeight-r-1) * nBytesWide;
nByte = nRow + p;

int nBUsed = (p < (nUsed >> 1) ) ? 8 : nLastBits;
// ^^ Not sure about this symbol Might be problem
for(b=0; b < nBUsed;b++)
{
bytCTEnt = lpPixels[nByte] << b; bytCTEnt = bytCTEnt >> 7;

jsmpPixels[r][q+0] = pCTab[bytCTEnt].rgbRed;
jsmpPixels[r][q+1] = pCTab[bytCTEnt].rgbGreen;
jsmpPixels[r][q+2] = pCTab[bytCTEnt].rgbBlue;

q += 3;
}
}
}
break;

case 4:
nUsed = (pbBmHdr->biWidth + 1) / 2;
nUnused = (((nUsed + 3) / 4) * 4) – nUsed;
nBytesWide = nUsed + nUnused;
nLastNibs = 2 – ((nUsed * 2) – pbBmHdr->biWidth);

for (r=0; r < pbBmHdr->biHeight;r++)
{
for (p=0,q=0; p < nUsed;p++) { nRow=(pbBmHdr->biHeight-r-1) * nBytesWide;
nByte = nRow + p;

int nNibbles = (p >> (4- (n * 4)) );
// ^^ Not sure about this symbol. Might be problem.

jsmpPixels[r][q+0] = pCTab[bytCTEnt].rgbRed;
jsmpPixels[r][q+1] = pCTab[bytCTEnt].rgbGreen;
jsmpPixels[r][q+2] = pCTab[bytCTEnt].rgbBlue;

q += 3;
}
}
break;

default:
case 8: //Each byte is a pointer to a pixel color
nUnused = (((pbBmHdr->biWidth + 3) / 4) * 4) -
pbBmHdr->biWidth;

for (r=0;r < pbBmHdr->biHeight; r++)
{
for (p=0,q=0; p < pbBmHdr->biWidth; p++,q+=3)
{
nRow = (pbBmHdr->biHeight-r-1) * (pbBmHdr->biWidth + nUnused);
nPixel = nRow + p;

jsmpPixels[r][q+0] = pCTab[lpPixels[nPixel]].rgbRed;
jsmpPixels[r][q+1] = pCTab[lpPixels[nPixel]].rgbGreen;
jsmpPixels[r][q+2] = pCTab[lpPixels[nPixel]].rgbBlue;
}
}
break;

case 16: //Hi-color (16 bits per pixel)
for (r=0;r < pbBmHdr->biHeight; r++)
{
for (p=0,q=0; p < pbBmHdr->biWidth; p++,q+=3)
{
nRow = (pbBmHdr->biHeight-r-1) * pbBmHdr->biWidth;
nPixel = nRow + p;

RGBQUAD quad = QuadFromWord(wPixels[nPixel]);

jsmpPixels[r][q+0] = quad.rgbRed;
jsmpPixels[r][q+1] = quad.rgbGreen;
jsmpPixels[r][q+2] = quad.rgbBlue;
}
}
break;

case 24:
nBytesWide = (pbBmHdr->biWidth*3);
nUnused = (((nBytesWide + 3) / 4) * 4) -
nBytesWide;
nBytesWide += nUnused;

for (r=0; r < pbBmHdr->biHeight; r++)
{
for (p=0,q=0;p < (nBytesWide-nUnused); p+=3,q+=3) { nRow = (pbBmHdr->biHeight-r-1) * nBytesWide;
nPixel = nRow + p;

jsmpPixels[r][q+0] = lpPixels[nPixel+2]; //Red
jsmpPixels[r][q+1] = lpPixels[nPixel+1]; //Green
jsmpPixels[r][q+2] = lpPixels[nPixel+0]; //Blue
}
}
break;

case 32:
for (r=0; r < pbBmHdr->biHeight; r++)
{
for (p=0,q=0; p < pbBmHdr->biWidth; p++,q+=3)
{
nRow = (pbBmHdr->biHeight-r-1) *
pbBmHdr->biWidth;
nPixel = nRow + p;

jsmpPixels[r][q+0] = pRgbQs[nPixel].rgbRed;
jsmpPixels[r][q+1] = pRgbQs[nPixel].rgbGreen;
jsmpPixels[r][q+2] = pRgbQs[nPixel].rgbBlue;
}
}
break;
} //end switch

return TRUE;
}

////////////////////////////////////////
//This function turns a 16-bit pixel
//into an RGBQUAD value.
////////////////////////////////////////
RGBQUAD CEditBoxDlg::QuadFromWord(WORD b16)
{
BYTE bytVals[] =
{
0, 16, 24, 32, 40, 48, 56, 64,
72, 80, 88, 96, 104,112,120,128,
136,144,152,160,168,176,184,192,
200,208,216,224,232,240,248,255
};

WORD wR = b16;
WORD wG = b16;
WORD wB = b16;

wR <<= 1; wR >>= 11;
wG <<= 6; wG >>= 11;
wB <<= 11; wB >>= 11;

RGBQUAD rgb;

rgb.rgbReserved = 0;
rgb.rgbBlue = bytVals[wB];
rgb.rgbGreen = bytVals[wG];
rgb.rgbRed = bytVals[wR];

return rgb;
}

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
保存MFC的CBitmap对象中的图象到一个BMP文件中
vc 保存Bitmap到文件
DDB转为DIB
根据指定窗口句柄进行截屏
Visual C++ 实现数字图像增强处理
VC++图像处理编程 - LiteQ的日志 - 网易博客
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服