/// <summary> /// Bitmap画像をSurfaceに変換(このあとTexture化したりするのに使える) /// </summary> /// <param name="bmp"></param> /// <param name="surface"></param> /// <returns></returns> public static YanesdkResult BitmapToSurface(Bitmap bmp,out Surface surface) { int w = bmp.Width; int h = bmp.Height; if (w == 0 || h == 0) { surface = null; return YanesdkResult.PreconditionError; } BitmapData bmpdata; bmpdata = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); if (bmpdata==null) { surface = null; return YanesdkResult.PreconditionError; } surface = new Surface(); surface.CreateDIB(w, h, true); // 32bpp ARGBになってんでない? // 画像コピー unsafe { // 最悪なのことにalignされている(´ω`) byte* src = (byte*)bmpdata.Scan0; int src_pitch = bmpdata.Stride; byte* dst = (byte*)surface.Pixels; int dst_pitch = surface.Pitch; for (int y = 0; y < h; ++y) { for (int i = 0; i < w * 4; i += 4) { // しかもR,G,B逆かよ!(`ω´) dst[i + 0] = src[i + 2]; dst[i + 1] = src[i + 1]; dst[i + 2] = src[i + 0]; dst[i + 3] = src[i + 3]; } src += src_pitch; dst += dst_pitch; } } bmp.UnlockBits(bmpdata); return YanesdkResult.NoError; }
/// <summary> /// このクラスではサーフェースの設定機能は実装されていない。 /// </summary> /// <param name="surface"></param> /// <returns></returns> public YanesdkResult SetSurface(Surface surface) { return YanesdkResult.NotImplemented; }
/// <summary> /// Screenの画像をサーフェスにする。 /// ただし、画面の上に載せている.NET Frameworkのコントロールは /// キャプチャできないので注意。 /// </summary> public Surface GetSurface() { Surface surface = new Surface(); if (surface.CreateDIB(Width, Height, false) != YanesdkResult.NoError) { surface.Dispose(); return(null); } // 読み出し元を設定。 // デフォルトでバックバッファだが念のため設定。 //Gl.glReadBuffer(Gl.GL_FRONT); Gl.glReadBuffer(Gl.GL_BACK); //* Gl.glReadPixels(0, 0, surface.Width, surface.Height, surface.Alpha ? Gl.GL_RGBA : Gl.GL_RGB, Gl.GL_UNSIGNED_BYTE, surface.Pixels); // glReadPixels()で取得したピクセルが上下逆で、 // 反転させる方法が分からなかったので、 // 仕方なくこちら側で反転させるコードを書いてみた。(´ω`) unsafe { int height = surface.Height; int pitch = surface.Pitch; byte *pixels = (byte *)surface.Pixels; byte *buffer = (byte *)Marshal.AllocHGlobal(pitch); for (int y = 0; y < height / 2; y++) { byte *y1 = pixels + y * pitch; byte *y2 = pixels + (height - y - 1) * pitch; CopyMemory(buffer, y1, (uint)pitch); CopyMemory(y1, y2, (uint)pitch); CopyMemory(y2, buffer, (uint)pitch); } Marshal.FreeHGlobal((IntPtr)buffer); } /*/ * * // ↓こっちの方が微妙に重い。 * // 排他処理かなにかでもしてるのかも? * unsafe { * byte* p = (byte*)surface.Pixels; * uint format = surface.Alpha ? Gl.GL_RGBA : Gl.GL_RGB; * for (int y = 0, h = surface.Height; y < h; y++) { * // 1行ずつ読む。 * Gl.glReadPixels(0, h - y - 1, surface.Width, 1, * format, Gl.GL_UNSIGNED_BYTE, (IntPtr)p); * p += surface.Pitch; * } * } * * //*/ return(surface); }
/// <summary> /// Screenの画像をサーフェスにする。 /// ただし、画面の上に載せている.NET Frameworkのコントロールは /// キャプチャできないので注意。 /// </summary> public Surface GetSurface() { Surface surface = new Surface(); if (surface.CreateDIB(Width, Height, false) != YanesdkResult.NoError) { surface.Dispose(); return null; } // 読み出し元を設定。 // デフォルトでバックバッファだが念のため設定。 //Gl.glReadBuffer(Gl.GL_FRONT); Gl.glReadBuffer(Gl.GL_BACK); //* Gl.glReadPixels(0, 0, surface.Width, surface.Height, surface.Alpha ? Gl.GL_RGBA : Gl.GL_RGB, Gl.GL_UNSIGNED_BYTE, surface.Pixels); // glReadPixels()で取得したピクセルが上下逆で、 // 反転させる方法が分からなかったので、 // 仕方なくこちら側で反転させるコードを書いてみた。(´ω`) unsafe { int height = surface.Height; int pitch = surface.Pitch; byte* pixels = (byte*)surface.Pixels; byte* buffer = (byte*)Marshal.AllocHGlobal(pitch); for (int y = 0; y < height / 2; y++) { byte* y1 = pixels + y * pitch; byte* y2 = pixels + (height - y - 1) * pitch; CopyMemory(buffer, y1, (uint)pitch); CopyMemory(y1, y2, (uint)pitch); CopyMemory(y2, buffer, (uint)pitch); } Marshal.FreeHGlobal((IntPtr)buffer); } /*/ // ↓こっちの方が微妙に重い。 // 排他処理かなにかでもしてるのかも? unsafe { byte* p = (byte*)surface.Pixels; uint format = surface.Alpha ? Gl.GL_RGBA : Gl.GL_RGB; for (int y = 0, h = surface.Height; y < h; y++) { // 1行ずつ読む。 Gl.glReadPixels(0, h - y - 1, surface.Width, 1, format, Gl.GL_UNSIGNED_BYTE, (IntPtr)p); p += surface.Pitch; } } //*/ return surface; }