• Advertisement
Sign in to follow this  

[MDX] Color space conversion using a Pixel Shader

This topic is 4211 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey All, I'm currently using the following code to convert the contents of a 32bit RGB surface to a YUY2 surface.
        private void CopyRGBtoYUV(DirectDraw.Surface sourceSurface, DirectDraw.Surface destSurface)
        {
            try
            {
                DirectDraw.LockedData src = sourceSurface.Lock(DirectDraw.LockFlags.SurfaceMemoryPointer | DirectDraw.LockFlags.Wait);
                DirectDraw.LockedData dest = destSurface.Lock(DirectDraw.LockFlags.SurfaceMemoryPointer | DirectDraw.LockFlags.Wait);

                byte[] rgb = new byte[src.Height * src.Pitch];
                src.Data.Read(rgb, 0, src.Height * src.Pitch);
                byte[] uyvy = new byte[dest.Pitch * dest.Height];

                for (int h = 0; h < src.Height; h += 1)
                {
                    for (int w = 0; w < src.Width; w += 2)
                    {
                        byte r, g, b;
                        int off = h * src.Pitch + w * 4;

                        b = (byte)(rgb[off + 0]);
                        g = (byte)(rgb[off + 1]);
                        r = (byte)(rgb[off + 2]);

                        byte Y0 = (byte)(((66 * r + 129 * g + 25 * b + 128) >> 8) + 16);
                        byte U = (byte)(((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128);
                        byte V = (byte)(((112 * r - 94 * g - 18 * b + 128) >> 8) + 128);

                        b = (byte)(rgb[off + 4]);
                        g = (byte)(rgb[off + 5]);
                        r = (byte)(rgb[off + 6]);

                        byte Y1 = (byte)(((66 * r + 129 * g + 25 * b + 128) >> 8) + 16);

                        uyvy[h * dest.Pitch + w * 2] = Y0;
                        uyvy[h * dest.Pitch + w * 2 + 1] = U;
                        uyvy[h * dest.Pitch + w * 2 + 2] = Y1;
                        uyvy[h * dest.Pitch + w * 2 + 3] = V;
                    }
                }

                dest.Data.Write(uyvy);
            }
            finally
            {
                sourceSurface.Unlock();
                destSurface.Unlock();
            }
        }
When this code is running on a surface that is 230 x 300, it's chewing approximately 8% of my cpu. I'm trying to work out how to make it run faster and more efficiently. After doing a bit of googling there are several articles i've found that suggest using a pixel shader to do the conversion from RGB -> YUV, but, they just suggest it with no more info. Does anyone know how this might be accomplished? Or if not, where i might some info on accomplishing this? Cheers :)

Share this post


Link to post
Share on other sites
Advertisement
I don't know how to accomplish this with DirectDraw, but with Direct3D it's fairly easy to do and very efficient. You'd basically need to set up rendering with the RenderToSurface helper class, onto which you render a pretransformed quad textured with the input surface. Then you can write a pixelshader for this rendering pass to apply the desired color space conversion. I don't have any sample code around atm, but if you want to use Direct3D, you can check out the SDK documentation on the RenderToSurface, CustomVertex.TransformedTextured and Effect classes.

On a recent videocard texture operations like this should run in a fraction of a second, so it would definately be worth the effort. Sorry if my spelling is even worse than usual, my keyboard battery is empty :p

Share this post


Link to post
Share on other sites
Cool, thanks :)

Never used Direct3d before so i spose this is a good time to learn :)

Is what you're suggesting relatively complicated or relatively easy? Just trying to guage how much time i'm going to need to put in so i can arrange my work schedule around it :)

Share this post


Link to post
Share on other sites
After several days of reading and playing, i've officially thrown this one in the "too-bloody-hard" basket for me.

Thanks to those that replied for you help :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement