/* ------------------------------------------------------------------
 * Copyright (C) 1998-2009 PacketVideo
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 * -------------------------------------------------------------------
 */
//                                                                              //
//  File: cczoomrotation24.cpp                                                //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////
/** Class ColorConvert24, YUV to RGB24 bit, 8bit per component. */
#include "colorconv_config.h"
#include "cczoomrotation24.h"



OSCL_EXPORT_REF ColorConvertBase* ColorConvert24::NewL(void)
{
    ColorConvert24* self = OSCL_NEW(ColorConvert24, ());
    return OSCL_STATIC_CAST(ColorConvertBase*, self);
}


ColorConvert24::ColorConvert24()
{
    mClip = ((uint8*)mCoefTbl32) + 400;
}


OSCL_EXPORT_REF ColorConvert24::~ColorConvert24()
{
}


int32 ColorConvert24::Init(int32 Src_width, int32 Src_height, int32 Src_pitch, int32 Dst_width, int32 Dst_height, int32 Dst_pitch, int32 nRotation)
{
    if (ColorConvertBase::Init(Src_width, Src_height, Src_pitch, Dst_width, Dst_height, Dst_pitch, nRotation) == 0)
    {
        return 0;
    }

    _mInitialized = false;
    if (Src_width&0x3) return 0; // must be multiple of 4.

    //local init
    _mInitialized = true;

    //default no zoom
    SetMode(0); // called after init
    SetYuvFullRange(false);

    return 1;
}


int32 ColorConvert24::SetYuvFullRange(bool range)
{
    OSCL_ASSERT(_mInitialized == true);

    _mYuvRange = range;

    if (_mYuvRange == false)
    {
        *((uint32*)(mClip - 400)) = 0x0000b2ce; //65536*0.813/1.164;
        *((uint32*)(mClip - 396)) =  0x00015f03; //65536*1.596/1.164;
        *((uint32*)(mClip - 392)) =  0x000055fe; //65536*0.391/1.164;
        *((uint32*)(mClip - 388)) =  0x0001bbd2; //65536*2.018/1.164;

        int32 tmp;
        for (int32 i = -384; i < 640; i++)
        {
            tmp = (int32)(1.164 * (i - 16));
            mClip[i] = (tmp < 0) ? 0 : ((tmp > 255) ? 255 : (uint8)tmp);
        }
    }
    else // full range 0-255
    {
        *((uint32*)(mClip - 400)) = (int)(65536 * 0.4681); //0.714);
        *((uint32*)(mClip - 396)) = (int)(65536 * 1.5748);//1.402);
        *((uint32*)(mClip - 392)) = (int)(65536 * 0.1873);//0.344);
        *((uint32*)(mClip - 388)) = (int)(65536 * 1.8556);//1.772);
        int32 tmp;
        for (int32 i = -384; i < 640; i++)
        {
            tmp = i;
            mClip[i] = (tmp < 0) ? 0 : ((tmp > 255) ? 255 : (uint8)tmp);
        }
    }

    return 1;
}

int32 ColorConvert24::SetMode(int32 nMode)  //iMode : 0 Off, 1 On
{
    OSCL_ASSERT(_mInitialized == true);

    if (nMode == 0)
    {
        mPtrYUV2RGB =   &ColorConvert24::get_frame24;
        _mState     =   0;
        _mDisp.src_pitch = _mSrc_pitch  ;
        _mDisp.dst_pitch = _mDst_pitch  ;
        _mDisp.src_width = _mSrc_width  ;
        _mDisp.src_height = _mSrc_height ;
        _mDisp.dst_width = _mSrc_width  ;
        _mDisp.dst_height = _mSrc_height ;
    }
    else
    {
        if (_mIsZoom)
        {
            if (_mRotation&0x1) /* zoom and rotate */
            {
                mPtrYUV2RGB = &ColorConvert24::cc24ZoomRotate;
            }
            else /* zoom only */
            {
                mPtrYUV2RGB =   &ColorConvert24::cc24ZoomIn;
            }
        }
        else
        {
            if (_mRotation&0x1) /* rotate only*/
            {
                mPtrYUV2RGB = &ColorConvert24::cc24Rotate;
            }
            else /* no zoom, no rotate, SetMode(1) = SetMode(0) */
            {
                mPtrYUV2RGB =   &ColorConvert24::get_frame24;
            }
        }
        _mState     =   nMode;
        _mDisp.src_pitch = _mSrc_pitch  ;
        _mDisp.dst_pitch = _mDst_pitch  ;
        _mDisp.src_width = _mSrc_width  ;
        _mDisp.src_height = _mSrc_height ;
        _mDisp.dst_width = _mDst_width  ;
        _mDisp.dst_height = _mDst_height ;
    }

    return 1;
}

int32 ColorConvert24::GetOutputBufferSize(void)
{
    OSCL_ASSERT(_mInitialized == true);
    // for zoom, need extra line of RGB buffer for processing otherwise memory will corrupt.
    if (_mIsZoom)
    {
        return  _mState ? ((_mDst_height + 1)*_mDst_pitch*3) : (_mDst_pitch*_mSrc_height*3);
    }
    else
    {
        return  _mState ? ((_mDst_height)*_mDst_pitch*3) : (_mDst_pitch*_mSrc_height*3);
    }
}


int32 ColorConvert24::Convert(uint8 **yuvBuf, uint8 *rgbBuf)
{
    OSCL_ASSERT(_mInitialized == true);
    OSCL_ASSERT(yuvBuf);
    OSCL_ASSERT(yuvBuf[0]);
    OSCL_ASSERT(yuvBuf[1]);
    OSCL_ASSERT(yuvBuf[2]);
    OSCL_ASSERT(rgbBuf);


    if (((uint)rgbBuf)&0x3 || ((uint)yuvBuf[0])&0x3) /* address is not word align */
    {
        return 0;
    }

    (*this.*mPtrYUV2RGB)(yuvBuf, rgbBuf, &_mDisp, (uint8 *)mClip);

    return 1;
}


int32 ColorConvert24::Convert(uint8 *yuvBuf, uint8 *rgbBuf)
{
    //this conversion will cause problems when do src clipping. However, if they want, they must give more info
    uint8 *TmpYuvBuf[3];

    OSCL_ASSERT(_mInitialized == true);
    OSCL_ASSERT(yuvBuf);
    OSCL_ASSERT(rgbBuf);

    if (((uint)rgbBuf)&0x3 || ((uint)yuvBuf)&0x3) /* address is not word align */
    {
        return 0;
    }

    TmpYuvBuf[0]    =   yuvBuf;
    TmpYuvBuf[1]    =   yuvBuf + (_mSrc_pitch) * (_mSrc_mheight);
    TmpYuvBuf[2]    =   TmpYuvBuf[1] + (_mSrc_pitch * _mSrc_mheight) / 4;
    (*this.*mPtrYUV2RGB)(TmpYuvBuf, rgbBuf, &_mDisp, (uint8 *)mClip);

    return 1;
}

int32 cc24(uint8 **src, uint8 *dst, int32 *disp_prop, uint8 *coeff_tbl);

int32 ColorConvert24::get_frame24(uint8 **src, uint8 *dst, DisplayProperties *disp, uint8 *clip)
{
    int32 disp_prop[8];

    disp_prop[0] = disp->src_pitch;
    disp_prop[1] = disp->dst_pitch;
    disp_prop[2] = disp->src_width;
    disp_prop[3] = disp->src_height;
    disp_prop[4] = disp->dst_width;
    disp_prop[5] = disp->dst_height;
    disp_prop[6] = (_mRotation > 0 ? 1 : 0);
    disp_prop[7] = _mIsFlip;

//  if(disp_prop[6]^disp_prop[7])   /* flip and rotate 180*/
//  {
//      return 0 ;//not yet implemented cc24Reverse(src,dst,disp_prop,coff_tbl);
//  }
//  else
    {
        return cc24(src, dst, disp_prop, clip);
    }
}

/*---------------------------------------------------------------------------------
 * CC24 WITH ARMV6 ASSEMBLY, FULL RANGE
 *---------------------------------------------------------------------------------
 */

int32 cc24(uint8 **src, uint8 *dst, int32 *disp, uint8 *clip)
{
    uint8 *pCb, *pCr;
    uint16 *pY;
    uint8   *pDst;
    int32   src_pitch, dst_pitch, dst_pitch3, src_width;
    int32   Y, Cb, Cr, Cg;
    int32   deltaY, deltaDst, deltaCbCr;
    int32   row, col;
    int32   tmp0, tmp1, tmp2, rgb, rgb2;

    src_pitch   =   disp[0];
    dst_pitch   =   disp[1];
    src_width   =   disp[2];

    if (disp[6]) /* rotate 180 and flip */
    {   /* move the starting point to the bottom-left corner of the picture */
        deltaY = src_pitch * (disp[3] - 1);
        pY = (uint16*)(src[0] + deltaY);
        deltaY = (src_pitch >> 1) * ((disp[3] >> 1) - 1);
        pCb = src[1] + deltaY;
        pCr = src[2] + deltaY;
        deltaY = -src_width - (src_pitch << 1);
        deltaCbCr = -((src_width + src_pitch) >> 1);
        src_pitch = -(src_pitch >> 1);
    }
    else
    {
        deltaY      = (src_pitch << 1) - src_width;
        deltaCbCr   = (src_pitch - src_width) >> 1;
        pY = (uint16 *)src[0];
        pCb = src[1];
        pCr = src[2];
        src_pitch >>= 1;
    }

    deltaDst    = ((dst_pitch << 1) - src_width) * 3;
    pDst =  dst;

    dst_pitch3  =   3 * dst_pitch;

    for (row = disp[3]; row > 0; row -= 2)
    {

        for (col = src_width; col > 0; col -= 4)
        {

            Cb = *pCb++;
            Cr = *pCr++;

            //load the bottom two pixels
            //Y =   *(((uint16 *)pY)+src_pitch);
            Y   =   pY[src_pitch];

            Cb -= 128;
            Cr -= 128;
            Cg  =   Cr * (*((int32*)(clip - 400)));
            Cg  +=  Cb * (*((int32*)(clip - 392)));

            Cr  *= (*((int32*)(clip - 396)));
            Cb  *= (*((int32*)(clip - 388)));

            tmp0    = (Y << 16) & 0xFF0000;     //Low endian    left pixel
            tmp1    =   tmp0 - Cg;
            tmp2    =   tmp0 + Cb;
            tmp0    =   tmp0 + Cr;

            tmp0    =   clip[tmp0>>16];
            tmp1    =   clip[tmp1>>16];
            tmp2    =   clip[tmp2>>16];
#if RGB_FORMAT
            rgb =   tmp0 | (tmp1 << 8); /* r1 & g1 */
#else
            rgb =   tmp2 | (tmp1 << 8); /* b1 & g1 */
#endif
            Y   = (Y << 8) & 0xFF0000;
#if RGB_FORMAT
            tmp0    =   Y + Cr;
            tmp0    =   clip[tmp0>>16];
            rgb     |= (tmp0 << 24);
            rgb     |= (tmp2 << 16); // tmp2 | (tmp0<<8); /* b1 & r2 */
            tmp2    =   Y + Cb;
            tmp2    =   clip[tmp2>>16];
#else
            tmp2    =   Y + Cb;
            tmp2    =   clip[tmp2>>16];
            rgb     |= (tmp2 << 24);
            rgb     |= (tmp0 << 16); //tmp0 | (tmp2<<8); /* r1 & b2 */
            tmp0    =   Y + Cr;
            tmp0    =   clip[tmp0>>16];
#endif
            *((uint32 *)(pDst + dst_pitch3))    =   rgb;

            tmp1    =   Y - Cg;
            tmp1    =   clip[tmp1>>16];
#if RGB_FORMAT
            rgb2    =   tmp1 | (tmp2 << 8); /* g2 & b2 */
#else
            rgb2    =   tmp1 | (tmp0 << 8); /* g2 & r2 */
#endif
            //load the top two pixels
            Y   =   *pY++;

            tmp0    = (Y << 16) & 0xFF0000;     //Low endian    left pixel
            tmp1    =   tmp0 - Cg;
            tmp2    =   tmp0 + Cb;
            tmp0    =   tmp0 + Cr;

            tmp0    =   clip[tmp0>>16];
            tmp1    =   clip[tmp1>>16];
            tmp2    =   clip[tmp2>>16];

#if RGB_FORMAT
            rgb =   tmp0 | (tmp1 << 8); /* r1 & g1 */
#else
            rgb =   tmp2 | (tmp1 << 8); /* b1 & g1 */
#endif
            Y   = (Y << 8) & 0xFF0000;

#if RGB_FORMAT
            tmp0    =   Y + Cr;
            tmp0    =   clip[tmp0>>16];
            rgb     |= (tmp0 << 24);
            rgb     |= (tmp2 << 16); //tmp2 | (tmp0<<8); /* r1 & b2 */
            tmp2    =   Y + Cb;
            tmp2    =   clip[tmp2>>16];
#else
            tmp2    =   Y + Cb;
            tmp2    =   clip[tmp2>>16];
            rgb     |= (tmp2 << 24);
            rgb     |= (tmp0 << 16); //tmp0 | (tmp2<<8); /* b1 & r2 */
            tmp0    =   Y + Cr;
            tmp0    =   clip[tmp0>>16];
#endif
            *((uint32 *)(pDst)) =   rgb;

            tmp1    =   Y - Cg;
            tmp1    =   clip[tmp1>>16];

#if RGB_FORMAT
            rgb =   tmp1 | (tmp2 << 8); /* g2 & b2 */
#else
            rgb =   tmp1 | (tmp0 << 8); /* g2 & r2 */
#endif

            //// next 2x2 pixels

            Cb = *pCb++;
            Cr = *pCr++;

            //load the bottom two pixels
            //Y =   *(((uint16 *)pY)+src_pitch);
            Y   =   pY[src_pitch];

            Cb -= 128;
            Cr -= 128;
            Cg  =   Cr * (*((int32*)(clip - 400)));
            Cg  +=  Cb * (*((int32*)(clip - 392)));

            Cr  *= (*((int32*)(clip - 396)));
            Cb  *= (*((int32*)(clip - 388)));

            tmp0    = (Y << 16) & 0xFF0000;     //Low endian    left pixel
            tmp1    =   tmp0 - Cg;
            tmp2    =   tmp0 + Cb;
            tmp0    =   tmp0 + Cr;

            tmp0    =   clip[tmp0>>16];
            tmp1    =   clip[tmp1>>16];
            tmp2    =   clip[tmp2>>16];
#if RGB_FORMAT
            rgb2    |= (tmp1 << 24);
            rgb2    |= (tmp0 << 16);
            //rgb   =   tmp0 | (tmp1<<8); /* r3 & g3 */
#else
            rgb2    |= (tmp1 << 24);
            rgb2    |= (tmp2 << 16);
//rgb   =   tmp2 | (tmp1<<8); /* b3 & g3 */
#endif
            *((uint32 *)(pDst + dst_pitch3 + 4)) = rgb2;

            Y   = (Y << 8) & 0xFF0000;
#if RGB_FORMAT
            tmp0    =   Y + Cr;
            tmp0    =   clip[tmp0>>16];
            rgb2    =   tmp2 | (tmp0 << 8); /* b3 & r4 */
            tmp2    =   Y + Cb;
            tmp2    =   clip[tmp2>>16];
#else
            tmp2    =   Y + Cb;
            tmp2    =   clip[tmp2>>16];
            rgb2    =   tmp0 | (tmp2 << 8); /* r3 & b4 */
            tmp0    =   Y + Cr;
            tmp0    =   clip[tmp0>>16];
#endif
            tmp1    =   Y - Cg;
            tmp1    =   clip[tmp1>>16];
#if RGB_FORMAT
            rgb2    |= (tmp2 << 24);
            rgb2    |= (tmp1 << 16); // tmp1|(tmp2<<8); /* g2 & b2 */
#else
            rgb2    |= (tmp0 << 24);
            rgb2    |= (tmp1 << 16); // tmp1|(tmp0<<8); /* g2 & r2 */
#endif
            *((uint32 *)(pDst + dst_pitch3 + 8)) = rgb2;

            //load the top two pixels
            Y   =   *pY++;

            tmp0    = (Y << 16) & 0xFF0000;     //Low endian    left pixel
            tmp1    =   tmp0 - Cg;
            tmp2    =   tmp0 + Cb;
            tmp0    =   tmp0 + Cr;

            tmp0    =   clip[tmp0>>16];
            tmp1    =   clip[tmp1>>16];
            tmp2    =   clip[tmp2>>16];

#if RGB_FORMAT
            rgb     |= (tmp1 << 24);
            rgb     |= (tmp0 << 16); //tmp0 | (tmp1<<8); /* r1 & g1 */
#else
            rgb     |= (tmp1 << 24);
            rgb     |= (tmp2 << 16); //tmp2 | (tmp1<<8); /* b1 & g1 */
#endif
            *((uint32*)(pDst + 4)) = rgb;

            Y   = (Y << 8) & 0xFF0000;

#if RGB_FORMAT
            tmp0    =   Y + Cr;
            tmp0    =   clip[tmp0>>16];
            rgb     =   tmp2 | (tmp0 << 8); /* r1 & b2 */
            tmp2    =   Y + Cb;
            tmp2    =   clip[tmp2>>16];
#else
            tmp2    =   Y + Cb;
            tmp2    =   clip[tmp2>>16];
            rgb     =   tmp0 | (tmp2 << 8); /* b1 & r2 */
            tmp0    =   Y + Cr;
            tmp0    =   clip[tmp0>>16];
#endif

            tmp1    =   Y - Cg;
            tmp1    =   clip[tmp1>>16];

#if RGB_FORMAT
            rgb     |= (tmp2 << 24);
            rgb     |= (tmp1 << 16);  //tmp1|(tmp2<<8); /* g2 & b2 */
#else
            rgb     |= (tmp0 << 24);
            rgb     |= (tmp1 << 16);  //tmp1|(tmp0<<8); /* g2 & r2 */
#endif
            *((uint32*)(pDst + 8)) = rgb;

            pDst += 12;
        }//end of COL

        pY  += (deltaY >> 1);
        pCb +=  deltaCbCr;
        pCr +=  deltaCbCr;
        pDst += (deltaDst); //coz pDst defined as UINT *
    }

    return 1;
}

int32 ColorConvert24::cc24Rotate(uint8 **src, uint8 *dst, DisplayProperties *disp, uint8 *clip)
{
#ifdef CCROTATE
    uint8 *pCb, *pCr;
    uint8 *pY;
    uint8 *pDst;
    int32       src_pitch, dst_pitch, src_width, dst_pitch3;
    int32       Y, Cb, Cr, Cg;
    int32       deltaY, deltaDst, deltaCbCr;
    int32       row, col;
    int32       tmp0, tmp1, tmp2;
    int32 half_src_pitch, read_idx, tmp_src_pitch;

    src_pitch   =   disp->src_pitch;
    dst_pitch   =   disp->dst_pitch;
    src_width   =   disp->src_width;

    deltaDst    =   3 * ((dst_pitch << 1) - disp->dst_width); // 3*((dst_pitch<<1) - src_height)

    if (_mRotation == CCROTATE_CLKWISE)
    {   // go from top-left to bottom-left
        deltaY      =  src_pitch * disp->src_height + 2;
        deltaCbCr   = ((src_pitch * disp->src_height) >> 2) + 1;
    }
    else  // rotate counterclockwise
    {   // go from bottom-right back to top-right
        deltaY      =  -(src_pitch * disp->src_height + 2);
        deltaCbCr   =  -(((src_pitch * disp->src_height) >> 2) + 1);
    }

    // map origin of the destination to the source
    if (_mRotation == CCROTATE_CLKWISE)
    {   // goto bottom-left
        pY = src[0] + src_pitch * (disp->src_height - 1);
        pCb = src[1] + ((src_pitch >> 1) * ((disp->src_height >> 1) - 1));
        pCr = src[2] + ((src_pitch >> 1) * ((disp->src_height >> 1) - 1));
    }
    else  // rotate counterclockwise
    {   // goto top-right
        pY = src[0] + src_width - 1;
        pCb = src[1] + (src_width >> 1) - 1;
        pCr = src[2] + (src_width >> 1) - 1;
    }

    if (_mRotation == CCROTATE_CLKWISE)
    {
        half_src_pitch = -(src_pitch >> 1);
        read_idx = 1;
        tmp_src_pitch = -src_pitch;
    }
    else // rotate counterclockwise
    {
        half_src_pitch = (src_pitch >> 1);
        read_idx = -1;
        tmp_src_pitch = src_pitch;
    }

    pDst =  dst;

    dst_pitch3  =   3 * dst_pitch;

    for (row = src_width; row > 0; row -= 2)
    {

        for (col = disp->src_height - 1; col >= 0; col -= 2)
        {

            Cb = *pCb;
            pCb += half_src_pitch;
            Cr = *pCr;
            pCr += half_src_pitch;

            Cb -= 128;
            Cr -= 128;
            Cg  =   Cr * (*((int32*)(clip - 400)));
            Cg  +=  Cb * (*((int32*)(clip - 392)));

            Cr  *= (*((int32*)(clip - 396)));
            Cb  *= (*((int32*)(clip - 388)));

            //process the bottom two pixels in RGB plane
            tmp0    =   pY[read_idx]; /* top-left pixel */

            tmp1    = (tmp0 << 16) - Cg;
            tmp2    = (tmp0 << 16) + Cb;
            tmp0    = (tmp0 << 16) + Cr;

            tmp0    =   clip[tmp0>>16];
            tmp1    =   clip[tmp1>>16];
            tmp2    =   clip[tmp2>>16];

#if RGB_FORMAT
            *((uint16 *)(pDst + dst_pitch3))    =   tmp0 | (tmp1 << 8); /* r1 & g1 */
#else
            *((uint16 *)(pDst + dst_pitch3))    =   tmp2 | (tmp1 << 8); /* b1 & g1 */
#endif
            Y       =   pY[read_idx+tmp_src_pitch];  /* bottom-left pixel */
#if RGB_FORMAT
            tmp0    = (Y << 16) + Cr;
            tmp0    =   clip[tmp0>>16];
            *((uint16 *)(pDst + dst_pitch3 + 2))    =   tmp2 | (tmp0 << 8); /* b1 & r2 */
            tmp2    = (Y << 16) + Cb;
            tmp2    =   clip[tmp2>>16];
#else
            tmp2    = (Y << 16) + Cb;
            tmp2    =   clip[tmp2>>16];
            *((uint16 *)(pDst + dst_pitch3 + 2))    =   tmp0 | (tmp2 << 8); /* r1 & b2 */
            tmp0    = (Y << 16) + Cr;
            tmp0    =   clip[tmp0>>16];
#endif
            tmp1    = (Y << 16) - Cg;
            tmp1    =   clip[tmp1>>16];

#if RGB_FORMAT
            *((uint16*)(pDst + dst_pitch3 + 4)) =   tmp1 | (tmp2 << 8); /* g2 & b2 */
#else
            *((uint16*)(pDst + dst_pitch3 + 4)) =   tmp1 | (tmp0 << 8); /* g2 & r2 */
#endif
            //process the top two pixels in RGB plane

            tmp0    =   *pY; /*upper-right pixel */
            tmp1    = (tmp0 << 16) - Cg;
            tmp2    = (tmp0 << 16) + Cb;
            tmp0    = (tmp0 << 16) + Cr;

            tmp0    =   clip[tmp0>>16];
            tmp1    =   clip[tmp1>>16];
            tmp2    =   clip[tmp2>>16];

#if RGB_FORMAT
            *((uint16 *)pDst)   =   tmp0 | (tmp1 << 8); /* r1 & g1 */
#else
            *((uint16 *)pDst)   =   tmp2 | (tmp1 << 8); /* b1 & g1 */
#endif
            Y       =   pY[tmp_src_pitch]; /* bottom-right pixel */
            pY += (tmp_src_pitch << 1);
#if RGB_FORMAT
            tmp0    = (Y << 16) + Cr;
            tmp0    =   clip[tmp0>>16];
            *((uint16 *)(pDst + 2)) =   tmp2 | (tmp0 << 8); /* b1 & r2 */
            tmp2    = (Y << 16) + Cb;
            tmp2    =   clip[tmp2>>16];
#else
            tmp2    = (Y << 16) + Cb;
            tmp2    =   clip[tmp2>>16];
            *((uint16 *)(pDst + 2)) =   tmp0 | (tmp2 << 8); /* r1 & b2 */
            tmp0    = (Y << 16) + Cr;
            tmp0    =   clip[tmp0>>16];
#endif
            tmp1    = (Y << 16) - Cg;
            tmp1    =   clip[tmp1>>16];
#if RGB_FORMAT
            *((uint16*)(pDst + 4))  =   tmp1 | (tmp2 << 8); /* g2 & r2 */
#else
            *((uint16*)(pDst + 4))  =   tmp1 | (tmp0 << 8); /* g2 & b2 */
#endif
            pDst += 6;

        }//end of COL

        pY  +=  deltaY;
        pCb +=  deltaCbCr;
        pCr +=  deltaCbCr;
        pDst += (deltaDst);
    }

    return 1;
#else
    return 0;
#endif // CCROTATE
}


// platform specific C function
int32 cc24scaling(uint8 **src, uint8 *dst, int32 *disp,
                  uint8 *clip,
                  uint8 *_mRowPix, uint8 *_mColPix);

/////////////////////////////////////////////////////////////////////////////
// Note:: This zoom algorithm needs an extra line of RGB buffer. So, users
// have to use GetRGBBufferSize API to get the size it needs. See GetRGBBufferSize().
int32 ColorConvert24::cc24ZoomIn(uint8 **src, uint8 *dst,
                                 DisplayProperties *disp, uint8 *clip)
{
    int32 disp_prop[6];

    disp_prop[0] = disp->src_pitch;
    disp_prop[1] = disp->dst_pitch;
    disp_prop[2] = disp->src_width;
    disp_prop[3] = disp->src_height;
    disp_prop[4] = disp->dst_width;
    disp_prop[5] = disp->dst_height;

    return cc24scaling(src, dst, disp_prop, clip, _mRowPix, _mColPix);
}


int32 cc24scaling(uint8 **src, uint8 *dst, int32 *disp,
                  uint8 *clip,
                  uint8 *_mRowPix, uint8 *_mColPix)
{
#if CCSCALING
    uint8 *pCb, *pCr;
    uint8 *pY;
    uint8 *pDst;
    int32 src_pitch, dst_pitch, dst_pitch3, src_width;
    int32 Y, Cb, Cr, Cg;
    int32 deltaY, dst_width3, deltaCbCr;
    int32 row, col;
    int32 tmp0, tmp1, tmp2;
    uint32 rgb;
    int32 offset;

    src_pitch = disp[0];
    dst_pitch = disp[1];
    src_width = disp[2];

    deltaY = (src_pitch << 1) - src_width;
    deltaCbCr = (src_pitch - src_width) >> 1;
    dst_width3 = disp[4] * 3;

    pY = src[0];
    pCb = src[1];
    pCr = src[2];

    pDst = dst;

    dst_pitch3 = 3 * dst_pitch;

    for (row = disp[3] - 1; row >= 0; row -= 2)
    {/* decrement index, _mColPix[.] is
                                                     symmetric to increment index */
        if ((_mColPix[row-1] == 0) && (_mColPix[row] == 0))
        {
            pCb += (src_pitch >> 1);
            pCr += (src_pitch >> 1);
            pY += (src_pitch << 1);
            continue;
        }

        for (col = src_width - 2; col >= 0; col -= 2)
        { /* decrement index, _mRowPix[.] is
                                                     symmetric to increment index */

            Cb = *pCb++;
            Cr = *pCr++;

            //load the bottom two pixels
            Cb -= 128;
            Cr -= 128;
            Cg  =   Cr * (*((int32*)(clip - 400)));
            Cg  +=  Cb * (*((int32*)(clip - 392)));

            Cr  *= (*((int32*)(clip - 396)));
            Cb  *= (*((int32*)(clip - 388)));

            if (_mRowPix[col])  /* compute this pixel */
            {
                tmp0    =   pY[src_pitch];          //bottom left

                tmp1    = (tmp0 << 16) - Cg;
                tmp2    = (tmp0 << 16) + Cb;
                tmp0    = (tmp0 << 16) + Cr;

                tmp0    =   clip[tmp0>>16];
                tmp1    =   clip[tmp1>>16];
                tmp2    =   clip[tmp2>>16];
#if RGB_FORMAT
                rgb = tmp0 | (tmp1 << 8) | (tmp2 << 16);
#else
                rgb = tmp2 | (tmp1 << 8) | (tmp0 << 16);
#endif
                Y   =   *pY++;                      //upper left
                tmp1    = (Y << 16) - Cg;
                tmp2    = (Y << 16) + Cb;
                tmp0    = (Y << 16) + Cr;

                tmp0    =   clip[tmp0>>16];
                tmp1    =   clip[tmp1>>16];
                tmp2    =   clip[tmp2>>16];
#if RGB_FORMAT
                tmp2 = ((tmp2 << 16) | (tmp1 << 8) | tmp0);
#else
                tmp2 |= ((tmp0 << 16) | (tmp1 << 8));
#endif
                if (((uint)pDst)&1) /* not word-aligned */
                {

                    *(pDst + dst_pitch3)    =   rgb & 0xFF; /* b */
                    *((uint16*)(pDst + dst_pitch3 + 1)) = rgb >> 8; /* gr */
                    *pDst = tmp2 & 0xFF;  /* b */
                    *((uint16*)(pDst + 1)) = tmp2 >> 8; /* gr */

                    if (_mRowPix[col] == 2)
                    {
                        *((uint16*)(pDst + dst_pitch3 + 3)) =   rgb & 0xFFFF; /* bg */
                        *(pDst + dst_pitch3 + 5) = rgb >> 16; /* r */
                        *((uint16*)(pDst + 3))  =   tmp2 & 0xFFFF; /* bg */
                        *(pDst + 5) = tmp2 >> 16; /* r */

                    }
                    else if (_mRowPix[col] == 3)
                    {
                        *((uint16*)(pDst + dst_pitch3 + 3)) =   rgb & 0xFFFF; /* bg */
                        *((uint16*)(pDst + dst_pitch3 + 5)) = (uint16)((rgb << 8) | (rgb >> 16)); /* rb */
                        *((uint16*)(pDst + dst_pitch3 + 7)) =   rgb >> 8;  /* gr */
                        *((uint16*)(pDst + 3))  =   tmp2 & 0xFFFF; /* bg */
                        *((uint16*)(pDst + 5)) = (uint16)((tmp2 << 8) | (tmp2 >> 16)); /* rb */
                        *((uint16*)(pDst + 7)) =   tmp2 >> 8;  /* gr */
                    }
                }
                else //word aligned
                {
                    if (_mRowPix[col] == 2)
                    {
                        *((uint16*)(pDst + dst_pitch3)) =   rgb & 0xFFFF; /* bg */
                        *((uint16*)(pDst + dst_pitch3 + 2)) = (uint16)((rgb << 8) | (rgb >> 16));   /* rb */
                        *((uint16*)(pDst + dst_pitch3 + 4)) = rgb >> 8 ; /* gr */
                        *((uint16*)(pDst))  =   tmp2 & 0xFFFF; /* bg */
                        *((uint16*)(pDst + 2)) = (uint16)((tmp2 << 8) | (tmp2 >> 16));    /* rb */
                        *((uint16*)(pDst + 4)) = tmp2 >> 8 ; /* gr */
                    }
                    else if (_mRowPix[col] == 3)
                    {
                        *((uint16*)(pDst + dst_pitch3)) =   rgb & 0xFFFF; /* bg */
                        *((uint16*)(pDst + dst_pitch3 + 2)) = (uint16)((rgb << 8) | (rgb >> 16));   /* rb */
                        *((uint16*)(pDst + dst_pitch3 + 4)) = rgb >> 8 ; /* gr */
                        *((uint16*)(pDst + dst_pitch3 + 6)) = rgb & 0xFFFF; /* bg */
                        *(pDst + dst_pitch3 + 8) = rgb >> 16; /* r */
                        *((uint16*)(pDst))  =   tmp2 & 0xFFFF; /* bg */
                        *((uint16*)(pDst + 2)) = (uint16)((tmp2 << 8) | (tmp2 >> 16));    /* rb */
                        *((uint16*)(pDst + 4)) = tmp2 >> 8 ; /* gr */
                        *((uint16*)(pDst + 6)) = tmp2 & 0xFFFF; /* bg */
                        *(pDst + 8) = tmp2 >> 16; /* r */
                    }
                    else
                    {
                        *((uint16*)(pDst + dst_pitch3)) =   rgb & 0xFFFF; /* bg */
                        *(pDst + dst_pitch3 + 2)    =   rgb >> 16; /* r */
                        *((uint16*)(pDst))  =   tmp2 & 0xFFFF; /* bg */
                        *(pDst + 2) =   tmp2 >> 16; /* r */
                    }
                }
            }
            else  /* if(_mRowPix[col]) */
            {
                pY++;
            }

            pDst += _mRowPix[col] + _mRowPix[col] + _mRowPix[col];

            if (_mRowPix[col+1])    /* compute this pixel */
            {
                //load the top two pixels
                tmp0    =   pY[src_pitch];      //bottom right

                tmp1    = (tmp0 << 16) - Cg;
                tmp2    = (tmp0 << 16) + Cb;
                tmp0    = (tmp0 << 16) + Cr;

                tmp0    =   clip[tmp0>>16];
                tmp1    =   clip[tmp1>>16];
                tmp2    =   clip[tmp2>>16];
#if RGB_FORMAT
                rgb = tmp0 | (tmp1 << 8) | (tmp2 << 16);
#else
                rgb = tmp2 | (tmp1 << 8) | (tmp0 << 16);
#endif
                Y   =   *pY++;                          //upper right
                tmp1    = (Y << 16) - Cg;
                tmp2    = (Y << 16) + Cb;
                tmp0    = (Y << 16) + Cr;

                tmp0    =   clip[tmp0>>16];
                tmp1    =   clip[tmp1>>16];
                tmp2    =   clip[tmp2>>16];
#if RGB_FORMAT
                tmp2 = ((tmp2 << 16) | (tmp1 << 8) | tmp0);
#else
                tmp2 |= ((tmp0 << 16) | (tmp1 << 8));
#endif
                if (((uint)pDst)&1) /* not word-aligned */
                {

                    *(pDst + dst_pitch3)    =   rgb & 0xFF; /* r */
                    *((uint16*)(pDst + dst_pitch3 + 1)) = rgb >> 8; /* gb */
                    *pDst = tmp2 & 0xFF;  /* r */
                    *((uint16*)(pDst + 1)) = rgb >> 8; /* gb */

                    if (_mRowPix[col+1] == 2)
                    {
                        *((uint16*)(pDst + dst_pitch3 + 3)) =   rgb & 0xFFFF; /* rg */
                        *(pDst + dst_pitch3 + 5) = rgb >> 16; /* b */
                        *((uint16*)(pDst + 3))  =   tmp2 & 0xFFFF; /* rg */
                        *(pDst + 5) = tmp2 >> 16; /* b */

                    }
                    else if (_mRowPix[col+1] == 3)
                    {
                        *((uint16*)(pDst + dst_pitch3 + 3)) =   rgb & 0xFFFF; /* rg */
                        *((uint16*)(pDst + dst_pitch3 + 5)) = (uint16)((rgb << 8) | (rgb >> 16)); /* br */
                        *((uint16*)(pDst + dst_pitch3 + 7)) =   rgb >> 8;  /* gb */
                        *((uint16*)(pDst + 3))  =   tmp2 & 0xFFFF; /* rg */
                        *((uint16*)(pDst + 5)) = (uint16)((tmp2 << 8) | (tmp2 >> 16)); /* br */
                        *((uint16*)(pDst + 7)) =   tmp2 >> 8;  /* gb */
                    }
                }
                else //word aligned
                {
                    if (_mRowPix[col+1] == 2)
                    {
                        *((uint16*)(pDst + dst_pitch3)) =   rgb & 0xFFFF; /* rg */
                        *((uint16*)(pDst + dst_pitch3 + 2)) = (uint16)((rgb << 8) | (rgb >> 16));   /* br */
                        *((uint16*)(pDst + dst_pitch3 + 4)) = rgb >> 8 ; /* gb */
                        *((uint16*)(pDst))  =   tmp2 & 0xFFFF; /* rg */
                        *((uint16*)(pDst + 2)) = (uint16)((tmp2 << 8) | (tmp2 >> 16));    /* br */
                        *((uint16*)(pDst + 4)) = tmp2 >> 8 ; /* gb */
                    }
                    else if (_mRowPix[col+1] == 3)
                    {
                        *((uint16*)(pDst + dst_pitch3)) =   rgb & 0xFFFF; /* rg */
                        *((uint16*)(pDst + dst_pitch3 + 2)) = (uint16)((rgb << 8) | (rgb >> 16));   /* br */
                        *((uint16*)(pDst + dst_pitch3 + 4)) = rgb >> 8 ; /* gb */
                        *((uint16*)(pDst + dst_pitch3 + 6)) = rgb & 0xFFFF; /* rg */
                        *(pDst + dst_pitch3 + 8) = rgb >> 16; /* b */
                        *((uint16*)(pDst))  =   tmp2 & 0xFFFF; /* rg */
                        *((uint16*)(pDst + 2)) = (uint16)((tmp2 << 8) | (tmp2 >> 16));    /* br */
                        *((uint16*)(pDst + 4)) = tmp2 >> 8 ; /* gb */
                        *((uint16*)(pDst + 6)) = tmp2 & 0xFFFF; /* rg */
                        *(pDst + 8) = tmp2 >> 16; /* b */
                    }
                    else
                    {
                        *((uint16*)(pDst + dst_pitch3)) =   rgb & 0xFFFF; /* rg */
                        *(pDst + dst_pitch3 + 2)    =   rgb >> 16; /* b */
                        *((uint16*)(pDst))  =   tmp2 & 0xFFFF; /* rg */
                        *(pDst + 2) =   tmp2 >> 16; /* b */
                    }
                }
            }
            else  /* if(_mRowPix[col+1]) */
            {
                pY++;
            }

            pDst    += _mRowPix[col+1] + _mRowPix[col+1] + _mRowPix[col+1];
        }//end of COL

        pY  +=  deltaY;
        pCb +=  deltaCbCr;
        pCr +=  deltaCbCr;

        pDst -= (dst_width3);   //goes back to the beginning of the line;

        //copy down
        offset = (_mColPix[row] * dst_pitch3);

        if (_mColPix[row-1] && _mColPix[row] != 1)
        {
            oscl_memcpy(pDst + offset, pDst + dst_pitch3, dst_width3);
        }
        if (_mColPix[row-1] == 2)
        {
            oscl_memcpy(pDst + offset + dst_pitch3, pDst + dst_pitch3, dst_width3);
        }
        else if (_mColPix[row-1] == 3)
        {
            oscl_memcpy(pDst + offset + dst_pitch3, pDst + dst_pitch3, dst_width3);
            oscl_memcpy(pDst + offset + dst_pitch3*2, pDst + dst_pitch3, dst_width3);
        }

        //copy up
        if (_mColPix[row] == 2)
        {
            oscl_memcpy(pDst + dst_pitch3, pDst, dst_width3);
        }
        else if (_mColPix[row] == 3)
        {
            oscl_memcpy(pDst + dst_pitch3, pDst, dst_width3);
            oscl_memcpy(pDst + dst_pitch3*2, pDst, dst_width3);
        }

        pDst += dst_pitch3 * (_mColPix[row-1] + _mColPix[row]);
    }

    return 1;
#else
    return 0;
#endif // CCSCALING
}


// platform specfic function in C
int32 cc24sc_rotate(uint8 **src, uint8 *dst, int32 *disp,
                    uint8 *clip, uint8 *_mRowPix,
                    uint8 *_mColPix, bool _mIsRotateClkwise);

/////////////////////////////////////////////////////////////////////////////
// Note:: This zoom algorithm needs an extra line of RGB buffer. So, users
// have to use GetRGBBufferSize API to get the size it needs. See GetRGBBufferSize().
int32 ColorConvert24::cc24ZoomRotate(uint8 **src, uint8 *dst,
                                     DisplayProperties *disp, uint8 *clip)
{
    int32 disp_prop[6];

    disp_prop[0] = disp->src_pitch;
    disp_prop[1] = disp->dst_pitch;
    disp_prop[2] = disp->src_width;
    disp_prop[3] = disp->src_height;
    disp_prop[4] = disp->dst_width;
    disp_prop[5] = disp->dst_height;

    return cc24sc_rotate(src, dst, disp_prop, clip, _mRowPix, _mColPix, (_mRotation == CCROTATE_CLKWISE));
}


int32 cc24sc_rotate(uint8 **src, uint8 *dst, int32 *disp,
                    uint8 *clip, uint8 *_mRowPix,
                    uint8 *_mColPix, bool _mIsRotateClkwise)
{
#if (CCROTATE && CCSCALING)
    uint8 *pCb, *pCr;
    uint8 *pY;
    uint8 *pDst;
    int32 src_pitch, dst_pitch, dst_pitch3, src_width;
    int32 Y, Cb, Cr, Cg;
    int32 deltaY, dst_width3, deltaCbCr;
    int32 row, col;
    int32 tmp0, tmp1, tmp2;
    uint32 rgb;
    int32 half_src_pitch, read_idx, tmp_src_pitch;
    int32 offset;

    src_pitch = disp[0];
    dst_pitch = disp[1];
    src_width = disp[2];

    dst_width3 = disp[4] * 3;

    if (_mIsRotateClkwise)
    {
        deltaY = src_pitch * disp[3] + 2;
        deltaCbCr = ((src_pitch * disp[3]) >> 2) + 1;
    }
    else    // rotate counterclockwise
    {
        deltaY = -(src_pitch * disp[3] + 2);
        deltaCbCr = -(((src_pitch * disp[3]) >> 2) + 1);
    }

    // map origin of the destination to the source
    if (_mIsRotateClkwise)
    {
        pY = src[0] + src_pitch * (disp[3] - 1);
        pCb = src[1] + ((src_pitch >> 1) * ((disp[3] >> 1) - 1));
        pCr = src[2] + ((src_pitch >> 1) * ((disp[3] >> 1) - 1));
    }
    else  // rotate counterclockwise
    {
        pY = src[0] + src_width - 1;
        pCb = src[1] + (src_width >> 1) - 1;
        pCr = src[2] + (src_width >> 1) - 1;
    }

    if (_mIsRotateClkwise)
    {
        half_src_pitch = -(src_pitch >> 1);
        read_idx = 1;
        tmp_src_pitch = -src_pitch;
    }
    else // rotate counterclockwise
    {
        half_src_pitch = (src_pitch >> 1);
        read_idx = -1;
        tmp_src_pitch = src_pitch;
    }

    pDst =  dst;

    dst_pitch3  =   3 * dst_pitch;

    for (row = src_width - 1; row > 0; row -= 2)
    { /* decrement index, _mColPix[.] is
                                                     symmetric to increment index */
        if ((_mColPix[row-1] == 0) && (_mColPix[row] == 0))
        {
            pCb += read_idx;
            pCr += read_idx;
            pY += (read_idx * 2);
            continue;
        }

        for (col = disp[3] - 2; col >= 0; col -= 2)
        {/* decrement index, _mRowPix[.] is
                                                     symmetric to increment index */

            Cb = *pCb;
            pCb += half_src_pitch;
            Cr = *pCr;
            pCr += half_src_pitch;

            //load the bottom two pixels
            Cb -= 128;
            Cr -= 128;
            Cg  =   Cr * (*((int32*)(clip - 400)));
            Cg  +=  Cb * (*((int32*)(clip - 392)));

            Cr  *= (*((int32*)(clip - 396)));
            Cb  *= (*((int32*)(clip - 388)));

            if (_mRowPix[col])  /* compute this pixel */
            {

                tmp0    =   pY[read_idx];       // bottom left

                tmp1    = (tmp0 << 16) - Cg;
                tmp2    = (tmp0 << 16) + Cb;
                tmp0    = (tmp0 << 16) + Cr;

                tmp0    =   clip[tmp0>>16];
                tmp1    =   clip[tmp1>>16];
                tmp2    =   clip[tmp2>>16];
#if RGB_FORMAT
                rgb = tmp0 | (tmp1 << 8) | (tmp2 << 16);
#else
                rgb = tmp2 | (tmp1 << 8) | (tmp0 << 16);
#endif
                Y   =   *pY;
                pY += tmp_src_pitch;    // upper right

                tmp1    = (Y << 16) - Cg;
                tmp2    = (Y << 16) + Cb;
                tmp0    = (Y << 16) + Cr;

                tmp0    =   clip[tmp0>>16];
                tmp1    =   clip[tmp1>>16];
                tmp2    =   clip[tmp2>>16];
#if RGB_FORMAT
                tmp2 = ((tmp2 << 16) | (tmp1 << 8) | tmp0);
#else
                tmp2 |= ((tmp0 << 16) | (tmp1 << 8));
#endif
                if (((uint)pDst)&1) /* not word-aligned */
                {

                    *(pDst + dst_pitch3)    =   rgb & 0xFF; /* b */
                    *((uint16*)(pDst + dst_pitch3 + 1)) = rgb >> 8; /* gr */
                    *pDst = tmp2 & 0xFF;  /* b */
                    *((uint16*)(pDst + 1)) = tmp2 >> 8; /* gr */

                    if (_mRowPix[col] == 2)
                    {
                        *((uint16*)(pDst + dst_pitch3 + 3)) =   rgb & 0xFFFF; /* bg */
                        *(pDst + dst_pitch3 + 5) = rgb >> 16; /* r */
                        *((uint16*)(pDst + 3))  =   tmp2 & 0xFFFF; /* bg */
                        *(pDst + 5) = tmp2 >> 16; /* r */

                    }
                    else if (_mRowPix[col] == 3)
                    {
                        *((uint16*)(pDst + dst_pitch3 + 3)) =   rgb & 0xFFFF; /* bg */
                        *((uint16*)(pDst + dst_pitch3 + 5)) = (uint16)((rgb << 8) | (rgb >> 16)); /* rb */
                        *((uint16*)(pDst + dst_pitch3 + 7)) =   rgb >> 8;  /* gr */
                        *((uint16*)(pDst + 3))  =   tmp2 & 0xFFFF; /* bg */
                        *((uint16*)(pDst + 5)) = (uint16)((tmp2 << 8) | (tmp2 >> 16)); /* rb */
                        *((uint16*)(pDst + 7)) =   tmp2 >> 8;  /* gr */
                    }
                }
                else //word aligned
                {
                    if (_mRowPix[col] == 2)
                    {
                        *((uint16*)(pDst + dst_pitch3)) =   rgb & 0xFFFF; /* bg */
                        *((uint16*)(pDst + dst_pitch3 + 2)) = (uint16)((rgb << 8) | (rgb >> 16));   /* rb */
                        *((uint16*)(pDst + dst_pitch3 + 4)) = rgb >> 8 ; /* gr */
                        *((uint16*)(pDst))  =   tmp2 & 0xFFFF; /* bg */
                        *((uint16*)(pDst + 2)) = (uint16)((tmp2 << 8) | (tmp2 >> 16));    /* rb */
                        *((uint16*)(pDst + 4)) = tmp2 >> 8 ; /* gr */
                    }
                    else if (_mRowPix[col] == 3)
                    {
                        *((uint16*)(pDst + dst_pitch3)) =   rgb & 0xFFFF; /* bg */
                        *((uint16*)(pDst + dst_pitch3 + 2)) = (uint16)((rgb << 8) | (rgb >> 16));   /* rb */
                        *((uint16*)(pDst + dst_pitch3 + 4)) = rgb >> 8 ; /* gr */
                        *((uint16*)(pDst + dst_pitch3 + 6)) = rgb & 0xFFFF; /* bg */
                        *(pDst + dst_pitch3 + 8) = rgb >> 16; /* r */
                        *((uint16*)(pDst))  =   tmp2 & 0xFFFF; /* bg */
                        *((uint16*)(pDst + 2)) = (uint16)((tmp2 << 8) | (tmp2 >> 16));    /* rb */
                        *((uint16*)(pDst + 4)) = tmp2 >> 8 ; /* gr */
                        *((uint16*)(pDst + 6)) = tmp2 & 0xFFFF; /* bg */
                        *(pDst + 8) = tmp2 >> 16; /* r */
                    }
                    else
                    {
                        *((uint16*)(pDst + dst_pitch3)) =   rgb & 0xFFFF; /* bg */
                        *(pDst + dst_pitch3 + 2)    =   rgb >> 16; /* r */
                        *((uint16*)(pDst))  =   tmp2 & 0xFFFF; /* bg */
                        *(pDst + 2) =   tmp2 >> 16; /* r */
                    }
                }
            }
            else  /* if(_mRowPix[col]) */
            {
                pY += tmp_src_pitch;    // upper right
            }

            pDst += _mRowPix[col] + _mRowPix[col] + _mRowPix[col];

            if (_mRowPix[col+1])    /* compute this pixel */
            {
                //load the top two pixels
                tmp0    =   pY[read_idx];   //bottom right

                tmp1    = (tmp0 << 16) - Cg;
                tmp2    = (tmp0 << 16) + Cb;
                tmp0    = (tmp0 << 16) + Cr;

                tmp0    =   clip[tmp0>>16];
                tmp1    =   clip[tmp1>>16];
                tmp2    =   clip[tmp2>>16];
#if RGB_FORMAT
                rgb = tmp0 | (tmp1 << 8) | (tmp2 << 16);
#else
                rgb = tmp2 | (tmp1 << 8) | (tmp0 << 16);
#endif
                Y   =   *pY;
                pY += tmp_src_pitch;                    //upper right

                tmp1    = (Y << 16) - Cg;
                tmp2    = (Y << 16) + Cb;
                tmp0    = (Y << 16) + Cr;

                tmp0    =   clip[tmp0>>16];
                tmp1    =   clip[tmp1>>16];
                tmp2    =   clip[tmp2>>16];
#if RGB_FORMAT
                tmp2 = ((tmp2 << 16) | (tmp1 << 8) | tmp0);
#else
                tmp2 |= ((tmp0 << 16) | (tmp1 << 8));
#endif
                if (((uint)pDst)&1) /* not word-aligned */
                {

                    *(pDst + dst_pitch3)    =   rgb & 0xFF; /* r */
                    *((uint16*)(pDst + dst_pitch3 + 1)) = rgb >> 8; /* gb */
                    *pDst = tmp2 & 0xFF;  /* r */
                    *((uint16*)(pDst + 1)) = rgb >> 8; /* gb */

                    if (_mRowPix[col+1] == 2)
                    {
                        *((uint16*)(pDst + dst_pitch3 + 3)) =   rgb & 0xFFFF; /* rg */
                        *(pDst + dst_pitch3 + 5) = rgb >> 16; /* b */
                        *((uint16*)(pDst + 3))  =   tmp2 & 0xFFFF; /* rg */
                        *(pDst + 5) = tmp2 >> 16; /* b */

                    }
                    else if (_mRowPix[col+1] == 3)
                    {
                        *((uint16*)(pDst + dst_pitch3 + 3)) =   rgb & 0xFFFF; /* rg */
                        *((uint16*)(pDst + dst_pitch3 + 5)) = (uint16)((rgb << 8) | (rgb >> 16)); /* br */
                        *((uint16*)(pDst + dst_pitch3 + 7)) =   rgb >> 8;  /* gb */
                        *((uint16*)(pDst + 3))  =   tmp2 & 0xFFFF; /* rg */
                        *((uint16*)(pDst + 5)) = (uint16)((tmp2 << 8) | (tmp2 >> 16)); /* br */
                        *((uint16*)(pDst + 7)) =   tmp2 >> 8;  /* gb */
                    }
                }
                else //word aligned
                {
                    if (_mRowPix[col+1] == 2)
                    {
                        *((uint16*)(pDst + dst_pitch3)) =   rgb & 0xFFFF; /* rg */
                        *((uint16*)(pDst + dst_pitch3 + 2)) = (uint16)((rgb << 8) | (rgb >> 16));   /* br */
                        *((uint16*)(pDst + dst_pitch3 + 4)) = rgb >> 8 ; /* gb */
                        *((uint16*)(pDst))  =   tmp2 & 0xFFFF; /* rg */
                        *((uint16*)(pDst + 2)) = (uint16)((tmp2 << 8) | (tmp2 >> 16));    /* br */
                        *((uint16*)(pDst + 4)) = tmp2 >> 8 ; /* gb */
                    }
                    else if (_mRowPix[col+1] == 3)
                    {
                        *((uint16*)(pDst + dst_pitch3)) =   rgb & 0xFFFF; /* rg */
                        *((uint16*)(pDst + dst_pitch3 + 2)) = (uint16)((rgb << 8) | (rgb >> 16));   /* br */
                        *((uint16*)(pDst + dst_pitch3 + 4)) = rgb >> 8 ; /* gb */
                        *((uint16*)(pDst + dst_pitch3 + 6)) = rgb & 0xFFFF; /* rg */
                        *(pDst + dst_pitch3 + 8) = rgb >> 16; /* b */
                        *((uint16*)(pDst))  =   tmp2 & 0xFFFF; /* rg */
                        *((uint16*)(pDst + 2)) = (uint16)((tmp2 << 8) | (tmp2 >> 16));    /* br */
                        *((uint16*)(pDst + 4)) = tmp2 >> 8 ; /* gb */
                        *((uint16*)(pDst + 6)) = tmp2 & 0xFFFF; /* rg */
                        *(pDst + 8) = tmp2 >> 16; /* b */
                    }
                    else
                    {
                        *((uint16*)(pDst + dst_pitch3)) =   rgb & 0xFFFF; /* rg */
                        *(pDst + dst_pitch3 + 2)    =   rgb >> 16; /* b */
                        *((uint16*)(pDst))  =   tmp2 & 0xFFFF; /* rg */
                        *(pDst + 2) =   tmp2 >> 16; /* b */
                    }
                }
            }
            else  /* if(_mRowPix[col]) */
            {
                pY += tmp_src_pitch;    // upper right
            }

            pDst    += _mRowPix[col+1] + _mRowPix[col+1] + _mRowPix[col+1];
        }//end of COL

        pY  +=  deltaY;
        pCb +=  deltaCbCr;
        pCr +=  deltaCbCr;
        pDst -= (dst_width3);   //goes back to the beginning of the line;

        //copy down
        offset = (_mColPix[row] * dst_pitch3);

        if (_mColPix[row-1] && _mColPix[row] != 1)
        {
            oscl_memcpy(pDst + offset, pDst + dst_pitch3, dst_width3);
        }
        if (_mColPix[row-1] == 2)
        {
            oscl_memcpy(pDst + offset + dst_pitch3, pDst + dst_pitch3, dst_width3);
        }
        else if (_mColPix[row-1] == 3)
        {
            oscl_memcpy(pDst + offset + dst_pitch3, pDst + dst_pitch3, dst_width3);
            oscl_memcpy(pDst + offset + dst_pitch3*2, pDst + dst_pitch3, dst_width3);
        }

        //copy up
        if (_mColPix[row] == 2)
        {
            oscl_memcpy(pDst + dst_pitch3, pDst, dst_width3);
        }
        else if (_mColPix[row] == 3)
        {
            oscl_memcpy(pDst + dst_pitch3, pDst, dst_width3);
            oscl_memcpy(pDst + dst_pitch3*2, pDst, dst_width3);
        }

        pDst += dst_pitch3 * (_mColPix[row-1] + _mColPix[row]);
    }

    return 1;
#else
    return 0;
#endif // defined(CCROTATE) && defined(CCSCALING)
}
