コード例 #1
0
        /// <summary>
        /// Creates a <see cref="Bitmap"/> from the image.
        /// </summary>
        /// <param name="makeCopy">Indicates whether to make a copy of the image data or not.</param>
        /// <returns>A corresponding <see cref="Bitmap"/> image.</returns>
        /// <remarks>If the <paramref name="makeCopy"/> parameter is set to <see langword="true"/>, then the method
        /// creates a copy of the image, so the <see cref="Bitmap"/> stays valid even when the
        /// image gets disposed. However, setting this parameter to <see langword="false"/> creates a <see cref="Bitmap"/> image which is just a wrapper around the image data. In this case, if the image is disposed, the
        /// will no longer be valid and accessing it will generate an exception.</remarks>
        public Bitmap ToBitmap(bool makeCopy = true)
        {
            Bitmap bitmap = null;

            try
            {
                if (!makeCopy)
                {
                    bitmap = new Bitmap(this.width, this.height, this.stride, PixelFormatHelper.ToSystemPixelFormat(this.pixelFormat), this.image.Data);
                    if (this.pixelFormat == PixelFormat.Gray_8bpp)
                    {
                        Operators.SetGrayscalePalette(bitmap);
                    }
                }
                else
                {
                    // create new image of required format
                    bitmap = new Bitmap(this.width, this.height, PixelFormatHelper.ToSystemPixelFormat(this.pixelFormat));
                    if (this.pixelFormat == PixelFormat.Gray_8bpp)
                    {
                        // set palette to grayscale
                        Operators.SetGrayscalePalette(bitmap);
                    }

                    // lock destination bitmap data
                    BitmapData bitmapData = bitmap.LockBits(
                        new Rectangle(0, 0, this.width, this.height),
                        ImageLockMode.ReadWrite,
                        PixelFormatHelper.ToSystemPixelFormat(this.pixelFormat));

                    int bitmapStride = bitmapData.Stride;
                    int lineSize     = Math.Min(this.stride, bitmapStride);

                    unsafe
                    {
                        byte *dst = (byte *)bitmapData.Scan0.ToPointer();
                        byte *src = (byte *)this.image.Data.ToPointer();

                        if (this.stride != bitmapStride)
                        {
                            // copy image
                            for (int y = 0; y < this.height; y++)
                            {
                                Buffer.MemoryCopy(src, dst, lineSize, lineSize);
                                dst += bitmapStride;
                                src += this.stride;
                            }
                        }
                        else
                        {
                            var size = this.stride * this.height;
                            Buffer.MemoryCopy(src, dst, size, size);
                        }
                    }

                    // unlock destination images
                    bitmap.UnlockBits(bitmapData);
                }

                return(bitmap);
            }
            catch (Exception)
            {
                if (bitmap != null)
                {
                    bitmap.Dispose();
                }

                throw new Exception("The image has some invalid properties, which caused a failure while converting it to managed image.");
            }
        }
コード例 #2
0
        private void CopyImageSlow(IntPtr sourceIntPtr, PixelFormat sourceFormat, IntPtr destinationIntPtr, int destinationStride, PixelFormat destinationFormat)
        {
            unsafe
            {
                int srcBytesPerPixel = sourceFormat.GetBytesPerPixel();
                int dstBytesPerPixel = destinationFormat.GetBytesPerPixel();
                Parallel.For(
                    0,
                    this.Height,
                    i =>
                {
                    byte *srcCol = (byte *)sourceIntPtr.ToPointer() + (i * this.stride);
                    byte *dstCol = (byte *)destinationIntPtr.ToPointer() + (i * destinationStride);
                    for (int j = 0; j < this.width; j++)
                    {
                        int red;
                        int green;
                        int blue;
                        int alpha;
                        int bits;
                        switch (sourceFormat)
                        {
                        case PixelFormat.Gray_8bpp:
                            red   = green = blue = srcCol[0];
                            alpha = 255;
                            bits  = 8;
                            break;

                        case PixelFormat.Gray_16bpp:
                            red   = green = blue = ((ushort *)srcCol)[0];
                            alpha = 65535;
                            bits  = 16;
                            break;

                        case PixelFormat.BGR_24bpp:
                        case PixelFormat.BGRX_32bpp:
                            blue  = srcCol[0];
                            green = srcCol[1];
                            red   = srcCol[2];
                            alpha = 255;
                            bits  = 8;
                            break;

                        case PixelFormat.BGRA_32bpp:
                            blue  = srcCol[0];
                            green = srcCol[1];
                            red   = srcCol[2];
                            alpha = srcCol[3];
                            bits  = 8;
                            break;

                        case PixelFormat.RGB_24bpp:
                            red   = srcCol[0];
                            green = srcCol[1];
                            blue  = srcCol[2];
                            alpha = 255;
                            bits  = 8;
                            break;

                        case PixelFormat.RGBA_64bpp:
                            red   = ((ushort *)srcCol)[0];
                            green = ((ushort *)srcCol)[1];
                            blue  = ((ushort *)srcCol)[2];
                            alpha = ((ushort *)srcCol)[3];
                            bits  = 16;
                            break;

                        case PixelFormat.Undefined:
                        default:
                            throw new ArgumentException(ExceptionDescriptionUnexpectedPixelFormat);
                        }

                        // Convert from 8-bits-per-channel (0-255) to 16-bits-per-channel (0-65535) and visa versa when needed.
                        switch (destinationFormat)
                        {
                        case PixelFormat.Gray_8bpp:
                        case PixelFormat.BGR_24bpp:
                        case PixelFormat.BGRX_32bpp:
                        case PixelFormat.BGRA_32bpp:
                        case PixelFormat.RGB_24bpp:
                            if (bits == 16)
                            {
                                red   >>= 8;
                                green >>= 8;
                                blue  >>= 8;
                                alpha >>= 8;
                            }

                            break;

                        case PixelFormat.Gray_16bpp:
                        case PixelFormat.RGBA_64bpp:
                            if (bits == 8)
                            {
                                red   = (red << 8) | red;
                                green = (green << 8) | green;
                                blue  = (blue << 8) | blue;
                                alpha = (alpha << 8) | alpha;
                            }

                            break;
                        }

                        switch (destinationFormat)
                        {
                        case PixelFormat.Gray_8bpp:
                            dstCol[0] = Operators.Rgb2Gray((byte)red, (byte)green, (byte)blue);
                            break;

                        case PixelFormat.Gray_16bpp:
                            ((ushort *)dstCol)[0] = Operators.Rgb2Gray((ushort)red, (ushort)green, (ushort)blue);
                            break;

                        case PixelFormat.BGR_24bpp:
                        case PixelFormat.BGRX_32bpp:
                            dstCol[0] = (byte)blue;
                            dstCol[1] = (byte)green;
                            dstCol[2] = (byte)red;
                            break;

                        case PixelFormat.BGRA_32bpp:
                            dstCol[0] = (byte)blue;
                            dstCol[1] = (byte)green;
                            dstCol[2] = (byte)red;
                            dstCol[3] = (byte)alpha;
                            break;

                        case PixelFormat.RGB_24bpp:
                            dstCol[0] = (byte)red;
                            dstCol[1] = (byte)green;
                            dstCol[2] = (byte)blue;
                            break;

                        case PixelFormat.RGBA_64bpp:
                            ((ushort *)dstCol)[0] = (ushort)red;
                            ((ushort *)dstCol)[1] = (ushort)green;
                            ((ushort *)dstCol)[2] = (ushort)blue;
                            ((ushort *)dstCol)[3] = (ushort)alpha;
                            break;

                        case PixelFormat.Undefined:
                        default:
                            throw new ArgumentException(ExceptionDescriptionUnexpectedPixelFormat);
                        }

                        srcCol += srcBytesPerPixel;
                        dstCol += dstBytesPerPixel;
                    }
                });
            }
        }
コード例 #3
0
        /// <summary>
        /// Copies the image to a destination pointer.
        /// </summary>
        /// <param name="destination">The destination pointer to copy the image to.</param>
        /// <param name="width">The destination width.</param>
        /// <param name="height">The destination height.</param>
        /// <param name="stride">The destination stride.</param>
        /// <param name="pixelFormat">The destination pixel format.</param>
        public void CopyTo(IntPtr destination, int width, int height, int stride, PixelFormat pixelFormat)
        {
            if ((this.width != width) || (this.height != height))
            {
                throw new InvalidOperationException("Destination image has different size.");
            }

            // Check if pixel formats are the same. If so, do a straight up copy
            if (this.PixelFormat == pixelFormat)
            {
                if (this.stride == stride)
                {
                    this.image.CopyTo(destination, stride * height);
                }
                else
                {
                    unsafe
                    {
                        int copyLength = (this.stride < stride) ? this.stride : stride;

                        byte *src = (byte *)this.image.Data.ToPointer();
                        byte *dst = (byte *)destination.ToPointer();

                        // copy line by line
                        for (int i = 0; i < this.height; i++)
                        {
                            Buffer.MemoryCopy(src, dst, copyLength, copyLength);

                            dst += stride;
                            src += this.stride;
                        }
                    }
                }
            }
            else if ((this.pixelFormat == PixelFormat.BGR_24bpp) &&
                     (pixelFormat == PixelFormat.BGRX_32bpp ||
                      pixelFormat == PixelFormat.BGRA_32bpp))
            {
                unsafe
                {
                    byte *src = (byte *)this.image.Data.ToPointer();
                    byte *dst = (byte *)destination.ToPointer();
                    Parallel.For(0, this.Height, i =>
                    {
                        byte *srcCopy = src + (this.stride * i);
                        byte *dstCopy = dst + (stride * i);
                        for (int j = 0; j < this.width; j++)
                        {
                            *dstCopy++ = *srcCopy++;
                            *dstCopy++ = *srcCopy++;
                            *dstCopy++ = *srcCopy++;
                            *dstCopy++ = 255;
                        }
                    });
                }
            }
            else if ((this.pixelFormat == PixelFormat.BGRX_32bpp) &&
                     (pixelFormat == PixelFormat.BGR_24bpp))
            {
                unsafe
                {
                    byte *src = (byte *)this.image.Data.ToPointer();
                    byte *dst = (byte *)destination.ToPointer();
                    Parallel.For(0, this.Height, i =>
                    {
                        byte *srcCopy = src + (this.stride * i);
                        byte *dstCopy = dst + (stride * i);
                        for (int j = 0; j < this.width; j++)
                        {
                            *dstCopy++ = *srcCopy++;
                            *dstCopy++ = *srcCopy++;
                            *dstCopy++ = *srcCopy++;
                            srcCopy++;
                        }
                    });
                }
            }
            else if ((this.pixelFormat == PixelFormat.BGR_24bpp) &&
                     (pixelFormat == PixelFormat.Gray_8bpp))
            {
                unsafe
                {
                    byte *src = (byte *)this.image.Data.ToPointer();
                    byte *dst = (byte *)destination.ToPointer();

                    Parallel.For(0, this.Height, i =>
                    {
                        byte *srcCopy = src + (this.stride * i);
                        byte *dstCopy = dst + (stride * i);
                        for (int j = 0; j < this.width; j++)
                        {
                            *dstCopy++ = Operators.Rgb2Gray(srcCopy[2], srcCopy[1], srcCopy[0]);
                            srcCopy   += 3;
                        }
                    });
                }
            }
            else if ((this.pixelFormat == PixelFormat.Gray_16bpp) &&
                     (pixelFormat == PixelFormat.Gray_8bpp))
            {
                unsafe
                {
                    byte *src = (byte *)this.image.Data.ToPointer();
                    byte *dst = (byte *)destination.ToPointer();

                    Parallel.For(0, this.Height, i =>
                    {
                        byte *srcCopy = src + (this.stride * i);
                        byte *dstCopy = dst + (stride * i);
                        for (int j = 0; j < this.width; j++)
                        {
                            // copy msb only
                            *dstCopy++ = *(srcCopy + 1);
                            srcCopy   += 2;
                        }
                    });
                }
            }
            else if ((this.pixelFormat == PixelFormat.Gray_8bpp) &&
                     (pixelFormat == PixelFormat.Gray_16bpp))
            {
                unsafe
                {
                    byte *src = (byte *)this.image.Data.ToPointer();
                    byte *dst = (byte *)destination.ToPointer();

                    Parallel.For(0, this.Height, i =>
                    {
                        byte *srcCopy = src + (this.stride * i);
                        byte *dstCopy = dst + (stride * i);
                        for (int j = 0; j < this.width; j++)
                        {
                            // dest = (src << 8) | src
                            *dstCopy++ = *srcCopy;
                            *dstCopy++ = *srcCopy++;
                        }
                    });
                }
            }
            else if ((this.pixelFormat == PixelFormat.Gray_8bpp) &&
                     (pixelFormat == PixelFormat.BGRA_32bpp))
            {
                unsafe
                {
                    byte *src = (byte *)this.image.Data.ToPointer();
                    byte *dst = (byte *)destination.ToPointer();

                    Parallel.For(0, this.Height, i =>
                    {
                        byte *srcCopy = src + (this.stride * i);
                        byte *dstCopy = dst + (stride * i);
                        for (int j = 0; j < this.width; j++)
                        {
                            // dest = (src << 24) | (src << 16) | (src << 8) | 0xff
                            *dstCopy++ = *srcCopy;
                            *dstCopy++ = *srcCopy;
                            *dstCopy++ = *srcCopy++;
                            *dstCopy++ = 0xff; // alpha
                        }
                    });
                }
            }
            else
            {
                this.CopyImageSlow(this.image.Data, this.pixelFormat, destination, stride, pixelFormat);
            }
        }