各位兄弟姐妹,谁用c做过图象获取及处理,请进来看看,有分相送的哦!
我想用c实现的功能是:将当前屏幕进行拷贝,并且将图像的值(什么值,我不知道)转换成数组的形式,请问:我该怎么做?
我现有的c语言的树上都没有这方面的内容,就指望大家了。谢谢!!
问题点数:50、回复次数:30Top
1 楼pengzhenwanli(紫气日盈)回复于 2005-01-23 15:29:06 得分 0
一会给你说Top
2 楼maryruan(maryruan)回复于 2005-01-23 16:26:30 得分 0
To: pengzhenwanli(紫气日盈)
你在干吗?怎么还不来?谢谢先!!Top
3 楼xuelong_zl(点雨点[我身上咋就没MM的香水味涅??#-_-])回复于 2005-01-23 18:16:36 得分 0
不知道楼主看没看过<VC++图象处理>这本书,别外用MapInfo,MapGis一类的好像都是用VC++来做图像数据处理的,这方面书应该好找一些的,如果不是一定要用C,看看那些书可能对你有帮助
我没做过具体的,只能说这些了Top
4 楼maryruan(maryruan)回复于 2005-01-23 18:32:29 得分 0
To:xuelong_zl(磊)
谢谢你的提醒,不过不幸被你言中了,我只能用c。
不管怎么说,还是要谢谢你!!Top
5 楼YFY(天易)回复于 2005-01-23 19:22:45 得分 0
跨平台的吗?
可以使用 WinAPI 吗?
在什么环境下使用啊??
纯 C 好像没有见过 支持 这个艾~~Top
6 楼yuanqiongbo2002(玉斑指)回复于 2005-01-23 19:41:31 得分 0
在tc下有一个<graphics.h>的头文件.是关于图像处理的Top
7 楼yuanqiongbo2002(玉斑指)回复于 2005-01-23 19:42:21 得分 0
我当年用过.Top
8 楼really168(苦涩的泪水)回复于 2005-01-23 20:05:22 得分 0
问一下,一般的编译器里找不到graphics.h这个头文件怎么办啊,谁能给点解决办法啊Top
9 楼yuanqiongbo2002(玉斑指)回复于 2005-01-23 20:26:10 得分 0
不同的编译器有不同的头文件.vc中好像是gl.h
graphics.h是16位c中的它有其lib库支持.不能在32位编译器中使用.
能不能在其它非tc环境的16位编译器中使用,还没试过.Top
10 楼pengzhenwanli(紫气日盈)回复于 2005-01-23 22:32:16 得分 0
太忙了。刚过来。不好意思。
关于图像处理的问题,如果要是单纯的处理比较简单。
但是如果要是显示的话,就牵扯到具体的平台了。
你从屏幕截图。应该使用系统的API.
这个依赖于具体的平台。你没有说。
如果你知道了具体的平台。根据API返回的图像格式。
标准的BMP有标准的文件格式。找那个文件格式读出来就行了。
把每个象素保存到数组中就好了。
其实只读出来就好了。这样就有一个数据的指针了。
Top
11 楼yuanqiongbo2002(玉斑指)回复于 2005-01-23 23:11:19 得分 0
void far getimage(int xl,int yl, int x2,int y2, void far *mapbuf);
void far putimge(int x,int,y,void * mapbuf, int op);
unsined far imagesize(int xl,int yl,int x2,int y2);
这三个函数用于将屏幕上的图像复制到内存,然后再将内存中的图像送回到
屏幕上。首先通过函数imagesize()测试要保存左上角为(xl,yl), 右上角为(x2,
y2)的图形屏幕区域内的全部内容需多少个字节, 然后再给mapbuf 分配一个所测
数字节内存空间的指针。通过调用getimage()函数就可将该区域内的图像保存在
内存中, 需要时可用putimage()函数将该图像输出到左上角为点(x, y)的位置上,
其中getimage()函数中的参数op规定如何释放内存中图像。
Top
12 楼dayforever(小胖)回复于 2005-01-24 13:47:29 得分 0
HDC GetDC(
HWND hWnd // handle to window //If this value is NULL, GetDC retrieves the DC for the entire screen.
);
BOOL BitBlt(
HDC hdcDest, // handle to destination DC
int nXDest, // x-coord of destination upper-left corner
int nYDest, // y-coord of destination upper-left corner
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
HDC hdcSrc, // handle to source DC
int nXSrc, // x-coordinate of source upper-left corner
int nYSrc, // y-coordinate of source upper-left corner
DWORD dwRop // raster operation code
);
HBITMAP和HDC互换,以上为APITop
13 楼maryruan(maryruan)回复于 2005-01-24 15:03:51 得分 0
to:大家
谢谢大家这么热心。:)
To: pengzhenwanli(紫气日盈)
你从屏幕截图。应该使用系统的API.
这个依赖于具体的平台。
如果你知道了具体的平台。根据API返回的图像格式。
标准的BMP有标准的文件格式。找那个文件格式读出来就行了。
把每个象素保存到数组中就好了。
------------------------------------------------------------
我用到的平台是windowsXP。是不是不同的平台,屏幕截取的图像是不同的格式,那么XP是什么格式?
(希望是jpeg格式)。
例外,得到象素的数组,如何在江该图象显示呢。因为我要做的是传输图象。
to: yuanqiongbo2002(玉斑指) (
void far getimage(int xl,int yl, int x2,int y2, void far *mapbuf);
void far putimge(int x,int,y,void * mapbuf, int op);
unsined far imagesize(int xl,int yl,int x2,int y2);
这三个函数用于将屏幕上的图像复制到内存,然后再将内存中的图像送回到
屏幕上。首先通过函数imagesize()测试要保存左上角为(xl,yl), 右上角为(x2,
y2)的图形屏幕区域内的全部内容需多少个字节, 然后再给mapbuf 分配一个所测
数字节内存空间的指针。通过调用getimage()函数就可将该区域内的图像保存在
内存中, 需要时可用putimage()函数将该图像输出到左上角为点(x, y)的位置上,
其中getimage()函数中的参数op规定如何释放内存中图像。
------------------------------------
我似乎明白了。我想知道的是:内存里边是图象的什么数值,可以得到吗?如果我要将这些数值传给其他应用程序显示图象的话,应该怎么做?谢谢你。
Top
14 楼yuanqiongbo2002(玉斑指)回复于 2005-01-24 17:55:04 得分 0
首先:你的程序的编译平台是什么?
是32位的话:可以用windows的图形API来处理,通过dde来和其它的程序共享.
如果是16位的话:在tc环境下,可以用我给的三个函数来处理,在该环境下,图像是256色的.void far *mapbuf 其实是个指向大小为imagesize 的一块内存.每一个图像点是一个字节.可以把它写到一个文件
中,在另一程序中打开就行了.Top
15 楼milozy1983(Detective)回复于 2005-01-24 18:21:57 得分 0
Pixel = getpixel( x , y );Top
16 楼coyprightbao(Mr'Bao)回复于 2005-01-24 18:53:09 得分 0
mark!Top
17 楼pengzhenwanli(紫气日盈)回复于 2005-01-24 23:06:51 得分 0
这个。
windows的话。用API
HBITMAP CopyScreenToBitmap(LPRECT lpRect)
//lpRect 代表选定区域
{
HDC hScrDC, hMemDC;
// 屏幕和内存设备描述表
HBITMAP hBitmap, hOldBitmap;
// 位图句柄
int nX, nY, nX2, nY2;
// 选定区域坐标
int nWidth, nHeight;
// 位图宽度和高度
int xScrn, yScrn;
// 屏幕分辨率
// 确保选定区域不为空矩形
if (IsRectEmpty(lpRect))
return NULL;
//为屏幕创建设备描述表
hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
//为屏幕设备描述表创建兼容的内存设备描述表
hMemDC = CreateCompatibleDC(hScrDC);
// 获得选定区域坐标
nX = lpRect- >left;
nY = lpRect- >top;
nX2 = lpRect- >right;
nY2 = lpRect- >bottom;
// 获得屏幕分辨率
xScrn = GetDeviceCaps(hScrDC, HORZRES);
yScrn = GetDeviceCaps(hScrDC, VERTRES);
//确保选定区域是可见的
if (nX < 0)
nX = 0;
if (nY < 0)
nY = 0;
if (nX2 > xScrn)
nX2 = xScrn;
if (nY2 > yScrn)
nY2 = yScrn;
nWidth = nX2 - nX;
nHeight = nY2 - nY;
// 创建一个与屏幕设备描述表兼容的位图
hBitmap = CreateCompatibleBitmap
(hScrDC, nWidth, nHeight);
// 把新位图选到内存设备描述表中
hOldBitmap = SelectObject(hMemDC, hBitmap);
// 把屏幕设备描述表拷贝到内存设备描述表中
BitBlt(hMemDC, 0, 0, nWidth, nHeight,
hScrDC, nX, nY, SRCCOPY);
//得到屏幕位图的句柄
hBitmap = SelectObject(hMemDC, hOldBitmap);
//清除
DeleteDC(hScrDC);
DeleteDC(hMemDC);
// 返回位图句柄
return hBitmap;
}
得到屏幕位图句柄以后,我们
可以把屏幕内容粘贴到剪贴板上.
if (OpenClipboard(hWnd))
//hWnd为程序窗口句柄
{
//清空剪贴板
EmptyClipboard();
//把屏幕内容粘贴到剪贴板上,
hBitmap 为刚才的屏幕位图句柄
SetClipboardData(CF_BITMAP, hBitmap);
//关闭剪贴板
CloseClipboard();
}
我们也可以把屏幕内容以位图格式存到磁盘文件上.
int SaveBitmapToFile(HBITMAP hBitmap ,
LPSTR lpFileName) //hBitmap 为刚才的屏幕位图句柄
{ //lpFileName 为位图文件名
HDC hDC;
//设备描述表
int iBits;
//当前显示分辨率下每个像素所占字节数
WORD wBitCount;
//位图中每个像素所占字节数
//定义调色板大小, 位图中像素字节大小 ,
位图文件大小 , 写入文件字节数
DWORD dwPaletteSize=0,
dwBmBitsSize,
dwDIBSize, dwWritten;
BITMAP Bitmap;
//位图属性结构
BITMAPFILEHEADER bmfHdr;
//位图文件头结构
BITMAPINFOHEADER bi;
//位图信息头结构
LPBITMAPINFOHEADER lpbi;
//指向位图信息头结构
HANDLE fh, hDib, hPal,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;
//计算调色板大小
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);
*lpbi = bi;
// 处理调色板
hPal = GetStockObject(DEFAULT_PALETTE);
if (hPal)
{
hDC = GetDC(NULL);
hOldPal = SelectPalette(hDC, hPal, FALSE);
RealizePalette(hDC);
}
// 获取该调色板下新的像素值
GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,
(LPSTR)lpbi + sizeof(BITMAPINFOHEADER)
+dwPaletteSize,
(BITMAPINFOHEADER *)
lpbi, DIB_RGB_COLORS);
//恢复调色板
if (hOldPal)
{
SelectPalette(hDC, 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);
}Top
18 楼pengzhenwanli(紫气日盈)回复于 2005-01-24 23:08:19 得分 0
应该好用了。
具体的看情况了Top
19 楼xuelong_zl(点雨点[我身上咋就没MM的香水味涅??#-_-])回复于 2005-01-25 08:25:49 得分 0
to pengzhenwanli(紫气日盈)
服了u,不但热心,技术也厉害Top
20 楼sadsword(sadsword)回复于 2005-01-25 15:01:21 得分 0
markTop
21 楼maryruan(maryruan)回复于 2005-01-25 20:30:37 得分 0
To:pengzhenwanli(紫气日盈)
谢谢你,真的好感动!:)
但是,我有一个疑问:xp下截屏得到的只能是位图文件吗?(bmp),而且这个文件会占用多少内存呢?
我会先试试,同时,十分想要你的邮箱。以后多多指教!谢谢谢谢.......Top
22 楼maryruan(maryruan)回复于 2005-01-25 20:35:33 得分 0
To: yuanqiongbo2002(玉斑指)
我用的是XP,应该是32位平台,这样的话还可以用你给的函数吗?
另外,我不能用到DDE,因为我的图像将要通过网络传到另一台机器上。
帮我再想想办法吧,谢谢谢谢........
另外,可以给你的邮箱吗,我的是maryruan.student@sina.com
Top
23 楼pengzhenwanli(紫气日盈)回复于 2005-01-25 21:19:19 得分 0
一定是BMP的。
大小比如说1024X768
1024X768X3基本上就是这么多字节。
大概2M多。
Top
24 楼yuanqiongbo2002(玉斑指)回复于 2005-01-25 21:48:16 得分 0
to 楼主,不能用.只能在16位的编译器上用.
我有jpeg的压缩代码.Top
25 楼kent5566(火星猪)回复于 2005-01-26 10:44:56 得分 0
厉害!学习。。。Top
26 楼maryruan(maryruan)回复于 2005-01-26 11:00:49 得分 0
To: yuanqiongbo2002(玉斑指)
to 楼主,不能用.只能在16位的编译器上用.
我有jpeg的压缩代码.
--------------------------------------
那我怎么实现截屏呢?另外.........
我可以拿到你的jpeg的压缩代码吗?谢谢!
Top
27 楼maryruan(maryruan)回复于 2005-01-26 11:04:23 得分 0
To:pengzhenwanli(紫气日盈)
那这个数组也太大了,我要实现的还是隔一段时间截一次,那.......怎么办?还得编码压缩吧?
怎么办?Top
28 楼pengzhenwanli(紫气日盈)回复于 2005-01-26 21:36:47 得分 40
不算大啊。2M的还大啊?
不过传输的时候最好还是压缩一下。这方面有现成的,你搜一下吧。
jTop
29 楼yuanqiongbo2002(玉斑指)回复于 2005-01-26 23:25:53 得分 10
如果图像要求不是太高的话,
可以把长和宽等分,均匀的取其中的一半,这样就压缩了1/4.就500k左右.
由于图像是每隔一段时间截一次的,图像变化不是很大.
这样可以把图像分成n个区域,保存最新的一次图像,然后每截一次,各个区域
同对应区域上一次的结果比较,不同则替换并发送.Top
30 楼maryruan(maryruan)回复于 2005-01-29 09:40:32 得分 0
了解,我先试试。
另外,我要放假回家了,先揭帖吧。如果有了新问题,还请各位大侠继续支持,在这里先谢了,顺便祝各位新年快乐!新年心想事成!!
...揭帖送分!Top




