/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#pragma ident	"@(#)mlib_c_ImageAffine_NN.c	9.2	07/10/09 SMI"

/*
 * FUNCTION
 *      mlib_ImageAffine_u8_1ch_nn
 *      mlib_ImageAffine_u8_2ch_nn
 *      mlib_ImageAffine_u8_3ch_nn
 *      mlib_ImageAffine_u8_4ch_nn
 *      mlib_ImageAffine_s16_1ch_nn
 *      mlib_ImageAffine_s16_2ch_nn
 *      mlib_ImageAffine_s16_3ch_nn
 *      mlib_ImageAffine_s16_4ch_nn
 *        - image affine transformation with Nearest Neighbor filtering
 * SYNOPSIS
 *      mlib_status mlib_ImageAffine_[u8|s16]_?ch_nn(mlib_s32 *leftEdges,
 *                                                   mlib_s32 *rightEdges,
 *                                                   mlib_s32 *xStarts,
 *                                                   mlib_s32 *yStarts,
 *                                                   mlib_s32 *sides,
 *                                                   mlib_u8  *dstData,
 *                                                   mlib_u8  **lineAddr,
 *                                                   mlib_s32 dstYStride,
 *                                                   mlib_s32 is_affine)
 *
 * ARGUMENTS
 *      leftEdges  array[dstHeight] of xLeft coordinates
 *      RightEdges array[dstHeight] of xRight coordinates
 *      xStarts    array[dstHeight] of xStart * 65536 coordinates
 *      yStarts    array[dstHeight] of yStart * 65536 coordinates
 *      sides      output array[4]. sides[0] is yStart, sides[1] is yFinish,
 *                 sides[2] is dx * 65536, sides[3] is dy * 65536
 *      dstData    pointer to the first pixel on (yStart - 1) line
 *      lineAddr   array[srcHeight] of pointers to the first pixel on
 *                 the corresponding lines
 *      dstYStride stride of destination image
 *      is_affine  indicator (Affine - GridWarp)
 *
 * DESCRIPTION
 *      The functions step along the lines from xLeft to xRight and get the
 *      nearest pixel values as being with the following coordinates
 *      ((xStart - (i - xLeft) * dx) >> 16, (yStart - (i - xLeft) * dy) >> 16)
 *
 */

#include <mlib_ImageAffine.h>

/* *********************************************************** */

#undef  DTYPE
#define	DTYPE	mlib_u8

mlib_status
mlib_ImageAffine_u8_1ch_nn(
	mlib_affine_param *param)
{
	DECLAREVAR_NN();
	DTYPE *dstLineEnd;

	for (j = yStart; j <= yFinish; j++) {
		DTYPE pix0;

		CLIP(1);
		dstLineEnd = (DTYPE *) dstData + xRight;

#ifdef __SUNPRO_C
#pragma pipeloop(0)
#endif /* __SUNPRO_C */
		for (; dstPixelPtr <= dstLineEnd; dstPixelPtr++) {
			ySrc = MLIB_POINTER_SHIFT(Y);
			Y += dY;
			srcPixelPtr = MLIB_POINTER_GET(lineAddr, ySrc);
			xSrc = X >> MLIB_SHIFT;
			X += dX;
			pix0 = srcPixelPtr[xSrc];
			dstPixelPtr[0] = pix0;
		}
	}

	return (MLIB_SUCCESS);
}

/* *********************************************************** */

mlib_status
mlib_ImageAffine_u8_2ch_nn(
	mlib_affine_param *param)
{
	DECLAREVAR_NN();
	DTYPE *dstLineEnd;

	for (j = yStart; j <= yFinish; j++) {
		DTYPE pix0, pix1;

		CLIP(2);
		dstLineEnd = (DTYPE *) dstData + 2 * xRight;

		ySrc = MLIB_POINTER_SHIFT(Y);
		Y += dY;
		xSrc = X >> MLIB_SHIFT;
		X += dX;
		srcPixelPtr = MLIB_POINTER_GET(lineAddr, ySrc) + 2 * xSrc;
		pix0 = srcPixelPtr[0];
		pix1 = srcPixelPtr[1];
		ySrc = MLIB_POINTER_SHIFT(Y);
		Y += dY;
		xSrc = X >> MLIB_SHIFT;
		X += dX;
#ifdef __SUNPRO_C
#pragma pipeloop(0)
#endif /* __SUNPRO_C */
		for (; dstPixelPtr < dstLineEnd; dstPixelPtr += 2) {
			srcPixelPtr =
				MLIB_POINTER_GET(lineAddr, ySrc) + 2 * xSrc;
			ySrc = MLIB_POINTER_SHIFT(Y);
			Y += dY;
			xSrc = X >> MLIB_SHIFT;
			X += dX;
			dstPixelPtr[0] = pix0;
			dstPixelPtr[1] = pix1;
			pix0 = srcPixelPtr[0];
			pix1 = srcPixelPtr[1];
		}

		dstPixelPtr[0] = pix0;
		dstPixelPtr[1] = pix1;
	}

	return (MLIB_SUCCESS);
}

/* *********************************************************** */

mlib_status
mlib_ImageAffine_u8_3ch_nn(
	mlib_affine_param *param)
{
	DECLAREVAR_NN();
	DTYPE *dstLineEnd;

	for (j = yStart; j <= yFinish; j++) {
		DTYPE pix0, pix1, pix2;

		CLIP(3);
		dstLineEnd = (DTYPE *) dstData + 3 * xRight;

		ySrc = MLIB_POINTER_SHIFT(Y);
		Y += dY;
		xSrc = X >> MLIB_SHIFT;
		X += dX;
		srcPixelPtr = MLIB_POINTER_GET(lineAddr, ySrc) + 3 * xSrc;
		pix0 = srcPixelPtr[0];
		pix1 = srcPixelPtr[1];
		pix2 = srcPixelPtr[2];
		ySrc = MLIB_POINTER_SHIFT(Y);
		Y += dY;
		xSrc = X >> MLIB_SHIFT;
		X += dX;
#ifdef __SUNPRO_C
#pragma pipeloop(0)
#endif /* __SUNPRO_C */
		for (; dstPixelPtr < dstLineEnd; dstPixelPtr += 3) {
			srcPixelPtr =
				MLIB_POINTER_GET(lineAddr, ySrc) + 3 * xSrc;
			ySrc = MLIB_POINTER_SHIFT(Y);
			Y += dY;
			xSrc = X >> MLIB_SHIFT;
			X += dX;
			dstPixelPtr[0] = pix0;
			dstPixelPtr[1] = pix1;
			dstPixelPtr[2] = pix2;
			pix0 = srcPixelPtr[0];
			pix1 = srcPixelPtr[1];
			pix2 = srcPixelPtr[2];
		}

		dstPixelPtr[0] = pix0;
		dstPixelPtr[1] = pix1;
		dstPixelPtr[2] = pix2;
	}

	return (MLIB_SUCCESS);
}

/* *********************************************************** */

mlib_status
mlib_ImageAffine_u8_4ch_nn(
	mlib_affine_param *param)
{
	DECLAREVAR_NN();
	DTYPE *dstLineEnd;

	for (j = yStart; j <= yFinish; j++) {
		DTYPE pix0, pix1, pix2, pix3;

		CLIP(4);
		dstLineEnd = (DTYPE *) dstData + 4 * xRight;

		ySrc = MLIB_POINTER_SHIFT(Y);
		Y += dY;
		xSrc = X >> MLIB_SHIFT;
		X += dX;
		srcPixelPtr = MLIB_POINTER_GET(lineAddr, ySrc) + 4 * xSrc;
		pix0 = srcPixelPtr[0];
		pix1 = srcPixelPtr[1];
		pix2 = srcPixelPtr[2];
		pix3 = srcPixelPtr[3];
		ySrc = MLIB_POINTER_SHIFT(Y);
		Y += dY;
		xSrc = X >> MLIB_SHIFT;
		X += dX;
		for (; dstPixelPtr < dstLineEnd; dstPixelPtr += 4) {
			srcPixelPtr =
				MLIB_POINTER_GET(lineAddr, ySrc) + 4 * xSrc;
			ySrc = MLIB_POINTER_SHIFT(Y);
			Y += dY;
			xSrc = X >> MLIB_SHIFT;
			X += dX;
			dstPixelPtr[0] = pix0;
			dstPixelPtr[1] = pix1;
			dstPixelPtr[2] = pix2;
			dstPixelPtr[3] = pix3;
			pix0 = srcPixelPtr[0];
			pix1 = srcPixelPtr[1];
			pix2 = srcPixelPtr[2];
			pix3 = srcPixelPtr[3];
		}

		dstPixelPtr[0] = pix0;
		dstPixelPtr[1] = pix1;
		dstPixelPtr[2] = pix2;
		dstPixelPtr[3] = pix3;
	}

	return (MLIB_SUCCESS);
}

/* *********************************************************** */

#undef  DTYPE
#define	DTYPE	mlib_u16

mlib_status
mlib_ImageAffine_s16_1ch_nn(
	mlib_affine_param *param)
{
	DECLAREVAR_NN();
	DTYPE *dstLineEnd;

	for (j = yStart; j <= yFinish; j++) {
		mlib_s32 pix0;

		CLIP(1);
		dstLineEnd = (DTYPE *) dstData + xRight;

		ySrc = MLIB_POINTER_SHIFT(Y);
		Y += dY;
		xSrc = X >> MLIB_SHIFT;
		X += dX;
		srcPixelPtr = MLIB_POINTER_GET(lineAddr, ySrc);
		pix0 = srcPixelPtr[xSrc];
		ySrc = MLIB_POINTER_SHIFT(Y);
		Y += dY;
		for (; dstPixelPtr < dstLineEnd; dstPixelPtr++) {
			xSrc = X >> MLIB_SHIFT;
			X += dX;
			srcPixelPtr = MLIB_POINTER_GET(lineAddr, ySrc);
			dstPixelPtr[0] = pix0;
			ySrc = MLIB_POINTER_SHIFT(Y);
			Y += dY;
			pix0 = srcPixelPtr[xSrc];
		}

		dstPixelPtr[0] = pix0;
	}

	return (MLIB_SUCCESS);
}

/* *********************************************************** */

mlib_status
mlib_ImageAffine_s16_2ch_nn(
	mlib_affine_param *param)
{
	DECLAREVAR_NN();
	DTYPE *dstLineEnd;

	for (j = yStart; j <= yFinish; j++) {
		mlib_s32 pix0, pix1;

		CLIP(2);
		dstLineEnd = (DTYPE *) dstData + 2 * xRight;

		ySrc = MLIB_POINTER_SHIFT(Y);
		Y += dY;
		xSrc = X >> MLIB_SHIFT;
		X += dX;
		srcPixelPtr = MLIB_POINTER_GET(lineAddr, ySrc) + 2 * xSrc;
		pix0 = srcPixelPtr[0];
		pix1 = srcPixelPtr[1];
		ySrc = MLIB_POINTER_SHIFT(Y);
		Y += dY;
		xSrc = X >> MLIB_SHIFT;
		X += dX;
#ifdef __SUNPRO_C
#pragma pipeloop(0)
#endif /* __SUNPRO_C */
		for (; dstPixelPtr < dstLineEnd; dstPixelPtr += 2) {
			srcPixelPtr =
				MLIB_POINTER_GET(lineAddr, ySrc) + 2 * xSrc;
			ySrc = MLIB_POINTER_SHIFT(Y);
			Y += dY;
			xSrc = X >> MLIB_SHIFT;
			X += dX;
			dstPixelPtr[0] = pix0;
			dstPixelPtr[1] = pix1;
			pix0 = srcPixelPtr[0];
			pix1 = srcPixelPtr[1];
		}

		dstPixelPtr[0] = pix0;
		dstPixelPtr[1] = pix1;
	}

	return (MLIB_SUCCESS);
}

/* *********************************************************** */

mlib_status
mlib_ImageAffine_s16_3ch_nn(
	mlib_affine_param *param)
{
	DECLAREVAR_NN();
	DTYPE *dstLineEnd;

	for (j = yStart; j <= yFinish; j++) {
		mlib_s32 pix0, pix1, pix2;

		CLIP(3);
		dstLineEnd = (DTYPE *) dstData + 3 * xRight;

		ySrc = MLIB_POINTER_SHIFT(Y);
		Y += dY;
		xSrc = X >> MLIB_SHIFT;
		X += dX;
		srcPixelPtr = MLIB_POINTER_GET(lineAddr, ySrc) + 3 * xSrc;
		pix0 = srcPixelPtr[0];
		pix1 = srcPixelPtr[1];
		pix2 = srcPixelPtr[2];
		ySrc = MLIB_POINTER_SHIFT(Y);
		Y += dY;
		xSrc = X >> MLIB_SHIFT;
		X += dX;
#ifdef __SUNPRO_C
#pragma pipeloop(0)
#endif /* __SUNPRO_C */
		for (; dstPixelPtr < dstLineEnd; dstPixelPtr += 3) {
			srcPixelPtr =
				MLIB_POINTER_GET(lineAddr, ySrc) + 3 * xSrc;
			ySrc = MLIB_POINTER_SHIFT(Y);
			Y += dY;
			xSrc = X >> MLIB_SHIFT;
			X += dX;
			dstPixelPtr[0] = pix0;
			dstPixelPtr[1] = pix1;
			dstPixelPtr[2] = pix2;
			pix0 = srcPixelPtr[0];
			pix1 = srcPixelPtr[1];
			pix2 = srcPixelPtr[2];
		}

		dstPixelPtr[0] = pix0;
		dstPixelPtr[1] = pix1;
		dstPixelPtr[2] = pix2;
	}

	return (MLIB_SUCCESS);
}

/* *********************************************************** */

mlib_status
mlib_ImageAffine_s16_4ch_nn(
	mlib_affine_param *param)
{
	DECLAREVAR_NN();
	DTYPE *dstLineEnd;

	for (j = yStart; j <= yFinish; j++) {
		mlib_s32 pix0, pix1, pix2, pix3;

		CLIP(4);
		dstLineEnd = (DTYPE *) dstData + 4 * xRight;

		ySrc = MLIB_POINTER_SHIFT(Y);
		Y += dY;
		xSrc = X >> MLIB_SHIFT;
		X += dX;
		srcPixelPtr = MLIB_POINTER_GET(lineAddr, ySrc) + 4 * xSrc;
		pix0 = srcPixelPtr[0];
		pix1 = srcPixelPtr[1];
		pix2 = srcPixelPtr[2];
		pix3 = srcPixelPtr[3];
		ySrc = MLIB_POINTER_SHIFT(Y);
		Y += dY;
		xSrc = X >> MLIB_SHIFT;
		X += dX;
		for (; dstPixelPtr < dstLineEnd; dstPixelPtr += 4) {
			srcPixelPtr =
				MLIB_POINTER_GET(lineAddr, ySrc) + 4 * xSrc;
			ySrc = MLIB_POINTER_SHIFT(Y);
			Y += dY;
			xSrc = X >> MLIB_SHIFT;
			X += dX;
			dstPixelPtr[0] = pix0;
			dstPixelPtr[1] = pix1;
			dstPixelPtr[2] = pix2;
			dstPixelPtr[3] = pix3;
			pix0 = srcPixelPtr[0];
			pix1 = srcPixelPtr[1];
			pix2 = srcPixelPtr[2];
			pix3 = srcPixelPtr[3];
		}

		dstPixelPtr[0] = pix0;
		dstPixelPtr[1] = pix1;
		dstPixelPtr[2] = pix2;
		dstPixelPtr[3] = pix3;
	}

	return (MLIB_SUCCESS);
}

/* *********************************************************** */
