public static Image FromBitmap(Bitmap bitmap)
        {
            if (bitmap == null)
            {
                throw new ArgumentNullException(nameof(bitmap));
            }

            var        width  = bitmap.Width;
            var        height = bitmap.Height;
            var        format = bitmap.PixelFormat;
            int        channels;
            var        byteAllocated = 0;
            ColorSpace colorSpace;

            switch (format)
            {
            case PixelFormat.Format24bppRgb:
                channels      = 3;
                colorSpace    = ColorSpace.Srgb;
                byteAllocated = 1;
                break;

            case PixelFormat.Format32bppArgb:
                channels      = 4;
                colorSpace    = ColorSpace.Srgb;
                byteAllocated = 1;
                break;

            case PixelFormat.Format8bppIndexed:
                channels      = 1;
                colorSpace    = ColorSpace.Gray;
                byteAllocated = 1;
                break;

            default:
                throw new NotSupportedException();
            }
            var precision = 24u / (uint)channels;

            BitmapData bitmapData = null;

            try
            {
                bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, format);
                var stride = bitmapData.Stride;
                var gap    = stride - width * channels;
                var scan0  = bitmapData.Scan0;

                using (var compressionParameters = new CompressionParameters())
                {
                    OpenJpeg.SetDefaultEncoderParameters(compressionParameters);

                    var subsamplingDx = compressionParameters.SubsamplingDx;
                    var subsamplingDy = compressionParameters.SubsamplingDy;

                    var componentParametersArray = new ImageComponentParameters[channels];
                    for (var i = 0; i < channels; i++)
                    {
                        componentParametersArray[i] = new ImageComponentParameters
                        {
                            Precision = precision,
                            Bpp       = precision,
                            Signed    = false,
                            Dx        = (uint)subsamplingDx,
                            Dy        = (uint)subsamplingDy,
                            Width     = (uint)width,
                            Height    = (uint)height
                        };
                    }

                    var image = OpenJpeg.ImageCreate((uint)channels, componentParametersArray, colorSpace);
                    if (image == null)
                    {
                        return(null);
                    }

                    image.X0 = (uint)compressionParameters.ImageOffsetX0;
                    image.Y0 = (uint)compressionParameters.ImageOffsetY0;
                    image.X1 = image.X0 == 0 ? (uint)(width - 1) * (uint)subsamplingDx + 1 : image.X0 + (uint)(width - 1) * (uint)subsamplingDx + 1;
                    image.Y1 = image.Y0 == 0 ? (uint)(height - 1) * (uint)subsamplingDy + 1 : image.Y0 + (uint)(height - 1) * (uint)subsamplingDy + 1;

                    unsafe
                    {
                        // Bitmap data is interleave.
                        // Convert it to planer
                        if (byteAllocated == 1)
                        {
                            for (var i = 0; i < channels; i++)
                            {
                                // need to fix the colorspace
                                IntPtr target;
                                if (channels >= 3)
                                {
                                    if (i == 0)
                                    {
                                        target = image.Components[2].Data; // B-R
                                    }
                                    else if (i == 1)
                                    {
                                        target = image.Components[1].Data; // G-G
                                    }
                                    else if (i == 2)
                                    {
                                        target = image.Components[0].Data; // R-B
                                    }
                                    else
                                    {
                                        target = image.Components[i].Data;
                                    }
                                }
                                else
                                {
                                    target = image.Components[i].Data;
                                }

                                var pTarget = (int *)target;
                                var source  = (byte *)scan0;
                                source += i;
                                for (var y = 0; y < height; y++)
                                {
                                    for (var x = 0; x < width; x++)
                                    {
                                        *pTarget = *source;
                                        pTarget++;
                                        source += channels;
                                    }

                                    source += gap;
                                }
                            }
                        }
                    }

                    return(image);
                }
            }
            finally
            {
                if (bitmapData != null)
                {
                    bitmap.UnlockBits(bitmapData);
                }
            }
        }
        public static Image FromRaw(byte[] raw, int width, int height, int stride, int channels, bool interleaved)
        {
            if (raw == null)
            {
                throw new ArgumentNullException(nameof(raw));
            }

            var byteAllocated = 1;
            var colorSpace    = ColorSpace.Srgb;
            var precision     = 24u / (uint)channels;
            var gap           = stride - width * channels;

            using (var compressionParameters = new CompressionParameters())
            {
                OpenJpeg.SetDefaultEncoderParameters(compressionParameters);

                var subsamplingDx = compressionParameters.SubsamplingDx;
                var subsamplingDy = compressionParameters.SubsamplingDy;

                var componentParametersArray = new ImageComponentParameters[channels];
                for (var i = 0; i < channels; i++)
                {
                    componentParametersArray[i] = new ImageComponentParameters
                    {
                        Precision = precision,
                        Bpp       = precision,
                        Signed    = false,
                        Dx        = (uint)subsamplingDx,
                        Dy        = (uint)subsamplingDy,
                        Width     = (uint)width,
                        Height    = (uint)height
                    };
                }

                var image = OpenJpeg.ImageCreate((uint)channels, componentParametersArray, colorSpace);
                if (image == null)
                {
                    return(null);
                }

                image.X0 = (uint)compressionParameters.ImageOffsetX0;
                image.Y0 = (uint)compressionParameters.ImageOffsetY0;
                image.X1 = image.X0 == 0 ? (uint)(width - 1) * (uint)subsamplingDx + 1 : image.X0 + (uint)(width - 1) * (uint)subsamplingDx + 1;
                image.Y1 = image.Y0 == 0 ? (uint)(height - 1) * (uint)subsamplingDy + 1 : image.Y0 + (uint)(height - 1) * (uint)subsamplingDy + 1;

                unsafe
                {
                    fixed(byte *pRaw = &raw[0])
                    {
                        // Bitmap data is interleave.
                        // Convert it to planer
                        if (byteAllocated == 1)
                        {
                            if (interleaved)
                            {
                                for (var i = 0; i < channels; i++)
                                {
                                    var target  = image.Components[i].Data;
                                    var pTarget = (int *)target;
                                    var source  = pRaw + i;
                                    for (var y = 0; y < height; y++)
                                    {
                                        for (var x = 0; x < width; x++)
                                        {
                                            *pTarget = *source;
                                            pTarget++;
                                            source += channels;
                                        }

                                        source += gap;
                                    }
                                }
                            }
                            else
                            {
                                for (var i = 0; i < channels; i++)
                                {
                                    var target  = image.Components[i].Data;
                                    var pTarget = (int *)target;
                                    var source  = pRaw + i * (stride * height);
                                    for (var y = 0; y < height; y++)
                                    {
                                        for (var x = 0; x < width; x++)
                                        {
                                            *pTarget = *source;
                                            pTarget++;
                                            source++;
                                        }

                                        source += gap;
                                    }
                                }
                            }
                        }
                    }
                }

                return(image);
            }
        }