Esempio n. 1
0
        /// <summary>
        /// Function to transfer a 24 bit rgb image into a <see cref="IGorgonImageBuffer"/>.
        /// </summary>
        /// <param name="bitmapLock">The lock on the bitmap to transfer from.</param>
        /// <param name="buffer">The buffer to transfer into.</param>
        private static void Transfer24Rgb(BitmapData bitmapLock, IGorgonImageBuffer buffer)
        {
            unsafe
            {
                byte *pixels = (byte *)bitmapLock.Scan0.ToPointer();

                for (int y = 0; y < bitmapLock.Height; y++)
                {
                    // We only need the width here, as our pointer will handle the stride by virtue of being an int.
                    byte *offset = pixels + (y * bitmapLock.Stride);

                    int destOffset = y * buffer.PitchInformation.RowPitch;
                    for (int x = 0; x < bitmapLock.Width; x++)
                    {
                        // The DXGI format nomenclature is a little confusing as we tend to think of the layout as being highest to
                        // lowest, but in fact, it is lowest to highest.
                        // So, we must convert to ABGR even though the DXGI format is RGBA. The memory layout is from lowest
                        // (R at byte 0) to the highest byte (A at byte 3).
                        // Thus, R is the lowest byte, and A is the highest: A(24), B(16), G(8), R(0).
                        byte b = *offset++;
                        byte g = *offset++;
                        byte r = *offset++;

                        var  color      = new GorgonColor(r / 255.0f, g / 255.0f, b / 255.0f, 1.0f);
                        int *destBuffer = (int *)(Unsafe.AsPointer(ref buffer.Data[destOffset]));
                        *    destBuffer = color.ToABGR();
                        destOffset += 4;
                    }
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Function to convert the image data into a premultiplied format.
        /// </summary>
        /// <param name="baseImage">The image to convert.</param>
        /// <returns>A <see cref="IGorgonImage"/> containing the image data with the premultiplied alpha pixel data.</returns>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="baseImage"/> is <b>null</b>.</exception>
        /// <exception cref="ArgumentException">Thrown when the original format could not be converted to <see cref="BufferFormat.R8G8B8A8_UNorm"/>.</exception>
        /// <remarks>
        /// <para>
        /// Use this to convert an image to a premultiplied format. This takes each Red, Green and Blue element and multiplies them by the Alpha element.
        /// </para>
        /// <para>
        /// Because this method will only operate on <see cref="BufferFormat.R8G8B8A8_UNorm"/> formattted image data, the image will be converted to that format and converted back to its original format
        /// after the alpha is premultiplied. This may cause color fidelity issues. If the image cannot be converted, then an exception will be thrown.
        /// </para>
        /// </remarks>
        public static IGorgonImage ConvertToPremultipliedAlpha(this IGorgonImage baseImage)
        {
            IGorgonImage newImage = null;

            if (baseImage == null)
            {
                throw new ArgumentNullException(nameof(baseImage));
            }

            try
            {
                // Worker image.
                var cloneImageInfo = new GorgonImageInfo(baseImage)
                {
                    HasPreMultipliedAlpha = true
                };
                newImage = new GorgonImage(cloneImageInfo);
                baseImage.CopyTo(newImage);

                if (newImage.Format != BufferFormat.R8G8B8A8_UNorm)
                {
                    if (!newImage.CanConvertToFormat(BufferFormat.R8G8B8A8_UNorm))
                    {
                        throw new ArgumentException(string.Format(Resources.GORIMG_ERR_FORMAT_NOT_SUPPORTED, BufferFormat.R8G8B8A8_UNorm), nameof(baseImage));
                    }

                    // Clone the image so we can convert it to the correct format.
                    newImage.ConvertToFormat(BufferFormat.R8G8B8A8_UNorm);
                }

                unsafe
                {
                    int *imagePtr = (int *)(newImage.ImageData);

                    for (int i = 0; i < newImage.SizeInBytes; i += newImage.FormatInfo.SizeInBytes)
                    {
                        var color = GorgonColor.FromABGR(*imagePtr);
                        color         = new GorgonColor(color.Red * color.Alpha, color.Green * color.Alpha, color.Blue * color.Alpha, color.Alpha);
                        *(imagePtr++) = color.ToABGR();
                    }
                }

                if (newImage.Format != baseImage.Format)
                {
                    newImage.ConvertToFormat(baseImage.Format);
                }

                newImage.CopyTo(baseImage);

                return(baseImage);
            }
            finally
            {
                newImage?.Dispose();
            }
        }
        /// <summary>
        /// Function to detect if a sprite has no pixel data.
        /// </summary>
        /// <param name="bounds">The bounds of the sprite on the texture.</param>
        /// <param name="imageData">The system memory representation of the texture.</param>
        /// <param name="skipMask">The color used to mask which pixels are considered empty.</param>
        /// <returns><b>true</b> if sprite is empty, <b>false</b> if not.</returns>
        private bool IsEmpty(DX.Rectangle bounds, IGorgonImageBuffer imageData, GorgonColor skipMask)
        {
            int pixelSize = imageData.FormatInformation.SizeInBytes;
            int color     = skipMask.ToABGR();

            for (int y = bounds.Y; y < bounds.Bottom; ++y)
            {
                for (int x = bounds.X; x < bounds.Right; ++x)
                {
                    // The last byte of the pixel should be the alpha (we force conversion to R8G8B8A8).
                    int value = imageData.Data.ReadAs <int>((y * imageData.PitchInformation.RowPitch) + (x * pixelSize));
                    if (color != value)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }