#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ANX.Framework.Graphics;
using ANX.Framework.Content.Pipeline.Helpers;
using System.Diagnostics;
#endregion
// This file is part of the ANX.Framework created by the
// "ANX.Framework developer group" and released under the Ms-PL license.
// For details see: http://anxframework.codeplex.com/license
namespace ANX.Framework.Content.Pipeline.Graphics
{
public abstract class BitmapContent : ContentItem
{
public BitmapContent()
{
}
protected BitmapContent(int width, int height)
{
if (width <= 0)
throw new ArgumentOutOfRangeException("width must be bigger than 0.");
if (height <= 0)
throw new ArgumentOutOfRangeException("height must be bigger than 0.");
Width = width;
Height = height;
}
///
/// Returns the height of the bitmap.
///
public int Height
{
get;
private set;
}
///
/// Returns the width of the bitmap.
///
public int Width
{
get;
private set;
}
///
/// Copies the content from onto by using and .
///
/// The source bitmap of the copy operation.
/// The destination bitmap of the copy operation.
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));
}
///
/// Copies a region of onto a region of .
///
///
///
/// The destination bitmap of the copy operation.
///
public static void Copy(BitmapContent sourceBitmap, Rectangle sourceRegion, BitmapContent destinationBitmap, Rectangle destinationRegion)
{
ValidateCopyArguments(sourceBitmap, sourceRegion, destinationBitmap, destinationRegion);
if (sourceBitmap.TryCopyTo(destinationBitmap, sourceRegion, destinationRegion))
{
return;
}
if (destinationBitmap.TryCopyFrom(sourceBitmap, sourceRegion, destinationRegion))
{
return;
}
}
private static void ValidateConvertArguments(BitmapContent source, Type newType)
{
if (source == null)
throw new ArgumentNullException("source");
if (newType == null)
throw new ArgumentNullException("newBitmapType");
if (!newType.IsSubclassOf(typeof(BitmapContent)))
{
throw new ArgumentException(string.Format("The wanted bitmap type {0} does not inherit from {1}.", newType.FullName, typeof(BitmapContent).FullName));
}
if (newType.IsAbstract)
{
throw new ArgumentException(string.Format("Can't construct a new instance of {0}. It must not be abstract.", newType.FullName));
}
if (newType.ContainsGenericParameters)
{
throw new ArgumentException(string.Format("Can't construct a new instance of {0}. It must not contain unset generic parameters.", newType.FullName));
}
if (newType.GetConstructor(new Type[] { typeof(int), typeof(int) }) == null)
{
throw new ArgumentException(string.Format("Can't construct a new instance of {0}. It must contain a public constructor that accepts width and height.", newType.FullName));
}
}
public static BitmapContent Convert(BitmapContent source, Type newType)
{
if (source == null)
throw new ArgumentNullException("source");
return Convert(source, newType, source.Width, source.Height);
}
public static T Convert(BitmapContent source) where T : BitmapContent
{
return (T)Convert(source, typeof(T));
}
public static BitmapContent Convert(BitmapContent source, Type newType, int newWidth, int newHeight)
{
ValidateConvertArguments(source, newType);
if (source.GetType() != newType)
{
BitmapContent newBitmap = (BitmapContent)Activator.CreateInstance(newType, newWidth, newHeight);
BitmapContent.Copy(source, newBitmap);
return newBitmap;
}
return source;
}
public static T Convert(BitmapContent source, int newWidth, int newHeight) where T : BitmapContent
{
return (T)Convert(source, typeof(T), newWidth, newHeight);
}
public abstract byte[] GetPixelData();
public abstract void SetPixelData(byte[] sourceData);
public abstract bool TryGetFormat(out SurfaceFormat format);
public override string ToString()
{
return string.Format("{0}, {1}x{2}", GetType().Name, this.Width, this.Height);
}
protected abstract bool TryCopyFrom(BitmapContent sourceBitmap, Rectangle sourceRegion, Rectangle destinationRegion);
protected abstract bool TryCopyTo(BitmapContent destinationBitmap, Rectangle sourceRegion, Rectangle destinationRegion);
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.X < 0 || sourceRegion.Y < 0 || sourceRegion.Width <= 0 || sourceRegion.Height <= 0 ||
sourceRegion.Right > sourceBitmap.Width || sourceRegion.Bottom > sourceBitmap.Height)
throw new ArgumentOutOfRangeException("sourceRegion");
if (destinationRegion.X < 0 || destinationRegion.Y < 0 || destinationRegion.Width <= 0 || destinationRegion.Height <= 0 ||
destinationRegion.Right > destinationBitmap.Width || destinationRegion.Bottom > destinationBitmap.Height)
throw new ArgumentOutOfRangeException("destinationRegion");
}
private void ValidateTextureSize(SurfaceFormat format, ref int width, ref int height)
{
switch (format)
{
case SurfaceFormat.Dxt1:
case SurfaceFormat.Dxt3:
case SurfaceFormat.Dxt5:
width = MathHelper.Multiple(width, 4);
height = MathHelper.Multiple(height, 4);
break;
}
}
protected static bool Draw(BitmapContent sourceBitmap, Rectangle sourceRegion, BitmapContent destinationBitmap, Rectangle destinationRegion, TextureFilter filter)
{
var pixelSource = BitmapContent.Convert>(sourceBitmap);
var pixelDestination = BitmapContent.Convert>(destinationBitmap);
if (pixelSource == null || pixelDestination == null)
return false;
using (Texture2D sourceTexture = new Texture2D(GraphicsHelper.ReferenceDevice, pixelSource.Width, pixelSource.Height, false, SurfaceFormat.Color))
using (RenderTarget2D destinationTexture = new RenderTarget2D(GraphicsHelper.ReferenceDevice, pixelDestination.Width, pixelDestination.Height, false, SurfaceFormat.Color, DepthFormat.None))
{
byte[] sourceData = pixelSource.GetPixelData();
byte[] destinationData = pixelDestination.GetPixelData();
sourceTexture.SetData(sourceData);
destinationTexture.SetData(destinationData);
GraphicsHelper.DrawQuad(GraphicsHelper.ReferenceDevice, sourceTexture, sourceRegion, destinationTexture, destinationRegion, filter);
sourceTexture.GetData(sourceData);
destinationTexture.GetData(destinationData);
pixelSource.SetPixelData(sourceData);
pixelDestination.SetPixelData(destinationData);
BitmapContent.Copy(pixelSource, sourceBitmap);
BitmapContent.Copy(pixelDestination, destinationBitmap);
}
return true;
}
}
}