API截屏模块,有代码

我看你有戏 2010-03-15 01:41:10

#include "stdio.h"
#include "windows.h"
/************************************************************************/
/* hBitmap 为刚才的屏幕位图句柄
/* lpFileName 为需要保存的位图文件名
/************************************************************************/
int SaveBitmapToFile(HBITMAP hBitmap,LPSTR lpFileName)
{
HDC hDC; //设备描述表
int iBits;//当前显示分辨率下每个像素所占字节数
WORD wBitCount;//位图中每个像素所占字节数
DWORD dwPaletteSize=0;//定义调色板大小
DWORD dwBmBitsSize;//位图中像素字节大小
DWORD dwDIBSize;// 位图文件大小
DWORD dwWritten;//写入文件字节数
BITMAP Bitmap;//位图结构
BITMAPFILEHEADER bmfHdr; //位图属性结构
BITMAPINFOHEADER bi; //位图文件头结构
LPBITMAPINFOHEADER lpbi; //位图信息头结构 指向位图信息头结构
HANDLE fh;//定义文件句柄
HANDLE hDib;//分配内存句柄
HANDLE hPal;//分配内存句柄
HANDLE hOldPal=NULL;//调色板句柄

//计算位图文件每个像素所占字节数
hDC = CreateDC("DISPLAY",NULL,NULL,NULL);
iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
DeleteDC(hDC);

if (iBits <= 1)
wBitCount = 1;
else if (iBits <= 4)
wBitCount = 4;
else if (iBits <= 8)
wBitCount = 8;
else if (iBits <= 24)
wBitCount = 24;
else if (iBits<=32)
wBitCount = 24;


//计算调色板大小
if (wBitCount <= 8)
dwPaletteSize = (1 << wBitCount) *sizeof(RGBQUAD);



//设置位图信息头结构
GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = Bitmap.bmWidth;
bi.biHeight = Bitmap.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
dwBmBitsSize = ((Bitmap.bmWidth *wBitCount+31)/32)* 4*Bitmap.bmHeight ;

//为位图内容分配内存
hDib = GlobalAlloc(GHND,dwBmBitsSize+dwPaletteSize+sizeof(BITMAPINFOHEADER));
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
if (lpbi==NULL)
{
return 0;
}

*lpbi = bi;
// 处理调色板
hPal = GetStockObject(DEFAULT_PALETTE);
if (hPal)
{
hDC = GetDC(NULL);
hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE);
RealizePalette(hDC);
}
// 获取该调色板下新的像素值
GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,
(LPSTR)lpbi + sizeof(BITMAPINFOHEADER)+dwPaletteSize,
(LPBITMAPINFO)lpbi, DIB_RGB_COLORS);
//恢复调色板
if (hOldPal)
{
SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
RealizePalette(hDC);
ReleaseDC(NULL, hDC);
}
//创建位图文件
fh = CreateFile(lpFileName, GENERIC_WRITE,
0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);

if (fh == INVALID_HANDLE_VALUE)
return FALSE;

// 设置位图文件头
bmfHdr.bfType = 0x4D42; // "BM"
dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+ dwPaletteSize + dwBmBitsSize;
bmfHdr.bfSize = dwDIBSize;
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER)+ dwPaletteSize;

// 写入位图文件头
WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);

// 写入位图文件其余内容
WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);

//清除
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(fh);

return 1;
}

HBITMAP GetCaptureBmp()
{
HDC hDC;
HDC MemDC;
BYTE* Data;
HBITMAP hBmp;
BITMAPINFO bi;

memset(&bi, 0, sizeof(bi));
bi.bmiHeader.biSize = sizeof(BITMAPINFO);
bi.bmiHeader.biWidth = GetSystemMetrics(SM_CXSCREEN);
bi.bmiHeader.biHeight = GetSystemMetrics(SM_CYSCREEN);
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 24;

hDC = GetDC(NULL);
MemDC = CreateCompatibleDC(hDC);
hBmp = CreateDIBSection(MemDC, &bi, DIB_RGB_COLORS, (void**)&Data, NULL, 0);
SelectObject(MemDC, hBmp);
BitBlt(MemDC, 0, 0, bi.bmiHeader.biWidth, bi.bmiHeader.biHeight,hDC, 0, 0, SRCCOPY);
ReleaseDC(NULL, hDC);
DeleteDC(MemDC);
return hBmp;
}


void main()
{
HBITMAP hBmp;
hBmp = GetCaptureBmp();
SaveBitmapToFile(hBmp,"c:\\11.bmp");
}



现在保存为11.bmp的文件很大

如何让这个文件保存为16位的啊,小一点,熟悉的朋友教一下小弟弟啊

...全文
1162 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2010-03-17
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 yuzl32 的回复:]
引用 8 楼 henry3695 的回复:
引用 6 楼 yuzl32 的回复:
LZ现在的问题应该是把BMP图片转换为JPG格式。



这一步我知道怎么做的,我现在就像先生成一个16位的图像,减少等下转换成jpg的成本

直接转换就可以了,你弄成16位并不能减少大小多少。

附:转换图片为PNG,才91KB(原先3601KB)

C/C++ code

#inclu……
[/Quote]
强!
zhao1zhong6 2010-03-15
  • 打赏
  • 举报
回复
总之有GDI+就好办多了.
可惜VC6.0用起来费劲啊!
findcsdn 2010-03-15
  • 打赏
  • 举报
回复
bi.bmiHeader.biBitCount = 24;

改成 16不就行了
yuzl32 2010-03-15
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 henry3695 的回复:]
引用 6 楼 yuzl32 的回复:
LZ现在的问题应该是把BMP图片转换为JPG格式。



这一步我知道怎么做的,我现在就像先生成一个16位的图像,减少等下转换成jpg的成本
[/Quote]
弄成16位的话,图片失真很厉害,看都看不清楚。
yuzl32 2010-03-15
  • 打赏
  • 举报
回复
转换为JPG为179KB.
yuzl32 2010-03-15
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 henry3695 的回复:]
引用 6 楼 yuzl32 的回复:
LZ现在的问题应该是把BMP图片转换为JPG格式。



这一步我知道怎么做的,我现在就像先生成一个16位的图像,减少等下转换成jpg的成本
[/Quote]
直接转换就可以了,你弄成16位并不能减少大小多少。

附:转换图片为PNG,才91KB(原先3601KB)

#include <windows.h>
#include <gdiplus.h>
#include <stdio.h>
using namespace Gdiplus;

#pragma comment(lib,"gdiplus")

int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes

ImageCodecInfo* pImageCodecInfo = NULL;

GetImageEncodersSize(&num, &size);
if(size == 0)
return -1; // Failure

pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if(pImageCodecInfo == NULL)
return -1; // Failure

GetImageEncoders(num, size, pImageCodecInfo);

for(UINT j = 0; j < num; ++j)
{
if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
{
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j; // Success
}
}

free(pImageCodecInfo);
return -1; // Failure
}

INT main()
{
// Initialize GDI+.
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

CLSID encoderClsid;
Status stat;
Image* image = new Image(L"f:\\11.bmp");

// Get the CLSID of the PNG encoder.
GetEncoderClsid(L"image/png", &encoderClsid);

stat = image->Save(L"11.png", &encoderClsid, NULL);

if(stat == Ok)
printf("Bird.png was saved successfully\n");
else
printf("Failure: stat = %d\n", stat);

delete image;
GdiplusShutdown(gdiplusToken);
return 0;
}
赵4老师 2010-03-15
  • 打赏
  • 举报
回复
也可以考虑保存后用system函数调用外部程序压缩或转换为jpg格式。
heguo2chao3 2010-03-15
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 henry3695 的回复:]
可否贴一下代码给我啊,谢谢
[/Quote]

if (iBits <= 1)
wBitCount = 1;
else if (iBits <= 4)
wBitCount = 4;
else if (iBits <= 8)
wBitCount = 8;
else if (iBits <= 24)
wBitCount = 24;
else if (iBits<=32)
wBitCount = 24;
直接换成
wBitCount=16即可!!
我看你有戏 2010-03-15
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 yuzl32 的回复:]
LZ现在的问题应该是把BMP图片转换为JPG格式。
[/Quote]


这一步我知道怎么做的,我现在就像先生成一个16位的图像,减少等下转换成jpg的成本
ayw215 2010-03-15
  • 打赏
  • 举报
回复
同意ls。。。。。。。。。。。。。。。。。。。
yuzl32 2010-03-15
  • 打赏
  • 举报
回复
LZ现在的问题应该是把BMP图片转换为JPG格式。
我看你有戏 2010-03-15
  • 打赏
  • 举报
回复
可否贴一下代码给我啊,谢谢
heguo2chao3 2010-03-15
  • 打赏
  • 举报
回复
修改文件头结构体中的相应信息即可
bmp位图信息头(40字节)
  BMP位图信息头数据用于说明位图的尺寸等信息。
  typedef struct tagBITMAPINFOHEADER{
  DWORD biSize; // 本结构所占用字节数(14-17字节)
  LONG biWidth; // 位图的宽度,以像素为单位(18-21字节)
  LONG biHeight; // 位图的高度,以像素为单位(22-25字节)
  WORD biPlanes; // 目标设备的级别,必须为1(26-27字节)
  WORD biBitCount;// 每个像素所需的位数,必须是1(双色),(28-29字节)
  // 4(16色),8(256色)或24(真彩色)之一

  DWORD biCompression; // 位图压缩类型,必须是 0(不压缩),(30-33字节)
  // 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
  DWORD biSizeImage; // 位图的大小,以字节为单位(34-37字节)
  LONG biXPelsPerMeter; // 位图水平分辨率,每米像素数(38-41字节)
  LONG biYPelsPerMeter; // 位图垂直分辨率,每米像素数(42-45字节)
  DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数(46-49字节)
  DWORD biClrImportant;// 位图显示过程中重要的颜色数(50-53字节)
  } BITMAPINFOHEADER;
GResume 2010-03-15
  • 打赏
  • 举报
回复
回复内容 回复内容太长了
GResume 2010-03-15
  • 打赏
  • 举报
回复
回复内容 回复内容太长了
yuzl32 2010-03-15
  • 打赏
  • 举报
回复
占位学习!

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧