1 using Microsoft.Xna.Framework.Graphics;
2 using Microsoft.Xna.Framework;
5 using System.Collections.Generic;
6 using System.ComponentModel;
10 using XnaV2 = Microsoft.Xna.Framework.Vector2;
11 using XnaColor = Microsoft.Xna.Framework.Color;
26 private Image parentImage;
29 private string assetName;
30 private Texture2D xnaTexture;
32 private event Action InitDimensions;
33 private event Action InitTexture;
38 internal Texture2D XNATexture
40 get { DoInitTexture();
return xnaTexture; }
43 public Color this[
int row,
int col]
51 xnaTexture.GetData<
Color>( 0, rect, buffer, 0, 1 );
59 if ( row < 0 || row >= xnaTexture.Height )
throw new IndexOutOfRangeException(
"row" );
60 if ( col < 0 || col >= XNATexture.Width )
throw new IndexOutOfRangeException(
"col" );
65 xnaTexture.SetData<
Color>( 0, rect, buffer, 0, 1 );
79 public Color[,]
GetData(
int ox = 0,
int oy = 0,
int w =
int.MaxValue,
int h =
int.MaxValue )
87 if ( nx <= 0 || ny <= 0 )
return new Color[0, 0];
94 xnaTexture.GetData<
Color>( 0, rect, buffer, 0, buffer.Length );
96 for (
int iy = 0; iy < ny; iy++ )
97 for (
int ix = 0; ix < nx; ix++ )
98 bmp[iy, ix] = buffer[i++];
112 public void SetData(
Color[,] bmp,
int ox = 0,
int oy = 0,
int w =
int.MaxValue,
int h =
int.MaxValue )
116 int ny = bmp.GetLength( 0 );
117 int nx = bmp.GetLength( 1 );
120 if ( ny > h ) ny = h;
121 if ( nx > w ) nx = w;
124 if ( nx <= 0 || ny <= 0 )
return;
129 for (
int iy = 0; iy < ny; iy++ )
130 for (
int ix = 0; ix < nx; ix++ )
131 buffer[i++] = bmp[iy, ix];
133 xnaTexture.SetData<
Color>( 0, rect, buffer, 0, buffer.Length );
146 public uint[,]
GetDataUInt(
int ox = 0,
int oy = 0,
int w =
int.MaxValue,
int h =
int.MaxValue )
149 if ( h < ny ) ny = h;
152 if ( w < nx ) nx = w;
154 if ( nx <= 0 || ny <= 0 )
return new uint[0, 0];
157 uint[,] bmp =
new uint[ny, nx];
161 xnaTexture.GetData<
Color>( 0, rect, buffer, 0, buffer.Length );
163 for (
int iy = 0; iy < ny; iy++ )
164 for (
int ix = 0; ix < nx; ix++ )
165 bmp[iy, ix] = buffer[i++].ToUInt();
178 public uint[][]
GetDataUIntAA(
int ox = 0,
int oy = 0,
int w =
int.MaxValue,
int h =
int.MaxValue )
181 if ( h < ny ) ny = h;
184 if ( w < nx ) nx = w;
186 if ( nx <= 0 || ny <= 0 )
return new uint[0][];
189 uint[][] bmp =
new uint[ny][];
193 xnaTexture.GetData<
Color>( 0, rect, buffer, 0, buffer.Length );
195 for (
int iy = 0; iy < ny; iy++ )
197 uint[] row =
new uint[nx];
199 for (
int ix = 0; ix < nx; ix++ )
200 row[ix] = buffer[i++].ToUInt();
214 public void SetData( uint[,] bmp,
int ox = 0,
int oy = 0,
int w =
int.MaxValue,
int h =
int.MaxValue )
218 int ny = bmp.GetLength( 0 );
219 int nx = bmp.GetLength( 1 );
222 if ( ny > h ) ny = h;
223 if ( nx > w ) nx = w;
227 if ( nx <= 0 || ny <= 0 )
return;
232 for (
int iy = 0; iy < ny; iy++ )
233 for (
int ix = 0; ix < nx; ix++ )
237 xnaTexture.SetData<
Color>( 0, rect, buffer, 0, buffer.Length );
250 public void SetData( uint[][] bmp,
int ox = 0,
int oy = 0,
int w =
int.MaxValue,
int h =
int.MaxValue )
255 int nx = bmp[0].Length;
258 if ( ny > h ) ny = h;
259 if ( nx > w ) nx = w;
260 if ( nx <= 0 || ny <= 0 )
return;
265 for (
int iy = 0; iy < ny; iy++ )
266 for (
int ix = 0; ix < nx; ix++ )
270 xnaTexture.SetData<
Color>( 0, rect, buffer, 0, buffer.Length );
276 if ( assetName != null )
277 return assetName.GetHashCode();
279 if ( xnaTexture != null )
280 return xnaTexture.GetHashCode();
282 return base.GetHashCode();
291 get { DoInitDimensions();
return _width; }
299 get { DoInitDimensions();
return _height; }
307 get { DoInitTexture();
return xnaTexture.Name; }
310 internal Image(
int width,
int height )
313 this._height = height;
314 this.InitTexture += CreateNewTexture;
317 internal Image(
string assetName )
319 this.assetName = assetName;
320 this.InitDimensions += LoadContentTexture;
323 [EditorBrowsable( EditorBrowsableState.Never )]
324 public Image( Microsoft.Xna.Framework.Graphics.Texture2D texture )
326 this.xnaTexture = texture;
327 this._width = texture.Width;
328 this._height = texture.Height;
341 this._height = height;
342 this.InitTexture += CreateNewTexture;
343 this.InitTexture += delegate { this.
Fill( backColor ); };
353 : this( (int)Math.Round( width ), (int)Math.Round( height ), backColor )
357 private void DoInitDimensions()
359 if ( _width >= 0 && _height >= 0 )
362 if ( InitDimensions != null )
365 throw new InvalidOperationException(
"Cannot initialize dimensions for image!" );
368 private void DoInitTexture()
372 if ( xnaTexture != null )
375 if ( InitTexture != null )
378 throw new InvalidOperationException(
"Cannot initialize texture for image!" );
381 private void LoadContentTexture()
385 Debug.Assert( assetName != null );
386 xnaTexture =
Game.
Instance.Content.Load<Texture2D>( assetName );
387 _width = xnaTexture.Width;
388 _height = xnaTexture.Height;
391 private void CreateNewTexture()
400 if ( assetName != null )
402 copy =
new Image( assetName );
407 copy.InitTexture += delegate { CopyData( copy,
this ); };
413 private static void CopyData(
Image dest,
Image src )
422 for ( rect.Y = 0; rect.Y < h; rect.Y++ )
424 src.xnaTexture.GetData<
Color>( 0, rect, scanline, 0, w );
425 dest.xnaTexture.SetData<
Color>( 0, rect, scanline, 0, w );
429 private static void CopyData( Texture2D dest, Texture2D src )
436 for ( rect.Y = 0; rect.Y < h; rect.Y++ )
438 src.GetData<
Color>( 0, rect, scanline, 0, w );
439 dest.SetData<
Color>( 0, rect, scanline, 0, w );
447 int w = srcRect.Width;
448 int h = srcRect.Height;
459 src.xnaTexture.GetData<
Color>( 0, srcRect, buffer, 0, w * h );
460 dest.xnaTexture.SetData<
Color>( 0, destRect, buffer, 0, w * h );
469 Converter<XnaColor, XnaColor> newOp = delegate(
XnaColor c )
471 return operation(
new Color( c ) ).AsXnaColor();
489 for ( scanRect.Y = 0; scanRect.Y < xnaTexture.Height; scanRect.Y++ )
491 xnaTexture.GetData<
XnaColor>( 0, scanRect, scanline, 0, xnaTexture.Width );
493 for (
int j = 0; j < xnaTexture.Width; j++ )
495 scanline[j] = operation( scanline[j] );
498 xnaTexture.SetData<
XnaColor>( 0, scanRect, scanline, 0, xnaTexture.Width );
509 private void InvalidateAsset()
511 if ( assetName == null )
514 Texture2D oldTex = xnaTexture;
516 CopyData( xnaTexture, oldTex );
520 private void UpdateTexture()
525 private void DoUpdateTexture()
527 if ( parentImage != null )
530 CopyData( parentImage,
this, parentRectangle, srcRect );
531 parentImage.UpdateTexture();
535 #region static methods 545 StreamReader sr =
new StreamReader( path );
573 public static Image FromURL(
string url )
580 HttpWebRequest request = (HttpWebRequest)WebRequest.Create( url );
581 HttpWebResponse response = (HttpWebResponse)request.GetResponse();
582 Stream resStream = response.GetResponseStream();
584 MemoryStream memStream =
new MemoryStream();
585 resStream.CopyTo( memStream );
606 for (
int ver = 0; ver < height; ver++ )
608 for (
int hor = 0; hor < width; hor++ )
610 if (transparent) textureColors[i++] =
XnaColor.Transparent;
611 else textureColors[i++] =
XnaColor.Black;
616 for (
int j = 0; j < stars; j++ )
621 for (
int k = 0; k < size / 2; k++ )
625 if ( star + k < textureColors.Length )
626 textureColors[star + k] = starcolor;
628 if ( size % 2 != 0 || size == 2 )
631 int nextStar = star + k + width;
633 if ( nextStar < ( width * height ) )
635 textureColors[nextStar] = starcolor;
641 Texture2D newTexture =
new Texture2D(
Game.
GraphicsDevice, width, height,
false, SurfaceFormat.Color );
642 newTexture.SetData<
XnaColor>( textureColors );
644 return new Image( newTexture );
661 var device = spriteBatch.GraphicsDevice;
663 XnaV2 textDims = font.XnaFont.MeasureString( text );
664 int textw = ( textDims.X > 1 ) ? Convert.ToInt32( textDims.X ) : 1;
665 int texth = ( textDims.Y > 1 ) ? Convert.ToInt32( textDims.Y ) : 1;
668 RenderTarget2D rt =
new RenderTarget2D( device, textw, texth,
false, SurfaceFormat.Color, DepthFormat.Depth24Stencil8 );
671 device.SetRenderTarget( rt );
672 device.Clear( ClearOptions.Target | ClearOptions.DepthBuffer, backgroundColor.AsXnaColor(), 1.0f, 0 );
675 spriteBatch.DrawString( font.XnaFont, text,
XnaV2.Zero, textColor.AsXnaColor() );
679 device.SetRenderTarget( null );
682 return new Image( rt );
701 var device = spriteBatch.GraphicsDevice;
703 XnaV2 textDims = font.XnaFont.MeasureString( text );
704 int textw = ( textDims.X > 1 ) ? Convert.ToInt32( textDims.X ) : 1;
705 int texth = ( textDims.Y > 1 ) ? Convert.ToInt32( textDims.Y ) : 1;
708 RenderTarget2D rt =
new RenderTarget2D( device, img.
Width, img.
Height,
false, SurfaceFormat.Color, DepthFormat.Depth24Stencil8 );
711 device.SetRenderTarget( rt );
712 device.Clear( ClearOptions.Target | ClearOptions.DepthBuffer, backgroundColor.AsXnaColor(), 1.0f, 0 );
714 float xpos = 0.5f * ( img.
Width - textw ) + (
float)position.
X;
715 float ypos = 0.5f * ( img.
Height - texth ) - (
float)position.
Y;
718 spriteBatch.Draw( img.XNATexture, rt.Bounds,
XnaColor.White );
719 spriteBatch.DrawString( font.XnaFont, text,
new XnaV2( xpos, ypos ), textColor.AsXnaColor() );
723 device.SetRenderTarget( null );
727 return new Image( rt );
753 XnaColor lower = lowerColor.AsXnaColor();
754 XnaColor upper = upperColor.AsXnaColor();
758 for (
int ver = 0; ver < imageHeight; ver++ )
760 for (
int hor = 0; hor < imageWidth; hor++ )
762 textureColors[i++] =
XnaColor.Lerp( upper, lower, ( (
float)ver / (
float)imageHeight ) );
766 Texture2D newTexture =
new Texture2D(
Game.
GraphicsDevice, imageWidth, imageHeight,
false, SurfaceFormat.Color );
767 newTexture.SetData<
XnaColor>( textureColors );
768 return new Image( newTexture );
791 res[l] = scanline[r];
792 res[r] = scanline[l];
799 res[l] = scanline[l];
812 Texture2D newTex =
new Texture2D( image.XNATexture.GraphicsDevice, image.
Width, image.
Height,
false, image.XNATexture.Format );
816 for ( scanRect.Y = 0; scanRect.Y < image.
Height; scanRect.Y++ )
818 image.XNATexture.GetData<
XnaColor>( 0, scanRect, scanline, 0, image.
Width );
819 scanline = MirrorLine( scanline, image.
Width );
820 newTex.SetData<
XnaColor>( 0, scanRect, scanline, 0, image.
Width );
823 return new Image( newTex );
834 for (
int i = 0; i < images.Length; i++ )
835 result[i] =
Mirror( images[i] );
846 Texture2D newTex =
new Texture2D( image.XNATexture.GraphicsDevice, image.
Width, image.
Height,
false, image.XNATexture.Format );
852 for (
int i = 0; i < image.
Height / 2; i++ )
855 scanRectLower.Y = image.
Height - 1 - i;
857 image.XNATexture.GetData<
XnaColor>( 0, scanRectUpper, scanlineUpper, 0, image.
Width );
858 image.XNATexture.GetData<
XnaColor>( 0, scanRectLower, scanlineLower, 0, image.
Width );
860 newTex.SetData<
XnaColor>( 0, scanRectUpper, scanlineLower, 0, image.
Width );
861 newTex.SetData<
XnaColor>( 0, scanRectLower, scanlineUpper, 0, image.
Width );
864 if ( image.
Height % 2 == 1 )
867 scanRectUpper.Y = image.
Height / 2;
868 image.XNATexture.GetData<
XnaColor>( 0, scanRectUpper, scanlineUpper, 0, image.
Width );
869 newTex.SetData<
XnaColor>( 0, scanRectUpper, scanlineUpper, 0, image.
Width );
872 return new Image( newTex );
883 for (
int i = 0; i < images.Length; i++ )
884 result[i] =
Flip( images[i] );
896 Texture2D newTex =
new Texture2D( image.XNATexture.GraphicsDevice, image.
Width, image.
Height,
false, image.XNATexture.Format );
899 XnaColor xnaColor = color.AsXnaColor();
901 for ( scanRect.Y = 0; scanRect.Y < image.
Height; scanRect.Y++ )
903 image.XNATexture.GetData<
XnaColor>( 0, scanRect, scanline, 0, image.
Width );
905 for (
int i = 0; i < image.
Width; i++ )
907 if ( scanline[i].
A < 255 )
909 scanline[i].R = (byte)( ( 255 - scanline[i].
A ) * xnaColor.R + scanline[i].A * scanline[i].R );
910 scanline[i].G = (byte)( ( 255 - scanline[i].A ) * xnaColor.G + scanline[i].A * scanline[i].G );
911 scanline[i].B = (byte)( ( 255 - scanline[i].A ) * xnaColor.B + scanline[i].A * scanline[i].B );
913 if ( scanline[i].A > 10 )
920 newTex.SetData<
XnaColor>( 0, scanRect, scanline, 0, image.
Width );
923 return new Image( newTex );
935 for (
int i = 0; i < images.Length; i++ )
936 result[i] =
Color( images[i], color );
942 Texture2D newTex =
new Texture2D( image.XNATexture.GraphicsDevice, image.
Width, image.
Height,
false, image.XNATexture.Format );
946 for ( scanRect.Y = 0; scanRect.Y < image.
Height; scanRect.Y++ )
948 image.XNATexture.GetData<
XnaColor>( 0, scanRect, scanline, 0, image.
Width );
949 for (
int i = 0; i < image.
Width; i++ )
951 scanline[i].A = alpha;
953 newTex.SetData<
XnaColor>( 0, scanRect, scanline, 0, image.
Width );
955 return new Image( newTex );
960 if ( left.
Height != right.
Height )
throw new InvalidOperationException(
"Cannot tile two images with different height" );
962 left.DoInitTexture();
963 right.DoInitTexture();
970 tiled.InitTexture += delegate { CopyData( tiled, left, leftRect, leftRect ); };
971 tiled.InitTexture += delegate { CopyData( tiled, right, rightDest, rightSrc ); };
978 if ( top.
Width != bottom.
Width )
throw new InvalidOperationException(
"Cannot tile two images with different width" );
981 bottom.DoInitTexture();
988 tiled.InitTexture += delegate { CopyData( tiled, top, topRect, topRect ); };
989 tiled.InitTexture += delegate { CopyData( tiled, bottom, botDest, botSrc ); };
996 public Image Area(
int left,
int top,
int right,
int bottom )
998 int width = right - left;
999 int height = bottom - top;
1001 if ( width <= 0 )
throw new ArgumentException(
"Left coordinate must be less than right coordinate" );
1002 if ( height <= 0 )
throw new ArgumentException(
"Top coordinate must be less than bottom coordinate" );
1007 Image areaImage =
new Image( width, height );
1008 areaImage.parentImage =
this;
1009 areaImage.parentRectangle = srcRect;
1010 areaImage.InitTexture += delegate { CopyData( areaImage,
this, destRect, srcRect ); };
1020 Color[] scanline =
new Color[xnaTexture.Width];
1022 for (
int i = 0; i < xnaTexture.Width; i++ )
1023 scanline[i] = backColor;
1025 for ( rect.Y = 0; rect.Y < xnaTexture.Height; rect.Y++ )
1026 xnaTexture.SetData<
Color>( 0, rect, scanline, 0, xnaTexture.Width );
1041 XnaColor srcColor = src.AsXnaColor();
1042 XnaColor destColor = dest.AsXnaColor();
1043 Converter<XnaColor, XnaColor> op = delegate(
XnaColor c )
1045 if ( exactAlpha && c.A != srcColor.A )
1048 if (
JyColor.Distance( c, srcColor ) <= tolerance )
1050 if ( !blend )
return destColor;
1051 Vector3 srcDist =
new Vector3( c.R - srcColor.R, c.G - srcColor.G, c.B - srcColor.B );
1052 return new XnaColor( destColor.ToVector3() + srcDist );
1068 XnaColor srcColor = src.AsXnaColor();
1069 XnaColor destColor = dest.AsXnaColor();
1070 Converter<XnaColor, XnaColor> op = delegate(
XnaColor c )
1072 return c == srcColor ? destColor : c;
1086 MemoryStream jpegStream =
new MemoryStream();
1087 XNATexture.SaveAsJpeg( jpegStream,
Width,
Height );
1088 jpegStream.Seek( 0, SeekOrigin.Begin );
1100 MemoryStream pngStream =
new MemoryStream();
1102 pngStream.Seek( 0, SeekOrigin.Begin );
static Color UIntToColor(uint c)
Tekee kokonaisluvusta värin
Stream AsPng()
Palauttaa kuvan png-muodossa, jossa se voidaan esimerkiksi tallentaa DataStorage.Export -metodilla...
void ReplaceColor(Color src, Color dest)
Korvaa värin toisella värillä.
static Image Mirror(Image image)
Peilaa kuvan X-suunnassa.
static Image DrawTextOnImage(Image img, string text, Vector position, Font font, Color textColor, Color backgroundColor)
Piirtää tekstiä kuvan päälle.
static void DoNextUpdate(Action action)
Suorittaa aliohjelman seuraavalla päivityksellä.
Image(int width, int height, Color backColor)
Luo uuden kuvan.
static Image FromColor(int imageWidth, int imageHeight, Color color)
Luo yksivärisen kuvan.
static Image FromText(string text, Font font, Color textColor, Color backgroundColor)
Luo kuvan tekstistä.
void ApplyPixelOperation(Converter< Color, Color > operation)
Suorittaa annetun pikselioperaation koko kuvalle.
Microsoft.Xna.Framework.Rectangle XnaRectangle
static Image FromStream(Stream stream)
Lataa kuvan tiedostovirrasta.
static Image [] Flip(Image[] images)
Peilaa kuvat Y-suunnassa.
uint [][] GetDataUIntAA(int ox=0, int oy=0, int w=int.MaxValue, int h=int.MaxValue)
Palalutetaan kuvan pikselit ARGB-uint[][] -taulukkona
Satunnaisgeneraattori. Luo satunnaisia arvoja, mm. lukuja, vektoreita sekä kulmia.
static Image [] Color(Image[] images, Color color)
Värittää kuvat.
int Width
Leveys pikseleinä.
static Image FromGradient(int imageWidth, int imageHeight, Color lowerColor, Color upperColor)
Luo pystysuuntaisen liukuväritetyn kuvan.
static readonly Vector Zero
Nollavektori.
void Fill(Color backColor)
Image(double width, double height, Color backColor)
Luo uuden kuvan.
static Image TileHorizontal(Image left, Image right)
static int NextInt(int maxValue)
Palauttaa satunnaisen kokonaisluvun, joka on vähintään 0 ja pienempi kuin
static Image [] Mirror(Image[] images)
Peilaa kuvat X-suunnassa.
void SetData(Color[,] bmp, int ox=0, int oy=0, int w=int.MaxValue, int h=int.MaxValue)
Asettaa kuvan pikselit Color-taulukosta
void SetData(uint[][] bmp, int ox=0, int oy=0, int w=int.MaxValue, int h=int.MaxValue)
Asetetaan kuvan pikselit ARGB-uint taulukosta
static readonly Color Transparent
Läpinäkyvä väri.
Peliluokka reaaliaikaisille peleille.
static Image Color(Image image, Color color)
Värittää kuvan.
Image(Microsoft.Xna.Framework.Graphics.Texture2D texture)
static Image Color(Image image, byte alpha)
int Height
Korkeus pikseleinä.
static Image FromFile(StorageFile file)
Lataa kuvan tiedostosta. Kuvan ei tarvitse olla lisättynä Content-projektiin.
static Image FromFile(string path)
Lataa kuvan tiedostosta. Kuvan ei tarvitse olla lisättynä Content-projektiin.
static new GraphicsDevice GraphicsDevice
static Image CreateStarSky(int width, int height, int stars, bool transparent=false)
Luo tähtitaivaskuvan.
static Color NextColor()
Palauttaa satunnaisen värin.
static Image TileVertical(Image top, Image bottom)
byte AlphaComponent
Läpinäkymättömyys välillä 0-255
void ReplaceColor(Color src, Color dest, double tolerance, bool blend, bool exactAlpha=false)
Korvaa värin toisella värillä.
Color [,] GetData(int ox=0, int oy=0, int w=int.MaxValue, int h=int.MaxValue)
Kuvan pikselit Color-taulukkona
Stream AsJpeg()
Palauttaa kuvan jpeg-muodossa, jossa se voidaan esimerkiksi tallentaa DataStorage.Export -metodilla.
Image Area(int left, int top, int right, int bottom)
static Image DrawTextOnImage(Image img, string text, Font font, Color textColor)
Piirtää tekstiä kuvan päälle keskelle kuvaa.
static readonly Color White
Valkoinen.
uint [,] GetDataUInt(int ox=0, int oy=0, int w=int.MaxValue, int h=int.MaxValue)
Palalutetaan kuvan pikselit ARGB-uint[,] -taulukkona
override int GetHashCode()
static Image Flip(Image image)
Peilaa kuvan Y-suunnassa.
void SetData(uint[,] bmp, int ox=0, int oy=0, int w=int.MaxValue, int h=int.MaxValue)
Asetetaan kuvan pikselit ARGB-uint taulukosta
Microsoft.Xna.Framework.Color XnaColor