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

Author Topic: texture.update(pixels), using std::vector of Uint8 instead of array  (Read 6358 times)

0 Members and 1 Guest are viewing this topic.

Ganado

  • Newbie
  • *
  • Posts: 34
  • Moo, I say.
    • View Profile
    • FOnline Engine, check it out.
After reading http://sfml-dev.org/documentation/2.0/classsf_1_1Texture.php usage examples and http://en.sfml-dev.org/forums/index.php?topic=11900.msg82631

You should really not use new[] and delete[]. Take std::vector instead.

I am trying to display an image from a set of pixel data from an old file format (width*height values, ranging from 0-255, mapped to a 256-color palette, the details aren't relevant).

My code won't compile if I attempt to use an std::vector.

As in, this compiles
Code: [Select]
        mTexture.create(width, height);
        mSprite.setTexture(mTexture, true);

        sf::Uint8* pixels = new sf::Uint8[width * height * 4];
        for (int i = 0; i < width*height; i+=4)
        {
            //TODO: Change to the palette mapping...
            pixels[i] = colors[i];
            pixels[i+1] = colors[i];
            pixels[i+2] = colors[i];
            pixels[i+3] = 255;
        }
        mTexture.update(pixels);
        delete[] pixels;

but it doesn't if I try to change it to an std::vector...
Code: [Select]
        mTexture.create(width, height);
        mSprite.setTexture(mTexture, true);

        std::vector<sf::Uint8> pixels(width * height * 4);
        for (int i = 0; i < width*height; i+=4)
        {
            //TODO: Change to the palette mapping...
            pixels[i] = colors[i];
            pixels[i+1] = colors[i];
            pixels[i+2] = colors[i];
            pixels[i+3] = 255;
        }
        mTexture.update(pixels);


What should I be doing instead to avoid using new and delete[]? It looks like the usage example in the docs is using a dynamically allocated array
Code: [Select]
sf::Uint8* pixels = ...; // get a fresh chunk of pixels
« Last Edit: July 17, 2014, 04:00:48 am by Ganado »

Strelok

  • Full Member
  • ***
  • Posts: 139
    • View Profile
    • GitHub
Re: texture.update(pixels), using std::vector of Uint8 instead of array
« Reply #1 on: July 17, 2014, 04:23:46 am »
How about using http://sfml-dev.org/documentation/2.1/classsf_1_1Image.php so that you can either pass image as reference or use getPixelStr() which is probably destructed when image is destructed ;)
It could be suboptimal performance wise, though. Maybe someone has a better way to do it.
P.S. the docs says: the returned pointer may become invalid if you modify the image, so you should never store it for too long. If the image is empty, a null pointer is returned
« Last Edit: July 17, 2014, 04:28:44 am by Strelok »

Ganado

  • Newbie
  • *
  • Posts: 34
  • Moo, I say.
    • View Profile
    • FOnline Engine, check it out.
Re: texture.update(pixels), using std::vector of Uint8 instead of array
« Reply #2 on: July 17, 2014, 04:40:40 am »
Thanks for the reply, I found a solution to the original problem at http://en.sfml-dev.org/forums/index.php?topic=14323.msg100700#msg100700

Code: [Select]
mTexture.update(&pixels[0]);
Not sure what you mean by "using" sf::Image. I hadn't used sf::Image like that before, you'd still need to make a texture and sprite to display it anyway, no?
« Last Edit: July 17, 2014, 04:42:29 am by Ganado »

Strelok

  • Full Member
  • ***
  • Posts: 139
    • View Profile
    • GitHub
Re: texture.update(pixels), using std::vector of Uint8 instead of array
« Reply #3 on: July 17, 2014, 04:52:34 am »
Texture.update has a (sf::Image& image) overload  but at this point it doesn't matter as Laurent's solution is better resource and performance wise. Perhaps using http://en.cppreference.com/w/cpp/container/array would improve things even more but at this point the difference is minimal and I can't test it now so stick with Laurent's solution.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: texture.update(pixels), using std::vector of Uint8 instead of array
« Reply #4 on: July 17, 2014, 08:11:21 am »
Quote
Perhaps using http://en.cppreference.com/w/cpp/container/array would improve things even more
std::array<T, N> is just a wrapper around T[N]. The size must be known at compile time, which is not the case here. And it is allocated on the stack (in this context), which makes its maximum size usually too low for storing images. So no, it wouldn't improve anything ;)
Laurent Gomila - SFML developer

Strelok

  • Full Member
  • ***
  • Posts: 139
    • View Profile
    • GitHub
Quote
Perhaps using http://en.cppreference.com/w/cpp/container/array would improve things even more
std::array<T, N> is just a wrapper around T[N]. The size must be known at compile time, which is not the case here. And it is allocated on the stack (in this context), which makes its maximum size usually too low for storing images. So no, it wouldn't improve anything ;)
I didn't know it needed a constant valute :o

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: texture.update(pixels), using std::vector of Uint8 instead of array
« Reply #6 on: July 17, 2014, 08:59:12 am »
My code won't compile if I attempt to use an std::vector.
sf::Texture::update() requires a pointer, you cannot just pass a std::vector.

Don't hesitate to consult a standard library reference like www.cppreference.com to see how you can get a pointer to the first element. &v[0] or v.data() in this case.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: texture.update(pixels), using std::vector of Uint8 instead of array
« Reply #7 on: July 17, 2014, 11:57:57 am »
Quote
I didn't know it needed a constant valute
A compile-time constant. Like any other template parameter.
Laurent Gomila - SFML developer