PDA

View Full Version : very strange problem in a plug-in i wrote


E-Male
20th January 2005, 23:59
i wrote a plug-in that creates gradient masks
here you can find it
http://forum.doom9.org/showthread.php?s=&threadid=87791&perpage=20&pagenumber=6

the problem is that c has no effect on odd frames in mode 1, 2 & 3, even frames are fine

i'll post you the part of the code that should be the problem [=no effect in odd frames] (and i got no idea why!!)
as well as the whole code


switch (d) {
case 1:
break;
case 2:
a=(src_width-1)-a;
break;
case 3:
a=(src_width-1)-a;
b=(src_height-1)-b;
break;
case 4:
b=(src_height-1)-b;
break;
}



#include "stdafx.h"
#include "avisynth.h"

class maskmaker : public GenericVideoFilter {
int m, d;
float a, b, c;

public:
maskmaker(PClip _child, int _m, int _d, float _a, float _b, float _c, IScriptEnvironment* env);

PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
};

maskmaker::maskmaker(PClip _child, int _m, int _d, float _a, float _b, float _c, IScriptEnvironment* env) :
GenericVideoFilter(_child), m(_m), d(_d), a(_a), b(_b), c(_c) {

if (m<1)
env->ThrowError("m<1");
if (m>4)
env->ThrowError("m>4");
if (d<1)
env->ThrowError("d<1");
if (d>4)
env->ThrowError("d>4");
}

PVideoFrame __stdcall maskmaker::GetFrame(int n, IScriptEnvironment* env) {

PVideoFrame src = child->GetFrame(n, env);
PVideoFrame dst = env->NewVideoFrame(vi);
const unsigned char* srcp = src->GetReadPtr();
unsigned char* dstp = dst->GetWritePtr();
const int dst_pitch = dst->GetPitch();
const int dst_width = dst->GetRowSize();
const int dst_height = dst->GetHeight();
const int src_pitch = src->GetPitch();
const int src_width = src->GetRowSize();
const int src_height = src->GetHeight();

float res;

if (m!=4)
switch (d) {
case 1:
break;
case 2:
a=(src_width-1)-a;
break;
case 3:
a=(src_width-1)-a;
b=(src_height-1)-b;
break;
case 4:
b=(src_height-1)-b;
break;
}

for (int h=0; h < src_height;h++) {
for (int w = 0; w < src_width; w++)
{

switch (m) {
case 1:
res = ((w-a)*(w-a))+((h-b)*(h-b));
res/=c;
break;
case 2:
if(abs(w-a)>abs(h-b))
res=abs(w-a);
else
res=abs(h-b);
res/=c;
break;
case 3:
res = abs(w-a)+abs(h-b);
res/=c;
break;
case 4:
if ( d==4)
res = abs(w-a);
if ( d==2)
res = abs(w-((src_width-1)-a));
if ( d==1)
res = abs(h-a);
if ( d==3)
res = abs(h-((src_height-1)-a));
res/=b;
break;
}




if (res < 0)
res = 0;
if (res > 255)
res = 255;
*(dstp + w) = res;

}

srcp = srcp + src_pitch;

dstp = dstp + dst_pitch;
}

const int dst_pitchUV = dst->GetPitch(PLANAR_U);
const int dst_widthUV = dst->GetRowSize(PLANAR_U);
const int dst_heightUV = dst->GetHeight(PLANAR_U);
const int src_pitchUV = src->GetPitch(PLANAR_U);
const int src_widthUV = src->GetRowSize(PLANAR_U);
const int src_heightUV = src->GetHeight(PLANAR_U);

srcp = src->GetReadPtr(PLANAR_U);

dstp = dst->GetWritePtr(PLANAR_U);

for (int h=0; h < src_heightUV;h++) {

for (int w = 0; w < src_widthUV; w++)
{

*(dstp + w) = 128;

}

srcp = srcp + src_pitchUV;

dstp = dstp + dst_pitchUV;
}

srcp = src->GetReadPtr(PLANAR_V);
dstp = dst->GetWritePtr(PLANAR_V);

for (int h=0; h < src_heightUV;h++) {

for (int w = 0; w < src_widthUV; w++)
{

*(dstp + w) = 128;

}

srcp = srcp + src_pitchUV;

dstp = dstp + dst_pitchUV;
}

return dst;
}

AVSValue __cdecl Create_maskmaker(AVSValue args, void* user_data, IScriptEnvironment* env) {
return new maskmaker(args[0].AsClip(),args[1].AsInt(1),args[2].AsInt(1),args[3].AsFloat(1),args[4].AsFloat(1),args[5].AsFloat(1),env);

}

extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* env) {
env->AddFunction("maskmaker", "c[m]i[d]i[a]f[b]f[c]f", Create_maskmaker, 0);

return "maskmaker";
}

neuron2
21st January 2005, 00:08
It's considered bad form to not comment your code.

At least tell us the syntax of the filter so we know what the variables are for.

E-Male
21st January 2005, 00:26
sorry, i thought the link was enough

from the original thread:
Originally posted by E-Male
i finished a little plug-in that can create such masks directly in avisynth

http://e-rels.dyndns.org/downloads/maskmaker.dll

maskmaker(m, c, x, y, r)

m = mode (int)
1: circle ("radial gradient" 2nd example)
2: square
3: square diagonal
4: line ("gradient mask" 1st example)

c = center corner/side (int)
1: (top) left
2-4 clockwise respectively

x&y, coordinates (float)
center coordinates of the gradient / line coordinate (no y then)
the center can be outside the picture

r, "radius" (float)
"size" of the gradient

the 2 examples in the last view posts should look like this:
maskmaker(4,3,-170,2.8)
maskmaker(1,3,0,0,500)

please post feedback (bugs; suggestion, maybe for new modes, ...)


EDIT: BUG FOUND: ON M = 1-3 ONLY USE C = 1 (adjust x, y accordingly)

(yv12 only)

the examples should give that:
http://img116.exs.cx/img116/9352/gradient25qw.png
http://img40.exs.cx/img40/5695/gradient44gt.jpg

neuron2
21st January 2005, 00:53
Originally posted by E-Male
sorry, i thought the link was enough Yeah, seven pages worth! I'll have a look.

E-Male
21st January 2005, 00:58
i linked to the right page
showing what it's about, the filters release and the bug found

neuron2
21st January 2005, 03:34
OK, I know why it is jumping back and forth. I don't understand fully what you are trying to do (no comments!), but if you do this it makes more sense. Calculate the new a and b values just once so they don't jump back and forth:

PVideoFrame __stdcall maskmaker::GetFrame(int n, IScriptEnvironment* env) {

PVideoFrame src = child->GetFrame(n, env);
PVideoFrame dst = env->NewVideoFrame(vi);
const unsigned char* srcp = src->GetReadPtr();
unsigned char* dstp = dst->GetWritePtr();
const int dst_pitch = dst->GetPitch();
const int dst_width = dst->GetRowSize();
const int dst_height = dst->GetHeight();
const int src_pitch = src->GetPitch();
const int src_width = src->GetRowSize();
const int src_height = src->GetHeight();
static int first_time = 1;

float res;

if (first_time && m!=4)
switch (d) {
case 1:
break;
case 2:
a=(src_width-1)-a;
break;
case 3:
a=(src_width-1)-a;
b=(src_height-1)-b;
break;
case 4:
b=(src_height-1)-b;
break;
}
first_time = 0;

E-Male
21st January 2005, 04:25
ah, i see
so avisynth doesn't re-read the prameters on every frame
(that's what i thought it does)

i fixed it by no longer changing a and b
but putting the right value into new variabls

neuron2
21st January 2005, 04:55
Originally posted by E-Male
ah, i see
so avisynth doesn't re-read the prameters on every frame
(that's what i thought it does) Your filter class's variables are initialized in the class constructor [all that x(_x) stuff!], which of course runs only once when the class is instantiated.

i fixed it by no longer changing a and b
but putting the right value into new variables That's the sensible way.

EDIT: Forgot to say: It's a nice filter -- great work!

E-Male
21st January 2005, 05:18
thx for the kind words
and the help of course