# Gradients on perspective projected Images..

There’s something I stumbled over while testing some gradients:

The gradients inherit the transform of the objects they are applied to. That makes perfect sense for me. In the spec this is only defined for the pathes, but ok - it makes sense to do the same for images as well.

However, the spec clearly states that paint transforms are affine only, and image transforms might be projective.

Now if I apply a gradient paint on a image drawn with perspective projection I don’t know what results to expect. The reference implementation draws something, but it’s hard to find out/guess how exactly the gradient should be drawn.

Question:

[ul]
[li] Do we have to mimic the behaviour of the reference implementation for this special case? After all it’s not defined in the spec.[/li][/xeh44fix]
[li] If so - how exactly should the gradient sampling work? Do we really have to sample the gradient projective?[/li][/
xeh44fix]
[li] If we have to sample the gradient affine, how should we get rid of the projective transform?[/*xeh44fix][/ul]
[/li]
Hope someone can help me with these issues. After all - there’s little to none traffic on this board…

Thanks,
Nils Pipenbrinck

Here’s a bit of code. draws a test image with radial gradient in perspective and affine mode.

``````void Gradient_WTF (void)
{
VGfloat stops[10] =
{
0, 0.8,0.2,0.1,1,
1, 0.1,0.2,0.8,1,
};

{
128,128,128,128,60,
};

VGfloat ImageMatrix[9] =
{
-0.4477,  0.8941,   0.0015,
-0.8941, -0.4477,  0.0018,
370,      140,      1,
};

// make checkerboard image:
VGImage img = vgCreateImage (VG_sL_8, 256, 256, VG_IMAGE_QUALITY_BETTER);
for (VGint y=0; y<256; y+=32)
for (VGint x=0; x<256; x+=32)
{
VGfloat white[4] = { 1,1,1,1       };
VGfloat gray[4]  = { 0.4,0.4,0.4,1 };
vgSetfv      (VG_CLEAR_COLOR, 4, (x^y)&32 ? white:gray);
vgClearImage (img, x,y,32,32);
}

// make paint:
VGPaint paint = vgCreatePaint();
vgSetPaint        (paint, VG_FILL_PATH);
vgSetParameterfv  (paint, VG_PAINT_COLOR_RAMP_STOPS, 10, stops);

// draw projective image:
vgSeti        (VG_IMAGE_MODE,  VG_DRAW_IMAGE_MULTIPLY);
vgSeti        (VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
vgDrawImage   (img);

// draw affine image:
vgTranslate    (400, 10);
vgDrawImage    (img);

vgDestroyImage (img);
vgDestroyPaint (paint);
}
``````

anyone?

Ok - if anyone is ever interested, this is what the reference implementation does:

Projective image matrices become unprojected before multiplication with the paint matrix. The unprojection works like this:

build 3 vectors that form a unit coordinate system in 2d:
vector v[3];
v[0] = vector(0,0);
v[1] = vector(1,0);
v[2] = vector(0,1);

transform these vectors by the image matrix (extend 2d vectors to homogenous 2d vectors by adding an implicit z=1). after transformation divide out the vectors x,y by z.

Then subtract projected origin from projected axis:

v[1] -= v[0];
v[2] -= v[0];

The output matrix directly built from these 3 vectors.

• translational part is equal to v[0],
• first column of upper 2x2 submatrix equals to v[1]
• second column of upper 2x2 submatrix equals to v[2]
• projective part becomes 0, 0, 1 (as usual for affine matrices)

I still scratch my head if this is fine with the standard.

OpenVG specifications do not clarify the correct behavior for perspective image matrixes coupled with a paint.

[quote=“muratmat”]

OpenVG specifications do not clarify the correct behavior for perspective image matrixes coupled with a paint.