Alien-FreeImage

 view release on metacpan or  search on metacpan

src/Source/LibJXR/image/decode/strdec.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 "decode.h"
#include "strTransform.h"
#include <math.h>
#include "perfTimer.h"

#ifdef MEM_TRACE
#define TRACE_MALLOC    1
#define TRACE_NEW       0
#define TRACE_HEAP      0
#include "memtrace.h"
#endif

#ifdef X86OPT_INLINE
#define _FORCEINLINE __forceinline
#else // X86OPT_INLINE
#define _FORCEINLINE
#endif // X86OPT_INLINE

#if defined(WMP_OPT_SSE2) || defined(WMP_OPT_CC_DEC) || defined(WMP_OPT_TRFM_DEC)
void StrDecOpt(CWMImageStrCodec* pSC);
#endif // OPT defined

Int processMacroblockDec(CWMImageStrCodec *);

U8 readQuantizerSB(U8 pQPIndex[MAX_CHANNELS], SimpleBitIO * pIO, size_t cChannel)
{
    U8 cChMode = 0;
    
    if(cChannel >= MAX_CHANNELS)
        return 0;

    if(cChannel > 1)
        cChMode = (U8)getBit32_SB(pIO, 2); // Channel mode

    pQPIndex[0] = (U8)getBit32_SB(pIO, 8); // Y

    if(cChMode == 1)  // MIXED
        pQPIndex[1] = (U8)getBit32_SB(pIO, 8); // UV
    else if(cChMode > 0){ // INDEPENDENT
        size_t i;

        for(i = 1; i < cChannel; i ++)
#pragma prefast(suppress: __WARNING_UNRELATED_LOOP_TERMINATION_NO_SIZEEXPR, "PREfast false alarm: 1 <= i < MAX_CHANNELS, no buffer over/underrun!")
            pQPIndex[i] = (U8)getBit32_SB(pIO, 8); // UV
    }

    return cChMode;
}

U8 readQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS], BitIOInfo * pIO, size_t cChannel, size_t iPos)
{
    U8 cChMode = 0;

    if(cChannel > 1)
        cChMode = (U8)getBit16(pIO, 2); // Channel mode

    pQuantizer[0][iPos].iIndex = (U8)getBit16(pIO, 8); // Y

    if(cChMode == 1)  // MIXED
        pQuantizer[1][iPos].iIndex = (U8)getBit16(pIO, 8); // UV
    else if(cChMode > 0){ // INDEPENDENT
        size_t i;

        for(i = 1; i < cChannel; i ++)
            pQuantizer[i][iPos].iIndex = (U8)getBit16(pIO, 8); // UV
    }

    return cChMode;
}

// packet header: 00000000 00000000 00000001 ?????xxx
// xxx:           000(spatial) 001(DC) 010(AD) 011(AC) 100(FL) 101-111(reserved)
// ?????:         (iTileY * cNumOfSliceV + iTileX) % 32
Int readPacketHeader(BitIOInfo * pIO, U8 ptPacketType, U8 pID)
{
    UNREFERENCED_PARAMETER( ptPacketType );
    UNREFERENCED_PARAMETER( pID );
    if(getBit16(pIO, 8) != 0 || getBit16(pIO, 8) != 0 || getBit16(pIO, 8) != 1)
        return ICERR_ERROR;
    getBit16(pIO, 8);
    return ICERR_OK;
}

src/Source/LibJXR/image/decode/strdec.c  view on Meta::CPAN

            
            for(k = 0; k <= pSC->WMISCP.cNumOfSliceMinus1V; k ++){
                U8 pID = (U8)((pSC->cTileRow * (pSC->WMISCP.cNumOfSliceMinus1V + 1) + k) & 0x1F);
                
                // read packet header
                if(pSC->WMISCP.bfBitstreamFormat == SPATIAL){
                    BitIOInfo * pIO = (pSC->cNumBitIO == 0 ? pSC->pIOHeader : pSC->m_ppBitIO[k]);

                    if(pIO->pWS == NULL || readPacketHeader(pIO, 0, pID) != ICERR_OK)
                        return ICERR_ERROR;
                    pSC->m_pCodingContext[k].m_iTrimFlexBits = (pSC->m_param.bTrimFlexbitsFlag) ? getBit16(pIO, 4) : 0;
                }
                else{
                    if(pSC->m_ppBitIO[k * pSC->cSB + 0] == NULL || readPacketHeader(pSC->m_ppBitIO[k * pSC->cSB + 0], 1, pID) != ICERR_OK)
                        return ICERR_ERROR;
                    if(pSC->cSB > 1){
                        if(pSC->m_ppBitIO[k * pSC->cSB + 1] == NULL || readPacketHeader(pSC->m_ppBitIO[k * pSC->cSB + 1], 2, pID) != ICERR_OK)
                            return ICERR_ERROR;
                    }
                    if(pSC->cSB > 2){
                        if(pSC->m_ppBitIO[k * pSC->cSB + 2] == NULL || readPacketHeader(pSC->m_ppBitIO[k * pSC->cSB + 2], 3, pID) != ICERR_OK)
                            return ICERR_ERROR;
//                        readTileHeaderHP(pSC, pSC->m_ppBitIO[k * pSC->cSB + 2]);
                    }
                    if(pSC->cSB > 3){
                        if(pSC->m_ppBitIO[k * pSC->cSB + 3] == NULL)
                            return ICERR_ERROR;
                        readPacketHeader(pSC->m_ppBitIO[k * pSC->cSB + 3], 4, pID);  // bad flexbits packet doesn't generate an error
                        pSC->m_pCodingContext[k].m_iTrimFlexBits = (pSC->m_param.bTrimFlexbitsFlag) ? getBit16(pSC->m_ppBitIO[k * pSC->cSB + 3], 4) : 0;
                    }
                }

                // reset coding contexts
                ResetCodingContextDec(&pSC->m_pCodingContext[k]);
            }
        }
    }
    
    if(pSC->m_bCtxLeft && pSC->m_bCtxTop && pSC->m_bSecondary == FALSE){
        CCodingContext *pContext = &pSC->m_pCodingContext[pSC->cTileColumn];
        
        readTileHeaderDC(pSC, pContext->m_pIODC);
        if(pSC->m_pNextSC != NULL)
            readTileHeaderDC(pSC->m_pNextSC, pContext->m_pIODC);
        if(pSC->cSB > 1){
            readTileHeaderLP(pSC, pContext->m_pIOLP);
            if(pSC->m_pNextSC != NULL)
                readTileHeaderLP(pSC->m_pNextSC, pContext->m_pIOLP);
        }
        if(pSC->cSB > 2){
            readTileHeaderHP(pSC, pContext->m_pIOAC);
            if(pSC->m_pNextSC != NULL)
                readTileHeaderHP(pSC->m_pNextSC, pContext->m_pIOAC);
        }
    }

    return ICERR_OK;
}

/* inverse transform and overlap possible part of a macroblock */
Int processMacroblockDec(CWMImageStrCodec * pSC)
{
    const OVERLAP olOverlap = pSC->WMISCP.olOverlap;
    // const Bool left = (pSC->cColumn == 0);
    const Bool /*top = (pSC->cRow == 0),*/ bottom = (pSC->cRow == pSC->cmbHeight);
    const Bool bottomORright = (bottom || pSC->cColumn == pSC->cmbWidth);
    // const size_t mbWidth = pSC->cmbWidth, mbX = pSC->cColumn;
    // Int iQIndex = 0;
    ERR_CODE result = ICERR_OK;
    size_t j, jend = (pSC->m_pNextSC != NULL);

    for (j = 0; j <= jend; j++) {
        if(!bottomORright){
            CCodingContext *pContext;
            
            getTilePos(pSC, pSC->cColumn, pSC->cRow);
            
            if(jend){
                pSC->m_pNextSC->cTileColumn = pSC->cTileColumn;
                pSC->m_pNextSC->cTileRow = pSC->cTileRow;
            }

            pContext = &pSC->m_pCodingContext[pSC->cTileColumn];
           
            if(readPackets(pSC) != ICERR_OK)
                return ICERR_ERROR;
         
            // check if we need to do entropy decode
			if(!pSC->m_Dparam->bDecodeFullFrame){
				if(pSC->cColumn == pSC->WMISCP.uiTileX[pSC->cTileColumn]){ // switching to a new tile
					size_t rLeft = pSC->m_Dparam->cROILeftX, rRight = pSC->m_Dparam->cROIRightX;
					size_t rTop = pSC->m_Dparam->cROITopY, rBottom = pSC->m_Dparam->cROIBottomY;
					size_t rExt = (olOverlap == OL_NONE ? 0 : olOverlap == OL_ONE ? 2 : 10);
					size_t tLeft = pSC->cColumn * 16, tTop = pSC->WMISCP.uiTileY[pSC->cTileRow] * 16;
					size_t tRight = (pSC->cTileColumn != pSC->WMISCP.cNumOfSliceMinus1V ? pSC->WMISCP.uiTileX[pSC->cTileColumn + 1] : pSC->cmbWidth) * 16;
					size_t tBottom = (pSC->cTileRow != pSC->WMISCP.cNumOfSliceMinus1H ? pSC->WMISCP.uiTileY[pSC->cTileRow + 1] : pSC->cmbHeight) * 16;

					// tile overlaps with ROI?
					pContext->m_bInROI = ((rLeft >= tRight + rExt || rTop >= tBottom + rExt || tLeft > rRight + rExt ||
						tTop > rBottom + rExt || pSC->cRow * 16 > rBottom + rExt) ? FALSE : TRUE);
				}
			}

            if(pSC->m_Dparam->bDecodeFullFrame || pContext->m_bInROI){                
                if ((result = DecodeMacroblockDC(pSC, pContext, (Int)pSC->cColumn, (Int)pSC->cRow)) != ICERR_OK)
                    return result;

                if(pSC->m_Dparam->bDecodeLP){
                    if ((result = DecodeMacroblockLowpass(pSC, pContext, (Int)pSC->cColumn, (Int)pSC->cRow)) != ICERR_OK)
                        return result;
                }

                predDCACDec(pSC);
                                
                dequantizeMacroblock(pSC);

                if(pSC->m_Dparam->bDecodeHP){
                    if ((result = DecodeMacroblockHighpass(pSC, pContext, (Int)pSC->cColumn, (Int)pSC->cRow)) != ICERR_OK)
                        return result;
                    predACDec(pSC);
                }
           
                /* keep necessary info for future prediction */
                updatePredInfo(pSC, &pSC->MBInfo, (Int)pSC->cColumn, pSC->m_param.cfColorFormat);
            }
        }

        if((!pSC->m_Dparam->bDecodeFullFrame) &&
            ((pSC->cColumn * 16 > pSC->m_Dparam->cROIRightX  + 25) || (pSC->cColumn * 16 + 25 < pSC->m_Dparam->cROILeftX)
            || (pSC->cRow * 16 > pSC->m_Dparam->cROIBottomY + 25) || (pSC->cRow * 16 + 25 < pSC->m_Dparam->cROITopY)))
        {
            // do nothing
        }
        else {
            pSC->Transform(pSC);
        }

        if (jend) {
            pSC->m_pNextSC->cRow = pSC->cRow;
            pSC->m_pNextSC->cColumn = pSC->cColumn;
            pSC = pSC->m_pNextSC;
        }
    }

    return result;
}

//================================================================
// Inverse Color Conversion 
//#define _ICC1(r, g, b) (g^=b^=g^=b, r^=g^=r^=g, b += ((g) >> 1), r += ((g) >> 1), g -= (b+3*r+2) >> 2) 
//#define _ICC(r, g, b) (g^=b^=g^=b, r^=g^=r^=g, b += ((g) >> 1), r += ((g) >> 1), g -= (b+3*r+2) >> 2) 
//================================================================
//#define _ICC1(r, g, b) r -= (g >> 1), g += r, r -= ((b + 1) >> 1), b += r
//#define _ICC(r, g, b) r -= (g >> 1), g += r, r -= (b >> 1), b += r

#define _ICC(r, g, b)  (g -= ((r + 0) >> 1), r -= ((b + 1) >> 1) - g, b += r)
#define _ICC_CMYK(c, m, y, k) (k -= ((m + 1) >> 1), m -= (c >> 1) - k, c -= ((y + 1) >> 1) - m, y += c)

#define _CLIP2(l, v, h) ((v) < (l) ? (l) : ((h) < (v) ? (h) : (v)))
#define _CLIP8(v) ((U8)_CLIP2(0, v, 255))
#define _CLIP16(v) ((I16)_CLIP2(-32768, v, 32767))
#define _CLIPU16(v) ((U16)_CLIP2(0, v, 65535))

#define min(a,b) (((a) < (b)) ? (a) : (b))

//inverseConvert: Inverse conversion from float RGB to RGBE
static _FORCEINLINE void inverseConvert (PixelI iF, U8 *pRGB, U8 *pE)
{
    if (iF <= 0) {
        *pRGB = *pE = 0;
    }
    else if ((iF >> 7) > 1) {
        /** normal form **/
        *pE = (U8) (iF >> 7); //+ 1;
        *pRGB = (iF & 0x7f) | 0x80;
    }
    else {  
        /** denormal form **/

src/Source/LibJXR/image/decode/strdec.c  view on Meta::CPAN

    if(cII.cfColorFormat == CF_RGBE)
        pII->cfColorFormat = CF_RGBE;

    // validate thumbnail parameters
    if(pII->cThumbnailWidth == 0 || pII->cThumbnailWidth > pII->cWidth)
        pII->cThumbnailWidth = pII->cWidth;
    if(pII->cThumbnailHeight == 0 || pII->cThumbnailHeight > pII->cHeight)
        pII->cThumbnailHeight = pII->cHeight;
    if((pII->cWidth + pII->cThumbnailWidth - 1) / pII->cThumbnailWidth != (pII->cHeight + pII->cThumbnailHeight - 1) / pII->cThumbnailHeight) {
        while((pII->cWidth + cScale - 1) / cScale > pII->cThumbnailWidth &&
            (pII->cHeight + cScale - 1) / cScale > pII->cThumbnailHeight && (cScale << 1))
            cScale <<= 1;
    }
    else {
        cScale = (pII->cWidth + pII->cThumbnailWidth - 1) / pII->cThumbnailWidth;    
        if (cScale == 0)
            cScale = 1;
    }
    pII->cThumbnailWidth = (pII->cWidth + cScale - 1) / cScale;
    pII->cThumbnailHeight = (pII->cHeight + cScale - 1) / cScale;

    // validate region decode parameters
    if(pII->cROIHeight == 0 || pII->cROIWidth == 0){
        pII->cROILeftX = pII->cROITopY = 0;
        pII->cROIWidth = pII->cThumbnailWidth;
        pII->cROIHeight = pII->cThumbnailHeight;
    }
    if(pII->cROILeftX >= pII->cThumbnailWidth)
        pII->cROILeftX = 0;
    if(pII->cROITopY >= pII->cThumbnailHeight)
        pII->cROITopY = 0;
    if(pII->cROILeftX + pII->cROIWidth > pII->cThumbnailWidth)
        pII->cROIWidth = pII->cThumbnailWidth - pII->cROILeftX;
    if(pII->cROITopY + pII->cROIHeight > pII->cThumbnailHeight)
        pII->cROIHeight = pII->cThumbnailHeight - pII->cROITopY;

    return ICERR_OK;
}

/*************************************************************************
  Initialization of CWMImageStrCodec struct
*************************************************************************/
static Void InitializeStrDec(CWMImageStrCodec *pSC,
  const CCoreParameters *pParams, const CWMImageStrCodec *pSCIn)
{
    // copy core parameters
    memcpy (&(pSC->m_param), pParams, sizeof (CCoreParameters));

    pSC->cbStruct = sizeof(*pSC);
    pSC->WMII = pSCIn->WMII;
    pSC->WMISCP = pSCIn->WMISCP;

    pSC->cRow = 0;
    pSC->cColumn = 0;
    
    pSC->cmbWidth = (pSC->WMII.cWidth + 15) / 16;
    pSC->cmbHeight = (pSC->WMII.cHeight + 15) / 16;

    pSC->Load = outputMBRow; // output decoding result (ICC, etc)
    pSC->Transform = pParams->cSubVersion == CODEC_SUBVERSION ?
        invTransformMacroblock : invTransformMacroblock_alteredOperators_hard;
    pSC->TransformCenter = pSC->Transform;

    pSC->ProcessTopLeft = processMacroblockDec;
    pSC->ProcessTop = processMacroblockDec;
    pSC->ProcessTopRight = processMacroblockDec;
    pSC->ProcessLeft = processMacroblockDec;
    pSC->ProcessCenter = processMacroblockDec;
    pSC->ProcessRight = processMacroblockDec;
    pSC->ProcessBottomLeft = processMacroblockDec;
    pSC->ProcessBottom = processMacroblockDec;
    pSC->ProcessBottomRight = processMacroblockDec;

    pSC->m_pNextSC = NULL;
    pSC->m_bSecondary = FALSE;
}

/*************************************************************************
  ImageStrDecInit
*************************************************************************/
Int ImageStrDecInit(
    CWMImageInfo* pII,
    CWMIStrCodecParam *pSCP,
    CTXSTRCODEC* pctxSC)
{
    static size_t cbChannels[BD_MAX] = {2, 4};
    ERR err = WMP_errSuccess;

    size_t cbChannel = 0, cblkChroma = 0;
    size_t cbMacBlockStride = 0, cbMacBlockChroma = 0, cMacBlock = 0;

    CWMImageStrCodec SC = {0};
    CWMImageStrCodec *pSC = NULL, *pNextSC = NULL;
    char* pb = NULL;
    size_t cb = 0, i;
    Bool bLossyTranscoding = FALSE;
    Bool bUseHardTileBoundaries = FALSE; //default is soft tile boundaries
    Bool bLessThan64Bit = sizeof(void *) < 8;

    *pctxSC = NULL;

    if(WMPhotoValidate(pII, pSCP) != ICERR_OK)
        return ICERR_ERROR;

    if(pSCP->sbSubband == SB_ISOLATED) // can not do anything with isolated bitstream
        return ICERR_ERROR;

    //================================================
    SC.WMISCP.pWStream = pSCP->pWStream;
    if (ReadWMIHeader(&SC.WMII, &SC.WMISCP, &SC.m_param) != ICERR_OK) {
        return ICERR_ERROR;
    }

    bUseHardTileBoundaries = SC.WMISCP.bUseHardTileBoundaries;
    if(SC.WMII.cfColorFormat == CMYK && pII->cfColorFormat == CF_RGB)
        bLossyTranscoding = TRUE;
    if(pSCP->cfColorFormat != CMYK && (pII->cfColorFormat == CMYK))
        return ICERR_ERROR;

    //================================================
    SC.WMISCP = *pSCP;
    SC.WMII   = *pII;

    // original image size
    SC.WMII.cWidth += SC.m_param.cExtraPixelsLeft + SC.m_param.cExtraPixelsRight;
    SC.WMII.cHeight += SC.m_param.cExtraPixelsTop + SC.m_param.cExtraPixelsBottom;
    pII->cROILeftX += SC.m_param.cExtraPixelsLeft;
    pII->cROITopY += SC.m_param.cExtraPixelsTop;
    
    //================================================
    cbChannel = cbChannels[SC.WMISCP.bdBitDepth];
    cblkChroma = cblkChromas[SC.m_param.cfColorFormat];

    cbMacBlockStride = cbChannel * 16 * 16;
    cbMacBlockChroma = cbChannel * 16 * cblkChroma;
    cMacBlock = (SC.WMII.cWidth + 15) / 16;

    //================================================
    cb = sizeof(*pSC) + (128 - 1) + sizeof(CWMDecoderParameters);
    cb += (PACKETLENGTH * 4 - 1) + (PACKETLENGTH * 2 ) + sizeof(*pSC->pIOHeader);

    i = (cbMacBlockStride + cbMacBlockChroma * (SC.m_param.cNumChannels - 1)) * 2; // i <= 2^15
    if (bLessThan64Bit && ((i * (cMacBlock >> 16)) & 0xffffc000)) {
        /** potential overflow - 32 bit pointers insufficient to address cache **/
        return ICERR_ERROR;
    }
    cb += i * cMacBlock;

    pb = malloc(cb);
    if(pb == NULL)
        return WMP_errOutOfMemory;
    memset(pb, 0, cb);

    //================================================
    pSC = (CWMImageStrCodec*)pb; pb += sizeof(*pSC);
    if(pSC == NULL)
        return ICERR_ERROR;

    // Set up perf timers
    PERFTIMER_ONLY(pSC->m_fMeasurePerf = pSCP->fMeasurePerf);
    PERFTIMER_NEW(pSC->m_fMeasurePerf, &pSC->m_ptEndToEndPerf);
    PERFTIMER_NEW(pSC->m_fMeasurePerf, &pSC->m_ptEncDecPerf);
    PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEndToEndPerf);
    PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
    PERFTIMER_COPYSTARTTIME(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf, pSC->m_ptEndToEndPerf);

    pSC->m_Dparam = (CWMDecoderParameters*)pb; pb += sizeof(CWMDecoderParameters);
    pSC->cbChannel = cbChannel;
    //pSC->cNumChannels = SC.WMISCP.cChannel;
    pSC->bUseHardTileBoundaries = bUseHardTileBoundaries;

    //================================================
    InitializeStrDec(pSC, &SC.m_param, &SC);

    //================================================
    // 2 Macro Row buffers for each channel
    pb = ALIGNUP(pb, 128);
    for (i = 0; i < pSC->m_param.cNumChannels; i++) {
        pSC->a0MBbuffer[i] = (PixelI*)pb; pb += cbMacBlockStride * pSC->cmbWidth;
        pSC->a1MBbuffer[i] = (PixelI*)pb; pb += cbMacBlockStride * pSC->cmbWidth;
        cbMacBlockStride = cbMacBlockChroma;
    }

    //================================================
    // lay 2 aligned IO buffers just below pIO struct
    pb = (char*)ALIGNUP(pb, PACKETLENGTH * 4) + PACKETLENGTH * 2;
    pSC->pIOHeader = (BitIOInfo*)pb; pb += sizeof(*pSC->pIOHeader);

    // if interleaved alpha is needed
    if (pSC->m_param.bAlphaChannel) {
        SimpleBitIO SB = {0};
        cbMacBlockStride = cbChannel * 16 * 16;

        // 1. allocate new pNextSC info
        //================================================
        cb = sizeof(*pNextSC) + (128 - 1) + cbMacBlockStride * cMacBlock * 2;
        // if primary image is safe to allocate, alpha channel is certainly safe
        pb = malloc(cb);
        if(pb == NULL)
            return WMP_errOutOfMemory;
        memset(pb, 0, cb);
        //================================================
        pNextSC = (CWMImageStrCodec*)pb; pb += sizeof(*pNextSC);

        // read plane header of second image plane
        Call(attach_SB(&SB, pSCP->pWStream));
        InitializeStrDec(pNextSC, &SC.m_param, &SC);
        ReadImagePlaneHeader(&pNextSC->WMII, &pNextSC->WMISCP, &pNextSC->m_param, &SB);
        detach_SB(&SB);

        // 2. initialize pNextSC
        if(pNextSC == NULL)
            return ICERR_ERROR;
        pNextSC->m_Dparam = pSC->m_Dparam;
        pNextSC->cbChannel = cbChannel;
        //================================================

        // 3. initialize arrays
//        InitializeStrDec(pNextSC, &SC.m_param, &SC);
        pNextSC->m_param.cfColorFormat = Y_ONLY;
        pNextSC->m_param.cNumChannels = 1;
        pNextSC->m_param.bAlphaChannel = TRUE;
        //================================================

        // 2 Macro Row buffers for each channel
        pb = ALIGNUP(pb, 128);
        pNextSC->a0MBbuffer[0] = (PixelI*)pb; pb += cbMacBlockStride * pNextSC->cmbWidth;
        pNextSC->a1MBbuffer[0] = (PixelI*)pb;
        //================================================
        pNextSC->pIOHeader = pSC->pIOHeader;
        //================================================

        // 4. link pSC->pNextSC = pNextSC
        pNextSC->m_pNextSC = pSC;
        pNextSC->m_bSecondary = TRUE;

    }
    else
        pSC->WMISCP.uAlphaMode = 0;

    //================================================
    FailIf((StrIODecInit(pSC) != ICERR_OK), WMP_errOutOfMemory);
    FailIf((StrDecInit(pSC) != ICERR_OK), WMP_errOutOfMemory);
    if (pNextSC) {
        // 5. StrEncInit
        FailIf((StrDecInit(pNextSC) != ICERR_OK), WMP_errOutOfMemory);
    }

    pSC->m_pNextSC = pNextSC;
    //================================================
    *pII = pSC->WMII;
    *pSCP = pSC->WMISCP;
    *pctxSC = (CTXSTRCODEC)pSC;

    if(pSC->WMII.cPostProcStrength){
        initPostProc(pSC->pPostProcInfo, pSC->cmbWidth, pSC->m_param.cNumChannels);
        if (pSC->m_param.bAlphaChannel) 
            initPostProc(pNextSC->pPostProcInfo, pNextSC->cmbWidth, pNextSC->m_param.cNumChannels);
    }

    PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);

Cleanup:
    return WMP_errSuccess == err ? ICERR_OK : ICERR_ERROR;
}

Int ImageStrDecDecode(
    CTXSTRCODEC ctxSC,
    const CWMImageBufferInfo* pBI
#ifdef REENTRANT_MODE
    , size_t *pcDecodedLines
#endif
    )
{
    CWMImageStrCodec* pSC = (CWMImageStrCodec*)ctxSC;
    CWMImageStrCodec* pNextSC = pSC->m_pNextSC;
    size_t cMBRow, k;

    ImageDataProc ProcessLeft, ProcessCenter, ProcessRight;
    ImageDataProc Transform = NULL;
    const size_t iChromaElements = (pSC->m_param.cfColorFormat == YUV_420) ? 8 * 8 
        : ((pSC->m_param.cfColorFormat == YUV_422) ? 8 * 16 : 16 * 16);

    if (sizeof(*pSC) != pSC->cbStruct)
    {

src/Source/LibJXR/image/decode/strdec.c  view on Meta::CPAN

#ifdef REENTRANT_MODE
    if (0 == pSC->WMIBI.uiFirstMBRow)
    {
        setROI(pSC);
        if (pNextSC) {
            pNextSC->WMIBI = pSC->WMIBI;
            setROI(pNextSC);
        }
    }
#else
    setROI(pSC);
    if (pNextSC) {
        pNextSC->WMIBI = pSC->WMIBI;
        setROI(pNextSC);
    }
#endif // REENTRANT_MODE

// optimization flags can be defined only after ROI is set!
#if defined(WMP_OPT_SSE2) || defined(WMP_OPT_CC_DEC) || defined(WMP_OPT_TRFM_DEC)
    StrDecOpt(pSC);
#endif // OPT defined



    cMBRow = (pSC->m_Dparam->bDecodeFullFrame ? pSC->cmbHeight : ((pSC->m_Dparam->cROIBottomY + 16) >> 4));

#ifdef REENTRANT_MODE
    if (0 == pSC->WMIBI.uiFirstMBRow)
    {
        if(initLookupTables(pSC) != ICERR_OK)
            return ICERR_ERROR;
        if (pNextSC && initLookupTables(pNextSC) != ICERR_OK)
            return ICERR_ERROR;
    }
#else
    if(initLookupTables(pSC) != ICERR_OK)
        return ICERR_ERROR;
    if (pNextSC && initLookupTables(pNextSC) != ICERR_OK)
        return ICERR_ERROR;
#endif // REENTRANT_MODE

#ifndef REENTRANT_MODE
    if(pSC->WMII.bdBitDepth == BD_1){
        size_t i;


        for(i = 0; i < pSC->WMIBI.cLine; i ++)
            memset(pSC->WMIBI.pv, 0, pSC->WMIBI.cbStride);
    }
#endif

    //================================
    // top row
#ifdef REENTRANT_MODE
#else
    pSC->cRow = 0;
    ProcessLeft = pSC->ProcessTopLeft;
    ProcessCenter = pSC->ProcessTop;
    ProcessRight = pSC->ProcessTopRight;
    Transform = pSC->m_param.cSubVersion == CODEC_SUBVERSION ?
        invTransformMacroblock : invTransformMacroblock_alteredOperators_hard;
#endif // REENTRANT_MODE

#ifdef REENTRANT_MODE
    for (pSC->cRow = pSC->WMIBI.uiFirstMBRow; pSC->cRow <= pSC->WMIBI.uiLastMBRow; pSC->cRow++)
    {
        // const COLORFORMAT cfExt = (pSC->m_param.cfColorFormat == Y_ONLY ? Y_ONLY : pSC->WMII.cfColorFormat);

        if (0 == pSC->cRow)
        {
            ProcessLeft = pSC->ProcessTopLeft;
            ProcessCenter = pSC->ProcessTop;
            ProcessRight = pSC->ProcessTopRight;
            Transform = pSC->m_param.cSubVersion == CODEC_SUBVERSION ?
                invTransformMacroblock : invTransformMacroblock_alteredOperators_hard;
        }
        else if (cMBRow == pSC->cRow)
        {
            //================================
            // bottom row
            ProcessLeft = pSC->ProcessBottomLeft;
            ProcessCenter = pSC->ProcessBottom;
            ProcessRight = pSC->ProcessBottomRight;
            Transform = pSC->m_param.cSubVersion == CODEC_SUBVERSION ?
                invTransformMacroblock : invTransformMacroblock_alteredOperators_hard;
        }
        else { // middle rows
            ProcessLeft = pSC->ProcessLeft;
            ProcessCenter = pSC->ProcessCenter;
            ProcessRight = pSC->ProcessRight;
            Transform = pSC->TransformCenter;
        }
#else
    //================================
    // central rows
    for(pSC->cRow = 0; pSC->cRow <= cMBRow; pSC->cRow++)
    {
#endif // REENTRANT_MODE
        pSC->cColumn = 0;
        initMRPtr(pSC);
        /** zero out the transform coefficients (pull this out to once per MB row) **/
        memset(pSC->p1MBbuffer[0], 0, sizeof(PixelI) * 16 * 16 * pSC->cmbWidth);
        for (k = 1; k < pSC->m_param.cNumChannels; k++) {
            memset(pSC->p1MBbuffer[k], 0, sizeof(PixelI) * iChromaElements * pSC->cmbWidth);
        }
        if (pSC->m_pNextSC != NULL) {  // alpha channel
            memset(pSC->m_pNextSC->p1MBbuffer[0], 0, sizeof(PixelI) * 16 * 16 * pSC->m_pNextSC->cmbWidth);
        }

        if(ProcessLeft(pSC) != ICERR_OK)
            return ICERR_ERROR;
        advanceMRPtr(pSC);

        pSC->Transform = Transform;
        for (pSC->cColumn = 1; pSC->cColumn < pSC->cmbWidth; ++pSC->cColumn)
        {
            if(ProcessCenter(pSC) != ICERR_OK)
                return ICERR_ERROR;
            advanceMRPtr(pSC);
        }
        pSC->Transform = pSC->m_param.cSubVersion == CODEC_SUBVERSION ?
            invTransformMacroblock : invTransformMacroblock_alteredOperators_hard;

        if(ProcessRight(pSC) != ICERR_OK)
            return ICERR_ERROR;

        if (pSC->cRow) {
            if(pSC->m_Dparam->cThumbnailScale < 2 && (pSC->m_Dparam->bDecodeFullFrame || 
                ((pSC->cRow * 16 > pSC->m_Dparam->cROITopY) && (pSC->cRow * 16 <= pSC->m_Dparam->cROIBottomY + 16)))) {
                if( pSC->Load(pSC) != ICERR_OK ) // bypass CC for thumbnail decode
            		return ICERR_ERROR;
            }

            if(pSC->m_Dparam->cThumbnailScale >= 2) // decode thumbnail
                decodeThumbnail(pSC);
        }

        advanceOneMBRow(pSC);
        swapMRPtr(pSC);
#ifdef REENTRANT_MODE
        *pcDecodedLines = pSC->WMIBI.cLinesDecoded;
#else
        if (pSC->cRow == cMBRow - 1) {
        //================================
        // bottom row
            ProcessLeft = pSC->ProcessBottomLeft;
            ProcessCenter = pSC->ProcessBottom;
            ProcessRight = pSC->ProcessBottomRight;
            Transform = pSC->m_param.cSubVersion == CODEC_SUBVERSION ?
                invTransformMacroblock : invTransformMacroblock_alteredOperators_hard;
        }
        else {
            ProcessLeft = pSC->ProcessLeft;
            ProcessCenter = pSC->ProcessCenter;
            ProcessRight = pSC->ProcessRight;
            Transform = pSC->TransformCenter;
        }
#endif // REENTRANT_MODE
    }

#ifndef REENTRANT_MODE
    fixup_Y_ONLY_to_Others(pSC, pBI);
#endif // REENTRANT_MODE

    PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
    return ICERR_OK;
}

Int ImageStrDecTerm(
    CTXSTRCODEC ctxSC)
{
    CWMImageStrCodec* pSC = (CWMImageStrCodec*)ctxSC;
    if (NULL == pSC)
    {
        return ICERR_OK;
    }
    if (sizeof(*pSC) != pSC->cbStruct)
    {
        return ICERR_ERROR;
    }

    PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);

    StrDecTerm(pSC);
    PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
    PERFTIMER_REPORT(pSC->m_fMeasurePerf, pSC);
    PERFTIMER_DELETE(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
    PERFTIMER_DELETE(pSC->m_fMeasurePerf, pSC->m_ptEndToEndPerf);

    free(pSC);

    return ICERR_OK;
}



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