ScreenToGif

ScreenToGif允许您记录屏幕的选定区域、网络摄像头的实时信息或素描板上的实时绘图。之后,您可以编辑动画并将其保存为 gif、apng、视频、psd 或 png 图像。

ScreenToGif在github下的地址在这里。

功能介绍:

  • 1.记录你的屏幕,并直接保存到一个GIF动画的环形。

  • 2.暂停和继续记录。

  • 3.移动窗口来记录你想要的。

  • 4.您可以添加文字,字幕和标题框。

  • 5.编辑框,添加过滤器,还原,做优悠风格,斯洛伐克运动,加边框。

  • 6.导出帧。

  • 7.作物和调整。

  • 8.你可以工作,即使在节目录制。

  • 9.删除你不想要的帧。

  • 10.选择一个文件夹,自动保存文件或选择一个enconding之前。

ScreenToGif也比较简单,主要的有两个功能,一个是录取屏幕一个是录取摄像头的视频。


还有一个白板的功能,也是挺好玩的:

主要代码分析

获取摄像头的数据:

protected void CreateGraph(){//Skip if already createdif ((int)ActualGraphState < (int)GraphState.Created){//Make a new filter graph.GraphBuilder = (ExtendStreaming.IGraphBuilder)Activator.CreateInstance(Type.GetTypeFromCLSID(Uuid.Clsid.FilterGraph, true));//Get the Capture Graph Builder.var clsid = Uuid.Clsid.CaptureGraphBuilder2;var riid = typeof(ExtendStreaming.ICaptureGraphBuilder2).GUID;CaptureGraphBuilder = (ExtendStreaming.ICaptureGraphBuilder2)Activator.CreateInstance(Type.GetTypeFromCLSID(clsid, true));//Link the CaptureGraphBuilder to the filter graphvar hr = CaptureGraphBuilder.SetFiltergraph(GraphBuilder);if (hr < 0)Marshal.ThrowExceptionForHR(hr);var comType = Type.GetTypeFromCLSID(Uuid.Clsid.SampleGrabber);if (comType == null)throw new Exception("DirectShow SampleGrabber not installed/registered!");var comObj = Activator.CreateInstance(comType);SampGrabber = (EditStreaming.ISampleGrabber)comObj; comObj = null;_baseGrabFlt = (CoreStreaming.IBaseFilter) SampGrabber;var media = new CoreStreaming.AmMediaType();//Get the video device and add it to the filter graphif (VideoDevice != null){VideoDeviceFilter = (CoreStreaming.IBaseFilter)Marshal.BindToMoniker(VideoDevice.MonikerString);hr = GraphBuilder.AddFilter(VideoDeviceFilter, "Video Capture Device");if (hr < 0)Marshal.ThrowExceptionForHR(hr);media.majorType = Uuid.MediaType.Video;media.subType = Uuid.MediaSubType.RGB32;//RGB24;media.formatType = Uuid.FormatType.VideoInfo;media.temporalCompression = true; //Newhr = SampGrabber.SetMediaType(media);if (hr < 0)Marshal.ThrowExceptionForHR(hr);hr = GraphBuilder.AddFilter(_baseGrabFlt, "Grabber");if (hr < 0)Marshal.ThrowExceptionForHR(hr);}// Retrieve the stream control interface for the video device// FindInterface will also add any required filters// (WDM devices in particular may need additional// upstream filters to function).// Try looking for an interleaved media typeobject o;var cat = Uuid.PinCategory.Capture;var med = Uuid.MediaType.Interleaved;var iid = typeof(ExtendStreaming.IAMStreamConfig).GUID;hr = CaptureGraphBuilder.FindInterface(cat, med, VideoDeviceFilter, iid, out o);if (hr != 0){// If not found, try looking for a video media typemed = Uuid.MediaType.Video;hr = CaptureGraphBuilder.FindInterface(cat, med, VideoDeviceFilter, iid, out o);if (hr != 0)o = null;}VideoStreamConfig = o as ExtendStreaming.IAMStreamConfig;// Retrieve the media control interface (for starting/stopping graph)MediaControl = (ControlStreaming.IMediaControl)GraphBuilder;// Reload any video crossbars//if (videoSources != null) videoSources.Dispose(); videoSources = null;_videoInfoHeader = (EditStreaming.VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, typeof(EditStreaming.VideoInfoHeader));Marshal.FreeCoTaskMem(media.formatPtr); media.formatPtr = IntPtr.Zero;hr = SampGrabber.SetBufferSamples(false);if (hr == 0)hr = SampGrabber.SetOneShot(false);if (hr == 0)hr = SampGrabber.SetCallback(null, 0);if (hr < 0)Marshal.ThrowExceptionForHR(hr);}//Update the state now that we are done.ActualGraphState = GraphState.Created;}

每一帧的数据:

public Bitmap GetFrame(){//TODO: Verify any possible leaks.//Asks for the buffer size.var bufferSize = 0;SampGrabber.GetCurrentBuffer(ref bufferSize, IntPtr.Zero);//Allocs the byte array.var handleObj = GCHandle.Alloc(_savedArray, GCHandleType.Pinned);//Gets the address of the pinned object.var address = handleObj.AddrOfPinnedObject();//Puts the buffer inside the byte array.SampGrabber.GetCurrentBuffer(ref bufferSize, address);//Image size.var width = _videoInfoHeader.BmiHeader.Width;var height = _videoInfoHeader.BmiHeader.Height;var stride = width * 3;//address += (height - 1) * stride;address += height * stride;var bitmap = new Bitmap(width, height, -stride, System.Drawing.Imaging.PixelFormat.Format24bppRgb, address);handleObj.Free();return bitmap;}

截取屏幕:

public override int Capture(FrameInfo frame){var res = new Result(-1);var wasCaptured = false;try{//Try to get the duplicated output frame within given time.res = DuplicatedOutput.TryAcquireNextFrame(0, out var info, out var resource);if (res.Failure || resource == null || info.TotalMetadataBufferSize == 0){//Somehow, it was not possible to retrieve the resource, frame or metadata.resource?.Dispose();return FrameCount;}#region Process changes//Copy resource into memory that can be accessed by the CPU.using (var screenTexture = resource.QueryInterface<Texture2D>()){#region Moved rectanglesvar movedRectangles = new OutputDuplicateMoveRectangle[info.TotalMetadataBufferSize];DuplicatedOutput.GetFrameMoveRects(movedRectangles.Length, movedRectangles, out var movedRegionsLength);for (var movedIndex = 0; movedIndex < movedRegionsLength / Marshal.SizeOf(typeof(OutputDuplicateMoveRectangle)); movedIndex++){//Crop the destination rectangle to the scree area rectangle.var left = Math.Max(movedRectangles[movedIndex].DestinationRect.Left, Left);var right = Math.Min(movedRectangles[movedIndex].DestinationRect.Right, Left + Width);var top = Math.Max(movedRectangles[movedIndex].DestinationRect.Top, Top);var bottom = Math.Min(movedRectangles[movedIndex].DestinationRect.Bottom, Top + Height);//Copies from the screen texture only the area which the user wants to capture.if (right > left && bottom > top){//Limit the source rectangle to the available size within the destination rectangle.var sourceWidth = movedRectangles[movedIndex].SourcePoint.X + (right - left);var sourceHeight = movedRectangles[movedIndex].SourcePoint.Y + (bottom - top);Device.ImmediateContext.CopySubresourceRegion(screenTexture, 0, new ResourceRegion(movedRectangles[movedIndex].SourcePoint.X, movedRectangles[movedIndex].SourcePoint.Y, 0, sourceWidth, sourceHeight, 1),StagingTexture, 0, left - Left, top - Top);wasCaptured = true;}}#endregion#region Dirty rectanglesvar dirtyRectangles = new RawRectangle[info.TotalMetadataBufferSize];DuplicatedOutput.GetFrameDirtyRects(dirtyRectangles.Length, dirtyRectangles, out var dirtyRegionsLength);for (var dirtyIndex = 0; dirtyIndex < dirtyRegionsLength / Marshal.SizeOf(typeof(RawRectangle)); dirtyIndex++){//Crop screen positions and size to frame sizes.var left = Math.Max(dirtyRectangles[dirtyIndex].Left, Left);var right = Math.Min(dirtyRectangles[dirtyIndex].Right, Left + Width);var top = Math.Max(dirtyRectangles[dirtyIndex].Top, Top);var bottom = Math.Min(dirtyRectangles[dirtyIndex].Bottom, Top + Height);//Copies from the screen texture only the area which the user wants to capture.if (right > left && bottom > top){Device.ImmediateContext.CopySubresourceRegion(screenTexture, 0, new ResourceRegion(left, top, 0, right, bottom, 1), StagingTexture, 0, left - Left, top - Top);wasCaptured = true;}}#endregionif (!wasCaptured){//Nothing was changed within the capture region, so ignore this frame.resource.Dispose();return FrameCount;}}#endregion#region Gets the image data//Gets the staging texture as a stream.var data = Device.ImmediateContext.MapSubresource(StagingTexture, 0, MapMode.Read, MapFlags.None);if (data.IsEmpty){Device.ImmediateContext.UnmapSubresource(StagingTexture, 0);resource?.Dispose();return FrameCount;}var bitmap = new System.Drawing.Bitmap(Width, Height, PixelFormat.Format32bppArgb);var boundsRect = new System.Drawing.Rectangle(0, 0, Width, Height);//Copy pixels from screen capture Texture to the GDI bitmap.var mapDest = bitmap.LockBits(boundsRect, ImageLockMode.WriteOnly, bitmap.PixelFormat);var sourcePtr = data.DataPointer;var destPtr = mapDest.Scan0;for (var y = 0; y < Height; y++){//Copy a single line.Utilities.CopyMemory(destPtr, sourcePtr, Width * 4);//Advance pointers.sourcePtr = IntPtr.Add(sourcePtr, data.RowPitch);destPtr = IntPtr.Add(destPtr, mapDest.Stride);}//Release source and dest locks.bitmap.UnlockBits(mapDest);//Set frame details.FrameCount++;frame.Path = $"{Project.FullPath}{FrameCount}.png";frame.Delay = FrameRate.GetMilliseconds();frame.Image = bitmap;BlockingCollection.Add(frame);#endregionDevice.ImmediateContext.UnmapSubresource(StagingTexture, 0);resource?.Dispose();return FrameCount;}catch (SharpDXException se) when (se.ResultCode.Code == SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code){return FrameCount;}catch (SharpDXException se) when (se.ResultCode.Code == SharpDX.DXGI.ResultCode.DeviceRemoved.Result.Code || se.ResultCode.Code == SharpDX.DXGI.ResultCode.DeviceReset.Result.Code){//When the device gets lost or reset, the resources should be instantiated again.DisposeInternal();Initialize();return FrameCount;}catch (Exception ex){LogWriter.Log(ex, "It was not possible to finish capturing the frame with DirectX.");OnError.Invoke(ex);return FrameCount;}finally{try{//Only release the frame if there was a success in capturing it.if (res.Success)DuplicatedOutput.ReleaseFrame();}catch (Exception e){LogWriter.Log(e, "It was not possible to release the frame.");}}}

白板数据:

定时获取白板内容:

private void Normal_Elapsed(object sender, EventArgs e){var fileName = $"{Project.FullPath}{FrameCount}.png";//TODO: GetRender fails to create useful image when the control has decimals values as size.var render = MainBorder.GetRender(_dpi); //TODO: Too heavy! Maybe just save the strokes? like layers?Project.Frames.Add(new FrameInfo(fileName, FrameRate.GetMilliseconds()));ThreadPool.QueueUserWorkItem(delegate { AddFrames(fileName, render); });FrameCount++;}

数据加入每一帧中:

   private void AddFrames(string fileName, BitmapSource bitmap){//var mutexLock = new Mutex(false, bitmap.GetHashCode().ToString());//mutexLock.WaitOne();using (var stream = new FileStream(fileName, FileMode.Create)){var encoder = new PngBitmapEncoder();encoder.Frames.Add(BitmapFrame.Create(bitmap));encoder.Save(stream);stream.Flush();stream.Close();}//GC.Collect(1);//mutexLock.ReleaseMutex();}

Github每日精选(第16期):录屏工具ScreenToGif相关推荐

  1. 录屏工具ScreenToGif功能总结

    录屏工具ScreenToGif功能总结,以2.15.1为例,比之前版本新增很多功能. 下载地址: https://download.csdn.net/download/xianyu_padding/1 ...

  2. 用JS轻松实现一个录音、录像、录屏工具库

    大家好,我是若川.持续组织了6个月源码共读活动,感兴趣的可以点此加我微信 ruochuan12 参与,每周大家一起学习200行左右的源码,共同进步.同时极力推荐订阅我写的<学习源码整体架构系列& ...

  3. 实用分享-免费录屏工具(无水印)

    作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 windows录屏工具,Bandicam 工具下载路径:录屏工具免费版.zip-其它文档类资源- ...

  4. win7录屏_学用系列|清晰、体积小,这些录屏工具适合正在为录屏苦恼的你

    2月10日,多家教学直播平台遭遇"教育双十一"的冲击,不少老师都感受到直播进不了课堂的苦,老师们不禁发出这样的困惑,直播那么难,我们可以录屏+视频网站发布吗?当然,不过,录屏软件那 ...

  5. android4.2屏幕录像,android——使用自带录屏工具进行屏幕录像

    在做开源项目的时候,想传一个gif效果图上去.但是,要有连贯的动画效果.所以,就想到先录制视频,然后视频转gif.但是,用第三录屏软件总是不完美. 那么,怎么办呢? android4.4 提供了自带录 ...

  6. 屏幕录制大师哪款好用?这3款录屏工具,值得推荐!

    案例:电脑录屏工具哪一款比较好用? [我一般用手机拍电脑上需要录制的内容,但是拍出来的视频画面小且不清晰.朋友说可以使用电脑录屏软件录制电脑屏幕,但我以前没有用过,不知道哪款好用?家人们有没有推荐的? ...

  7. 屏幕录像工具哪个好?这3款录屏工具就很不错!

    案例:有没有好用的录屏工具分享? [每次对电脑屏幕进行录制都要花费我很多时间,录制的内容质量还差,真是事倍功半.听说使用好的录屏工具可以提高录屏的效率,那录屏软件哪款好用?在线蹲一款!] 在现代科技时 ...

  8. python录屏工具下载_Python移动端录屏库

    Python移动端录屏库 背景 日常移动端专项测试和自动化测试通常有一些场景如:Ui自动化的操作捕获.App启动耗时.视频启播耗时等,通常都有需要边操作边录屏,而对于启动耗时测试通常还需要质量较高且帧 ...

  9. 3款免费好用的电脑录屏工具

    案例:电脑录屏工具哪款免费又好用? "我想要挑选一款适合自己的好用的电脑录屏软件,但是我尝试了很多款录屏软件结果都不尽人意.免费版的软件功能少,录制效果差,想要高级功能需要付费解锁.想问问大 ...

  10. linux中录屏工具byzanz

    linux中录屏工具byzanz: 1.安装 sudo apt install byzanz 2.使用 help:byzanz-record --help 配合xwininfo使用--xwininfo ...

最新文章

  1. centos下升级glib
  2. Expected a key while parsing a block mapping. assets: ^
  3. create_softLink.sh
  4. 详解 TCP 和 UDP
  5. Kafka 监控 Kafka Eagle 图形化版本
  6. HTML渐变背景不重复,如何停止重复自身的背景颜色渐变? (css)
  7. zynq中mgtx应用_【干货分享】ZYNQ常用外设设计 (上)
  8. 【LeetCode】Sum Root to Leaf Numbers
  9. 超过父控件的部分不能响应事件怎么办
  10. 西威变频器调试软件GF-EXprss
  11. 华为USG防火墙配置命令
  12. yytext table html,快速掌握YYText
  13. 74ls20设计半加器_组合逻辑电路(半加器全加器及逻辑运算)实验报告
  14. UNet++ 论文翻译
  15. qgc地面站如何导入离线地图_离线地图
  16. matlab单位函数定义,MATLAB 函数(一)
  17. Google Earth Engine ——QGIS中计算加权质心
  18. 桌面上程序可以用计算机打不开,我电脑桌面图标程序都打不开怎么办
  19. 阿里云视频点播功能使用
  20. 组播地址MAC的计算

热门文章

  1. DisplayTag1.2
  2. 火星人学习第二周——虚幻引擎蓝图应用与开发
  3. 虚幻引擎5安装踩坑记录
  4. 修改tomcat服务器图标,如何修改tomcat项目的图标(两种)
  5. VB.NET 教程_02_常见对象
  6. 水经注地图下载器注册机机器码过长_微图影像下载参数说明
  7. HTML5从入门到精通电子书pdf下载
  8. 怎样使用U盘启动盘安装乌班图系统
  9. 邓小铁:博弈论研究中的学术快乐
  10. SiteMesh框架统一布局用法介绍