private static int decode4to3(byte[] source, int srcOffset, byte[] destination, int destOffset, int options) {
		// Lots of error checking and exception throwing
		if (source == null) {
			throw new NullPointerException("Source array was null.");
		}
		if (destination == null) {
			throw new NullPointerException("Destination array was null.");
		}
		if (srcOffset < 0 || srcOffset + 3 >= source.length) {
			throw new IllegalArgumentException(String.format(
					"Source array with length %d cannot have offset of %d and still process four bytes.", source.length, srcOffset));
		}
		if (destOffset < 0 || destOffset +2 >= destination.length) {
			throw new IllegalArgumentException(String.format(
					"Destination array with length %d cannot have offset of %d and still store three bytes.", destination.length, destOffset));
		}

		byte[] DECODABET = getDecodabet(options);

		// Example: Dk==
		if (source[srcOffset + 2] == EQUALS_SIGN) {
			// Two ways to do the same thing. Don't know which way I like best.
			//int outBuff =   ((DECODABET[source[srcOffset    ]] << 24 ) >>>  6)
			//              | ((DECODABET[source[srcOffset + 1]] << 24 ) >>> 12);
			int outBuff =	  ((DECODABET[source[srcOffset    ]] & 0xFF) << 18)
							| ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12);

			destination[destOffset] = (byte) (outBuff >>> 16);
			return 1;
		} else if (source[srcOffset + 3] == EQUALS_SIGN) {
			// Example: DkL=
			// Two ways to do the same thing. Don't know which way I like best.
			//int outBuff =   ((DECODABET[source[srcOffset    ]] << 24) >>>  6)
			//              | ((DECODABET[source[srcOffset + 1]] << 24) >>> 12)
			//              | ((DECODABET[source[srcOffset + 2]] << 24) >>> 18);
			int outBuff =     ((DECODABET[source[srcOffset    ]] & 0xFF) << 18)
							| ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12)
							| ((DECODABET[source[srcOffset + 2]] & 0xFF) <<  6);

			destination[destOffset    ] = (byte) (outBuff >>> 16);
			destination[destOffset + 1] = (byte) (outBuff >>>  8);
			return 2;
		} else {
			// Example: DkLE
			// Two ways to do the same thing. Don't know which way I like best.
			//int outBuff =   ((DECODABET[source[srcOffset    ]] << 24) >>>  6)
			//              | ((DECODABET[source[srcOffset + 1]] << 24) >>> 12)
			//              | ((DECODABET[source[srcOffset + 2]] << 24) >>> 18)
			//              | ((DECODABET[source[srcOffset + 3]] << 24) >>> 24);
			int outBuff =     ((DECODABET[source[srcOffset    ]] & 0xFF) << 18)
							| ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12)
							| ((DECODABET[source[srcOffset + 2]] & 0xFF) <<  6)
							| ((DECODABET[source[srcOffset + 3]] & 0xFF)      );

			destination[destOffset    ] = (byte) (outBuff >> 16);
			destination[destOffset + 1] = (byte) (outBuff >>  8);
			destination[destOffset + 2] = (byte) (outBuff      );

			return 3;
		}
	}