protected override bool TryCopyTo(BitmapContent dstBitmap, Rectangle srcRect, Rectangle dstRect) { SurfaceFormat format; if (!dstBitmap.TryGetFormat(out format) || format != _format) { return(false); } var dst = dstBitmap as PixelBitmapContent <T>; for (var i = 0; i < dstRect.Height; i++) { var dy = dstRect.Y + i; for (var j = 0; j < dstRect.Width; j++) { var dx = dstRect.X + j; var uv = new Vector2() { X = j / (float)dstRect.Width, Y = i / (float)dstRect.Height, }; var sx = MathHelper.Clamp((int)Math.Round(uv.X * srcRect.Width) + srcRect.X, 0, Width - 1); var sy = MathHelper.Clamp((int)Math.Round(uv.Y * srcRect.Height) + srcRect.Y, 0, Height - 1); var pixel = GetPixel(sx, sy); dst.SetPixel(dx, dy, pixel); } } return(true); }
public DxtDataHandler(BitmapContent content) { _content = content; WriteData = new OutputOptions.WriteDataDelegate(WriteDataInternal); BeginImage = new OutputOptions.ImageDelegate(BeginImageInternal); }
public DxtDataHandler(BitmapContent content) { _content = content; WriteData = new OutputOptions.WriteDataDelegate(WriteDataInternal); BeginImage = new OutputOptions.ImageDelegate(BeginImageInternal); }
/// <summary> /// Gets the alpha range in a set of pixels. /// </summary> /// <param name="bitmap">A bitmap of full-colour floating point pixel data in RGBA or BGRA order.</param> /// <returns>A member of the AlphaRange enum to describe the range of alpha in the pixel data.</returns> static AlphaRange CalculateAlphaRange(BitmapContent bitmap) { AlphaRange result = AlphaRange.Opaque; var pixelBitmap = bitmap as PixelBitmapContent <Vector4>; if (pixelBitmap != null) { for (int y = 0; y < pixelBitmap.Height; ++y) { var row = pixelBitmap.GetRow(y); foreach (var pixel in row) { if (pixel.W == 0.0) { result = AlphaRange.Cutout; } else if (pixel.W < 1.0) { return(AlphaRange.Full); } } } } 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) { width /= 2; height /= 2; var mip = (BitmapContent)Activator.CreateInstance(faceType, new object[] { width, height }); BitmapContent.Copy(faceBitmap, mip); face.Add(mip); } } }
/// <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) { ImageAttributes imageAttr = new ImageAttributes(); imageAttr.SetWrapMode(WrapMode.TileFlipXY); foreach (MipmapChain face in faces) { BitmapContent faceBitmap = face[0]; int width = faceBitmap.Width, height = faceBitmap.Height; Bitmap systemBitmap; while (width > 1 && height > 1) { systemBitmap = face[face.Count - 1].ToSystemBitmap(); width /= 2; height /= 2; Bitmap bitmap = new Bitmap(width, height); using (var graphics = System.Drawing.Graphics.FromImage(bitmap)) { var destRect = new System.Drawing.Rectangle(0, 0, width, height); graphics.InterpolationMode = InterpolationMode.HighQualityBilinear; graphics.DrawImage(systemBitmap, destRect, 0, 0, width * 2, height * 2, GraphicsUnit.Pixel, imageAttr); } face.Add(bitmap.ToXnaBitmap(false)); //we dont want to flip textures twice systemBitmap.Dispose(); } } }
protected override bool TryCopyTo(BitmapContent destinationBitmap, Rectangle sourceRegion, Rectangle destinationRegion) { throw new NotImplementedException(); // return BitmapContent.InteropCopy(this, sourceRegion, destinationBitmap, destinationRegion); }
// Checks whether an area of a bitmap contains entirely the specified alpha value. public static bool IsAlphaEntirely(byte expectedAlpha, BitmapContent bitmap, Rectangle? region = null) { var bitmapRegion = region.HasValue ? region.Value : new Rectangle(0, 0, bitmap.Width, bitmap.Height); // Works with PixelBitmapContent<byte> at this stage if (bitmap is PixelBitmapContent<byte>) { var bmp = bitmap as PixelBitmapContent<byte>; for (int y = 0; y < bitmapRegion.Height; y++) { for (int x = 0; x < bitmapRegion.Width; x++) { var alpha = bmp.GetPixel(bitmapRegion.X + x, bitmapRegion.Y + y); if (alpha != expectedAlpha) return false; } } return true; } else if (bitmap is PixelBitmapContent<Color>) { var bmp = bitmap as PixelBitmapContent<Color>; for (int y = 0; y < bitmapRegion.Height; y++) { for (int x = 0; x < bitmapRegion.Width; x++) { var alpha = bmp.GetPixel(bitmapRegion.X + x, bitmapRegion.Y + y).A; if (alpha != expectedAlpha) return false; } } return true; } throw new ArgumentException("Expected PixelBitmapContent<byte> or PixelBitmapContent<Color>, got " + bitmap.GetType().Name, "bitmap"); }
static void Compress(Type targetType, TextureContent content, bool generateMipMaps) { var wh = new object[2]; if (generateMipMaps) { for (int i = 0; i < content.Faces.Count; ++i) { // Only generate mipmaps if there are none already if (content.Faces[i].Count == 1) { var src = content.Faces[i][0]; var w = src.Width; var h = src.Height; content.Faces[i].Clear(); wh[0] = w; wh[1] = h; var dest = (BitmapContent)Activator.CreateInstance(targetType, wh); BitmapContent.Copy(src, dest); content.Faces[i].Add(dest); while (w > 1 && h > 1) { if (w > 1) { w = w >> 1; } if (h > 1) { h = h >> 1; } wh[0] = w; wh[1] = h; dest = (BitmapContent)Activator.CreateInstance(targetType, wh); BitmapContent.Copy(src, dest); content.Faces[i].Add(dest); } } else { // Convert the existing mipmaps var chain = content.Faces[i]; for (int j = 0; j < chain.Count; ++j) { var src = chain[j]; wh[0] = src.Width; wh[1] = src.Height; var dest = (BitmapContent)Activator.CreateInstance(targetType, wh); BitmapContent.Copy(src, dest); chain[j] = dest; } } } } else { // Converts all existing faces and mipmaps content.ConvertBitmapType(targetType); } }
/// <summary> /// Validates the arguments to the Copy function. /// </summary> /// <param name="sourceBitmap">BitmapContent being copied.</param> /// <param name="sourceRegion">Location of sourceBitmap.</param> /// <param name="destinationBitmap">BitmapContent being overwritten.</param> /// <param name="destinationRegion">Region of bitmap to be overwritten.</param> protected static void ValidateCopyArguments(BitmapContent sourceBitmap, Rectangle sourceRegion, BitmapContent destinationBitmap, Rectangle destinationRegion) { if (sourceBitmap == null) { throw new ArgumentNullException("sourceBitmap"); } if (destinationBitmap == null) { throw new ArgumentNullException("destinationBitmap"); } // Make sure regions are within the bounds of the bitmaps if (sourceRegion.Left < 0 || sourceRegion.Top < 0 || sourceRegion.Width <= 0 || sourceRegion.Height <= 0 || sourceRegion.Right > sourceBitmap.Width || sourceRegion.Bottom > sourceBitmap.Height) { throw new ArgumentOutOfRangeException("sourceRegion"); } if (destinationRegion.Left < 0 || destinationRegion.Top < 0 || destinationRegion.Width <= 0 || destinationRegion.Height <= 0 || destinationRegion.Right > destinationBitmap.Width || destinationRegion.Bottom > destinationBitmap.Height) { throw new ArgumentOutOfRangeException("destinationRegion"); } }
protected override bool TryCopyTo(BitmapContent destinationBitmap, Rectangle sourceRegion, Rectangle destinationRegion) { SurfaceFormat destinationFormat; if (!destinationBitmap.TryGetFormat(out destinationFormat)) { return(false); } SurfaceFormat format; TryGetFormat(out format); // A shortcut for copying the entire bitmap to another bitmap of the same type and format var fullRegion = new Rectangle(0, 0, Width, Height); if ((format == destinationFormat) && (sourceRegion == fullRegion) && (sourceRegion == destinationRegion)) { destinationBitmap.SetPixelData(GetPixelData()); return(true); } // No other support for copying from a DXT texture yet return(false); }
// Constructor. public Glyph(char character, BitmapContent bitmap, Rectangle?subrect = null) { this.Character = character; this.Bitmap = bitmap; this.Subrect = subrect.GetValueOrDefault(new Rectangle(0, 0, bitmap.Width, bitmap.Height)); this.Width = bitmap.Width; this.Height = bitmap.Height; }
// Constructor. public Glyph(char character, BitmapContent bitmap, Rectangle? subrect = null) { this.Character = character; this.Bitmap = bitmap; this.Subrect = subrect.GetValueOrDefault(new Rectangle(0, 0, bitmap.Width, bitmap.Height)); this.Width = bitmap.Width; this.Height = bitmap.Height; }
/// <summary> /// Copies one bitmap into another. /// The destination bitmap can be in any format and size. If the destination is larger or smaller, the source bitmap is scaled accordingly. /// </summary> /// <param name="sourceBitmap">BitmapContent being copied.</param> /// <param name="destinationBitmap">BitmapContent being overwritten.</param> public static void Copy(BitmapContent sourceBitmap, BitmapContent destinationBitmap) { if (sourceBitmap == null) throw new ArgumentNullException("sourceBitmap"); if (destinationBitmap == null) throw new ArgumentNullException("destinationBitmap"); Copy(sourceBitmap, new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height), destinationBitmap, new Rectangle(0, 0, destinationBitmap.Width, destinationBitmap.Height)); }
protected override bool TryCopyFrom(BitmapContent sourceBitmap, Rectangle sourceRegion, Rectangle destinationRegion) { SurfaceFormat sourceFormat; if (!sourceBitmap.TryGetFormat(out sourceFormat)) return false; SurfaceFormat format; TryGetFormat(out format); // A shortcut for copying the entire bitmap to another bitmap of the same type and format if (format == sourceFormat && (sourceRegion == new Rectangle(0, 0, Width, Height)) && sourceRegion == destinationRegion) { SetPixelData(sourceBitmap.GetPixelData()); return true; } // Destination region copy is not yet supported if (destinationRegion != new Rectangle(0, 0, Width, Height)) return false; // If the source is not Vector4 or requires resizing, send it through BitmapContent.Copy if (!(sourceBitmap is PixelBitmapContent<Vector4>) || sourceRegion.Width != destinationRegion.Width || sourceRegion.Height != destinationRegion.Height) { try { BitmapContent.Copy(sourceBitmap, sourceRegion, this, destinationRegion); return true; } catch (InvalidOperationException) { return false; } } // Convert to full colour 32-bit format. Floating point would be preferred for processing, but it appears the ATICompressor does not support this var colorBitmap = new PixelBitmapContent<Color>(sourceRegion.Width, sourceRegion.Height); BitmapContent.Copy(sourceBitmap, sourceRegion, colorBitmap, new Rectangle(0, 0, colorBitmap.Width, colorBitmap.Height)); sourceBitmap = colorBitmap; ATICompressor.CompressionFormat targetFormat; switch (format) { case SurfaceFormat.RgbaAtcExplicitAlpha: targetFormat = ATICompressor.CompressionFormat.AtcRgbaExplicitAlpha; break; case SurfaceFormat.RgbaAtcInterpolatedAlpha: targetFormat = ATICompressor.CompressionFormat.AtcRgbaInterpolatedAlpha; break; default: return false; } var sourceData = sourceBitmap.GetPixelData(); var compressedData = ATICompressor.Compress(sourceData, Width, Height, targetFormat); SetPixelData(compressedData); return true; }
protected override bool TryCopyFrom(BitmapContent sourceBitmap, Rectangle sourceRegion, Rectangle destinationRegion) { SurfaceFormat sourceFormat; if (!sourceBitmap.TryGetFormat(out sourceFormat)) { return(false); } // A shortcut for copying the entire bitmap to another bitmap of the same type and format if (SurfaceFormat.RgbEtc1 == sourceFormat && (sourceRegion == new Rectangle(0, 0, Width, Height)) && sourceRegion == destinationRegion) { SetPixelData(sourceBitmap.GetPixelData()); return(true); } // Destination region copy is not yet supported if (destinationRegion != new Rectangle(0, 0, Width, Height)) { return(false); } // If the source is not Vector4 or requires resizing, send it through BitmapContent.Copy if (!(sourceBitmap is PixelBitmapContent <Vector4>) || sourceRegion.Width != destinationRegion.Width || sourceRegion.Height != destinationRegion.Height) { try { BitmapContent.Copy(sourceBitmap, sourceRegion, this, destinationRegion); return(true); } catch (InvalidOperationException) { return(false); } } // Create the texture object in the PVR library var sourceData = sourceBitmap.GetPixelData(); var rgba32F = (PixelFormat)0x2020202061626772; // static const PixelType PVRStandard32PixelType = PixelType('r', 'g', 'b', 'a', 32, 32, 32, 32); using (var pvrTexture = PVRTexture.CreateTexture(sourceData, (uint)sourceBitmap.Width, (uint)sourceBitmap.Height, 1, rgba32F, true, VariableType.Float, ColourSpace.lRGB)) { // Resize the bitmap if needed if ((sourceBitmap.Width != Width) || (sourceBitmap.Height != Height)) { pvrTexture.Resize((uint)Width, (uint)Height, 1, ResizeMode.Cubic); } pvrTexture.Transcode(PixelFormat.ETC1, VariableType.UnsignedByte, ColourSpace.lRGB /*, CompressorQuality.ETCMediumPerceptual, true*/); var texDataSize = pvrTexture.GetTextureDataSize(0); var texData = new byte[texDataSize]; pvrTexture.GetTextureData(texData, texDataSize); SetPixelData(texData); } return(true); }
/// <summary> /// Copies one bitmap into another. /// The destination bitmap can be in any format and size. If the destination is larger or smaller, the source bitmap is scaled accordingly. /// </summary> /// <param name="sourceBitmap">BitmapContent being copied.</param> /// <param name="destinationBitmap">BitmapContent being overwritten.</param> public static void Copy(BitmapContent sourceBitmap, BitmapContent destinationBitmap) { if (sourceBitmap == null) { throw new ArgumentNullException("sourceBitmap"); } if (destinationBitmap == null) { throw new ArgumentNullException("destinationBitmap"); } Copy(sourceBitmap, new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height), destinationBitmap, new Rectangle(0, 0, destinationBitmap.Width, destinationBitmap.Height)); }
/// <summary> /// Copies one bitmap into another. /// The destination bitmap can be in any format and size. If the destination is larger or smaller, the source bitmap is scaled accordingly. /// </summary> /// <param name="sourceBitmap">BitmapContent being copied.</param> /// <param name="sourceRegion">Region of sourceBitmap.</param> /// <param name="destinationBitmap">BitmapContent being overwritten.</param> /// <param name="destinationRegion">Region of bitmap to be overwritten.</param> public static void Copy(BitmapContent sourceBitmap, Rectangle sourceRegion, BitmapContent destinationBitmap, Rectangle destinationRegion) { ValidateCopyArguments(sourceBitmap, sourceRegion, destinationBitmap, destinationRegion); if (sourceBitmap.TryCopyTo(destinationBitmap, sourceRegion, destinationRegion) || destinationBitmap.TryCopyFrom(sourceBitmap, sourceRegion, destinationRegion)) { return; } throw new NotImplementedException(); }
/// <summary> /// Copies one bitmap into another. /// The destination bitmap can be in any format and size. If the destination is larger or smaller, the source bitmap is scaled accordingly. /// </summary> /// <param name="sourceBitmap">BitmapContent being copied.</param> /// <param name="sourceRegion">Region of sourceBitmap.</param> /// <param name="destinationBitmap">BitmapContent being overwritten.</param> /// <param name="destinationRegion">Region of bitmap to be overwritten.</param> public static void Copy(BitmapContent sourceBitmap, Rectangle sourceRegion, BitmapContent destinationBitmap, Rectangle destinationRegion) { ValidateCopyArguments(sourceBitmap, sourceRegion, destinationBitmap, destinationRegion); SurfaceFormat sourceFormat; if (!sourceBitmap.TryGetFormat(out sourceFormat)) { throw new InvalidOperationException("Could not retrieve surface format of source bitmap"); } SurfaceFormat destinationFormat; if (!destinationBitmap.TryGetFormat(out destinationFormat)) { throw new InvalidOperationException("Could not retrieve surface format of destination bitmap"); } // If the formats are the same and the regions are the full bounds of the bitmaps and they are the same size, do a simpler copy if (sourceFormat == destinationFormat && sourceRegion == destinationRegion && sourceRegion == new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height) && destinationRegion == new Rectangle(0, 0, destinationBitmap.Width, destinationBitmap.Height)) { destinationBitmap.SetPixelData(sourceBitmap.GetPixelData()); return; } // The basic process is // 1. Copy from source bitmap region to a new PixelBitmapContent<Vector4> using sourceBitmap.TryCopyTo() // 2. If source and destination regions are a different size, resize Vector4 version // 3. Copy from Vector4 to destination region using destinationBitmap.TryCopyFrom() // Copy from the source to the intermediate Vector4 format var intermediate = new PixelBitmapContent <Vector4>(sourceRegion.Width, sourceRegion.Height); var intermediateRegion = new Rectangle(0, 0, intermediate.Width, intermediate.Height); if (sourceBitmap.TryCopyTo(intermediate, sourceRegion, intermediateRegion)) { // Resize the intermediate if required if (intermediate.Width != destinationRegion.Width || intermediate.Height != destinationRegion.Height) { intermediate = intermediate.Resize(destinationRegion.Width, destinationRegion.Height) as PixelBitmapContent <Vector4>; } // Copy from the intermediate to the destination if (destinationBitmap.TryCopyFrom(intermediate, new Rectangle(0, 0, intermediate.Width, intermediate.Height), destinationRegion)) { return; } } // If we got here, one of the above steps didn't work throw new InvalidOperationException("Could not copy between " + sourceFormat + " and " + destinationFormat); }
public DxtDataHandler(BitmapContent content, OutputOptions outputOptions) { _content = content; WriteData = new OutputOptions.WriteDataDelegate(WriteDataInternal); BeginImage = new OutputOptions.ImageDelegate(BeginImageInternal); // Keep the delegate from being re-located or collected by the garbage collector. delegateHandleBeginImage = GCHandle.Alloc(BeginImage); delegateHandleWriteData = GCHandle.Alloc(WriteData); outputOptions.SetOutputHandler(BeginImage, WriteData); }
protected override bool TryCopyFrom(BitmapContent sourceBitmap, Rectangle sourceRegion, Rectangle destinationRegion) { SurfaceFormat sourceFormat; if (!sourceBitmap.TryGetFormat(out sourceFormat)) return false; // A shortcut for copying the entire bitmap to another bitmap of the same type and format if (SurfaceFormat.RgbEtc1 == sourceFormat && (sourceRegion == new Rectangle(0, 0, Width, Height)) && sourceRegion == destinationRegion) { SetPixelData(sourceBitmap.GetPixelData()); return true; } // Destination region copy is not yet supported if (destinationRegion != new Rectangle(0, 0, Width, Height)) return false; // If the source is not Vector4 or requires resizing, send it through BitmapContent.Copy if (!(sourceBitmap is PixelBitmapContent<Vector4>) || sourceRegion.Width != destinationRegion.Width || sourceRegion.Height != destinationRegion.Height) { try { BitmapContent.Copy(sourceBitmap, sourceRegion, this, destinationRegion); return true; } catch (InvalidOperationException) { return false; } } // Create the texture object in the PVR library var sourceData = sourceBitmap.GetPixelData(); var rgba32F = (PixelFormat)0x2020202061626772; // static const PixelType PVRStandard32PixelType = PixelType('r', 'g', 'b', 'a', 32, 32, 32, 32); using (var pvrTexture = PVRTexture.CreateTexture(sourceData, (uint)sourceBitmap.Width, (uint)sourceBitmap.Height, 1, rgba32F, true, VariableType.Float, ColourSpace.lRGB)) { // Resize the bitmap if needed if ((sourceBitmap.Width != Width) || (sourceBitmap.Height != Height)) pvrTexture.Resize((uint)Width, (uint)Height, 1, ResizeMode.Cubic); pvrTexture.Transcode(PixelFormat.ETC1, VariableType.UnsignedByte, ColourSpace.lRGB /*, CompressorQuality.ETCMediumPerceptual, true*/); var texDataSize = pvrTexture.GetTextureDataSize(0); var texData = new byte[texDataSize]; pvrTexture.GetTextureData(texData, texDataSize); SetPixelData(texData); } return true; }
internal static Bitmap ToSystemBitmap(this BitmapContent bitmapContent) { var srcBmp = bitmapContent; var srcData = srcBmp.GetPixelData(); var srcDataHandle = GCHandle.Alloc(srcData, GCHandleType.Pinned); var srcDataPtr = (IntPtr)(srcDataHandle.AddrOfPinnedObject().ToInt64()); // stride must be aligned on a 32 bit boundary or 4 bytes int stride = ((srcBmp.Width * 32 + 31) & ~31) >> 3; var systemBitmap = new Bitmap(srcBmp.Width, srcBmp.Height, stride, PixelFormat.Format32bppArgb | PixelFormat.Alpha, srcDataPtr); srcDataHandle.Free(); return(systemBitmap); }
// Once arranging is complete, copies each glyph to its chosen position in the single larger output bitmap. static BitmapContent 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); }
/// <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("newBitmapType"); } if (!newBitmapType.IsSubclassOf(typeof(BitmapContent))) { throw new ArgumentException(string.Format("Type '{0}' is not a subclass of BitmapContent.", newBitmapType)); } if (newBitmapType.IsAbstract) { throw new ArgumentException(string.Format("Type '{0}' is abstract and cannot be allocated.", newBitmapType)); } if (newBitmapType.ContainsGenericParameters) { throw new ArgumentException(string.Format("Type '{0}' contains generic parameters and cannot be allocated.", newBitmapType)); } if (newBitmapType.GetConstructor(new Type[2] { typeof(int), typeof(int) }) == null) { throw new ArgumentException(string.Format("Type '{0} does not have a constructor with signature (int, int) and cannot be allocated.", newBitmapType)); } 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; } } } }
// Checks whether an area of a bitmap contains entirely the specified alpha value. public static bool IsAlphaEntirely(byte expectedAlpha, BitmapContent bitmap, Rectangle?region = null) { var bitmapRegion = region.HasValue ? region.Value : new Rectangle(0, 0, bitmap.Width, bitmap.Height); // Works with PixelBitmapContent<byte> at this stage if (bitmap is PixelBitmapContent <byte> ) { var bmp = bitmap as PixelBitmapContent <byte>; for (int y = 0; y < bitmapRegion.Height; y++) { for (int x = 0; x < bitmapRegion.Width; x++) { var alpha = bmp.GetPixel(bitmapRegion.X + x, bitmapRegion.Y + y); if (alpha != expectedAlpha) { return(false); } } } return(true); } else if (bitmap is PixelBitmapContent <Color> ) { var bmp = bitmap as PixelBitmapContent <Color>; for (int y = 0; y < bitmapRegion.Height; y++) { for (int x = 0; x < bitmapRegion.Width; x++) { var alpha = bmp.GetPixel(bitmapRegion.X + x, bitmapRegion.Y + y).A; if (alpha != expectedAlpha) { return(false); } } } return(true); } throw new ArgumentException("Expected PixelBitmapContent<byte> or PixelBitmapContent<Color>, got " + bitmap.GetType().Name, "bitmap"); }
internal static BitmapContent Resize(this BitmapContent bitmap, int newWidth, int newHeight) { BitmapContent src = bitmap; SurfaceFormat format; src.TryGetFormat(out format); if (format != SurfaceFormat.Vector4) { var v4 = new PixelBitmapContent <Vector4>(src.Width, src.Height); BitmapContent.Copy(src, v4); src = v4; } // Convert to FreeImage bitmap var bytes = src.GetPixelData(); var fi = FreeImage.ConvertFromRawBits(bytes, FREE_IMAGE_TYPE.FIT_RGBAF, src.Width, src.Height, SurfaceFormat.Vector4.GetSize() * src.Width, 128, 0, 0, 0, true); // Resize var newfi = FreeImage.Rescale(fi, newWidth, newHeight, FREE_IMAGE_FILTER.FILTER_BICUBIC); FreeImage.UnloadEx(ref fi); // Convert back to PixelBitmapContent<Vector4> src = new PixelBitmapContent <Vector4>(newWidth, newHeight); bytes = new byte[SurfaceFormat.Vector4.GetSize() * newWidth * newHeight]; FreeImage.ConvertToRawBits(bytes, newfi, SurfaceFormat.Vector4.GetSize() * newWidth, 128, 0, 0, 0, true); src.SetPixelData(bytes); FreeImage.UnloadEx(ref newfi); // Convert back to source type if required if (format != SurfaceFormat.Vector4) { var s = (BitmapContent)Activator.CreateInstance(bitmap.GetType(), new object[] { newWidth, newHeight }); BitmapContent.Copy(src, s); src = s; } return(src); }
private MipmapChain CreateFace(BitmapContent bitmapContent, int w, int h, int xOffset) { PixelBitmapContent<Color> result; result = new PixelBitmapContent<Color>(w, h); Rectangle sourceRegion = new Rectangle(xOffset, 0, w, h); Rectangle destinationRegion = new Rectangle(0, 0, w, h); BitmapContent.Copy(bitmapContent, sourceRegion, result, destinationRegion); return result; }
protected override bool TryCopyTo(BitmapContent destinationBitmap, Rectangle sourceRegion, Rectangle destinationRegion) { throw new NotImplementedException(); }
/// <summary> /// Copies one bitmap into another. /// The destination bitmap can be in any format and size. If the destination is larger or smaller, the source bitmap is scaled accordingly. /// </summary> /// <param name="sourceBitmap">BitmapContent being copied.</param> /// <param name="sourceRegion">Region of sourceBitmap.</param> /// <param name="destinationBitmap">BitmapContent being overwritten.</param> /// <param name="destinationRegion">Region of bitmap to be overwritten.</param> public static void Copy(BitmapContent sourceBitmap, Rectangle sourceRegion, BitmapContent destinationBitmap, Rectangle destinationRegion) { ValidateCopyArguments(sourceBitmap, sourceRegion, destinationBitmap, destinationRegion); if (sourceBitmap.TryCopyTo(destinationBitmap, sourceRegion, destinationRegion) || destinationBitmap.TryCopyFrom(sourceBitmap, sourceRegion, destinationRegion)) return; throw new NotImplementedException(); }
/// <summary> /// Attempts to copy a region of the specified bitmap onto another. /// </summary> /// <param name="destinationBitmap">BitmapContent being overwritten.</param> /// <param name="sourceRegion">Location of the source bitmap.</param> /// <param name="destinationRegion">Region of destination bitmap to be overwritten.</param> /// <returns>true if region copy is supported; false otherwise.</returns> protected abstract bool TryCopyTo(BitmapContent destinationBitmap, Rectangle sourceRegion, Rectangle destinationRegion);
protected static void ValidateCopyArguments(BitmapContent sourceBitmap, Rectangle sourceRegion, BitmapContent destinationBitmap, Rectangle destinationRegion) { throw new NotImplementedException(); }
public static void Copy(BitmapContent sourceBitmap, BitmapContent destinationBitmap) { throw new NotImplementedException(); }
protected override bool TryCopyTo(BitmapContent destinationBitmap, Rectangle sourceRegion, Rectangle destinationRegion) { SurfaceFormat destinationFormat; if (!destinationBitmap.TryGetFormat(out destinationFormat)) { return(false); } // A shortcut for copying the entire bitmap to another bitmap of the same type and format if (_format == destinationFormat && (sourceRegion == new Rectangle(0, 0, Width, Height)) && sourceRegion == destinationRegion) { destinationBitmap.SetPixelData(GetPixelData()); return(true); } // If the destination is not Vector4 or requires resizing, send it through BitmapContent.Copy if (!(destinationBitmap is PixelBitmapContent <Vector4>) || sourceRegion.Width != destinationRegion.Width || sourceRegion.Height != destinationRegion.Height) { try { BitmapContent.Copy(this, sourceRegion, destinationBitmap, destinationRegion); return(true); } catch (InvalidOperationException) { return(false); } } // Convert to a Vector4 format var dest = destinationBitmap as PixelBitmapContent <Vector4>; if (default(T) is IPackedVector) { Parallel.For(0, sourceRegion.Height, (y) => { var row = GetRow(sourceRegion.Top + y); for (int x = 0; x < sourceRegion.Width; ++x) { dest.SetPixel(destinationRegion.Left + x, destinationRegion.Top + y, ((IPackedVector)row[sourceRegion.Left + x]).ToVector4()); } }); } else { var converter = new Vector4Converter() as IVector4Converter <T>; // If no converter could be created, converting from this format is not supported if (converter == null) { return(false); } Parallel.For(0, sourceRegion.Height, (y) => { var row = GetRow(sourceRegion.Top + y); for (int x = 0; x < sourceRegion.Width; ++x) { dest.SetPixel(destinationRegion.Left + x, destinationRegion.Top + y, converter.ToVector4(row[sourceRegion.Left + x])); } }); } return(true); }
protected override bool TryCopyFrom(BitmapContent sourceBitmap, Rectangle sourceRegion, Rectangle destRegion) { throw new NotImplementedException(); }
public static void Copy(BitmapContent sourceBitmap, Rectangle sourceRegion, BitmapContent destinationBitmap, Rectangle destinationRegion) { throw new NotImplementedException(); }
protected static void ValidateCopyArguments(BitmapContent sourceBitmap, Rectangle sourceRegion, BitmapContent destinationBitmap, Rectangle destinationRegion) { throw new NotImplementedException(); }
public Texture2DContent(BitmapContent bitmapContent) : base(new MipmapChainCollection(1)) { base.Faces[0] = bitmapContent; }
/// <summary> /// Copies one bitmap into another. /// The destination bitmap can be in any format and size. If the destination is larger or smaller, the source bitmap is scaled accordingly. /// </summary> /// <param name="sourceBitmap">BitmapContent being copied.</param> /// <param name="sourceRegion">Region of sourceBitmap.</param> /// <param name="destinationBitmap">BitmapContent being overwritten.</param> /// <param name="destinationRegion">Region of bitmap to be overwritten.</param> public static void Copy(BitmapContent sourceBitmap, Rectangle sourceRegion, BitmapContent destinationBitmap, Rectangle destinationRegion) { ValidateCopyArguments(sourceBitmap, sourceRegion, destinationBitmap, destinationRegion); throw new NotImplementedException(); }
protected override bool TryCopyFrom(BitmapContent sourceBitmap, Rectangle sourceRegion, Rectangle destinationRegion) { throw new NotImplementedException(); }
protected override bool TryCopyTo(BitmapContent destBitmap, Rectangle sourceRegion, Rectangle destRegion) { throw new NotImplementedException(); }
protected override bool TryCopyFrom(BitmapContent srcBitmap, Rectangle srcRect, Rectangle dstRect) { return(false); }
public static void Copy(BitmapContent sourceBitmap, BitmapContent destinationBitmap) { throw new NotImplementedException(); }
public static void CompressPngToTexture2DContent( ParsedPath pngFileName, string compressionType, out Texture2DContent textureContent) { PngFile pngFile = PngFileReader.ReadFile(pngFileName); SquishMethod? squishMethod = null; SurfaceFormat surfaceFormat = SurfaceFormat.Color; switch (compressionType.ToLower()) { case "dxt1": squishMethod = SquishMethod.Dxt1; surfaceFormat = SurfaceFormat.Dxt1; break; case "dxt3": squishMethod = SquishMethod.Dxt3; surfaceFormat = SurfaceFormat.Dxt3; break; case "dxt5": squishMethod = SquishMethod.Dxt5; surfaceFormat = SurfaceFormat.Dxt5; break; default: case "none": surfaceFormat = SurfaceFormat.Color; break; } BitmapContent bitmapContent; if (surfaceFormat != SurfaceFormat.Color) { byte[] rgbaData = Squish.CompressImage( pngFile.RgbaData, pngFile.Width, pngFile.Height, squishMethod.Value, SquishFit.IterativeCluster, SquishMetric.Default, SquishExtra.None); bitmapContent = new BitmapContent(surfaceFormat, pngFile.Width, pngFile.Height, rgbaData); } else { bitmapContent = new BitmapContent(SurfaceFormat.Color, pngFile.Width, pngFile.Height, pngFile.RgbaData); } textureContent = new Texture2DContent(bitmapContent); }
/// <summary> /// Copies one bitmap into another. /// The destination bitmap can be in any format and size. If the destination is larger or smaller, the source bitmap is scaled accordingly. /// </summary> /// <param name="sourceBitmap">BitmapContent being copied.</param> /// <param name="sourceRegion">Region of sourceBitmap.</param> /// <param name="destinationBitmap">BitmapContent being overwritten.</param> /// <param name="destinationRegion">Region of bitmap to be overwritten.</param> public static void Copy(BitmapContent sourceBitmap, Rectangle sourceRegion, BitmapContent destinationBitmap, Rectangle destinationRegion) { ValidateCopyArguments(sourceBitmap, sourceRegion, destinationBitmap, destinationRegion); throw new NotImplementedException(); }
public static void Copy(BitmapContent sourceBitmap, Rectangle sourceRegion, BitmapContent destinationBitmap, Rectangle destinationRegion) { throw new NotImplementedException(); }
/// <summary> /// Gets the alpha range in a set of pixels. /// </summary> /// <param name="bitmap">A bitmap of full-colour floating point pixel data in RGBA or BGRA order.</param> /// <returns>A member of the AlphaRange enum to describe the range of alpha in the pixel data.</returns> static AlphaRange CalculateAlphaRange(BitmapContent bitmap) { AlphaRange result = AlphaRange.Opaque; var pixelBitmap = bitmap as PixelBitmapContent<Vector4>; if (pixelBitmap != null) { for (int y = 0; y < pixelBitmap.Height; ++y) { var row = pixelBitmap.GetRow(y); foreach (var pixel in row) { if (pixel.W == 0.0) result = AlphaRange.Cutout; else if (pixel.W < 1.0) return AlphaRange.Full; } } } return result; }
private static BitmapContent ConvertBitmap(BitmapContent source, Type newType, int width, int height) { BitmapContent content; try { content = (BitmapContent)Activator.CreateInstance(newType, new object[] {width, height}); } catch (TargetInvocationException exception) { throw new Exception(exception.InnerException.Message); } BitmapContent.Copy(source, content); return content; }
protected override bool TryCopyTo(BitmapContent destinationBitmap, Rectangle sourceRegion, Rectangle destinationRegion) { SurfaceFormat destinationFormat; if (!destinationBitmap.TryGetFormat(out destinationFormat)) return false; SurfaceFormat format; TryGetFormat(out format); // A shortcut for copying the entire bitmap to another bitmap of the same type and format var fullRegion = new Rectangle(0, 0, Width, Height); if ((format == destinationFormat) && (sourceRegion == fullRegion) && (sourceRegion == destinationRegion)) { destinationBitmap.SetPixelData(GetPixelData()); return true; } // No other support for copying from a DXT texture yet return false; }
/// <summary> /// Validates the arguments to the Copy function. /// </summary> /// <param name="sourceBitmap">BitmapContent being copied.</param> /// <param name="sourceRegion">Location of sourceBitmap.</param> /// <param name="destinationBitmap">BitmapContent being overwritten.</param> /// <param name="destinationRegion">Region of bitmap to be overwritten.</param> protected static void ValidateCopyArguments(BitmapContent sourceBitmap, Rectangle sourceRegion, BitmapContent destinationBitmap, Rectangle destinationRegion) { if (sourceBitmap == null) throw new ArgumentNullException("sourceBitmap"); if (destinationBitmap == null) throw new ArgumentNullException("destinationBitmap"); // Make sure regions are within the bounds of the bitmaps if (sourceRegion.Left < 0 || sourceRegion.Top < 0 || sourceRegion.Width <= 0 || sourceRegion.Height <= 0 || sourceRegion.Right > sourceBitmap.Width || sourceRegion.Bottom > sourceBitmap.Height) throw new ArgumentOutOfRangeException("sourceRegion"); if (destinationRegion.Left < 0 || destinationRegion.Top < 0 || destinationRegion.Width <= 0 || destinationRegion.Height <= 0 || destinationRegion.Right > destinationBitmap.Width || destinationRegion.Bottom > destinationBitmap.Height) throw new ArgumentOutOfRangeException("destinationRegion"); }
protected override bool TryCopyFrom(BitmapContent sourceBitmap, Rectangle sourceRegion, Rectangle destinationRegion) { SurfaceFormat sourceFormat; if (!sourceBitmap.TryGetFormat(out sourceFormat)) { return(false); } SurfaceFormat format; TryGetFormat(out format); // A shortcut for copying the entire bitmap to another bitmap of the same type and format if (format == sourceFormat && (sourceRegion == new Rectangle(0, 0, Width, Height)) && sourceRegion == destinationRegion) { SetPixelData(sourceBitmap.GetPixelData()); return(true); } // TODO: Add a XNA unit test to see what it does // my guess is that this is invalid for DXT. // // Destination region copy is not yet supported if (destinationRegion != new Rectangle(0, 0, Width, Height)) { return(false); } // If the source is not Vector4 or requires resizing, send it through BitmapContent.Copy if (!(sourceBitmap is PixelBitmapContent <Vector4>) || sourceRegion.Width != destinationRegion.Width || sourceRegion.Height != destinationRegion.Height) { try { BitmapContent.Copy(sourceBitmap, sourceRegion, this, destinationRegion); return(true); } catch (InvalidOperationException) { return(false); } } // NVTT wants 8bit data in BGRA format. var colorBitmap = new PixelBitmapContent <Color>(sourceBitmap.Width, sourceBitmap.Height); BitmapContent.Copy(sourceBitmap, colorBitmap); var sourceData = colorBitmap.GetPixelData(); var dataHandle = GCHandle.Alloc(sourceData, GCHandleType.Pinned); AlphaMode alphaMode; Format outputFormat; var alphaDither = false; switch (format) { case SurfaceFormat.Dxt1: case SurfaceFormat.Dxt1SRgb: { bool hasTransparency; PrepareNVTT_DXT1(sourceData, out hasTransparency); outputFormat = hasTransparency ? Format.DXT1a : Format.DXT1; alphaMode = hasTransparency ? AlphaMode.Transparency : AlphaMode.None; alphaDither = true; break; } case SurfaceFormat.Dxt3: case SurfaceFormat.Dxt3SRgb: { PrepareNVTT(sourceData); outputFormat = Format.DXT3; alphaMode = AlphaMode.Transparency; break; } case SurfaceFormat.Dxt5: case SurfaceFormat.Dxt5SRgb: { PrepareNVTT(sourceData); outputFormat = Format.DXT5; alphaMode = AlphaMode.Transparency; break; } default: throw new InvalidOperationException("Invalid DXT surface format!"); } // Do all the calls to the NVTT wrapper within this handler // so we properly clean up if things blow up. try { var dataPtr = dataHandle.AddrOfPinnedObject(); var inputOptions = new InputOptions(); inputOptions.SetTextureLayout(TextureType.Texture2D, colorBitmap.Width, colorBitmap.Height, 1); inputOptions.SetMipmapData(dataPtr, colorBitmap.Width, colorBitmap.Height, 1, 0, 0); inputOptions.SetMipmapGeneration(false); inputOptions.SetGamma(1.0f, 1.0f); inputOptions.SetAlphaMode(alphaMode); var compressionOptions = new CompressionOptions(); compressionOptions.SetFormat(outputFormat); compressionOptions.SetQuality(Quality.Normal); // TODO: This isn't working which keeps us from getting the // same alpha dither behavior on DXT1 as XNA. // // See https://github.com/MonoGame/MonoGame/issues/6259 // //if (alphaDither) //compressionOptions.SetQuantization(false, false, true); var outputOptions = new OutputOptions(); outputOptions.SetOutputHeader(false); outputOptions.SetOutputOptionsOutputHandler(NvttBeginImage, NvttWriteImage, NvttEndImage); var dxtCompressor = new Compressor(); dxtCompressor.Compress(inputOptions, compressionOptions, outputOptions); } finally { dataHandle.Free(); } return(true); }
public Texture2DContent(BitmapContent bitmapContent) : base(new MipmapChainCollection(1)) { base.Faces[0] = bitmapContent; }
protected override bool TryCopyFrom(BitmapContent sourceBitmap, Rectangle sourceRegion, Rectangle destinationRegion) { SurfaceFormat sourceFormat; if (!sourceBitmap.TryGetFormat(out sourceFormat)) return false; SurfaceFormat format; TryGetFormat(out format); // A shortcut for copying the entire bitmap to another bitmap of the same type and format if (format == sourceFormat && (sourceRegion == new Rectangle(0, 0, Width, Height)) && sourceRegion == destinationRegion) { SetPixelData(sourceBitmap.GetPixelData()); return true; } // Destination region copy is not yet supported if (destinationRegion != new Rectangle(0, 0, Width, Height)) return false; // If the source is not Vector4 or requires resizing, send it through BitmapContent.Copy if (!(sourceBitmap is PixelBitmapContent<Vector4>) || sourceRegion.Width != destinationRegion.Width || sourceRegion.Height != destinationRegion.Height) { try { BitmapContent.Copy(sourceBitmap, sourceRegion, this, destinationRegion); return true; } catch (InvalidOperationException) { return false; } } //SquishFlags targetFormat = SquishFlags.ColourClusterFit; Format outputFormat = Format.DXT1; switch (format) { case SurfaceFormat.Dxt1: outputFormat = Format.DXT1; break; case SurfaceFormat.Dxt1SRgb: outputFormat = Format.DXT1; break; case SurfaceFormat.Dxt3: outputFormat = Format.DXT3; break; case SurfaceFormat.Dxt3SRgb: outputFormat = Format.DXT3; break; case SurfaceFormat.Dxt5: outputFormat = Format.DXT5; break; case SurfaceFormat.Dxt5SRgb: outputFormat = Format.DXT5; break; default: return false; } // libsquish requires RGBA8888 var colorBitmap = new PixelBitmapContent<Color>(sourceBitmap.Width, sourceBitmap.Height); BitmapContent.Copy(sourceBitmap, colorBitmap); var sourceData = colorBitmap.GetPixelData(); /* var dataSize = Squish.GetStorageRequirements(colorBitmap.Width, colorBitmap.Height, targetFormat); var data = new byte[dataSize]; var metric = new float[] { 1.0f, 1.0f, 1.0f }; Squish.CompressImage(sourceData, colorBitmap.Width, colorBitmap.Height, data, targetFormat, metric); SetPixelData(data); */ var dxtCompressor = new Compressor(); var inputOptions = new InputOptions(); if (outputFormat != Format.DXT1) inputOptions.SetAlphaMode(AlphaMode.Premultiplied); else inputOptions.SetAlphaMode(AlphaMode.None); inputOptions.SetTextureLayout(TextureType.Texture2D, colorBitmap.Width, colorBitmap.Height, 1); // Small hack here. NVTT wants 8bit data in BGRA. Flip the B and R channels // again here. GraphicsUtil.BGRAtoRGBA(sourceData); var dataHandle = GCHandle.Alloc(sourceData, GCHandleType.Pinned); try { var dataPtr = dataHandle.AddrOfPinnedObject(); inputOptions.SetMipmapData(dataPtr, colorBitmap.Width, colorBitmap.Height, 1, 0, 0); inputOptions.SetMipmapGeneration(false); inputOptions.SetGamma(1.0f, 1.0f); var outputOptions = new OutputOptions(); outputOptions.SetOutputHeader(false); var handler = new DxtDataHandler(this); outputOptions.SetOutputHandler(handler.BeginImage, handler.WriteData); var compressionOptions = new CompressionOptions(); compressionOptions.SetFormat(outputFormat); compressionOptions.SetQuality(Quality.Normal); dxtCompressor.Compress(inputOptions, compressionOptions, outputOptions); } finally { dataHandle.Free (); } return true; }
/// <summary> /// Copies one bitmap into another. /// The destination bitmap can be in any format and size. If the destination is larger or smaller, the source bitmap is scaled accordingly. /// </summary> /// <param name="sourceBitmap">BitmapContent being copied.</param> /// <param name="sourceRegion">Region of sourceBitmap.</param> /// <param name="destinationBitmap">BitmapContent being overwritten.</param> /// <param name="destinationRegion">Region of bitmap to be overwritten.</param> public static void Copy(BitmapContent sourceBitmap, Rectangle sourceRegion, BitmapContent destinationBitmap, Rectangle destinationRegion) { ValidateCopyArguments(sourceBitmap, sourceRegion, destinationBitmap, destinationRegion); SurfaceFormat sourceFormat; if (!sourceBitmap.TryGetFormat(out sourceFormat)) throw new InvalidOperationException("Could not retrieve surface format of source bitmap"); SurfaceFormat destinationFormat; if (!destinationBitmap.TryGetFormat(out destinationFormat)) throw new InvalidOperationException("Could not retrieve surface format of destination bitmap"); // If the formats are the same and the regions are the full bounds of the bitmaps and they are the same size, do a simpler copy if (sourceFormat == destinationFormat && sourceRegion == destinationRegion && sourceRegion == new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height) && destinationRegion == new Rectangle(0, 0, destinationBitmap.Width, destinationBitmap.Height)) { destinationBitmap.SetPixelData(sourceBitmap.GetPixelData()); return; } // The basic process is // 1. Copy from source bitmap region to a new PixelBitmapContent<Vector4> using sourceBitmap.TryCopyTo() // 2. If source and destination regions are a different size, resize Vector4 version // 3. Copy from Vector4 to destination region using destinationBitmap.TryCopyFrom() // Copy from the source to the intermediate Vector4 format var intermediate = new PixelBitmapContent<Vector4>(sourceRegion.Width, sourceRegion.Height); var intermediateRegion = new Rectangle(0, 0, intermediate.Width, intermediate.Height); if (sourceBitmap.TryCopyTo(intermediate, sourceRegion, intermediateRegion)) { // Resize the intermediate if required if (intermediate.Width != destinationRegion.Width || intermediate.Height != destinationRegion.Height) intermediate = intermediate.Resize(destinationRegion.Width, destinationRegion.Height) as PixelBitmapContent<Vector4>; // Copy from the intermediate to the destination if (destinationBitmap.TryCopyFrom(intermediate, new Rectangle(0, 0, intermediate.Width, intermediate.Height), destinationRegion)) return; } // If we got here, one of the above steps didn't work throw new InvalidOperationException("Could not copy between " + sourceFormat + " and " + destinationFormat); }
/// <summary> /// Attempts to copy a region of the specified bitmap onto another. /// </summary> /// <param name="destinationBitmap">BitmapContent being overwritten.</param> /// <param name="sourceRegion">Location of the source bitmap.</param> /// <param name="destinationRegion">Region of destination bitmap to be overwritten.</param> /// <returns>true if region copy is supported; false otherwise.</returns> protected abstract bool TryCopyTo(BitmapContent destinationBitmap, Rectangle sourceRegion, Rectangle destinationRegion);