/// <summary> /// Converts all bitmaps for this texture to a different format. /// </summary> /// <param name="newBitmapType"> /// Type being converted to. /// The new type must be a subclass of BitmapContent, /// such as PixelBitmapContent or DxtBitmapContent. /// </param> public void ConvertBitmapType(Type newBitmapType) { if (newBitmapType == null) { throw new ArgumentNullException(nameof(newBitmapType)); } if (!newBitmapType.IsSubclassOf(typeof(BitmapContent))) { throw new ArgumentException( $"Type '{newBitmapType}' is not a subclass of BitmapContent."); } if (newBitmapType.IsAbstract) { throw new ArgumentException( $"Type '{newBitmapType}' is abstract and cannot be allocated."); } if (newBitmapType.ContainsGenericParameters) { throw new ArgumentException( $"Type '{newBitmapType}' contains generic parameters and cannot be allocated."); } if (newBitmapType.GetConstructor(new Type[2] { typeof(int), typeof(int) }) == null) { throw new ArgumentException( $"Type '{newBitmapType} does not have a " + $"constructor with signature (int, int) and cannot be allocated."); } foreach (var mipChain in Faces) { for (var i = 0; i < mipChain.Count; i++) { var src = mipChain[i]; if (src.GetType() != newBitmapType) { var dst = (BitmapContent)Activator.CreateInstance( newBitmapType, new object[] { src.Width, src.Height }); BitmapContent.Copy(src, dst); mipChain[i] = dst; } } } }
// Once arranging is complete, copies each glyph to its chosen position in the single larger output bitmap. static PixelBitmapContent <Color> CopyGlyphsToOutput( List <ArrangedGlyph> glyphs, int width, int height) { var output = new PixelBitmapContent <Color>(width, height); foreach (var glyph in glyphs) { var sourceGlyph = glyph.Source; var sourceRegion = sourceGlyph.Subrect; var destinationRegion = new Rectangle(glyph.X + 1, glyph.Y + 1, sourceRegion.Width, sourceRegion.Height); BitmapContent.Copy(sourceGlyph.Bitmap, sourceRegion, output, destinationRegion); sourceGlyph.Bitmap = output; sourceGlyph.Subrect = destinationRegion; } return(output); }
internal static PixelBitmapContent <RgbaVector> Resize( this BitmapContent bitmap, int newWidth, int newHeight) { BitmapContent src = bitmap; src.TryGetFormat(out SurfaceFormat format); if (format != SurfaceFormat.Vector4) { var v4 = new PixelBitmapContent <RgbaVector>(src.Width, src.Height); BitmapContent.Copy(src, v4); src = v4; } using (var image = Image.WrapMemory <RgbaVector>(src.GetPixelData(), new Size(src.Height, src.Width))) using (var resized = image.ProcessRows(x => x.Resize(new Size(newWidth, newHeight), 0))) { var result = new PixelBitmapContent <RgbaVector>(newWidth, newHeight); result.SetPixelData(resized.GetPixelSpan()); return(result); } }
/// <summary> /// Generates a full set of mipmaps for the texture. /// </summary> /// <param name="overwriteExistingMipmaps"> /// true if the existing mipmap set is replaced with the new set; false otherwise. /// </param> public virtual void GenerateMipmaps(bool overwriteExistingMipmaps) { // If we already have mipmaps and we're not supposed to overwrite // them then return without any generation. if (!overwriteExistingMipmaps && Faces.Any(f => f.Count > 1)) { return; } // Generate the mips for each face. foreach (var face in Faces) { // Remove any existing mipmaps. var faceBitmap = face[0]; face.Clear(); face.Add(faceBitmap); var faceType = faceBitmap.GetType(); int width = faceBitmap.Width; int height = faceBitmap.Height; while (width > 1 || height > 1) { if (width > 1) { width /= 2; } if (height > 1) { height /= 2; } var mip = (BitmapContent)Activator.CreateInstance( faceType, new object[] { width, height }); BitmapContent.Copy(faceBitmap, mip); face.Add(mip); } } }