diff --git a/ScreenCapture.NET/DirectX/DX11ScreenCapture.cs b/ScreenCapture.NET/DirectX/DX11ScreenCapture.cs index e7e39ff..77d0b2d 100644 --- a/ScreenCapture.NET/DirectX/DX11ScreenCapture.cs +++ b/ScreenCapture.NET/DirectX/DX11ScreenCapture.cs @@ -171,17 +171,17 @@ namespace ScreenCapture.NET if (scalingTexture != null) { _context.CopySubresourceRegion(scalingTexture, 0, 0, 0, 0, _captureTexture, 0, - new Box(captureZone.X, captureZone.Y, 0, - captureZone.X + captureZone.UnscaledWidth, - captureZone.Y + captureZone.UnscaledHeight, 1)); + new Box(captureZone.X, captureZone.Y, 0, + captureZone.X + captureZone.UnscaledWidth, + captureZone.Y + captureZone.UnscaledHeight, 1)); _context.GenerateMips(scalingTextureView); _context.CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, scalingTexture, captureZone.DownscaleLevel); } else _context.CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, _captureTexture, 0, - new Box(captureZone.X, captureZone.Y, 0, - captureZone.X + captureZone.UnscaledWidth, - captureZone.Y + captureZone.UnscaledHeight, 1)); + new Box(captureZone.X, captureZone.Y, 0, + captureZone.X + captureZone.UnscaledWidth, + captureZone.Y + captureZone.UnscaledHeight, 1)); MappedSubresource mapSource = _context.Map(stagingTexture, 0, MapMode.Read, MapFlags.None); IntPtr sourcePtr = mapSource.DataPointer; @@ -203,21 +203,13 @@ namespace ScreenCapture.NET /// public CaptureZone RegisterCaptureZone(int x, int y, int width, int height, int downscaleLevel = 0) { - CaptureZoneValidityCheck(x, y, width, height); + ValidateCaptureZoneAndThrow(x, y, width, height); int unscaledWidth = width; int unscaledHeight = height; - if (downscaleLevel > 0) - for (int i = 0; i < downscaleLevel; i++) - { - width /= 2; - height /= 2; - } + (width, height) = CalculateScaledSize(unscaledWidth, unscaledHeight, downscaleLevel); - if (width < 1) width = 1; - if (height < 1) height = 1; - - byte[] buffer = new byte[width * height * 4]; + byte[] buffer = new byte[width * height * BPP]; CaptureZone captureZone = new(_indexCounter++, x, y, width, height, BPP, downscaleLevel, unscaledWidth, unscaledHeight, buffer); lock (_captureZones) @@ -246,21 +238,59 @@ namespace ScreenCapture.NET } /// - public void RepositionCaptureZone(CaptureZone captureZone, int x, int y) + public void UpdateCaptureZone(CaptureZone captureZone, int? x = null, int? y = null, int? width = null, int? height = null, int? downscaleLevel = null) { - CaptureZoneValidityCheck(x, y, captureZone.UnscaledWidth, captureZone.UnscaledHeight); - lock (_captureZones) - { if (!_captureZones.ContainsKey(captureZone)) - throw new ArgumentException("Non registered CaptureZone", nameof(captureZone)); - } + throw new ArgumentException("The capture zone is not registered to this ScreenCapture", nameof(captureZone)); - captureZone.X = x; - captureZone.Y = y; + int newX = x ?? captureZone.X; + int newY = y ?? captureZone.Y; + int newUnscaledWidth = width ?? captureZone.UnscaledWidth; + int newUnscaledHeight = height ?? captureZone.UnscaledHeight; + int newDownscaleLevel = downscaleLevel ?? captureZone.DownscaleLevel; + + ValidateCaptureZoneAndThrow(newX, newY, newUnscaledWidth, newUnscaledHeight); + + captureZone.X = newX; + captureZone.Y = newY; + + //TODO DarthAffe 01.05.2022: For now just reinitialize the zone in that case, but this could be optimized to only recreate the textures needed. + if ((width != null) || (height != null) || (downscaleLevel != null)) + { + (int newWidth, int newHeight) = CalculateScaledSize(newUnscaledWidth, newUnscaledHeight, newDownscaleLevel); + lock (_captureZones) + { + UnregisterCaptureZone(captureZone); + + captureZone.UnscaledWidth = newUnscaledWidth; + captureZone.UnscaledHeight = newUnscaledHeight; + captureZone.Width = newWidth; + captureZone.Height = newHeight; + captureZone.DownscaleLevel = newDownscaleLevel; + captureZone.Buffer = new byte[newWidth * newHeight * BPP]; + + InitializeCaptureZone(captureZone); + } + } } - private void CaptureZoneValidityCheck(int x, int y, int width, int height) + private (int width, int height) CalculateScaledSize(int width, int height, int downscaleLevel) + { + if (downscaleLevel > 0) + for (int i = 0; i < downscaleLevel; i++) + { + width /= 2; + height /= 2; + } + + if (width < 1) width = 1; + if (height < 1) height = 1; + + return (width, height); + } + + private void ValidateCaptureZoneAndThrow(int x, int y, int width, int height) { if (_device == null) throw new ApplicationException("ScreenCapture isn't initialized."); diff --git a/ScreenCapture.NET/IScreenCapture.cs b/ScreenCapture.NET/IScreenCapture.cs index 7107c35..e2b47e9 100644 --- a/ScreenCapture.NET/IScreenCapture.cs +++ b/ScreenCapture.NET/IScreenCapture.cs @@ -27,7 +27,7 @@ namespace ScreenCapture.NET /// Creates a new for this . /// /// The x-location of the region to capture (must be >= 0 and < screen-width). - /// The x-location of the region to capture (must be >= 0 and < screen-height). + /// The y-location of the region to capture (must be >= 0 and < screen-height). /// The width of the region to capture (must be >= 0 and this + x must be <= screen-width). /// The height of the region to capture (must be >= 0 and this + y must be <= screen-height). /// The level of downscaling applied to the image of this region before copying to local memory. The calculation is (width and height)/2^downscaleLevel. @@ -42,13 +42,18 @@ namespace ScreenCapture.NET bool UnregisterCaptureZone(CaptureZone captureZone); /// - /// Updates the position of the given . + /// Updates the the given . /// + /// + /// null-parameters are ignored and not changed. + /// /// The previously registered . - /// The new x-location of the region on the screen. - /// The new y-location of the region on the screen - /// true if the was successfully repositioned; otherwise, false. - void RepositionCaptureZone(CaptureZone captureZone, int x, int y); + /// The new x-location of the region to capture (must be >= 0 and < screen-width). + /// The new y-location of the region to capture (must be >= 0 and < screen-height). + /// The width of the region to capture (must be >= 0 and this + x must be <= screen-width). + /// The new height of the region to capture (must be >= 0 and this + y must be <= screen-height). + /// The new level of downscaling applied to the image of this region before copying to local memory. The calculation is (width and height)/2^downscaleLevel. + void UpdateCaptureZone(CaptureZone captureZone, int? x = null, int? y = null, int? width = null, int? height = null, int? downscaleLevel = null); /// /// Restarts the . diff --git a/ScreenCapture.NET/Model/CaptureZone.cs b/ScreenCapture.NET/Model/CaptureZone.cs index 83ff803..460a0a6 100644 --- a/ScreenCapture.NET/Model/CaptureZone.cs +++ b/ScreenCapture.NET/Model/CaptureZone.cs @@ -27,29 +27,29 @@ namespace ScreenCapture.NET public int Y { get; internal set; } /// - /// Gets the width of the region on the screen. + /// Gets the width of the captured region. /// - public int Width { get; } + public int Width { get; internal set; } /// - /// Gets the height of the region on the screen. + /// Gets the height of the captured region. /// - public int Height { get; } + public int Height { get; internal set; } /// /// Gets the level of downscaling applied to the image of this region before copying to local memory. The calculation is (width and height)/2^downscaleLevel. /// - public int DownscaleLevel { get; } + public int DownscaleLevel { get; internal set; } /// /// Gets the original width of the region (this equals if is 0). /// - public int UnscaledWidth { get; } + public int UnscaledWidth { get; internal set; } /// /// Gets the original height of the region (this equals if is 0). /// - public int UnscaledHeight { get; } + public int UnscaledHeight { get; internal set; } /// /// Gets the amount of bytes per pixel in the image (most likely 3 [RGB] or 4 [ARGB]). @@ -64,7 +64,7 @@ namespace ScreenCapture.NET /// /// Gets the buffer containing the image data. Format depends on the specific capture but is most likely BGRA32. /// - public byte[] Buffer { get; } + public byte[] Buffer { get; internal set; } /// /// Gets the config for black-bar detection.