Alien-FreeImage

 view release on metacpan or  search on metacpan

src/Source/LibJXR/image/encode/strPredQuantEnc.c  view on Meta::CPAN

//*@@@+++@@@@******************************************************************
//
// Copyright © Microsoft Corp.
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// 
// • Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
// • Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//*@@@---@@@@******************************************************************

#include "strcodec.h"
#include "encode.h"

I32 QUANT_Mulless(PixelI v, PixelI o, I32 r)
{
    const I32 m = v >> 31;

    assert(sizeof(PixelI) == sizeof(U32));
    return ((((v ^ m) - m + o) >> r) ^ m) - m;
}

I32 MUL32HR(U32 a, U32 b, U32 r)
{
    return (I32)((U32)((U64)a * b >> 32) >> r);
}

I32 QUANT(PixelI v, PixelI o, I32 man, I32 exp)
{
    const I32 m = v >> 31;

    assert(sizeof(PixelI) == sizeof(U32));
    return (MUL32HR((v ^ m) - m + o, man, exp) ^ m) - m;
}

Int quantizeMacroblock(CWMImageStrCodec* pSC)
{
    CWMITile * pTile = pSC->pTile + pSC->cTileColumn;
    CWMIMBInfo * pMBInfo = &pSC->MBInfo;
    const COLORFORMAT cf = pSC->m_param.cfColorFormat;
    int iChannel, i, j;

    if(/*pSC->m_param.bScaledArith && */pSC->m_param.bTranscode == FALSE)
        for(iChannel = 0; iChannel < (int)pSC->m_param.cNumChannels; iChannel ++){
            const Bool bUV = (iChannel > 0 && (cf == YUV_444 || cf == YUV_422 || cf == YUV_420));
            const int iNumBlock = (bUV ? (cf == YUV_422 ? 8 : (cf == YUV_420 ? 4 : 16)) : 16);
            const int * pOffset = (iNumBlock == 4 ? blkOffsetUV : (iNumBlock == 8 ? blkOffsetUV_422 : blkOffset));
            CWMIQuantizer * pQPDC = pTile->pQuantizerDC[iChannel];
            CWMIQuantizer * pQPLP = pTile->pQuantizerLP[iChannel] + pMBInfo->iQIndexLP;
            CWMIQuantizer * pQPHP = pTile->pQuantizerHP[iChannel] + pMBInfo->iQIndexHP;

            for(j = 0; j < iNumBlock; j ++){
                PixelI * pData = pSC->pPlane[iChannel] + pOffset[j];

                if(j == 0) // DC
                    pData[0] = (pQPDC->iMan == 0 ? QUANT_Mulless(pData[0], pQPDC->iOffset, pQPDC->iExp) : QUANT(pData[0], pQPDC->iOffset, pQPDC->iMan, pQPDC->iExp));
                else if(pSC->WMISCP.sbSubband != SB_DC_ONLY) // LP
                    pData[0] = (pQPLP->iMan == 0 ? QUANT_Mulless(pData[0], pQPLP->iOffset, pQPLP->iExp) : QUANT(pData[0], pQPLP->iOffset, pQPLP->iMan, pQPLP->iExp));

                // quantize HP
                if(pSC->WMISCP.sbSubband != SB_DC_ONLY && pSC->WMISCP.sbSubband != SB_NO_HIGHPASS)
                    for(i = 1; i < 16; i ++)
                        pData[i] = (pQPHP->iMan == 0 ? QUANT_Mulless(pData[i], pQPHP->iOffset, pQPHP->iExp) : QUANT(pData[i], pQPHP->iOffset, pQPHP->iMan, pQPHP->iExp));
            }
        }
    
    for(iChannel = 0; iChannel < (int)pSC->m_param.cNumChannels; iChannel ++){
        I32 * pDC = pSC->MBInfo.iBlockDC[iChannel];
        PixelI * pData = pSC->pPlane[iChannel];

        if(iChannel > 0 && cf == YUV_422){
            for(i = 0; i < 8; i ++){
                pDC[i] = pData[blkOffsetUV_422[i]];
            }
        }
        else if(iChannel > 0 && cf == YUV_420){
            for(i = 0; i < 4; i ++){
                pDC[i] = pData[blkOffsetUV[i]];
            }
        }
        else{
            for(i = 0; i < 16; i ++){
                pDC[i] = pData[dctIndex[2][i]];
            }
        }
    }

    return 0;
}

/* frequency domain prediction */
Void predMacroblockEnc(CWMImageStrCodec * pSC)
{
    const COLORFORMAT cf = pSC->m_param.cfColorFormat;
    const Int iChannels = (cf == YUV_420 || cf == YUV_422) ? 1 : (Int) pSC->m_param.cNumChannels;
    size_t mbX = pSC->cColumn - 1;// mbY = pSC->cRow - 1;
    CWMIMBInfo *pMBInfo = &(pSC->MBInfo);
    Int iDCACPredMode = getDCACPredMode(pSC, mbX);
    Int iDCPredMode = (iDCACPredMode & 0x3);
    Int iADPredMode = (iDCACPredMode & 0xC);
    Int iACPredMode = getACPredMode(pMBInfo, cf);
    PixelI * pOrg, * pRef;
    Int i, j, k;

    pMBInfo->iOrientation = 2 - iACPredMode;

    /* keep necessary info for future prediction */
    updatePredInfo(pSC, pMBInfo, mbX, cf);

    for(i = 0; i < iChannels; i ++){
        pOrg = pMBInfo->iBlockDC[i]; // current DC block
        
        /* DC prediction */
        if(iDCPredMode == 1){ // predict DC from top
            pOrg[0] -= (pSC->PredInfoPrevRow[i] + mbX)->iDC;
        }
        else if(iDCPredMode == 0){ // predict DC from left
            pOrg[0] -= (pSC->PredInfo[i] + mbX - 1)->iDC;
        }
        else if(iDCPredMode == 2){// predict DC from top&left
            pOrg[0] -= ((pSC->PredInfo[i] + mbX - 1)->iDC + (pSC->PredInfoPrevRow[i] + mbX)->iDC) >> 1;
        }

        /* AD prediction */
        if(iADPredMode == 4){// predict AD from top
            pRef = (pSC->PredInfoPrevRow[i] + mbX)->piAD;
            pOrg[4] -= pRef[3], pOrg[8] -= pRef[4], pOrg[12] -= pRef[5];
        }
        else if(iADPredMode == 0){// predict AD from left
            pRef = (pSC->PredInfo[i] + mbX - 1)->piAD;
            pOrg[1] -= pRef[0], pOrg[2] -= pRef[1], pOrg[3] -= pRef[2];
        }
        
        pOrg = pSC->pPlane[i];
        /* AC prediction */
        if(iACPredMode == 1){ // predict from top
            for(k = 0; k <= 192; k += 64){
                /* inside macroblock, in reverse order */
                for(j = 48; j > 0; j -= 16){
                    pOrg[k + j + 10] -= pOrg[k + j + 10 - 16];
                    pOrg[k + j +  2] -= pOrg[k + j +  2 - 16];
                    pOrg[k + j +  9] -= pOrg[k + j +  9 - 16];
                }
            }
        }
        else if(iACPredMode == 0){ // predict from left
            for(k = 0; k < 64; k += 16){
                /* inside macroblock, in reverse order */
                for(j = 192; j > 0; j -= 64){
                    pOrg[k + j + 5] -= pOrg[k + j + 5 - 64];
                    pOrg[k + j + 1] -= pOrg[k + j + 1 - 64];
                    pOrg[k + j + 6] -= pOrg[k + j + 6 - 64];



( run in 0.695 second using v1.01-cache-2.11-cpan-0bd6704ced7 )