1 using System.Drawing; 2 using System.Drawing.Imaging; 3 using OpenBveApi.Colors; 4 5 namespace OpenBveApi.Textures 6 { 7 /// <summary>Represents a System.Drawing.Bitmap where the texture can be loaded from.</summary> 8 public class BitmapOrigin : TextureOrigin 9 { 10 /// <summary>The bitmap.</summary> 11 public readonly Bitmap Bitmap; 12 /// <summary>The texture parameters to be applied when loading the texture to OpenGL</summary> 13 public readonly TextureParameters Parameters; 14 15 // --- constructors --- 16 /// <summary>Creates a new bitmap origin.</summary> 17 /// <param name="bitmap">The bitmap.</param> BitmapOrigin(Bitmap bitmap)18 public BitmapOrigin(Bitmap bitmap) 19 { 20 this.Bitmap = bitmap; 21 } 22 23 /// <summary>Creates a new bitmap origin.</summary> 24 /// <param name="bitmap">The bitmap.</param> 25 /// <param name="parameters">The texture parameters</param> BitmapOrigin(Bitmap bitmap, TextureParameters parameters)26 public BitmapOrigin(Bitmap bitmap, TextureParameters parameters) 27 { 28 this.Bitmap = bitmap; 29 this.Parameters = parameters; 30 } 31 32 // --- functions --- 33 /// <summary>Gets the texture from this origin.</summary> 34 /// <param name="texture">Receives the texture.</param> 35 /// <returns>Whether the texture could be obtained successfully.</returns> GetTexture(out Texture texture)36 public override bool GetTexture(out Texture texture) 37 { 38 Bitmap bitmap = this.Bitmap; 39 Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height); 40 /* 41 * If the bitmap format is not already 32-bit BGRA, 42 * then convert it to 32-bit BGRA. 43 * */ 44 Color24[] p = null; 45 if (bitmap.PixelFormat != PixelFormat.Format32bppArgb && bitmap.PixelFormat != PixelFormat.Format24bppRgb) 46 { 47 /* Only store the color palette data for 48 * textures using a restricted palette 49 * With a large number of textures loaded at 50 * once, this can save a decent chunk of memory 51 * */ 52 p = new Color24[bitmap.Palette.Entries.Length]; 53 for (int i = 0; i < bitmap.Palette.Entries.Length; i++) 54 { 55 p[i] = bitmap.Palette.Entries[i]; 56 } 57 } 58 59 if (bitmap.PixelFormat != PixelFormat.Format32bppArgb) 60 { 61 Bitmap compatibleBitmap = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format32bppArgb); 62 System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(compatibleBitmap); 63 graphics.DrawImage(bitmap, rect, rect, GraphicsUnit.Pixel); 64 graphics.Dispose(); 65 bitmap = compatibleBitmap; 66 } 67 68 /* 69 * Extract the raw bitmap data. 70 * */ 71 BitmapData data = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat); 72 if (data.Stride == 4 * data.Width) 73 { 74 /* 75 * Copy the data from the bitmap 76 * to the array in BGRA format. 77 * */ 78 byte[] raw = new byte[data.Stride * data.Height]; 79 System.Runtime.InteropServices.Marshal.Copy(data.Scan0, raw, 0, data.Stride * data.Height); 80 bitmap.UnlockBits(data); 81 int width = bitmap.Width; 82 int height = bitmap.Height; 83 /* 84 * Change the byte order from BGRA to RGBA. 85 * */ 86 for (int i = 0; i < raw.Length; i += 4) 87 { 88 byte temp = raw[i]; 89 raw[i] = raw[i + 2]; 90 raw[i + 2] = temp; 91 } 92 93 texture = new Texture(width, height, 32, raw, p); 94 texture = texture.ApplyParameters(this.Parameters); 95 return true; 96 } 97 98 /* 99 * The stride is invalid. This indicates that the 100 * CLI either does not implement the conversion to 101 * 32-bit BGRA correctly, or that the CLI has 102 * applied additional padding that we do not 103 * support. 104 * */ 105 bitmap.UnlockBits(data); 106 texture = null; 107 return false; 108 } 109 } 110 } 111