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

Author Topic: RGBA to BGR  (Read 3728 times)

0 Members and 2 Guests are viewing this topic.

morrisb

  • Newbie
  • *
  • Posts: 10
    • View Profile
    • http://www.avpresentations.com
RGBA to BGR
« on: February 16, 2011, 04:12:59 pm »
I have some large textures (1920x1080) that are currently using BGR from video capture devices.  Rather than create new textures when I want to display a still image, I was hoping to re-use these textures in a similar way to how I'm doing it now with continuously updating video data, using glTexSubImage2D.

If I load an image from file using sfml, I'll have an RGBA set of pixel data as I understand it.  Can I simply change the glTexSubImage2D data type from BGR to RGBA and pass in the data pointer, or will there be a problem since the texture is currently using a different image data type?

On a related note, I know that I can do a screen grab directly using sfml, but there may be times when I want to grab an image from a video stream that is not being displayed on screen.  This data will be in BGR format as I mentioned above.  How would you suggest getting that to a format that can be saved using LoadFromPixels (or LoadFromMemory if that makes more sense)?

I should note that I'm still using glut for the opengl portions of the code.  I've only recently come across (the outstanding) SFML library and am slowly integrating it into the project.  Sorry if this confuses matters, it's a work in progress.

thanks,

morris

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
RGBA to BGR
« Reply #1 on: February 16, 2011, 07:38:12 pm »
Quote
Can I simply change the glTexSubImage2D data type from BGR to RGBA and pass in the data pointer, or will there be a problem since the texture is currently using a different image data type?

It's ok, OpenGL should perform the conversion.

Quote
This data will be in BGR format as I mentioned above. How would you suggest getting that to a format that can be saved using LoadFromPixels (or LoadFromMemory if that makes more sense)?

I suggest you convert it to RGBA manually and use LoadFromPixels.
Laurent Gomila - SFML developer

morrisb

  • Newbie
  • *
  • Posts: 10
    • View Profile
    • http://www.avpresentations.com
RGBA to BGR
« Reply #2 on: February 16, 2011, 08:26:04 pm »
Thanks Laurent.

Is there a better way than just making a new, larger, array and copying in 3 bytes in the new RGB order and then poking a 255 into the fourth spot with a for next loop?

morris

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
RGBA to BGR
« Reply #3 on: February 16, 2011, 08:32:53 pm »
Quote
Is there a better way than just making a new, larger, array and copying in 3 bytes in the new RGB order and then poking a 255 into the fourth spot with a for next loop?

Well, this conversion has to happen anyway, so this kind of code has to exist somewhere. And since there's nothing in SFML or OpenGL that does it for you... ;)
Laurent Gomila - SFML developer

morrisb

  • Newbie
  • *
  • Posts: 10
    • View Profile
    • http://www.avpresentations.com
RGBA to BGR
« Reply #4 on: February 16, 2011, 08:36:06 pm »
I guess that's why they call it manual ;)

thanks again

morrisb

  • Newbie
  • *
  • Posts: 10
    • View Profile
    • http://www.avpresentations.com
RGBA to BGR
« Reply #5 on: February 17, 2011, 04:03:12 pm »
I did a test on the time it takes to do this on a laptop that's about 3 years old - Core-2 (not core-2 duo) processor with 3 gig of ram and winXP and also on a desktop machine with a core i7 950, 3.2 gHz, 6 gig ram and win7 64bit.

With a 1024x768 image (actually just random data) the laptop took about 28ms to do the conversion from BGR to RGBA.  The desktop took about 6ms.

I've included the code I used below.  Comments are welcome.

Code: [Select]


void testConversion()
{

__int64 freqx, tStartx, tStopx;
unsigned long TimeDiffx;
unsigned long microsec;

// Get the frequency of the hi-res timer
QueryPerformanceFrequency((LARGE_INTEGER*)&freqx);

int w = 1024;
int h = 768;
int d = 3;  // rgb bit depth
int da = 4; // rgba bit depth

// this makes a 3 bit depth "image" of static
unsigned char* old_image = makeARandomByteArray(w, h, d);

//QueryPerformanceCounter((LARGE_INTEGER*)&tStartx);

int old_size = w * h * d;
int new_size = w * h * da;

//unsigned char r = 0;
//unsigned char g = 0;
//unsigned char b = 0;
unsigned char a = 255;

long counter = 0;

//QueryPerformanceCounter((LARGE_INTEGER*)&tStartx);
// this takes about 3 ms on my laptop
unsigned char *new_image = new unsigned char[new_size];

QueryPerformanceCounter((LARGE_INTEGER*)&tStartx);

// this loop takes about 31 ms on my laptop
// after dropping the assignment to r,g,b this dropped to 28 ms
        // on an i7 3.2 gHz 64bit Win7 machine this took 6 ms
for (int i = 0; i < old_size; i+=3)
{
//b = old_image[i];
//g = old_image[i + 1];
//r = old_image[i + 2];

// I saved about 3 ms (around 10% of total time) by not assigning to variable r, g & b (above)

new_image[counter] = old_image[i + 2]; // r
new_image[counter + 1] = old_image[i + 1]; // g
new_image[counter + 2] = old_image[i]; // b
new_image[counter + 3] = a;
counter += 4;
}

QueryPerformanceCounter((LARGE_INTEGER*)&tStopx);
microsec = (unsigned long)(((tStopx - tStartx) * 1000000) / freqx);
cout << "Conversion took " << microsec << " microseconds" << endl;

}


Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
RGBA to BGR
« Reply #6 on: February 17, 2011, 04:45:45 pm »
Don't you have optimized conversion functions in the video library that you use? For example, FFmpeg has one that is fast enough for real-time HD streaming.
Laurent Gomila - SFML developer

morrisb

  • Newbie
  • *
  • Posts: 10
    • View Profile
    • http://www.avpresentations.com
RGBA to BGR
« Reply #7 on: February 17, 2011, 05:27:50 pm »
I'm just using direcshow capture and spitting pointers to the video data out to opengl for display.

This seems to work fine as far as display goes.  With a fast machine I can display 2 1920x1080 video inputs with very little problem. My real enemy is latency, but initial tests seem to suggest it's generally under 10ms and so far has been no more than one frame.  As I refine the code I expect it to actually go up because I'm not doing much error checking right now.  Howver, as long as it stays below 30ms I should be fine.

I plan to look at the ffmpeg library, especially when I get to a port to linux, but my only experience with it so far was using a java wrapper for it on a project a couple years ago.

As far as the RGBA conversion goes, this would only be for capturing frames as a "still store", so the time isn't too big a deal if I do it in a thread.

If you have some suggestions on how ffmpeg might be used here, I'd love to get more details.

thanks,

morris

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
RGBA to BGR
« Reply #8 on: February 17, 2011, 07:02:52 pm »
Laurent Gomila - SFML developer