当前位置:   article > 正文

Bitmap & Texture2D 互转方法搜集_bitmap 转 texture2d

bitmap 转 texture2d

最近学习emgucv,我在写读摄像头的程序然后需要bitmap 转texture2D 其实可以直接使用setdata<bytes>的方法赋值,感觉帧率不是一般的低,是无法忍受的。

也试了多种方法,基本上都是无法忍受的。可能有人会用得到,将搜集的列下来。

这是一些方法的搜集。

Texture2D toBitmap 的方法

 

  1. public static Bitmap FastTextureToBitmap(Texture2D texture)
  2. {
  3. // Setup pointer back to bitmap
  4. Bitmap newBitmap = new Bitmap(texture.Width, texture.Height);
  5. // Get color data from the texture
  6. Microsoft.Xna.Framework.Graphics.Color[ textureColors = GetColorDataFromTexture(texture);
  7. System.Drawing.Imaging.BitmapData bmpData = newBitmap.LockBits(new System.Drawing.Rectangle(0, 0, newBitmap.Width, newBitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
  8. // Loop through pixels and set values
  9. unsafe
  10. {
  11. byte* bmpPointer = (byte*)bmpData.Scan0;
  12. for (int y = 0; y < texture.Height; y++)
  13. {
  14. for (int x = 0; x < texture.Width; x++)
  15. {
  16. bmpPointer[0] = textureColors[x + y * texture.Width].B;
  17. bmpPointer[1] = textureColors[x + y * texture.Width].G;
  18. bmpPointer[2] = textureColors[x + y * texture.Width].R;
  19. bmpPointer[3] = textureColors[x + y * texture.Width].A;
  20. bmpPointer += 4;
  21. }
  22. bmpPointer += bmpData.Stride - (bmpData.Width * 4);
  23. }
  24. }
  25. textureColors = null;
  26. newBitmap.UnlockBits(bmpData);
  27. return newBitmap;
  28. }

 

bitmap to texture2D 的方法:

  1. private Texture2D GetTexture(GraphicsDevice dev, System.Drawing.Bitmap bmp)
  2. {
  3. int[] imgData = new int[bmp.Width * bmp.Height];
  4. Texture2D texture = new Texture2D(dev, bmp.Width, bmp.Height);
  5. unsafe
  6. {
  7. // lock bitmap
  8. System.Drawing.Imaging.BitmapData origdata =
  9. bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);
  10. uint* byteData = (uint*)origdata.Scan0;
  11. // Switch bgra -> rgba
  12. for (int i = 0; i < imgData.Length; i++)
  13. {
  14. byteData[i] = (byteData[i] & 0x000000ff) << 16 | (byteData[i] & 0x0000FF00) | (byteData[i] & 0x00FF0000) >> 16 | (byteData[i] & 0xFF000000);
  15. }
  16. // copy data
  17. System.Runtime.InteropServices.Marshal.Copy(origdata.Scan0, imgData, 0, bmp.Width * bmp.Height);
  18. byteData = null;
  19. // unlock bitmap
  20. bmp.UnlockBits(origdata);
  21. }
  22. texture.SetData(imgData);
  23. return texture;
  24. }



貌似对于赋值这一步C#的效率好像不高,帧率一般都会降的很低。我还没有想到更好的办法,表示无奈中。。。 


实际上还有一个方法可以直接使用

BitmapSourceExtensions.CopyTo Method (BitmapSource, Texture2D)

此方法需要使用   System.Windows.Media.Imaging 我倒还没有尝试过。估计应该是挺好用的。
例子可以参见http://msdn.microsoft.com/en-us/library/gg712857(v=vs.96).aspx 
这种方法试过,但是不管用,自己也是新手,搞不定了。。。就扔了,有人搞懂的话,可以回个帖。~
值得一提的是对于BITMAP的格式,要值得仔细查看一下,不要直接套用上面的方法

这个是另外一种方法,试了一下貌似帧率有所提高,但依然还是不如窗体直接用的那种性能好。都准备放弃XNA了。。。
  1. 1publicstatic Texture2D BitmapToTexture2D(
  2. 2 GraphicsDevice GraphicsDevice,
  3. 3 System.Drawing.Bitmap image)
  4. 4{
  5. 5 // Buffer size is size of color array multiplied by 4 because
  6. 6// each pixel has four color bytes
  7. 7int bufferSize = image.Height * image.Width * 4;
  8. 8
  9. 9 // Create new memory stream and save image to stream so
  10. 10// we don't have to save and read file
  11. 11 System.IO.MemoryStream memoryStream =
  12. 12 new System.IO.MemoryStream(bufferSize);
  13. 13 image.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png);
  14. 14 15 // Creates a texture from IO.Stream - our memory stream
  15. 16 Texture2D texture = Texture2D.FromStream(
  16. 17 GraphicsDevice, memoryStream);
  17. 18 19return texture;
  18. 20}


我依然觉得这是个性能瓶颈。。。又搜到了国外某人发的一个类
  1. using System;
  2. using Microsoft.Xna.Framework;
  3. using Microsoft.Xna.Framework.Graphics;
  4. using System.Drawing;
  5. using System.Drawing.Imaging;
  6. using System.Runtime.InteropServices;
  7. namespace MrXNAHelper
  8. {
  9. public class ImageToTexture
  10. {
  11. byte[] bmpBytes;
  12. Texture2D background;
  13. int width, height;
  14. Game game;
  15. public ImageToTexture(Game game, int width, int height)
  16. {
  17. this.width = width;
  18. this.height = height;
  19. this.game = game;
  20. GenerateBitmap(game, width, height);
  21. }
  22. public ImageToTexture(Game game)
  23. {
  24. this.game = game;
  25. }
  26. private void GenerateBitmap(Game game, int width, int height)
  27. {
  28. background = new Texture2D(game.GraphicsDevice, width, height);
  29. }
  30. public Texture2D ConvertBitmapToTexture(Bitmap b)
  31. {
  32. game.GraphicsDevice.Textures[0] = null;
  33. if (background == null ||
  34. b.Width != background.Width ||
  35. b.Height != background.Height)
  36. {
  37. width = b.Width;
  38. height = b.Height;
  39. GenerateBitmap(game, width, height);
  40. }
  41. BitmapData bData = b.LockBits(new System.Drawing.Rectangle(new System.Drawing.Point(), b.Size),
  42. ImageLockMode.ReadOnly,
  43. PixelFormat.Format32bppRgb);
  44. // number of bytes in the bitmap
  45. int byteCount = bData.Stride * b.Height;
  46. if (bmpBytes == null ||
  47. bmpBytes.Length != byteCount)
  48. bmpBytes = new byte[byteCount];
  49. // Copy the locked bytes from memory
  50. Marshal.Copy(bData.Scan0, bmpBytes, 0, byteCount);
  51. // don't forget to unlock the bitmap!!
  52. b.UnlockBits(bData);
  53. background.SetData(bmpBytes);
  54. return background;
  55. }
  56. }
  57. }
我终于会插代码了,,,,囧

现在知道降低XNA帧率或者自己写个定时器,总之不要使用60Hz的话,好像帧率也会有很大的提高。
  1. byte[] bgrData = nextFrame.Bytes;
  2. for (int i = 0; i < colorData.Length; i++)
  3. colorData[i] = new Color(bgrData[3 * i + 2], bgrData[3 * i + 1], bgrData[3 * i]);
惊人也没有用到什么内存指针之类的,但是就做到了。使用2张贴图交错的加载方法。膜拜老外啊。


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/118512
推荐阅读
  

闽ICP备14008679号