A static class which provides conversion between System.Windows.Media.Imaging.WriteableBitmap and IplImage
예제 #1
0
        /// <summary>
        /// BitmapSourceをMatに変換する
        /// </summary>
        /// <param name="src">変換するBitmapSource</param>
        /// <returns>OpenCvSharpで扱えるMat</returns>
#else
        /// <summary>
        /// Converts BitmapSource to Mat
        /// </summary>
        /// <param name="src">Input BitmapSource</param>
        /// <returns>IplImage</returns>
#endif
        public static Mat ToMat(this BitmapSource src)
        {
            if (src == null)
            {
                throw new ArgumentNullException(nameof(src));
            }

            int     w    = src.PixelWidth;
            int     h    = src.PixelHeight;
            MatType type = WriteableBitmapConverter.GetOptimumType(src.Format);
            Mat     dst  = new Mat(h, w, type);

            ToMat(src, dst);
            return(dst);
        }
예제 #2
0
        /// <summary>
        /// BitmapSourceをMatに変換する.
        /// </summary>
        /// <param name="src">変換するBitmapSource</param>
        /// <param name="dst">出力先のMat</param>
#else
        /// <summary>
        /// Converts BitmapSource to Mat
        /// </summary>
        /// <param name="src">Input BitmapSource</param>
        /// <param name="dst">Output Mat</param>
#endif
        public static void ToMat(this BitmapSource src, Mat dst)
        {
            if (src == null)
            {
                throw new ArgumentNullException(nameof(src));
            }
            if (dst == null)
            {
                throw new ArgumentNullException(nameof(dst));
            }
            if (src.PixelWidth != dst.Width || src.PixelHeight != dst.Height)
            {
                throw new ArgumentException("size of src must be equal to size of dst");
            }
            if (dst.Dims > 2)
            {
                throw new ArgumentException("Mat dimensions must be 2");
            }

            int w        = src.PixelWidth;
            int h        = src.PixelHeight;
            int bpp      = src.Format.BitsPerPixel;
            int channels = WriteableBitmapConverter.GetOptimumChannels(src.Format);

            if (dst.Channels() != channels)
            {
                throw new ArgumentException("nChannels of dst is invalid", nameof(dst));
            }

            bool submat     = dst.IsSubmatrix();
            bool continuous = dst.IsContinuous();

            unsafe
            {
                byte *p    = (byte *)(dst.Data);
                long  step = dst.Step();

                // 1bppは手作業でコピー
                if (bpp == 1)
                {
                    if (submat)
                    {
                        throw new NotImplementedException("submatrix not supported");
                    }

                    // BitmapImageのデータを配列にコピー
                    // 要素1つに横8ピクセル分のデータが入っている。
                    int    stride = (w / 8) + 1;
                    byte[] pixels = new byte[h * stride];
                    src.CopyPixels(pixels, stride, 0);
                    int x = 0;
                    for (int y = 0; y < h; y++)
                    {
                        int offset = y * stride;
                        // この行の各バイトを調べていく
                        for (int bytePos = 0; bytePos < stride; bytePos++)
                        {
                            if (x < w)
                            {
                                // 現在の位置のバイトからそれぞれのビット8つを取り出す
                                byte b = pixels[offset + bytePos];
                                for (int i = 0; i < 8; i++)
                                {
                                    if (x >= w)
                                    {
                                        break;
                                    }
                                    p[step * y + x] = ((b & 0x80) == 0x80) ? (byte)255 : (byte)0;
                                    b <<= 1;
                                    x++;
                                }
                            }
                        }
                        // 次の行へ
                        x = 0;
                    }
                }
                // 8bpp

                /*else if (bpp == 8)
                 * {
                 *  int stride = w;
                 *  byte[] pixels = new byte[h * stride];
                 *  src.CopyPixels(pixels, stride, 0);
                 *  for (int y = 0; y < h; y++)
                 *  {
                 *      for (int x = 0; x < w; x++)
                 *      {
                 *          p[step * y + x] = pixels[y * stride + x];
                 *      }
                 *  }
                 * }*/
                // 24bpp, 32bpp, ...
                else
                {
                    int stride = w * ((bpp + 7) / 8);
                    if (!submat && continuous)
                    {
                        long imageSize = dst.DataEnd.ToInt64() - dst.Data.ToInt64();
                        if (imageSize < 0)
                        {
                            throw new OpenCvSharpException("The mat has invalid data pointer");
                        }
                        if (imageSize > int.MaxValue)
                        {
                            throw new OpenCvSharpException("Too big mat data");
                        }
                        src.CopyPixels(Int32Rect.Empty, dst.Data, (int)imageSize, stride);
                    }
                    else
                    {
                        // 高さ1pxの矩形ごと(≒1行ごと)にコピー
                        var roi = new Int32Rect {
                            X = 0, Y = 0, Width = w, Height = 1
                        };
                        IntPtr dstData = dst.Data;
                        for (int y = 0; y < h; y++)
                        {
                            roi.Y = y;
                            src.CopyPixels(roi, dstData, stride, stride);
                            dstData = new IntPtr(dstData.ToInt64() + stride);
                        }
                    }
                }
            }
        }