예제 #1
0
 public static Vector <double> BitmapToVector(Stream stream, BitmapChannel channel = BitmapChannel.Gray)
 {
     using var bitmap = Bitmap.FromStream(stream);
     return(BitmapToVector(bitmap as Bitmap, channel));
 }
예제 #2
0
        public unsafe static Vector <double> BitmapToVector(Bitmap bitmap, BitmapChannel channel = BitmapChannel.Gray)
        {
            int width      = bitmap.Width;
            int height     = bitmap.Height;
            int pixelCount = width * height;

            bool needDispose = false;
            bool isGray      = false;

            var rect = new Rectangle(0, 0, width, height);

            int depth = Bitmap.GetPixelFormatSize(bitmap.PixelFormat);

            switch (bitmap.PixelFormat)
            {
            case PixelFormat.Format24bppRgb:
            case PixelFormat.Format32bppArgb:
            case PixelFormat.Format32bppPArgb:
            case PixelFormat.Format32bppRgb:
                break;

            default:
                bitmap      = channel == BitmapChannel.Gray ? MakeGrayscale(bitmap) : MakeColor(bitmap);
                needDispose = true;
                break;
            }

            if (!needDispose && channel == BitmapChannel.Gray)
            {
                bitmap      = MakeGrayscale(bitmap);
                needDispose = true;
                isGray      = true;
            }

            var result = new double[pixelCount];

            var bitmapData = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat);

            try
            {
                unsafe
                {
                    byte *scan0 = (byte *)bitmapData.Scan0.ToPointer();

                    var ptr = bitmapData.Scan0;
                    int startIndex;

                    switch (depth)
                    {
                    case 8:     // For 8 bpp get color value (Red, Green and Blue values are the same)
                        if (channel == BitmapChannel.Alpha)
                        {
                            break;
                        }

                        for (int y = 0; y < bitmapData.Height; y++)
                        {
                            var rowB = (byte *)bitmapData.Scan0 + (y * bitmapData.Stride);
                            startIndex = y * bitmapData.Width;
                            if (bitmapData.Stride < 0)
                            {
                                startIndex = (pixelCount - bitmapData.Width) - startIndex;
                            }

                            for (int x = 0; x < bitmapData.Width; x++)
                            {
                                result[startIndex + x] = rowB[x];
                            }
                        }

                        PointwiseDivideInPlace(result, 256.0);
                        break;

                    case 16:     // For 16 bpp - gray with 65536 shades
                        if (channel == BitmapChannel.Alpha)
                        {
                            break;
                        }

                        for (int y = 0; y < bitmapData.Height; y++)
                        {
                            var rowS = (short *)bitmapData.Scan0 + (y * bitmapData.Stride);
                            startIndex = y * bitmapData.Width;
                            if (bitmapData.Stride < 0)
                            {
                                startIndex = (pixelCount - bitmapData.Width) - startIndex;
                            }

                            for (int x = 0; x < bitmapData.Width; x++)
                            {
                                result[startIndex + x] = rowS[x];
                            }
                        }

                        PointwiseDivideInPlace(result, 65536.0);
                        break;

                    case 24:     // For 24 bpp get Red, Green and Blue
                    case 32:     // For 32 bpp get Red, Green, Blue and Alpha
                        if (channel == BitmapChannel.Alpha && depth == 24)
                        {
                            break;
                        }

                        int step = depth / 8;

                        if (channel == BitmapChannel.Gray)
                        {
                            if (isGray && UseGrayConverter)
                            {
                                for (int y = 0; y < bitmapData.Height; y++)
                                {
                                    var row3B = (byte *)bitmapData.Scan0.ToPointer() + (y * bitmapData.Stride);
                                    startIndex = y * bitmapData.Width;
                                    if (bitmapData.Stride < 0)
                                    {
                                        startIndex = (pixelCount - bitmapData.Width) - startIndex;
                                    }

                                    for (int i = 0, x = 0; i < bitmapData.Width; i++, x += step)
                                    {
                                        result[startIndex + i] = row3B[x];     //In gray image (made with method MakeGray()) R = G = B.
                                    }
                                }

                                PointwiseDivideInPlace(result, 256.0);
                            }
                            else if (UseAvx)
                            {
                                var vectorGrayCoeffAvx = Vector256.Create(0.11d, 0.59d, 0.3d, 0d);

                                for (int y = 0; y < bitmapData.Height; y++)
                                {
                                    var row3B = (byte *)bitmapData.Scan0 + (y * bitmapData.Stride);
                                    startIndex = y * bitmapData.Width;
                                    if (bitmapData.Stride < 0)
                                    {
                                        startIndex = (pixelCount - bitmapData.Width) - startIndex;
                                    }

                                    for (int i = 0, x = 0; i < bitmapData.Width; i++, x += step)
                                    {
                                        var    vectorB    = Vector128.Create((int)row3B[x], (int)row3B[x + 1], (int)row3B[x + 2], (int)0);
                                        var    vectorD    = Avx.ConvertToVector256Double(vectorB);
                                        var    vectorGray = Avx.Multiply(vectorD, vectorGrayCoeffAvx);
                                        double dGray      = vectorGray.GetElement(0) + vectorGray.GetElement(1) + vectorGray.GetElement(2);
                                        result[startIndex + i] = dGray;
                                    }
                                }

                                PointwiseDivideInPlace(result, 256.0);
                            }
                            else if (UseSIMD)
                            {
                                var vectorGrayCoeff = new Numerics.Vector4(0.11f, 0.59f, 0.3f, 0f);

                                for (int y = 0; y < bitmapData.Height; y++)
                                {
                                    var row3B = (byte *)bitmapData.Scan0 + (y * bitmapData.Stride);
                                    startIndex = y * bitmapData.Width;
                                    if (bitmapData.Stride < 0)
                                    {
                                        startIndex = (pixelCount - bitmapData.Width) - startIndex;
                                    }

                                    for (int i = 0, x = 0; i < bitmapData.Width; i++, x += step)
                                    {
                                        var vectorF = new Numerics.Vector4(row3B[x], row3B[x + 1], row3B[x + 2], 0);
                                        var fGray   = Numerics.Vector4.Dot(vectorF, vectorGrayCoeff);
                                        result[startIndex + i] = fGray;
                                    }
                                }

                                PointwiseDivideInPlace(result, 256.0);
                            }
                            else
                            {
                                for (int y = 0; y < bitmapData.Height; y++)
                                {
                                    var row3B = (byte *)bitmapData.Scan0.ToPointer() + (y * bitmapData.Stride);
                                    startIndex = y * bitmapData.Width;
                                    if (bitmapData.Stride < 0)
                                    {
                                        startIndex = (pixelCount - bitmapData.Width) - startIndex;
                                    }

                                    for (int i = 0, x = 0; i < bitmapData.Width; i++, x += step)
                                    {
                                        double gray = 0.11d * row3B[x] + 0.59d * row3B[x + 1] + 0.11d * row3B[x + 2];
                                        result[startIndex + i] = gray;
                                    }
                                }

                                PointwiseDivideInPlace(result, 256.0);
                            }
                        }
                        else
                        {
                            for (int y = 0; y < bitmapData.Height; y++)
                            {
                                var row3B = (byte *)bitmapData.Scan0 + (y * bitmapData.Stride);
                                startIndex = y * bitmapData.Width;
                                if (bitmapData.Stride < 0)
                                {
                                    startIndex = (pixelCount - bitmapData.Width) - startIndex;
                                }

                                switch (channel)
                                {
                                case BitmapChannel.Red:
                                    for (int i = 0, x = 0; i < bitmapData.Width; i++, x += step)
                                    {
                                        result[startIndex + i] = row3B[x + 2];
                                    }
                                    break;

                                case BitmapChannel.Green:
                                    for (int i = 0, x = 0; i < bitmapData.Width; i++, x += step)
                                    {
                                        result[startIndex + i] = row3B[x + 1];
                                    }
                                    break;

                                case BitmapChannel.Blue:
                                    for (int i = 0, x = 0; i < bitmapData.Width; i++, x += step)
                                    {
                                        result[startIndex + i] = row3B[x];
                                    }
                                    break;

                                case BitmapChannel.Alpha:
                                    if (depth == 32)
                                    {
                                        for (int i = 0, x = 0; i < bitmapData.Width; i++, x += step)
                                        {
                                            result[startIndex + i] = row3B[x + 3];
                                        }
                                    }
                                    else
                                    {
                                        //Do nothing, 24bit images have no alpha channel
                                    }
                                    break;
                                }
                            }

                            PointwiseDivideInPlace(result, 256.0);
                        }
                        break;
                    }
                }
            }
            finally
            {
                bitmap.UnlockBits(bitmapData);
                if (needDispose)
                {
                    bitmap.Dispose();
                }
            }

            return(Vector <double> .Build.Dense(result));
        }
예제 #3
0
 public static Vector <double> BitmapToVector(string fileName, BitmapChannel channel = BitmapChannel.Gray)
 {
     using var bitmap = Bitmap.FromFile(fileName);
     return(BitmapToVector(bitmap as Bitmap, channel));
 }