Esempio n. 1
0
        /// <summary>
        /// OpenCVのMatをSystem.Drawing.Bitmapに変換する
        /// </summary>
        /// <param name="src">変換するMat</param>
        /// <returns>System.Drawing.Bitmap</returns>
#else
        /// <summary>
        /// Converts Mat to System.Drawing.Bitmap
        /// </summary>
        /// <param name="src">Mat</param>
        /// <returns></returns>
#endif
        public static Bitmap ToBitmap(Mat src)
        {
            if (src == null)
            {
                throw new ArgumentNullException("src");
            }
            PixelFormat pf;

            switch (src.Channels())
            {
            case 1:
                pf = PixelFormat.Format8bppIndexed; break;

            case 3:
                pf = PixelFormat.Format24bppRgb; break;

            case 4:
                pf = PixelFormat.Format32bppArgb; break;

            default:
                throw new ArgumentException("Number of channels must be 1, 3 or 4.", "src");
            }
            return(ToBitmap(src, pf));
        }
Esempio n. 2
0
        //bufferをもとに白黒Matデータ作成
        private void KinectImagetoMat(Mat mat, byte[] buffer)
        {

            int channel = mat.Channels();
            int depth = mat.Depth();
            unsafe
            {
                byte* matPtr = mat.DataPointer;
                for (int i = 0; i < this.imageWidth * this.imageHeight; i++)
                {
                    if (buffer[i] == 255)
                    {
                        for (int j = 0; j < channel; j++)
                        {
                            *(matPtr + i * channel + j) = 255;
                        }
                    }
                    else
                    {
                        for (int j = 0; j < channel; j++)
                        {
                            *(matPtr + i * channel + j) = 0;
                        }
                    }

                }
            }
        }
Esempio n. 3
0
        /// <summary>
        /// System.Drawing.BitmapからOpenCVのMatへ変換して返す.
        /// </summary>
        /// <param name="src">変換するSystem.Drawing.Bitmap</param>
        /// <param name="dst">変換結果を格納するMat</param>
#else
        /// <summary>
        /// Converts System.Drawing.Bitmap to Mat
        /// </summary>
        /// <param name="src">System.Drawing.Bitmap object to be converted</param>
        /// <param name="dst">A Mat object which is converted from System.Drawing.Bitmap</param>
#endif
        public static unsafe void ToMat(Bitmap src, Mat dst)
        {
            if (src == null)
            {
                throw new ArgumentNullException("src");
            }
            if (dst == null)
            {
                throw new ArgumentNullException("dst");
            }
            if (dst.IsDisposed)
            {
                throw new ArgumentException("The specified dst is disposed.", "dst");
            }
            if (dst.Depth() != MatType.CV_8U)
            {
                throw new NotSupportedException("Mat depth != CV_8U");
            }
            if (dst.Dims() != 2)
            {
                throw new NotSupportedException("Mat dims != 2");
            }
            //if (dst.IsSubmatrix())
            //    throw new NotSupportedException("Submatrix is not supported");
            if (src.Width != dst.Width || src.Height != dst.Height)
            {
                throw new ArgumentException("src.Size != dst.Size");
            }

            int        w    = src.Width;
            int        h    = src.Height;
            Rectangle  rect = new Rectangle(0, 0, w, h);
            BitmapData bd   = null;

            try
            {
                bd = src.LockBits(rect, ImageLockMode.ReadOnly, src.PixelFormat);

                byte *p       = (byte *)bd.Scan0.ToPointer();
                int   sstep   = bd.Stride;
                int   offset  = sstep - (w / 8);
                uint  dstep   = (uint)dst.Step();
                byte *dstData = (byte *)dst.Data.ToPointer();

                switch (src.PixelFormat)
                {
                case PixelFormat.Format1bppIndexed:
                {
                    if (dst.Channels() != 1)
                    {
                        throw new ArgumentException("Invalid nChannels");
                    }
                    int  x = 0;
                    int  y;
                    int  bytePos;
                    byte b;
                    int  i;
                    for (y = 0; y < h; y++)
                    {
                        // 横は必ず4byte幅に切り上げられる。
                        // この行の各バイトを調べていく
                        for (bytePos = 0; bytePos < sstep; bytePos++)
                        {
                            if (x < w)
                            {
                                // 現在の位置のバイトからそれぞれのビット8つを取り出す
                                b = p[bytePos];
                                for (i = 0; i < 8; i++)
                                {
                                    if (x >= w)
                                    {
                                        break;
                                    }
                                    // IplImageは8bit/pixel
                                    dstData[dstep * y + x] = ((b & 0x80) == 0x80) ? (byte)255 : (byte)0;
                                    b <<= 1;
                                    x++;
                                }
                            }
                        }
                        // 次の行へ
                        x  = 0;
                        p += sstep;
                    }
                }
                break;

                case PixelFormat.Format8bppIndexed:
                case PixelFormat.Format24bppRgb:
                {
                    if (dst.Channels() != 1)
                    {
                        throw new ArgumentException("Invalid nChannels");
                    }

                    // Mat幅が4の倍数なら一気にコピー
                    if (dstep % 4 == 0)
                    {
                        uint length = (uint)(dst.DataEnd.ToInt64() - dst.DataStart.ToInt64());
                        Util.CopyMemory(dst.DataStart, bd.Scan0, length);
                    }
                    else
                    {
                        // 各行ごとにdstの行バイト幅コピー
                        byte *sp = (byte *)bd.Scan0;
                        byte *dp = (byte *)dst.DataStart;
                        for (int y = 0; y < h; y++)
                        {
                            Util.CopyMemory(dp, sp, dstep);
                            sp += sstep;
                            dp += dstep;
                        }
                    }
                }
                break;

                case PixelFormat.Format32bppRgb:
                case PixelFormat.Format32bppArgb:
                case PixelFormat.Format32bppPArgb:
                {
                    // 4チャネルならアラインメント調整いらない(はず)
                    switch (dst.Channels())
                    {
                    case 4:
                        uint length = (uint)(dst.DataEnd.ToInt64() - dst.DataStart.ToInt64());
                        Util.CopyMemory(dst.DataStart, bd.Scan0, length);
                        break;

                    case 3:
                        for (int y = 0; y < h; y++)
                        {
                            for (int x = 0; x < w; x++)
                            {
                                dstData[y * dstep + x * 3 + 0] = p[y * sstep + x * 4 + 0];
                                dstData[y * dstep + x * 3 + 1] = p[y * sstep + x * 4 + 1];
                                dstData[y * dstep + x * 3 + 2] = p[y * sstep + x * 4 + 2];
                            }
                        }
                        break;

                    default:
                        throw new ArgumentException("Invalid nChannels");
                    }
                }
                break;
                }
            }
            finally
            {
                if (bd != null)
                {
                    src.UnlockBits(bd);
                }
            }
        }
Esempio n. 4
0
        /// <summary>
        /// OpenCVのMatを指定した出力先にSystem.Drawing.Bitmapとして変換する
        /// </summary>
        /// <param name="src">変換するMat</param>
        /// <param name="dst">出力先のSystem.Drawing.Bitmap</param>
        /// <remarks>Author: shimat, Gummo (ROI support)</remarks>
#else
        /// <summary>
        /// Converts Mat to System.Drawing.Bitmap
        /// </summary>
        /// <param name="src">Mat</param>
        /// <param name="dst">Mat</param>
        /// <remarks>Author: shimat, Gummo (ROI support)</remarks>
#endif
        public static unsafe void ToBitmap(Mat src, Bitmap dst)
        {
            if (src == null)
            {
                throw new ArgumentNullException("src");
            }
            if (dst == null)
            {
                throw new ArgumentNullException("dst");
            }
            if (src.IsDisposed)
            {
                throw new ArgumentException("The image is disposed.", "src");
            }
            if (src.Depth() != MatType.CV_8U)
            {
                throw new ArgumentException("Depth of the image must be CV_8U");
            }
            //if (src.IsSubmatrix())
            //    throw new ArgumentException("Submatrix is not supported");
            if (src.Width != dst.Width || src.Height != dst.Height)
            {
                throw new ArgumentException("");
            }

            PixelFormat pf = dst.PixelFormat;

            // 1プレーン用の場合、グレースケールのパレット情報を生成する
            if (pf == PixelFormat.Format8bppIndexed)
            {
                ColorPalette plt = dst.Palette;
                for (int x = 0; x < 256; x++)
                {
                    plt.Entries[x] = Color.FromArgb(x, x, x);
                }
                dst.Palette = plt;
            }

            int        w    = src.Width;
            int        h    = src.Height;
            Rectangle  rect = new Rectangle(0, 0, w, h);
            BitmapData bd   = null;

            try
            {
                bd = dst.LockBits(rect, ImageLockMode.WriteOnly, pf);


                byte *psrc   = (byte *)(src.DataStart.ToPointer());
                byte *pdst   = (byte *)(bd.Scan0.ToPointer());
                int   ch     = src.Channels();
                int   sstep  = (int)src.Step();
                int   dstep  = ((src.Width * ch) + 3) / 4 * 4; // 4の倍数に揃える
                int   stride = bd.Stride;

                switch (pf)
                {
                case PixelFormat.Format1bppIndexed:
                {
                    // BitmapDataは4byte幅だが、IplImageは1byte幅
                    // 手作業で移し替える
                    //int offset = stride - (w / 8);
                    int  x = 0;
                    int  y;
                    int  bytePos;
                    byte mask;
                    byte b = 0;
                    int  i;
                    for (y = 0; y < h; y++)
                    {
                        for (bytePos = 0; bytePos < stride; bytePos++)
                        {
                            if (x < w)
                            {
                                for (i = 0; i < 8; i++)
                                {
                                    mask = (byte)(0x80 >> i);
                                    if (x < w && psrc[sstep * y + x] == 0)
                                    {
                                        b &= (byte)(mask ^ 0xff);
                                    }
                                    else
                                    {
                                        b |= mask;
                                    }

                                    x++;
                                }
                                pdst[bytePos] = b;
                            }
                        }
                        x     = 0;
                        pdst += stride;
                    }
                    break;
                }

                case PixelFormat.Format8bppIndexed:
                case PixelFormat.Format24bppRgb:
                case PixelFormat.Format32bppArgb:
                    if (sstep == dstep)
                    {
                        uint imageSize = (uint)(src.DataEnd.ToInt64() - src.DataStart.ToInt64());
                        Util.CopyMemory(pdst, psrc, imageSize);
                    }
                    else
                    {
                        for (int y = 0; y < h; y++)
                        {
                            int offsetSrc = (y * sstep);
                            int offsetDst = (y * dstep);
                            // 一列ごとにコピー
                            Util.CopyMemory(pdst + offsetDst, psrc + offsetSrc, w * ch);
                        }
                    }
                    break;

                default:
                    throw new NotImplementedException();
                }
            }
            finally
            {
                dst.UnlockBits(bd);
            }
        }
Esempio n. 5
0
        /// <summary>
        /// System.Drawing.BitmapからOpenCVのMatへ変換して返す.
        /// </summary>
        /// <param name="src">変換するSystem.Drawing.Bitmap</param>
        /// <param name="dst">変換結果を格納するMat</param>
#else
        /// <summary>
        /// Converts System.Drawing.Bitmap to Mat
        /// </summary>
        /// <param name="src">System.Drawing.Bitmap object to be converted</param>
        /// <param name="dst">A Mat object which is converted from System.Drawing.Bitmap</param>
#endif
        public static unsafe void ToMat(this Bitmap src, Mat dst)
        {
            if (src == null)
                throw new ArgumentNullException("src");
            if (dst == null)
                throw new ArgumentNullException("dst");
            if (dst.IsDisposed)
                throw new ArgumentException("The specified dst is disposed.", "dst");
            if (dst.Depth() != MatType.CV_8U)
                throw new NotSupportedException("Mat depth != CV_8U");
            if (dst.Dims() != 2)
                throw new NotSupportedException("Mat dims != 2");
            if (src.Width != dst.Width || src.Height != dst.Height)
                throw new ArgumentException("src.Size != dst.Size");

            int w = src.Width;
            int h = src.Height;
            Rectangle rect = new Rectangle(0, 0, w, h);
            BitmapData bd = null;
            try
            {
                bd = src.LockBits(rect, ImageLockMode.ReadOnly, src.PixelFormat);

                byte* p = (byte*)bd.Scan0.ToPointer();
                int sstep = bd.Stride;
                int offset = sstep - (w / 8);
                uint dstep = (uint)dst.Step();
                IntPtr dstData = dst.Data;
                byte* dstPtr = (byte*)dstData.ToPointer();

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

                switch (src.PixelFormat)
                {
                    case PixelFormat.Format1bppIndexed:
                    {
                        if (dst.Channels() != 1)                        
                            throw new ArgumentException("Invalid nChannels");
                        if (submat)
                            throw new NotImplementedException("submatrix not supported");

                        int x = 0;
                        int y;
                        int bytePos;
                        byte b;
                        int i;
                        for (y = 0; y < h; y++)
                        {
                            // 横は必ず4byte幅に切り上げられる。
                            // この行の各バイトを調べていく
                            for (bytePos = 0; bytePos < sstep; bytePos++)
                            {
                                if (x < w)
                                {
                                    // 現在の位置のバイトからそれぞれのビット8つを取り出す
                                    b = p[bytePos];
                                    for (i = 0; i < 8; i++)
                                    {
                                        if (x >= w)
                                        {
                                            break;
                                        }
                                        // IplImageは8bit/pixel
                                        dstPtr[dstep * y + x] = ((b & 0x80) == 0x80) ? (byte)255 : (byte)0;
                                        b <<= 1;
                                        x++;
                                    }
                                }
                            }
                            // 次の行へ
                            x = 0;
                            p += sstep;
                        }
                    }
                        break;

                    case PixelFormat.Format8bppIndexed:
                    case PixelFormat.Format24bppRgb:
                    {
                        if (src.PixelFormat == PixelFormat.Format8bppIndexed)
                            if (dst.Channels() != 1)
                                throw new ArgumentException("Invalid nChannels");
                        if (src.PixelFormat == PixelFormat.Format24bppRgb)
                            if (dst.Channels() != 3)
                                throw new ArgumentException("Invalid nChannels");

                        // ステップが同じで連続なら、一気にコピー
                        if (dstep == sstep && !submat && continuous)
                        {
                            uint length = (uint)(dst.DataEnd.ToInt64() - dstData.ToInt64());
                            Util.CopyMemory(dstData, bd.Scan0, length);
                        }
                        else
                        {
                            // 各行ごとにdstの行バイト幅コピー
                            byte* sp = (byte*)bd.Scan0;
                            byte* dp = (byte*)dst.Data;
                            for (int y = 0; y < h; y++)
                            {
                                Util.CopyMemory(dp, sp, dstep);
                                sp += sstep;
                                dp += dstep;
                            }
                        }
                    }
                        break;

                    case PixelFormat.Format32bppRgb:
                    case PixelFormat.Format32bppArgb:
                    case PixelFormat.Format32bppPArgb:
                    {
                        switch (dst.Channels())
                        {
                            case 4:
                                if (!submat && continuous)
                                {
                                    uint length = (uint)(dst.DataEnd.ToInt64() - dstData.ToInt64());
                                    Util.CopyMemory(dstData, bd.Scan0, length);
                                }
                                else
                                {
                                    byte* sp = (byte*)bd.Scan0;
                                    byte* dp = (byte*)dst.Data;
                                    for (int y = 0; y < h; y++)
                                    {
                                        Util.CopyMemory(dp, sp, dstep);
                                        sp += sstep;
                                        dp += dstep;
                                    }
                                }
                                break;
                            case 3:
                                for (int y = 0; y < h; y++)
                                {
                                    for (int x = 0; x < w; x++)
                                    {
                                        dstPtr[y * dstep + x * 3 + 0] = p[y * sstep + x * 4 + 0];
                                        dstPtr[y * dstep + x * 3 + 1] = p[y * sstep + x * 4 + 1];
                                        dstPtr[y * dstep + x * 3 + 2] = p[y * sstep + x * 4 + 2];
                                    }
                                }
                                break;
                            default:
                                throw new ArgumentException("Invalid nChannels");
                        }
                    }
                        break;
                }
            }
            finally
            {
                if(bd != null)
                    src.UnlockBits(bd);
            }
        }
        /// <summary>
        /// WriteableBitmapをMatに変換する.
        /// </summary>
        /// <param name="src">変換するWriteableBitmap</param>
        /// <param name="dst">出力先のMat</param>
#else
        /// <summary>
        /// Converts WriteableBitmap to Mat
        /// </summary>
        /// <param name="src">Input WriteableBitmap</param>
        /// <param name="dst">Output Mat</param>
#endif
        public static void ToMat(this WriteableBitmap src, Mat dst)
        {
            if (src == null)
                throw new ArgumentNullException("src");
            if (dst == null)
                throw new ArgumentNullException("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 = GetOptimumChannels(src.Format);            
            if (dst.Channels() != channels)
            {
                throw new ArgumentException("nChannels of dst is invalid", "dst");
            }

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

                // 1bppは手作業でコピー
                if (bpp == 1)
                {
                    // 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);
                    long imageSize = dst.DataEnd.ToInt64() - dst.DataStart.ToInt64();
                    if (imageSize < 0)
                        throw new OpenCvSharpException("The mat has invalid data pointer");
                    if (imageSize > Int32.MaxValue)
                        throw new OpenCvSharpException("Too big mat data");
                    src.CopyPixels(Int32Rect.Empty, dst.Data, (int)imageSize, stride);
                }

            }
        }
        /// <summary>
        /// MatをWriteableBitmapに変換する.
        /// 返却値を新たに生成せず引数で指定したWriteableBitmapに格納するので、メモリ効率が良い。
        /// </summary>
        /// <param name="src">変換するMat</param>
        /// <param name="dst">変換結果を設定するWriteableBitmap</param>
#else
        /// <summary>
        /// Converts Mat to WriteableBitmap.
        /// This method is more efficient because new instance of WriteableBitmap is not allocated.
        /// </summary>
        /// <param name="src">Input Mat</param>
        /// <param name="dst">Output WriteableBitmap</param>
#endif
        public static void ToWriteableBitmap(Mat src, WriteableBitmap dst)
        {
            if (src == null)
                throw new ArgumentNullException("src");
            if (dst == null)
                throw new ArgumentNullException("dst");
            if (src.Width != dst.PixelWidth || src.Height != dst.PixelHeight)
                throw new ArgumentException("size of src must be equal to size of dst");
            //if (src.Depth != BitDepth.U8)
                //throw new ArgumentException("bit depth of src must be BitDepth.U8", "src");
            if (src.Dims() > 2)
                throw new ArgumentException("Mat dimensions must be 2");

            int w = src.Width;
            int h = src.Height;
            int bpp = dst.Format.BitsPerPixel;

            int channels = GetOptimumChannels(dst.Format);   
            if (src.Channels() != channels)
            {
                throw new ArgumentException("channels of dst != channels of PixelFormat", "dst");
            }

            if (bpp == 1)
            {
                unsafe
                {
                    // 手作業で移し替える
                    int stride = w / 8 + 1;
                    if (stride < 2)
                    {
                        stride = 2;
                    }
                    byte[] pixels = new byte[h * stride];
                    byte* p = (byte*)(src.Data);
                    int x = 0;
                    long step = src.Step();
                    for (int y = 0; y < h; y++)
                    {
                        int offset = y * stride;
                        for (int bytePos = 0; bytePos < stride; bytePos++)
                        {
                            if (x < w)
                            {
                                byte b = 0;
                                // 現在の位置から横8ピクセル分、ビットがそれぞれ立っているか調べ、1つのbyteにまとめる
                                for (int i = 0; i < 8; i++)
                                {
                                    b <<= 1;
                                    if (x < w && p[step * y + x] != 0)
                                    {
                                        b |= 1;
                                    }
                                    x++;
                                }
                                pixels[offset + bytePos] = b;
                            }
                        }
                        x = 0;
                    }
                    dst.WritePixels(new Int32Rect(0, 0, w, h), pixels, stride, 0);
                }
            }
            else
            {
                long imageSize = src.DataEnd.ToInt64() - src.DataStart.ToInt64();
                if (imageSize < 0)
                    throw new OpenCvSharpException("The mat has invalid data pointer");
                if (imageSize > Int32.MaxValue)
                    throw new OpenCvSharpException("Too big mat data");
                dst.WritePixels(new Int32Rect(0, 0, w, h), src.Data, (int)imageSize, (int)src.Step());
            }
        }
        /// <summary>
        /// MatをWriteableBitmapに変換する.
        /// 返却値を新たに生成せず引数で指定したWriteableBitmapに格納するので、メモリ効率が良い。
        /// </summary>
        /// <param name="src">変換するMat</param>
        /// <param name="dst">変換結果を設定するWriteableBitmap</param>
#else
        /// <summary>
        /// Converts Mat to WriteableBitmap.
        /// This method is more efficient because new instance of WriteableBitmap is not allocated.
        /// </summary>
        /// <param name="src">Input Mat</param>
        /// <param name="dst">Output WriteableBitmap</param>
#endif
        public static void ToWriteableBitmap(Mat src, WriteableBitmap dst)
        {
            if (src == null)
                throw new ArgumentNullException("src");
            if (dst == null)
                throw new ArgumentNullException("dst");
            if (src.Width != dst.PixelWidth || src.Height != dst.PixelHeight)
                throw new ArgumentException("size of src must be equal to size of dst");
            //if (src.Depth != BitDepth.U8)
            //throw new ArgumentException("bit depth of src must be BitDepth.U8", "src");
            if (src.Dims() > 2)
                throw new ArgumentException("Mat dimensions must be 2");

            int w = src.Width;
            int h = src.Height;
            int bpp = dst.Format.BitsPerPixel;

            int channels = GetOptimumChannels(dst.Format);
            if (src.Channels() != channels)
            {
                throw new ArgumentException("channels of dst != channels of PixelFormat", "dst");
            }

            bool submat = src.IsSubmatrix();
            bool continuous = src.IsContinuous();
            unsafe
            {
                byte* pSrc = (byte*)(src.Data);
                int sstep = (int)src.Step();

                if (bpp == 1)
                {
                    if (submat)
                        throw new NotImplementedException("submatrix not supported");

                    // 手作業で移し替える
                    int stride = w / 8 + 1;
                    if (stride < 2)                    
                        stride = 2;
                    
                    byte[] pixels = new byte[h * stride];

                    for (int x = 0, y = 0; y < h; y++)
                    {
                        int offset = y * stride;
                        for (int bytePos = 0; bytePos < stride; bytePos++)
                        {
                            if (x < w)
                            {
                                byte b = 0;
                                // 現在の位置から横8ピクセル分、ビットがそれぞれ立っているか調べ、1つのbyteにまとめる
                                for (int i = 0; i < 8; i++)
                                {
                                    b <<= 1;
                                    if (x < w && pSrc[sstep * y + x] != 0)
                                    {
                                        b |= 1;
                                    }
                                    x++;
                                }
                                pixels[offset + bytePos] = b;
                            }
                        }
                        x = 0;
                    }
                    dst.WritePixels(new Int32Rect(0, 0, w, h), pixels, stride, 0);
                    return;
                }

                // 一気にコピー            
                if (!submat && continuous)
                {                    
                    long imageSize = src.DataEnd.ToInt64() - src.Data.ToInt64();
                    if (imageSize < 0)
                        throw new OpenCvSharpException("The mat has invalid data pointer");
                    if (imageSize > Int32.MaxValue)
                        throw new OpenCvSharpException("Too big mat data");
                    dst.WritePixels(new Int32Rect(0, 0, w, h), src.Data, (int)imageSize, sstep);
                    return;
                }

                // 一列ごとにコピー
                try
                {
                    dst.Lock();

                    int dstep = dst.BackBufferStride;
                    byte* pDst = (byte*)dst.BackBuffer;

                    for (int y = 0; y < h; y++)
                    {
                        long offsetSrc = (y * sstep);
                        long offsetDst = (y * dstep);
                        Util.CopyMemory(pDst + offsetDst, pSrc + offsetSrc, w * channels);
                    }
                }
                finally
                {
                    dst.Unlock();
                }
            }
        }
Esempio n. 9
0
        /// <summary>
        /// OpenCVのMatを指定した出力先にSystem.Drawing.Bitmapとして変換する
        /// </summary>
        /// <param name="src">変換するMat</param>
        /// <param name="dst">出力先のSystem.Drawing.Bitmap</param>
        /// <remarks>Author: shimat, Gummo (ROI support)</remarks>
#else
        /// <summary>
        /// Converts Mat to System.Drawing.Bitmap
        /// </summary>
        /// <param name="src">Mat</param>
        /// <param name="dst">Mat</param>
        /// <remarks>Author: shimat, Gummo (ROI support)</remarks>
#endif
        public static unsafe void ToBitmap(Mat src, Bitmap dst)
        {
            if (src == null)
                throw new ArgumentNullException("src");
            if (dst == null)
                throw new ArgumentNullException("dst");
            if (src.IsDisposed)
                throw new ArgumentException("The image is disposed.", "src");
            if (src.Depth() != MatType.CV_8U)
                throw new ArgumentException("Depth of the image must be CV_8U");
            //if (src.IsSubmatrix())
            //    throw new ArgumentException("Submatrix is not supported");
            if (src.Width != dst.Width || src.Height != dst.Height)
                throw new ArgumentException("");

            PixelFormat pf = dst.PixelFormat;

            // 1プレーン用の場合、グレースケールのパレット情報を生成する
            if (pf == PixelFormat.Format8bppIndexed)
            {
                ColorPalette plt = dst.Palette;
                for (int x = 0; x < 256; x++)
                {
                    plt.Entries[x] = Color.FromArgb(x, x, x);
                }
                dst.Palette = plt;
            }

            int w = src.Width;
            int h = src.Height;
            Rectangle rect = new Rectangle(0, 0, w, h);
            BitmapData bd = null;

            try
            {
                bd = dst.LockBits(rect, ImageLockMode.WriteOnly, pf);


                byte* psrc = (byte*)(src.DataStart.ToPointer());
                byte* pdst = (byte*)(bd.Scan0.ToPointer());
                int ch = src.Channels();
                int sstep = (int)src.Step();
                int dstep = ((src.Width * ch) + 3) / 4 * 4; // 4の倍数に揃える
                int stride = bd.Stride;

                switch (pf)
                {
                    case PixelFormat.Format1bppIndexed:
                    {
                        // BitmapDataは4byte幅だが、IplImageは1byte幅
                        // 手作業で移し替える				 
                        //int offset = stride - (w / 8);
                        int x = 0;
                        int y;
                        int bytePos;
                        byte mask;
                        byte b = 0;
                        int i;
                        for (y = 0; y < h; y++)
                        {
                            for (bytePos = 0; bytePos < stride; bytePos++)
                            {
                                if (x < w)
                                {
                                    for (i = 0; i < 8; i++)
                                    {
                                        mask = (byte)(0x80 >> i);
                                        if (x < w && psrc[sstep * y + x] == 0)
                                            b &= (byte)(mask ^ 0xff);
                                        else
                                            b |= mask;

                                        x++;
                                    }
                                    pdst[bytePos] = b;
                                }
                            }
                            x = 0;
                            pdst += stride;
                        }
                        break;
                    }

                    case PixelFormat.Format8bppIndexed:
                    case PixelFormat.Format24bppRgb:
                    case PixelFormat.Format32bppArgb:
                        if (sstep == dstep)
                        {
                            uint imageSize = (uint)(src.DataEnd.ToInt64() - src.DataStart.ToInt64());
                            Util.CopyMemory(pdst, psrc, imageSize);
                        }
                        else
                        {
                            for (int y = 0; y < h; y++)
                            {
                                int offsetSrc = (y * sstep);
                                int offsetDst = (y * dstep);
                                // 一列ごとにコピー
                                Util.CopyMemory(pdst + offsetDst, psrc + offsetSrc, w * ch);
                            }
                        }
                        break;

                    default:
                        throw new NotImplementedException();
                }
            }
            finally
            {
                dst.UnlockBits(bd);
            }
        }
Esempio n. 10
0
        /// <summary>
        /// OpenCVのMatをSystem.Drawing.Bitmapに変換する
        /// </summary>
        /// <param name="src">変換するMat</param>
        /// <returns>System.Drawing.Bitmap</returns>
#else
        /// <summary>
        /// Converts Mat to System.Drawing.Bitmap
        /// </summary>
        /// <param name="src">Mat</param>
        /// <returns></returns>
#endif
        public static Bitmap ToBitmap(Mat src)
        {
            if (src == null)
            {
                throw new ArgumentNullException("src");
            }
            PixelFormat pf;
            switch (src.Channels())
            {
                case 1:
                    pf = PixelFormat.Format8bppIndexed; break;
                case 3:
                    pf = PixelFormat.Format24bppRgb; break;
                case 4:
                    pf = PixelFormat.Format32bppArgb; break;
                default:
                    throw new ArgumentException("Number of channels must be 1, 3 or 4.", "src");
            }
            return ToBitmap(src, pf);
        }