2
\$\begingroup\$

To display an image from Content in a .NET Forms Dialog, I'm trying to make a function that loads an image through .NET's Image.FromFile(string fileName) function, but instead of taking a whole path, it takes the path you'd usually put in Content.Load<T>(string assetName).

For this, I need to be able to get the complete root directory of the Content folder, but how do I get that?

I've already tried Content.RootDirectory, but that seems to give only a relative file path (in my case, it just says "Content" because I left it at default)

Thanks in advance!

\$\endgroup\$
4
\$\begingroup\$

There's a few things you need to understand to get this to work.

First, what you're trying to do will be platform specific. So I'm going to assume you're only concerned with getting it working on Windows.

Second, if you're adding content to the Content.mgcb file it will be compiled by MonoGame's Content Pipeline and it will end up in a Content folder as an XNB file relative to the executable.

For example, let's say you've added a texture.png file to your Content.mgcb file. When the game or tool runs the image will be compiled and end up in the following place by default.

 - Game.exe
 - Content
     - texture.xnb

This means that the path relative to your executable would be Content\texture.xnb and you could use the regular C# method Path.GetFullPath("Content\texture.xnb") to get the full path relative to the executable.

Of course, you won't be able to load an XNB file with Image.FromFile(string fileName) because it's not a standard image format. To deal with that what you'll probably want to do is copy the original texture.png file to the output folder.

To do that you can use the Properties of the file and set the Build Action to Content and the Copy to Output Directory to Copy if newer.

copy image to the output directory

Now the texture.png file will be available to load relative to the executable.

 - Game.exe
 - Content
     - texture.png

Lastly, if you want to actually load this PNG file directly into MonoGame without using the Content.Load method you can write you're own method using Texture2D.FromStream like this:

public Texture2D LoadTexture(string filePath)
{
    using (var fileStream = File.OpenRead(filePath))
    {
        var newTexture = Texture2D.FromStream(GraphicsDevice, fileStream);
        PremultiplyTexture(newTexture);
        return newTexture;
    }
}

private static void PremultiplyTexture(Texture2D texture)
{
    var data = new Color[texture.Width * texture.Height];

    texture.GetData(data);

    for (var i = 0; i < data.Length; i++)
        data[i] = Color.FromNonPremultiplied(data[i].R, data[i].G, data[i].B, data[i].A);

    texture.SetData(data);
}

Note: I've also included a method to pre-multiply the texture because this is something normally done by the MonoGame Content Pipeline. If you don't do this the texture won't work properly with AlphaBlend mode.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks for the answer! Aside from the ability to preview the image in a windows form, is there any advantage of using png files over resuming to build them with Monogame's pipeline tool? \$\endgroup\$ – Suhbahstiejaan Aug 28 '19 at 11:44
  • \$\begingroup\$ I don't understand what you mean by "resuming to build them"? \$\endgroup\$ – craftworkgames Aug 28 '19 at 13:36
  • \$\begingroup\$ Oh sorry. I meant resuming to use MonoGame's Content Pipeline tool for managing them in xnb format instead of png. Like is there an advantage of using png's exclusively and circumventing the Content Pipeline Tool entirely? \$\endgroup\$ – Suhbahstiejaan Aug 28 '19 at 16:33
  • \$\begingroup\$ The Content Pipeline essentially solves 2 problems. 1. It makes content cross platform by compiling it into a known format. 2. It sometimes adds extra information when processing it like premultiplying the alpha channel for rendering. If you want to bypass the Pipeline you can solve those problems yourself and a lot if the time you can easily enough. It really depends on the platforms you're targeting and what kind of content you need to load. \$\endgroup\$ – craftworkgames Aug 29 '19 at 6:31
1
\$\begingroup\$

Use Application.dataPath to get the folder of your game, the concatenate the string with "Assets\Resources" or wherever your pictures may be.

https://docs.unity3d.com/ScriptReference/Application-dataPath.html

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I feel like now would be a good time to mention I'm not using Unity, but MonoGame. The only classes that seem close to it are System.ApplicationId, System.ApplicationIdentity and System.ApplicationException. \$\endgroup\$ – Suhbahstiejaan Aug 27 '19 at 13:18
1
\$\begingroup\$
string contentPath = System.Forms.Application.StartupPath + "\\" + Content.RootDirectory;

Did the trick for me. Unfortunately, the files it'll give you are in a .xnb format, making it impossible to pass on to the image of a Windows Form.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.