vtprotocolplugins/DisplaySink/src/CVtImageScalerImplNearest.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 23 Nov 2009 14:47:47 +0200
changeset 0 ed9695c8bcbe
permissions -rw-r--r--
Revision: 200948

/*
* Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  Image Transforms subsystem.
*
*/


// INCLUDE FILES

#include <e32svr.h>
#include <fbs.h>

#include "CVtImageScalerImplNearest.h"
#include "cvtimage.h"

// MACROS

#ifdef _DEBUG
#    define __IF_DEBUG(t) {RDebug::t;}
#else
#    define __IF_DEBUG(t)
#endif

// LOCAL CONSTANTS AND MACROS

const TUint32 KDecimalBits = 16;        // 16.16 pseudo real format

// ============================ MEMBER FUNCTIONS ===============================

// ======================= CVtImageScalerImplNearest =======================

// -----------------------------------------------------------------------------
// CVtImageScalerImplNearest::Scale( TBool& aContinue )
// -----------------------------------------------------------------------------
TInt CVtImageScalerImplNearest::Scale( TBool& aContinue )
    {
    TInt result( KErrNone );

    aContinue = EFalse;

    // this implementation does not support different display modes for source
    // and target
    if( iSource->DisplayMode() != iTarget->DisplayMode() )
        {
        return KErrNotSupported;
        }

    // if sizes are same, just copy the data
    if( iSource->Size() == iTarget->Size() )
        {
        Mem::Copy(
            iTarget->DataAddress(),
            iSource->DataAddress(),
            iTarget->BytesPerRow() * iTarget->Size().iHeight );
        }
    else if( ( iSource->Size().iHeight * 2 == iTarget->Size().iHeight ) &&
        ( iSource->Size().iWidth * 2 == iTarget->Size().iWidth ) )
        {
        switch( iSource->DisplayMode() )
            {
            case CVtImage::EVtColor4K:
            case CVtImage::EVtColor64K:
                Scale2x4K64K();
                break;

            case CVtImage::EVtColor16M:
                Scale2x16M();
                break;

            case CVtImage::EVtColor16MU:
            case CVtImage::EVtColor16MA:
                Scale2x16MU16MA();
                break;

            default:
                if ( iSource->Type() == CVtImage::EVtImageBitmap &&
                     iTarget->Type() == CVtImage::EVtImageBitmap )
                    {
                    TRAPD( error,
                        ScaleWithBitmapScalerL(
                            CBitmapScaler::EMinimumQuality ) );
                    result = error;
                    }
                else
                    {
                    result = KErrNotSupported;
                    }
            }
        }
    else
        {
        Initialize();

        switch( iSource->DisplayMode() )
            {
            case CVtImage::EVtColor4K:
                Scale4K(
                    reinterpret_cast< const TUint16* >(
                        iSource->DataAddress() ),
                    iSource->BytesPerRow(),
                    reinterpret_cast< TUint16* >( iTarget->DataAddress() ),
                    iTarget->Size().iWidth,
                    iTarget->Size().iHeight,
                    iU,
                    iV );
                break;

            case CVtImage::EVtColor64K:
                Scale64K(
                    reinterpret_cast< const TUint16* >(
                        iSource->DataAddress() ),
                    iSource->BytesPerRow(),
                    reinterpret_cast< TUint16* >( iTarget->DataAddress() ),
                    iTarget->Size().iWidth,
                    iTarget->Size().iHeight,
                    iU,
                    iV );
                break;

            case CVtImage::EVtColor16M:
                Scale16M(
                    reinterpret_cast< const TUint8* >(
                        iSource->DataAddress() ),
                    iSource->BytesPerRow(),
                    reinterpret_cast< TUint8* >( iTarget->DataAddress() ),
                    iTarget->Size().iWidth,
                    iTarget->Size().iHeight,
                    iTarget->BytesPerRow(),
                    iU,
                    iV );
                break;

            case CVtImage::EVtColor16MU:
            case CVtImage::EVtColor16MA:
                Scale16MU16MA(
                    iSource->DataAddress(),
                    iSource->BytesPerRow(),
                    iTarget->DataAddress(),
                    iTarget->Size().iWidth,
                    iTarget->Size().iHeight,
                    iU,
                    iV );
                break;

            default:
                if ( iSource->Type() == CVtImage::EVtImageBitmap &&
                     iTarget->Type() == CVtImage::EVtImageBitmap )
                    {
                    TRAPD( error,
                        ScaleWithBitmapScalerL(
                            CBitmapScaler::EMinimumQuality ) );
                    result = error;
                    }
                else
                    {
                    result = KErrNotSupported;
                    }
            }
        }

    return result;
    }

// -----------------------------------------------------------------------------
// CVtImageScalerImplNearest::ValidateSourceTargetL(
//  const CVtImage& aSource, CVtImage& aTarget )
// -----------------------------------------------------------------------------
void CVtImageScalerImplNearest::ValidateSourceTargetL(
    const CVtImage& aSource,
    CVtImage& aTarget )
    {
    if( aSource.DisplayMode() != aTarget.DisplayMode() )
        {
        User::Leave( KErrNotSupported );
        }

    switch( aSource.DisplayMode() )
        {
        case CVtImage::EVtColor4K:
        case CVtImage::EVtColor64K:
        case CVtImage::EVtColor16M:
        case CVtImage::EVtColor16MU:
        case CVtImage::EVtColor16MA:
            break;

        default:
            // Scaling for bitmaps is supported for other display modes
            if ( !( aSource.Type() == CVtImage::EVtImageBitmap &&
                 aTarget.Type() == CVtImage::EVtImageBitmap ) )
                {
                User::Leave( KErrNotSupported );
                }
        }
    }

// -----------------------------------------------------------------------------
// CVtImageScalerImplNearest::Initialize()
// -----------------------------------------------------------------------------
void CVtImageScalerImplNearest::Initialize()
    {
    iU = ( 1 << KDecimalBits ) * iSource->Size().iWidth /
        iTarget->Size().iWidth + 1;
    iV = ( 1 << KDecimalBits ) * iSource->Size().iHeight /
        iTarget->Size().iHeight + 1;
    }

// -----------------------------------------------------------------------------
// CVtImageScalerImplNearest::Scale4K(
//  const TUint16* aSrcPtr, TUint32 aSrcWidth, TUint16* aTrgPtr,
//  TUint32 aTrgWidth, TUint32 aTrgHeight, TUint32 aDx, TUint32 aDy )
// -----------------------------------------------------------------------------
void CVtImageScalerImplNearest::Scale4K(
    const TUint16* aSrcPtr,
    TUint32 aSrcWidth,
    TUint16* aTrgPtr,
    TUint32 aTrgWidth,
    TUint32 aTrgHeight,
    TUint32 aDx,
    TUint32 aDy )
    {
    __IF_DEBUG( Print( _L( "ImageScaler [%d]: CVtImageScalerImplNearest::Scale4K() >>" ), RThread().Id().operator TUint() ) );
    // scaling 4K and 64K is equal procedure
    Scale64K( aSrcPtr, aSrcWidth, aTrgPtr, aTrgWidth, aTrgHeight, aDx, aDy );
    __IF_DEBUG( Print( _L( "ImageScaler [%d]: CVtImageScalerImplNearest::Scale4K() <<" ), RThread().Id().operator TUint() ) );
    }

// -----------------------------------------------------------------------------
// CVtImageScalerImplNearest::Scale64K(
//  const TUint16* aSrcPtr, TUint32 aSrcPitch, TUint16* aTrgPtr,
//  TUint32 aTrgWidth, TUint32 aTrgHeight, TUint32 aDx, TUint32 aDy )
// -----------------------------------------------------------------------------
void CVtImageScalerImplNearest::Scale64K(
    const TUint16* aSrcPtr,
    TUint32 aSrcPitch,
    TUint16* aTrgPtr,
    TUint32 aTrgWidth,
    TUint32 aTrgHeight,
    TUint32 aDx,
    TUint32 aDy )
    {
    __IF_DEBUG( Print( _L( "ImageScaler [%d]: CVtImageScalerImplNearest::Scale64K() >>" ), RThread().Id().operator TUint() ) );

    TUint32 sy( 0 );

    for( TUint32 y = 0; y < aTrgHeight; y++ )
        {
        const TUint16* srow =
            aSrcPtr + ( sy >> KDecimalBits ) * ( aSrcPitch >> 1 );

        TUint32 sx( 0 );

        TUint32 x( 0 );

        // loop unrolled with 8
        for( ; x < ( aTrgWidth >> 3 ); x++ )
            {
            *aTrgPtr++ = srow[ sx >> KDecimalBits ];
            sx += aDx;
            *aTrgPtr++ = srow[ sx >> KDecimalBits ];
            sx += aDx;
            *aTrgPtr++ = srow[ sx >> KDecimalBits ];
            sx += aDx;
            *aTrgPtr++ = srow[ sx >> KDecimalBits ];
            sx += aDx;
            *aTrgPtr++ = srow[ sx >> KDecimalBits ];
            sx += aDx;
            *aTrgPtr++ = srow[ sx >> KDecimalBits ];
            sx += aDx;
            *aTrgPtr++ = srow[ sx >> KDecimalBits ];
            sx += aDx;
            *aTrgPtr++ = srow[ sx >> KDecimalBits ];
            sx += aDx;
            }

        // handle remaining columns
        for( x = 0; x < ( aTrgWidth & 7 ); x++ )
            {
            *aTrgPtr++ = srow[ sx >> KDecimalBits ];
            sx += aDx;
            }

        // if target width is not even aligning is needed
        if( aTrgWidth & 1 )
            {
            aTrgPtr++;
            }

        sy += aDy;
        }

    __IF_DEBUG( Print( _L( "ImageScaler [%d]: CVtImageScalerImplNearest::Scale64K() <<" ), RThread().Id().operator TUint() ) );
    }

// -----------------------------------------------------------------------------
// CVtImageScalerImplNearest::Scale16M(
//  const TUint8* aSrcPtr, TUint32 aSrcPitch, TUint8* aTrgPtr,
//  TUint32 aTrgWidth, TUint32 aTrgHeight, TUint32 aTrgPitch, TUint32 aDx, TUint32 aDy )
// -----------------------------------------------------------------------------
void CVtImageScalerImplNearest::Scale16M(
    const TUint8* aSrcPtr,
    TUint32 aSrcPitch,
    TUint8* aTrgPtr,
    TUint32 aTrgWidth,
    TUint32 aTrgHeight,
    TUint32 aTrgPitch,
    TUint32 aDx,
    TUint32 aDy )
    {
    __IF_DEBUG( Print( _L( "ImageScaler [%d]: CVtImageScalerImplNearest::Scale16M() >>" ), RThread().Id().operator TUint() ) );

    TUint32 sy( 0 );

    for( TUint32 y = 0; y < aTrgHeight; y++ )
        {
        const TUint8* s = aSrcPtr + ( sy >> KDecimalBits ) * aSrcPitch;

        TUint8* d = aTrgPtr;

        TUint32 sx( 0 );

        TUint32 x( 0 );

        for( ; x < aTrgWidth; x++ )
            {
            const TUint8* tempSrc = s + ( sx >> KDecimalBits ) * 3;
            *d++ = *tempSrc++;
            *d++ = *tempSrc++;
            *d++ = *tempSrc++;
            sx += aDx;
            }

        aTrgPtr += aTrgPitch;

        sy += aDy;
        }

    __IF_DEBUG( Print( _L( "ImageScaler [%d]: CVtImageScalerImplNearest::Scale16M() <<" ), RThread().Id().operator TUint() ) );
    }

// -----------------------------------------------------------------------------
// CVtImageScalerImplNearest::Scale16MU16MA( const TUint32* aSrcPtr,
//  TUint32 aSrcPitch, TUint32* aTrgPtr, TUint32 aTrgWidth, TUint32 aTrgHeight,
//  TUint32 aDx, TUint32 aDy )
// -----------------------------------------------------------------------------
void CVtImageScalerImplNearest::Scale16MU16MA(
    const TUint32* aSrcPtr,
    TUint32 aSrcPitch,
    TUint32* aTrgPtr,
    TUint32 aTrgWidth,
    TUint32 aTrgHeight,
    TUint32 aDx,
    TUint32 aDy )
    {
    __IF_DEBUG( Print( _L( "ImageScaler [%d]: CVtImageScalerImplNearest::Scale16MU16MA() >>" ), RThread().Id().operator TUint() ) );

    TUint32 sy( 0 );

    for( TUint32 y = 0; y < aTrgHeight; y++ )
        {
        const TUint32* srow =
            aSrcPtr + ( sy >> KDecimalBits ) * ( aSrcPitch >> 2 );

        TUint32 sx( 0 );

        TUint32 x( 0 );

        // loop unrolled with 8
        for( ; x < ( aTrgWidth >> 3 ); x++ )
            {
            *aTrgPtr++ = srow[ sx >> KDecimalBits ];
            sx += aDx;
            *aTrgPtr++ = srow[ sx >> KDecimalBits ];
            sx += aDx;
            *aTrgPtr++ = srow[ sx >> KDecimalBits ];
            sx += aDx;
            *aTrgPtr++ = srow[ sx >> KDecimalBits ];
            sx += aDx;
            *aTrgPtr++ = srow[ sx >> KDecimalBits ];
            sx += aDx;
            *aTrgPtr++ = srow[ sx >> KDecimalBits ];
            sx += aDx;
            *aTrgPtr++ = srow[ sx >> KDecimalBits ];
            sx += aDx;
            *aTrgPtr++ = srow[ sx >> KDecimalBits ];
            sx += aDx;
            }

        // handle remaining columns
        for( x = 0; x < ( aTrgWidth & 7 ); x++ )
            {
            *aTrgPtr++ = srow[ sx >> KDecimalBits ];
            sx += aDx;
            }

        sy += aDy;
        }

    __IF_DEBUG( Print( _L( "ImageScaler [%d]: CVtImageScalerImplNearest::Scale16MU16MA() <<" ), RThread().Id().operator TUint() ) );
    }

// -----------------------------------------------------------------------------
// CVtImageScalerImplNearest::Scale2x4K64K()
// -----------------------------------------------------------------------------
void CVtImageScalerImplNearest::Scale2x4K64K()
    {
    __IF_DEBUG( Print( _L( "ImageScaler [%d]: CVtImageScalerImplNearest::Scale2x4K64K() >>" ), RThread().Id().operator TUint() ) );

    TInt sheight = iSource->Size().iHeight;
    TInt swidth = iSource->Size().iWidth;
    TInt spitch = iSource->BytesPerRow();
    TInt dpitch = iTarget->BytesPerRow();

    TUint16* s = reinterpret_cast< TUint16* >( iSource->DataAddress() );
    TUint32* d = iTarget->DataAddress();

    for( TInt y = 0; y < sheight; y++ )
        {
        TUint16* s2 = s;
        TUint32* d1 = d;
        for( TInt x = 0; x < swidth; x++ )
            {
            TUint32 p = *s2++;
            p |= ( p << 16 );
            *d1++ = p;
            }
        d = reinterpret_cast< TUint32* >(
            Mem::Copy( reinterpret_cast< TUint8* >( d ) + dpitch, d, dpitch ) );
        s = reinterpret_cast< TUint16* >(
            reinterpret_cast< TUint8* >( s ) + spitch );
        }

    __IF_DEBUG( Print( _L( "ImageScaler [%d]: CVtImageScalerImplNearest::Scale2x4K64K() <<" ), RThread().Id().operator TUint() ) );
    }

// -----------------------------------------------------------------------------
// CVtImageScalerImplNearest::Scale2x16M()
// -----------------------------------------------------------------------------
void CVtImageScalerImplNearest::Scale2x16M()
    {
    __IF_DEBUG( Print( _L( "ImageScaler [%d]: CVtImageScalerImplNearest::Scale2x16M() >>" ), RThread().Id().operator TUint() ) );

    TInt sheight = iSource->Size().iHeight;
    TInt swidth = iSource->Size().iWidth;
    TInt spitch = iSource->BytesPerRow();
    TInt dpitch = iTarget->BytesPerRow();

    TUint8* s = reinterpret_cast< TUint8* >( iSource->DataAddress() );
    TUint8* d = reinterpret_cast< TUint8* >( iTarget->DataAddress() );

    for( TInt y = 0; y < sheight; y++ )
        {
        TUint8* s2 = s;
        TUint8* d1 = d;
        for( TInt x = 0; x < swidth; x++ )
            {
            TUint8 g = *s2++;
            TUint8 b = *s2++;
            TUint8 r = *s2++;

            *d1++ = g;
            *d1++ = b;
            *d1++ = r;

            *d1++ = g;
            *d1++ = b;
            *d1++ = r;
            }
        d = Mem::Copy( d + dpitch, d, dpitch );
        s += spitch;
        }

    __IF_DEBUG( Print( _L( "ImageScaler [%d]: CVtImageScalerImplNearest::Scale2x16M() <<" ), RThread().Id().operator TUint() ) );
    }

// -----------------------------------------------------------------------------
// CVtImageScalerImplNearest::Scale2x16MU16MA()
// -----------------------------------------------------------------------------
void CVtImageScalerImplNearest::Scale2x16MU16MA()
    {
    __IF_DEBUG( Print( _L( "ImageScaler [%d]: CVtImageScalerImplNearest::Scale2x16MU16MA() >>" ), RThread().Id().operator TUint() ) );

    TInt sheight = iSource->Size().iHeight;
    TInt swidth = iSource->Size().iWidth;
    TInt spitch = iSource->BytesPerRow();
    TInt dpitch = iTarget->BytesPerRow();

    TUint32* s = iSource->DataAddress();
    TUint32* d = iTarget->DataAddress();

    for( TInt y = 0; y < sheight; y++ )
        {
        TUint32* s2 = s;
        TUint32* d1 = d;
        for( TInt x = 0; x < swidth; x++ )
            {
            TUint32 p = *s2++;
            *d1++ = p;
            *d1++ = p;
            }
        d = reinterpret_cast< TUint32* >(
            Mem::Copy( reinterpret_cast< TUint8* >( d ) + dpitch, d, dpitch ) );
        s = reinterpret_cast< TUint32* >(
            reinterpret_cast< TUint8* >( s ) + spitch );
        }

    __IF_DEBUG( Print( _L( "ImageScaler [%d]: CVtImageScalerImplNearest::Scale2x16MU16MA() <<" ), RThread().Id().operator TUint() ) );
    }

// End of File