Exemplo n.º 1
0
        /// <summary>
        /// Function to retrieve an image based on the current depth slice.
        /// </summary>
        /// <param name="sourceImage">The image to extract the depth slice from.</param>
        /// <param name="currentDepthSlice">The depth slice to extract.</param>
        /// <returns>A new image with the specified depth slice.</returns>
        public IGorgonImage GetDepthSliceAsImage(IGorgonImage sourceImage, int currentDepthSlice)
        {
            if (sourceImage.MipCount == 1)
            {
                return(sourceImage);
            }

            IGorgonImage result = new GorgonImage(new GorgonImageInfo(sourceImage, ImageType.Image2D)
            {
                Depth = 1
            });

            for (int mip = 0; mip < result.MipCount; ++mip)
            {
                int depthCount = sourceImage.GetDepthCount(mip);

                if (currentDepthSlice >= depthCount)
                {
                    return(result);
                }

                IGorgonImageBuffer srcBuffer  = sourceImage.Buffers[mip, currentDepthSlice];
                IGorgonImageBuffer destBuffer = result.Buffers[mip];

                srcBuffer.CopyTo(destBuffer);
            }

            return(result);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Function to retrieve an image based on the current mip level.
        /// </summary>
        /// <param name="sourceImage">The image to extract the mip level from.</param>
        /// <param name="currentMipLevel">The mip level to extract.</param>
        /// <returns>A new image with the specified mip level.</returns>
        public IGorgonImage GetMipLevelAsImage(IGorgonImage sourceImage, int currentMipLevel)
        {
            if (sourceImage.MipCount == 1)
            {
                return(sourceImage);
            }

            int depthCount = 1;

            if (sourceImage.ImageType == ImageType.Image3D)
            {
                depthCount = sourceImage.GetDepthCount(currentMipLevel);
            }

            IGorgonImage result = new GorgonImage(new GorgonImageInfo(sourceImage)
            {
                Width    = sourceImage.Buffers[currentMipLevel].Width,
                Height   = sourceImage.Buffers[currentMipLevel].Height,
                Depth    = depthCount,
                MipCount = 1
            });

            for (int array = 0; array < sourceImage.ArrayCount; ++array)
            {
                for (int depth = 0; depth < result.Depth; ++depth)
                {
                    IGorgonImageBuffer srcBuffer  = sourceImage.Buffers[currentMipLevel, sourceImage.ImageType == ImageType.Image3D ? depth : array];
                    IGorgonImageBuffer destBuffer = result.Buffers[0, sourceImage.ImageType == ImageType.Image3D ? depth : array];

                    srcBuffer.CopyTo(destBuffer);
                }
            }

            return(result);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Function to convert the image to B4G4R4A4.
        /// </summary>
        /// <param name="baseImage">The base image to convert.</param>
        /// <param name="dithering">Dithering to apply to the converstion to B8G8R8A8.</param>
        /// <returns>The updated image.</returns>
        private static IGorgonImage ConvertToB4G4R4A4(IGorgonImage baseImage, ImageDithering dithering)
        {
            // This temporary image will be used to convert to B8G8R8A8.
            IGorgonImage newImage = baseImage;

            IGorgonImageInfo destInfo = new GorgonImageInfo(baseImage.ImageType, BufferFormat.B4G4R4A4_UNorm)
            {
                Depth      = baseImage.Depth,
                Height     = baseImage.Height,
                Width      = baseImage.Width,
                ArrayCount = baseImage.ArrayCount,
                MipCount   = baseImage.MipCount
            };

            // This is our working buffer for B4G4R4A4.
            IGorgonImage destImage = new GorgonImage(destInfo);

            try
            {
                // If necessary, convert to B8G8R8A8. Otherwise, we'll just downsample directly.
                if ((newImage.Format != BufferFormat.B8G8R8A8_UNorm) &&
                    (newImage.Format != BufferFormat.R8G8B8A8_UNorm))
                {
                    newImage = baseImage.Clone();
                    ConvertToFormat(newImage, BufferFormat.B8G8R8A8_UNorm, dithering);
                }

                // The next step is to manually downsample to R4G4B4A4.
                // Because we're doing this manually, dithering won't be an option unless unless we've downsampled from a much higher bit format when converting to B8G8R8A8.
                for (int array = 0; array < newImage.ArrayCount; ++array)
                {
                    for (int mip = 0; mip < newImage.MipCount; ++mip)
                    {
                        int depthCount = newImage.GetDepthCount(mip);

                        for (int depth = 0; depth < depthCount; depth++)
                        {
                            IGorgonImageBuffer destBuffer = destImage.Buffers[mip, destInfo.ImageType == ImageType.Image3D ? depth : array];
                            IGorgonImageBuffer srcBuffer  = newImage.Buffers[mip, newImage.ImageType == ImageType.Image3D ? depth : array];

                            ConvertPixelsToB4G4R4A4(destBuffer, srcBuffer);
                        }
                    }
                }

                destImage.CopyTo(baseImage);

                return(baseImage);
            }
            finally
            {
                destImage.Dispose();

                if (newImage != baseImage)
                {
                    newImage.Dispose();
                }
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Function to convert the image from B4G4R4A4.
        /// </summary>
        /// <param name="baseImage">The base image to convert.</param>
        /// <param name="destFormat">The destination format.</param>
        /// <returns>The updated image.</returns>
        private static IGorgonImage ConvertFromB4G4R4A4(IGorgonImage baseImage, BufferFormat destFormat)
        {
            // If we're converting to R8G8B8A8 or B8G8R8A8, then use those formats, otherwise, default to B8G8R8A8 as an intermediate buffer.
            BufferFormat tempFormat = ((destFormat != BufferFormat.B8G8R8A8_UNorm) && (destFormat != BufferFormat.R8G8B8A8_UNorm)) ? BufferFormat.B8G8R8A8_UNorm : destFormat;

            // Create an worker image in B8G8R8A8 format.
            IGorgonImageInfo destInfo = new GorgonImageInfo(baseImage.ImageType, tempFormat)
            {
                Depth      = baseImage.Depth,
                Height     = baseImage.Height,
                Width      = baseImage.Width,
                ArrayCount = baseImage.ArrayCount,
                MipCount   = baseImage.MipCount
            };

            // Our destination image for B8G8R8A8 or R8G8B8A8.
            var destImage = new GorgonImage(destInfo);

            try
            {
                // We have to manually upsample from R4G4B4A4 to B8R8G8A8.
                // Because we're doing this manually, dithering won't be an option unless
                for (int array = 0; array < baseImage.ArrayCount; ++array)
                {
                    for (int mip = 0; mip < baseImage.MipCount; ++mip)
                    {
                        int depthCount = baseImage.GetDepthCount(mip);

                        for (int depth = 0; depth < depthCount; depth++)
                        {
                            IGorgonImageBuffer destBuffer = destImage.Buffers[mip, baseImage.ImageType == ImageType.Image3D ? depth : array];
                            IGorgonImageBuffer srcBuffer  = baseImage.Buffers[mip, baseImage.ImageType == ImageType.Image3D ? depth : array];

                            ConvertPixelsFromB4G4R4A4(destBuffer, srcBuffer);
                        }
                    }
                }

                // If the destination format is not R8G8B8A8 or B8G8R8A8, then we need to do more conversion.
                if (destFormat != destImage.Format)
                {
                    ConvertToFormat(destImage, destFormat);
                }

                // Update the base image with our worker image.
                destImage.CopyTo(baseImage);

                return(baseImage);
            }
            finally
            {
                destImage.Dispose();
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Function to copy an image onto another image, using the supplied alignment.
        /// </summary>
        /// <param name="srcImage">The image to copy.</param>
        /// <param name="destImage">The destination image.</param>
        /// <param name="startMip">The starting mip map level to copy.</param>
        /// <param name="startArrayOrDepth">The starting array index for 2D images, or depth slice for 3D images.</param>
        /// <param name="alignment">The alignment of the image, relative to the source image.</param>
        public void CopyTo(IGorgonImage srcImage, IGorgonImage destImage, int startMip, int startArrayOrDepth, Alignment alignment)
        {
            int mipCount   = destImage.MipCount - startMip;
            int arrayCount = destImage.ArrayCount - (destImage.ImageType == ImageType.Image3D ? 0 : startArrayOrDepth);

            int minMipCount   = mipCount.Min(srcImage.MipCount);
            int minArrayCount = arrayCount.Min(srcImage.ArrayCount);

            var size = new DX.Size2(srcImage.Width, srcImage.Height);

            for (int array = 0; array < minArrayCount; ++array)
            {
                for (int mip = 0; mip < minMipCount; ++mip)
                {
                    int destDepthCount = destImage.GetDepthCount(mip + startMip);
                    int minDepth       = destDepthCount.Min(srcImage.GetDepthCount(mip));

                    for (int depth = 0; depth < minDepth; ++depth)
                    {
                        int destOffset;
                        if (destImage.ImageType == ImageType.Image3D)
                        {
                            destOffset = depth + startArrayOrDepth;

                            // We're at the end of the destination buffer, skip the rest of the slices.
                            if (destOffset >= destDepthCount)
                            {
                                break;
                            }
                        }
                        else
                        {
                            destOffset = array + startArrayOrDepth;
                        }

                        IGorgonImageBuffer srcBuffer  = srcImage.Buffers[mip, srcImage.ImageType == ImageType.Image3D ? depth : array];
                        IGorgonImageBuffer destBuffer = destImage.Buffers[mip + startMip, destOffset];

                        // Clear the destination buffer before copying.
                        destBuffer.Data.Fill(0);

                        int minWidth   = destBuffer.Width.Min(srcBuffer.Width);
                        int minHeight  = destBuffer.Height.Min(srcBuffer.Height);
                        var copyRegion = new DX.Rectangle(0, 0, minWidth, minHeight);

                        DX.Point startLoc = GetAnchorStart(new DX.Size2(minWidth, minHeight), ref size, alignment);

                        srcBuffer.CopyTo(destBuffer, copyRegion, startLoc.X, startLoc.Y);
                    }
                }
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Function to update the depth slice count for a 3D image, or the array index count for a 2D/cube image.
        /// </summary>
        /// <param name="sourceImage">The image to update.</param>
        /// <param name="arrayOrDepthCount">The new depth or array count.</param>
        /// <returns>A new image with the specified depth/array count, or the same image if no changes were made.</returns>
        public IGorgonImage ChangeArrayOrDepthCount(IGorgonImage sourceImage, int arrayOrDepthCount)
        {
            int currentArrayOrDepth = sourceImage.ImageType == ImageType.Image3D ? sourceImage.Depth : sourceImage.ArrayCount;
            int depthCount          = sourceImage.ImageType == ImageType.Image3D ? arrayOrDepthCount : 1;
            int arrayCount          = sourceImage.ImageType != ImageType.Image3D ? arrayOrDepthCount : 1;

            if (currentArrayOrDepth == arrayOrDepthCount)
            {
                return(sourceImage);
            }

            IGorgonImage newImage = new GorgonImage(new GorgonImageInfo(sourceImage)
            {
                Depth      = depthCount,
                ArrayCount = arrayCount
            });

            for (int array = 0; array < arrayCount.Min(sourceImage.ArrayCount); ++array)
            {
                for (int mip = 0; mip < sourceImage.MipCount; ++mip)
                {
                    for (int depth = 0; depth < depthCount.Min(sourceImage.GetDepthCount(mip)); ++depth)
                    {
                        IGorgonImageBuffer srcBuffer  = sourceImage.Buffers[mip, sourceImage.ImageType == ImageType.Image3D ? depth : array];
                        IGorgonImageBuffer destBuffer = newImage.Buffers[mip, sourceImage.ImageType == ImageType.Image3D ? depth : array];
                        srcBuffer.CopyTo(destBuffer);
                    }

                    depthCount >>= 1;

                    if (depthCount < 1)
                    {
                        depthCount = 1;
                    }
                }
            }

            return(newImage);
        }