SFML community forums

Help => Graphics => Topic started by: Ragbot on May 27, 2021, 05:31:26 pm

Title: Is there a way to just pass in .png or .jpg data into sf::Texture(); ?
Post by: Ragbot on May 27, 2021, 05:31:26 pm
Like when we have the data stored in a char[] or std::string?

and is the same possible for sf::Music with .wav and .ogg files?

I tried this.... but...
I kinda regret it now...

That was hell...

#include <iostream>
#include <fstream>
#include <ios>
#include <SFML/Audio.hpp>


int main()
{
        std::string str = "";
        std::string file = "";
        std::ifstream fileStream("audio.wav", std::ios::binary);
        while(getline(fileStream, str))
        {
                file += str;
        }

        sf::Music audio;
        audio.openFromMemory(file.data(), file.length());
        audio.play();

        while(audio.getStatus() != sf::SoundSource::Stopped){}


        return 0;
}
 
Title: Re: Is there a way to just pass in .png or .jpg data into sf::Texture(); ?
Post by: kojack on May 27, 2021, 08:10:16 pm
That loop is corrupting the data.
Wav files are binary data, they don't have lines as such. The getline function looks for end of line characters (which will be coincidental, since there's no lines to end) and strips them away. So the result in file will be missing bytes.
Wav is just waveform data, so you probably won't notice, but more complex formats like compressed textures will be corrupted.

Anyway, Texture has loadFromMemory, which is the equivalent of Music's openFromMemory.
Title: Re: Is there a way to just pass in .png or .jpg data into sf::Texture(); ?
Post by: Ragbot on May 28, 2021, 06:57:12 am
so what should I use to get the binary without corrupting the data?
Title: Re: Is there a way to just pass in .png or .jpg data into sf::Texture(); ?
Post by: Stauricus on May 28, 2021, 07:57:49 am
why are you trying to open from memory the file that you just did read? why don't you simply use 'openFromFile'?
anyway, if you really want to have the resource included in your executable, this is how you do it (https://en.sfml-dev.org/forums/index.php?topic=17256.msg124157#msg124157).
Title: Re: Is there a way to just pass in .png or .jpg data into sf::Texture(); ?
Post by: kojack on May 28, 2021, 11:02:39 am
so what should I use to get the binary without corrupting the data?
As Stauricus said, the easiest way to get stuff into SFML is to use the open/load functions. Music::openFromFile can load wav, ogg and flac. Texture::loadFromFile can load bmp, png, tga, jpg, gif, psd, hdr and pic.

But if you do want to open a binary file yourself (handy for things not part of SFML like save files, maps, etc), here's an quick example.
#include <fstream>
#include <filesystem>

int main()
{
    // Path to file
    std::filesystem::path p = "raw.dat";
    std::error_code ec;
    // Get the size of the file
    auto size = std::filesystem::file_size(p,ec);
    // Make sure no errors happened when getting the size
    if (!ec)
    {
        // Allocate enough memory for it
        char* data = new char[size];
        // Open the file for binary reading
        std::fstream in("raw.dat", std::ios::binary | std::ios::in);
        // If it opened...
        if (in.good())
        {
            // Read in the file
            in.read(data, size);
            // You now have the entire file sitting in data
        }
        // Release memory now that we are done
        delete[] data;
    }
    return 0;
}
 
This is using C++17, it added the file system stuff that can check the size of a file.
Also some may prefer to use a vector or something for the data, but I just stick to simple new/delete (yeah, I learned C++ long before std existed)
Title: Re: Is there a way to just pass in .png or .jpg data into sf::Texture(); ?
Post by: Ragbot on May 28, 2021, 12:22:15 pm
why are you trying to open from memory the file that you just did read? why don't you simply use 'openFromFile'?
anyway, if you really want to have the resource included in your executable, this is how you do it (https://en.sfml-dev.org/forums/index.php?topic=17256.msg124157#msg124157).

I was just using it as an example, in my app ill try to download the data from the internet  ;)

and thanks @kojack that's exactly what I wanted