# Thread: Render an image into a given quadrilateral

1. Member
Join Date
Aug 2011
Posts
9
Rep Power
0

## Render an image into a given quadrilateral

I say quadrilateral and not rectangle because I need the image to be rendered inside of a quadrilateral which does not consist of only right angles. I would like to render an image inside of a quadrilateral defined by four Points. I'm aware I can use Graphics::clip but such a function does not stretch or scale the image. Thanks :)

2. What does "render" an image mean? Do you mean draw it on a Graphics context?

3. Senior Member
Join Date
Jul 2009
Posts
1,236
Rep Power
9

4. Member
Join Date
Aug 2011
Posts
9
Rep Power
0
Yes I would like it to be drawn onto a graphics context.

I have looked at the shear and skew of images but I can't figure out how I would use it so that all corners were matched to one of the four points.

I.e if I have four points, (0,0) (0,1) (1,1) (1, 0) I would expect the image to be stretched(or shrunk) into a 1 by 1 square. I have done this before with a 3D graphics library quite easily by defining two triangles that form the desired quad, map the texture coordinates to their respective vertices and then have the sharder do the rest. However, I don't want to instroduce an entire 3D graphics library for a simple 2d operation.

Also I don't think I would be able to draw a Trapezoid using shear.

Thanks :)
Last edited by JeremyWilms; 08-20-2011 at 03:09 AM.

5. Given a normal rectangular image how would its pixels be mapped into the quadrilateral? Would all the pixels go somewhere in the new image, perhaps with some distortion or would some of them be cropped?

6. Member
Join Date
Aug 2011
Posts
9
Rep Power
0
I have done this before with a 3D graphics library quite easily by defining two triangles that form the desired quad, map the texture coordinates to their respective vertices and then have the sharder do the rest. However, I don't want to instroduce an entire 3D graphics library for a simple 2d operation.
I supposed I'd expect something similar to what the pixel shader does to a texture mapped over a quadrilateral surface.

7. Not familiar with pixel shader or texture mapping.

8. Moderator
Join Date
Feb 2009
Location
New Zealand
Posts
4,712
Rep Power
15
I have looked at the shear and skew of images
What do you mean by "skew" - something other than "shear"? (Genuine question: it's a long time since I studied any geometry!)

Generally a combination of rotation, enlargement, shear and translation (a so-called affine transformation) will take you from any parallelogram to any other. And there are standard Java methods for that. But you seem to want more than that: you want to transform to a general quadralateral that may or may not be a parallelogram.

I have done this before with a 3D graphics library quite easily by defining two triangles that form the desired quad
This seems doable with a pair of affine transformations. The point is that *any* triangle can be seen as half a parallelogram and can, therefore, be mapped via an affine transform to any other triangle.

I'm not sure, though, that such a transform would be the "prettiest" because a straight line in the source crossing from one of the triangles to the other might well end up "kinked" in the destination. Since you are going from a rectangle (parallel sides) to a thing whose sides are not parallel it looks like you want some sort of projective transformation. A brief google turned up this stackoverflow discussion. Maybe it'll help.
Last edited by pbrockway2; 08-20-2011 at 03:48 AM.

9. Take a look at Java Advanced Imaging's PerspectiveTransform, or if you're free to use JavaFX 2.0 (still in beta) it also has a PerspectiveTransform.

A perspective transformation is capable of mapping an arbitrary quadrilateral into another arbitrary quadrilateral, while preserving the straightness of lines.
db

10. Member
Join Date
Aug 2011
Posts
9
Rep Power
0
Thank you pbrockway2, the images I am transforming are rather small and so, at least I hope, it will not be too noticable.

@DarrylBurke: Thats exactly what I am looking for :) Thanks.

11. Member
Join Date
Aug 2011
Posts
9
Rep Power
0
I can't figure out how to apply a PerspectiveTransform to a graphics object or Image. Do you mind pointing me to a particular example? Thanks.

12. Have you gone through the guide? There's a section on Mapping a Quadrilateral.

db

13. Member
Join Date
Aug 2011
Posts
9
Rep Power
0
Hmm, so it seems I would have to reconstruct the image in another buffer; copying all the pixel data and transforming its position by going via the PerspetiveTransform. Thats doable I guess, are there any other solutions though? It just seems like a lot of post-processing inside of the CPU.

Thanks.

14. Moderator
Join Date
Feb 2009
Location
New Zealand
Posts
4,712
Rep Power
15
I don't think you are supposed to copy the pixel data and then transform (for one thing the result would be a bit rough - you should really take each pixel of the destination and find the "preimage" pixels in the source and take a weighted average of their colours...). My reading of the docs db pointed to is that you use one of the JAI.create() family to create a rendered image.

Here's an example using a polnomial warp. The image creation happens in the updateWarp() method where a transformation is created based on user entered points, a parameter block made up using a source image and the transformation, then JAI.create() is called to create the rendered image that actually gets used.

15. Member
Join Date
Aug 2011
Posts
9
Rep Power
0
Ah, sorry, I should've gone through it more thoroughly. I didn't have much time when I was going over it and sort of made the assumption after a quick look at PerspectiveTransform object. Anyway, you have a good point, I really should have looked at the example code.

Thanks again for your help, and sorry for the confusion.

16. Moderator
Join Date
Feb 2009
Location
New Zealand
Posts
4,712
Rep Power
15
No problem - I had the question as you when I read about the perspective transform: how do you make an image out of the thing?! I think the guide could do with a "tutorial" style commentary (ie some code for us folk in a hurry)

Darryl will doubtless jump in if I'm putting you wrong, but the code at that link and nearby looks good.

If JAI.create() works out, post your code: I'd be interested.

17. Member
Join Date
Aug 2011
Posts
9
Rep Power
0
I can't quite get this to work.

Heres the function I've written to wrap the process of creating a warp:
;
m_srcImage is set like so:
Java Code:
`m_srcImage = = ImageIO.read(new File("C:\\image.png"));`
m_srcImage does draw correctly.
Java Code:
```    public boolean setWarp(Point[] srcPoints, Point[] destPoints)
{
if(srcPoints.length != destPoints.length || destPoints.length != 4)
return false;

float[] src = new float[srcPoints.length * 2];
float[] dest = new float[destPoints.length * 2];

//Organize points so that they can be applied to JAI warp
for(int i = 0; i < srcPoints.length; i++)
{
src[i * 2] = (float)srcPoints[i].getX();
src[(i * 2) + 1] = (float)srcPoints[i].getY();

dest[i * 2] = (float)destPoints[i].getX();
dest[(i * 2) + 1] = (float)destPoints[i].getY();

}

//apply warp to source image.
WarpPolynomial warp = WarpPolynomial.createWarp(src, 0, dest, 0,
srcPoints.length,
1, //PrescaleX
1, //PrescaleY
1, //PostScaleX
1, //PostScaleY
1  //Degree
);

ParameterBlock pb = new ParameterBlock();
RenderedOp o = JAI.create("warp", pb);
m_buildImage = o.getAsBufferedImage();
return true;
}```
When drawing m_buildImage I just get a black image(There's no problem in the drawing procedure).

I call the routine like so:
Java Code:
```txtu.setWarp(
new Point[] {
new Point(0, 0),
new Point(img.getWidth(null), 0),
new Point(0, img.getHeight(null)),
new Point(img.getWidth(null), img.getHeight(null))
},
new Point[] {
new Point(0, 0),
new Point(img.getWidth(null), 0),
new Point(0, img.getHeight(null)),
new Point(img.getWidth(null), img.getHeight(null))
});```
Thanks, and sorry to load all this code on you.

18. Member
Join Date
Aug 2011
Posts
9
Rep Power
0
i missed the WarpPerspective object when I was going through the JAI api. Anyway, I got it working, here it is:

Java Code:
```    public boolean setWarp(Point[] srcPoints, Point[] destPoints)
{
if(srcPoints.length != destPoints.length || destPoints.length != 4)
return false;

//apply warp to source image.
WarpPerspective warp = new WarpPerspective(
srcPoints[1].x, srcPoints[1].y,//x2, y2
srcPoints[2].x, srcPoints[2].y,//x3, y3
srcPoints[3].x, srcPoints[3].y,//x4, y5
//dest
destPoints[0].x, destPoints[0].y, //x1, y1
destPoints[1].x, destPoints[1].y,//x2, y2
destPoints[2].x, destPoints[2].y,//x3, y3
destPoints[3].x, destPoints[3].y //x4, y5
));

ParameterBlock pb = new ParameterBlock();

RenderedOp o = JAI.create("warp", pb);
m_buildImage = o.getAsBufferedImage();
return true;
}```

19. Moderator
Join Date
Feb 2009
Location
New Zealand
Posts
4,712
Rep Power
15
I'm glad you've the transformation doing what you want. And thanks for the follow up.

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•