Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Jiiks/ImgBinner

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ImgBinner

Simple application to bin a directory of images into a single binary to use with ImGui

Creates a binary with the following header:

[<filename>@<width>x<height>x<channels>|<offset>^<length>]

Generates a source file with constants for every image

for example for a directory named test with some_image.30.png in it

// Auto generated by imgbinner

namespace ImgBinner;

public static class Test {
    public const string SOME_IMAGE_30 = "some_image.30";
}

Rendering is as simple as

var tex = _textures.First(t => t.Name == "textureName");
ImGui.Image(tex.Texture, new Vector2(128, 128));

// or with the generated source file:
var tex = _textures.First(t => t.Name == Test.SOME_IMAGE_30);
ImGui.Image(tex.Texture, new Vector2(128, 128));

TODO

  • Indexing for speed

Usage:

Just drop a folder containing your images on the exe and then in your app:

struct ImgBinEntry {
    public string Name;
    public int Width;
    public int Height;
    public int Channels;
    public int Offset;
    public int Length;
}

struct Texture2D {
    public string Name;
    public int Width;
    public int Height;
    public int Channels;
    public uint Texture;
}

private static IEnumerable<ImgBinEntry> Parseheader(byte[] bytes, int headerEnd = 0) {
    if(headerEnd == 0)
        headerEnd = Array.IndexOf(bytes, (byte)'$');

    if (headerEnd == -1) {
        return [];
    }

    var headerBytes = new byte[headerEnd + 1];
    Array.Copy(bytes, 0, headerBytes, 0, headerEnd + 1);


    var header = Encoding.ASCII.GetString(headerBytes);
    var list = new List<ImgBinEntry>();
    var start = 0;
    while ((start = header.IndexOf('[', start)) != -1) {
        var end = header.IndexOf(']', start + 1);
        if (end == -1) break;

        var entry = header.Substring(start + 1, end - start - 1);

        var parts = entry.Split('@', '|', '^');

        //Extract filename, dimensions, start, and length
        var filename = parts[0];
        var dimensions = parts[1].Split('x');
        var width = int.Parse(dimensions[0]);
        var height = int.Parse(dimensions[1]);
        var channels = int.Parse(dimensions[2]);
        var dataStart = int.Parse(parts[2]);
        var dataLength = int.Parse(parts[3]);
        
        // Add to the list as a FileEntry object
        list.Add(new ImgBinEntry {
            Name = filename,
            Width = width,
            Height = height,
            Channels = channels,
            Offset = dataStart,
            Length = dataLength
        });

        start = end + 1;
    }

    return list;
}


public unsafe static IEnumerable<Texture2D> LoadBinary(byte[] bin) {
    var headerEnd = Array.IndexOf(bin, (byte)'$');
    if (headerEnd == -1 || headerEnd >= bin.Length - 1) {
        return [];
    }


    List<Texture2D> textures = [];
    // Parse header
    var header = Parseheader(bin, headerEnd);

    // Get body
    var bodyLength = bin.Length - (headerEnd + 1);
    var body = new byte[bodyLength];
    Array.Copy(bin, headerEnd + 1, body, 0, bodyLength);

    foreach (var entry in header) {
        var filebytes = new byte[entry.Length];
        Array.Copy(body, entry.Offset, filebytes, 0, filebytes.Length);

        fixed (byte* bytePtr = filebytes) {
            var tex = CreateTexture(bytePtr, entry.Width, entry.Height); // Replace with your create texture
            textures.Add(new Texture2D {
                Name = entry.Name,
                Width = entry.Width,
                Height = entry.Height,
                Channels = entry.Channels,
                Texture = tex
            });
        }

    }

    return textures;
}
// OpenTK CreateTexture
private static unsafe uint CreateTexture(byte* imageData, int width, int height) {
    // Generate a texture ID
    GL.GenTextures(1, out uint texture);

    // Bind the texture to the 2D texture target
    GL.BindTexture(TextureTarget.Texture2D, texture);

    // Upload the texture data
    GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0,
                  PixelFormat.Rgba, PixelType.UnsignedByte, (IntPtr)imageData);

    // Set texture parameters
    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
    GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);

    // Unbind the texture to prevent accidental modifications
    GL.BindTexture(TextureTarget.Texture2D, 0);

    // Return the generated texture ID
    return texture;
}
// Silk CreateTexture
private static unsafe uint CreateTexture(byte* imageData, int width, int height) {
    _gl.GenTextures(1, out uint texture);
    _gl.BindTexture(GLEnum.Texture2D, texture);
    _gl.TexImage2D(GLEnum.Texture2D, 0, (int)GLEnum.Rgba, (uint)width, (uint)height, 0, GLEnum.Rgba, GLEnum.UnsignedByte, imageData);
    _gl.TexParameter(GLEnum.Texture2D, GLEnum.TextureMinFilter, (int)GLEnum.Linear);
    _gl.TexParameter(GLEnum.Texture2D, GLEnum.TextureMagFilter, (int)GLEnum.Linear);
    _gl.BindTexture(GLEnum.Texture2D, 0);
    return texture;
}

About

Simple application to bin a directory of images into a single binary to use with ImGui

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages