2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

System.Drawing.Bitmap から SoftwareBitmap を取得する方法 & C#/WinRT で OCR やってみた - クリップボードから取得版

Last updated at Posted at 2021-06-23

1. System.Drawing.Bitmap から SoftwareBitmap を取得する方法

2-1. ソースコード の MakeSoftwareBitmap メソッドの処理で実現可能。

1-1. SoftwareBitmap をプログラムから生成する方法(参考サイト)

ビットマップ画像の作成、編集、保存 - UWP applications | Microsoft Docs

2. C#/WinRT で OCR やってみた - クリップボードから取得版

2-1. ソースコード

以下、C#/WinRT で OCR やってみた - Qiitaからの派生

※SoftwareBitmap側 の RGB の順序が合っているかは裏どりしていない。


using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.Graphics.Imaging;
using Windows.Media.Ocr;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.Foundation;


class OcrTest
{
    [System.STAThread]
    static void Main(string[] args)
    {
        System.Drawing.Image img = System.Windows.Forms.Clipboard.GetImage();
        if (img != null)
        {
            var bmp = (System.Drawing.Bitmap)img; // 例外が発生する可能性あり
            SoftwareBitmap softBmp = MakeSoftwareBitmap(bmp);
            Task<string> ret = LoadImageAndOcr(softBmp);
            Console.WriteLine(ret.Result);
        }
    }

    [ComImport]
    [Guid("5B0D3235-4DBA-4D44-865E-8F1D0E4FD04D")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    unsafe interface IMemoryBufferByteAccess
    {
        void GetBuffer(out byte* buffer, out uint capacity);
    }

    static SoftwareBitmap MakeSoftwareBitmap(System.Drawing.Bitmap bmp)
    {
        unsafe {
            var softwareBitmap = new SoftwareBitmap(BitmapPixelFormat.Bgra8, bmp.Width, bmp.Height, BitmapAlphaMode.Premultiplied);


            System.Drawing.Imaging.BitmapData bd = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

            byte* pSrc = (byte*)bd.Scan0;

            using (BitmapBuffer buffer = softwareBitmap.LockBuffer(BitmapBufferAccessMode.Write))
            {
                using (var reference = buffer.CreateReference())
                {
                    byte* pDest;
                    uint capacity;
                    ((IMemoryBufferByteAccess)reference).GetBuffer(out pDest, out capacity);

                    // Fill-in the BGRA plane
                    BitmapPlaneDescription bl = buffer.GetPlaneDescription(0);
                    for (int y = 0; y < bl.Height; y++) {
                        int blOffset = bl.StartIndex + y*bl.Stride;
                        int yb = y*bd.Stride;
                        for (int x = 0; x < bl.Width; x++) {
                            pDest[blOffset + 4*x    ] = pSrc[yb + 4*x    ]; // blue
                            pDest[blOffset + 4*x + 1] = pSrc[yb + 4*x + 1]; // green
                            pDest[blOffset + 4*x + 2] = pSrc[yb + 4*x + 2]; // red
                            pDest[blOffset + 4*x + 3] = (byte)255; // alpha
                        }
                    }
                }
            }
            
            bmp.UnlockBits(bd);

            return softwareBitmap;
        }
    }

    static async Task<OcrResult> detect(SoftwareBitmap bitmap)
    {
        var ocrEngine = OcrEngine.TryCreateFromUserProfileLanguages();
        var ocrResult = await MyWaitUtil<OcrResult>.GetResultWithWaiting( ocrEngine.RecognizeAsync(bitmap) );
        // https://docs.microsoft.com/ja-jp/uwp/api/windows.media.ocr.ocrresult.lines?view=winrt-19041
        return ocrResult;
    }
    
    static async Task<string> LoadImageAndOcr(SoftwareBitmap softwareBitmap)
    {
        OcrResult t = await detect(softwareBitmap);
        return t.Text;
    }
}

public static class MyWaitUtil<T>
{
    public static async Task<T> GetResultWithWaiting(IAsyncOperation<T> task)
    {
        while ( task.Status != AsyncStatus.Completed ) {
            if ( task.Status == AsyncStatus.Error || task.Status == AsyncStatus.Canceled ) {
                Console.WriteLine("Error or Canceled");
                return default(T);
            }
            await Task.Delay(1);
        };
        return task.GetResults();
    }
}

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?