Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: sf::Texture load from memory  (Read 38156 times)

0 Members and 1 Guest are viewing this topic.

Mörkö

  • Jr. Member
  • **
  • Posts: 96
    • View Profile
sf::Texture load from memory
« on: January 14, 2015, 05:34:57 pm »
Hi. I'm having trouble figuring out how sf::Texture::loadFromMemory works. I would be grateful if you could demonstrate a complete minimal working example how to use it.

If you don't want to generate your own image, then you may take one of these:

(click to show/hide)

(click to show/hide)

Thanks.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: sf::Texture load from memory
« Reply #1 on: January 14, 2015, 07:33:08 pm »
This function is simple, it acts the same as loadFromFile except that the file contents are in memory rather than on the disk.

Sorry I haven't got the time to write a minimal example for it, maybe later.
Laurent Gomila - SFML developer

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: sf::Texture load from memory
« Reply #2 on: January 14, 2015, 09:44:51 pm »
Here's a quick and dirty example that I just quickly threw together:
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <iostream>
#include <fstream>
#include <cstdlib>

int main()
{
    sf::ContextSettings glsettings;
    glsettings.antialiasingLevel = 2;
    sf::RenderWindow window{sf::VideoMode{300, 80}, "loadFromMemory Example", sf::Style::Titlebar | sf::Style::Close, glsettings};

    const auto desktop = sf::VideoMode::getDesktopMode();
    window.setPosition({static_cast<int>(desktop.width / 2 - window.getSize().x / 2),
                       static_cast<int>(desktop.height / 4 - window.getSize().y / 4)});

    window.setMouseCursorVisible(false);
    window.setVerticalSyncEnabled(true);
    window.setKeyRepeatEnabled(false);

    std::ifstream texture_file{"example-texture.png", std::ifstream::binary};
    std::vector<char> buffer;
    if (texture_file) {
        // get length of file:
        texture_file.seekg(0, texture_file.end);
        const auto length = texture_file.tellg();
        if (!length) {
            std::cerr << "Cannot load zero byte texture file" << std::endl;
            return EXIT_FAILURE;
        }
        buffer.resize(length); // reserve space

        texture_file.seekg(0, texture_file.beg);

        auto start = &*buffer.begin();
        texture_file.read(start, length);
        texture_file.close();
    } else {
        std::cerr << "Could not open texture file" << std::endl;
        return EXIT_FAILURE;
    }

    sf::Texture texture;
    if (!texture.loadFromMemory(&buffer[0], buffer.size())) {
        std::cerr << "Texture load failed" << std::endl;
        return EXIT_FAILURE;
    }

    sf::Sprite sprite;
    sprite.setTexture(texture);

    while (window.isOpen()) {
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        window.clear(sf::Color::Black);
        window.draw(sprite);
        window.display();
    }

    return EXIT_SUCCESS;
}
 

The "example-texture.png" image I used is here:

And here's a screenshot of the result:
« Last Edit: January 14, 2015, 11:32:00 pm by Jesper Juhl »

Mörkö

  • Jr. Member
  • **
  • Posts: 96
    • View Profile
Re: sf::Texture load from memory
« Reply #3 on: January 14, 2015, 11:43:11 pm »
Yeah, I guess that will do it, but it's not quite what I was after  ;D

I should have mentioned my goal is to embed some images in the executable, so obviously loading the data from a file defeats the purpose. Sorry my bad.

How would you do it with C formatted data?

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: sf::Texture load from memory
« Reply #4 on: January 14, 2015, 11:49:52 pm »
Whether or not you load a file from disk to a memory buffer and then loadFromMemory() from that buffer or have a memory buffer already embedded in the executable (like an array or similar) makes no difference what-so-ever. As long as you can pass loadFromMemory() the address of the start of your memory buffer as well as the size, it doesn't care how that data got to be in memory - it'll just load it.
So, if your data is in an array named "foo" embedded in the executable, then just do
Code: [Select]
loadFromMemory(foo, sizeof(foo / sizeof(foo[0])); or similar.
« Last Edit: January 14, 2015, 11:52:38 pm by Jesper Juhl »

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: sf::Texture load from memory
« Reply #5 on: January 15, 2015, 01:13:16 am »
The memory that loadFromMemory loads from should still be in a recognised file format.
If you require to load a texture from raw pixel data, you would use sf::Image directly and create one from the data. Then, you load the sf::Texture from the sf::Image.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

grok

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
    • Email
Re: sf::Texture load from memory
« Reply #6 on: January 15, 2015, 06:21:59 am »
Mörkö,
am I right you want to embed your encrypted images into the executable and then load them normally using loadFromMemory into sf::Texture?
if yes, then it is possible, but requires a few more steps to be performed:
1) load your image in the memory
2) perform some encryption
3) save that chunk of memory into somewhere (probably on disk)
4) copy that chunk of bytes from disk to some static array in your program
5) when your program runs you decrypt that array
6) load image normally from the decrypted chunk of memory you got from 5).

Or did I miss your point?  8)
« Last Edit: January 15, 2015, 06:24:16 am by grok »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: sf::Texture load from memory
« Reply #7 on: January 15, 2015, 07:55:43 am »
static const char embeddedImageData[] =
{
    /* content generated by one of the hundreds
        of programs that do it, or by your own small utility
       (doesn't take more than 10 lines of C++ code) */

};

texture.loadFromMemory(embeddedImageData, sizeof(embeddedImageData));

Example of code that generate such an array:

#include <fstream>
#include <iomanip>

int main(int argc, char** argv)
{
    std::ifstream in("image.png", std::ios_base::binary);
    std::ofstream out("header.hpp");

    out << "const char imageData[] =" << std::endl;
    out << "{" << std::endl;
    do
    {
        out << "    ";
        for (int i = 0; (i < 20) && in; ++i)
            out << "0x" << std::hex << std::setw(2) << std::setfill('0') << in.get() << std::dec << ", ";
        out << std::endl;
    }
    while (in);
    out << "};" << std::endl;

    return 0;
 

Note that it can be more concise if you don't care about the pretty formatting.

Quote
loadFromMemory(foo, sizeof(foo / sizeof(foo[0]));
This one is wrong, we really want the size in bytes, not the number of elements.
« Last Edit: January 15, 2015, 08:02:33 am by Laurent »
Laurent Gomila - SFML developer

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: sf::Texture load from memory
« Reply #8 on: January 15, 2015, 07:59:36 am »
Of course. Stupid late at night mistake.

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: sf::Texture load from memory
« Reply #9 on: January 15, 2015, 09:08:16 am »
am I right you want to embed your encrypted images into the executable and then load them normally using loadFromMemory into sf::Texture?
if yes, then it is possible, but requires a few more steps to be performed:
You are overcomplicating things.

First of all, the easiest way to get a C array from an image is to just use the 'convert' tool from ImageMagick or one of a ton of other similar tools.

And there is certainly no need to use any encryption as you wrote.
« Last Edit: January 15, 2015, 09:16:41 am by Jesper Juhl »

Mörkö

  • Jr. Member
  • **
  • Posts: 96
    • View Profile
Re: sf::Texture load from memory
« Reply #10 on: January 15, 2015, 05:24:40 pm »
Thanks all, and esp Jesper and Laurent for the examples, it's clear now, and I got it to work.

Quote from: grok
am I right you want to embed your encrypted images into the executable and then load them normally using loadFromMemory into sf::Texture?

Nope, like Jesper Juhl said, embedding is enough.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: sf::Texture load from memory
« Reply #11 on: January 20, 2015, 04:02:14 pm »
Just in case someone runs into this topic again and doesn't fully understand how it got resolved.

GIMP exports files in the pixel format, meaning that you get an array of char with each char representing a pixel component and each 4 chars representing a full pixel in the RGBA format. If you want to use this kind of format, you can call the sf::Image::create(width, height, pixels) function. This is also optimal for direct usage with the sf::Window::setIcon() function.

However if you want to use the loadFromMemory() function, you actually need to have the full binary data of the image in memory. It needs to be in a supported format like PNG, JPEG or similar. So basically a file from your disk, but in memory.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Austin J

  • Newbie
  • *
  • Posts: 29
    • View Profile
    • Email
Re: sf::Texture load from memory
« Reply #12 on: January 22, 2015, 06:18:52 am »
Yeah, the only time I've seen the call for loadFromMemory() is if you loaded the file with another lib, then passed it on, which does arise for some people.

shadowmouse

  • Sr. Member
  • ****
  • Posts: 302
    • View Profile
Re: sf::Texture load from memory
« Reply #13 on: January 25, 2015, 10:52:48 pm »
Is this what I would use if I wanted to load a texture from a resource file that had been compiled into the exe?

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: sf::Texture load from memory
« Reply #14 on: January 25, 2015, 11:06:08 pm »
Yes.