Printable Version of Topic
Click here to view this topic in its original format
Unofficial VirtualDub Support Forums > VirtualDub Filters and Filter Development > Filter - Separate Rgb Arrays


Posted by: mancanfly Mar 26 2003, 02:58 AM
Hello,

I am interested in developing a filter for Virtual Dub and would need some help from developers. Actually the filter has already been developed for images and I want to extend it to videos.

The following is written in 'filtsdk-1_05\Filtsdk\docs\crashcourse.html' (the filter SDK provided on VirtualDub website)-

"...This generally means that if you need to do any arithmetic on a pixel, such as averaging several together, you will need to either unpack the pixels into triplets to get more range or mask off bits to reduce precision. The latter generally leads to poor results, so you will want to unpack pixels."

To begin with, I would like to do a simple operation (in the same format and not through masking) as:

for(i=0;i<w;i++) //assign destination the modified RGBs.
{
for(j=0;j<h;j++)
{
dst[count++] = IpixelR[i][j];
dst[count++] = IpixelG[i][j]/2;
dst[count++] = IpixelB[i][j]/3;
}
}

and not as:

do {
w = fa->src.w;

do {
Pixel32 old_pixel, new_pixel;

old_pixel = *src++;

new_pixel = (old_pixel & 0xFF0000) + ((old_pixel & 0x00FF00)>>1) + 0x0000FF;

*dst++ = new_pixel;
} while(--w);

src = (Pixel32 *)((char *)src + fa->src.modulo);
dst = (Pixel32 *)((char *)dst + fa->dst.modulo);
} while(--h);

Can somebody suggest me the required changes in the example given in 'filtsdk-1_05\Filtsdk\docs\tutorial_maincode.html' to achieve this?

waiting for a reply.[B][/B]

Posted by: fccHandler Mar 26 2003, 03:27 AM
I don't really understand your question, but I think what the SDK is saying is that it's better to split the pixel into its R/G/B components and do the math on the components, rather than on the pixel as a whole:

CODE
int r,g,b;

/* Unpack red, green, and blue */
r = (old_pixel >> 16) & 0xFF;
g = (old_pixel >> 8) & 0xFF;
b = old_pixel & 0xFF;

/* Do some math with r, g, and b... */
g = g / 2;
b = b / 3;

/* Clamp the results if necessary */
if (r < 0) r = 0; else if (r > 255) r = 255;
if (g < 0) g = 0; else if (g > 255) g = 255;
if (b < 0) b = 0; else if (b > 255) b = 255;

/* Pack into new pixel */
new_pixel = (r << 16) + (g << 8) + b;


Does this help you at all?

Posted by: mancanfly Mar 28 2003, 02:41 AM
actually what i am interested in is processing a 2D array (of the form PixelR[i][j], PixelG[i][j], PixelB[i][j]) of different pixels instead of handling individual RGBs (in a scanline).

How can I store the RGB components of the frame in a 2D array? Consider the 2D array being created as follows:
_______________________________________________
//Allocation of R,G,B components of Input Image begins...
float **IpixelR, **IpixelG, **IpixelB;

IpixelR = (float **)malloc((fa->src.w)*sizeof(float *));
IpixelG = (float **)malloc((fa->src.w)*sizeof(float *));
IpixelB = (float **)malloc((fa->src.w)*sizeof(float *));

for(j=0;j<(fa->src.h);j++)
{
IpixelR[j] = (float *)malloc((fa->src.w)*sizeof(float));
IpixelG[j] = (float *)malloc((fa->src.w)*sizeof(float));
IpixelB[j] = (float *)malloc((fa->src.w)*sizeof(float));
}
_______________________________________________

And consider what you suggested in the following loop:

h = fa->src.h;

for (i=h; i>0; i--)
{
w = fa->src.w;
for (j=w; j>0; j--)
{
Pixel32 old_pixel, new_pixel;

old_pixel = *src++;

int r,g,b, l;

//Unpack red, green, and blue
//IpixelR[j][i] =
r = (old_pixel >> 16) & 0xFF;
//IpixelG[j][i] =
g = (old_pixel >> 8) & 0xFF;
//IpixelB[j][i] =
b = old_pixel & 0xFF;

//Do some math with r, g, and b...
g = g / 2;
b = b / 3;

//Clamp the results if necessary
if (r < 0) r = 0; else if (r > 255) r = 255;
if (g < 0) g = 0; else if (g > 255) g = 255;
if (b < 0) b = 0; else if (b > 255) b = 255;

//Pack into new pixel
new_pixel = (r << 16) + (g << 8) + b;

*dst++ = new_pixel;
}

src = (Pixel32 *)((char *)src + fa->src.modulo);
dst = (Pixel32 *)((char *)dst + fa->dst.modulo);
}

thanks for you earlier reply!

Posted by: fccHandler Mar 28 2003, 03:38 AM
I still don't completely understand, but it sounds like what you want is a planar image of floats, however, VirtualDub's internal storage is packed bytes. It's still possible to convert from one to the other for your processing, but it won't be terribly efficient:

CODE
// Allocate your arrays
// ...

// Convert source to planar format
int i,j;
Pixel32 *src = fa->src.data;
for (j = 0; j < fa->src.h; j++) {
   for (i = 0; i < fa->src.w; i++) {
       Pixel32 p = *src++;
       IPixelR[i][j] = (p >> 16) & 0xFF;
       IPixelG[i][j] = (p >> 8) & 0xFF;
       IPixelB[i][j] = p & 0xFF;
   }
   src = (Pixel32 *)((char)src + fa->src.modulo);
}

// Do some stuff with the planar image
// ...

// Write to destination in packed format
int r,g,b;
Pixel32 *dst = fa->dst.data;
for (j = 0; j < fa->dst.h; j++) {
   for (i = 0; i < fa->dst.w; i++) {
       r = (int)IPixelR[i][j];
       g = (int)IPixelG[i][j];
       b = (int)IPixelB[i][j];
       if (r < 0) r = 0; else if (r > 255) r = 255;
       if (g < 0) g = 0; else if (g > 255) g = 255;
       if (b < 0) b = 0; else if (b > 255) b = 255;
       *dst++ = (Pixel32)((r << 16) + (g << 8) + b);
   }
   dst = (Pixel32 *)((char)dst + fa->dst.modulo);
}

// Deallocate your arrays
// ...


I didn't test the code but it should work (if I haven't make any typos). tongue.gif
Also, it's better to alloc/dealloc in StartProc/EndProc.


Posted by: mancanfly Mar 29 2003, 07:26 PM
This thing is really confusing me.. Now where is the mistake?? On debugging I get error in the line where comments are in UPPERCASE (where I assign the src values to IpixelR[i][j], IpixelG[i][j], IpixelB[i][j].
________________________________________________________

int i,j, count;
//Allocation of R,G,B components of Input Image begins...
float **IpixelR, **IpixelG, **IpixelB;

IpixelR = (float **)malloc((fa->src.h)*sizeof(float *));
IpixelG = (float **)malloc((fa->src.h)*sizeof(float *));
IpixelB = (float **)malloc((fa->src.h)*sizeof(float *));

for(j=0;j<(fa->src.h);j++)
{
IpixelR[j] = (float *)malloc((fa->src.w)*sizeof(float));
IpixelG[j] = (float *)malloc((fa->src.w)*sizeof(float));
IpixelB[j] = (float *)malloc((fa->src.w)*sizeof(float));
}

// Convert source to planar format
for (j = 0; j < fa->src.h; j++)
{
for (i = 0; i < fa->src.w; i++)
{
Pixel32 p = *src++;
IpixelR[i][j] = (p >> 16) & 0xFF; //ERROR ON DEBUGGING
IpixelG[i][j] = (p >> 8) & 0xFF;
IpixelB[i][j] = p & 0xFF;
}
src = (Pixel32 *)((char)src + fa->src.modulo);
}

// Write to destination in packed format
int r,g,b;
for (j = 0; j < fa->src.h; j++)
{
for (i = 0; i < fa->src.w; i++)
{
r = (int)IpixelR[i][j];
g = (int)IpixelG[i][j];
b = (int)IpixelB[i][j];
if (r < 0) r = 0; else if (r > 255) r = 255;
if (g < 0) g = 0; else if (g > 255) g = 255;
if (b < 0) b = 0; else if (b > 255) b = 255;
*dst++ = (Pixel32)((r << 16) + (g << 8) +b);
}
dst = (Pixel32 *)((char)dst + fa->dst.modulo);
}

// Deallocate arrays
// ...
_____________________________________

The error message says that:
AVIAudioPreviewOutputStream: flushing...
First-chance exception in VirtualDub.exe: 0xC0000005: Access Violation.

Posted by: phaeron Mar 29 2003, 08:42 PM
Your arrays are allocated [y][x] but you are accessing them [x][y].

Posted by: fccHandler Mar 29 2003, 08:58 PM
ph34r.gif Doh! I didn't look closely enough at your allocation strategy, sorry. (Thanks phaeron!)

It should be:
CODE
//Allocation of R,G,B components of Input Image begins...
float **IpixelR, **IpixelG, **IpixelB;

IpixelR = (float **)malloc((fa->src.w)*sizeof(float *));
IpixelG = (float **)malloc((fa->src.w)*sizeof(float *));
IpixelB = (float **)malloc((fa->src.w)*sizeof(float *));

for(i=0;i<(fa->src.w);i++) {
   IpixelR[i] = (float *)malloc((fa->src.h)*sizeof(float));
   IpixelG[i] = (float *)malloc((fa->src.h)*sizeof(float));
   IpixelB[i] = (float *)malloc((fa->src.h)*sizeof(float));
}


Don't forget to deallocate:
CODE
//Deallocate arrays...
for(i=(fa->src.w)-1;i>=0;i--) {
   free(IpixelB[i]);
   free(IpixelG[i]);
   free(IpixelR[i]);
}
free(IpixelB);
free(IpixelG);
free(IpixelR);


smile.gif

Posted by: mancanfly Mar 30 2003, 09:05 PM
Seems FOURCC is not with me! Can you just create a .cpp file (say, test_filter.cpp) and test the following code for me? Now the error line is the one where the src pointer is being equated to the Pixel32 variable 'p'.
I truly appreciate your patience. Though it has to be something trivial, but this step has become so critical that I simply can't proceed with my work any further without it getting completed. Actually I intend to do some matrix operations on the frame array hence obtained.
_____________________________________________
#include <stdio.h>

#include "filter.h"
#include "filters.h"
#include "f_convolute.h"
#include "ScriptInterpreter.h"
#include "ScriptValue.h"
#include "ScriptError.h"


int tutorialRunProc(const FilterActivation *fa, const FilterFunctions *ff)
{
PixDim w, h;
Pixel32 *src, *dst;

src = (Pixel32 *)fa->src.data;
dst = (Pixel32 *)fa->dst.data;

int i,j, count;
//Allocation of R,G,B components of Input Image begins...
float **IpixelR, **IpixelG, **IpixelB;

IpixelR = (float **)malloc((fa->src.w)*sizeof(float *));
IpixelG = (float **)malloc((fa->src.w)*sizeof(float *));
IpixelB = (float **)malloc((fa->src.w)*sizeof(float *));

for(j=0;j<(fa->src.w);j++)
{
IpixelR[j] = (float *)malloc((fa->src.h)*sizeof(float));
IpixelG[j] = (float *)malloc((fa->src.h)*sizeof(float));
IpixelB[j] = (float *)malloc((fa->src.h)*sizeof(float));
}

///////////
// Convert source to planar format
for (j = 0; j < fa->src.h; j++)
{
for (i = 0; i < fa->src.w; i++)
{
Pixel32 p = (Pixel32) *src++; // <-- ERROR ON DEBUGGING
IpixelR[i][j] = (p >> 16) & 0xFF;
IpixelG[i][j] = (p >> 8) & 0xFF;
IpixelB[i][j] = p & 0xFF;
}
src = (Pixel32 *)((char)src + fa->src.modulo);
}

///////////

//
// Do some stuff with the planar image
//

///////////
// Write to destination in packed format
int r,g,b;
for (j = 0; j < fa->src.h; j++)
{
for (i = 0; i < fa->src.w; i++)
{
r = (int)IpixelR[i][j];
g = (int)IpixelG[i][j]/2;
b = (int)IpixelB[i][j]/3;
if (r < 0) r = 0; else if (r > 255) r = 255;
if (g < 0) g = 0; else if (g > 255) g = 255;
if (b < 0) b = 0; else if (b > 255) b = 255;
*dst++ = (Pixel32)((r << 16) + (g << 8) + b);
}
dst = (Pixel32 *)((char)dst + fa->dst.modulo);
}

//free allocated memory
for(i=(fa->src.w)-1;i>=0;i--)
{
free(IpixelR[i]);
free(IpixelG[i]);
free(IpixelB[i]);
}
free(IpixelR);
free(IpixelG);
free(IpixelB);

return 0;
}

struct FilterDefinition filterDef_tutorial = {

NULL, NULL, NULL, // next, prev, module
"tutorial", // name
"This is a test filter.",
// desc
"test", // maker
NULL, // private_data
0, // inst_data_size

NULL, // initProc
NULL, // deinitProc
tutorialRunProc, // runProc
NULL, // paramProc
NULL, // configProc
NULL, // stringProc
NULL, // startProc
NULL, // endProc

NULL, // script_obj
NULL, // fssProc

};
_____________________________________________


Posted by: phaeron Mar 30 2003, 09:53 PM
src = (Pixel32 *)((char)src + fa->src.modulo);

That should be (char *).

Posted by: fccHandler Mar 31 2003, 05:50 AM
mad.gif That darn typo devil strikes again!

For sure, next time I will test any code before I post it. rolleyes.gif

Powered by Invision Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)