Terraria ModLoader  0.11.7.8
A mod to make and play Terraria mods
ImageIO.cs
Go to the documentation of this file.
1 using Microsoft.Xna.Framework.Graphics;
2 using System;
3 using System.Drawing;
4 using System.Drawing.Imaging;
5 using System.IO;
6 using System.Runtime.InteropServices;
7 using System.Text;
8 using System.Threading.Tasks;
9 using Terraria.ModLoader.Engine;
10 
11 namespace Terraria.ModLoader.IO
12 {
13  public class ImageIO
14  {
15  public const int VERSION = 1;
16 
17  public static bool ToRaw(Stream src, Stream dst) {
18  using (var img = new Bitmap(src)) {
19  // now that the hi-def profile is always enabled, the max texture size is 4096
20  // if we get bug reports with old graphics cards forcing fallback to Reach and failing to load
21  // large textures, we can implement a slower path where the rawimg is converted to png before loading
22 
23  //if (img.Width > 2048 || img.Height > 2048)
24  // return false;
25 
26  var bitmapData = img.LockBits(new Rectangle(0, 0, img.Width, img.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
27  var rawdata = new int[img.Width * img.Height];
28  Marshal.Copy(bitmapData.Scan0, rawdata, 0, rawdata.Length);
29  var w = new BinaryWriter(dst);
30  w.Write(VERSION);
31  w.Write(img.Width);
32  w.Write(img.Height);
33  foreach (int c in rawdata) {
34  //Bitmap is in ABGR
35  int a = c >> 24 & 0xFF;
36  int b = c >> 16 & 0xFF;
37  int g = c >> 8 & 0xFF;
38  int r = c >> 0 & 0xFF;
39 
40  //special note, mirror XNA behaviour of zeroing out textures with full alpha zero
41  //this means that an author doesn't have to set their fully transparent pixels to black
42  //if they want additive blending they need to use alpha 1/255
43  if (a == 0) {
44  w.Write(0);
45  continue;
46  }
47 
48  //write ARGB, note that the texture is assumed pre-multiplied, allowing for extra blending effects
49  w.Write((byte)b);
50  w.Write((byte)g);
51  w.Write((byte)r);
52  w.Write((byte)a);
53  }
54 
55  return true;
56  }
57  }
58 
59  public static byte[] ToRawBytes(Stream src) {
60  using (var ms = new MemoryStream()) {
61  return ToRaw(src, ms) ? ms.ToArray() : null;
62  }
63  }
64 
65  public static Texture2D RawToTexture2D(GraphicsDevice graphicsDevice, Stream src) =>
66  RawToTexture2D(graphicsDevice, new BinaryReader(src, Encoding.UTF8));
67 
68  public static void RawToPng(Stream src, Stream dst) {
69  using (var img = RawToTexture2D(Main.instance.GraphicsDevice, src))
70  img.SaveAsPng(dst, img.Width, img.Height);
71  }
72 
73  public static Tuple<int, int, byte[]> ReadRaw(Stream src) =>
74  ReadRaw(new BinaryReader(src, Encoding.UTF8));
75 
76  public static Tuple<int, int, byte[]> ReadRaw(BinaryReader r) {
77  int v = r.ReadInt32();
78  if (v != VERSION)
79  throw new Exception("Unknown RawImg Format Version: " + v);
80 
81  int width = r.ReadInt32();
82  int height = r.ReadInt32();
83  var rawdata = r.ReadBytes(width * height * 4);
84  return new Tuple<int, int, byte[]>(width, height, rawdata);
85  }
86 
87  public static Texture2D RawToTexture2D(GraphicsDevice graphicsDevice, BinaryReader r) {
88  var rawData = ReadRaw(r);
89  var tex = new Texture2D(graphicsDevice, rawData.Item1, rawData.Item2);
90  tex.SetData(rawData.Item3);
91  return tex;
92  }
93 
94  public static Task<Texture2D> RawToTexture2DAsync(GraphicsDevice graphicsDevice, BinaryReader r) {
95  var rawData = ReadRaw(r);
96  return GLCallLocker.InvokeAsync(() => {
97  var tex = new Texture2D(graphicsDevice, rawData.Item1, rawData.Item2);
98  tex.SetData(rawData.Item3);
99  return tex;
100  });
101  }
102 
103  public static Task<Texture2D> PngToTexture2DAsync(GraphicsDevice graphicsDevice, Stream stream) {
104 #if XNA
105  if (!(stream is MemoryStream)) {
106  var ms = new MemoryStream((int)stream.Length);
107  stream.CopyTo(ms);
108  ms.Position = 0;
109  stream = ms;
110  }
111  return GLCallLocker.InvokeAsync(() => Texture2D.FromStream(graphicsDevice, stream));
112 #else
113  Texture2D.TextureDataFromStreamEXT(stream, out int width, out int height, out byte[] rawdata, -1, -1, false);
114  return GLCallLocker.InvokeAsync(() => {
115  var tex = new Texture2D(graphicsDevice, width, height);
116  tex.SetData(rawdata);
117  return tex;
118  });
119 #endif
120  }
121  }
122 }
static Texture2D RawToTexture2D(GraphicsDevice graphicsDevice, BinaryReader r)
Definition: ImageIO.cs:87
static bool ToRaw(Stream src, Stream dst)
Definition: ImageIO.cs:17
static Tuple< int, int, byte[]> ReadRaw(BinaryReader r)
Definition: ImageIO.cs:76
static void RawToPng(Stream src, Stream dst)
Definition: ImageIO.cs:68
static byte[] ToRawBytes(Stream src)
Definition: ImageIO.cs:59
static Task< Texture2D > RawToTexture2DAsync(GraphicsDevice graphicsDevice, BinaryReader r)
Definition: ImageIO.cs:94
static Task< Texture2D > PngToTexture2DAsync(GraphicsDevice graphicsDevice, Stream stream)
Definition: ImageIO.cs:103