public override void UpdateSubResource(GorgonImageBuffer buffer, Rectangle destRect, int destArrayIndex = 0, int destMipLevel = 0, GorgonGraphics deferred = null) { throw new NotSupportedException(Resources.GORGFX_DEPTH_OPERATION_NOT_SUPPORTED); }
/// <summary> /// Function to clip a bitmap. /// </summary> /// <param name="bitmap">Bitmap to clip.</param> /// <param name="buffer">Buffer containing clipped data.</param> private void ClipBitmap(WIC.BitmapSource bitmap, GorgonImageBuffer buffer) { using (var clipper = new WIC.BitmapClipper(Factory)) { clipper.Initialize(bitmap, new DX.Rectangle(0, 0, buffer.Width < bitmap.Size.Width ? buffer.Width : bitmap.Size.Width, buffer.Height < bitmap.Size.Height ? buffer.Height : bitmap.Size.Height)); clipper.CopyPixels(buffer.PitchInformation.RowPitch, buffer.Data.BasePointer, buffer.PitchInformation.SlicePitch); } }
/// <summary> /// Function to copy data from the CPU to the texture on the GPU. /// </summary> /// <param name="buffer">A buffer containing the image data to copy.</param> /// <param name="destBox">A 3D box that will specify the region that will receive the data.</param> /// <param name="destArrayIndex">[Optional] The array index that will receive the data.</param> /// <param name="destMipLevel">[Optional] The mip map level that will receive the data.</param> /// <param name="deferred">[Optional] A deferred graphics context used to copy the data.</param> /// <exception cref="System.InvalidOperationException">Thrown when the texture is dynamic or immutable. /// <para>-or-</para> /// <para>Thrown when the texture is multisampled.</para> /// </exception> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="destArrayIndex"/> or the <paramref name="destMipLevel"/> is less than 0 or greater than/equal to the /// number of array indices or mip levels in the texture.</exception> /// <remarks> /// Use this to copy data into a texture with a usage of staging or default. If the <paramref name="destBox"/> values are larger than the dimensions of the texture, then the data will be clipped. /// <para>Passing NULL (Nothing in VB.Net) to the <paramref name="destArrayIndex"/> and/or the <paramref name="destMipLevel"/> parameters will use the first array index and/or mip map level.</para> /// <para>This method will not work with depth/stencil textures or with textures that have multisampling applied.</para> /// <para>If the <paramref name="deferred"/> parameter is NULL (Nothing in VB.Net) then the immediate context will be used. If this method is called from multiple threads, then a deferred context should be passed for each thread that is /// accessing the sub resource.</para> /// </remarks> public void UpdateSubResource(GorgonImageBuffer buffer, GorgonBox destBox, int destArrayIndex = 0, int destMipLevel = 0, GorgonGraphics deferred = null) { OnUpdateSubResource(buffer, destBox, destArrayIndex, destMipLevel, deferred); }
/// <summary> /// Function to create a WIC bitmap from a Gorgon image buffer. /// </summary> /// <param name="buffer">Image buffer containing the image data to convert.</param> /// <returns>The WIC bitmap.</returns> public WIC.Bitmap CreateWICBitmapFromImageBuffer(GorgonImageBuffer buffer) { var pointer = new DX.DataRectangle(buffer.Data.BasePointer, buffer.PitchInformation.RowPitch); Guid bitmapFormat = GetGUID(buffer.Format); if (bitmapFormat == Guid.Empty) { throw new GorgonException(GorgonResult.FormatNotSupported, string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, buffer.Format)); } return(new WIC.Bitmap(Factory, buffer.Width, buffer.Height, bitmapFormat, pointer, pointer.Pitch * buffer.Height)); }
/// <summary> /// Function to copy data from the CPU to the texture on the GPU. /// </summary> /// <param name="buffer">A buffer containing the image data to copy.</param> /// <param name="destRect">A rectangle that will specify the region that will receive the data.</param> /// <param name="destArrayIndex">[Optional] The array index that will receive the data.</param> /// <param name="destMipLevel">[Optional] The mip map level that will receive the data.</param> /// <param name="deferred">[Optional] A deferred graphics context used to copy the data.</param> /// <exception cref="System.InvalidOperationException">Thrown when the texture is dynamic or immutable. /// <para>-or-</para> /// <para>Thrown when the texture is multisampled.</para> /// </exception> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="destArrayIndex"/> or the <paramref name="destMipLevel"/> is less than 0 or greater than/equal to the /// number of array indices or mip levels in the texture.</exception> /// <remarks> /// Use this to copy data into a texture with a usage of staging or default. If the <paramref name="destRect"/> values are larger than the dimensions of the texture, then the data will be clipped. /// <para>Passing NULL (Nothing in VB.Net) to the <paramref name="destArrayIndex"/> and/or the <paramref name="destMipLevel"/> parameters will use the first array index and/or mip map level.</para> /// <para>This method will not work with depth/stencil textures or with textures that have multisampling applied.</para> /// <para>If the <paramref name="deferred"/> parameter is NULL (Nothing in VB.Net) then the immediate context will be used. If this method is called from multiple threads, then a deferred context should be passed for each thread that is /// accessing the sub resource.</para> /// </remarks> public virtual void UpdateSubResource(GorgonImageBuffer buffer, Rectangle destRect, int destArrayIndex = 0, int destMipLevel = 0, GorgonGraphics deferred = null) { OnUpdateSubResource(buffer, new GorgonBox { Front = 0, Depth = 1, Left = destRect.Left, Width = destRect.Width, Top = destRect.Top, Height = destRect.Height }, destArrayIndex, destMipLevel, deferred); }
/// <summary> /// Function to copy data from the CPU to the texture on the GPU. /// </summary> /// <param name="buffer">A buffer containing the image data to copy.</param> /// <param name="destRange">A start and end range value that will specify the region that will receive the data.</param> /// <param name="destArrayIndex">[Optional] The array index that will receive the data.</param> /// <param name="destMipLevel">[Optional] The mip map level that will receive the data.</param> /// <param name="deferred">[Optional] A deferred graphics context used to copy the data.</param> /// <exception cref="System.InvalidOperationException">Thrown when the texture is dynamic or immutable. /// <para>-or-</para> /// <para>Thrown when the texture is multisampled.</para> /// </exception> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the <paramref name="destArrayIndex"/> or the <paramref name="destMipLevel"/> is less than 0 or greater than/equal to the /// number of array indices or mip levels in the texture.</exception> /// <remarks> /// Use this to copy data into a texture with a usage of staging or default. If the <paramref name="destRange"/> values are larger than the dimensions of the texture, then the data will be clipped. /// <para>Passing NULL (Nothing in VB.Net) to the <paramref name="destArrayIndex"/> and/or the <paramref name="destMipLevel"/> parameters will use the first array index and/or mip map level.</para> /// <para>This method will not work with depth/stencil textures or with textures that have multisampling applied.</para> /// <para>If the <paramref name="deferred"/> parameter is NULL (Nothing in VB.Net) then the immediate context will be used. If this method is called from multiple threads, then a deferred context should be passed for each thread that is /// accessing the sub resource.</para> /// </remarks> public virtual void UpdateSubResource(GorgonImageBuffer buffer, GorgonRange destRange, int destArrayIndex = 0, int destMipLevel = 0, GorgonGraphics deferred = null) { OnUpdateSubResource(buffer, new GorgonBox { Front = 0, Depth = 1, Left = destRange.Minimum, Width = destRange.Maximum, Top = 0, Height = 1 }, destArrayIndex, destMipLevel, deferred); }
/// <summary> /// Function to copy the image buffer data from this buffer into another. /// </summary> /// <param name="buffer">The buffer to copy into.</param> /// <param name="sourceRegion">[Optional] The region in the source to copy.</param> /// <param name="destX">[Optional] Horizontal offset in the destination buffer.</param> /// <param name="destY">[Optional] Vertical offset in the destination buffer.</param> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="buffer" /> parameter is NULL (Nothing in VB.Net).</exception> /// <exception cref="System.ArgumentException">Thrown when the <paramref name="buffer" /> is not the same format as this buffer.</exception> /// <exception cref="System.ArgumentOutOfRangeException">Thrown when the source region does not fit within the bounds of this buffer.</exception> /// <remarks> /// This method will copy the contents of this buffer into another buffer and will provide clipping to handle cases where the buffer or <paramref name="sourceRegion" /> is mismatched with the /// destination size. /// <para>Users may define an area on this buffer to copy by specifying the <paramref name="sourceRegion" /> parameter. If NULL (Nothing in VB.Net) is passed to this parameter, then the /// entire buffer will be copied to the destination.</para><para>An offset into the destination buffer may also be specified to relocate the data copied from this buffer into the destination. Clipping will be applied if the offset pushes the /// source data outside of the boundaries of the destination buffer.</para><para>The destination buffer must be the same format as the source buffer. If it is not, then an exception will be thrown.</para> /// <para>The <paramref name="buffer"/> parameter must not be the same as the this buffer. An exception will be thrown if an attempt to copy this buffer into itself is made.</para> /// <para>If the source region does not fit within the bounds of this buffer, then an exception will be thrown.</para> /// </remarks> public unsafe void CopyTo(GorgonImageBuffer buffer, Rectangle?sourceRegion = null, int destX = 0, int destY = 0) { var sourceBufferDims = new Rectangle(0, 0, Width, Height); Rectangle srcRegion = sourceRegion != null ? sourceRegion.Value : sourceBufferDims; if ((buffer == null) || (buffer.Data == null) || (buffer.Data.Length == 0)) { throw new ArgumentNullException("buffer"); } if ((buffer == this) || (buffer.Data.UnsafePointer == Data.UnsafePointer)) { throw new ArgumentException(Resources.GORGFX_IMAGE_BUFFER_CANT_BE_SAME, "buffer"); } if (buffer.Format != Format) { throw new ArgumentException(Resources.GORGFX_IMAGE_MUST_BE_SAME_FORMAT, "buffer"); } if (!sourceBufferDims.Contains(srcRegion)) { throw new ArgumentOutOfRangeException("sourceRegion"); } // If we try to place this image outside of the target buffer, then do nothing. if ((destX >= buffer.Width) || (destY >= buffer.Height)) { return; } // Adjust in case we're trying to move off the target. if (destX < 0) { srcRegion.X -= destX; srcRegion.Width += destX; destX = 0; } if (destY < 0) { srcRegion.Y -= destY; srcRegion.Height += destY; destY = 0; } // Ensure that the regions actually fit within their respective buffers. srcRegion = Rectangle.FromLTRB(srcRegion.X.Max(0), srcRegion.Y.Max(0), srcRegion.Right.Min(Width), srcRegion.Bottom.Min(Height)); Rectangle dstRegion = Rectangle.FromLTRB(destX, destY, (destX + buffer.Width).Min(buffer.Width), (destY + buffer.Height).Min(buffer.Height)); // If the source/dest region is empty, then we have nothing to copy. if ((srcRegion.IsEmpty) || (dstRegion.IsEmpty) || (dstRegion.Right < 0) || (dstRegion.Bottom < 0)) { return; } // If the buffers are identical in dimensions and have no offset, then just do a straight copy. if (srcRegion == dstRegion) { DirectAccess.MemoryCopy(buffer.Data.UnsafePointer, Data.UnsafePointer, (int)Data.Length); return; } // Find out how many bytes each pixel occupies. int dataSize = PitchInformation.RowPitch / Width; int srcLineSize = dataSize * srcRegion.Width; // Number of source bytes/scanline. var srcData = ((byte *)Data.UnsafePointer) + (srcRegion.Y * PitchInformation.RowPitch) + (srcRegion.X * dataSize); int dstLineSize = dataSize * dstRegion.Width; // Number of dest bytes/scanline. var dstData = ((byte *)buffer.Data.UnsafePointer) + (dstRegion.Y * buffer.PitchInformation.RowPitch) + (dstRegion.X * dataSize); // Get the smallest line size. int minLineSize = dstLineSize.Min(srcLineSize); int minHeight = dstRegion.Height.Min(srcRegion.Height); // Finally, copy our data. for (int i = 0; i < minHeight; ++i) { DirectAccess.MemoryCopy(dstData, srcData, minLineSize); srcData += PitchInformation.RowPitch; dstData += buffer.PitchInformation.RowPitch; } }
/// <summary> /// Function to create a WIC bitmap from a System.Drawing.Image object. /// </summary> /// <param name="bitmap">WIC bitmap to copy to our image data.</param> /// <param name="filter">Filter used to scale the image.</param> /// <param name="ditherFlags">Flags used to dither the image.</param> /// <param name="buffer">Buffer for holding the image data.</param> /// <param name="clip">TRUE to clip the data, FALSE to scale it.</param> public void AddWICBitmapToImageData(WIC.Bitmap bitmap, ImageFilter filter, ImageDithering ditherFlags, GorgonImageBuffer buffer, bool clip) { Guid conversionFormat = GetGUID(buffer.Format); bool needsResize = (buffer.Width != bitmap.Size.Width) || (buffer.Height != bitmap.Size.Height); if (conversionFormat == Guid.Empty) { throw new GorgonException(GorgonResult.FormatNotSupported, string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, buffer.Format)); } // Turn off filtering if we're not resizing. if (!needsResize) { filter = ImageFilter.Point; } // If the pixel format of the bitmap is not the same as our // conversion format, then we need to convert the image. if (bitmap.PixelFormat != conversionFormat) { ConvertFormat(bitmap.PixelFormat, conversionFormat, (WIC.BitmapDitherType)ditherFlags, (WIC.BitmapInterpolationMode)filter, bitmap, null, 0, buffer, needsResize, clip); } else { // Just dump without converting because our formats are equal. if ((!needsResize) || (!ResizeBitmap(bitmap, (WIC.BitmapInterpolationMode)filter, buffer, clip))) { bitmap.CopyPixels(buffer.PitchInformation.RowPitch, buffer.Data.BasePointer, buffer.PitchInformation.SlicePitch); } } }
/// <summary> /// Function to clip or scale the bitmap up or down to the size of the buffer. /// </summary> /// <param name="bitmap">Bitmap to scale.</param> /// <param name="filter">Filtering to apply to the scaled bitmap.</param> /// <param name="buffer">Buffer to receive the scaled bitmap.</param> /// <param name="clip">TRUE to clip, FALSE to scale.</param> /// <returns>TRUE if clipping/scaling was performed, FALSE if not.</returns> private bool ResizeBitmap(WIC.BitmapSource bitmap, WIC.BitmapInterpolationMode filter, GorgonImageBuffer buffer, bool clip) { if (!clip) { using (var scaler = new WIC.BitmapScaler(Factory)) { scaler.Initialize(bitmap, buffer.Width, buffer.Height, filter); scaler.CopyPixels(buffer.PitchInformation.RowPitch, buffer.Data.BasePointer, buffer.PitchInformation.SlicePitch); } return(true); } if ((buffer.Width >= bitmap.Size.Width) && (buffer.Height >= bitmap.Size.Height)) { return(false); } ClipBitmap(bitmap, buffer); return(true); }
/// <summary> /// Function to convert the format of a bitmap into the format of the buffer. /// </summary> /// <param name="sourceFormat">Format to convert from.</param> /// <param name="destFormat">Format to convert into.</param> /// <param name="dithering">Dithering to apply.</param> /// <param name="filter">Filtering to apply to scaled bitmaps.</param> /// <param name="bitmap">Bitmap to convert.</param> /// <param name="bitmapPalette">Palette for the bitmap.</param> /// <param name="alphaValue">Value of pixel to consider transparent.</param> /// <param name="buffer">Buffer holding the converted data.</param> /// <param name="scale">TRUE to scale when converting, FALSE to keep at original size.</param> /// <param name="clip">TRUE to perform clipping, FALSE to keep at original size.</param> private void ConvertFormat(Guid sourceFormat, Guid destFormat, WIC.BitmapDitherType dithering, WIC.BitmapInterpolationMode filter, WIC.BitmapSource bitmap, WIC.Palette bitmapPalette, int alphaValue, GorgonImageBuffer buffer, bool scale, bool clip) { WIC.BitmapSource source = bitmap; double alphaPercent = alphaValue / 255.0; var paletteType = WIC.BitmapPaletteType.Custom; // If we have a palette, then confirm that the dithering method is valid. if (bitmapPalette != null) { // Do not apply dithering if we're using // a custom palette and request ordered dithering. switch (dithering) { case WIC.BitmapDitherType.Ordered4x4: case WIC.BitmapDitherType.Ordered8x8: case WIC.BitmapDitherType.Ordered16x16: if (bitmapPalette.TypeInfo == WIC.BitmapPaletteType.Custom) { dithering = WIC.BitmapDitherType.None; } break; } paletteType = bitmapPalette.TypeInfo; } try { // Create a scaler if need one. if ((scale) && (!clip)) { var scaler = new WIC.BitmapScaler(Factory); scaler.Initialize(bitmap, buffer.Width, buffer.Height, filter); source = scaler; } // Create a clipper if we want to clip and the image needs resizing. if ((clip) && (scale) && ((buffer.Width < bitmap.Size.Width) || (buffer.Height < bitmap.Size.Height))) { var clipper = new WIC.BitmapClipper(Factory); clipper.Initialize(bitmap, new DX.Rectangle(0, 0, buffer.Width < bitmap.Size.Width ? buffer.Width : bitmap.Size.Width, buffer.Height < bitmap.Size.Height ? buffer.Height : bitmap.Size.Height)); source = clipper; } using (var converter = new WIC.FormatConverter(Factory)) { if (!converter.CanConvert(sourceFormat, destFormat)) { throw new GorgonException(GorgonResult.FormatNotSupported, string.Format(Resources.GORGFX_FORMAT_NOT_SUPPORTED, buffer.Format)); } converter.Initialize(source, destFormat, dithering, bitmapPalette, alphaPercent, paletteType); if (!scale) { int rowPitch = (GetBitsPerPixel(destFormat) * bitmap.Size.Width + 7) / 8; int slicePitch = rowPitch * bitmap.Size.Height; if ((rowPitch != buffer.PitchInformation.RowPitch) || (slicePitch != buffer.PitchInformation.SlicePitch)) { throw new GorgonException(GorgonResult.CannotWrite, Resources.GORGFX_IMAGE_PITCH_TOO_SMALL); } } converter.CopyPixels(buffer.PitchInformation.RowPitch, buffer.Data.BasePointer, buffer.PitchInformation.SlicePitch); } } finally { if (source != bitmap) { source.Dispose(); } } }