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

Author Topic: Most efficient way to draw a picture pixel by pixel?  (Read 42162 times)

0 Members and 1 Guest are viewing this topic.

sam

  • Newbie
  • *
  • Posts: 5
    • View Profile
Most efficient way to draw a picture pixel by pixel?
« on: November 12, 2010, 06:17:04 pm »
Hello,

in case I have a whole lot(!) of coordinates in an two-dimensional array, what would be the most efficient way to draw them on my window?

With GDI+ I used the LockBits-method like so (just in reverse). Is there anything similar in SFML?

Thanks in advance!  :oops:

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Most efficient way to draw a picture pixel by pixel?
« Reply #1 on: November 12, 2010, 06:47:34 pm »
Use your own array of pixels, and pass it to sf::Image when it's completely filled and ready to be displayed. That's the most efficient way of doing it, since all pixels will be transfered to the GPU at once.
Laurent Gomila - SFML developer

sam

  • Newbie
  • *
  • Posts: 5
    • View Profile
Most efficient way to draw a picture pixel by pixel?
« Reply #2 on: November 12, 2010, 07:07:22 pm »
Quote from: "Laurent"
Use your own array of pixels, and pass it to sf::Image when it's completely filled and ready to be displayed. That's the most efficient way of doing it, since all pixels will be transfered to the GPU at once.
Thank you, but how does the array have to look like?  :?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Most efficient way to draw a picture pixel by pixel?
« Reply #3 on: November 12, 2010, 11:34:27 pm »
It must be an array of sf::Uint8, with size Width * Height * 4. Components are stored in RGBA order.
Laurent Gomila - SFML developer

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Most efficient way to draw a picture pixel by pixel?
« Reply #4 on: November 13, 2010, 12:02:33 am »
Quote from: "Laurent"
It must be an array of sf::Uint8, with size Width * Height * 4. Components are stored in RGBA order.


Is this written somewhere in the documentation? If not that would be quite handy.
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

sam

  • Newbie
  • *
  • Posts: 5
    • View Profile
Most efficient way to draw a picture pixel by pixel?
« Reply #5 on: November 13, 2010, 12:57:37 am »
I don't get it (stupid nonsense example of what I tried follows)  :?

Code: [Select]
sf::RenderWindow window(sf::VideoMode(800, 600, 32), "Test");
sf::Image        image(800, 600, sf::Color(0, 0, 0));
sf::Sprite       sprite;
sf::Uint8        *pixels  = new sf::Uint8[800 * 600 * 4];
// ...
while(window.IsOpened())
{
  // ...
  for(int x = 0; x < 800; x++)
  {
    for(int y = 0; y < 600; y++)
    {
      pixels[y * x]     = 255; // R?
      pixels[y * x + 1] = 255; // G?
      pixels[y * x + 2] = 255; // B?
      pixels[y * x + 3] = 255; // A?
    }
  }
  // ...
  image.LoadFromPixels(800, 600, pixels);
  sprite.SetImage(image);
  window.Draw(sprite);
  window.Display();
}
// ...
delete [] pixels;
// ...


Result:

Clairvoire

  • Newbie
  • *
  • Posts: 29
    • AOL Instant Messenger - Clairvoire
    • View Profile
    • http://clairvoire.deviantart.com
Most efficient way to draw a picture pixel by pixel?
« Reply #6 on: November 13, 2010, 09:04:37 am »
In the code, you didn't account for x and y needing to move 4 bytes, since every pixel is 4 bytes, but in your array, it's going through it byte by byte.  

Code: [Select]
for(int x = 0; x < 800; x++)
  {
    for(int y = 0; y < 600; y++)
    {
      pixels[(y * x)*4]     = 255; // R?
      pixels[(y * x)*4 + 1] = 255; // G?
      pixels[(y * x)*4+ 2] = 255; // B?
      pixels[(y * x)*4 + 3] = 255; // A?
    }
  }


Made the minor adjustments.  This may be more favourable

Xorlium

  • Jr. Member
  • **
  • Posts: 84
    • View Profile
Most efficient way to draw a picture pixel by pixel?
« Reply #7 on: November 13, 2010, 10:31:16 am »
Check your math there :)

For example, if x = 2, y =17 and x=17, y =2, you'd be getting always the same colour, but you clearly don't want that.

What you actually want is something like this:

Code: [Select]

for(int x = 0; x < 800; x++)
{
    for(int y = 0; y < 600; y++)
    {
      pixels[4*(x * 600+y)]      = 255; // R?
      pixels[4*(x * 600+y)+1] = 255; // G?
      pixels[4*(x * 600+y)+2] = 255; // B?
      pixels[4*(x * 600+y)+3] = 255; // A?
    }
}


or you might try with y*800+x, I don't remember how sfml expects it right now (it's late!)

Xorlium

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Most efficient way to draw a picture pixel by pixel?
« Reply #8 on: November 13, 2010, 11:13:53 am »
Quote
Is this written somewhere in the documentation?

It is written in the documentation of LoadFromPixels, I think. If not, it is at least in SFML 2.
Laurent Gomila - SFML developer

sam

  • Newbie
  • *
  • Posts: 5
    • View Profile
Most efficient way to draw a picture pixel by pixel?
« Reply #9 on: November 13, 2010, 03:16:35 pm »
Quote from: "Clairvoire"
In the code, you didn't account for x and y needing to move 4 bytes, since every pixel is 4 bytes, but in your array, it's going through it byte by byte.  

Code: [Select]
for(int x = 0; x < 800; x++)
  {
    for(int y = 0; y < 600; y++)
    {
      pixels[(y * x)*4]     = 255; // R?
      pixels[(y * x)*4 + 1] = 255; // G?
      pixels[(y * x)*4+ 2] = 255; // B?
      pixels[(y * x)*4 + 3] = 255; // A?
    }
  }


Made the minor adjustments.  This may be more favourable
Doh! I guess I was tired yesterday.  :oops:

The example's source code now looks like this:
Code: [Select]
#include <SFML\Graphics.hpp>
#include <SFML\Window.hpp>

int main(int argc, char *argv[])
{
    sf::RenderWindow window(sf::VideoMode(800, 600, 32), "Test");
    sf::Image        image(800, 600, sf::Color(0, 0, 0));
    sf::Sprite       sprite;
    sf::Uint8        *pixels  = new sf::Uint8[800 * 600 * 4];

    while(window.IsOpened())
    {
        for(int x = 0; x < 800; x++)
        {
            for(int y = 0; y < 600; y++)
            {
                pixels[(y * x) * 4]     = 255; // R?
                pixels[(y * x) * 4 + 1] = 255; // G?
                pixels[(y * x) * 4 + 2] = 255; // B?
                pixels[(y * x) * 4 + 3] = 255; // A?
            }
        }

        image.LoadFromPixels(800, 600, pixels);
        sprite.SetImage(image);
        window.Draw(sprite);
        window.Display();
    }

    delete [] pixels;
    return 0;
}

And this is the result:


I kind of expected it to be all white now... :?



Quote from: "Xorlium"
For example, if x = 2, y =17 and x=17, y =2, you'd be getting always the same colour, but you clearly don't want that.
No, it's right. I wanted to see if I can get everything to be painted white before I make the next big step (adding the array). That's why I wrote
Quote from: "sam"
(stupid nonsense example of what I tried follows)
But I even failed this simple test.  :?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Most efficient way to draw a picture pixel by pixel?
« Reply #10 on: November 13, 2010, 03:39:51 pm »
It's not (x * y * 4), but (x + y * 800) * 4.

Try your formulas with simple numbers like 0, 1, 2 ... you clearly see that the result is wrong ;)

PS: that was a nice effect :lol:
Laurent Gomila - SFML developer

sam

  • Newbie
  • *
  • Posts: 5
    • View Profile
Most efficient way to draw a picture pixel by pixel?
« Reply #11 on: November 13, 2010, 05:28:54 pm »
Quote from: "Laurent"
It's not (x * y * 4), but (x + y * 800) * 4.

Try your formulas with simple numbers like 0, 1, 2 ... you clearly see that the result is wrong ;)

PS: that was a nice effect :lol:
Where does the 800 come from? Is it the width? So it's (x + y * width) * 4?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Most efficient way to draw a picture pixel by pixel?
« Reply #12 on: November 13, 2010, 06:08:19 pm »
Yes it is.
Laurent Gomila - SFML developer

Spodi

  • Full Member
  • ***
  • Posts: 150
    • View Profile
    • http://www.netgore.com/
Most efficient way to draw a picture pixel by pixel?
« Reply #13 on: November 13, 2010, 07:00:42 pm »
Think of it this way: row one (top-left corner to top-right corner) is index 0 to Width. To get to row two (right below row one), you have to add the number of pixels in row one, which is = Width. So (y * Width) is your row offset, and x is your column offset.

Spidyy

  • Sr. Member
  • ****
  • Posts: 493
    • View Profile
Most efficient way to draw a picture pixel by pixel?
« Reply #14 on: November 13, 2010, 07:28:42 pm »
Errors can lead to some nice and artistic effects