Jypeli  9
The simple game programming library
Image.cs
Siirry tämän tiedoston dokumentaatioon.
1 using Microsoft.Xna.Framework.Graphics;
3 using System;
4 using System.IO;
5 using System.ComponentModel;
6 using System.Diagnostics;
7 using System.Net;
8 
9 using XnaRectangle = Microsoft.Xna.Framework.Rectangle;
10 using XnaV2 = Microsoft.Xna.Framework.Vector2;
13 
14 #if WINDOWS_STOREAPP
17 #else
20 #endif
21 
22 
23 namespace Jypeli
24 {
28  public class Image
29  {
30 
31  private static int MONOGETDATAMUL = 1;
32  private static int MONOGETDATAINC = 0;
33  // private static const int MONOGETDATAMUL = 1;
34  // private static const int MONOGETDATAINC = 0; // tavallinen
35 
36  private Image parentImage;
38 
39  private string assetName;
40  private Texture2D xnaTexture;
41 
42  private event Action InitDimensions;
43  private event Action InitTexture;
44 
45  int _width = -1;
46  int _height = -1;
47 
48  private static string[] imageExtensions = { ".png", ".jpg", ".xnb"};
49 
54  public static void SetLineCorrection(int n)
55  {
56  if ( n == 1 )
57  {
58  MONOGETDATAMUL = 2;
59  MONOGETDATAINC = 1;
60  return;
61  }
62  if (n == 0)
63  {
64  MONOGETDATAMUL = 1;
65  MONOGETDATAINC = 0;
66  return;
67  }
68  }
69 
70  internal Texture2D XNATexture
71  {
72  get { DoInitTexture(); return xnaTexture; }
73  }
74 
75  public Color this[int row, int col]
76  {
77  get
78  {
79  DoInitTexture();
80 
81  Color[] buffer = new Color[1];
82  XnaRectangle rect = new XnaRectangle( col, row, 1, 1 );
83  xnaTexture.GetData<Color>( 0, rect, buffer, 0, 1 );
84  return buffer[0];
85  }
86  set
87  {
88  DoInitTexture();
90 
91  if ( row < 0 || row >= xnaTexture.Height ) throw new IndexOutOfRangeException( "row" );
92  if ( col < 0 || col >= XNATexture.Width ) throw new IndexOutOfRangeException( "col" );
93 
94  Color[] buffer = new Color[1] { value };
95  XnaRectangle rect = new XnaRectangle( col, row, 1, 1 );
96 
97  xnaTexture.SetData<Color>( 0, rect, buffer, 0, 1 );
98  UpdateTexture();
99  }
100  }
101 
102 
111  public Color[,] GetData( int ox = 0, int oy = 0, int w = int.MaxValue, int h = int.MaxValue )
112  {
113  int ny = Height;
114  if ( h < ny ) ny = h;
115  if ( Height < ny + oy ) ny = Height - oy;
116  int nx = Width;
117  if ( w < nx ) nx = w;
118  if ( Width < nx + ox ) nx = Width - ox;
119  if ( nx <= 0 || ny <= 0 ) return new Color[0, 0];
120 
121  DoInitTexture();
122  Color[,] bmp = new Color[ny, nx];
123 
124  XnaRectangle rect = new XnaRectangle( ox, oy, nx, ny );
125  Color[] buffer = new Color[ny * nx * MONOGETDATAMUL];
126  xnaTexture.GetData<Color>( 0, rect, buffer, 0, buffer.Length );
127  int i = 0;
128  for (int iy = 0; iy < ny; iy++)
129  {
130  for (int ix = 0; ix < nx; ix++)
131  bmp[iy, ix] = buffer[i++];
132  i += nx * MONOGETDATAINC;
133  }
134  return bmp;
135  }
136 
137 
147  public void SetData( Color[,] bmp, int ox = 0, int oy = 0, int w = int.MaxValue, int h = int.MaxValue )
148  {
149  DoInitTexture();
150  InvalidateAsset();
151  int ny = bmp.GetLength( 0 );
152  int nx = bmp.GetLength( 1 );
153  if ( ny > Height ) ny = Height;
154  if ( nx > Width ) nx = Height;
155  if ( ny > h ) ny = h;
156  if ( nx > w ) nx = w;
157  if ( Height < ny + oy ) ny = Height - oy;
158  if ( Width < nx + ox ) nx = Width - ox;
159  if ( nx <= 0 || ny <= 0 ) return;
160 
161  XnaRectangle rect = new XnaRectangle( ox, oy, nx, ny );
162  Color[] buffer = new Color[ny * nx];
163  int i = 0;
164  for ( int iy = 0; iy < ny; iy++ )
165  for ( int ix = 0; ix < nx; ix++ )
166  buffer[i++] = bmp[iy, ix];
167 
168  xnaTexture.SetData<Color>( 0, rect, buffer, 0, buffer.Length );
169  UpdateTexture();
170  }
171 
181  public void SetData(byte[] byteArr, int height, int width)
182  {
183  Color[,] newColor = new Color[height, width];
184 
185  for (int i = 0; i < height; i++)
186  {
187  for (int j = 0; j < width; j++)
188  {
189  int r = byteArr[4 * (i * width + j) + 0];
190  int g = byteArr[4 * (i * width + j) + 1];
191  int b = byteArr[4 * (i * width + j) + 2];
192  int a = byteArr[4 * (i * width + j) + 3];
193  newColor[i, j] = new Color(r, g, b, a);
194  }
195  }
196  this.SetData(newColor);
197  }
198 
205  public void SetData(byte[] byteArr)
206  {
207  SetData(byteArr, this.Height, this.Width);
208  }
209 
215  public byte[] GetByteArray()
216  {
217  DoInitTexture();
218  byte[] buffer = new byte[4 * Width * Height];
219  xnaTexture.GetData<byte>( buffer );
220  return buffer;
221  }
222 
231  public uint[,] GetDataUInt( int ox = 0, int oy = 0, int w = int.MaxValue, int h = int.MaxValue )
232  {
233  int ny = Height;
234  if ( h < ny ) ny = h;
235  if ( Height < ny + oy ) ny = Height - oy;
236  int nx = Width;
237  if ( w < nx ) nx = w;
238  if ( Width < nx + ox ) nx = Width - ox;
239  if ( nx <= 0 || ny <= 0 ) return new uint[0, 0];
240 
241  DoInitTexture();
242  uint[,] bmp = new uint[ny, nx];
243 
244  XnaRectangle rect = new XnaRectangle( ox, oy, nx, ny );
245  Color[] buffer = new Color[ny * nx * MONOGETDATAMUL];
246  xnaTexture.GetData<Color>( 0, rect, buffer, 0, buffer.Length );
247  int i = 0;
248  for (int iy = 0; iy < ny; iy++)
249  {
250  for (int ix = 0; ix < nx; ix++)
251  bmp[iy, ix] = buffer[i++].ToUInt();
252  i += nx * MONOGETDATAINC;
253  }
254  return bmp;
255  }
256 
257 
266  public uint[][] GetDataUIntAA( int ox = 0, int oy = 0, int w = int.MaxValue, int h = int.MaxValue )
267  {
268  int ny = Height;
269  if ( h < ny ) ny = h;
270  if ( Height < ny + oy ) ny = Height - oy;
271  int nx = Width;
272  if ( w < nx ) nx = w;
273  if ( Width < nx + ox ) nx = Width - ox;
274  if ( nx <= 0 || ny <= 0 ) return new uint[0][];
275 
276  DoInitTexture();
277  uint[][] bmp = new uint[ny][];
278 
279  XnaRectangle rect = new XnaRectangle( ox, oy, nx, ny );
280  Color[] buffer = new Color[ny * nx * MONOGETDATAMUL];
281  xnaTexture.GetData<Color>( 0, rect, buffer, 0, buffer.Length );
282  int i = 0;
283  for ( int iy = 0; iy < ny; iy++ )
284  {
285  uint[] row = new uint[nx];
286  bmp[iy] = row;
287  for ( int ix = 0; ix < nx; ix++ )
288  row[ix] = buffer[i++].ToUInt();
289  i += nx * MONOGETDATAINC;
290  }
291  return bmp;
292  }
293 
294 
303  public void SetData( uint[,] bmp, int ox = 0, int oy = 0, int w = int.MaxValue, int h = int.MaxValue )
304  {
305  DoInitTexture();
306  InvalidateAsset();
307  int ny = bmp.GetLength( 0 );
308  int nx = bmp.GetLength( 1 );
309  if ( ny > Height ) ny = Height;
310  if ( nx > Width ) nx = Width;
311  if ( ny > h ) ny = h;
312  if ( nx > w ) nx = w;
313  if ( Height < ny + oy ) ny = Height - oy;
314  if ( Width < nx + ox ) nx = Width - ox;
315 
316  if ( nx <= 0 || ny <= 0 ) return;
317 
318  XnaRectangle rect = new XnaRectangle( ox, oy, nx, ny );
319  Color[] buffer = new Color[ny * nx];
320  int i = 0;
321  for ( int iy = 0; iy < ny; iy++ )
322  for ( int ix = 0; ix < nx; ix++ )
323  buffer[i++] = Jypeli.Color.UIntToColor( bmp[iy, ix] );
324  // foreach (int c in bmp) buffer[i++] = Jypeli.Color.IntToColor(c);
325 
326  xnaTexture.SetData<Color>( 0, rect, buffer, 0, buffer.Length );
327  UpdateTexture();
328  }
329 
330 
339  public void SetData( uint[][] bmp, int ox = 0, int oy = 0, int w = int.MaxValue, int h = int.MaxValue )
340  {
341  DoInitTexture();
342  InvalidateAsset();
343  int ny = bmp.Length;
344  int nx = bmp[0].Length;
345  if ( ny > Height ) ny = Height;
346  if ( nx > Width ) nx = Width;
347  if ( ny > h ) ny = h;
348  if ( nx > w ) nx = w;
349  if ( nx <= 0 || ny <= 0 ) return;
350 
351  XnaRectangle rect = new XnaRectangle( ox, oy, nx, ny );
352  Color[] buffer = new Color[ny * nx];
353  int i = 0;
354  for ( int iy = 0; iy < ny; iy++ )
355  for ( int ix = 0; ix < nx; ix++ )
356  buffer[i++] = Jypeli.Color.UIntToColor( bmp[iy][ix] );
357  // foreach (int c in bmp) buffer[i++] = Jypeli.Color.IntToColor(c);
358 
359  xnaTexture.SetData<Color>( 0, rect, buffer, 0, buffer.Length );
360  UpdateTexture();
361  }
362 
363 
367  public int Width
368  {
369  get { DoInitDimensions(); return _width; }
370  }
371 
375  public int Height
376  {
377  get { DoInitDimensions(); return _height; }
378  }
379 
383  public string Name
384  {
385  get { DoInitTexture(); return xnaTexture.Name; }
386  }
387 
388  internal Image( int width, int height )
389  {
390  AssertDimensions( width, height );
391  this._width = width;
392  this._height = height;
393  this.InitTexture += CreateNewTexture;
394  }
395 
396  internal Image( string assetName )
397  {
398  this.assetName = assetName;
399  this.InitDimensions += LoadContentTexture;
400  }
401 
402  [EditorBrowsable( EditorBrowsableState.Never )]
403  public Image( Microsoft.Xna.Framework.Graphics.Texture2D texture )
404  {
405  AssertDimensions( texture.Width, texture.Height );
406  this.xnaTexture = texture;
407  this._width = texture.Width;
408  this._height = texture.Height;
409  }
410 
417  public Image( int width, int height, Color backColor )
418  {
419  AssertDimensions( width, height );
420  assetName = null;
421  this._width = width;
422  this._height = height;
423  this.InitTexture += CreateNewTexture;
424  this.InitTexture += delegate { this.Fill( backColor ); };
425  }
426 
433  public Image( double width, double height, Color backColor )
434  : this( (int)Math.Round( width ), (int)Math.Round( height ), backColor )
435  {
436  }
437 
438  private void AssertDimensions(int width, int height)
439  {
440  if ( width < 1 || height < 1 )
441  throw new ArgumentException( String.Format( "Image dimensions must be at least 1 x 1! (given: {0} x {1}", width, height ) );
442  }
443 
444  private void DoInitDimensions()
445  {
446  if ( _width > 0 && _height > 0 )
447  return;
448 
449  if ( InitDimensions != null )
450  InitDimensions();
451  else
452  throw new InvalidOperationException( "Cannot initialize dimensions for image!" );
453  }
454 
455  private void DoInitTexture()
456  {
458  AssertDimensions( this.Width, this.Height );
459 
460  if ( xnaTexture != null )
461  return;
462 
463  if ( InitTexture != null )
464  InitTexture();
465  else
466  throw new InvalidOperationException( "Cannot initialize texture for image!" );
467  }
468 
469  private void LoadContentTexture()
470  {
471  // Some duct tape around the fact that in XNA,
472  // content can not be loaded before LoadContent().
473  Debug.Assert( assetName != null );
475  _width = xnaTexture.Width;
476  _height = xnaTexture.Height;
477 
478  }
479  // TODO: Why is this path not used???
480  private Texture2D LoadFile(string path)
481  {
483  FileStream fileStream = new FileStream(assetName, FileMode.Open);
484  Texture2D texture = Texture2D.FromStream(Game.GraphicsDevice, fileStream);
485  fileStream.Dispose();
486 
487  return texture;
488  }
489 
490  private void CreateNewTexture()
491  {
492  this.xnaTexture = new Texture2D( Game.GraphicsDevice, Width, Height );
493  }
494 
495  public Image Clone()
496  {
497  Image copy;
498 
499  if ( assetName != null )
500  {
501  copy = new Image( assetName );
502  }
503  else
504  {
505  copy = new Image( this.Width, this.Height );
506  copy.InitTexture += delegate { CopyData( copy, this ); };
507  }
508 
509  return copy;
510  }
511 
512  private static void CopyData( Image dest, Image src )
513  {
514  src.DoInitTexture();
515 
516  int w = src.Width;
517  int h = src.Height;
518  XnaRectangle rect = new XnaRectangle( 0, 0, w, 1 );
519  Color[] scanline = new Color[w];
520 
521  for ( rect.Y = 0; rect.Y < h; rect.Y++ )
522  {
523  src.xnaTexture.GetData<Color>( 0, rect, scanline, 0, w );
524  dest.xnaTexture.SetData<Color>( 0, rect, scanline, 0, w );
525  }
526  }
527 
528  private static void CopyData( Texture2D dest, Texture2D src )
529  {
530  int w = src.Width;
531  int h = src.Height;
532  XnaRectangle rect = new XnaRectangle( 0, 0, w, 1 );
533  Color[] scanline = new Color[w];
534 
535  for ( rect.Y = 0; rect.Y < h; rect.Y++ )
536  {
537  src.GetData<Color>( 0, rect, scanline, 0, w );
538  dest.SetData<Color>( 0, rect, scanline, 0, w );
539  }
540  }
541 
542  private static void CopyData( Image dest, Image src, XnaRectangle destRect, XnaRectangle srcRect )
543  {
544  src.DoInitTexture();
545 
546  int w = srcRect.Width;
547  int h = srcRect.Height;
548  XnaRectangle srcScan = new XnaRectangle( srcRect.X, srcRect.Y, w, 1 );
549  XnaRectangle destScan = new XnaRectangle( destRect.X, destRect.Y, w, 1 );
550  Color[] scanline = new Color[w];
551 
552  for ( int i = 0; i < h; i++ )
553  {
554  src.xnaTexture.GetData<Color>( 0, srcScan, scanline, 0, w );
555  dest.xnaTexture.SetData<Color>( 0, destScan, scanline, 0, w );
556  srcScan.Y += MONOGETDATAINC;
557  destScan.Y += MONOGETDATAINC;
558  }
559  }
560 
565  public void ApplyPixelOperation( ColorConverter operation )
566  {
567  XnaColorConverter newOp = delegate( XnaColor c )
568  {
569  return operation( new Color( c ) ).AsXnaColor();
570  };
571 
572  ApplyPixelOperation( newOp );
573  }
574 
579  internal void ApplyPixelOperation( XnaColorConverter operation )
580  {
581  DoInitTexture();
582  InvalidateAsset();
583 
584  XnaRectangle scanRect = new XnaRectangle( 0, 0, xnaTexture.Width, 1 );
585  XnaColor[] scanline = new XnaColor[xnaTexture.Width];
586 
587  for ( scanRect.Y = 0; scanRect.Y < xnaTexture.Height; scanRect.Y++ )
588  {
589  xnaTexture.GetData<XnaColor>( 0, scanRect, scanline, 0, xnaTexture.Width );
590 
591  for ( int j = 0; j < xnaTexture.Width; j++ )
592  {
593  scanline[j] = operation( scanline[j] );
594  }
595 
596  xnaTexture.SetData<XnaColor>( 0, scanRect, scanline, 0, xnaTexture.Width );
597  }
598 
599  UpdateTexture();
600  }
601 
607  private void InvalidateAsset()
608  {
609  if ( assetName == null )
610  return;
611 
612  Texture2D oldTex = xnaTexture;
614  CopyData( xnaTexture, oldTex );
615  assetName = null;
616  }
617 
618  private void UpdateTexture()
619  {
621  }
622 
623  private void DoUpdateTexture()
624  {
625  if ( parentImage != null )
626  {
627  XnaRectangle srcRect = new XnaRectangle( 0, 0, Width, Height );
628  CopyData( parentImage, this, parentRectangle, srcRect );
630  }
631  }
632 
633  #region static methods
634 
635 #if !WINDOWS_STOREAPP
636  public static Image FromFile( string path )
642  {
643  StreamReader sr = new StreamReader( path );
644  Image img = new Image( Texture2D.FromStream( Game.GraphicsDevice, sr.BaseStream ) );
645  return img;
646  }
647 #endif
648 
654  //public static Image FromFile( StorageFile file )
655  //{
656  // return FromStream( file.Stream );
657  //}
658 
664  public static Image FromStream( Stream stream )
665  {
666  return new Image( Texture2D.FromStream( Game.GraphicsDevice, stream ) );
667  }
668 
669 #if WINDOWS
670  public static Image FromURL( string url )
676  {
677  HttpWebRequest request = (HttpWebRequest)WebRequest.Create( url );
678  HttpWebResponse response = (HttpWebResponse)request.GetResponse();
679  Stream resStream = response.GetResponseStream();
680 
681  MemoryStream memStream = new MemoryStream();
682  resStream.CopyTo( memStream );
683 
684  Image img = new Image( Texture2D.FromStream( Game.GraphicsDevice, memStream ) );
685  return img;
686  }
687 #endif
688 
697  public static Image CreateStarSky( int width, int height, int stars, bool transparent = false)
698  {
699  XnaColor[] textureColors = new XnaColor[width * height];
700 
701  // Background, black or transparent
702  int i = 0;
703  for ( int ver = 0; ver < height; ver++ )
704  {
705  for ( int hor = 0; hor < width; hor++ )
706  {
707  if (transparent) textureColors[i++] = XnaColor.Transparent;
708  else textureColors[i++] = XnaColor.Black;
709  }
710  }
711 
712  // Random stars
713  for ( int j = 0; j < stars; j++ )
714  {
715  int star = RandomGen.NextInt( 0, width * height );
716  int size = RandomGen.NextInt( 1, 5 );
717 
718  for ( int k = 0; k < size / 2; k++ )
719  {
720  XnaColor starcolor = RandomGen.NextColor( Jypeli.Color.White, new Color( 192, 192, 192, 255 ) ).AsXnaColor();
721 
722  if ( star + k < textureColors.Length )
723  textureColors[star + k] = starcolor;
724 
725  if ( size % 2 != 0 || size == 2 )
726  continue;
727 
728  int nextStar = star + k + width;
729 
730  if ( nextStar < ( width * height ) )
731  {
732  textureColors[nextStar] = starcolor;
733  }
734  }
735  }
736 
737  //Texture2D newTexture = new Texture2D( Game.GraphicsDevice, width, height, 1, TextureUsage.None, SurfaceFormat.Color );
738  Texture2D newTexture = new Texture2D( Game.GraphicsDevice, width, height, false, SurfaceFormat.Color );
739  newTexture.SetData<XnaColor>( textureColors );
740 
741  return new Image( newTexture );
742  }
743 
752  public static Image FromText( string text, Font font, Color textColor, Color backgroundColor )
753  {
754  if ( text == null )
755  text = "";
756 
757  var spriteBatch = new SpriteBatch( Game.GraphicsDevice );
758  var device = spriteBatch.GraphicsDevice;
759 
760  XnaV2 textDims = font.XnaFont.MeasureString( text );
761  int textw = ( textDims.X > 1 ) ? Convert.ToInt32( textDims.X ) : 1;
762  int texth = ( textDims.Y > 1 ) ? Convert.ToInt32( textDims.Y ) : 1;
763 
764  //RenderTarget2D rt = new RenderTarget2D( device, textw, texth, 1, device.DisplayMode.Format );
765  RenderTarget2D rt = new RenderTarget2D( device, textw, texth, false, SurfaceFormat.Color, DepthFormat.Depth24Stencil8 );
766 
767  //device.SetRenderTarget( 0, rt );
768  device.SetRenderTarget( rt );
769  device.Clear( ClearOptions.Target | ClearOptions.DepthBuffer, backgroundColor.AsXnaColor(), 1.0f, 0 );
770 
771  spriteBatch.Begin();
772  spriteBatch.DrawString( font.XnaFont, text, XnaV2.Zero, textColor.AsXnaColor() );
773  spriteBatch.End();
774 
775  //device.SetRenderTarget( 0, null );
776  device.SetRenderTarget( null );
777 
778  //return new Image( rt.GetTexture() );
779  return new Image( rt );
780  }
781 
792  public static Image DrawTextOnImage( Image img, string text, Vector position, Font font, Color textColor, Color backgroundColor )
793  {
794  if ( text == null )
795  text = "";
796 
797  var spriteBatch = new SpriteBatch( Game.GraphicsDevice );
798  var device = spriteBatch.GraphicsDevice;
799 
800  XnaV2 textDims = font.XnaFont.MeasureString( text );
801  int textw = ( textDims.X > 1 ) ? Convert.ToInt32( textDims.X ) : 1;
802  int texth = ( textDims.Y > 1 ) ? Convert.ToInt32( textDims.Y ) : 1;
803 
804  //RenderTarget2D rt = new RenderTarget2D( device, textw, texth, 1, device.DisplayMode.Format );
805  RenderTarget2D rt = new RenderTarget2D( device, img.Width, img.Height, false, SurfaceFormat.Color, DepthFormat.Depth24Stencil8 );
806 
807  //device.SetRenderTarget( 0, rt );
808  device.SetRenderTarget( rt );
809  device.Clear( ClearOptions.Target | ClearOptions.DepthBuffer, backgroundColor.AsXnaColor(), 1.0f, 0 );
810 
811  float xpos = 0.5f * ( img.Width - textw ) + (float)position.X;
812  float ypos = 0.5f * ( img.Height - texth ) - (float)position.Y;
813 
814  spriteBatch.Begin();
815  spriteBatch.Draw( img.XNATexture, rt.Bounds, XnaColor.White );
816  spriteBatch.DrawString( font.XnaFont, text, new XnaV2( xpos, ypos ), textColor.AsXnaColor() );
817  spriteBatch.End();
818 
819  //device.SetRenderTarget( 0, null );
820  device.SetRenderTarget( null );
821 
822 
823  //return new Image( rt.GetTexture() );
824  return new Image( rt );
825  }
826 
835  public static Image DrawTextOnImage( Image img, string text, Font font, Color textColor )
836  {
837  return DrawTextOnImage( img, text, Vector.Zero, font, textColor, Jypeli.Color.Transparent );
838  }
839 
848  public static Image FromGradient( int imageWidth, int imageHeight, Color lowerColor, Color upperColor )
849  {
850  XnaColor lower = lowerColor.AsXnaColor();
851  XnaColor upper = upperColor.AsXnaColor();
852  XnaColor[] textureColors = new XnaColor[imageWidth * imageHeight];
853  int i = 0;
854 
855  for ( int ver = 0; ver < imageHeight; ver++ )
856  {
857  for ( int hor = 0; hor < imageWidth; hor++ )
858  {
859  textureColors[i++] = XnaColor.Lerp( upper, lower, ( (float)ver / (float)imageHeight ) );
860  }
861  }
862 
863  Texture2D newTexture = new Texture2D( Game.GraphicsDevice, imageWidth, imageHeight, false, SurfaceFormat.Color );
864  newTexture.SetData<XnaColor>( textureColors );
865  return new Image( newTexture );
866  }
867 
875  public static Image FromColor( int imageWidth, int imageHeight, Color color )
876  {
877  return Image.FromGradient( imageWidth, imageHeight, color, color );
878  }
879 
880  private static XnaColor[] MirrorLine( XnaColor[] scanline, int width )
881  {
882  XnaColor[] res = new XnaColor[width];
883  int l = 0;
884  int r = width - 1;
885 
886  while ( l < r )
887  {
888  res[l] = scanline[r];
889  res[r] = scanline[l];
890  l++; r--;
891  }
892 
893  if ( l == r )
894  {
895  // Center pixel
896  res[l] = scanline[l];
897  }
898 
899  return res;
900  }
901 
907  public static Image Mirror( Image image )
908  {
909  Texture2D newTex = new Texture2D( image.XNATexture.GraphicsDevice, image.Width, image.Height, false, image.XNATexture.Format );
910  XnaColor[] scanline = new XnaColor[image.Width];
911  var scanRect = new XnaRectangle( 0, 0, image.Width, 1 );
912 
913  for ( scanRect.Y = 0; scanRect.Y < image.Height; scanRect.Y++ )
914  {
915  image.XNATexture.GetData<XnaColor>( 0, scanRect, scanline, 0, image.Width );
916  scanline = MirrorLine( scanline, image.Width );
917  newTex.SetData<XnaColor>( 0, scanRect, scanline, 0, image.Width );
918  }
919 
920  return new Image( newTex );
921  }
922 
928  public static Image[] Mirror( Image[] images )
929  {
930  Image[] result = new Image[images.Length];
931  for ( int i = 0; i < images.Length; i++ )
932  result[i] = Mirror( images[i] );
933  return result;
934  }
935 
941  public static Image Flip( Image image )
942  {
943  Texture2D newTex = new Texture2D( image.XNATexture.GraphicsDevice, image.Width, image.Height, false, image.XNATexture.Format );
944  XnaColor[] scanlineUpper = new XnaColor[image.Width];
945  XnaColor[] scanlineLower = new XnaColor[image.Width];
946  var scanRectUpper = new XnaRectangle( 0, 0, image.Width, 1 );
947  var scanRectLower = new XnaRectangle( 0, 0, image.Width, 1 );
948 
949  for ( int i = 0; i < image.Height / 2; i++ )
950  {
951  scanRectUpper.Y = i;
952  scanRectLower.Y = image.Height - 1 - i;
953 
954  image.XNATexture.GetData<XnaColor>( 0, scanRectUpper, scanlineUpper, 0, image.Width );
955  image.XNATexture.GetData<XnaColor>( 0, scanRectLower, scanlineLower, 0, image.Width );
956 
957  newTex.SetData<XnaColor>( 0, scanRectUpper, scanlineLower, 0, image.Width );
958  newTex.SetData<XnaColor>( 0, scanRectLower, scanlineUpper, 0, image.Width );
959  }
960 
961  if ( image.Height % 2 == 1 )
962  {
963  // Center line
964  scanRectUpper.Y = image.Height / 2;
965  image.XNATexture.GetData<XnaColor>( 0, scanRectUpper, scanlineUpper, 0, image.Width );
966  newTex.SetData<XnaColor>( 0, scanRectUpper, scanlineUpper, 0, image.Width );
967  }
968 
969  return new Image( newTex );
970  }
971 
977  public static Image[] Flip( Image[] images )
978  {
979  Image[] result = new Image[images.Length];
980  for ( int i = 0; i < images.Length; i++ )
981  result[i] = Flip( images[i] );
982  return result;
983  }
984 
991  public static Image Color( Image image, Color color )
992  {
993  Texture2D newTex = new Texture2D( image.XNATexture.GraphicsDevice, image.Width, image.Height, false, image.XNATexture.Format );
994  XnaColor[] scanline = new XnaColor[image.Width];
995  var scanRect = new XnaRectangle( 0, 0, image.Width, 1 );
996  XnaColor xnaColor = color.AsXnaColor();
997 
998  for ( scanRect.Y = 0; scanRect.Y < image.Height; scanRect.Y++ )
999  {
1000  image.XNATexture.GetData<XnaColor>( 0, scanRect, scanline, 0, image.Width );
1001 
1002  for ( int i = 0; i < image.Width; i++ )
1003  {
1004  if ( scanline[i].A < 255 )
1005  {
1006  scanline[i].R = (byte)( ( 255 - scanline[i].A ) * xnaColor.R + scanline[i].A * scanline[i].R );
1007  scanline[i].G = (byte)( ( 255 - scanline[i].A ) * xnaColor.G + scanline[i].A * scanline[i].G );
1008  scanline[i].B = (byte)( ( 255 - scanline[i].A ) * xnaColor.B + scanline[i].A * scanline[i].B );
1009 
1010  if ( scanline[i].A > 10 )
1011  {
1012  scanline[i].A = color.AlphaComponent;
1013  }
1014  }
1015  }
1016 
1017  newTex.SetData<XnaColor>( 0, scanRect, scanline, 0, image.Width );
1018  }
1019 
1020  return new Image( newTex );
1021  }
1022 
1029  public static Image[] Color( Image[] images, Color color )
1030  {
1031  Image[] result = new Image[images.Length];
1032  for ( int i = 0; i < images.Length; i++ )
1033  result[i] = Color( images[i], color );
1034  return result;
1035  }
1036 
1037  public static Image Color( Image image, byte alpha )
1038  {
1039  Texture2D newTex = new Texture2D( image.XNATexture.GraphicsDevice, image.Width, image.Height, false, image.XNATexture.Format );
1040  XnaColor[] scanline = new XnaColor[image.Width];
1041  var scanRect = new XnaRectangle( 0, 0, image.Width, 1 );
1042 
1043  for ( scanRect.Y = 0; scanRect.Y < image.Height; scanRect.Y++ )
1044  {
1045  image.XNATexture.GetData<XnaColor>( 0, scanRect, scanline, 0, image.Width );
1046  for ( int i = 0; i < image.Width; i++ )
1047  {
1048  scanline[i].A = alpha;
1049  }
1050  newTex.SetData<XnaColor>( 0, scanRect, scanline, 0, image.Width );
1051  }
1052  return new Image( newTex );
1053  }
1054 
1055  public static Image TileHorizontal( Image left, Image right )
1056  {
1057  if ( left.Height != right.Height ) throw new InvalidOperationException( "Cannot tile two images with different height" );
1058 
1059  left.DoInitTexture();
1060  right.DoInitTexture();
1061 
1062  XnaRectangle leftRect = new XnaRectangle( 0, 0, left.Width, left.Height );
1063  XnaRectangle rightSrc = new XnaRectangle( 0, 0, right.Width, right.Height );
1064  XnaRectangle rightDest = new XnaRectangle( left.Width, 0, right.Width, right.Height );
1065 
1066  Image tiled = new Image( left.Width + right.Width, left.Height );
1067  tiled.InitTexture += delegate { CopyData( tiled, left, leftRect, leftRect ); };
1068  tiled.InitTexture += delegate { CopyData( tiled, right, rightDest, rightSrc ); };
1069 
1070  return tiled;
1071  }
1072 
1073  public static Image TileVertical( Image top, Image bottom )
1074  {
1075  if ( top.Width != bottom.Width ) throw new InvalidOperationException( "Cannot tile two images with different width" );
1076 
1077  top.DoInitTexture();
1078  bottom.DoInitTexture();
1079 
1080  XnaRectangle topRect = new XnaRectangle( 0, 0, top.Width, top.Height );
1081  XnaRectangle botSrc = new XnaRectangle( 0, 0, bottom.Width, bottom.Height );
1082  XnaRectangle botDest = new XnaRectangle( 0, top.Height, bottom.Width, bottom.Height );
1083 
1084  Image tiled = new Image( top.Width, top.Height + bottom.Height );
1085  tiled.InitTexture += delegate { CopyData( tiled, top, topRect, topRect ); };
1086  tiled.InitTexture += delegate { CopyData( tiled, bottom, botDest, botSrc ); };
1087 
1088  return tiled;
1089  }
1090 
1091  #endregion
1092 
1093  public Image Area( int left, int top, int right, int bottom )
1094  {
1095  int width = right - left;
1096  int height = bottom - top;
1097 
1098  if ( width <= 0 ) throw new ArgumentException( "Left coordinate must be less than right coordinate" );
1099  if ( height <= 0 ) throw new ArgumentException( "Top coordinate must be less than bottom coordinate" );
1100 
1101  XnaRectangle srcRect = new XnaRectangle( left, top, width, height );
1102  XnaRectangle destRect = new XnaRectangle( 0, 0, width, height );
1103 
1104  Image areaImage = new Image( width, height );
1105  areaImage.parentImage = this;
1106  areaImage.parentRectangle = srcRect;
1107  areaImage.InitTexture += delegate { CopyData( areaImage, this, destRect, srcRect ); };
1108  return areaImage;
1109  }
1110 
1111  public void Fill( Color backColor )
1112  {
1113  DoInitTexture();
1114  InvalidateAsset();
1115 
1116  XnaRectangle rect = new XnaRectangle( 0, 0, xnaTexture.Width, 1 );
1117  Color[] scanline = new Color[xnaTexture.Width];
1118 
1119  for ( int i = 0; i < xnaTexture.Width; i++ )
1120  scanline[i] = backColor;
1121 
1122  for ( rect.Y = 0; rect.Y < xnaTexture.Height; rect.Y++ )
1123  xnaTexture.SetData<Color>( 0, rect, scanline, 0, xnaTexture.Width );
1124 
1125  UpdateTexture();
1126  }
1127 
1136  public void ReplaceColor( Color src, Color dest, double tolerance, bool blend, bool exactAlpha = false )
1137  {
1138  XnaColor srcColor = src.AsXnaColor();
1139  XnaColor destColor = dest.AsXnaColor();
1140  XnaColorConverter op = delegate( XnaColor c )
1141  {
1142  if ( exactAlpha && c.A != srcColor.A )
1143  return c;
1144 
1145  if ( JyColor.Distance( c, srcColor ) <= tolerance )
1146  {
1147  if ( !blend ) return destColor;
1148  Vector3 srcDist = new Vector3( c.R - srcColor.R, c.G - srcColor.G, c.B - srcColor.B );
1149  return new XnaColor( destColor.ToVector3() + srcDist );
1150  }
1151 
1152  return c;
1153  };
1154 
1155  ApplyPixelOperation( op );
1156  }
1157 
1163  public void ReplaceColor( Color src, Color dest )
1164  {
1165  XnaColor srcColor = src.AsXnaColor();
1166  XnaColor destColor = dest.AsXnaColor();
1167  XnaColorConverter op = delegate( XnaColor c )
1168  {
1169  return c == srcColor ? destColor : c;
1170  };
1171 
1172  ApplyPixelOperation( op );
1173  }
1174 
1180  public Stream AsJpeg()
1181  {
1182  DoInitTexture();
1183  MemoryStream jpegStream = new MemoryStream();
1184  XNATexture.SaveAsJpeg( jpegStream, Width, Height );
1185  jpegStream.Seek( 0, SeekOrigin.Begin );
1186  return jpegStream;
1187  }
1188 
1194  public Stream AsPng()
1195  {
1196  DoInitTexture();
1197  MemoryStream pngStream = new MemoryStream();
1198  XNATexture.SaveAsPng( pngStream, Width, Height );
1199  pngStream.Seek( 0, SeekOrigin.Begin );
1200  return pngStream;
1201  }
1202  }
1203 }
1204 
Jypeli.Image.Area
Image Area(int left, int top, int right, int bottom)
Definition: Image.cs:1093
Jypeli.XnaV2
Microsoft.Xna.Framework.Vector2 XnaV2
Definition: Mouse.cs:37
Jypeli.Image.FromColor
static Image FromColor(int imageWidth, int imageHeight, Color color)
Luo yksivärisen kuvan.
Definition: Image.cs:875
Jypeli.Image.Mirror
static Image[] Mirror(Image[] images)
Peilaa kuvat X-suunnassa.
Definition: Image.cs:928
Jypeli.Image.DrawTextOnImage
static Image DrawTextOnImage(Image img, string text, Vector position, Font font, Color textColor, Color backgroundColor)
Piirtää tekstiä kuvan päälle.
Definition: Image.cs:792
Jypeli.Image._width
int _width
Definition: Image.cs:45
Jypeli.Image.CreateNewTexture
void CreateNewTexture()
Definition: Image.cs:490
Jypeli.Image.SetData
void SetData(uint[][] bmp, int ox=0, int oy=0, int w=int.MaxValue, int h=int.MaxValue)
Asetetaan kuvan pikselit ARGB-uint taulukosta
Definition: Image.cs:339
Jypeli.Image.DoInitDimensions
void DoInitDimensions()
Definition: Image.cs:444
Jypeli.Image.InitDimensions
Action InitDimensions
Definition: Image.cs:42
Microsoft.Xna
Definition: JypeliContentManager.cs:6
Jypeli.Image.Image
Image(int width, int height)
Definition: Image.cs:388
Jypeli.Image.CreateStarSky
static Image CreateStarSky(int width, int height, int stars, bool transparent=false)
Luo tähtitaivaskuvan.
Definition: Image.cs:697
Jypeli.Image.LoadContentTexture
void LoadContentTexture()
Definition: Image.cs:469
Jypeli.Image.FromGradient
static Image FromGradient(int imageWidth, int imageHeight, Color lowerColor, Color upperColor)
Luo pystysuuntaisen liukuväritetyn kuvan.
Definition: Image.cs:848
Jypeli.Image.DrawTextOnImage
static Image DrawTextOnImage(Image img, string text, Font font, Color textColor)
Piirtää tekstiä kuvan päälle keskelle kuvaa.
Definition: Image.cs:835
Jypeli.Vector.X
double X
Definition: Vector.cs:312
Jypeli.Image.FromText
static Image FromText(string text, Font font, Color textColor, Color backgroundColor)
Luo kuvan tekstistä.
Definition: Image.cs:752
Jypeli.Vector.Zero
static readonly Vector Zero
Nollavektori.
Definition: Vector.cs:63
Jypeli.Image.Image
Image(string assetName)
Definition: Image.cs:396
XnaColor
Microsoft.Xna.Framework.Color XnaColor
Definition: Image.cs:11
Jypeli.Image.SetData
void SetData(byte[] byteArr)
Asettaa kuvan pikselit annetun tavutaulukon mukaan.
Definition: Image.cs:205
Jypeli.Image.parentRectangle
XnaRectangle parentRectangle
Definition: Image.cs:37
Jypeli
Definition: Automobile.cs:5
JyColor
Jypeli.Color JyColor
Definition: Image.cs:12
Jypeli.Image.InitTexture
Action InitTexture
Definition: Image.cs:43
Jypeli.Image.InvalidateAsset
void InvalidateAsset()
Tekee uuden lokaalin instanssin kuvan tekstuurista ja poistaa viitteen assettiin josta kuva on luotu....
Definition: Image.cs:607
Jypeli.Image.xnaTexture
Texture2D xnaTexture
Definition: Image.cs:40
Microsoft
Definition: JypeliContentManager.cs:6
Microsoft.Xna.Framework
Definition: JypeliContentManager.cs:6
Jypeli.Image.parentImage
Image parentImage
Definition: Image.cs:36
Jypeli.Image.AsPng
Stream AsPng()
Palauttaa kuvan png-muodossa, jossa se voidaan esimerkiksi tallentaa DataStorage.Export -metodilla.
Definition: Image.cs:1194
XnaRectangle
Microsoft.Xna.Framework.Rectangle XnaRectangle
Definition: Image.cs:9
Jypeli.Color.AlphaComponent
byte AlphaComponent
Läpinäkymättömyys välillä 0-255
Definition: Color.cs:36
Jypeli.Image.Color
static Image Color(Image image, Color color)
Värittää kuvan.
Definition: Image.cs:991
Jypeli.Color.UIntToColor
static Color UIntToColor(uint c)
Tekee kokonaisluvusta värin
Definition: Color.cs:262
Jypeli.Font.XnaFont
SpriteFont XnaFont
Definition: Font.cs:90
Jypeli.Image.GetByteArray
byte[] GetByteArray()
Kuvan pikselit byte-taulukkona. Tavut ovat järjestyksessä punainen, vihreä, sininen,...
Definition: Image.cs:215
Jypeli.Game.FileExtensionCheck
static string FileExtensionCheck(string file, string[] extensions)
Etsii millä päätteellä annettu tiedosto löytyy
Definition: Content.cs:195
Jypeli.Image.Flip
static Image Flip(Image image)
Peilaa kuvan Y-suunnassa.
Definition: Image.cs:941
Jypeli.Image._height
int _height
Definition: Image.cs:46
Jypeli.Image.Height
int Height
Korkeus pikseleinä.
Definition: Image.cs:376
ColorConverter
System.Converter< Jypeli.Color, Jypeli.Color > ColorConverter
Definition: Image.cs:18
Jypeli.Image.AssertDimensions
void AssertDimensions(int width, int height)
Definition: Image.cs:438
Jypeli.Game.DoNextUpdate
static void DoNextUpdate(Action action)
Suorittaa aliohjelman seuraavalla päivityksellä.
Definition: DelayedActions.cs:65
Jypeli.Image.XNATexture
Texture2D XNATexture
Definition: Image.cs:71
Jypeli.Image.Color
static Image Color(Image image, byte alpha)
Definition: Image.cs:1037
XnaColor
Microsoft.Xna.Framework.Color XnaColor
Definition: VirtualKeyboard.cs:11
Jypeli.Image.FromFile
static Image FromFile(string path)
Lataa kuvan tiedostosta. Kuvan ei tarvitse olla lisättynä Content-projektiin.
Definition: Image.cs:641
Jypeli.Image.DoUpdateTexture
void DoUpdateTexture()
Definition: Image.cs:623
XnaColorConverter
System.Converter< Microsoft.Xna.Framework.Color, Microsoft.Xna.Framework.Color > XnaColorConverter
Definition: Image.cs:19
Jypeli.RandomGen
Satunnaisgeneraattori. Luo satunnaisia arvoja, mm. lukuja, vektoreita sekä kulmia.
Definition: RandomGen.cs:39
Jypeli.Image.Color
static Image[] Color(Image[] images, Color color)
Värittää kuvat.
Definition: Image.cs:1029
Jypeli.Image.SetData
void SetData(Color[,] bmp, int ox=0, int oy=0, int w=int.MaxValue, int h=int.MaxValue)
Asettaa kuvan pikselit Color-taulukosta
Definition: Image.cs:147
Jypeli.Image.MONOGETDATAINC
static int MONOGETDATAINC
Definition: Image.cs:32
Jypeli.Color.Transparent
static readonly Color Transparent
Läpinäkyvä väri.
Definition: Color.cs:878
Jypeli.Image.LoadFile
Texture2D LoadFile(string path)
Definition: Image.cs:480
Jypeli.Image.DoInitTexture
void DoInitTexture()
Definition: Image.cs:455
Jypeli.ListHelpers
Apufunktioita listojen ja muiden tietorakenteiden käyttöön.
Definition: ListHelpers.cs:11
Jypeli.Image.Clone
Image Clone()
Definition: Image.cs:495
Jypeli.Image.ApplyPixelOperation
void ApplyPixelOperation(ColorConverter operation)
Suorittaa annetun pikselioperaation koko kuvalle.
Definition: Image.cs:565
Jypeli.Image.TileVertical
static Image TileVertical(Image top, Image bottom)
Definition: Image.cs:1073
Jypeli.Image.Width
int Width
Leveys pikseleinä.
Definition: Image.cs:368
Jypeli.Image.CopyData
static void CopyData(Texture2D dest, Texture2D src)
Definition: Image.cs:528
Jypeli.Image.ReplaceColor
void ReplaceColor(Color src, Color dest, double tolerance, bool blend, bool exactAlpha=false)
Korvaa värin toisella värillä.
Definition: Image.cs:1136
Jypeli.Image.Image
Image(double width, double height, Color backColor)
Luo uuden kuvan.
Definition: Image.cs:433
Jypeli.RandomGen.NextColor
static Color NextColor()
Palauttaa satunnaisen värin.
Definition: RandomGen.cs:154
Jypeli.RandomGen.NextInt
static int NextInt(int maxValue)
Palauttaa satunnaisen kokonaisluvun, joka on vähintään 0 ja pienempi kuin
Definition: RandomGen.cs:54
Jypeli.Image.assetName
string assetName
Definition: Image.cs:39
Jypeli.Color
Väri.
Definition: Color.cs:13
Jypeli.Image.imageExtensions
static string[] imageExtensions
Definition: Image.cs:48
Jypeli.Image.GetDataUIntAA
uint[][] GetDataUIntAA(int ox=0, int oy=0, int w=int.MaxValue, int h=int.MaxValue)
Palalutetaan kuvan pikselit ARGB-uint[][] -taulukkona
Definition: Image.cs:266
Jypeli.Image.Flip
static Image[] Flip(Image[] images)
Peilaa kuvat Y-suunnassa.
Definition: Image.cs:977
Jypeli.Image.ApplyPixelOperation
void ApplyPixelOperation(XnaColorConverter operation)
Suorittaa annetun pikselioperaation koko kuvalle.
Definition: Image.cs:579
Jypeli.Image.AsJpeg
Stream AsJpeg()
Palauttaa kuvan jpeg-muodossa, jossa se voidaan esimerkiksi tallentaa DataStorage....
Definition: Image.cs:1180
Jypeli.Image.GetDataUInt
uint[,] GetDataUInt(int ox=0, int oy=0, int w=int.MaxValue, int h=int.MaxValue)
Palalutetaan kuvan pikselit ARGB-uint[,] -taulukkona
Definition: Image.cs:231
Jypeli.Image
Kuva.
Definition: Image.cs:29
Jypeli.Vector
2D-vektori.
Definition: Vector.cs:59
System
Definition: CFFauxAttributes.cs:29
Jypeli.Image.Name
string Name
Nimi.
Definition: Image.cs:384
Jypeli.Image.UpdateTexture
void UpdateTexture()
Definition: Image.cs:618
Jypeli.Image.CopyData
static void CopyData(Image dest, Image src)
Definition: Image.cs:512
Jypeli.Image.ReplaceColor
void ReplaceColor(Color src, Color dest)
Korvaa värin toisella värillä.
Definition: Image.cs:1163
Jypeli.Image.FromStream
static Image FromStream(Stream stream)
Lataa kuvan tiedostovirrasta.
Definition: Image.cs:664
Jypeli.Image.TileHorizontal
static Image TileHorizontal(Image left, Image right)
Definition: Image.cs:1055
Jypeli.Image.GetData
Color[,] GetData(int ox=0, int oy=0, int w=int.MaxValue, int h=int.MaxValue)
Kuvan pikselit Color-taulukkona
Definition: Image.cs:111
Jypeli.Font
Fontti.
Definition: Font.cs:23
Jypeli.Game.GraphicsDevice
static new GraphicsDevice GraphicsDevice
XNA:n grafiikkakortti.
Definition: Graphics.cs:49
Jypeli.Color.White
static readonly Color White
Valkoinen.
Definition: Color.cs:903
Jypeli.Image.Image
Image(int width, int height, Color backColor)
Luo uuden kuvan.
Definition: Image.cs:417
Jypeli.Image.SetData
void SetData(byte[] byteArr, int height, int width)
Asettaa kuvan pikselit annetun tavutaulukon mukaan.
Definition: Image.cs:181
Jypeli.Image.Mirror
static Image Mirror(Image image)
Peilaa kuvan X-suunnassa.
Definition: Image.cs:907
Jypeli.Game
Definition: Content.cs:46
Jypeli.Image.Fill
void Fill(Color backColor)
Definition: Image.cs:1111
Jypeli.Image.SetData
void SetData(uint[,] bmp, int ox=0, int oy=0, int w=int.MaxValue, int h=int.MaxValue)
Asetetaan kuvan pikselit ARGB-uint taulukosta
Definition: Image.cs:303
Jypeli.Color.AsXnaColor
XnaColor AsXnaColor()
Definition: Color.cs:46
Jypeli.Image.SetLineCorrection
static void SetLineCorrection(int n)
Asetetaan bitmapin rivikorjaus Mono:n bugin (???) takia
Definition: Image.cs:54
Jypeli.Image.MirrorLine
static XnaColor[] MirrorLine(XnaColor[] scanline, int width)
Definition: Image.cs:880
XnaV2
Microsoft.Xna.Framework.Vector2 XnaV2
Definition: Font.cs:4
Jypeli.Vector.Y
double Y
Definition: Vector.cs:313
Jypeli.Image.MONOGETDATAMUL
static int MONOGETDATAMUL
Definition: Image.cs:31
Jypeli.Image.Image
Image(Microsoft.Xna.Framework.Graphics.Texture2D texture)
Definition: Image.cs:403
Jypeli.Image.CopyData
static void CopyData(Image dest, Image src, XnaRectangle destRect, XnaRectangle srcRect)
Definition: Image.cs:542
XnaRectangle
Microsoft.Xna.Framework.Rectangle XnaRectangle
Definition: VirtualKeyboard.cs:10