private BufferedImage filter( BufferedImage src, BufferedImage dst ) {
        int width = src.getWidth();
        int height = src.getHeight();
        //int type = src.getType();
        //WritableRaster srcRaster = src.getRaster();

        originalSpace = new Rectangle(0, 0, width, height);
        transformedSpace = new Rectangle(0, 0, width, height);
        transformSpace(transformedSpace);

        if ( dst == null ) {
            ColorModel dstCM = src.getColorModel();
            dst = new BufferedImage(
                dstCM,
                dstCM.createCompatibleWritableRaster(transformedSpace.width, transformedSpace.height),
                dstCM.isAlphaPremultiplied(),
                null
            );
        }
        //WritableRaster dstRaster = dst.getRaster();

        int[] inPixels = getRGB( src, 0, 0, width, height, null );

        if ( interpolation == NEAREST_NEIGHBOUR )
            return filterPixelsNN( dst, width, height, inPixels, transformedSpace );

        int srcWidth = width;
        int srcHeight = height;
        int srcWidth1 = width-1;
        int srcHeight1 = height-1;
        int outWidth = transformedSpace.width;
        int outHeight = transformedSpace.height;
        int outX, outY;
        //int index = 0;
        int[] outPixels = new int[outWidth];

        outX = transformedSpace.x;
        outY = transformedSpace.y;
        float[] out = new float[2];

        for (int y = 0; y < outHeight; y++) {
            for (int x = 0; x < outWidth; x++) {
                transformInverse(outX+x, outY+y, out);
                int srcX = (int)Math.floor( out[0] );
                int srcY = (int)Math.floor( out[1] );
                float xWeight = out[0]-srcX;
                float yWeight = out[1]-srcY;
                int nw, ne, sw, se;

                if ( srcX >= 0 && srcX < srcWidth1 && srcY >= 0 && srcY < srcHeight1) {
                    // Easy case, all corners are in the image
                    int i = srcWidth*srcY + srcX;
                    nw = inPixels[i];
                    ne = inPixels[i+1];
                    sw = inPixels[i+srcWidth];
                    se = inPixels[i+srcWidth+1];
                } else {
                    // Some of the corners are off the image
                    nw = getPixel( inPixels, srcX, srcY, srcWidth, srcHeight );
                    ne = getPixel( inPixels, srcX+1, srcY, srcWidth, srcHeight );
                    sw = getPixel( inPixels, srcX, srcY+1, srcWidth, srcHeight );
                    se = getPixel( inPixels, srcX+1, srcY+1, srcWidth, srcHeight );
                }
                outPixels[x] = bilinearInterpolate(xWeight, yWeight, nw, ne, sw, se);
            }
            setRGB( dst, 0, y, transformedSpace.width, 1, outPixels );
        }
            return dst;
    }