/// キャプチャしたbyte[]をBitmapSource(Freezed)にして返す
        /// @param request スクリーンキャプチャ設定をまとめたリクエスト
        /// @return スクリーンキャプチャ結果が格納されたBitmapSource
        private BitmapSource CaptureByGetDIBits(ScreenCaptureRequest request)
        {
            if (request.ClippingWidth <= 0 || request.ClippingHeight <= 0)
            {
                // Debug.WriteLine("Invalid clipping size", "ScreenCaptureTimer.CaptureByGetDIBits");
                return(null);
            }

            // GetDIBitsでbyte[]にデータを格納
            int dpiX, dpiY;
            var result = request.ExecuteByGetDIBits(out dpiX, out dpiY);

            if (result == null)
            {
                return(null);
            }

            var bitmap = BitmapSource.Create(request.ClippingWidth, request.ClippingHeight,
                                             dpiX, dpiY, PixelFormats.Bgr32, null, result, request.Stride);

            result = null;
            /// @todo(me) あまり大きな画像をメモリにおいておきたくない。
            ///           とはいえ、TransformedBitmapはちょっと重過ぎる。
            ///           メモリよりもCPUリソースを残しておきたいのでこのままでいいかも。
            //bitmap = this.Resize(bitmap);

            // スレッド越しにアクセスされるためFreeze
            bitmap.Freeze();
            return(bitmap);
        }
        /// 結果を取得
        /// @param layoutElement 対象のレイアウト要素
        /// @return 生成済みならBitmapSourceを。でなければNullを返す。
        public BitmapSource GetBitmapSource(LayoutElement layoutElement)
        {
            if (!layoutElement.IsWindowValid)
            {
                return(null);
            }
            var request = new ScreenCaptureRequest(layoutElement);

            /// ディクショナリはスレッドセーフではない
            lock (this.sharedLock) {
                BitmapSource result;
                var          success = this.cache.TryGetValue(request, out result);
                Debug.WriteLineIf(!success, "No request in cache", "ScreenCaptureTimer");
                return(result);
            }
        }
        /// キャプチャしたHBitmapをBitmapSource(Freezed)にして返す
        /// @param request スクリーンキャプチャ設定をまとめたリクエスト
        /// @return スクリーンキャプチャ結果が格納されたBitmapSource
        private BitmapSource Capture(ScreenCaptureRequest request)
        {
            if (request.ClippingWidth <= 0 || request.ClippingHeight <= 0)
            {
                // Debug.WriteLine("Invalid clipping size", "ScreenCaptureTimer.CaptureByGetDIBits");
                return(null);
            }

            // HBitmapからBitmapSourceを作成
            BitmapSource bitmap = null;

            using (var result = request.Execute()) {
                if (result == null)
                {
                    return(bitmap);
                }

                // HBitmapからBitmapSourceに変換
                bitmap = Imaging.CreateBitmapSourceFromHBitmap(
                    result.Bitmap, IntPtr.Zero, Int32Rect.Empty,
                    BitmapSizeOptions.FromEmptyOptions());

                // Debug.WriteLine(string.Format("Captured: {0:D}x{1:D}",
                //                 bitmap.PixelWidth, bitmap.PixelHeight),
                //                 "ScreenCapture");
            }

            // Alphaチャンネル情報を削除
            bitmap = new FormatConvertedBitmap(bitmap, PixelFormats.Bgr32, null, 0.0);

            /// @todo(me) あまり大きな画像をメモリにおいておきたくない。
            ///           とはいえ、TransformedBitmapはちょっと重過ぎる。
            ///           メモリよりもCPUリソースを残しておきたいのでこのままでいいかも。
            //bitmap = this.Resize(bitmap);

            // スレッド越しにアクセスされるためFreeze
            bitmap.Freeze();
            return(bitmap);
        }
Esempio n. 4
0
        private VideoInputConfigBase RebuildInputSource_Capture(string id, SceneItemSourceCapture capture, bool isWindow, StreamerRebuildContext rebuildContext)
        {
            var ci = _sources.GetOrCreateCaptureItem(capture.Source, isWindow);

            if (ci?.Wrapped != null)
            {
                var request = new ScreenCaptureRequest
                {
                    Id          = $"{capture.Source.CaptureId}",
                    Cursor      = capture.CaptureCursor,
                    InitialSize = ci.Wrapped.Size,
                    Item        = ci.Wrapped,
                    DebugName   = capture.Source.Name
                };
                return(new VideoInputConfigFull(new InputSetup(Type: ScreenCaptureContext.Name, Input: ci.Prefix + capture.Source.CaptureId,
                                                               ObjectInput: request)));
            }
            else
            {
                return(GetFailedInputSource(id, rebuildContext, InputIssueDesc.CaptureNotFound, $"Capture target '{capture.Source.Name}' not found"));
            }
        }