Warping rects to quads (was: [GOODIE] FishEyeMorph)

Bob Arning arning at charm.net
Thu Dec 16 17:40:21 UTC 1999


Hi Yoshiki,

This one got my interest. After trying to analytically compute the reverse transformation, I gave up and tried something simpler: run the normal quad-to-rectangle code, but copy the bits in the other direction. Sample code is included below. There are some simplifications here that warrant further attention:

1. To make the minimal change, the notion of source and dest are reversed. It's ugly, but simple.
2. Again, in the interest of simplicity, I did not implement the smoothing part.
3. Smoothing is important in another regard since the algorithm as written steps through each pixel (once) in the rectangular form in order to put pixels into the arbitrary quad form. If the rectangular form is a good bit larger than the quad form, this works reasonably well, but if the situation is reversed, holes will appear in the quad form. Possible fixes: magnify the rectangular form yourself beforehand, step in sub-pixel increments or rewrite the algorithm altogether.
4. It is not a primitive, so it's not real fast.

Cheers,
Bob

======
'From Squeak2.7alpha of 9 November 1999 [latest update: #1716] on 16 December 1999 at 12:25:36 pm'!

!WarpBlt methodsFor: 'primitives' stamp: 'RAA 12/16/1999 12:16'!
warpBackwards
	| deltaP12 deltaP43 pA pB deltaPAB sp fixedPtOne picker poker nSteps |

	(width < 1) | (height < 1) ifTrue: [^ self].
	fixedPtOne _ 16384.  "1.0 in fixed-pt representation"

	nSteps _ height-1 max: 1.
	deltaP12 _ (self deltaFrom: p1x to: p2x nSteps: nSteps)
			@ (self deltaFrom: p1y to: p2y nSteps: nSteps).
	pA _ (self startFrom: p1x to: p2x offset: nSteps*deltaP12 x)
		@ (self startFrom: p1y to: p2y offset: nSteps*deltaP12 y).
	deltaP43 _ (self deltaFrom: p4x to: p3x nSteps: nSteps)
			@ (self deltaFrom: p4y to: p3y nSteps: nSteps).
	pB _ (self startFrom: p4x to: p3x offset: nSteps*deltaP43 x)
		@ (self startFrom: p4y to: p3y offset: nSteps*deltaP43 y).

	picker _ BitBlt bitPeekerFromForm: destForm.		"ugly"
	poker _ BitBlt bitPokerToForm: sourceForm .
	poker clipRect: sourceForm boundingBox.
	nSteps _ width-1 max: 1.
	destY to: destY+height-1 do: [:y |
		deltaPAB _ (self deltaFrom: pA x to: pB x nSteps: nSteps)
				@ (self deltaFrom: pA y to: pB y nSteps: nSteps).
		sp _ (self startFrom: pA x to: pB x offset: nSteps*deltaPAB x)
			@ (self startFrom: pA y to: pB y offset: nSteps*deltaPAB y).
		destX to: destX+width-1 do: [:x | 
			poker pixelAt: sp // fixedPtOne asPoint put: (picker pixelAt: x at y).
			sp _ sp + deltaPAB.
		].
		pA _ pA + deltaP12.
		pB _ pB + deltaP43.
	].! !


!WarpBlt class methodsFor: 'examples' stamp: 'RAA 12/16/1999 12:25'!
warpToQuad
"An experiment in warping FROM a rectangle TO a quad"

 "Here is an example: there is a Form whose bounding box is
(0 at 0 corner: 10 at 10), and I'd like to transform it onto a
quad specified as {0 at 0. 2 at 12. 7 at 8. 16 at -6}.  It's ok the
edges are distorted (inward) by WarpBlt but I want the
original corners to be transformed onto the corners of the
resulting quad."
"WarpBlt warpToQuad"

	| sourceForm destQuad destRect destForm |

	sourceForm _ Color colorRampForDepth: 32 extent: 256 at 80.
	destQuad _ {0 at 0. 2 at 12. 7 at 8. 16 at -6}.
	destRect _ destQuad min corner: destQuad max.
	(destForm _ Form extent: destRect extent depth: 32) fillColor: Color white.
	(self toForm: sourceForm)
		sourceForm: destForm;
		combinationRule: Form over;
		sourceQuad: (destQuad collect: [ :pt | pt - destRect topLeft]) 
		destRect: sourceForm boundingBox;
		warpBackwards.
	destForm bitEdit.

	
 ! !



======

On Thu, 16 Dec 1999 02:35:08 +0900 ohshima at is.titech.ac.jp wrote:
>  However, there are many other classes of the distorted
>views, including "polar fish eye", "polyfocal (close to the
>'science' screen saver of Windows)", etc.  Even I could
>include "Perspective Wall" among them.
>
>  In order to implement those views, it must be able to
>transform square Forms (or rectangle, more generally) onto
>arbitrary quadrilaterals.  The limitation of WarpBlt is it
>cannot perform such a kind of transformation. (At least my
>mathematics ability doesn't let me to do so).
>
>  I think such graphics primitive is very handy and more
>general than WarpBlt.
>
>  By the way, if I want to implement the approximation of
>those transformation by using WarpBlt, does anyone have idea
>how I can figure out the sourceQuad?
>
>  Here is an example: there is a Form whose bounding box is
>(0 at 0 corner: 10 at 10), and I'd like to transform it onto a
>quad specified as "{0 at 0. 2 at 12. 7 at 8. 16 at -6}".  It's ok the
>edges are distorted (inward) by WarpBlt but I want the
>original corners to be transformed onto the corners of the
>resulting quad.





More information about the Squeak-dev mailing list