Esempio n. 1
0
/* Uses Gauss-Jordan elimination.

   The elimination procedure works by applying elementary row
   operations to our input matrix until the input matrix is reduced to
   the identity matrix.
   Simultaneously, we apply the same elementary row operations to a
   separate identity matrix to produce the inverse matrix.
   If this makes no sense, read wikipedia on Gauss-Jordan elimination.
   
   This is not the fastest way to invert matrices, so this is quite
   possibly the bottleneck. */
int destructive_invert_matrix(const Matrix_t * input, const Matrix_t * output)
{
	uint8_t i,j,r;
	double scalar, shear_needed;
	set_identity_matrix(output);

	/*
		Convert input to the identity matrix via elementary row operations.
		The ith pass through this loop turns the element at i,i to a 1
		and turns all other elements in column i to a 0.
	*/
	for (i = 0; i < input->rows; ++i)
	{
		if (input->data[i][i] == 0.0)
		{
			/* We must swap rows to get a nonzero diagonal element. */
			for (r = i + 1; r < input->rows; ++r)
			{
				if (input->data[r][i] != 0.0)
					break;
			}
			if (r == input->rows)
				/* Every remaining element in this column is zero, so this
				matrix cannot be inverted. */
				return 0;
			swap_rows(input, i, r);
			swap_rows(output, i, r);
		}

		/*
			Scale this row to ensure a 1 along the diagonal.
			We might need to worry about overflow from a huge scalar here. */
		scalar = 1.0 / input->data[i][i];
		scale_row(input, i, scalar);
		scale_row(output, i, scalar);

		/* Zero out the other elements in this column. */
		for (j = 0; j < input->rows; ++j)
		{
			if (i == j)
				continue;
			shear_needed = -input->data[j][i];
			shear_row(input, j, i, shear_needed);
			shear_row(output, j, i, shear_needed);
		}
	}
	return 1;
}
Esempio n. 2
0
int
main(int argc, char * argv[]) {
    FILE* ifp;
    xel* xelrow;
    xel* newxelrow;
    xel bgxel;
    int rows, cols, format; 
    int newformat, newcols; 
    int row;
    xelval maxval, newmaxval;
    double shearfac;

    struct cmdline_info cmdline;

    pnm_init( &argc, argv );

    parse_command_line( argc, argv, &cmdline );

    ifp = pm_openr( cmdline.input_filespec );

    pnm_readpnminit( ifp, &cols, &rows, &maxval, &format );
    xelrow = pnm_allocrow( cols );

    /* Promote PBM files to PGM. */
    if ( !cmdline.noantialias && PNM_FORMAT_TYPE(format) == PBM_TYPE ) {
        newformat = PGM_TYPE;
        newmaxval = PGM_MAXMAXVAL;
        pm_message( "promoting from PBM to PGM - "
                    "use -noantialias to avoid this" );
    } else {
        newformat = format;
        newmaxval = maxval;
    }

    shearfac = tan( cmdline.angle );
    if ( shearfac < 0.0 )
        shearfac = -shearfac;

    if(rows * shearfac >= INT_MAX-1)
    	pm_error("image too large");
    
    overflow_add(rows * shearfac, cols+1);
    
    newcols = rows * shearfac + cols + 0.999999;

    pnm_writepnminit( stdout, newcols, rows, newmaxval, newformat, 0 );
    newxelrow = pnm_allocrow( newcols );

    bgxel = pnm_backgroundxelrow( xelrow, cols, newmaxval, format );

    for ( row = 0; row < rows; ++row ) {
        double shearCols;

        pnm_readpnmrow( ifp, xelrow, cols, newmaxval, format );

        if ( cmdline.angle > 0.0 )
            shearCols = row * shearfac;
        else
            shearCols = ( rows - row ) * shearfac;

        shear_row(xelrow, cols, newxelrow, newcols, 
                  shearCols, format, bgxel, !cmdline.noantialias);

        pnm_writepnmrow( stdout, newxelrow, newcols, newmaxval, newformat, 0 );
    }

    pm_close( ifp );
    pm_close( stdout );

    exit( 0 );
}