精华内容
下载资源
问答
  • 2021-12-09 22:10:54

    之前写过两篇ffmpeg录制桌面,读者可以翻看我的博客,但是都存在着问题,尤其当一个进程里面,自己创建几个线程干其他事情时,出错概率大大增加,

    ret = avcodec_send_frame(pCodecEncodeCtx_Video, pFrameYUV);
    if (ret == AVERROR(EAGAIN))
    {
    	continue;
    }
    
    ret = avcodec_receive_packet(pCodecEncodeCtx_Video, &packet);
    if (ret == AVERROR(EAGAIN))
    {
    	continue;
    }
    

    这是个编码的过程,其中avcodec_receive_packet的返回值经常是AVERROR(EAGAIN),而我源头是通过av_read_frame(pFormatCtx_Video, &packet)读取的视频帧,最终的结果导致视频里面的时间比实际录制的时间要短。

    这让我很头疼,无意中发现了一个人的博客,自己用gdi抓图,博客地址如下:
    https://blog.csdn.net/Donghui_Luo/article/details/88383313

    但是这篇博客存在着一点瑕疵,该博客设置帧率为15,我自己稍微修改了点代码,修改录制时间为1分钟,则最终发现,生成的mp4文件中的视频时长不止1分钟,大概在1分钟17秒的样子,经过分析,其抓图时,一秒钟不止抓15张,所以导致最终的时间大于1分钟。如果其线程得不到充分运行,比如一分钟才能抓5张,则对应的最终mp4的文件视频时长是20秒。

    所以需要自己控制抓图频率,线程性能太好,一秒钟抓的图片数量大于帧率时,需要适当的进行Sleep,如果线程性能太差,比如无论如何,也无法做到1秒钟抓15张,则可以降低编码器的帧率。

    为方便演示,本人将编码器的帧率设置为10,核心逻辑修改如下:

    DWORD dwBeginTime = ::GetTickCount();
    	for (;;)
    	{
    		BYTE* frameimage = ccs->CaptureImage();
    
    		RGB24_TO_YUV420(frameimage, width, height, outbuffer);
    		//Sframe->pkt_dts = frame->pts = frameNumber * avCodecCtx_Out->time_base.num * avStream->time_base.den / (avCodecCtx_Out->time_base.den *  avStream->time_base.num);
    		frame->pkt_dts = frame->pts = av_rescale_q_rnd(frameNumber, avCodecCtx_Out->time_base, avStream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
    		frame->pkt_duration = 0;
    		frame->pkt_pos = -1;
    
    		ret = avcodec_send_frame(avCodecCtx_Out, frame);
    		if (ret < 0)
    			continue;
    
    		ret = avcodec_receive_packet(avCodecCtx_Out, packet);
    		if (ret < 0)
    			continue;
    
    		static DWORD dwInitTime = ::GetTickCount();
    		if (packet->size > 0)
    		{
    			//av_packet_rescale_ts(packet, avCodecCtx_Out->time_base, avStream->time_base);
    			av_write_frame(avFormCtx_Out, packet);
    			frameNumber++;
    			printf("录入第%d帧....\n", frameNumber);
    		}
    
    		DWORD dwCurrentTime = ::GetTickCount();
    		if (dwCurrentTime - dwInitTime > 60000)
    		{
    			break;
    		}
    
    		int dwPassedMillSeconds = dwCurrentTime - dwBeginTime;
    		int dwDiff = frameNumber * 100 - dwPassedMillSeconds;
    		if (dwDiff > 0)
    		{
    			Sleep(dwDiff);
    		}
    	}
    

    本人在抓图开始前记录下时间dwBeginTime,然后每次抓图后,计算出从开始到现在的抓图时间dwPassedMillSeconds,因为帧率是10,所以理论上,每100毫秒抓取一张,dwDiff用于表示实际的时差。

    本人乐于直接将代码贴在博客内,便于本人日后查看。
    总共是3个文件,如下图所示:
    在这里插入图片描述
    现在本人依次粘贴它们的代码
    CaptureScreen.cpp代码如下:

    //#include "stdafx.h"
    #include "CaptureScreen.h"
    
    CCaptureScreen::CCaptureScreen(void)
    {
    	m_hdib = NULL;
    	m_hSavedCursor = NULL;
    	hScreenDC = NULL;
    	hMemDC = NULL;
    	hbm = NULL;
    	m_width = 1920;
    	m_height = 1080;
    	FetchCursorHandle();
    }
    //
    // 释放资源
    //
    CCaptureScreen::~CCaptureScreen(void)
    {
    	DeleteObject(hbm);
    	if (m_hdib){
    
    		free(m_hdib);
    		m_hdib = NULL;
    	}
    	if (hScreenDC){
    
    		::ReleaseDC(NULL, hScreenDC);
    	}
    	if (hMemDC) {
    
    		DeleteDC(hMemDC);
    	}
    	if (hbm)
    	{
    		DeleteObject(hbm);
    	}
    }
    
    //
    // 初始化
    //
    int CCaptureScreen::Init(int& src_VideoWidth, int& src_VideoHeight)
    {
    	hScreenDC = ::GetDC(GetDesktopWindow());
    	if (hScreenDC == NULL) return 0;
    
    	int m_nMaxxScreen = GetDeviceCaps(hScreenDC, HORZRES);
    	int m_nMaxyScreen = GetDeviceCaps(hScreenDC, VERTRES);
    
    	hMemDC = ::CreateCompatibleDC(hScreenDC);
    	if (hMemDC == NULL) return 0;
    
    	m_width = m_nMaxxScreen;
    	m_height = m_nMaxyScreen;
    
    	if (!m_hdib){
    		m_hdib = (PRGBTRIPLE)malloc(m_width * m_height * 3);//24位图像大小
    	}
    	//位图头信息结构体
    	pbi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    	pbi.bmiHeader.biWidth = m_width;
    	pbi.bmiHeader.biHeight = m_height;
    	pbi.bmiHeader.biPlanes = 1;
    	pbi.bmiHeader.biBitCount = 24;
    	pbi.bmiHeader.biCompression = BI_RGB;
    
    	src_VideoWidth = m_width;
    	src_VideoHeight = m_height;
    
    	hbm = CreateCompatibleBitmap(hScreenDC, m_width, m_height);
    	SelectObject(hMemDC, hbm);
    
    	wLineLen = ((m_width * 24 + 31) & 0xffffffe0) / 8;
    	wColSize = sizeof(RGBQUAD)* ((24 <= 8) ? 1 << 24 : 0);
    	dwSize = (DWORD)(UINT)wLineLen * (DWORD)(UINT)m_height;
    
    	return 1;
    }
    
    //抓取屏幕数据
    BYTE* CCaptureScreen::CaptureImage()
    {
    
    	VOID*  alpbi = CaptureScreenFrame(0, 0, m_width, m_height);
    	return (BYTE*)(alpbi);
    }
    
    void* CCaptureScreen::CaptureScreenFrame(int left, int top, int width, int height)
    {
    
    	if (hbm == NULL || hMemDC == NULL || hScreenDC == NULL) return NULL;
    
    	BitBlt(hMemDC, 0, 0, width, height, hScreenDC, left, top, SRCCOPY);
    	/*-------------------------捕获鼠标-------------------------------*/
    	{
    		POINT xPoint;
    		GetCursorPos(&xPoint);
    		HCURSOR hcur = FetchCursorHandle();
    		xPoint.x -= left;
    		xPoint.y -= top;
    
    		ICONINFO iconinfo;
    		BOOL ret;
    		ret = GetIconInfo(hcur, &iconinfo);
    		if (ret){
    			xPoint.x -= iconinfo.xHotspot;
    			xPoint.y -= iconinfo.yHotspot;
    
    			if (iconinfo.hbmMask) DeleteObject(iconinfo.hbmMask);
    			if (iconinfo.hbmColor) DeleteObject(iconinfo.hbmColor);
    		}
    		/*画鼠标*/
    		::DrawIcon(hMemDC, xPoint.x, xPoint.y, hcur);
    	}
    	//动态分配的内存
    	PRGBTRIPLE hdib = m_hdib;
    	if (!hdib)
    		return hdib;
    
    	GetDIBits(hMemDC, hbm, 0, m_height, hdib, (LPBITMAPINFO)&pbi, DIB_RGB_COLORS);
    	return hdib;
    }
    
    //
    // 获取窗体鼠标光标
    //
    HCURSOR CCaptureScreen::FetchCursorHandle()
    {
    	if (m_hSavedCursor == NULL)
    	{
    		m_hSavedCursor = GetCursor();
    	}
    	return m_hSavedCursor;
    }
    

    CaptureScreen.h的代码如下:

    #ifndef _CCAPTURE_SCREEN_HH
    #define _CCAPTURE_SCREEN_HH
    
    #include<time.h>
    #include <d3d9.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdarg.h>
    #include <windows.h>
    
    #include <tchar.h>
    #include <winbase.h>
    #include <winreg.h>
    #include <Strsafe.h>
    
    
    //
    // ---抓屏类----
    //
    class CCaptureScreen
    {
    public:
    	CCaptureScreen(void);
    	~CCaptureScreen(void);
    
    public:
    	/*-----------定义外部调用函数-----------*/
    	int Init(int&, int&);//初始化
    	BYTE* CaptureImage(); //抓取屏幕
    
    private:
    	/*-----------定义内部调用函数-----------*/
    	void* CaptureScreenFrame(int, int, int, int);//抓屏
    	HCURSOR FetchCursorHandle(); //获取鼠标光标
    
    private:
    	/*-----------定义私有变量-----------*/
    	int m_width;
    	int m_height;
    	UINT   wLineLen;
    	DWORD  dwSize;
    	DWORD  wColSize;
    
    	//设备句柄
    	HDC hScreenDC;
    	HDC hMemDC;
    	//图像RGB内存缓存
    	PRGBTRIPLE m_hdib;
    	//位图头信息结构体
    	BITMAPINFO pbi;
    
    	HBITMAP hbm;
    	//鼠标光标
    	HCURSOR m_hSavedCursor;
    
    
    };
    
    #endif //--_CCAPTURE_SCREEN_HH
    

    FfmpegVideoCaptureWithGdi.cpp的代码如下:

    // RecordingScreen.cpp : 定义控制台应用程序的入口点。
    //
    
    //#include "stdafx.h"
    #include "CaptureScreen.h"
    extern "C"
    {
    #include <libavutil/opt.h>
    #include <libavutil/mathematics.h>
    #include <libavutil\time.h>
    #include <libavformat/avformat.h>
    #include <libswscale/swscale.h>
    #include <libswresample/swresample.h>
    #include <libavutil/imgutils.h>
    #include <libavcodec/avcodec.h>
    #include <libavdevice\avdevice.h>
    
    #pragma comment(lib, "avcodec.lib")
    #pragma comment(lib, "avformat.lib")
    #pragma comment(lib, "avutil.lib")
    #pragma comment(lib, "avdevice.lib")
    #pragma comment(lib, "avfilter.lib")
    #pragma comment(lib, "postproc.lib")
    #pragma comment(lib, "swresample.lib")
    #pragma comment(lib, "swscale.lib")
    
    
    }
    //#include <ipp.h>
    #include <chrono>
    
    //signed int Bgr2YuvI420(const BYTE* srcBgr, int image_width, int image_height, BYTE* dstYuvI420)
    //{
    //	IppStatus ipp_status;
    //
    //	int srcStep = image_width * 3;
    //	int dstYStep = image_width;
    //	int dstCbCrStep = image_width;
    //	IppiSize roiSize = { image_width, image_height };
    //
    //	const Ipp8u* pSrc = (Ipp8u*)srcBgr;
    //
    //	Ipp8u *pDstY = (Ipp8u*)dstYuvI420;
    //	Ipp8u *pDstU = (Ipp8u*)&dstYuvI420[image_width * image_height];
    //	Ipp8u *pDstV = (Ipp8u*)&dstYuvI420[image_width * image_height * 5 / 4];
    //	Ipp8u *pDst[3];
    //	pDst[0] = pDstY;
    //	pDst[1] = pDstU;
    //	pDst[2] = pDstV;
    //	int dstStep[3] = { image_width, image_width / 2, image_width / 2 };
    //
    //	ipp_status = ippiBGRToYCbCr420_8u_C3P3R(pSrc, srcStep, pDst, dstStep, roiSize);
    //
    //	return ipp_status;
    //}
    
    
    unsigned char clip_value(unsigned char x, unsigned char min_val, unsigned char  max_val) {
    	if (x > max_val) {
    		return max_val;
    	}
    	else if (x < min_val) {
    		return min_val;
    	}
    	else {
    		return x;
    	}
    }
    
    //RGB to YUV420
    bool RGB24_TO_YUV420(unsigned char *RgbBuf, int w, int h, unsigned char *yuvBuf)
    {
    	unsigned char*ptrY, *ptrU, *ptrV, *ptrRGB;
    	memset(yuvBuf, 0, w*h * 3 / 2);
    	ptrY = yuvBuf;
    	ptrU = yuvBuf + w * h;
    	ptrV = ptrU + (w*h * 1 / 4);
    	unsigned char y, u, v, r, g, b;
    	for (int j = h - 1; j >= 0; j--) {
    		ptrRGB = RgbBuf + w * j * 3;
    		for (int i = 0; i < w; i++) {
    
    			b = *(ptrRGB++);
    			g = *(ptrRGB++);
    			r = *(ptrRGB++);
    
    
    			y = (unsigned char)((66 * r + 129 * g + 25 * b + 128) >> 8) + 16;
    			u = (unsigned char)((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128;
    			v = (unsigned char)((112 * r - 94 * g - 18 * b + 128) >> 8) + 128;
    			*(ptrY++) = clip_value(y, 0, 255);
    			if (j % 2 == 0 && i % 2 == 0) {
    				*(ptrU++) = clip_value(u, 0, 255);
    			}
    			else {
    				if (i % 2 == 0) {
    					*(ptrV++) = clip_value(v, 0, 255);
    				}
    			}
    		}
    	}
    	return true;
    }
    
    
    DWORD WINAPI ScreenCapThreadProc(LPVOID lpParam)
    {
    	CCaptureScreen* ccs = new CCaptureScreen();
    	int width = 0;
    	int height = 0;
    
    	ccs->Init(width, height);
    
    	AVFormatContext* avFormCtx_Out;
    	AVCodecContext*  avCodecCtx_Out;
    	AVCodec*  avCodec;
    	AVStream* avStream;
    	AVFrame* frame;
    	AVPacket* packet;
    
    	int frameRate = 10;
    	int ret = 0;
    	const char* filename = "out.mp4";
    
    	ret = avformat_alloc_output_context2(&avFormCtx_Out, NULL, NULL, filename);
    	if (ret < 0)
    	{
    		printf("Init avformat object is faild! \n");
    		return 0;
    	}
    
    	avCodec = (AVCodec *)avcodec_find_encoder(avFormCtx_Out->oformat->video_codec);
    	if (!avCodec)
    	{
    		printf("Init avCodec object is faild! \n");
    		return 0;
    	}
    
    	avCodecCtx_Out = avcodec_alloc_context3(avCodec);
    	if (!avCodecCtx_Out)
    	{
    		printf("Init avCodecCtx_Out object is faild! \n");
    		return 0;
    	}
    	avStream = avformat_new_stream(avFormCtx_Out, avCodec);
    	if (!avStream)
    	{
    		printf("Init avStream object is faild! \n");
    		return 0;
    	}
    
    	avCodecCtx_Out->flags |= AV_CODEC_FLAG_QSCALE;
    	avCodecCtx_Out->bit_rate = 4000000;
    	avCodecCtx_Out->rc_min_rate = 4000000;
    	avCodecCtx_Out->rc_max_rate = 4000000;
    	avCodecCtx_Out->bit_rate_tolerance = 4000000;
    	avCodecCtx_Out->time_base.den = frameRate;
    	avCodecCtx_Out->time_base.num = 1;
    
    	avCodecCtx_Out->width = width;
    	avCodecCtx_Out->height = height;
    	//pH264Encoder->pCodecCtx->frame_number = 1;
    	avCodecCtx_Out->gop_size = 12;
    	avCodecCtx_Out->max_b_frames = 0;
    	avCodecCtx_Out->thread_count = 4;
    	avCodecCtx_Out->pix_fmt = AV_PIX_FMT_YUV420P;
    	avCodecCtx_Out->codec_id = AV_CODEC_ID_H264;
    	avCodecCtx_Out->codec_type = AVMEDIA_TYPE_VIDEO;
    
    	av_opt_set(avCodecCtx_Out->priv_data, "b-pyramid", "none", 0);
    	av_opt_set(avCodecCtx_Out->priv_data, "preset", "superfast", 0);
    	av_opt_set(avCodecCtx_Out->priv_data, "tune", "zerolatency", 0);
    
    	if (avFormCtx_Out->oformat->flags & AVFMT_GLOBALHEADER)
    		avCodecCtx_Out->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
    
    	ret = avcodec_open2(avCodecCtx_Out, avCodec, NULL);
    	if (ret < 0)
    	{
    		printf("Open avcodec is faild! \n");
    		return 0;
    	}
    
    	avcodec_parameters_from_context(avStream->codecpar, avCodecCtx_Out);
    	if (!(avFormCtx_Out->oformat->flags & AVFMT_NOFILE))
    	{
    		ret = avio_open(&avFormCtx_Out->pb, filename, AVIO_FLAG_WRITE);
    		if (ret < 0)
    		{
    			printf("Open file is faild! \n");
    			return 0;
    		}
    	}
    	ret = avformat_write_header(avFormCtx_Out, NULL);
    	if (ret < 0)
    	{
    		printf("write header is faild! \n");
    		return 0;
    	}
    
    	frame = av_frame_alloc();
    	if (!frame)
    	{
    		printf("Init frame is faild! \n");
    		return 0;
    	}
    	frame->format = AV_PIX_FMT_YUV420P;
    	frame->width = width;
    	frame->height = height;
    
    	LONG64 frameSize = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, 1920, 1080, 1);
    	BYTE* outbuffer = new BYTE[frameSize];
    
    	ret = av_image_fill_arrays(frame->data,
    		frame->linesize,
    		outbuffer,
    		AV_PIX_FMT_YUV420P,
    		1920,
    		1080, 1);
    
    	if (ret < 0)
    	{
    		printf("av_image_fill_arrays is faild! \n");
    		return 0;
    	}
    	packet = av_packet_alloc();
    	//av_init_packet(packet);
    	if (!packet)
    	{
    		printf("packet is faild! \n");
    		return 0;
    	}
    
    	int frameNumber = 0;
    	int got_packet = 0;
    
    	DWORD dwBeginTime = ::GetTickCount();
    	for (;;)
    	{
    		BYTE* frameimage = ccs->CaptureImage();
    
    		RGB24_TO_YUV420(frameimage, width, height, outbuffer);
    		//Sframe->pkt_dts = frame->pts = frameNumber * avCodecCtx_Out->time_base.num * avStream->time_base.den / (avCodecCtx_Out->time_base.den *  avStream->time_base.num);
    		frame->pkt_dts = frame->pts = av_rescale_q_rnd(frameNumber, avCodecCtx_Out->time_base, avStream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
    		frame->pkt_duration = 0;
    		frame->pkt_pos = -1;
    
    		ret = avcodec_send_frame(avCodecCtx_Out, frame);
    		if (ret < 0)
    			continue;
    
    		ret = avcodec_receive_packet(avCodecCtx_Out, packet);
    		if (ret < 0)
    			continue;
    
    		static DWORD dwInitTime = ::GetTickCount();
    		if (packet->size > 0)
    		{
    			//av_packet_rescale_ts(packet, avCodecCtx_Out->time_base, avStream->time_base);
    			av_write_frame(avFormCtx_Out, packet);
    			frameNumber++;
    			printf("录入第%d帧....\n", frameNumber);
    		}
    
    		DWORD dwCurrentTime = ::GetTickCount();
    		if (dwCurrentTime - dwInitTime > 60000)
    		{
    			break;
    		}
    
    		int dwPassedMillSeconds = dwCurrentTime - dwBeginTime;
    		int dwDiff = frameNumber * 100 - dwPassedMillSeconds;
    		if (dwDiff > 0)
    		{
    			Sleep(dwDiff);
    		}
    	}
    	av_write_trailer(avFormCtx_Out);
    	avformat_free_context(avFormCtx_Out);
    	avcodec_close(avCodecCtx_Out);
    	avcodec_free_context(&avCodecCtx_Out);
    	av_free(avCodec);
    	av_packet_free(&packet);
    	av_frame_free(&frame);
    	return 0;
    }
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	//av_register_all();
    	//avformat_network_init();
    	avdevice_register_all();
    
    
    	HANDLE hThread = CreateThread(NULL, 0, ScreenCapThreadProc, 0, 0, NULL);
    	WaitForSingleObject(hThread, INFINITE);
    	return 0;
    }
    
    
    
    
    
    
    
    更多相关内容
  • 摘要:VB源码,网络相关,局域网抓图,截屏,抓屏 VB局域网抓图,局域网截屏、抓屏程序,很值得参考吧,可以学习一下屏幕抓图过程中使用的API函数都有哪些,本源码中给出了详细的函数及使用方法。再此注意,输入的计算机...
  • Delphi截屏,抓图抓屏程序,支持连续抓屏,效果不错,再完善一些,加入鼠标选框截图的功能,我想那就更完善了。PS注:本来想做网络抓屏,但似乎没准备好,就先做了这个本地抓屏的程序。
  • 易语言代码抓图工具

    2020-08-21 00:19:01
    易语言代码抓图工具源码系统结构:取代码编辑区和滚动条句柄,取易语言句柄,取窗口类名,取窗口标题,取滚动条最大值,取滚动条位置,置滚动条位置,刷新窗口显示,截取窗口位图,取要拼接
  • 抓屏工具 抓屏源码 捕捉屏幕 抓图工具 抓图源码
  • 抓屏服务器

    2018-09-11 16:25:47
    抓屏服务器是一款用于对本地PC机桌面图像进行编码的软件。支持通过网络的方式进行远程登录,取流。功能类似于一台IPC。
  • 网上找的大多只有实时预览 自己写了一个 功能包括 实时预览 截图 录像 按指定时间、通道号回放硬盘录像机上录像 截图 等 附件包含所需dll 请解压后放入同一目录
  • 本实例通过一个钩子DLL实现了屏幕抓图的功能,它有一个缺陷,那就是只能保存整个屏幕图像,不过可以在此基础上,实现屏幕任意区域的抓图功能.
  • 4.抓屏服务器.rar

    2020-03-09 11:45:14
    海康抓屏服务器,本机安装,实现桌面作为ipc可被添加预览,配合海康4200等软件使用。内含说明文档,免费使用
  • 抓图软件(淘宝天猫阿里)抓取 淘宝 天猫 阿里巴巴图片的工具 喜欢的自己下载
  • 海康摄像机实时预览与抓图的Demo,界面只有两个按钮,播放按钮和抓图按钮,代码简单有注释,非常适合海康API入门开发。并且程序顺带封装了海康C++API为.net方法(这个就不止目前下载的分数)。项目基于.net4.0 ,目标...
  • 海康威视SDK调用,登录、预览显示图像、抓图、车牌解析等功能! -DELPHI 源码精品 车牌解析:登录后,直接点击车牌解析即可。 预览显示图像:登陆后,直接点击显示图像即可。 ... ...
  • 内容索引:Delphi源码,图形处理,Capture.rar Delphi 全屏抓图、常规截屏,区域截图,活动窗口抓图代码,支持滚屏截图功能。截屏完毕,可打印,可保存为指定格式,可显示图片信息,代码可在delphi7中直接编译成功。源...
  • 大华摄像头抓图录像亲测可用
  • 主要介绍了linux下python抓屏实现方法,涉及Python操作屏幕截取的相关技巧,需要的朋友可以参考下
  • 抓图-crx插件

    2021-04-04 01:28:26
    抓图是一个神奇的AR工具,它能帮您把手机拍到的物体直观地放置到浏览器上 抓图能将图片中的主体,包括人、物品、场景等,进行智能抠图,并通过云端自动传送至您的浏览器上。需要您使用移动设备及应用配套使用,包括...
  • VC WINSOCK技术实现抓图及屏幕传输,捕获当前屏幕并保存到imagestream中,拷贝屏幕的指定区域到位图,将接收到的字符串分解为接收端口、色深、品质3个参数,捕获当前屏幕并保存到ImageStream中。这是一个例子程序,...
  • python 截图 抓图 源码

    2019-01-09 10:48:35
    python 截图 抓图 源码,支持快捷键截屏,自动保存,源码自由修改
  • 此分享的是我用了很多年的抓图软件,叫做抓图英雄,软件本身很小,每次工作中文档处理需要截图的时候用这个软件非常方便,可鼠标选取需要截图的区域,可以直接粘贴在office系列软件中,也可以另存为图片格式,兼容xp...
  • 抓图实用小程序,只是分享搬运,自己用过,比较好使 有需要用到的朋友可以下载试试 截图方便,功能足够满足一般的操作
  • 红蜻蜓抓图精灵2018

    2019-03-06 16:07:30
    红蜻蜓抓图精灵(RdfSnap) 是一款完全免费的专业级屏幕捕捉软件,能够让您得心应手地捕捉到需要的屏幕截图。捕捉图像方式灵活,主要可以捕捉整个屏幕、活动窗口、选定区域、固定区域、选定控件、选定菜单、选定网页等...
  • 淘宝天猫批量下载工具,正在联系原作者,本人只是搬运工。以前京东能用 现在京东不能用了! 不懂程序。有懂的可以改改啊!
  • C# 屏幕抓图 (图像操作)
  • 海康威视二次开发。布防,撤防,预览,抓图,录像,停止录像,入侵告警 演示地址: https://blog.csdn.net/weixin_39276851/article/details/110871893 开发环境:Vs2013+QT5.6.2
  • 布防,撤防,预览,抓图等 开发环境:Vs2013+QT5.6.2 摄像头:红外网络摄像头枪机,型号DS-2CD3T10D-13 Email:okjokull@gmail.com GitHub: https://github.com/okjokull/QHikvision/tree/master 演示地址: ...
  • FSCapture抓屏软件

    2018-06-05 13:09:46
    FSCapture :一个非常简单也非常方便的截图小软件,可以添加水平印,也可以对图像进行简单处理。很好用的。
  • 海康威视云台摄像仪DEMO,控制云台运动
  • VC 抓图程序,把屏幕上的显示的所有内容保存成图片,可以通过本程序以抓图的模式保存,有时候称为“屏幕捕捉”、“截屏”、“抓屏”,总之就是这一类程序,当然键盘上的PrtscSysRq键,也是可以完成抓屏功能的,只是...
  • 翻译自@啪啪啪么么哒 提供的源码 原帖地址: https://bbs.125.la/forum.php?mod=viewthreadtid=14196772

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 18,332
精华内容 7,332
关键字:

怎么抓屏