Raylib-cs icon indicating copy to clipboard operation
Raylib-cs copied to clipboard

Load image from EmbeddedResource

Open drum445 opened this issue 3 years ago • 7 comments

Before submitting a new issue, please verify and check:

  • [x] The issue is specific to Raylib-cs and not raylib
  • [x] I checked there is no similar issue already reported
  • [x] My code has no errors or misuse of Raylib-cs

Issue description

I would like to be able to load an image file using embedded resources and convert this to a Raylib_cs.Image/Texture

Environment

Code example

My current code:

var myStream = Program.game.GetType().Assembly.GetManifestResourceStream(path);
var image = System.Drawing.Image.FromStream(myStream);

return Raylib.LoadTextureFromImage(image);

Throws the error:

error CS1503: Argument 1: cannot convert from 'System.Drawing.Image' to 'Raylib_cs.Image'

There may already be a way to do this, but I couldn't find one in the examples or looking at the lib's code. The Go raylib library provides a NewImageFromImage function that converts a native go Image into a Raylib one, so something like that would probably do

Thanks

drum445 avatar Aug 17 '22 21:08 drum445

would #113 fix your issue, or would you require the use of embedded resources?

9ParsonsB avatar Aug 18 '22 01:08 9ParsonsB

That does look interesting thanks, but I ideally want to be able to embed all my resources into a single stand-alone executable and deploy that way

drum445 avatar Aug 20 '22 16:08 drum445

You could always combine the files after building (e.g. copy /b Game.exe + Resources.rres GameWithResources.exe) and then split them up again at runtime by looking for the rres Magic Bytes (HEX: 72 72 65 73).

I am currently developing an rres parser for use with Raylib-cs, so I will take this use-case under consideration

9ParsonsB avatar Aug 22 '22 01:08 9ParsonsB

It might be possible to convert it to a raylib Image by creating it directly. You need to check the pixel format matches and make sure the data is unmanaged. Not sure how to get the raw data from a System.Drawing.Image though.

rgebee avatar Aug 22 '22 06:08 rgebee

@ChrisDill the System.Drawing.Image wasn't for any particular reason, it was just the way I'm currently loading an image from disk. Any way where I can go from an embedded file to a raylib image would be top cheers

drum445 avatar Aug 23 '22 17:08 drum445

@drum445 Yes, there is a way:

using System;
using Raylib_cs;
using System.Reflection;
using System.Runtime.InteropServices;

static class Program
{
    static void Main(string[] args)
    {
        Raylib.SetConfigFlags(ConfigFlags.FLAG_VSYNC_HINT);
        Raylib.InitWindow(1280, 720, "Demo Game");

        Texture2D texture;

        using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("DemoGame.icon.png")!)
        {
            using (var memoryStream = new MemoryStream())
            {
                stream.CopyTo(memoryStream);

                var image = LoadImageFromMemory(".png", memoryStream.ToArray(), (int)memoryStream.Length);
                texture = Raylib.LoadTextureFromImage(image);
                Raylib.UnloadImage(image);
            }
        }

        while (!Raylib.WindowShouldClose())
        {
            Raylib.BeginDrawing();
            Raylib.ClearBackground(Color.BEIGE);
            Raylib.DrawTexture(texture, 0, 0, Color.WHITE);
            Raylib.EndDrawing();
        }

        Raylib.UnloadTexture(texture);
        Raylib.CloseWindow();
    }

    [DllImport("raylib", CallingConvention = CallingConvention.Cdecl)]
    static extern Image LoadImageFromMemory(string fileType, byte[] fileData, int dataSize);
}

Once you have added your Image as embedded resource in your csproj ...

  <ItemGroup>
    <EmbeddedResource Include="icon.png" />
  </ItemGroup>

... you can load it like above. The "original" LoadImageFromMemory takes a pointer. If you don't want to mess with them, you can write your own method:

    [DllImport("raylib", CallingConvention = CallingConvention.Cdecl)]
    static extern Image LoadImageFromMemory(string fileType, byte[] fileData, int dataSize);

JupiterRider avatar Sep 18 '22 16:09 JupiterRider

@JupiterRider Thanks for sharing! Though your example shouldn't load the image with managed memory as the image data and functions around it assume the data to be unmanaged.

rgebee avatar Sep 18 '22 19:09 rgebee

@JupiterRider cheers for that, it seems to be working well.

Many thanks 👍

drum445 avatar Dec 27 '22 20:12 drum445