Beispiel #1
0
	/**
	 * Matrix scalar div
	 */
	void operator /= ( fix32 s )
	{
		for ( int i = 0; i < 4; i++ )
		{
			m_matrix[i][0] = FIXDIV( m_matrix[i][0], s );
			m_matrix[i][1] = FIXDIV( m_matrix[i][1], s );
			m_matrix[i][2] = FIXDIV( m_matrix[i][2], s );
			m_matrix[i][3] = FIXDIV( m_matrix[i][0], s );
		}
	}
Beispiel #2
0
	/**
	 * Matrix scalar division
	 */
	Matrix4fi operator / ( fix32 s ) const
	{
		Matrix4fi r( false );

		for ( int i = 0; i < 4; i++ )
		{
			r.m_matrix[i][0] = FIXDIV( m_matrix[i][0], s );
			r.m_matrix[i][1] = FIXDIV( m_matrix[i][1], s );
			r.m_matrix[i][2] = FIXDIV( m_matrix[i][2], s );
			r.m_matrix[i][3] = FIXDIV( m_matrix[i][0], s );
		}

		return r;
	}
Beispiel #3
0
void ByteHomo (ByteImage *srcBuf, ByteImage *destBuf, double a, double b,
                    double c, double d, double e, double f, double m, double n, double p)
{
    unsigned char *dest, *src;
    double acm, bcn, dfm, efn, dnm, det, xNom, yNom, Denom;
    double h11, h12, h13, h21, h22, h23, h31, h32, h33;
    double xh[4], yh[4], z, tmp;
    double xstartF, xendF;
    double srcXf, srcYf;
    double angle, minAngle;
    int tmpInt;
    int yend, ystart, xstartI, xendI, destX, destY, srcXi, srcYi;
    int x, y, p00, p01, p10, p11;
    int w, h;
    int order[4], startNextOrder, endNextOrder;
    int i, j, best, region, startP, startQ, endP, endQ, delta, minj;
    int h11Fixed, h21Fixed, h31Fixed, xNomFixed, yNomFixed, DenomFixed;
    int srcXfixed, srcYfixed, p00Fixed, p01Fixed;

    /* make compiler happy */
    startNextOrder = endNextOrder = startP = startQ = endP = endQ = minj = 0;
    
    /*
     * Calculate where the source rectangle lands on the destination image.
     * These will be four coordinates, xh[0]..xh[3], yh[0]..yh[3].
     */
    w = srcBuf->width-1;
    h = srcBuf->height-1;
    z = m * 0 + n * 0 + p;
    xh[0] = (a * 0 + b * 0 + c) / z;
    yh[0] = (d * 0 + e * 0 + f) / z;
    z = m * w + n * 0 + p;
    xh[1] = (a * w + b * 0 + c) / z;
    yh[1] = (d * w + e * 0 + f) / z;
    z = m * 0 + n * h + p;
    xh[2] = (a * 0 + b * h + c) / z;
    yh[2] = d * 0 + e * h + f;
    z = m * w + n * h + p;
    xh[3] = (a * w + b * h + c) / z;
    yh[3] = (d * w + e * h + f) / z;

    /*
     * calculate all the entries in the inverse matrix H
     */
    acm = a*p  -c*m;
    bcn = b*p  -c*n;
    dnm = d*n - e*m;
    dfm = d*p - f*m;
    efn = e*p - f*n;
    det = a * efn - b * dfm + c*dnm;
    h11 = efn / det;
    h12 = -bcn / det;
    h21 = -dfm / det;
    h22 = acm / det;
    h13 = (b*f - e*c)/ det;
    h23 = -(a*f - d*c)/det;
    h31 = dnm / det;
    h32 = -(a*n - b*m)/det;
    h33 = (a*e - b*d)/det;
    h11Fixed = FIX(h11);
    h21Fixed = FIX(h21);
    h31Fixed = FIX(h31);

    /*
     * Sort these 4 coordinates first by y coordinate, then by
     * x coordinate
     */
    for (i=0; i<4; i++) {
        best = i;
        for (j=i+1; j<4; j++) {
            if ((yh[j] < yh[best]) ||
                ((yh[j] == yh[best]) && (xh[j] < xh[best]))) {
                best = j;
            }
        }
        tmp = xh[i];
        xh[i] = xh[best];
        xh[best] = tmp;
        tmp = yh[i];
        yh[i] = yh[best];
        yh[best] = tmp;
    }

    /*
     * find the anti-clockwise order of the points
     * start from (x[order[0]], y[order[0]]
     * where (x[order[i+1]], y[order[i+1]]) is the next point of 
     *       (x[order[i]], y[order[i]]) in anti-clockwise direction
     */
    for (i=0; i<4; i++) {
        order[i] = i;
    }
    
    for (i=1; i<4; i++) {
        minAngle = 2*M_PI;
        
        /* starting from the horizontal line on the left of point(order[i-1]),
         * rotating the line anti-clockwise,
         * the first point being swept thru is the next point in 
         * anticlockwise direction
         */
        for (j=i; j<4; j++) {
            /* angle = anticlockwise angle from
             *         the horizontal line on the left of point(order[i-1]) to
             *         the line thru point(order[i-1]), point(order[j])
             */
            angle = M_PI - atan2(yh[order[j]] - yh[order[i-1]], 
                            xh[order[j]] - xh[order[i-1]]);
            if (angle < minAngle) {
                    minAngle = angle;
                    minj = j;
            }
        }
        tmpInt = order[i];
        order[i] = order[minj];
        order[minj] = tmpInt;
    }

    /*
     * We now have the coordinates to the quadrilateral that the
     * src image maps into on the destination image.  x[0],y[0] is
     * the top, x[3],y[3] is the bottom.  Divide it up into 3 regions:
     * the top (y[0]..y[1]), the middle (y[1]..y[2]) and the bottom
     * (y[2]..y[3]).  For each region, calculate the starting and
     * ending x coordinates for scanline y on the destination image.
     * These are the only pixels in the destination that are affected.
     */
    for (region=0; region<3; region++) {
        if (region == 0) {
            startNextOrder = 1;
            endNextOrder = 3;
            startP = 0;
            startQ = order[1];
            endP = 0;
            endQ = order[3];
        } else {
            if (yh[startQ] > yh[endQ]) {
                endP = endQ;
                endQ = order[--endNextOrder];
            } else {
                startP = startQ;
                startQ = order[++startNextOrder];
            }
        }
        ystart = max(0, (int)floor(yh[region]));
        yend = min(destBuf->height, (int)yh[region+1]);

        for (destY=ystart; destY < yend; destY++) {
        
            /*
             * We're working on scanline destY.  Compute the starting and
             * ending x coordinates (xstart, xend) on the destination
             * image of the region for which source pixels are defined.
             * xstart is given by the x coordinate of the line from
             * (x[startP], y[startP]) to x(x[startQ], y[startQ]) with
             * y coordinate destY.
             * xend is similarly computed from x/y[endP/endQ]
             * The starting coordinate is rounded down, the ending coordinate
             * rounded up.
             */
            xstartF = xh[startP] + 
                (destY-yh[startP])*(xh[startQ]-xh[startP])/
                (yh[startQ]-yh[startP]);
            xendF = xh[endP] + 
                (destY-yh[endP])*(xh[endQ]-xh[endP])/(yh[endQ]-yh[endP]);
            xstartF = max (0, xstartF);
            xendF = min (xendF, destBuf->width);
            xstartI = (int)ceil(xstartF);
            xendI = (int)(xendF);
            dest = destBuf->firstByte + (destY*destBuf->parentWidth + xstartI);

            /*
             * H is the inverse homogeneous matrix which maps destination points
             * back to source image
             * H(x,y,1) = (xNom, yNom, Denom)
             * srcX = xNom/Denom
             * srcY = yNom/Denom
             */
            xNom =  h11 * xstartI + h12 * destY + h13;
            yNom =  h21 * xstartI + h22 * destY + h23;
            Denom = h31 * xstartI + h32 * destY + h33;
            xNomFixed = FIX(xNom);
            yNomFixed = FIX(yNom);
            DenomFixed = FIX(Denom);
            srcXf = xNom / Denom;
            srcYf = yNom / Denom;
            srcXfixed = FIX(srcXf);
            srcYfixed = FIX(srcYf);

            for (destX = xstartI; destX < xendI; destX++, dest++) {

                /*
                 * The following code computes the value of a pixel in
                 * the destination image at (destX, destY).  It has been
                 * optimized by using fixed point arithmetic (see macro.h
                 * for a description of the fixed point operators).
                 * src[XY]fixed are the fixed-point coordinates of the
                 * corresponding location in the source image.  We compute
                 * the integer (truncated) value of that location in src[XY]i,
                 * and the remainder in x and y.  p00..p11 are the four closest
                 * pixels to src[XY], and we use them in the bilinear
                 * interpolation routine.  On a Pentium 266, this routine will
                 * process about 2.02 Mpix/sec. For comparison, 320x240
                 * video at 30 fps is 2.3 Mpix/sec
                 */
                srcXi = IUNFIX(srcXfixed);
                srcYi = IUNFIX(srcYfixed);
                if ((srcXi >= 0) && (srcXi <= w) && (srcYi >= 0) && (srcYi <= h)) {
                    src = srcBuf->firstByte + (srcYi*srcBuf->parentWidth + srcXi);
                    x = srcXfixed - IFIX(srcXi);
                    y = srcYfixed - IFIX(srcYi);
                    p00 = *src++;
                    p10 = *src;
                    src += srcBuf->parentWidth;
                    p11 = *src--;
                    p01 = *src;

                    p00Fixed = IFIX(p00) + x*(p10-p00);
                    p01Fixed = IFIX(p01) + x*(p11-p01);
                    delta = IUNFIX_ROUND(p01Fixed - p00Fixed);
                    p00Fixed = p00Fixed + y*delta;
                    *dest = IUNFIX_ROUND(p00Fixed);
                }

                /*
                 * update the srcX, srcY
                 * H(x+1,y,1) = (xNom+h11, yNom+h21, Denom+h31)
                 */
                xNomFixed += h11Fixed;
                yNomFixed += h21Fixed;
                DenomFixed += h31Fixed;
                srcXfixed = FIXDIV(xNomFixed, DenomFixed);
                srcYfixed = FIXDIV(yNomFixed, DenomFixed);
            }
        }
    }
}