1 //*@@@+++@@@@******************************************************************
2 //
3 // Copyright � Microsoft Corp.
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 //
9 // � Redistributions of source code must retain the above copyright notice,
10 //   this list of conditions and the following disclaimer.
11 // � Redistributions in binary form must reproduce the above copyright notice,
12 //   this list of conditions and the following disclaimer in the documentation
13 //   and/or other materials provided with the distribution.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 // POSSIBILITY OF SUCH DAMAGE.
26 //
27 //*@@@---@@@@******************************************************************
28 #include "strcodec.h"
29 #include "decode.h"
30 #include "strTransform.h"
31 #include <math.h>
32 #include "perfTimer.h"
33 
34 #ifdef MEM_TRACE
35 #define TRACE_MALLOC    1
36 #define TRACE_NEW       0
37 #define TRACE_HEAP      0
38 #include "memtrace.h"
39 #endif
40 
41 #ifdef X86OPT_INLINE
42 #define _FORCEINLINE __forceinline
43 #else // X86OPT_INLINE
44 #define _FORCEINLINE
45 #endif // X86OPT_INLINE
46 
47 #if defined(WMP_OPT_SSE2) || defined(WMP_OPT_CC_DEC) || defined(WMP_OPT_TRFM_DEC)
48 void StrDecOpt(CWMImageStrCodec* pSC);
49 #endif // OPT defined
50 
51 Int processMacroblockDec(CWMImageStrCodec *);
52 
readQuantizerSB(U8 pQPIndex[MAX_CHANNELS],SimpleBitIO * pIO,size_t cChannel)53 U8 readQuantizerSB(U8 pQPIndex[MAX_CHANNELS], SimpleBitIO * pIO, size_t cChannel)
54 {
55     U8 cChMode = 0;
56 
57     if(cChannel >= MAX_CHANNELS)
58         return 0;
59 
60     if(cChannel > 1)
61         cChMode = (U8)getBit32_SB(pIO, 2); // Channel mode
62 
63     pQPIndex[0] = (U8)getBit32_SB(pIO, 8); // Y
64 
65     if(cChMode == 1)  // MIXED
66         pQPIndex[1] = (U8)getBit32_SB(pIO, 8); // UV
67     else if(cChMode > 0){ // INDEPENDENT
68         size_t i;
69 
70         for(i = 1; i < cChannel; i ++)
71 #pragma prefast(suppress: __WARNING_UNRELATED_LOOP_TERMINATION_NO_SIZEEXPR, "PREfast false alarm: 1 <= i < MAX_CHANNELS, no buffer over/underrun!")
72             pQPIndex[i] = (U8)getBit32_SB(pIO, 8); // UV
73     }
74 
75     return cChMode;
76 }
77 
readQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS],BitIOInfo * pIO,size_t cChannel,size_t iPos)78 U8 readQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS], BitIOInfo * pIO, size_t cChannel, size_t iPos)
79 {
80     U8 cChMode = 0;
81 
82     if(cChannel > 1)
83         cChMode = (U8)getBit16(pIO, 2); // Channel mode
84 
85     pQuantizer[0][iPos].iIndex = (U8)getBit16(pIO, 8); // Y
86 
87     if(cChMode == 1)  // MIXED
88         pQuantizer[1][iPos].iIndex = (U8)getBit16(pIO, 8); // UV
89     else if(cChMode > 0){ // INDEPENDENT
90         size_t i;
91 
92         for(i = 1; i < cChannel; i ++)
93             pQuantizer[i][iPos].iIndex = (U8)getBit16(pIO, 8); // UV
94     }
95 
96     return cChMode;
97 }
98 
99 // packet header: 00000000 00000000 00000001 ?????xxx
100 // xxx:           000(spatial) 001(DC) 010(AD) 011(AC) 100(FL) 101-111(reserved)
101 // ?????:         (iTileY * cNumOfSliceV + iTileX) % 32
readPacketHeader(BitIOInfo * pIO,U8 ptPacketType,U8 pID)102 Int readPacketHeader(BitIOInfo * pIO, U8 ptPacketType, U8 pID)
103 {
104     UNREFERENCED_PARAMETER( ptPacketType );
105     UNREFERENCED_PARAMETER( pID );
106     if(getBit16(pIO, 8) != 0 || getBit16(pIO, 8) != 0 || getBit16(pIO, 8) != 1)
107         return ICERR_ERROR;
108     getBit16(pIO, 8);
109     return ICERR_OK;
110 }
111 
readTileHeaderDC(CWMImageStrCodec * pSC,BitIOInfo * pIO)112 Int readTileHeaderDC(CWMImageStrCodec * pSC, BitIOInfo * pIO)
113 {
114     if((pSC->m_param.uQPMode & 1) != 0){ // not DC uniform
115         size_t iTile;
116         CWMITile * pTile = pSC->pTile + pSC->cTileColumn;
117 
118         if(pSC->cTileRow + pSC->cTileColumn == 0) // allocate DC QP info
119             for(iTile = 0; iTile <= pSC->WMISCP.cNumOfSliceMinus1V; iTile ++)
120                 if(allocateQuantizer(pSC->pTile[iTile].pQuantizerDC, pSC->m_param.cNumChannels, 1) != ICERR_OK)
121                     return ICERR_ERROR;
122 
123         pTile->cChModeDC = readQuantizer(pTile->pQuantizerDC, pIO, pSC->m_param.cNumChannels, 0);
124         formatQuantizer(pTile->pQuantizerDC, pTile->cChModeDC, pSC->m_param.cNumChannels, 0, TRUE, pSC->m_param.bScaledArith);
125     }
126 
127     return ICERR_OK;
128 }
129 
readTileHeaderLP(CWMImageStrCodec * pSC,BitIOInfo * pIO)130 Int readTileHeaderLP(CWMImageStrCodec * pSC, BitIOInfo * pIO)
131 {
132     if(pSC->WMISCP.sbSubband != SB_DC_ONLY && (pSC->m_param.uQPMode & 2) != 0){ // not LP uniform
133         CWMITile * pTile = pSC->pTile + pSC->cTileColumn;
134         U8 i;
135 
136         pTile->bUseDC = (getBit16(pIO, 1) == 1 ? TRUE : FALSE);
137         pTile->cBitsLP = 0;
138         pTile->cNumQPLP = 1;
139 
140         if(pSC->cTileRow > 0)
141             freeQuantizer(pTile->pQuantizerLP);
142 
143         if(pTile->bUseDC == TRUE){
144             if(allocateQuantizer(pTile->pQuantizerLP, pSC->m_param.cNumChannels, pTile->cNumQPLP) != ICERR_OK)
145                 return ICERR_ERROR;
146             useDCQuantizer(pSC, pSC->cTileColumn);
147         }
148         else{
149             pTile->cNumQPLP = (U8)getBit16(pIO, 4) + 1;
150             pTile->cBitsLP = dquantBits(pTile->cNumQPLP);
151 
152             if(allocateQuantizer(pTile->pQuantizerLP, pSC->m_param.cNumChannels, pTile->cNumQPLP) != ICERR_OK)
153                 return ICERR_ERROR;
154 
155             for(i = 0; i < pTile->cNumQPLP; i ++){
156                 pTile->cChModeLP[i] = readQuantizer(pTile->pQuantizerLP, pIO, pSC->m_param.cNumChannels, i);
157                 formatQuantizer(pTile->pQuantizerLP, pTile->cChModeLP[i], pSC->m_param.cNumChannels, i, TRUE, pSC->m_param.bScaledArith);
158             }
159         }
160     }
161 
162     return ICERR_OK;
163 }
164 
readTileHeaderHP(CWMImageStrCodec * pSC,BitIOInfo * pIO)165 Int readTileHeaderHP(CWMImageStrCodec * pSC, BitIOInfo * pIO)
166 {
167     if(pSC->WMISCP.sbSubband != SB_DC_ONLY && pSC->WMISCP.sbSubband != SB_NO_HIGHPASS && (pSC->m_param.uQPMode & 4) != 0){ // not HP uniform
168         CWMITile * pTile = pSC->pTile + pSC->cTileColumn;
169         U8 i;
170 
171         pTile->bUseLP = (getBit16(pIO, 1) == 1 ? TRUE : FALSE);
172         pTile->cBitsHP = 0;
173         pTile->cNumQPHP = 1;
174 
175         if(pSC->cTileRow > 0)
176             freeQuantizer(pTile->pQuantizerHP);
177 
178         if(pTile->bUseLP == TRUE){
179             pTile->cNumQPHP = pTile->cNumQPLP;
180             if(allocateQuantizer(pTile->pQuantizerHP, pSC->m_param.cNumChannels, pTile->cNumQPHP) != ICERR_OK)
181                 return ICERR_ERROR;
182             useLPQuantizer(pSC, pTile->cNumQPHP, pSC->cTileColumn);
183         }
184         else{
185             pTile->cNumQPHP = (U8)getBit16(pIO, 4) + 1;
186             pTile->cBitsHP = dquantBits(pTile->cNumQPHP);
187 
188             if(allocateQuantizer(pTile->pQuantizerHP, pSC->m_param.cNumChannels, pTile->cNumQPHP) != ICERR_OK)
189                 return ICERR_ERROR;
190 
191             for(i = 0; i < pTile->cNumQPHP; i ++){
192                 pTile->cChModeHP[i] = readQuantizer(pTile->pQuantizerHP, pIO, pSC->m_param.cNumChannels, i);
193                 formatQuantizer(pTile->pQuantizerHP, pTile->cChModeHP[i], pSC->m_param.cNumChannels, i, FALSE, pSC->m_param.bScaledArith);
194             }
195         }
196     }
197 
198     return ICERR_OK;
199 }
200 
readPackets(CWMImageStrCodec * pSC)201 Int readPackets(CWMImageStrCodec * pSC)
202 {
203     if(pSC->cColumn == 0 && pSC->cRow == pSC->WMISCP.uiTileY[pSC->cTileRow]){ // start of a new horizontal slice
204         size_t k;
205 
206         if (pSC->m_bSecondary) {
207              if(pSC->cNumBitIO > 0){
208                 for(k = 0; k <= pSC->WMISCP.cNumOfSliceMinus1V; k ++){
209                     // reset coding contexts
210                     ResetCodingContextDec(&pSC->m_pCodingContext[k]);
211                 }
212             }
213             else{ // for multiple decoding calls!
214                 ResetCodingContextDec(&pSC->m_pCodingContext[0]);
215             }
216         }
217         else {
218             // get sizes of each packet and update index table
219             for(k = 0; k < pSC->cNumBitIO; k ++){
220                 if(pSC->ppWStream != NULL){ // new API
221                     unsigned cBands = (pSC->WMISCP.bfBitstreamFormat == SPATIAL ? 1 : pSC->cSB);
222                     struct WMPStream ** ppWS = pSC->ppWStream + (pSC->WMISCP.cNumOfSliceMinus1V + 1) * pSC->cTileRow * cBands
223                         + k / cBands * cBands + (k % cBands);
224 
225                     if(pSC->cTileRow > 0 && pSC->m_ppBitIO[k]->pWS != NULL)     // attached to the same packet of the tile on top
226                         detachISRead(pSC, pSC->m_ppBitIO[k]);    // detach it
227 
228                     if(ppWS[0] != NULL)
229                         attachISRead(pSC->m_ppBitIO[k], ppWS[0], pSC); // need to attach it
230                 }
231                 else{
232                     if(pSC->cTileRow > 0)
233                         detachISRead(pSC, pSC->m_ppBitIO[k]);
234                     pSC->WMISCP.pWStream->SetPos(pSC->WMISCP.pWStream, pSC->pIndexTable[pSC->cNumBitIO * pSC->cTileRow + k] + pSC->cHeaderSize);
235                     attachISRead(pSC->m_ppBitIO[k], pSC->WMISCP.pWStream, pSC);
236                 }
237             }
238 
239             if(pSC->cNumBitIO == 0){
240                 detachISRead(pSC, pSC->pIOHeader);
241                 if(pSC->ppWStream != NULL){// new API
242                     attachISRead(pSC->pIOHeader, pSC->ppWStream[0], pSC); // need to attach it
243                 }
244                 else{
245                     pSC->WMISCP.pWStream->SetPos(pSC->WMISCP.pWStream, pSC->cHeaderSize);
246                     attachISRead(pSC->pIOHeader, pSC->WMISCP.pWStream, pSC);
247                 }
248             }
249 
250             for(k = 0; k <= pSC->WMISCP.cNumOfSliceMinus1V; k ++){
251                 U8 pID = (U8)((pSC->cTileRow * (pSC->WMISCP.cNumOfSliceMinus1V + 1) + k) & 0x1F);
252 
253                 // read packet header
254                 if(pSC->WMISCP.bfBitstreamFormat == SPATIAL){
255                     BitIOInfo * pIO = (pSC->cNumBitIO == 0 ? pSC->pIOHeader : pSC->m_ppBitIO[k]);
256 
257                     if(pIO->pWS == NULL || readPacketHeader(pIO, 0, pID) != ICERR_OK)
258                         return ICERR_ERROR;
259                     pSC->m_pCodingContext[k].m_iTrimFlexBits = (pSC->m_param.bTrimFlexbitsFlag) ? getBit16(pIO, 4) : 0;
260                 }
261                 else{
262                     if(pSC->m_ppBitIO[k * pSC->cSB + 0] == NULL || readPacketHeader(pSC->m_ppBitIO[k * pSC->cSB + 0], 1, pID) != ICERR_OK)
263                         return ICERR_ERROR;
264                     if(pSC->cSB > 1){
265                         if(pSC->m_ppBitIO[k * pSC->cSB + 1] == NULL || readPacketHeader(pSC->m_ppBitIO[k * pSC->cSB + 1], 2, pID) != ICERR_OK)
266                             return ICERR_ERROR;
267                     }
268                     if(pSC->cSB > 2){
269                         if(pSC->m_ppBitIO[k * pSC->cSB + 2] == NULL || readPacketHeader(pSC->m_ppBitIO[k * pSC->cSB + 2], 3, pID) != ICERR_OK)
270                             return ICERR_ERROR;
271 //                        readTileHeaderHP(pSC, pSC->m_ppBitIO[k * pSC->cSB + 2]);
272                     }
273                     if(pSC->cSB > 3){
274                         if(pSC->m_ppBitIO[k * pSC->cSB + 3] == NULL)
275                             return ICERR_ERROR;
276                         readPacketHeader(pSC->m_ppBitIO[k * pSC->cSB + 3], 4, pID);  // bad flexbits packet doesn't generate an error
277                         pSC->m_pCodingContext[k].m_iTrimFlexBits = (pSC->m_param.bTrimFlexbitsFlag) ? getBit16(pSC->m_ppBitIO[k * pSC->cSB + 3], 4) : 0;
278                     }
279                 }
280 
281                 // reset coding contexts
282                 ResetCodingContextDec(&pSC->m_pCodingContext[k]);
283             }
284         }
285     }
286 
287     if(pSC->m_bCtxLeft && pSC->m_bCtxTop && pSC->m_bSecondary == FALSE){
288         CCodingContext *pContext = &pSC->m_pCodingContext[pSC->cTileColumn];
289 
290         readTileHeaderDC(pSC, pContext->m_pIODC);
291         if(pSC->m_pNextSC != NULL)
292             readTileHeaderDC(pSC->m_pNextSC, pContext->m_pIODC);
293         if(pSC->cSB > 1){
294             readTileHeaderLP(pSC, pContext->m_pIOLP);
295             if(pSC->m_pNextSC != NULL)
296                 readTileHeaderLP(pSC->m_pNextSC, pContext->m_pIOLP);
297         }
298         if(pSC->cSB > 2){
299             readTileHeaderHP(pSC, pContext->m_pIOAC);
300             if(pSC->m_pNextSC != NULL)
301                 readTileHeaderHP(pSC->m_pNextSC, pContext->m_pIOAC);
302         }
303     }
304 
305     return ICERR_OK;
306 }
307 
308 /* inverse transform and overlap possible part of a macroblock */
processMacroblockDec(CWMImageStrCodec * pSC)309 Int processMacroblockDec(CWMImageStrCodec * pSC)
310 {
311     const OVERLAP olOverlap = pSC->WMISCP.olOverlap;
312     // const Bool left = (pSC->cColumn == 0);
313     const Bool /*top = (pSC->cRow == 0),*/ bottom = (pSC->cRow == pSC->cmbHeight);
314     const Bool bottomORright = (bottom || pSC->cColumn == pSC->cmbWidth);
315     // const size_t mbWidth = pSC->cmbWidth, mbX = pSC->cColumn;
316     // Int iQIndex = 0;
317     ERR_CODE result = ICERR_OK;
318     size_t j, jend = (pSC->m_pNextSC != NULL);
319 
320     for (j = 0; j <= jend; j++) {
321         if(!bottomORright){
322             CCodingContext *pContext;
323 
324             getTilePos(pSC, pSC->cColumn, pSC->cRow);
325 
326             if(jend){
327                 pSC->m_pNextSC->cTileColumn = pSC->cTileColumn;
328                 pSC->m_pNextSC->cTileRow = pSC->cTileRow;
329             }
330 
331             pContext = &pSC->m_pCodingContext[pSC->cTileColumn];
332 
333             if(readPackets(pSC) != ICERR_OK)
334                 return ICERR_ERROR;
335 
336             // check if we need to do entropy decode
337 			if(!pSC->m_Dparam->bDecodeFullFrame){
338 				if(pSC->cColumn == pSC->WMISCP.uiTileX[pSC->cTileColumn]){ // switching to a new tile
339 					size_t rLeft = pSC->m_Dparam->cROILeftX, rRight = pSC->m_Dparam->cROIRightX;
340 					size_t rTop = pSC->m_Dparam->cROITopY, rBottom = pSC->m_Dparam->cROIBottomY;
341 					size_t rExt = (olOverlap == OL_NONE ? 0 : olOverlap == OL_ONE ? 2 : 10);
342 					size_t tLeft = pSC->cColumn * 16, tTop = pSC->WMISCP.uiTileY[pSC->cTileRow] * 16;
343 					size_t tRight = (pSC->cTileColumn != pSC->WMISCP.cNumOfSliceMinus1V ? pSC->WMISCP.uiTileX[pSC->cTileColumn + 1] : pSC->cmbWidth) * 16;
344 					size_t tBottom = (pSC->cTileRow != pSC->WMISCP.cNumOfSliceMinus1H ? pSC->WMISCP.uiTileY[pSC->cTileRow + 1] : pSC->cmbHeight) * 16;
345 
346 					// tile overlaps with ROI?
347 					pContext->m_bInROI = ((rLeft >= tRight + rExt || rTop >= tBottom + rExt || tLeft > rRight + rExt ||
348 						tTop > rBottom + rExt || pSC->cRow * 16 > rBottom + rExt) ? FALSE : TRUE);
349 				}
350 			}
351 
352             if(pSC->m_Dparam->bDecodeFullFrame || pContext->m_bInROI){
353                 if ((result = DecodeMacroblockDC(pSC, pContext, (Int)pSC->cColumn, (Int)pSC->cRow)) != ICERR_OK)
354                     return result;
355 
356                 if(pSC->m_Dparam->bDecodeLP){
357                     if ((result = DecodeMacroblockLowpass(pSC, pContext, (Int)pSC->cColumn, (Int)pSC->cRow)) != ICERR_OK)
358                         return result;
359                 }
360 
361                 predDCACDec(pSC);
362 
363                 dequantizeMacroblock(pSC);
364 
365                 if(pSC->m_Dparam->bDecodeHP){
366                     if ((result = DecodeMacroblockHighpass(pSC, pContext, (Int)pSC->cColumn, (Int)pSC->cRow)) != ICERR_OK)
367                         return result;
368                     predACDec(pSC);
369                 }
370 
371                 /* keep necessary info for future prediction */
372                 updatePredInfo(pSC, &pSC->MBInfo, (Int)pSC->cColumn, pSC->m_param.cfColorFormat);
373             }
374         }
375 
376         if((!pSC->m_Dparam->bDecodeFullFrame) &&
377             ((pSC->cColumn * 16 > pSC->m_Dparam->cROIRightX  + 25) || (pSC->cColumn * 16 + 25 < pSC->m_Dparam->cROILeftX)
378             || (pSC->cRow * 16 > pSC->m_Dparam->cROIBottomY + 25) || (pSC->cRow * 16 + 25 < pSC->m_Dparam->cROITopY)))
379         {
380             // do nothing
381         }
382         else {
383             pSC->Transform(pSC);
384         }
385 
386         if (jend) {
387             pSC->m_pNextSC->cRow = pSC->cRow;
388             pSC->m_pNextSC->cColumn = pSC->cColumn;
389             pSC = pSC->m_pNextSC;
390         }
391     }
392 
393     return result;
394 }
395 
396 //================================================================
397 // Inverse Color Conversion
398 //#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)
399 //#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)
400 //================================================================
401 //#define _ICC1(r, g, b) r -= (g >> 1), g += r, r -= ((b + 1) >> 1), b += r
402 //#define _ICC(r, g, b) r -= (g >> 1), g += r, r -= (b >> 1), b += r
403 
404 #define _ICC(r, g, b)  (g -= ((r + 0) >> 1), r -= ((b + 1) >> 1) - g, b += r)
405 #define _ICC_CMYK(c, m, y, k) (k -= ((m + 1) >> 1), m -= (c >> 1) - k, c -= ((y + 1) >> 1) - m, y += c)
406 
407 #define _CLIP2(l, v, h) ((v) < (l) ? (l) : ((h) < (v) ? (h) : (v)))
408 #define _CLIP8(v) ((U8)_CLIP2(0, v, 255))
409 #define _CLIP16(v) ((I16)_CLIP2(-32768, v, 32767))
410 #define _CLIPU16(v) ((U16)_CLIP2(0, v, 65535))
411 
412 #define min(a,b) (((a) < (b)) ? (a) : (b))
413 
414 //inverseConvert: Inverse conversion from float RGB to RGBE
inverseConvert(PixelI iF,U8 * pRGB,U8 * pE)415 static _FORCEINLINE void inverseConvert (PixelI iF, U8 *pRGB, U8 *pE)
416 {
417     if (iF <= 0) {
418         *pRGB = *pE = 0;
419     }
420     else if ((iF >> 7) > 1) {
421         /** normal form **/
422         *pE = (U8) (iF >> 7); //+ 1;
423         *pRGB = (iF & 0x7f) | 0x80;
424     }
425     else {
426         /** denormal form **/
427         *pE = 1;
428         *pRGB = (U8) iF;
429     }
430 }
431 
432 #ifdef __ANSI__
433 #define max(a,b) ((a) > (b) ? (a) : (b))
434 #endif // __ANSI__
435 
inverseConvertRGBE(PixelI iFr,PixelI iFg,PixelI iFb,U8 * pR,U8 * pG,U8 * pB,U8 * pE)436 static _FORCEINLINE void inverseConvertRGBE (PixelI iFr, PixelI iFg, PixelI iFb, U8 *pR, U8 *pG, U8 *pB, U8 *pE)
437 {
438     U8 iShift;
439 
440     U8 pR_E, pG_E, pB_E;
441 
442     inverseConvert (iFr, pR, &pR_E);
443     inverseConvert (iFg, pG, &pG_E);
444     inverseConvert (iFb, pB, &pB_E);
445 
446     *pE = max(max(pR_E, pG_E), pB_E);
447 
448     if(*pE > pR_E){
449             iShift = (*pE - pR_E);
450             *pR = (U8)((((int)*pR) * 2 + 1) >> (iShift + 1));
451     }
452     if(*pE > pG_E){
453             iShift = (*pE - pG_E);
454             *pG = (U8)((((int)*pG) * 2 + 1) >> (iShift + 1));
455     }
456     if(*pE > pB_E){
457             iShift = (*pE - pB_E);
458             *pB = (U8)((((int)*pB) * 2 + 1) >> (iShift + 1));
459     }
460 }
461 
462 
463 //pixel to float 32!
pixel2float(PixelI _h,const char _c,const unsigned char _lm)464 static _FORCEINLINE float pixel2float(PixelI _h, const char _c, const unsigned char _lm)
465 {
466     union uif
467     {
468         I32   i;
469         float f;
470     } x;
471 
472     I32 s, iTempH, m, e, lmshift = (1 << _lm);
473 
474     // assert (_c <= 127);
475 
476     iTempH = (I32) _h ;
477     s = (iTempH >> 31);
478     iTempH = (iTempH ^ s) - s; // abs(iTempH)
479 
480     e = (U32) iTempH >> _lm;// & ((1 << (31 - _lm)) - 1);
481     m = (iTempH & (lmshift - 1)) | lmshift; // actual mantissa, with normalizer
482     if (e == 0) { // denormal land
483         m ^= lmshift; // normalizer removed
484         e = 1; // actual exponent
485     }
486 
487     e += (127 - _c);
488     while (m < lmshift && e > 1 && m > 0) { // denormal originally, see if normal is possible
489         e--;
490         m <<= 1;
491     }
492     if (m < lmshift) // truly denormal
493         e = 0;
494     else
495         m ^= lmshift;
496     m <<= (23 - _lm);
497 
498     x.i = (s & 0x80000000) | (e << 23) | m;
499 
500     return x.f;
501 }
502 
503 //convert Half-16 to internal format, only need to handle sign bit
backwardHalf(PixelI hHalf)504 static _FORCEINLINE U16 backwardHalf (PixelI hHalf)
505 {
506     PixelI s;
507     s = hHalf >> 31;
508     hHalf = ((hHalf & 0x7fff) ^ s) - s; // don't worry about overflow
509     return (U16) hHalf;
510 }
511 
512 
interpolateUV(CWMImageStrCodec * pSC)513 Void interpolateUV(CWMImageStrCodec * pSC)
514 {
515     const COLORFORMAT cfExt = pSC->WMII.cfColorFormat;
516     const size_t cWidth = pSC->cmbWidth * 16;
517     PixelI * pSrcU = pSC->a0MBbuffer[1], * pSrcV = pSC->a0MBbuffer[2];
518     PixelI * pDstU = pSC->pResU, * pDstV = pSC->pResV;
519     size_t iRow, iColumn;
520     size_t iIdxS = 0, iIdxD = 0;
521 
522     if(pSC->m_param.cfColorFormat == YUV_422){  // 422 => 444, interpolate horizontally
523         for(iRow = 0; iRow < 16; iRow ++){
524             for(iColumn = 0; iColumn < cWidth; iColumn += 2){
525                 iIdxS = ((iColumn >> 4) << 7) + idxCC[iRow][(iColumn >> 1) & 7];
526                 iIdxD = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
527 
528                 // copy over
529                 pDstU[iIdxD] = pSrcU[iIdxS];
530                 pDstV[iIdxD] = pSrcV[iIdxS];
531 
532                 if(iColumn > 0){
533                     size_t iL = iColumn - 2, iIdxL = ((iL >> 4) << 8) + idxCC[iRow][iL & 15];
534                     size_t iC = iColumn - 1, iIdxC = ((iC >> 4) << 8) + idxCC[iRow][iC & 15];
535 
536                     // interpolate
537                     pDstU[iIdxC] = ((pDstU[iIdxL] + pDstU[iIdxD] + 1) >> 1);
538                     pDstV[iIdxC] = ((pDstV[iIdxL] + pDstV[iIdxD] + 1) >> 1);
539                 }
540             }
541 
542             //last pixel
543             iIdxS = (((iColumn - 1) >> 4) << 8) + idxCC[iRow][(iColumn - 1) & 15];
544             pDstU[iIdxS] = pDstU[iIdxD];
545             pDstV[iIdxS] = pDstV[iIdxD];
546         }
547     }
548     else{ // 420 => 422 or 444, interpolate vertically
549         const size_t cShift = (cfExt == YUV_422 ? 3 : 4);
550 
551         for(iColumn = 0; iColumn < cWidth; iColumn += 2){
552             const size_t cMB = ((iColumn >> 4) << (4 + cShift)), cPix = (iColumn >> (4 - cShift)) & ((1 << cShift) - 1);
553 
554             for(iRow = 0; iRow < 16; iRow += 2){
555                 iIdxS = ((iColumn >> 4) << 6) + idxCC_420[iRow >> 1][(iColumn >> 1) & 7];
556                 iIdxD = cMB + idxCC[iRow][cPix];
557 
558                 // copy over
559                 pDstU[iIdxD] = pSrcU[iIdxS];
560                 pDstV[iIdxD] = pSrcV[iIdxS];
561 
562                 if(iRow > 0){
563                     size_t iIdxT = cMB + idxCC[iRow - 2][cPix];
564                     size_t iIdxC = cMB + idxCC[iRow - 1][cPix];
565 
566                     // interpolate
567                     pDstU[iIdxC] = ((pDstU[iIdxT] + pDstU[iIdxD] + 1) >> 1);
568                     pDstV[iIdxC] = ((pDstV[iIdxT] + pDstV[iIdxD] + 1) >> 1);
569                 }
570             }
571 
572             //last row
573             iIdxS = cMB + idxCC[15][cPix];
574             if(pSC->cRow == pSC->cmbHeight){ // image boundary
575                 pDstU[iIdxS] = pDstU[iIdxD];
576                 pDstV[iIdxS] = pDstV[iIdxD];
577             }
578             else{ // need next MB row
579                 size_t iIdxB = ((iColumn >> 4) << 6) + idxCC_420[0][(iColumn >> 1) & 7];
580 
581                 pDstU[iIdxS] = ((pSC->a1MBbuffer[1][iIdxB] + pDstU[iIdxD] + 1) >> 1);
582                 pDstV[iIdxS] = ((pSC->a1MBbuffer[2][iIdxB] + pDstV[iIdxD] + 1) >> 1);
583             }
584         }
585 
586         if(cfExt != YUV_422){ // 420 => 444, interpolate horizontally
587             for(iRow = 0; iRow < 16; iRow ++){
588                 for(iColumn = 1; iColumn < cWidth - 2; iColumn += 2){
589                     size_t iIdxL = (((iColumn - 1) >> 4) << 8) + idxCC[iRow][(iColumn - 1) & 15];
590 
591                     iIdxD = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
592                     iIdxS = (((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15];
593 
594                     pDstU[iIdxD] = ((pDstU[iIdxS] + pDstU[iIdxL] + 1) >> 1);
595                     pDstV[iIdxD] = ((pDstV[iIdxS] + pDstV[iIdxL] + 1) >> 1);
596                 }
597 
598                 // last pixel
599                 iIdxD = (((cWidth - 1) >> 4) << 8) + idxCC[iRow][(cWidth - 1) & 15];
600                 pDstU[iIdxD] = pDstU[iIdxS];
601                 pDstV[iIdxD] = pDstV[iIdxS];
602             }
603         }
604     }
605 }
606 
607 // write one MB row of Y_ONLY/CF_ALPHA/YUV_444/N_CHANNEL to output buffer
outputNChannel(CWMImageStrCodec * pSC,size_t iFirstRow,size_t iFirstColumn,size_t cWidth,size_t cHeight,size_t iShift,PixelI iBias)608 Void outputNChannel(CWMImageStrCodec * pSC, size_t iFirstRow, size_t iFirstColumn, size_t cWidth, size_t cHeight, size_t iShift, PixelI iBias)
609 {
610     const CWMImageInfo* pII = &pSC->WMII;
611     const size_t cChannel = pII->cfColorFormat == Y_ONLY ? 1 : pSC->WMISCP.cChannel;
612     // const U8 cbChannels[BDB_MAX] = {-1, 1, 2, 2, 2, 4, 4, -1, -1, };
613     const U8 nLen = pSC->WMISCP.nLenMantissaOrShift;
614     const I8 nExpBias = pSC->WMISCP.nExpBias;
615 
616     PixelI * pChannel[16];
617     size_t iChannel, iRow, iColumn;
618     size_t * pOffsetX = pSC->m_Dparam->pOffsetX, * pOffsetY = pSC->m_Dparam->pOffsetY + (pSC->cRow - 1) * 16, iY;
619 
620     assert(cChannel <= 16);
621 
622     for(iChannel = 0; iChannel < cChannel; iChannel ++)
623         pChannel[iChannel & 15] = pSC->a0MBbuffer[iChannel];
624 
625     if(pSC->m_bUVResolutionChange)
626         pChannel[1] = pSC->pResU, pChannel[2] = pSC->pResV;
627 
628     switch(pSC->WMII.bdBitDepth){
629         case BD_8:
630             for(iRow = iFirstRow; iRow < cHeight; iRow ++){
631                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
632                     U8 * pDst = (U8 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn];
633 
634                     for(iChannel = 0; iChannel < cChannel; iChannel ++){
635                         PixelI p = ((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift);
636 
637                         pDst[iChannel] = _CLIP8(p);
638                     }
639                 }
640             }
641             break;
642 
643         case BD_16:
644             for(iRow = iFirstRow; iRow < cHeight; iRow ++){
645                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
646                     U16 * pDst = (U16 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn];
647 
648                     for(iChannel = 0; iChannel < cChannel; iChannel ++){
649                         PixelI p = ((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift);
650 
651                         p <<= nLen;
652                         pDst[iChannel] = _CLIPU16(p);
653                     }
654                 }
655             }
656             break;
657 
658         case BD_16S:
659             for(iRow = iFirstRow; iRow < cHeight; iRow ++){
660                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
661                     I16 * pDst = (I16 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn];
662 
663                     for(iChannel = 0; iChannel < cChannel; iChannel ++){
664                         PixelI p = ((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift);
665 
666                         p <<= nLen;
667                         pDst[iChannel] = _CLIP16(p);
668                     }
669                 }
670             }
671             break;
672 
673         case BD_16F:
674             for(iRow = iFirstRow; iRow < cHeight; iRow ++){
675                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
676                     U16 * pDst = (U16 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn];
677 
678                     for(iChannel = 0; iChannel < cChannel; iChannel ++){
679                         PixelI p = ((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] + iBias) >> iShift);
680 
681                         pDst[iChannel] = backwardHalf(p);
682                     }
683                 }
684             }
685             break;
686 
687         case BD_32:
688             for(iRow = iFirstRow; iRow < cHeight; iRow ++){
689                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
690                     U32 * pDst = (U32 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn];
691 
692                     for(iChannel = 0; iChannel < cChannel; iChannel ++){
693                         PixelI p = ((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] + iBias) >> iShift);
694 
695                         p <<= nLen;
696                         pDst[iChannel] = (U32)(p);
697                     }
698                 }
699             }
700             break;
701 
702         case BD_32S:
703             for(iRow = iFirstRow; iRow < cHeight; iRow ++){
704                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
705                     I32 * pDst = (I32 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn];
706 
707                     for(iChannel = 0; iChannel < cChannel; iChannel ++){
708                         PixelI p = ((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] + iBias) >> iShift);
709 
710                         p <<= nLen;
711                         pDst[iChannel] = (I32)(p);
712                     }
713                 }
714             }
715             break;
716 
717         case BD_32F:
718             for(iRow = iFirstRow; iRow < cHeight; iRow ++){
719                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
720                     float * pDst = (float *)pSC->WMIBI.pv + iY + pOffsetX[iColumn];
721 
722                     for(iChannel = 0; iChannel < cChannel; iChannel ++){
723                         PixelI p = ((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] + iBias) >> iShift);
724 
725                         pDst[iChannel] = pixel2float (p, nExpBias, nLen);
726                     }
727                 }
728             }
729             break;
730 
731         default:
732             assert(0);
733             break;
734     }
735 }
736 
fixup_Y_ONLY_to_Others(const CWMImageStrCodec * pSC,const CWMImageBufferInfo * pBI)737 static void fixup_Y_ONLY_to_Others(
738     const CWMImageStrCodec* pSC,
739     const CWMImageBufferInfo* pBI)
740 {
741     const CWMImageInfo* pII = &pSC->WMII;
742     const CWMIStrCodecParam* pSCP = &pSC->WMISCP;
743     size_t cWidth = 0, cHeight = 0;
744     size_t idxY = 0, idxX = 0;
745 
746     if (CF_RGB != pII->cfColorFormat || Y_ONLY != pSCP->cfColorFormat)
747         return;
748 
749     cWidth = 0 != pII->cROIWidth ? pII->cROIWidth : pII->cWidth;
750     cHeight = 0 != pII->cROIHeight ? pII->cROIHeight : pII->cHeight;
751 
752 #define fixup(type, nCh) \
753 for (idxY = 0; idxY < cHeight; ++idxY) \
754 { \
755     type * pT = (type *)((U8*)pBI->pv + pBI->cbStride * idxY); \
756     for (idxX = 0; idxX < cWidth; ++idxX) \
757     { \
758         pT[2] = pT[1] = pT[0]; \
759         pT += nCh; \
760     } \
761 } \
762 break
763 
764     switch (pII->bdBitDepth)
765     {
766         case BD_8:
767             fixup(U8, (pII->cBitsPerUnit >> 3));
768             break;
769 
770         case BD_16:
771         case BD_16S:
772         case BD_16F:
773             fixup(U16, (pII->cBitsPerUnit >> 3) / sizeof(U16));
774             break;
775 
776         case BD_32:
777         case BD_32S:
778         case BD_32F:
779             fixup(U32, (pII->cBitsPerUnit >> 3) / sizeof(float));
780             break;
781 
782         case BD_5:
783         case BD_10:
784         case BD_565:
785         default:
786             break;
787     }
788 }
789 
790 // centralized alpha channel color conversion, small perf penalty
outputMBRowAlpha(CWMImageStrCodec * pSC)791 Int outputMBRowAlpha(CWMImageStrCodec * pSC)
792 {
793     if(pSC->WMII.bdBitDepth == BD_8 && pSC->WMISCP.cfColorFormat == CF_RGB)  // has been taken care of and optimized out
794         return ICERR_OK;
795 
796     if(pSC->m_bSecondary == FALSE && pSC->m_pNextSC != NULL){ // with alpha channel
797         const BITDEPTH_BITS bd = pSC->WMII.bdBitDepth;
798         const PixelI iShift = (pSC->m_param.bScaledArith ? SHIFTZERO + QPFRACBITS : 0);
799         const size_t cHeight = min((pSC->m_Dparam->cROIBottomY + 1) - (pSC->cRow - 1) * 16, 16);
800         const size_t cWidth = (pSC->m_Dparam->cROIRightX + 1);
801         const size_t iFirstRow = ((pSC->cRow - 1) * 16 > pSC->m_Dparam->cROITopY ? 0 : (pSC->m_Dparam->cROITopY & 0xf)), iFirstColumn = pSC->m_Dparam->cROILeftX;
802         const size_t iAlphaPos = pSC->WMII.cLeadingPadding + (pSC->WMII.cfColorFormat == CMYK ? 4 : 3);//only RGB and CMYK may have interleaved alpha
803         const PixelI * pA = pSC->m_pNextSC->a0MBbuffer[0];
804         const U8 nLen = pSC->WMISCP.nLenMantissaOrShift;
805         const I8 nExpBias = pSC->WMISCP.nExpBias;
806         size_t iRow, iColumn;
807         size_t * pOffsetX = pSC->m_Dparam->pOffsetX, * pOffsetY = pSC->m_Dparam->pOffsetY + (pSC->cRow - 1) * 16, iY;
808 
809         if (CF_RGB != pSC->WMII.cfColorFormat && CMYK != pSC->WMII.cfColorFormat)
810             return ICERR_ERROR;
811 
812         if(bd == BD_8){
813             const PixelI iBias = (1 << (iShift + 7)) + (iShift == 0 ? 0 : (1 << (iShift - 1)));
814 
815             for(iRow = iFirstRow; iRow < cHeight; iRow ++)
816                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
817                     PixelI a = ((pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift);
818                     ((U8 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY)[iAlphaPos] = _CLIP8(a);
819                 }
820         }
821         else if(bd == BD_16){
822             const PixelI iBias = (1 << (iShift + 15)) + (iShift == 0 ? 0 : (1 << (iShift - 1)));
823 
824             for(iRow = iFirstRow; iRow < cHeight; iRow ++)
825                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
826                     PixelI a = (((pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift) << nLen);
827                     ((U16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY)[iAlphaPos] = _CLIPU16(a);
828                 }
829         }
830         else if(bd == BD_16S){
831             const PixelI iBias = (iShift == 0 ? 0 : (1 << (iShift - 1)));
832 
833             for(iRow = iFirstRow; iRow < cHeight; iRow ++)
834                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
835                     PixelI a = (((pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift) << nLen);
836                     ((I16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY)[iAlphaPos] = _CLIP16(a);
837                 }
838         }
839         else if(bd == BD_16F){
840             const PixelI iBias = (iShift == 0 ? 0 : (1 << (iShift - 1)));
841 
842             for(iRow = iFirstRow; iRow < cHeight; iRow ++)
843                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
844                     PixelI a = ((pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift);
845                     ((U16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY)[iAlphaPos] = backwardHalf(a);
846                 }
847         }
848         else if(bd == BD_32S){
849             const PixelI iBias = (iShift == 0 ? 0 : (1 << (iShift - 1)));
850 
851             for(iRow = iFirstRow; iRow < cHeight; iRow ++)
852                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
853                     PixelI a = (((pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift) << nLen);
854                     ((I32 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY)[iAlphaPos] = a;
855                 }
856         }
857         else if(bd == BD_32F){
858             const PixelI iBias = (iShift == 0 ? 0 : (1 << (iShift - 1)));
859 
860             for(iRow = iFirstRow; iRow < cHeight; iRow ++)
861                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
862                     PixelI a = ((pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift);
863                     ((float *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY)[iAlphaPos] = pixel2float (a, nExpBias, nLen);
864                 }
865         }
866         else // not supported
867             return ICERR_ERROR;
868     }
869 
870     return ICERR_OK;
871 }
872 
outputMBRow(CWMImageStrCodec * pSC)873 Int outputMBRow(CWMImageStrCodec * pSC)
874 {
875     const COLORFORMAT cfExt = (pSC->m_param.cfColorFormat == Y_ONLY ? Y_ONLY : pSC->WMII.cfColorFormat);
876     const BITDEPTH_BITS bd = pSC->WMII.bdBitDepth;
877     const PixelI iShift = (pSC->m_param.bScaledArith ? SHIFTZERO + QPFRACBITS : 0);
878     const size_t cHeight = min((pSC->m_Dparam->cROIBottomY + 1) - (pSC->cRow - 1) * 16, 16);
879     const size_t cWidth = (pSC->m_Dparam->cROIRightX + 1);
880     const size_t iFirstRow = ((pSC->cRow - 1) * 16 > pSC->m_Dparam->cROITopY ? 0 : (pSC->m_Dparam->cROITopY & 0xf)), iFirstColumn = pSC->m_Dparam->cROILeftX;
881     const PixelI *pY = pSC->a0MBbuffer[0];
882     const PixelI *pU = (pSC->m_bUVResolutionChange ? pSC->pResU : pSC->a0MBbuffer[1]);
883     const PixelI *pV = (pSC->m_bUVResolutionChange ? pSC->pResV : pSC->a0MBbuffer[2]);
884     const PixelI *pA = NULL;
885 	const size_t iB = (pSC->WMII.bRGB ? 2 : 0);
886 	const size_t iR = 2 - iB;
887     const U8 nLen = pSC->WMISCP.nLenMantissaOrShift;
888     const I8 nExpBias = pSC->WMISCP.nExpBias;
889     size_t iRow, iColumn, iIdx;
890     size_t * pOffsetX = pSC->m_Dparam->pOffsetX, * pOffsetY = pSC->m_Dparam->pOffsetY + (pSC->cRow - 1) * (cfExt == YUV_420 ? 8 : 16), iY;
891 
892 
893     if (pSC->m_pNextSC) {
894         assert (pSC->m_param.bScaledArith == pSC->m_pNextSC->m_param.bScaledArith);  // will be relaxed later
895     }
896 
897     // guard output buffer
898     if(checkImageBuffer(pSC, pSC->WMII.oOrientation >= O_RCW ? pSC->WMII.cROIHeight : pSC->WMII.cROIWidth, cHeight - iFirstRow) != ICERR_OK)
899         return ICERR_ERROR;
900 
901     if(pSC->m_bUVResolutionChange)
902         interpolateUV(pSC);
903 
904     if(pSC->WMISCP.bYUVData){
905         I32 * pDst = (I32 *)pSC->WMIBI.pv + (pSC->cRow - 1) *
906             (pSC->m_param.cfColorFormat == YUV_420 ? 8 : 16) * pSC->WMIBI.cbStride / sizeof(I32);
907 
908         switch(pSC->m_param.cfColorFormat){
909         case Y_ONLY:
910         case YUV_444:
911         case NCOMPONENT:
912             {
913                 PixelI * pChannel[16];
914                 size_t iChannel;
915 
916                 const size_t cChannel = pSC->WMII.cfColorFormat == Y_ONLY ? 1 : pSC->WMISCP.cChannel;
917                 assert(cChannel <= 16);
918 
919                 for(iChannel = 0; iChannel < cChannel; iChannel ++)
920                     pChannel[iChannel & 15] = pSC->a0MBbuffer[iChannel];
921 
922                 for(iRow = iFirstRow; iRow < cHeight; iRow ++){
923                     I32 * pRow = pDst;
924                     for(iColumn = iFirstColumn; iColumn < cWidth; iColumn ++){
925                         for(iChannel = 0; iChannel < cChannel; iChannel ++){
926                             PixelI p = pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]];
927 
928                             *pRow++ = p;
929                         }
930                     }
931                     pDst += pSC->WMIBI.cbStride / sizeof(I32);
932                 }
933             }
934             break;
935 
936         case YUV_422:
937             {
938 				PixelI y0, y1, u, v;
939 
940 				for(iRow = iFirstRow; iRow < cHeight; iRow ++){
941                     I32 * pRow = pDst;
942 					for(iColumn = iFirstColumn; iColumn < cWidth; iColumn += 2){
943 						iIdx = ((iColumn >> 4) << 7) + idxCC[iRow][(iColumn >> 1) & 7];
944 						u = pU[iIdx], v = pV[iIdx];
945 
946 						y0 = pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]];
947 						y1 = pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]];
948 
949 						pRow[0] = u, pRow[1] = y0, pRow[2] = v, pRow[3] = y1;
950                         pRow += 4;
951 					}
952                     pDst += pSC->WMIBI.cbStride / sizeof(I32);
953 				}
954 			}
955             break;
956 
957         case YUV_420:
958 			{
959 				PixelI y0, y1, y2, y3, u, v;
960 				// const size_t iS4[8][4] = {{0, 1, 2, 3}, {2, 3, 0, 1}, {1, 0, 3, 2}, {3, 2, 1, 0}, {1, 3, 0, 2}, {3, 1, 2, 0}, {0, 2, 1, 3}, {2, 0, 3, 1}};
961 
962 				for(iRow = iFirstRow; iRow < cHeight; iRow += 2){
963                     I32 * pRow = pDst;
964 					for(iColumn = iFirstColumn; iColumn < cWidth; iColumn += 2){
965 						iIdx = ((iColumn >> 4) << 6) + idxCC_420[iRow >> 1][(iColumn >> 1) & 7];
966 						u = pU[iIdx], v = pV[iIdx];
967 
968 						y0 = pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]];
969 						y1 = pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]];
970 						y2 = pY[((iColumn >> 4) << 8) + idxCC[iRow + 1][iColumn & 15]];
971 						y3 = pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow + 1][(iColumn + 1) & 15]];
972 
973 						pRow[0] = y0, pRow[1] = y1, pRow[2] = y2, pRow[3] = y3, pRow[4] = u, pRow[5] = v;
974                         pRow += 6;
975 					}
976                     pDst += pSC->WMIBI.cbStride / sizeof(I32);
977 				}
978 			}
979             break;
980 
981         default:
982             assert(0);
983             break;
984         }
985     }
986     else if(bd == BD_8){
987         U8 * pDst;
988         const PixelI iBias1 = 128 << iShift;
989         const PixelI iBias2 = pSC->m_param.bScaledArith ? ((1 << (SHIFTZERO + QPFRACBITS - 1)) - 1) : 0;
990         const PixelI iBias = iBias1 + iBias2;
991 
992         switch(cfExt){
993         case CF_RGB:
994         {
995             PixelI r, g, b, a;
996 
997             if (pSC->m_pNextSC && pSC->WMISCP.uAlphaMode > 0) { // RGBA
998 
999                 pA = pSC->m_pNextSC->a0MBbuffer[0];
1000 
1001                 if (pSC->m_param.bScaledArith == FALSE) {
1002                     for(iRow = iFirstRow; iRow < cHeight; iRow ++)
1003                         for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
1004                             iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
1005 
1006                             g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx];
1007                             a = pA[iIdx] + iBias;
1008 
1009                             _ICC(r, g, b);
1010 
1011                             pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY;
1012                             if ((g | b | r | a) & ~0xff)
1013                                 pDst[iR] = _CLIP8(r), pDst[1] = _CLIP8(g), pDst[iB] = _CLIP8(b), pDst[3] = _CLIP8(a);
1014                             else
1015                                 pDst[iR] = (U8)r, pDst[1] = (U8)g, pDst[iB] = (U8)b, pDst[3] = (U8)(a);
1016                         }
1017                 }
1018                 else{
1019                     for(iRow = iFirstRow; iRow < cHeight; iRow ++)
1020                         for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
1021                             iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
1022 
1023                             g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx];
1024                             a = pA[iIdx] + iBias;
1025 
1026                             _ICC(r, g, b);
1027 
1028                             g >>= iShift, b >>= iShift, r >>= iShift, a >>= iShift;
1029                             pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY;
1030                             if ((g | b | r | a) & ~0xff)
1031                                 pDst[iR] = _CLIP8(r), pDst[1] = _CLIP8(g), pDst[iB] = _CLIP8(b), pDst[3] = _CLIP8(a);
1032                             else
1033                                 pDst[iR] = (U8)r, pDst[1] = (U8)g, pDst[iB] = (U8)b, pDst[3] = (U8)(a);
1034                         }
1035                 }
1036             }
1037             else {
1038                 if (pSC->m_param.bScaledArith == FALSE) {
1039                     for(iRow = iFirstRow; iRow < cHeight; iRow ++)
1040                         for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
1041                             iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
1042 
1043                             g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx];
1044 
1045                             _ICC(r, g, b);
1046 
1047                             pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY;
1048                             if ((g | b | r) & ~0xff)
1049                                 pDst[iR] = _CLIP8(r), pDst[1] = _CLIP8(g), pDst[iB] = _CLIP8(b);
1050                             else
1051                                 pDst[iR] = (U8)r, pDst[1] = (U8)g, pDst[iB] = (U8)b;
1052                         }
1053                 }
1054                 else{
1055                     for(iRow = iFirstRow; iRow < cHeight; iRow ++)
1056                         for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
1057                             iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
1058 
1059                             g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx];
1060 
1061                             _ICC(r, g, b);
1062 
1063                             g >>= iShift, b >>= iShift, r >>= iShift;
1064                             pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY;
1065                             if ((g | b | r) & ~0xff)
1066                                 pDst[iR] = _CLIP8(r), pDst[1] = _CLIP8(g), pDst[iB] = _CLIP8(b);
1067                             else
1068                                 pDst[iR] = (U8)r, pDst[1] = (U8)g, pDst[iB] = (U8)b;
1069                         }
1070                 }
1071             }
1072             break;
1073         }
1074 
1075         case Y_ONLY:
1076         case YUV_444:
1077         case NCOMPONENT:
1078             outputNChannel(pSC, iFirstRow, iFirstColumn, cWidth, cHeight, iShift, iBias);
1079             break;
1080 
1081         case YUV_422:
1082 			{
1083 				PixelI y0, y1, u, v;
1084 				// const ORIENTATION oO = pSC->WMII.oOrientation;
1085 				// const size_t i0 = ((oO > O_FLIPV && oO <= O_RCW_FLIPVH) ? 1 : 0), i1 = 1 - i0;
1086 
1087 				for(iRow = iFirstRow; iRow < cHeight; iRow ++){
1088 					for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn += 2){
1089 						iIdx = ((iColumn >> 4) << 7) + idxCC[iRow][(iColumn >> 1) & 7];
1090 						u = ((pU[iIdx] + iBias) >> iShift), v = ((pV[iIdx] + iBias) >> iShift);
1091 
1092 						y0 = ((pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift);
1093 						y1 = ((pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] + iBias) >> iShift);
1094 
1095 						pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn >> 1] + iY;
1096 						if ((y0 | y1 | u | v) & ~0xff)//UYVY
1097 							pDst[0] = _CLIP8(u), pDst[1] = _CLIP8(y0), pDst[2] = _CLIP8(v), pDst[3] = _CLIP8(y1);
1098 						else
1099 							pDst[0] = (U8)u, pDst[1] = (U8)y0, pDst[2] = (U8)v, pDst[3] = (U8)y1;
1100 					}
1101 				}
1102 			}
1103 			break;
1104 
1105         case YUV_420:
1106 			{
1107 				PixelI y0, y1, y2, y3, u, v;
1108 				const size_t iS4[8][4] = {{0, 1, 2, 3}, {2, 3, 0, 1}, {1, 0, 3, 2}, {3, 2, 1, 0}, {1, 3, 0, 2}, {3, 1, 2, 0}, {0, 2, 1, 3}, {2, 0, 3, 1}};
1109 				const ORIENTATION oO = pSC->WMII.oOrientation;
1110 				const size_t i0 = iS4[oO][0], i1 = iS4[oO][1], i2 = iS4[oO][2], i3 = iS4[oO][3];
1111 
1112 				for(iRow = iFirstRow; iRow < cHeight; iRow += 2){
1113 					for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> 1]; iColumn < cWidth; iColumn += 2){
1114 						iIdx = ((iColumn >> 4) << 6) + idxCC_420[iRow >> 1][(iColumn >> 1) & 7];
1115 						u = ((pU[iIdx] + iBias) >> iShift), v = ((pV[iIdx] + iBias) >> iShift);
1116 
1117 						y0 = ((pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift);
1118 						y1 = ((pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] + iBias) >> iShift);
1119 						y2 = ((pY[((iColumn >> 4) << 8) + idxCC[iRow + 1][iColumn & 15]] + iBias) >> iShift);
1120 						y3 = ((pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow + 1][(iColumn + 1) & 15]] + iBias) >> iShift);
1121 
1122 						pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn >> 1] + iY;
1123 						if ((y0 | y1 | y2 | y3 | u | v) & ~0xff)
1124 							pDst[i0] = _CLIP8(y0), pDst[i1] = _CLIP8(y1), pDst[i2] = _CLIP8(y2), pDst[i3] = _CLIP8(y3), pDst[4] = _CLIP8(u), pDst[5] = _CLIP8(v);
1125 						else
1126 							pDst[i0] = (U8)y0, pDst[i1] = (U8)y1, pDst[i2] = (U8)y2, pDst[i3] = (U8)y3, pDst[4] = (U8)u, pDst[5] = (U8)v;
1127 					}
1128 				}
1129 			}
1130 			break;
1131 
1132         case CMYK:
1133 			{
1134 				PixelI c, m, y, k;
1135 				PixelI * pK = pSC->a0MBbuffer[3];
1136 
1137 				for(iRow = iFirstRow; iRow < cHeight; iRow++){
1138 					for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn++){
1139 						iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
1140 
1141 						m = -pY[iIdx] + iBias1, c = pU[iIdx], y = -pV[iIdx], k = pK[iIdx] + iBias2;
1142 
1143 						_ICC_CMYK(c, m, y, k); // color conversion
1144 
1145 						c >>= iShift, m >>= iShift, y >>= iShift, k >>= iShift;
1146 
1147 						pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY;
1148 						if ((c | m | y | k) & ~0xff)
1149 							pDst[0] = _CLIP8(c), pDst[1] = _CLIP8(m), pDst[2] = _CLIP8(y), pDst[3] = _CLIP8(k);
1150 						else
1151 							pDst[0] = (U8)c, pDst[1] = (U8)m, pDst[2] = (U8)y, pDst[3] = (U8)k;
1152 					}
1153 				}
1154 			}
1155 			break;
1156 
1157         case CF_RGBE:
1158 			{
1159 				PixelI r, g, b;
1160 
1161 				for(iRow = iFirstRow; iRow < cHeight; iRow ++){
1162 					for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
1163 							iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
1164 
1165 							g = pY[iIdx] + iBias2, r = -pU[iIdx], b = pV[iIdx];
1166 
1167 							_ICC(r, g, b);
1168 
1169 							pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY;
1170 
1171 							inverseConvertRGBE (r >> iShift, g >> iShift, b >> iShift, pDst, pDst + 1, pDst + 2, pDst + 3);
1172 						}
1173 				}
1174 			}
1175 			break;
1176 
1177         default:
1178             assert(0);
1179             break;
1180     }
1181     }
1182     else if(bd == BD_16){
1183         const PixelI iBias = (((1 << 15) >> nLen) << iShift) + (iShift == 0 ? 0 : (1 << (iShift - 1)));
1184         U16 * pDst;
1185 
1186         switch(cfExt){
1187         case CF_RGB:
1188         {
1189             PixelI r, g, b;
1190 			if (pSC->m_param.bScaledArith == FALSE) {
1191 				for(iRow = iFirstRow; iRow < cHeight; iRow ++)
1192 					for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
1193 						iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
1194 
1195 						g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx];
1196 
1197 						_ICC(r, g, b);
1198 
1199 						g <<= nLen, b <<= nLen, r <<= nLen;
1200 
1201 						pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY;
1202 
1203 						if ((g | b | r) & ~0xffff)
1204 							pDst[0] = _CLIPU16(r),  pDst[1] = _CLIPU16(g), pDst[2] = _CLIPU16(b);
1205 						else
1206 							pDst[0] = (U16)r, pDst[1] = (U16)g, pDst[2] = (U16)b;
1207 					}
1208 			}
1209 			else{
1210 				for(iRow = iFirstRow; iRow < cHeight; iRow ++)
1211 					for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
1212 						iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
1213 
1214 						g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx];
1215 
1216 						_ICC(r, g, b);
1217 
1218 						g = (g >> iShift) << nLen, b = (b >> iShift) << nLen, r = (r >> iShift) << nLen;
1219 						pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY;
1220 						if ((g | b | r) & ~0xffff)
1221 							pDst[0] = _CLIPU16(r),  pDst[1] = _CLIPU16(g), pDst[2] = _CLIPU16(b);
1222 						else
1223 							pDst[0] = (U16)r, pDst[1] = (U16)g, pDst[2] = (U16)b;
1224 					}
1225 			}
1226             break;
1227         }
1228 
1229         case Y_ONLY:
1230         case YUV_444:
1231         case NCOMPONENT:
1232             outputNChannel(pSC, iFirstRow, iFirstColumn, cWidth, cHeight, iShift, iBias);
1233             break;
1234 
1235         case YUV_422:
1236 			{
1237 				PixelI y0, y1, u, v;
1238 				const ORIENTATION oO = pSC->WMII.oOrientation;
1239 				const size_t i0 = ((oO == O_FLIPH || oO == O_FLIPVH || oO == O_RCW_FLIPV || oO == O_RCW_FLIPVH) ? 1 : 0), i1 = 1 - i0;
1240 
1241 				for(iRow = iFirstRow; iRow < cHeight; iRow ++){
1242 					for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn += 2){
1243 						iIdx = ((iColumn >> 4) << 7) + idxCC[iRow][(iColumn >> 1) & 7];
1244 						u = ((pU[iIdx] + iBias) >> iShift) << nLen, v = ((pV[iIdx] + iBias) >> iShift) << nLen;
1245 
1246 						y0 = ((pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift) << nLen;
1247 						y1 = ((pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] + iBias) >> iShift) << nLen;
1248 
1249 						pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> 1] + iY;
1250 						if ((y0 | y1 | u | v) & ~0xffff)
1251 							{
1252 								pDst[i0] = _CLIPU16(u);
1253 								pDst[i1] = _CLIPU16(y0);
1254 								pDst[2] = _CLIPU16(v);
1255 								pDst[3] = _CLIPU16(y1);
1256 							}
1257 						else
1258 							{
1259 								pDst[i0] = (U16)(u);
1260 								pDst[i1] = (U16)(y0);
1261 								pDst[2] = (U16)(v);
1262 								pDst[3] = (U16)(y1);
1263 							}
1264 					}
1265 				}
1266 			}
1267 			break;
1268 
1269         case YUV_420:
1270 			{
1271 				PixelI y0, y1, y2, y3, u, v;
1272 				const size_t iS4[8][4] = {{0, 1, 2, 3}, {2, 3, 0, 1}, {1, 0, 3, 2}, {3, 2, 1, 0}, {1, 3, 0, 2}, {3, 1, 2, 0}, {0, 2, 1, 3}, {2, 0, 3, 1}};
1273 				const ORIENTATION oO = pSC->WMII.oOrientation;
1274 				const size_t i0 = iS4[oO][0], i1 = iS4[oO][1], i2 = iS4[oO][2], i3 = iS4[oO][3];
1275 
1276 				for(iRow = iFirstRow; iRow < cHeight; iRow += 2){
1277 					for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> 1]; iColumn < cWidth; iColumn += 2){
1278 						iIdx = ((iColumn >> 3) << 6) + idxCC[iRow][(iColumn >> 1) & 7];
1279 						u = ((pU[iIdx] + iBias) >> iShift) << nLen, v = ((pV[iIdx] + iBias) >> iShift) << nLen;
1280 
1281 						y0 = ((pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iBias) >> iShift) << nLen;
1282 						y1 = ((pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] + iBias) >> iShift) << nLen;
1283 						y2 = ((pY[((iColumn >> 4) << 8) + idxCC[iRow + 1][iColumn & 15]] + iBias) >> iShift) << nLen;
1284 						y3 = ((pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow + 1][(iColumn + 1) & 15]] + iBias) >> iShift) << nLen;
1285 
1286 						pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> 1] + iY;
1287 						if ((y0 | y1 | y2 | y3 | u | v) & ~0xffff)
1288 							{
1289 								pDst[i0] = _CLIPU16(y0);
1290 								pDst[i1] = _CLIPU16(y1);
1291 								pDst[i2] = _CLIPU16(y2);
1292 								pDst[i3] = _CLIPU16(y3);
1293 								pDst[4] = _CLIPU16(u);
1294 								pDst[5] = _CLIPU16(v);
1295 							}
1296 						else
1297 							{
1298 								pDst[i0] = (U16)(y0);
1299 								pDst[i1] = (U16)(y1);
1300 								pDst[i2] = (U16)(y2);
1301 								pDst[i3] = (U16)(y3);
1302 								pDst[4] = (U16)(u);
1303 								pDst[5] = (U16)(v);
1304 							}
1305 					}
1306 				}
1307 			}
1308 			break;
1309 
1310         case CMYK:
1311 			{
1312 				PixelI c, m, y, k;
1313 				PixelI * pK = pSC->a0MBbuffer[3];
1314 				const PixelI iBias1 = (32768 >> nLen) << iShift;
1315 				const PixelI iBias2 = iBias - iBias1;
1316 
1317 				for(iRow = iFirstRow; iRow < cHeight; iRow++){
1318 					for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn++){
1319 						iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
1320 
1321 						m = -pY[iIdx] + iBias1, c = pU[iIdx], y = -pV[iIdx], k = pK[iIdx] + iBias2;
1322 
1323 						_ICC_CMYK(c, m, y, k); // color conversion
1324 
1325 						c = (c >> iShift) << nLen, m = (m >> iShift) << nLen, y = (y >> iShift) << nLen, k = (k >> iShift) << nLen;
1326 
1327 						pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY;
1328 						if ((c | m | y | k) & ~0xffff)
1329 							pDst[0] = _CLIPU16(c), pDst[1] = _CLIPU16(m), pDst[2] = _CLIPU16(y), pDst[3] = _CLIPU16(k);
1330 						else
1331 							pDst[0] = (U16)(c), pDst[1] = (U16)(m), pDst[2] = (U16)(y), pDst[3] = (U16)(k);
1332 						}
1333 				}
1334 			}
1335 			break;
1336         default:
1337             assert(0);
1338             break;
1339     }
1340     }
1341     else if(bd == BD_16S){
1342         const PixelI iBias = pSC->m_param.bScaledArith ? ((1 << (SHIFTZERO + QPFRACBITS - 1)) - 1) : 0;
1343         I16 * pDst;
1344 
1345         switch(cfExt){
1346         case CF_RGB:
1347         {
1348             PixelI r, g, b;
1349 
1350             for(iRow = iFirstRow; iRow < cHeight; iRow ++)
1351                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
1352                     iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
1353 
1354                     g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx];
1355 
1356                     _ICC(r, g, b);
1357 
1358                     r = (r >> iShift) << nLen, g = (g >> iShift) << nLen, b = (b >> iShift) << nLen;
1359 
1360                     pDst = (I16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY;
1361                     pDst[0] = _CLIP16(r), pDst[1] = _CLIP16(g), pDst[2] = _CLIP16(b);
1362                 }
1363             break;
1364         }
1365 
1366         case Y_ONLY:
1367         case YUV_444:
1368         case NCOMPONENT:
1369             outputNChannel(pSC, iFirstRow, iFirstColumn, cWidth, cHeight, iShift, iBias);
1370             break;
1371 
1372         case CMYK:
1373 			{
1374 				PixelI c, m, y, k;
1375 				PixelI * pK = pSC->a0MBbuffer[3];
1376 
1377 				for(iRow = iFirstRow; iRow < cHeight; iRow++){
1378 					for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn++){
1379 						iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
1380 
1381 						m = -pY[iIdx], c = pU[iIdx], y = -pV[iIdx], k = pK[iIdx] + iBias;
1382 
1383 						_ICC_CMYK(c, m, y, k); // color conversion
1384 
1385 						c = (c >> iShift) << nLen, m = (m >> iShift) << nLen, y = (y >> iShift) << nLen, k = (k >> iShift) << nLen;
1386 
1387 						pDst = (I16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY;
1388 						pDst[0] = (I16)(c), pDst[1] = (I16)(m), pDst[2] = (I16)(y), pDst[3] = (I16)(k);
1389 					}
1390 				}
1391 			}
1392 			break;
1393 
1394         default:
1395             assert(0);
1396             break;
1397     }
1398     }
1399     else if(bd == BD_16F){
1400         const PixelI iBias = pSC->m_param.bScaledArith ? ((1 << (SHIFTZERO + QPFRACBITS - 1)) - 1) : 0;
1401         U16 *pDst;
1402 
1403         switch (cfExt)
1404         {
1405         case CF_RGB:
1406         {
1407             PixelI r, g, b;
1408 
1409             for(iRow = iFirstRow; iRow < cHeight; iRow ++){
1410                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
1411                     iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
1412 
1413                     g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx];
1414 
1415                     _ICC(r, g, b);
1416 
1417                     pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY;
1418                     pDst[0] = backwardHalf(r >> iShift);
1419                     pDst[1] = backwardHalf(g >> iShift);
1420                     pDst[2] = backwardHalf(b >> iShift);
1421                 }
1422             }
1423             break;
1424         }
1425 
1426         case Y_ONLY:
1427         case YUV_444:
1428         case NCOMPONENT:
1429             outputNChannel(pSC, iFirstRow, iFirstColumn, cWidth, cHeight, iShift, iBias);
1430             break;
1431 
1432         default:
1433             assert(0);
1434             break;
1435         }
1436     }
1437     else if(bd == BD_32){
1438         const PixelI iBias = (((1 << 31) >> nLen) << iShift) + (iShift == 0 ? 0 : (1 << (iShift - 1)));
1439         U32 * pDst;
1440 
1441         switch (cfExt)
1442         {
1443         case CF_RGB:
1444 			{
1445 				PixelI r, g, b;
1446 
1447 				for(iRow = iFirstRow; iRow < cHeight; iRow ++){
1448 					for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
1449 						iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
1450 
1451 						g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx];
1452 
1453 						_ICC(r, g, b);
1454 
1455 						pDst = (U32 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY;
1456 						pDst[0] = ((r >> iShift) << nLen);
1457 						pDst[1] = ((g >> iShift) << nLen);
1458 						pDst[2] = ((b >> iShift) << nLen);
1459 					}
1460 				}
1461 			}
1462 			break;
1463 
1464         case Y_ONLY:
1465         case YUV_444:
1466         case NCOMPONENT:
1467         {
1468             outputNChannel(pSC, iFirstRow, iFirstColumn, cWidth, cHeight, iShift, iBias);
1469             break;
1470         }
1471         default:
1472             assert(0);
1473             break;
1474         }
1475     }
1476     else if(bd == BD_32S){
1477         const PixelI iBias = pSC->m_param.bScaledArith ? ((1 << (SHIFTZERO + QPFRACBITS - 1)) - 1) : 0;
1478         int * pDst;
1479 
1480         switch (cfExt)
1481         {
1482         case CF_RGB:
1483         {
1484             PixelI r, g, b;
1485 
1486             for(iRow = iFirstRow; iRow < cHeight; iRow ++){
1487                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
1488                     iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
1489 
1490                     g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx];
1491 
1492                     _ICC(r, g, b);
1493 
1494                     pDst = (int *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY;
1495                     pDst[0] = ((r >> iShift) << nLen);
1496                     pDst[1] = ((g >> iShift) << nLen);
1497                     pDst[2] = ((b >> iShift) << nLen);
1498                 }
1499             }
1500             break;
1501         }
1502 
1503         case Y_ONLY:
1504         case YUV_444:
1505         case NCOMPONENT:
1506             outputNChannel(pSC, iFirstRow, iFirstColumn, cWidth, cHeight, iShift, iBias);
1507             break;
1508 
1509 		default:
1510             assert(0);
1511             break;
1512         }
1513     }
1514     else if(bd == BD_32F){
1515         const PixelI iBias = pSC->m_param.bScaledArith ? ((1 << (SHIFTZERO + QPFRACBITS - 1)) - 1) : 0;
1516         float * pDst;
1517 
1518         switch (cfExt)
1519         {
1520         case CF_RGB:
1521         {
1522             PixelI r, g, b;
1523 
1524             for(iRow = iFirstRow; iRow < cHeight; iRow ++){
1525                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
1526                     iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
1527 
1528                     g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx];
1529 
1530                     _ICC(r, g, b);
1531 
1532                     pDst = (float *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY;
1533                     pDst[0] = pixel2float (r >> iShift, nExpBias, nLen);
1534                     pDst[1] = pixel2float (g >> iShift, nExpBias, nLen);
1535                     pDst[2] = pixel2float (b >> iShift, nExpBias, nLen);
1536                 }
1537             }
1538             break;
1539         }
1540         case Y_ONLY:
1541         case YUV_444:
1542         case NCOMPONENT:
1543             outputNChannel(pSC, iFirstRow, iFirstColumn, cWidth, cHeight, iShift, iBias);
1544             break;
1545 
1546         default:
1547             assert(0);
1548             break;
1549         }
1550     }
1551     else if(bd == BD_5){
1552         const PixelI iBias = (16 << iShift) + (pSC->m_param.bScaledArith ? ((1 << (SHIFTZERO + QPFRACBITS - 1)) - 1) : 0);
1553         PixelI r, g, b;
1554         U16 * pDst;
1555 
1556         assert(cfExt == CF_RGB);
1557 
1558         for(iRow = iFirstRow; iRow < cHeight; iRow ++)
1559             for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
1560                 iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
1561 
1562                 g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx];
1563 
1564                 _ICC(r, g, b);
1565 
1566                 g >>= iShift, b >>= iShift, r >>= iShift;
1567                 pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY;
1568                 if (pSC->m_param.bRBSwapped)
1569                     pDst[0] = (U16)_CLIP2(0, b, 31) + (((U16)_CLIP2(0, g, 31)) << 5) + (((U16)_CLIP2(0, r, 31)) << 10);
1570                 else
1571                     pDst[0] = (U16)_CLIP2(0, r, 31) + (((U16)_CLIP2(0, g, 31)) << 5) + (((U16)_CLIP2(0, b, 31)) << 10);
1572             }
1573     }
1574     else if(bd == BD_565){
1575         const PixelI iBias = (32 << iShift) + (pSC->m_param.bScaledArith ? ((1 << (SHIFTZERO + QPFRACBITS - 1)) - 1) : 0);
1576         PixelI r, g, b;
1577         U16 * pDst;
1578 
1579         assert(cfExt == CF_RGB);
1580 
1581         for(iRow = iFirstRow; iRow < cHeight; iRow ++)
1582             for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
1583                 iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
1584 
1585                 g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx];
1586 
1587                 _ICC(r, g, b);
1588 
1589                 g >>= iShift, b >>= iShift + 1, r >>= iShift + 1;
1590                 pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY;
1591                 if (pSC->m_param.bRBSwapped)
1592                     pDst[0] = (U16)_CLIP2(0, b, 31) + (((U16)_CLIP2(0, g, 63)) << 5) + (((U16)_CLIP2(0, r, 31)) << 11);
1593                 else
1594                     pDst[0] = (U16)_CLIP2(0, r, 31) + (((U16)_CLIP2(0, g, 63)) << 5) + (((U16)_CLIP2(0, b, 31)) << 11);
1595             }
1596     }
1597     else if(bd == BD_10){
1598         const PixelI iBias = (512 << iShift) + (pSC->m_param.bScaledArith ? ((1 << (SHIFTZERO + QPFRACBITS - 1)) - 1) : 0);
1599         PixelI r, g, b;
1600         U32 * pDst;
1601 
1602         assert(cfExt == CF_RGB);
1603 
1604         for(iRow = iFirstRow; iRow < cHeight; iRow ++)
1605             for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){
1606                 iIdx = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
1607 
1608                 g = pY[iIdx] + iBias, r = -pU[iIdx], b = pV[iIdx];
1609 
1610                 _ICC(r, g, b);
1611 
1612                 g >>= iShift, b >>= iShift, r >>= iShift;
1613 
1614                 pDst = (U32 *)pSC->WMIBI.pv + pOffsetX[iColumn] + iY;
1615                 if (pSC->m_param.bRBSwapped)
1616                     pDst[0] = (U32)_CLIP2(0, b, 1023) +
1617                         (((U32)_CLIP2(0, g, 1023)) << 10) +
1618                         (((U32)_CLIP2(0, r, 1023)) << 20);
1619                 else
1620                     pDst[0] = (U32)_CLIP2(0, r, 1023) +
1621                         (((U32)_CLIP2(0, g, 1023)) << 10) +
1622                         (((U32)_CLIP2(0, b, 1023)) << 20);
1623             }
1624     }
1625     else if(bd == BD_1){
1626         const size_t iPos = pSC->WMII.cLeadingPadding;
1627         const Int iTh = (iShift > 0) ? (1 << (iShift - 1)) : 1;
1628         assert(cfExt == Y_ONLY && pSC->m_param.cfColorFormat == Y_ONLY);
1629 
1630         if(pSC->WMII.oOrientation < O_RCW)
1631             for(iRow = iFirstRow; iRow < cHeight; iRow ++) {
1632                 iY = pOffsetY[iRow] + iPos;
1633                 for(iColumn = iFirstColumn; iColumn < cWidth; iColumn ++) {
1634                     U8 cByte = ((U8 *)pSC->WMIBI.pv + (pOffsetX[iColumn] >> 3) + iY)[0];
1635                     U8 cShift = (U8)(7 - (pOffsetX[iColumn] & 7));
1636                     ((U8 *)pSC->WMIBI.pv + (pOffsetX[iColumn] >> 3) + iY)[0] ^= // exor is used because we can't assume the byte was originally zero
1637                     (((pSC->WMISCP.bBlackWhite + (pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] >= iTh)
1638                     + (cByte >> cShift)) & 0x1) << cShift);
1639                 }
1640             }
1641         else
1642             for(iRow = iFirstRow; iRow < cHeight; iRow ++) {
1643                 iY = pOffsetY[iRow] + iPos;
1644                 for(iColumn = iFirstColumn; iColumn < cWidth; iColumn ++) {
1645                     U8 cByte = ((U8 *)pSC->WMIBI.pv + pOffsetX[iColumn] + (iY >> 3))[0];
1646                     U8 cShift = (U8)(7 - (iY & 7));  // should be optimized out
1647                     ((U8 *)pSC->WMIBI.pv + pOffsetX[iColumn] + (iY >> 3))[0] ^= // exor is used because we can't assume the byte was originally zero
1648                     (((pSC->WMISCP.bBlackWhite + (pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] >= iTh)
1649                     + (cByte >> cShift)) & 0x1) << cShift);
1650                 }
1651             }
1652     }
1653 
1654     if(pSC->WMISCP.uAlphaMode > 0)
1655         if(outputMBRowAlpha(pSC) != ICERR_OK)
1656             return ICERR_ERROR;
1657 
1658 #ifdef REENTRANT_MODE
1659     pSC->WMIBI.cLinesDecoded = cHeight - iFirstRow;
1660 
1661     if (CF_RGB == pSC->WMII.cfColorFormat && Y_ONLY == pSC->WMISCP.cfColorFormat)
1662     {
1663         const CWMImageInfo* pII = &pSC->WMII;
1664 
1665 #define fixupFullSize(type, nCh) \
1666 for(iRow = iFirstRow; iRow < cHeight; iRow ++) {\
1667     size_t iY;\
1668     for(iColumn = iFirstColumn, iY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){\
1669         type *pT = (type*)(U8 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn];\
1670         pT[2] = pT[1] = pT[0]; \
1671         pT += nCh; \
1672     } \
1673 } \
1674 break
1675 
1676         switch (pII->bdBitDepth)
1677         {
1678             case BD_8:
1679                 fixupFullSize(U8, (pII->cBitsPerUnit >> 3));
1680                 break;
1681 
1682             case BD_16:
1683             case BD_16S:
1684             case BD_16F:
1685                 fixupFullSize(U16, (pII->cBitsPerUnit >> 3) / sizeof(U16));
1686                 break;
1687 
1688             case BD_32:
1689             case BD_32S:
1690             case BD_32F:
1691                 fixupFullSize(U32, (pII->cBitsPerUnit >> 3) / sizeof(float));
1692                 break;
1693 
1694             case BD_5:
1695             case BD_10:
1696             case BD_565:
1697             default:
1698                 break;
1699         }
1700     }
1701 #endif
1702 
1703     return ICERR_OK;
1704 }
1705 
1706 // Y_ONLY/CF_ALPHA/YUV_444/N_CHANNEL thumbnail decode
outputNChannelThumbnail(CWMImageStrCodec * pSC,const PixelI cMul,const size_t rShiftY,size_t iFirstRow,size_t iFirstColumn)1707 Void outputNChannelThumbnail(CWMImageStrCodec * pSC, const PixelI cMul, const size_t rShiftY, size_t iFirstRow, size_t iFirstColumn)
1708 {
1709     const size_t tScale = pSC->m_Dparam->cThumbnailScale;
1710     const size_t cWidth = (pSC->m_Dparam->cROIRightX + 1);
1711     const size_t cHeight = min((pSC->m_Dparam->cROIBottomY + 1) - (pSC->cRow - 1) * 16, 16);
1712     const size_t cChannel = pSC->WMISCP.cChannel;
1713     const U8 nLen = pSC->WMISCP.nLenMantissaOrShift;
1714     const I8 nExpBias = pSC->WMISCP.nExpBias;
1715     size_t nBits = 0;
1716     PixelI iOffset;
1717     PixelI * pChannel[16];
1718     size_t iChannel, iRow, iColumn;
1719     size_t * pOffsetX = pSC->m_Dparam->pOffsetX, * pOffsetY = pSC->m_Dparam->pOffsetY + (pSC->cRow - 1) * 16 / tScale, iY;
1720 
1721     while((size_t)(1U << nBits) < tScale)
1722         nBits ++;
1723 
1724     assert(cChannel <= 16);
1725 
1726     for(iChannel = 0; iChannel < cChannel; iChannel ++)
1727         pChannel[iChannel & 15] = pSC->a0MBbuffer[iChannel];
1728 
1729     if(pSC->m_bUVResolutionChange)
1730         pChannel[1] = pSC->pResU, pChannel[2] = pSC->pResV;
1731 
1732     switch(pSC->WMII.bdBitDepth){
1733         case BD_8:
1734             for(iOffset = (128 << rShiftY) / cMul, iRow = iFirstRow; iRow < cHeight; iRow += tScale){
1735                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
1736                     U8 * pDst = (U8 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn >> nBits];
1737 
1738                     for(iChannel = 0; iChannel < cChannel; iChannel ++){
1739                         PixelI p = ((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iOffset) * cMul) >> rShiftY;
1740 
1741                         pDst[iChannel] = _CLIP8(p);
1742                     }
1743                 }
1744             }
1745             break;
1746 
1747         case BD_16:
1748             for(iOffset = (32768 << rShiftY) / cMul, iRow = iFirstRow; iRow < cHeight; iRow += tScale){
1749                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
1750                     U16 * pDst = (U16 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn >> nBits];
1751 
1752                     for(iChannel = 0; iChannel < cChannel; iChannel ++){
1753                         PixelI p = (((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iOffset) * cMul) >> rShiftY) << nLen;
1754 
1755                         pDst[iChannel] = _CLIPU16(p);
1756                     }
1757                 }
1758             }
1759             break;
1760 
1761         case BD_16S:
1762             for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){
1763                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
1764                     I16 * pDst = (I16 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn >> nBits];
1765 
1766                     for(iChannel = 0; iChannel < cChannel; iChannel ++){
1767                         PixelI p = ((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] * cMul) >> rShiftY) << nLen;
1768 
1769                         pDst[iChannel] = _CLIP16(p);
1770                     }
1771                 }
1772             }
1773             break;
1774 
1775         case BD_16F:
1776             for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){
1777                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
1778                     U16 * pDst = (U16 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn >> nBits];
1779 
1780                     for(iChannel = 0; iChannel < cChannel; iChannel ++){
1781                         PixelI p = (pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] * cMul) >> rShiftY;
1782 
1783                         pDst[iChannel] = backwardHalf(p);
1784                     }
1785                 }
1786             }
1787             break;
1788         case BD_32:
1789             for(iOffset = (((1 << 31) >> nLen) << rShiftY) / cMul, iRow = iFirstRow; iRow < cHeight; iRow += tScale){
1790                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
1791                     U32 * pDst = (U32 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn >> nBits];
1792 
1793                     for(iChannel = 0; iChannel < cChannel; iChannel ++){
1794                         PixelI p = (((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] + iOffset) * cMul) >> rShiftY) << nLen;
1795 
1796                         pDst[iChannel] = (U32)(p);
1797                     }
1798                 }
1799             }
1800             break;
1801         case BD_32S:
1802             for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){
1803                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
1804                     I32 * pDst = (I32 *)pSC->WMIBI.pv + iY + pOffsetX[iColumn >> nBits];
1805 
1806                     for(iChannel = 0; iChannel < cChannel; iChannel ++){
1807                         PixelI p = ((pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] * cMul) >> rShiftY) << nLen;
1808 
1809                         pDst[iChannel] = (I32)(p);
1810                     }
1811                 }
1812             }
1813             break;
1814         case BD_32F:
1815             for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){
1816                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
1817                     float * pDst = (float *)pSC->WMIBI.pv + iY + pOffsetX[iColumn >> nBits];
1818 
1819                     for(iChannel = 0; iChannel < cChannel; iChannel ++){
1820                         PixelI p = (pChannel[iChannel & 15][((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] * cMul) >> rShiftY;
1821 
1822                         pDst[iChannel] = pixel2float (p, nExpBias, nLen);
1823                     }
1824                 }
1825             }
1826             break;
1827 
1828         default:
1829             assert(0);
1830             break;
1831     }
1832 }
1833 
1834 // centralized alpha channel thumbnail, small perf penalty
decodeThumbnailAlpha(CWMImageStrCodec * pSC,const size_t nBits,const PixelI cMul,const size_t rShiftY)1835 Int decodeThumbnailAlpha(CWMImageStrCodec * pSC, const size_t nBits, const PixelI cMul, const size_t rShiftY)
1836 {
1837     if(pSC->m_bSecondary == FALSE && pSC->m_pNextSC != NULL){ // with alpha channel
1838         const size_t tScale = (size_t)(1U << nBits);
1839         const size_t cHeight = min((pSC->m_Dparam->cROIBottomY + 1) - (pSC->cRow - 1) * 16, 16);
1840         const size_t cWidth = (pSC->m_Dparam->cROIRightX + 1);
1841         const size_t iFirstRow = ((((pSC->cRow - 1) * 16 > pSC->m_Dparam->cROITopY ? 0 : (pSC->m_Dparam->cROITopY & 0xf)) + tScale - 1) / tScale * tScale);
1842         const size_t iFirstColumn = (pSC->m_Dparam->cROILeftX + tScale - 1) / tScale * tScale;
1843         const size_t iAlphaPos = pSC->WMII.cLeadingPadding + (pSC->WMII.cfColorFormat == CMYK ? 4 : 3);//only RGB and CMYK may have interleaved alpha
1844         const BITDEPTH_BITS bd = pSC->WMII.bdBitDepth;
1845         const PixelI * pSrc = pSC->m_pNextSC->a0MBbuffer[0];
1846         const U8 nLen = pSC->m_pNextSC->WMISCP.nLenMantissaOrShift;
1847         const I8 nExpBias = pSC->m_pNextSC->WMISCP.nExpBias;
1848         size_t iRow, iColumn;
1849         size_t * pOffsetX = pSC->m_Dparam->pOffsetX, * pOffsetY = pSC->m_Dparam->pOffsetY + (pSC->cRow - 1) * 16 / tScale, iY;
1850 
1851         if (CF_RGB != pSC->WMII.cfColorFormat && CMYK != pSC->WMII.cfColorFormat)
1852             return ICERR_ERROR;
1853 
1854         if(bd == BD_8){
1855             const PixelI offset = (128 << rShiftY) / cMul;
1856 
1857             for(iRow = iFirstRow; iRow < cHeight; iRow += tScale)
1858                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
1859                     PixelI a = ((pSrc[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] + offset) * cMul) >> rShiftY;
1860 
1861                     ((U8 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY)[iAlphaPos] = _CLIP8(a);
1862                 }
1863         }
1864         else if(bd == BD_16){
1865             const PixelI offset = (32768 << rShiftY) / cMul;
1866 
1867             for(iRow = iFirstRow; iRow < cHeight; iRow += tScale)
1868                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
1869                     PixelI a = (((pSrc[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] + offset) * cMul) >> rShiftY) << nLen;
1870 
1871                     ((U16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY)[iAlphaPos] = _CLIPU16(a);
1872                 }
1873         }
1874         else if(bd == BD_16S){
1875             for(iRow = iFirstRow; iRow < cHeight; iRow += tScale)
1876                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
1877                     PixelI a = ((pSrc[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] * cMul) >> rShiftY) << nLen;
1878 
1879                     ((I16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY)[iAlphaPos] = _CLIP16(a);
1880                 }
1881         }
1882         else if(bd == BD_16F){
1883             for(iRow = iFirstRow; iRow < cHeight; iRow += tScale)
1884                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
1885                     PixelI a = (pSrc[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] * cMul) >> rShiftY;
1886 
1887                     ((U16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY)[iAlphaPos] = backwardHalf(a);
1888                 }
1889         }
1890         else if(bd == BD_32S){
1891             for(iRow = iFirstRow; iRow < cHeight; iRow += tScale)
1892                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
1893                     PixelI a = ((pSrc[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] * cMul) >> rShiftY) << nLen;
1894 
1895                     ((I32 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY)[iAlphaPos] = a;
1896                 }
1897         }
1898         else if(bd == BD_32F){
1899             for(iRow = iFirstRow; iRow < cHeight; iRow += tScale)
1900                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
1901                     PixelI a = (pSrc[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] * cMul) >> rShiftY;
1902 
1903                     ((float *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY)[iAlphaPos] = pixel2float (a, nExpBias, nLen);
1904                 }
1905         }
1906         else // not supported
1907             return ICERR_ERROR;
1908     }
1909 
1910     return ICERR_OK;
1911 }
1912 
decodeThumbnail(CWMImageStrCodec * pSC)1913 Int decodeThumbnail(CWMImageStrCodec * pSC)
1914 {
1915     const size_t tScale = pSC->m_Dparam->cThumbnailScale;
1916     const size_t cHeight = min((pSC->m_Dparam->bDecodeFullFrame ? pSC->WMII.cHeight : pSC->m_Dparam->cROIBottomY + 1) - (pSC->cRow - 1) * 16, 16);
1917     const size_t cWidth = (pSC->m_Dparam->bDecodeFullFrame ? pSC->WMII.cWidth : pSC->m_Dparam->cROIRightX + 1);
1918     const size_t iFirstRow = ((((pSC->cRow - 1) * 16 > pSC->m_Dparam->cROITopY ? 0 : (pSC->m_Dparam->cROITopY & 0xf)) + tScale - 1) / tScale * tScale);
1919     const size_t iFirstColumn = (pSC->m_Dparam->cROILeftX + tScale - 1) / tScale * tScale;
1920     const COLORFORMAT cfInt = pSC->m_param.cfColorFormat;
1921     const COLORFORMAT cfExt = (pSC->m_param.cfColorFormat == Y_ONLY ? Y_ONLY : pSC->WMII.cfColorFormat);
1922     const BITDEPTH_BITS bd = pSC->WMII.bdBitDepth;
1923     const OVERLAP ol = pSC->WMISCP.olOverlap;
1924 	const size_t iB = (pSC->WMII.bRGB ? 2 : 0);
1925     const size_t iR = 2 - iB;
1926 
1927     const U8 nLen = pSC->WMISCP.nLenMantissaOrShift;
1928     const I8 nExpBias = pSC->WMISCP.nExpBias;
1929     PixelI offset;
1930     size_t iRow, iColumn, iIdx1, iIdx2, iIdx3 = 0, nBits = 0;
1931     PixelI * pSrcY = pSC->a0MBbuffer[0];
1932     PixelI * pSrcU = pSC->a0MBbuffer[1], * pSrcV = pSC->a0MBbuffer[2];
1933     size_t * pOffsetX = pSC->m_Dparam->pOffsetX, * pOffsetY = pSC->m_Dparam->pOffsetY + (pSC->cRow - 1) * 16 / tScale, iY;
1934     const PixelI cMul = (tScale >= 16 ? (ol == OL_NONE ? 16 : (ol == OL_ONE ? 23 : 34)) : (tScale >= 4 ? (ol == OL_NONE ? 64 : 93) : 258));
1935     const size_t rShiftY = 8 + (pSC->m_param.bScaledArith ? (SHIFTZERO + QPFRACBITS) : 0);
1936     const size_t rShiftUV = rShiftY - ((pSC->m_param.bScaledArith && tScale >= 16) ? ((cfInt == YUV_420 || cfInt == YUV_422) ? 2 : 1) : 0);
1937 
1938     while((size_t)(1U << nBits) < tScale)
1939         nBits ++;
1940 
1941     assert(tScale == (size_t)(1U << nBits));
1942 
1943     // guard output buffer
1944     if(checkImageBuffer(pSC, pSC->WMII.oOrientation < O_RCW ? pSC->WMII.cROIWidth : pSC->WMII.cROIHeight, (cHeight - iFirstRow) / pSC->m_Dparam->cThumbnailScale) != ICERR_OK)
1945         return ICERR_ERROR;
1946 
1947     if((((pSC->cRow - 1) * 16) % tScale) != 0)
1948         return ICERR_OK;
1949 
1950     if(pSC->cRow * 16 <= pSC->m_Dparam->cROITopY || pSC->cRow * 16 > pSC->m_Dparam->cROIBottomY + 16)
1951         return ICERR_OK;
1952 
1953     if((cfInt == YUV_422 || cfInt == YUV_420) && cfExt != Y_ONLY){
1954         PixelI * pDstU = pSC->pResU, * pDstV = pSC->pResV;
1955 
1956         for(iRow = 0; iRow < 16; iRow += tScale){
1957             for(iColumn = 0; iColumn < cWidth; iColumn += tScale){
1958                 iIdx1 = (cfInt == YUV_422 ? ((iColumn >> 4) << 7) + idxCC[iRow][(iColumn >> 1) & 7] : ((iColumn >> 4) << 6) + idxCC_420[iRow >> 1][(iColumn >> 1) & 7]);
1959                 iIdx2 = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
1960 
1961                 // copy over
1962                 pDstU[iIdx2] = pSrcU[iIdx1];
1963                 pDstV[iIdx2] = pSrcV[iIdx1];
1964             }
1965         }
1966 
1967         if(tScale == 4){
1968             if(cfInt == YUV_420){
1969                 for(iColumn = 0; iColumn < cWidth; iColumn += 8){
1970                     iIdx1 = ((iColumn >> 4) << 8) + idxCC[0][iColumn & 15];
1971                     iIdx2 = ((iColumn >> 4) << 8) + idxCC[4][iColumn & 15];
1972                     iIdx3 = ((iColumn >> 4) << 8) + idxCC[8][iColumn & 15];
1973 
1974                     pDstU[iIdx2] = ((pDstU[iIdx1] + pDstU[iIdx3] + 1) >> 1);
1975                     pDstV[iIdx2] = ((pDstV[iIdx1] + pDstV[iIdx3] + 1) >> 1);
1976 
1977                     iIdx1 = ((iColumn >> 4) << 8) + idxCC[12][iColumn & 15];
1978                     pDstU[iIdx1] = pDstU[iIdx3];
1979                     pDstV[iIdx1] = pDstV[iIdx3];
1980                 }
1981             }
1982 
1983             for(iRow = 0; iRow < 16; iRow += 4){
1984                 for(iColumn = 0; iColumn < cWidth - 8; iColumn += 8){
1985                     iIdx1 = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15];
1986                     iIdx2 = ((iColumn >> 4) << 8) + idxCC[iRow][(iColumn + 4) & 15];
1987                     iIdx3 = ((iColumn >> 4) << 8) + idxCC[iRow][(iColumn + 8) & 15];
1988 
1989                     pDstU[iIdx2] = ((pDstU[iIdx1] + pDstU[iIdx3] + 1) >> 1);
1990                     pDstV[iIdx2] = ((pDstV[iIdx1] + pDstV[iIdx3] + 1) >> 1);
1991                 }
1992 
1993                 iIdx2 = ((iColumn >> 4) << 8) + idxCC[iRow][(iColumn + 4) & 15];
1994                 pDstU[iIdx2] = pDstU[iIdx3];
1995                 pDstV[iIdx2] = pDstV[iIdx3];
1996             }
1997         }
1998 
1999         pSrcU = pDstU, pSrcV = pDstV;
2000     }
2001 
2002     if(bd == BD_8){
2003         U8 * pDst;
2004 
2005         offset = (128 << rShiftY) / cMul;
2006 
2007         switch(cfExt){
2008             case CF_RGB:
2009                 for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){
2010                     for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
2011                         size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2012                         PixelI g = ((pSrcY[iPos] + offset) * cMul) >> rShiftY, r = -(pSrcU[iPos] * cMul) >> rShiftUV, b = (pSrcV[iPos] * cMul) >> rShiftUV;
2013 
2014                         _ICC(r, g, b);
2015 
2016                         pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY;
2017                         pDst[iB] = _CLIP8(b), pDst[1] = _CLIP8(g), pDst[iR] = _CLIP8(r);
2018                 }
2019             }
2020             break;
2021 
2022         case Y_ONLY:
2023         case YUV_444:
2024         case NCOMPONENT:
2025             outputNChannelThumbnail(pSC, cMul, rShiftY, iFirstRow, iFirstColumn);
2026             break;
2027 
2028         case CF_RGBE:
2029             for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){
2030                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
2031                     size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2032                     PixelI g = ((pSrcY[iPos] * cMul) >> rShiftY), r = - ((pSrcU[iPos] * cMul) >> rShiftUV), b = ((pSrcV[iPos] * cMul) >> rShiftUV);
2033 
2034                     _ICC(r, g, b);
2035 
2036                     pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY;
2037                     inverseConvertRGBE (r, g, b, pDst, pDst + 1, pDst + 2, pDst + 3);
2038                 }
2039             }
2040             break;
2041 
2042         case CMYK:
2043         {
2044             PixelI * pSrcK = pSC->a0MBbuffer[3];
2045             PixelI iBias1 = (128 << rShiftY) / cMul, iBias2 = (((128 << rShiftUV) / cMul) >> 1);
2046 
2047             for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){
2048                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
2049                     size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2050                     PixelI m = ((-pSrcY[iPos] + iBias1) * cMul) >> rShiftY, c = (pSrcU[iPos] * cMul) >> rShiftUV, y = -(pSrcV[iPos] * cMul) >> rShiftUV, k = ((pSrcK[iPos] + iBias2) * cMul) >> rShiftUV;
2051 
2052                     _ICC_CMYK(c, m, y, k);
2053 
2054                     pDst = (U8 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY;
2055                     pDst[0] = _CLIP8(c), pDst[1] = _CLIP8(m), pDst[2] = _CLIP8(y), pDst[3] = _CLIP8(k);
2056                 }
2057             }
2058             break;
2059         }
2060         default:
2061             assert(0);
2062             break;
2063         }
2064     }
2065     if(bd == BD_16){
2066         U16 * pDst;
2067 
2068         offset = (((1 << 15) >> nLen) << rShiftY) / cMul;
2069 
2070         switch(cfExt){
2071             case CF_RGB:
2072                 for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){
2073                     for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
2074                         size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2075                         PixelI g = ((pSrcY[iPos] + offset) * cMul) >> rShiftY, r = -(pSrcU[iPos] * cMul) >> rShiftUV, b = (pSrcV[iPos] * cMul) >> rShiftUV;
2076 
2077                         _ICC(r, g, b);
2078 
2079                         pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY;
2080                         r <<= nLen, g <<= nLen, b <<= nLen;
2081                         pDst[0] = _CLIPU16(r);
2082                         pDst[1] = _CLIPU16(g);
2083                         pDst[2] = _CLIPU16(b);
2084                 }
2085             }
2086             break;
2087 
2088         case Y_ONLY:
2089         case YUV_444:
2090         case NCOMPONENT:
2091             outputNChannelThumbnail(pSC, cMul, rShiftY, iFirstRow, iFirstColumn);
2092             break;
2093 
2094         case CMYK:
2095         {
2096             PixelI * pSrcK = pSC->a0MBbuffer[3];
2097             PixelI iBias1 = (32768 << rShiftY) / cMul, iBias2 = (((32768 << rShiftUV) / cMul) >> 1);
2098 
2099             for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){
2100                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
2101                     size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2102                     PixelI m = ((-pSrcY[iPos] + iBias1) * cMul) >> rShiftY, c = (pSrcU[iPos] * cMul) >> rShiftUV, y = -(pSrcV[iPos] * cMul) >> rShiftUV, k = ((pSrcK[iPos] + iBias2) * cMul) >> rShiftUV;
2103 
2104                     _ICC_CMYK(c, m, y, k);
2105 
2106                     pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY;
2107                     c <<= nLen, m <<= nLen, y <<= nLen, k <<= nLen;
2108                     pDst[0] = _CLIPU16(c);
2109                     pDst[1] = _CLIPU16(m);
2110                     pDst[2] = _CLIPU16(y);
2111                     pDst[3] = _CLIPU16(k);
2112                 }
2113             }
2114             break;
2115         }
2116         default:
2117             assert(0);
2118             break;
2119         }
2120     }
2121     if(bd == BD_16S){
2122         I16 * pDst;
2123 
2124         switch(cfExt){
2125             case CF_RGB:
2126                 for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){
2127                     for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
2128                         size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2129                         PixelI g = (pSrcY[iPos] * cMul) >> rShiftY, r = -(pSrcU[iPos] * cMul) >> rShiftUV, b = (pSrcV[iPos] * cMul) >> rShiftUV;
2130 
2131                         _ICC(r, g, b);
2132 
2133                         pDst = (I16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY;
2134                         r <<= nLen, g <<= nLen, b <<= nLen;
2135                         pDst[0] = _CLIP16(r);
2136                         pDst[1] = _CLIP16(g);
2137                         pDst[2] = _CLIP16(b);
2138                 }
2139             }
2140             break;
2141 
2142         case Y_ONLY:
2143         case YUV_444:
2144         case NCOMPONENT:
2145             outputNChannelThumbnail(pSC, cMul, rShiftY, iFirstRow, iFirstColumn);
2146             break;
2147 
2148         case CMYK:
2149 			{
2150 				PixelI * pSrcK = pSC->a0MBbuffer[3];
2151 
2152 				for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){
2153 					for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
2154 						size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2155 						PixelI m = -(pSrcY[iPos] * cMul) >> rShiftY, c = (pSrcU[iPos] * cMul) >> rShiftUV, y = -(pSrcV[iPos] * cMul) >> rShiftUV, k = (pSrcK[iPos] * cMul) >> rShiftUV;
2156 
2157 						_ICC_CMYK(c, m, y, k);
2158 
2159 						pDst = (I16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY;
2160 						c <<= nLen, m <<= nLen, y <<= nLen, k <<= nLen;
2161 						pDst[0] = _CLIP16(c);
2162 						pDst[1] = _CLIP16(m);
2163 						pDst[2] = _CLIP16(y);
2164 						pDst[3] = _CLIP16(k);
2165 					}
2166 				}
2167 			}
2168 			break;
2169 
2170         default:
2171             assert(0);
2172             break;
2173         }
2174     }
2175     else if(bd == BD_16F){
2176         U16 * pDst;
2177 
2178         switch(cfExt){
2179             case CF_RGB:
2180                 for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){
2181                     for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
2182                         size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2183                         PixelI g = (pSrcY[iPos] * cMul) >> rShiftY, r = -(pSrcU[iPos] * cMul) >> rShiftUV, b = (pSrcV[iPos] * cMul) >> rShiftUV;
2184 
2185                         _ICC(r, g, b);
2186 
2187                         pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY;
2188                         pDst[0] = backwardHalf (r);
2189                         pDst[1] = backwardHalf (g);
2190                         pDst[2] = backwardHalf (b);
2191                     }
2192                 }
2193                 break;
2194 
2195             case Y_ONLY:
2196             case YUV_444:
2197             case NCOMPONENT:
2198                 outputNChannelThumbnail(pSC, cMul, rShiftY, iFirstRow, iFirstColumn);
2199             break;
2200 
2201             default:
2202                 assert(0);
2203                 break;
2204         }
2205     }
2206     else if(bd == BD_32){
2207         U32 * pDst;
2208 
2209         offset = (((1 << 31) >> nLen) << rShiftY) / cMul;
2210 
2211         switch(cfExt){
2212             case CF_RGB:
2213                 for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){
2214                     for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
2215                         size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2216                         PixelI g = ((pSrcY[iPos] + offset) * cMul) >> rShiftY, r = -(pSrcU[iPos] * cMul) >> rShiftUV, b = (pSrcV[iPos] * cMul) >> rShiftUV;
2217 
2218                         _ICC(r, g, b);
2219 
2220                         pDst = (U32 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY;
2221 
2222                         pDst[0] = (U32)(r << nLen);
2223                         pDst[1] = (U32)(g << nLen);
2224                         pDst[2] = (U32)(b << nLen);
2225                     }
2226                 }
2227                 break;
2228 
2229             case Y_ONLY:
2230             case YUV_444:
2231             case NCOMPONENT:
2232                 outputNChannelThumbnail(pSC, cMul, rShiftY, iFirstRow, iFirstColumn);
2233             break;
2234 
2235             default:
2236                 assert(0);
2237                 break;
2238         }
2239     }
2240     else if(bd == BD_32S){
2241         I32 * pDst;
2242 
2243         switch(cfExt){
2244             case CF_RGB:
2245                 for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){
2246                     for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
2247                         size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2248                         PixelI g = (pSrcY[iPos] * cMul) >> rShiftY, r = -(pSrcU[iPos] * cMul) >> rShiftUV, b = (pSrcV[iPos] * cMul) >> rShiftUV;
2249 
2250                         _ICC(r, g, b);
2251 
2252                         pDst = (I32 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY;
2253                         pDst[0] = (I32)(r << nLen);
2254                         pDst[1] = (I32)(g << nLen);
2255                         pDst[2] = (I32)(b << nLen);
2256                     }
2257                 }
2258                 break;
2259 
2260             case Y_ONLY:
2261             case YUV_444:
2262             case NCOMPONENT:
2263                 outputNChannelThumbnail(pSC, cMul, rShiftY, iFirstRow, iFirstColumn);
2264             break;
2265 
2266             default:
2267                 assert(0);
2268                 break;
2269         }
2270     }
2271 
2272     else if(bd == BD_32F){
2273         float * pDst;
2274 
2275         switch(cfExt){
2276             case CF_RGB:
2277                 for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){
2278                     for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
2279                         size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2280                         PixelI g = (pSrcY[iPos] * cMul) >> rShiftY, r = -(pSrcU[iPos] * cMul) >> rShiftUV, b = (pSrcV[iPos] * cMul) >> rShiftUV;
2281 
2282                         _ICC(r, g, b);
2283 
2284                         pDst = (float *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY;
2285                         pDst[0] = pixel2float (r, nExpBias, nLen);
2286                         pDst[1] = pixel2float (g, nExpBias, nLen);
2287                         pDst[2] = pixel2float (b, nExpBias, nLen);
2288                     }
2289                 }
2290                 break;
2291 
2292             case Y_ONLY:
2293             case YUV_444:
2294             case NCOMPONENT:
2295                 outputNChannelThumbnail(pSC, cMul, rShiftY, iFirstRow, iFirstColumn);
2296                 break;
2297 
2298             default:
2299                 assert(0);
2300                 break;
2301         }
2302     }
2303     else if(bd == BD_1){
2304         const size_t iPos = pSC->WMII.cLeadingPadding;
2305         Bool bBW;
2306         U8 cByte, cShift;
2307         assert(cfExt == Y_ONLY && pSC->m_param.cfColorFormat == Y_ONLY);
2308 
2309         if(pSC->WMII.oOrientation < O_RCW){
2310             for(iRow = iFirstRow; iRow < cHeight; iRow += tScale)
2311                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits] + iPos; iColumn < cWidth; iColumn += tScale){
2312                     bBW = (pSC->WMISCP.bBlackWhite ^ (pSrcY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] > 0));
2313                     cByte = ((U8 *)pSC->WMIBI.pv + (pOffsetX[iColumn >> nBits] >> 3) + iY)[0];
2314                     cShift = (U8)(7 - (pOffsetX[iColumn >> nBits] & 7));
2315                     ((U8 *)pSC->WMIBI.pv + (pOffsetX[iColumn >> nBits] >> 3) + iY)[0] ^= ((((bBW + (cByte >> cShift)) & 0x1)) << cShift);
2316                 }
2317         }
2318         else{
2319             for(iRow = iFirstRow; iRow < cHeight; iRow += tScale)
2320                 for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits] + iPos; iColumn < cWidth; iColumn += tScale){
2321                     bBW = (pSC->WMISCP.bBlackWhite ^ (pSrcY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] > 0));
2322                     cByte = ((U8 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + (iY >> 3))[0];
2323                     cShift = (U8)(7 - (iY & 7));
2324                     ((U8 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + (iY >> 3))[0] ^= ((((bBW + (cByte >> cShift)) & 0x1)) << cShift);
2325                 }
2326         }
2327     }
2328     else if(bd == BD_5){
2329         U16 * pDst;
2330 
2331         offset = (16 << rShiftY) / cMul;
2332 
2333         for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){
2334             for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
2335                 size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2336                 PixelI g = ((pSrcY[iPos] + offset) * cMul) >> rShiftY, r = -(pSrcU[iPos] * cMul) >> rShiftUV, b = (pSrcV[iPos] * cMul) >> rShiftUV;
2337 
2338                 _ICC(r, g, b);
2339                 pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY;
2340                 pDst[0] = (U16)_CLIP2(0, r, 31) + (((U16)_CLIP2(0, g, 31)) << 5) + (((U16)_CLIP2(0, b, 31)) << 10);
2341             }
2342         }
2343     }
2344     else if(bd == BD_565){
2345         U16 * pDst;
2346 
2347         offset = (32 << rShiftY) / cMul;
2348 
2349         for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){
2350             for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
2351                 size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2352                 PixelI g = ((pSrcY[iPos] + offset) * cMul) >> rShiftY, r = -(pSrcU[iPos] * cMul) >> rShiftUV, b = (pSrcV[iPos] * cMul) >> rShiftUV;
2353 
2354                 _ICC(r, g, b);
2355                 r /= 2, b /= 2;
2356                 pDst = (U16 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY;
2357                 pDst[0] = (U16)_CLIP2(0, r, 31) + (((U16)_CLIP2(0, g, 63)) << 5) + (((U16)_CLIP2(0, b, 31)) << 11);
2358             }
2359         }
2360     }
2361     else if(bd == BD_10){
2362         U32 * pDst;
2363 
2364         offset = (512 << rShiftY) / cMul;
2365 
2366         for(iRow = iFirstRow; iRow < cHeight; iRow += tScale){
2367             for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){
2368                 size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2369                 PixelI g = ((pSrcY[iPos] + offset) * cMul) >> rShiftY, r = -(pSrcU[iPos] * cMul) >> rShiftUV, b = (pSrcV[iPos] * cMul) >> rShiftUV;
2370 
2371                 _ICC(r, g, b);
2372                 pDst = (U32 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY;
2373                 pDst[0] = (U32)_CLIP2(0, r, 1023) +
2374                     (((U32)_CLIP2(0, g, 1023)) << 10) +
2375                     (((U32)_CLIP2(0, b, 1023)) << 20);
2376             }
2377         }
2378     }
2379 
2380     if(pSC->WMISCP.uAlphaMode > 0)
2381         if(decodeThumbnailAlpha(pSC, nBits, cMul, rShiftY) != ICERR_OK)
2382             return ICERR_ERROR;
2383 
2384 #ifdef REENTRANT_MODE
2385     pSC->WMIBI.cLinesDecoded = ( cHeight - iFirstRow + tScale - 1 ) / tScale;
2386     if (CF_RGB == pSC->WMII.cfColorFormat && Y_ONLY == pSC->WMISCP.cfColorFormat)
2387     {
2388         const CWMImageInfo* pII = &pSC->WMII;
2389 
2390 #define fixupThumb(type, nCh) \
2391 for(iRow = iFirstRow; iRow < cHeight; iRow += tScale) {\
2392     size_t iY;\
2393     for(iColumn = iFirstColumn, iY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){\
2394         type *pT = (type*)((U8 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iY);\
2395         pT[iB] = pT[1] = pT[iR]; \
2396     } \
2397 } \
2398 break
2399 
2400         switch (pII->bdBitDepth)
2401         {
2402             case BD_8:
2403                 fixupThumb(U8, (pII->cBitsPerUnit >> 3));
2404                 break;
2405 
2406             case BD_16:
2407             case BD_16S:
2408             case BD_16F:
2409                 fixupThumb(U16, (pII->cBitsPerUnit >> 3) / sizeof(U16));
2410                 break;
2411 
2412             case BD_32:
2413             case BD_32S:
2414             case BD_32F:
2415                 fixupThumb(U32, (pII->cBitsPerUnit >> 3) / sizeof(float));
2416                 break;
2417 
2418             case BD_5:
2419             case BD_10:
2420             case BD_565:
2421             default:
2422                 break;
2423         }
2424     }
2425 #endif
2426 
2427     return ICERR_OK;
2428 }
2429 
2430 /*************************************************************************
2431     Read variable length byte aligned integer
2432 *************************************************************************/
GetVLWordEsc(BitIOInfo * pIO,Int * iEscape)2433 static size_t GetVLWordEsc(BitIOInfo* pIO, Int *iEscape)
2434 {
2435     size_t s;
2436 
2437     if (iEscape)
2438         *iEscape = 0;
2439 
2440     s = getBit32(pIO, 8);
2441     if (s == 0xfd || s == 0xfe || s == 0xff) {
2442         if (iEscape)
2443             *iEscape = (Int) s;
2444         s = 0;
2445     }
2446     else if (s < 0xfb) {
2447         s = (s << 8) | getBit32(pIO, 8);
2448     }
2449     else {
2450         s -= 0xfb;
2451         if (s) {
2452             s = getBit32(pIO, 16) << 16;
2453             s = (s | getBit32(pIO, 16)) << 16;
2454             s <<= 16;
2455         }
2456         s |= (getBit32(pIO, 16) << 16);
2457         s |= getBit32(pIO, 16);
2458     }
2459     return s;
2460 }
2461 
2462 //================================================================
readIndexTable(CWMImageStrCodec * pSC)2463 Int readIndexTable(CWMImageStrCodec * pSC)
2464 {
2465     BitIOInfo* pIO = pSC->pIOHeader;
2466     readIS_L1(pSC, pIO);
2467 
2468     if(pSC->cNumBitIO > 0){
2469         size_t *pTable = pSC->pIndexTable;
2470         U32 iEntry = (U32)pSC->cNumBitIO * (pSC->WMISCP.cNumOfSliceMinus1H + 1), i;
2471 
2472         // read index table header [0x0001] - 2 bytes
2473         if (getBit32(pIO, 16) != 1)
2474             return ICERR_ERROR;
2475 
2476         //iBits = getBit16(pIO, 5) + 1; // how many bits per entry
2477         for(i = 0; i < iEntry; i ++){
2478             readIS_L1(pSC, pIO);
2479             pTable[i] = GetVLWordEsc(pIO, NULL);  // escape handling is not important since the respective band is not accessed
2480         }
2481     }
2482 
2483     pSC->cHeaderSize = GetVLWordEsc(pIO, NULL);  // escape handling is not important
2484     flushToByte(pIO);
2485 
2486     pSC->cHeaderSize += getPosRead(pSC->pIOHeader); // get header length
2487 
2488     return ICERR_OK;
2489 }
2490 
StrIODecInit(CWMImageStrCodec * pSC)2491 Int StrIODecInit(CWMImageStrCodec* pSC)
2492 {
2493     if(allocateBitIOInfo(pSC) != ICERR_OK){
2494         return ICERR_ERROR;
2495     }
2496 
2497     attachISRead(pSC->pIOHeader, pSC->WMISCP.pWStream, pSC);
2498 
2499     readIndexTable(pSC);
2500 
2501     if(pSC->WMISCP.bVerbose){
2502         U32 i, j;
2503 
2504         printf("\n%d horizontal tiles:\n", pSC->WMISCP.cNumOfSliceMinus1H + 1);
2505         for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1H; i ++){
2506             printf("    offset of tile %d in MBs: %d\n", i, pSC->WMISCP.uiTileY[i]);
2507         }
2508 
2509         printf("\n%d vertical tiles:\n", pSC->WMISCP.cNumOfSliceMinus1V + 1);
2510         for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1V; i ++){
2511             printf("    offset of tile %d in MBs: %d\n", i, pSC->WMISCP.uiTileX[i]);
2512         }
2513 
2514         if(pSC->WMISCP.bfBitstreamFormat == SPATIAL){
2515             printf("\nSpatial order bitstream\n");
2516         }
2517         else{
2518             printf("\nFrequency order bitstream\n");
2519         }
2520 
2521         if(!pSC->m_param.bIndexTable){
2522             printf("\nstreaming mode, no index table.\n");
2523         }
2524         else if(pSC->WMISCP.bfBitstreamFormat == SPATIAL){
2525             for(j = 0; j <= pSC->WMISCP.cNumOfSliceMinus1H; j ++){
2526                 for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1V; i ++){
2527                     size_t * p = &pSC->pIndexTable[j * (pSC->WMISCP.cNumOfSliceMinus1V + 1) + i];
2528                     if(i + j != pSC->WMISCP.cNumOfSliceMinus1H + pSC->WMISCP.cNumOfSliceMinus1V){
2529                         printf("bitstream size for tile (%d, %d): %d.\n", j, i, (int) (p[1] - p[0]));
2530                     }
2531                     else{
2532                         printf("bitstream size for tile (%d, %d): unknown.\n", j, i);
2533                     }
2534                 }
2535             }
2536         }
2537         else{
2538             for(j = 0; j <= pSC->WMISCP.cNumOfSliceMinus1H; j ++){
2539                 for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1V; i ++){
2540                     size_t * p = &pSC->pIndexTable[(j * (pSC->WMISCP.cNumOfSliceMinus1V + 1) + i) * 4];
2541                     if(i + j != pSC->WMISCP.cNumOfSliceMinus1H + pSC->WMISCP.cNumOfSliceMinus1V){
2542                         printf("bitstream size of (DC, LP, AC, FL) for tile (%d, %d): %d %d %d %d.\n", j, i,
2543                             (int) (p[1] - p[0]), (int) (p[2] - p[1]), (int) (p[3] - p[2]), (int) (p[4] - p[3]));
2544                     }
2545                     else{
2546                         printf("bitstream size of (DC, LP, AC, FL) for tile (%d, %d): %d %d %d unknown.\n", j, i,
2547                             (int) (p[1] - p[0]), (int) (p[2] - p[1]), (int) (p[3] - p[2]));
2548                     }
2549                 }
2550             }
2551         }
2552     }
2553 
2554     return 0;
2555 }
2556 
StrIODecTerm(CWMImageStrCodec * pSC)2557 Int StrIODecTerm(CWMImageStrCodec* pSC)
2558 {
2559     detachISRead(pSC, pSC->pIOHeader);
2560 
2561     free(pSC->m_ppBitIO);
2562     free(pSC->pIndexTable);
2563 
2564     return 0;
2565 }
2566 
initLookupTables(CWMImageStrCodec * pSC)2567 Int initLookupTables(CWMImageStrCodec* pSC)
2568 {
2569     static const U8 cbChannels[BDB_MAX] = {1, 1, 2, 2, 2, 4, 4, 4, (U8) -1, (U8) -1, (U8) -1 };
2570 
2571     CWMImageInfo * pII = &pSC->WMII;
2572     size_t cStrideX, cStrideY;
2573     size_t w, h, i, iFirst = 0;
2574     Bool bReverse;
2575 
2576     // lookup tables for rotation and flipping
2577     if(pSC->m_Dparam->cThumbnailScale > 1) // thumbnail
2578         w = pII->cThumbnailWidth, h = pII->cThumbnailHeight;
2579     else
2580         w = pII->cWidth, h = pII->cHeight;
2581     w += (pSC->m_Dparam->cROILeftX + pSC->m_Dparam->cThumbnailScale - 1) / pSC->m_Dparam->cThumbnailScale;
2582     h += (pSC->m_Dparam->cROITopY + pSC->m_Dparam->cThumbnailScale - 1) / pSC->m_Dparam->cThumbnailScale;
2583 
2584     switch(pII->bdBitDepth){
2585         case BD_16:
2586         case BD_16S:
2587         case BD_5:
2588         case BD_565:
2589         case BD_16F:
2590             cStrideY = pSC->WMIBI.cbStride / 2;
2591             break;
2592 
2593         case BD_32:
2594         case BD_32S:
2595         case BD_32F:
2596         case BD_10:
2597             cStrideY = pSC->WMIBI.cbStride / 4;
2598             break;
2599 
2600         default: //BD_8, BD_1
2601             cStrideY = pSC->WMIBI.cbStride;
2602             break;
2603     }
2604 
2605     switch(pII->cfColorFormat){
2606         case YUV_420:
2607             cStrideX = 6;
2608             w >>= 1, h >>= 1;
2609             break;
2610 
2611         case YUV_422:
2612             cStrideX = 4;
2613             w >>= 1;
2614             break;
2615 
2616         default:
2617             cStrideX = (pII->cBitsPerUnit >> 3) / cbChannels[pII->bdBitDepth];
2618             break;
2619     }
2620 
2621     if(pII->bdBitDepth == BD_1 || pII->bdBitDepth == BD_5 || pII->bdBitDepth == BD_10 ||  pII->bdBitDepth == BD_565)
2622         cStrideX = 1;
2623 
2624     if(pII->oOrientation > O_FLIPVH) // rotated !!
2625         i =cStrideX, cStrideX = cStrideY, cStrideY = i;
2626 
2627     pSC->m_Dparam->pOffsetX = (size_t *)malloc(w * sizeof(size_t));
2628     if(pSC->m_Dparam->pOffsetX == NULL || w * sizeof(size_t) < w)
2629         return ICERR_ERROR;
2630     /*
2631     consider a row in the source image. if it becomes a reversed row in the target, or a reversed (upside-down)column
2632     in the target, we have to reverse the offsets. bReverse here tells us when this happened.
2633     */
2634     bReverse = (pII->oOrientation == O_FLIPH || pII->oOrientation == O_FLIPVH ||
2635         pII->oOrientation == O_RCW_FLIPV || pII->oOrientation == O_RCW_FLIPVH);
2636     if(!pSC->m_Dparam->bDecodeFullFrame) // take care of region decode here!
2637         iFirst = (pSC->m_Dparam->cROILeftX + pSC->m_Dparam->cThumbnailScale - 1) / pSC->m_Dparam->cThumbnailScale;
2638     for(i = 0; i + iFirst < w; i ++){
2639         pSC->m_Dparam->pOffsetX[i + iFirst] = pII->cLeadingPadding + (bReverse ? (pSC->m_Dparam->bDecodeFullFrame ? w :
2640     (pSC->m_Dparam->cROIRightX - pSC->m_Dparam->cROILeftX + pSC->m_Dparam->cThumbnailScale) / pSC->m_Dparam->cThumbnailScale / ((pII->cfColorFormat == YUV_420 || pII->cfColorFormat == YUV_422) ? 2 : 1)) - 1 - i : i) * cStrideX;
2641     }
2642 
2643     pSC->m_Dparam->pOffsetY = (size_t *)malloc(h * sizeof(size_t));
2644     if(pSC->m_Dparam->pOffsetY == NULL || h * sizeof(size_t) < h)
2645         return ICERR_ERROR;
2646     /*
2647     consider a column in the source image. if it becomes an upside-down column in the target, or a reversed row
2648     in the target, we have to reverse the offsets. bReverse here tells us when this happened.
2649     */
2650     bReverse = (pII->oOrientation == O_FLIPV || pII->oOrientation == O_FLIPVH ||
2651         pII->oOrientation == O_RCW || pII->oOrientation == O_RCW_FLIPV);
2652     if(!pSC->m_Dparam->bDecodeFullFrame) // take care of region decode here!
2653         iFirst = (pSC->m_Dparam->cROITopY + pSC->m_Dparam->cThumbnailScale - 1) / pSC->m_Dparam->cThumbnailScale;
2654     for(i = 0; i + iFirst < h; i ++){
2655         pSC->m_Dparam->pOffsetY[i + iFirst] = (bReverse ? (pSC->m_Dparam->bDecodeFullFrame ? h :
2656     (pSC->m_Dparam->cROIBottomY - pSC->m_Dparam->cROITopY + pSC->m_Dparam->cThumbnailScale) / pSC->m_Dparam->cThumbnailScale / (pII->cfColorFormat == YUV_420 ? 2 : 1)) - 1 - i : i) * cStrideY;
2657     }
2658 
2659     return ICERR_OK;
2660 }
2661 
setROI(CWMImageStrCodec * pSC)2662 Void setROI(CWMImageStrCodec* pSC)
2663 {
2664     CWMImageInfo * pWMII = &pSC->WMII;
2665     CWMIStrCodecParam * pSCP = &pSC->WMISCP;
2666 
2667     // inscribed image size
2668     pWMII->cWidth -= pSC->m_param.cExtraPixelsLeft + pSC->m_param.cExtraPixelsRight;
2669     pWMII->cHeight -= pSC->m_param.cExtraPixelsTop + pSC->m_param.cExtraPixelsBottom;
2670 
2671     pSC->m_Dparam->bSkipFlexbits = (pSCP->sbSubband == SB_NO_FLEXBITS);
2672     pSC->m_Dparam->bDecodeHP = (pSCP->sbSubband == SB_ALL || pSCP->sbSubband == SB_NO_FLEXBITS);
2673     pSC->m_Dparam->bDecodeLP = (pSCP->sbSubband != SB_DC_ONLY);
2674     pSC->m_Dparam->cThumbnailScale = 1;
2675     while(pSC->m_Dparam->cThumbnailScale * pWMII->cThumbnailWidth < pWMII->cWidth)
2676         pSC->m_Dparam->cThumbnailScale <<= 1;
2677     if(pSC->WMISCP.bfBitstreamFormat == FREQUENCY){
2678         if(pSC->m_Dparam->cThumbnailScale >= 4)
2679             pSC->m_Dparam->bDecodeHP = FALSE;  // no need to decode HP
2680         if(pSC->m_Dparam->cThumbnailScale >= 16)
2681             pSC->m_Dparam->bDecodeLP = FALSE; // only need to decode DC
2682     }
2683 
2684     // original image size
2685     pWMII->cWidth += pSC->m_param.cExtraPixelsLeft + pSC->m_param.cExtraPixelsRight;
2686     pWMII->cHeight += pSC->m_param.cExtraPixelsTop + pSC->m_param.cExtraPixelsBottom;
2687 
2688     /** region decode stuff */
2689     pSC->m_Dparam->cROILeftX = pWMII->cROILeftX * pSC->m_Dparam->cThumbnailScale + pSC->m_param.cExtraPixelsLeft;
2690     pSC->m_Dparam->cROIRightX = pSC->m_Dparam->cROILeftX + pWMII->cROIWidth * pSC->m_Dparam->cThumbnailScale - 1;
2691     pSC->m_Dparam->cROITopY = pWMII->cROITopY * pSC->m_Dparam->cThumbnailScale + pSC->m_param.cExtraPixelsTop;
2692     pSC->m_Dparam->cROIBottomY = pSC->m_Dparam->cROITopY + pWMII->cROIHeight * pSC->m_Dparam->cThumbnailScale - 1;
2693     if(pSC->m_Dparam->cROIRightX >= pWMII->cWidth)
2694         pSC->m_Dparam->cROIRightX = pWMII->cWidth - 1;
2695     if(pSC->m_Dparam->cROIBottomY >= pWMII->cHeight)
2696         pSC->m_Dparam->cROIBottomY = pWMII->cHeight - 1;
2697 
2698     pSC->m_Dparam->bDecodeFullFrame = (pSC->m_Dparam->cROILeftX + pSC->m_Dparam->cROITopY == 0 &&
2699         ((pSC->m_Dparam->cROIRightX + 15) / 16 >= (pWMII->cWidth + 14) / 16) && ((pSC->m_Dparam->cROIBottomY + 15) / 16 >= (pWMII->cHeight + 14) / 16));
2700 
2701     pSC->m_Dparam->bDecodeFullWidth = (pSC->m_Dparam->cROILeftX == 0 && ((pSC->m_Dparam->cROIRightX + 15) / 16 >= (pWMII->cWidth + 14) / 16));
2702 
2703     // inscribed image size
2704     pWMII->cWidth -= pSC->m_param.cExtraPixelsLeft + pSC->m_param.cExtraPixelsRight;
2705     pWMII->cHeight -= pSC->m_param.cExtraPixelsTop + pSC->m_param.cExtraPixelsBottom;
2706 
2707     if(pSC->WMISCP.bfBitstreamFormat == FREQUENCY && pWMII->bSkipFlexbits == TRUE)
2708         pSC->m_Dparam->bSkipFlexbits = TRUE;
2709 
2710     pSC->cTileColumn = pSC->cTileRow = 0;
2711 }
2712 
StrDecInit(CWMImageStrCodec * pSC)2713 Int StrDecInit(CWMImageStrCodec* pSC)
2714 {
2715     // CWMImageInfo * pWMII = &pSC->WMII;
2716     COLORFORMAT cfInt = pSC->m_param.cfColorFormat;
2717     COLORFORMAT cfExt = pSC->WMII.cfColorFormat;
2718     size_t i;
2719 
2720     /** color transcoding with resolution change **/
2721     pSC->m_bUVResolutionChange = ((cfExt != Y_ONLY) && ((cfInt == YUV_420 && cfExt != YUV_420) ||
2722         (cfInt == YUV_422 && cfExt != YUV_422))) && !pSC->WMISCP.bYUVData;
2723     if(pSC->m_bUVResolutionChange){
2724         pSC->pResU = (PixelI *)malloc((cfExt == YUV_422 ? 128 : 256) * pSC->cmbWidth * sizeof(PixelI));
2725         pSC->pResV = (PixelI *)malloc((cfExt == YUV_422 ? 128 : 256) * pSC->cmbWidth * sizeof(PixelI));
2726         if(pSC->pResU == NULL || pSC->pResV == NULL || (cfExt == YUV_422 ? 128 : 256) * pSC->cmbWidth * sizeof(PixelI) < pSC->cmbWidth){
2727             return ICERR_ERROR;
2728         }
2729     }
2730 
2731     if(allocatePredInfo(pSC) != ICERR_OK){
2732         return ICERR_ERROR;
2733     }
2734 
2735     if(allocateTileInfo(pSC) != ICERR_OK)
2736         return ICERR_ERROR;
2737 
2738     if((pSC->m_param.uQPMode & 1) == 0){ // DC frame uniform quantization
2739         if(allocateQuantizer(pSC->pTile[0].pQuantizerDC, pSC->m_param.cNumChannels, 1) != ICERR_OK)
2740             return ICERR_ERROR;
2741         setUniformQuantizer(pSC, 0);
2742         for(i = 0; i < pSC->m_param.cNumChannels; i ++)
2743             pSC->pTile[0].pQuantizerDC[i]->iIndex = pSC->m_param.uiQPIndexDC[i];
2744         formatQuantizer(pSC->pTile[0].pQuantizerDC, (pSC->m_param.uQPMode >> 3) & 3, pSC->m_param.cNumChannels, 0, TRUE, pSC->m_param.bScaledArith);
2745     }
2746 
2747     if(pSC->WMISCP.sbSubband != SB_DC_ONLY){
2748         if((pSC->m_param.uQPMode & 2) == 0){ // LP frame uniform quantization
2749             if(allocateQuantizer(pSC->pTile[0].pQuantizerLP, pSC->m_param.cNumChannels, 1) != ICERR_OK)
2750                 return ICERR_ERROR;
2751             setUniformQuantizer(pSC, 1);
2752             if((pSC->m_param.uQPMode & 0x200) == 0) // use DC quantizer
2753                 useDCQuantizer(pSC, 0);
2754             else{
2755                 for(i = 0; i < pSC->m_param.cNumChannels; i ++)
2756                     pSC->pTile[0].pQuantizerLP[i]->iIndex = pSC->m_param.uiQPIndexLP[i];
2757                 formatQuantizer(pSC->pTile[0].pQuantizerLP, (pSC->m_param.uQPMode >> 5) & 3, pSC->m_param.cNumChannels, 0, TRUE, pSC->m_param.bScaledArith);
2758             }
2759         }
2760 
2761         if(pSC->WMISCP.sbSubband != SB_NO_HIGHPASS){
2762             if((pSC->m_param.uQPMode & 4) == 0){ // HP frame uniform quantization
2763                 if(allocateQuantizer(pSC->pTile[0].pQuantizerHP, pSC->m_param.cNumChannels, 1) != ICERR_OK)
2764                     return ICERR_ERROR;
2765                 setUniformQuantizer(pSC, 2);
2766 
2767                 if((pSC->m_param.uQPMode & 0x400) == 0) // use LP quantizer
2768                     useLPQuantizer(pSC, 1, 0);
2769                 else{
2770                     for(i = 0; i < pSC->m_param.cNumChannels; i ++)
2771                         pSC->pTile[0].pQuantizerHP[i]->iIndex = pSC->m_param.uiQPIndexHP[i];
2772                     formatQuantizer(pSC->pTile[0].pQuantizerHP, (pSC->m_param.uQPMode >> 7) & 3, pSC->m_param.cNumChannels, 0, FALSE, pSC->m_param.bScaledArith);
2773                 }
2774             }
2775         }
2776     }
2777 
2778     if(pSC->WMISCP.cNumOfSliceMinus1V >= MAX_TILES || AllocateCodingContextDec(pSC, pSC->WMISCP.cNumOfSliceMinus1V + 1) != ICERR_OK){
2779         return ICERR_ERROR;
2780     }
2781 
2782     if (pSC->m_bSecondary) {
2783         pSC->pIOHeader = pSC->m_pNextSC->pIOHeader;
2784         pSC->m_ppBitIO = pSC->m_pNextSC->m_ppBitIO;
2785         pSC->cNumBitIO = pSC->m_pNextSC->cNumBitIO;
2786         pSC->cSB = pSC->m_pNextSC->cSB;
2787     }
2788 
2789     setBitIOPointers(pSC);
2790 
2791     return ICERR_OK;
2792 }
2793 
StrDecTerm(CWMImageStrCodec * pSC)2794 Int StrDecTerm(CWMImageStrCodec* pSC)
2795 {
2796     size_t j, jend = (pSC->m_pNextSC != NULL);
2797 
2798     for (j = 0; j <= jend; j++) {
2799         if(pSC->m_bUVResolutionChange){
2800             if(pSC->pResU != NULL)
2801                 free(pSC->pResU);
2802             if(pSC->pResV != NULL)
2803                 free(pSC->pResV);
2804         }
2805 
2806         freePredInfo(pSC);
2807 
2808         freeTileInfo(pSC);
2809 
2810         FreeCodingContextDec(pSC);
2811 
2812         if (j == 0) {
2813             StrIODecTerm(pSC);
2814 
2815             // free lookup tables for rotation and flipping
2816             if(pSC->m_Dparam->pOffsetX != NULL)
2817                 free(pSC->m_Dparam->pOffsetX);
2818             if(pSC->m_Dparam->pOffsetY != NULL)
2819                 free(pSC->m_Dparam->pOffsetY);
2820         }
2821 
2822         pSC = pSC->m_pNextSC;
2823     }
2824 
2825     return 0;
2826 }
2827 
2828 /*************************************************************************
2829     Read header of image plane
2830 *************************************************************************/
ReadImagePlaneHeader(CWMImageInfo * pII,CWMIStrCodecParam * pSCP,CCoreParameters * pSC,SimpleBitIO * pSB)2831 Int ReadImagePlaneHeader(CWMImageInfo* pII, CWMIStrCodecParam *pSCP,
2832     CCoreParameters *pSC, SimpleBitIO* pSB)
2833 {
2834     ERR err = WMP_errSuccess;
2835 
2836     pSC->cfColorFormat = getBit32_SB(pSB, 3); // internal color format
2837     FailIf((pSC->cfColorFormat < Y_ONLY || pSC->cfColorFormat > NCOMPONENT), WMP_errUnsupportedFormat);
2838     pSCP->cfColorFormat = pSC->cfColorFormat;  // this should be removed later
2839     pSC->bScaledArith = getBit32_SB(pSB, 1); // lossless mode
2840 
2841     // subbands
2842     pSCP->sbSubband = getBit32_SB(pSB, 4);
2843 
2844 // color parameters
2845     switch (pSC->cfColorFormat) {
2846         case Y_ONLY:
2847             pSC->cNumChannels = 1;
2848             break;
2849         case YUV_420:
2850             pSC->cNumChannels = 3;
2851             getBit32_SB(pSB, 1);
2852             pII->cChromaCenteringX = (U8) getBit32_SB(pSB, 3);
2853             getBit32_SB(pSB, 1);
2854             pII->cChromaCenteringY = (U8) getBit32_SB(pSB, 3);
2855             break;
2856         case YUV_422:
2857             pSC->cNumChannels = 3;
2858             getBit32_SB(pSB, 1);
2859             pII->cChromaCenteringX = (U8) getBit32_SB(pSB, 3);
2860             getBit32_SB(pSB, 4);
2861             break;
2862         case YUV_444:
2863             pSC->cNumChannels = 3;
2864             getBit32_SB(pSB, 4);
2865             getBit32_SB(pSB, 4);
2866             break;
2867         case NCOMPONENT:
2868             pSC->cNumChannels = (Int) getBit32_SB(pSB, 4) + 1;
2869             getBit32_SB(pSB, 4);
2870             break;
2871         case CMYK:
2872             pSC->cNumChannels = 4;
2873             break;
2874         default:
2875             break;
2876     }
2877 
2878 // float and 32s additional parameters
2879     switch (pII->bdBitDepth) {
2880         case BD_16:
2881         case BD_16S:
2882         case BD_32:
2883         case BD_32S:
2884             pSCP->nLenMantissaOrShift = (U8) getBit32_SB(pSB, 8);
2885             break;
2886         case BD_32F:
2887             pSCP->nLenMantissaOrShift = (U8) getBit32_SB(pSB, 8);//float conversion parameters
2888             pSCP->nExpBias = (I8) getBit32_SB(pSB, 8);
2889             break;
2890         default:
2891             break;
2892     }
2893 
2894         // quantization
2895     pSC->uQPMode = 0;
2896     if(getBit32_SB(pSB, 1) == 1) // DC uniform
2897         pSC->uQPMode += (readQuantizerSB(pSC->uiQPIndexDC, pSB, pSC->cNumChannels) << 3);
2898     else
2899         pSC->uQPMode ++;
2900     if(pSCP->sbSubband != SB_DC_ONLY){
2901         if(getBit32_SB(pSB, 1) == 0){ // don't use DC QP
2902             pSC->uQPMode += 0x200;
2903             if(getBit32_SB(pSB, 1) == 1) // LP uniform
2904                 pSC->uQPMode += (readQuantizerSB(pSC->uiQPIndexLP, pSB, pSC->cNumChannels) << 5);
2905             else
2906                 pSC->uQPMode += 2;
2907         }
2908         else
2909             pSC->uQPMode += ((pSC->uQPMode & 1) << 1) + ((pSC->uQPMode & 0x18) << 2);
2910 
2911         if(pSCP->sbSubband != SB_NO_HIGHPASS){
2912             if(getBit32_SB(pSB, 1) == 0){ // don't use LP QP
2913                 pSC->uQPMode += 0x400;
2914                 if(getBit32_SB(pSB, 1) == 1) // HP uniform
2915                     pSC->uQPMode += (readQuantizerSB(pSC->uiQPIndexHP, pSB, pSC->cNumChannels) << 7);
2916                 else
2917                     pSC->uQPMode += 4;
2918             }
2919             else
2920                 pSC->uQPMode += ((pSC->uQPMode & 2) << 1) + ((pSC->uQPMode & 0x60) << 2);
2921         }
2922     }
2923 
2924     if(pSCP->sbSubband == SB_DC_ONLY)
2925         pSC->uQPMode |= 0x200;
2926     else if(pSCP->sbSubband == SB_NO_HIGHPASS)
2927         pSC->uQPMode |= 0x400;
2928 
2929 
2930     FailIf((pSC->uQPMode & 0x600) == 0, WMP_errInvalidParameter); // frame level QPs must be specified independently!
2931 
2932     flushToByte_SB(pSB);  // remove this later
2933 
2934 Cleanup:
2935     return WMP_errSuccess == err ? ICERR_OK : ICERR_ERROR;
2936 }
2937 
2938 /*************************************************************************
2939     Read header of image, and header of FIRST PLANE only
2940 *************************************************************************/
ReadWMIHeader(CWMImageInfo * pII,CWMIStrCodecParam * pSCP,CCoreParameters * pSC)2941 Int ReadWMIHeader(
2942     CWMImageInfo* pII,
2943     CWMIStrCodecParam *pSCP,
2944     CCoreParameters *pSC)
2945 {
2946     U32 i;
2947     ERR err = WMP_errSuccess;
2948     Bool bTilingPresent, bInscribed, bTileStretch, bAbbreviatedHeader;
2949     struct WMPStream* pWS = pSCP->pWStream;
2950 
2951     SimpleBitIO SB = {0};
2952     SimpleBitIO* pSB = &SB;
2953 
2954     U8 szMS[8] = {0};
2955     U32 cbStream = 0;
2956 
2957     // U32 bits = 0;
2958     // Int HEADERSIZE = 0;
2959 
2960     assert(pSC != NULL);
2961     //================================
2962 // 0
2963     /** signature **/
2964     Call(pWS->Read(pWS, szMS, sizeof(szMS)));
2965     FailIf(szMS != (U8 *) strstr((char *) szMS, "WMPHOTO"), WMP_errUnsupportedFormat);
2966     //================================
2967     Call(attach_SB(pSB, pWS));
2968 
2969 // 8
2970     /** codec version and subversion **/
2971     i = getBit32_SB(pSB, 4);
2972     FailIf((i != CODEC_VERSION), WMP_errIncorrectCodecVersion);
2973     pSC->cVersion = i;
2974     i = getBit32_SB(pSB, 4); // subversion
2975     FailIf((i != CODEC_SUBVERSION &&
2976         i != CODEC_SUBVERSION_NEWSCALING_SOFT_TILES && i != CODEC_SUBVERSION_NEWSCALING_HARD_TILES),
2977         WMP_errIncorrectCodecSubVersion);
2978     pSC->cSubVersion = i;
2979 
2980     pSC->bUseHardTileBoundaries = FALSE;
2981     if (pSC->cSubVersion == CODEC_SUBVERSION_NEWSCALING_HARD_TILES)
2982         pSC->bUseHardTileBoundaries = TRUE;
2983 
2984     pSCP->bUseHardTileBoundaries = pSC->bUseHardTileBoundaries;
2985 
2986 // 9 primary parameters
2987     bTilingPresent = (Bool) getBit32_SB(pSB, 1); // tiling present
2988     pSCP->bfBitstreamFormat = getBit32_SB(pSB, 1); // bitstream layout
2989     pII->oOrientation = (ORIENTATION)getBit32_SB(pSB, 3); // presentation orientation
2990     pSC->bIndexTable = getBit32_SB(pSB, 1);
2991     i = getBit32_SB(pSB, 2); // overlap
2992     FailIf((i == 3), WMP_errInvalidParameter);
2993     pSCP->olOverlap = i;
2994 
2995 // 11 some other parameters
2996     bAbbreviatedHeader = (Bool) getBit32_SB(pSB, 1); // short words for size and tiles
2997     pSCP->bdBitDepth = (BITDEPTH) getBit32_SB(pSB, 1); // long word
2998 pSCP->bdBitDepth = BD_LONG; // remove when optimization is done
2999     bInscribed = (Bool) getBit32_SB(pSB, 1); // windowing
3000     pSC->bTrimFlexbitsFlag = (Bool) getBit32_SB(pSB, 1); // trim flexbits flag
3001     bTileStretch = (Bool) getBit32_SB(pSB, 1); // tile stretching flag
3002     pSC->bRBSwapped = (Bool) getBit32_SB(pSB, 1); // red-blue swap flag
3003     getBit32_SB(pSB, 1);  // padding / reserved bit
3004     pSC->bAlphaChannel = (Bool) getBit32_SB(pSB, 1); // alpha channel present
3005 
3006 // 10 - informational
3007     pII->cfColorFormat = getBit32_SB(pSB, 4); // source color format
3008     pII->bdBitDepth = getBit32_SB(pSB, 4); // source bit depth
3009 
3010     if(BD_1alt == pII->bdBitDepth)
3011     {
3012         pII->bdBitDepth = BD_1;
3013         pSCP->bBlackWhite = 1;
3014     }
3015 
3016 // 12 - Variable length fields
3017 // size
3018     pII->cWidth = getBit32_SB(pSB, bAbbreviatedHeader ? 16 : 32) + 1;
3019     pII->cHeight = getBit32_SB(pSB, bAbbreviatedHeader ? 16 : 32) + 1;
3020     pSC->cExtraPixelsTop = pSC->cExtraPixelsLeft = pSC->cExtraPixelsBottom = pSC->cExtraPixelsRight = 0;
3021     if (bInscribed == FALSE && (pII->cWidth & 0xf) != 0)
3022         pSC->cExtraPixelsRight = 0x10 - (pII->cWidth & 0xF);
3023     if (bInscribed == FALSE && (pII->cHeight & 0xf) != 0)
3024         pSC->cExtraPixelsBottom = 0x10 - (pII->cHeight & 0xF);
3025 
3026 // tiling
3027     pSCP->cNumOfSliceMinus1V = pSCP->cNumOfSliceMinus1H = 0;
3028     if (bTilingPresent) {
3029         pSCP->cNumOfSliceMinus1V = getBit32_SB(pSB, LOG_MAX_TILES); // # of vertical slices along X axis
3030         pSCP->cNumOfSliceMinus1H = getBit32_SB(pSB, LOG_MAX_TILES); // # of horizontal slices along Y axis
3031     }
3032     FailIf((pSC->bIndexTable == FALSE) && (pSCP->bfBitstreamFormat == FREQUENCY || pSCP->cNumOfSliceMinus1V + pSCP->cNumOfSliceMinus1H > 0),
3033         WMP_errUnsupportedFormat);
3034 
3035 // tile sizes
3036     pSCP->uiTileX[0] = pSCP->uiTileY[0] = 0;
3037     for(i = 0; i < pSCP->cNumOfSliceMinus1V; i ++){ // width in MB of vertical slices, not needed for last slice!
3038         pSCP->uiTileX[i + 1] = (U32) getBit32_SB(pSB, bAbbreviatedHeader ? 8 : 16) + pSCP->uiTileX[i];
3039     }
3040     for(i = 0; i < pSCP->cNumOfSliceMinus1H; i ++){ // width in MB of vertical slices, not needed for last slice!
3041         pSCP->uiTileY[i + 1] = (U32) getBit32_SB(pSB, bAbbreviatedHeader ? 8 : 16) + pSCP->uiTileY[i];
3042     }
3043     if (bTileStretch) {  // no handling of tile stretching enabled as of now
3044         for (i = 0; i < (pSCP->cNumOfSliceMinus1V + 1) * (pSCP->cNumOfSliceMinus1H + 1); i++)
3045             getBit32_SB(pSB, 8);
3046     }
3047 
3048 // window due to compressed domain processing
3049     if (bInscribed) {
3050         pSC->cExtraPixelsTop = (U8)getBit32_SB(pSB, 6);
3051         pSC->cExtraPixelsLeft = (U8)getBit32_SB(pSB, 6);
3052         pSC->cExtraPixelsBottom = (U8)getBit32_SB(pSB, 6);
3053         pSC->cExtraPixelsRight = (U8)getBit32_SB(pSB, 6);
3054     }
3055 
3056     if(((pII->cWidth + pSC->cExtraPixelsLeft + pSC->cExtraPixelsRight) & 0xf) + ((pII->cHeight + pSC->cExtraPixelsTop + pSC->cExtraPixelsBottom) & 0xf) != 0){
3057         FailIf((pII->cWidth & 0xf) + (pII->cHeight & 0xf) + pSC->cExtraPixelsLeft + pSC->cExtraPixelsTop != 0, WMP_errInvalidParameter);
3058         FailIf(pII->cWidth <= pSC->cExtraPixelsRight || pII->cHeight <= pSC->cExtraPixelsBottom, WMP_errInvalidParameter);
3059         pII->cWidth -= pSC->cExtraPixelsRight, pII->cHeight -= pSC->cExtraPixelsBottom;
3060     }
3061 
3062     flushToByte_SB(pSB);  // redundant
3063 
3064     // read header of first image plane
3065     FailIf(ReadImagePlaneHeader(pII, pSCP, pSC, pSB), WMP_errUnsupportedFormat);
3066 
3067     // maybe UNALIGNED!!!
3068 
3069     //================================
3070     detach_SB(pSB);
3071     pSCP->cbStream = cbStream - getByteRead_SB(pSB);
3072 
3073     pSCP->uAlphaMode = (pSC->bAlphaChannel ? pSCP->uAlphaMode : 0);
3074     pSCP->cChannel = pSC->cNumChannels;
3075 
3076     if((pII->bdBitDepth == BD_5 || pII->bdBitDepth == BD_10 || pII->bdBitDepth == BD_565) &&
3077         (pSCP->cfColorFormat != YUV_444 && pSCP->cfColorFormat != YUV_422 && pSCP->cfColorFormat != YUV_420 && pSCP->cfColorFormat != Y_ONLY))
3078         return ICERR_ERROR;
3079 
3080 Cleanup:
3081     return WMP_errSuccess == err ? ICERR_OK : ICERR_ERROR;
3082 }
3083 
3084 //----------------------------------------------------------------
3085 // streaming api init/decode/term
ImageStrDecGetInfo(CWMImageInfo * pII,CWMIStrCodecParam * pSCP)3086 EXTERN_C Int ImageStrDecGetInfo(
3087     CWMImageInfo* pII,
3088     CWMIStrCodecParam *pSCP)
3089 {
3090     ERR err = WMP_errSuccess;
3091     size_t cMarker;
3092     CCoreParameters aDummy;
3093     // mark position of start of data
3094     Call(pSCP->pWStream->GetPos(pSCP->pWStream, &cMarker));
3095     Call(ReadWMIHeader(pII, pSCP, &aDummy));
3096     // rewind to start of data
3097     Call(pSCP->pWStream->SetPos(pSCP->pWStream, cMarker));
3098     return ICERR_OK;
3099 
3100 Cleanup:
3101     return ICERR_ERROR;
3102 }
3103 
WMPhotoValidate(CWMImageInfo * pII,CWMIStrCodecParam * pSCP)3104 EXTERN_C Int WMPhotoValidate(
3105     CWMImageInfo * pII,
3106     CWMIStrCodecParam * pSCP)
3107 {
3108     CWMImageInfo cII;
3109     CWMIStrCodecParam cSCP = *pSCP;
3110     size_t cScale = 1;
3111 
3112     if(ImageStrDecGetInfo(&cII, pSCP) != ICERR_OK)
3113         return ICERR_ERROR;
3114 
3115     // copy over un-overwritable ImageInfo parameters
3116     pII->bdBitDepth = cII.bdBitDepth;
3117     pII->cWidth = cII.cWidth;
3118     pII->cHeight = cII.cHeight;
3119 
3120     if(pII->cWidth == 0 || pII->cHeight == 0)
3121         return ICERR_ERROR;
3122 
3123     // copy over overwritable CodecParam parameters
3124     pSCP->bVerbose = cSCP.bVerbose;
3125     pSCP->cbStream = cSCP.cbStream;
3126     pSCP->pWStream = cSCP.pWStream;
3127     if(pSCP->uAlphaMode > 1) // something + alpha
3128         pSCP->uAlphaMode = cSCP.uAlphaMode; // something + alpha to alpha or something transcoding!
3129 
3130     // validate color transcoding
3131     if(pSCP->cfColorFormat == NCOMPONENT)
3132         pII->cfColorFormat = NCOMPONENT;
3133     if(pSCP->cfColorFormat == CMYK && pII->cfColorFormat != Y_ONLY && pII->cfColorFormat != CF_RGB)
3134         pII->cfColorFormat = CMYK;
3135     if(pSCP->cfColorFormat == YUV_422 && pII->cfColorFormat == YUV_420)
3136         pII->cfColorFormat = YUV_422;
3137     if(pSCP->cfColorFormat == YUV_444 && (pII->cfColorFormat == YUV_422 || pII->cfColorFormat == YUV_420))
3138         pII->cfColorFormat = YUV_444;
3139     if(cII.cfColorFormat == CF_RGB && pII->cfColorFormat != Y_ONLY &&
3140         pII->cfColorFormat != NCOMPONENT)  // no guarantee that number of channels will be >= 3
3141         pII->cfColorFormat = cII.cfColorFormat;
3142     if(cII.cfColorFormat == CF_RGBE)
3143         pII->cfColorFormat = CF_RGBE;
3144 
3145     // validate thumbnail parameters
3146     if(pII->cThumbnailWidth == 0 || pII->cThumbnailWidth > pII->cWidth)
3147         pII->cThumbnailWidth = pII->cWidth;
3148     if(pII->cThumbnailHeight == 0 || pII->cThumbnailHeight > pII->cHeight)
3149         pII->cThumbnailHeight = pII->cHeight;
3150     if((pII->cWidth + pII->cThumbnailWidth - 1) / pII->cThumbnailWidth != (pII->cHeight + pII->cThumbnailHeight - 1) / pII->cThumbnailHeight) {
3151         while((pII->cWidth + cScale - 1) / cScale > pII->cThumbnailWidth &&
3152             (pII->cHeight + cScale - 1) / cScale > pII->cThumbnailHeight && (cScale << 1))
3153             cScale <<= 1;
3154     }
3155     else {
3156         cScale = (pII->cWidth + pII->cThumbnailWidth - 1) / pII->cThumbnailWidth;
3157         if (cScale == 0)
3158             cScale = 1;
3159     }
3160     pII->cThumbnailWidth = (pII->cWidth + cScale - 1) / cScale;
3161     pII->cThumbnailHeight = (pII->cHeight + cScale - 1) / cScale;
3162 
3163     // validate region decode parameters
3164     if(pII->cROIHeight == 0 || pII->cROIWidth == 0){
3165         pII->cROILeftX = pII->cROITopY = 0;
3166         pII->cROIWidth = pII->cThumbnailWidth;
3167         pII->cROIHeight = pII->cThumbnailHeight;
3168     }
3169     if(pII->cROILeftX >= pII->cThumbnailWidth)
3170         pII->cROILeftX = 0;
3171     if(pII->cROITopY >= pII->cThumbnailHeight)
3172         pII->cROITopY = 0;
3173     if(pII->cROILeftX + pII->cROIWidth > pII->cThumbnailWidth)
3174         pII->cROIWidth = pII->cThumbnailWidth - pII->cROILeftX;
3175     if(pII->cROITopY + pII->cROIHeight > pII->cThumbnailHeight)
3176         pII->cROIHeight = pII->cThumbnailHeight - pII->cROITopY;
3177 
3178     return ICERR_OK;
3179 }
3180 
3181 /*************************************************************************
3182   Initialization of CWMImageStrCodec struct
3183 *************************************************************************/
InitializeStrDec(CWMImageStrCodec * pSC,const CCoreParameters * pParams,const CWMImageStrCodec * pSCIn)3184 static Void InitializeStrDec(CWMImageStrCodec *pSC,
3185   const CCoreParameters *pParams, const CWMImageStrCodec *pSCIn)
3186 {
3187     // copy core parameters
3188     memcpy (&(pSC->m_param), pParams, sizeof (CCoreParameters));
3189 
3190     pSC->cbStruct = sizeof(*pSC);
3191     pSC->WMII = pSCIn->WMII;
3192     pSC->WMISCP = pSCIn->WMISCP;
3193 
3194     pSC->cRow = 0;
3195     pSC->cColumn = 0;
3196 
3197     pSC->cmbWidth = (pSC->WMII.cWidth + 15) / 16;
3198     pSC->cmbHeight = (pSC->WMII.cHeight + 15) / 16;
3199 
3200     pSC->Load = outputMBRow; // output decoding result (ICC, etc)
3201     pSC->Transform = pParams->cSubVersion == CODEC_SUBVERSION ?
3202         invTransformMacroblock : invTransformMacroblock_alteredOperators_hard;
3203     pSC->TransformCenter = pSC->Transform;
3204 
3205     pSC->ProcessTopLeft = processMacroblockDec;
3206     pSC->ProcessTop = processMacroblockDec;
3207     pSC->ProcessTopRight = processMacroblockDec;
3208     pSC->ProcessLeft = processMacroblockDec;
3209     pSC->ProcessCenter = processMacroblockDec;
3210     pSC->ProcessRight = processMacroblockDec;
3211     pSC->ProcessBottomLeft = processMacroblockDec;
3212     pSC->ProcessBottom = processMacroblockDec;
3213     pSC->ProcessBottomRight = processMacroblockDec;
3214 
3215     pSC->m_pNextSC = NULL;
3216     pSC->m_bSecondary = FALSE;
3217 }
3218 
3219 /*************************************************************************
3220   ImageStrDecInit
3221 *************************************************************************/
ImageStrDecInit(CWMImageInfo * pII,CWMIStrCodecParam * pSCP,CTXSTRCODEC * pctxSC)3222 Int ImageStrDecInit(
3223     CWMImageInfo* pII,
3224     CWMIStrCodecParam *pSCP,
3225     CTXSTRCODEC* pctxSC)
3226 {
3227     static size_t cbChannels[BD_MAX] = {2, 4};
3228     ERR err = WMP_errSuccess;
3229 
3230     size_t cbChannel = 0, cblkChroma = 0;
3231     size_t cbMacBlockStride = 0, cbMacBlockChroma = 0, cMacBlock = 0;
3232 
3233     CWMImageStrCodec SC = {0};
3234     CWMImageStrCodec *pSC = NULL, *pNextSC = NULL;
3235     char* pb = NULL;
3236     size_t cb = 0, i;
3237     Bool bLossyTranscoding = FALSE;
3238     Bool bUseHardTileBoundaries = FALSE; //default is soft tile boundaries
3239     Bool bLessThan64Bit = sizeof(void *) < 8;
3240 
3241     *pctxSC = NULL;
3242 
3243     if(WMPhotoValidate(pII, pSCP) != ICERR_OK)
3244         return ICERR_ERROR;
3245 
3246     if(pSCP->sbSubband == SB_ISOLATED) // can not do anything with isolated bitstream
3247         return ICERR_ERROR;
3248 
3249     //================================================
3250     SC.WMISCP.pWStream = pSCP->pWStream;
3251     if (ReadWMIHeader(&SC.WMII, &SC.WMISCP, &SC.m_param) != ICERR_OK) {
3252         return ICERR_ERROR;
3253     }
3254 
3255     bUseHardTileBoundaries = SC.WMISCP.bUseHardTileBoundaries;
3256     if(SC.WMII.cfColorFormat == CMYK && pII->cfColorFormat == CF_RGB)
3257         bLossyTranscoding = TRUE;
3258     if(pSCP->cfColorFormat != CMYK && (pII->cfColorFormat == CMYK))
3259         return ICERR_ERROR;
3260 
3261     //================================================
3262     SC.WMISCP = *pSCP;
3263     SC.WMII   = *pII;
3264 
3265     // original image size
3266     SC.WMII.cWidth += SC.m_param.cExtraPixelsLeft + SC.m_param.cExtraPixelsRight;
3267     SC.WMII.cHeight += SC.m_param.cExtraPixelsTop + SC.m_param.cExtraPixelsBottom;
3268     pII->cROILeftX += SC.m_param.cExtraPixelsLeft;
3269     pII->cROITopY += SC.m_param.cExtraPixelsTop;
3270 
3271     //================================================
3272     cbChannel = cbChannels[SC.WMISCP.bdBitDepth];
3273     cblkChroma = cblkChromas[SC.m_param.cfColorFormat];
3274 
3275     cbMacBlockStride = cbChannel * 16 * 16;
3276     cbMacBlockChroma = cbChannel * 16 * cblkChroma;
3277     cMacBlock = (SC.WMII.cWidth + 15) / 16;
3278 
3279     //================================================
3280     cb = sizeof(*pSC) + (128 - 1) + sizeof(CWMDecoderParameters);
3281     cb += (PACKETLENGTH * 4 - 1) + (PACKETLENGTH * 2 ) + sizeof(*pSC->pIOHeader);
3282 
3283     i = (cbMacBlockStride + cbMacBlockChroma * (SC.m_param.cNumChannels - 1)) * 2; // i <= 2^15
3284     if (bLessThan64Bit && ((i * (cMacBlock >> 16)) & 0xffffc000)) {
3285         /** potential overflow - 32 bit pointers insufficient to address cache **/
3286         return ICERR_ERROR;
3287     }
3288     cb += i * cMacBlock;
3289 
3290     pb = malloc(cb);
3291     if(pb == NULL)
3292         return WMP_errOutOfMemory;
3293     memset(pb, 0, cb);
3294 
3295     //================================================
3296     pSC = (CWMImageStrCodec*)pb; pb += sizeof(*pSC);
3297     if(pSC == NULL)
3298         return ICERR_ERROR;
3299 
3300     // Set up perf timers
3301     PERFTIMER_ONLY(pSC->m_fMeasurePerf = pSCP->fMeasurePerf);
3302     PERFTIMER_NEW(pSC->m_fMeasurePerf, &pSC->m_ptEndToEndPerf);
3303     PERFTIMER_NEW(pSC->m_fMeasurePerf, &pSC->m_ptEncDecPerf);
3304     PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEndToEndPerf);
3305     PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
3306     PERFTIMER_COPYSTARTTIME(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf, pSC->m_ptEndToEndPerf);
3307 
3308     pSC->m_Dparam = (CWMDecoderParameters*)pb; pb += sizeof(CWMDecoderParameters);
3309     pSC->cbChannel = cbChannel;
3310     //pSC->cNumChannels = SC.WMISCP.cChannel;
3311     pSC->bUseHardTileBoundaries = bUseHardTileBoundaries;
3312 
3313     //================================================
3314     InitializeStrDec(pSC, &SC.m_param, &SC);
3315 
3316     //================================================
3317     // 2 Macro Row buffers for each channel
3318     pb = ALIGNUP(pb, 128);
3319     for (i = 0; i < pSC->m_param.cNumChannels; i++) {
3320         pSC->a0MBbuffer[i] = (PixelI*)pb; pb += cbMacBlockStride * pSC->cmbWidth;
3321         pSC->a1MBbuffer[i] = (PixelI*)pb; pb += cbMacBlockStride * pSC->cmbWidth;
3322         cbMacBlockStride = cbMacBlockChroma;
3323     }
3324 
3325     //================================================
3326     // lay 2 aligned IO buffers just below pIO struct
3327     pb = (char*)ALIGNUP(pb, PACKETLENGTH * 4) + PACKETLENGTH * 2;
3328     pSC->pIOHeader = (BitIOInfo*)pb; pb += sizeof(*pSC->pIOHeader);
3329 
3330     // if interleaved alpha is needed
3331     if (pSC->m_param.bAlphaChannel) {
3332         SimpleBitIO SB = {0};
3333         cbMacBlockStride = cbChannel * 16 * 16;
3334 
3335         // 1. allocate new pNextSC info
3336         //================================================
3337         cb = sizeof(*pNextSC) + (128 - 1) + cbMacBlockStride * cMacBlock * 2;
3338         // if primary image is safe to allocate, alpha channel is certainly safe
3339         pb = malloc(cb);
3340         if(pb == NULL)
3341             return WMP_errOutOfMemory;
3342         memset(pb, 0, cb);
3343         //================================================
3344         pNextSC = (CWMImageStrCodec*)pb; pb += sizeof(*pNextSC);
3345 
3346         // read plane header of second image plane
3347         Call(attach_SB(&SB, pSCP->pWStream));
3348         InitializeStrDec(pNextSC, &SC.m_param, &SC);
3349         ReadImagePlaneHeader(&pNextSC->WMII, &pNextSC->WMISCP, &pNextSC->m_param, &SB);
3350         detach_SB(&SB);
3351 
3352         // 2. initialize pNextSC
3353         if(pNextSC == NULL)
3354             return ICERR_ERROR;
3355         pNextSC->m_Dparam = pSC->m_Dparam;
3356         pNextSC->cbChannel = cbChannel;
3357         //================================================
3358 
3359         // 3. initialize arrays
3360 //        InitializeStrDec(pNextSC, &SC.m_param, &SC);
3361         pNextSC->m_param.cfColorFormat = Y_ONLY;
3362         pNextSC->m_param.cNumChannels = 1;
3363         pNextSC->m_param.bAlphaChannel = TRUE;
3364         //================================================
3365 
3366         // 2 Macro Row buffers for each channel
3367         pb = ALIGNUP(pb, 128);
3368         pNextSC->a0MBbuffer[0] = (PixelI*)pb; pb += cbMacBlockStride * pNextSC->cmbWidth;
3369         pNextSC->a1MBbuffer[0] = (PixelI*)pb;
3370         //================================================
3371         pNextSC->pIOHeader = pSC->pIOHeader;
3372         //================================================
3373 
3374         // 4. link pSC->pNextSC = pNextSC
3375         pNextSC->m_pNextSC = pSC;
3376         pNextSC->m_bSecondary = TRUE;
3377 
3378     }
3379     else
3380         pSC->WMISCP.uAlphaMode = 0;
3381 
3382     //================================================
3383     FailIf((StrIODecInit(pSC) != ICERR_OK), WMP_errOutOfMemory);
3384     FailIf((StrDecInit(pSC) != ICERR_OK), WMP_errOutOfMemory);
3385     if (pNextSC) {
3386         // 5. StrEncInit
3387         FailIf((StrDecInit(pNextSC) != ICERR_OK), WMP_errOutOfMemory);
3388     }
3389 
3390     pSC->m_pNextSC = pNextSC;
3391     //================================================
3392     *pII = pSC->WMII;
3393     *pSCP = pSC->WMISCP;
3394     *pctxSC = (CTXSTRCODEC)pSC;
3395 
3396     if(pSC->WMII.cPostProcStrength){
3397         initPostProc(pSC->pPostProcInfo, pSC->cmbWidth, pSC->m_param.cNumChannels);
3398         if (pSC->m_param.bAlphaChannel)
3399             initPostProc(pNextSC->pPostProcInfo, pNextSC->cmbWidth, pNextSC->m_param.cNumChannels);
3400     }
3401 
3402     PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
3403 
3404 Cleanup:
3405     return WMP_errSuccess == err ? ICERR_OK : ICERR_ERROR;
3406 }
3407 
ImageStrDecDecode(CTXSTRCODEC ctxSC,const CWMImageBufferInfo * pBI,size_t * pcDecodedLines)3408 Int ImageStrDecDecode(
3409     CTXSTRCODEC ctxSC,
3410     const CWMImageBufferInfo* pBI
3411 #ifdef REENTRANT_MODE
3412     , size_t *pcDecodedLines
3413 #endif
3414     )
3415 {
3416     CWMImageStrCodec* pSC = (CWMImageStrCodec*)ctxSC;
3417     CWMImageStrCodec* pNextSC = pSC->m_pNextSC;
3418     size_t cMBRow, k;
3419 
3420     ImageDataProc ProcessLeft, ProcessCenter, ProcessRight;
3421     ImageDataProc Transform = NULL;
3422     const size_t iChromaElements = (pSC->m_param.cfColorFormat == YUV_420) ? 8 * 8
3423         : ((pSC->m_param.cfColorFormat == YUV_422) ? 8 * 16 : 16 * 16);
3424 
3425     if (sizeof(*pSC) != pSC->cbStruct)
3426     {
3427         return ICERR_ERROR;
3428     }
3429 
3430     //================================
3431     PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
3432 
3433     pSC->WMIBI = *pBI;
3434 
3435 #ifdef REENTRANT_MODE
3436     if (0 == pSC->WMIBI.uiFirstMBRow)
3437     {
3438         setROI(pSC);
3439         if (pNextSC) {
3440             pNextSC->WMIBI = pSC->WMIBI;
3441             setROI(pNextSC);
3442         }
3443     }
3444 #else
3445     setROI(pSC);
3446     if (pNextSC) {
3447         pNextSC->WMIBI = pSC->WMIBI;
3448         setROI(pNextSC);
3449     }
3450 #endif // REENTRANT_MODE
3451 
3452 // optimization flags can be defined only after ROI is set!
3453 #if defined(WMP_OPT_SSE2) || defined(WMP_OPT_CC_DEC) || defined(WMP_OPT_TRFM_DEC)
3454     StrDecOpt(pSC);
3455 #endif // OPT defined
3456 
3457 
3458 
3459     cMBRow = (pSC->m_Dparam->bDecodeFullFrame ? pSC->cmbHeight : ((pSC->m_Dparam->cROIBottomY + 16) >> 4));
3460 
3461 #ifdef REENTRANT_MODE
3462     if (0 == pSC->WMIBI.uiFirstMBRow)
3463     {
3464         if(initLookupTables(pSC) != ICERR_OK)
3465             return ICERR_ERROR;
3466         if (pNextSC && initLookupTables(pNextSC) != ICERR_OK)
3467             return ICERR_ERROR;
3468     }
3469 #else
3470     if(initLookupTables(pSC) != ICERR_OK)
3471         return ICERR_ERROR;
3472     if (pNextSC && initLookupTables(pNextSC) != ICERR_OK)
3473         return ICERR_ERROR;
3474 #endif // REENTRANT_MODE
3475 
3476 #ifndef REENTRANT_MODE
3477     if(pSC->WMII.bdBitDepth == BD_1){
3478         size_t i;
3479 
3480 
3481         for(i = 0; i < pSC->WMIBI.cLine; i ++)
3482             memset(pSC->WMIBI.pv, 0, pSC->WMIBI.cbStride);
3483     }
3484 #endif
3485 
3486     //================================
3487     // top row
3488 #ifdef REENTRANT_MODE
3489 #else
3490     pSC->cRow = 0;
3491     ProcessLeft = pSC->ProcessTopLeft;
3492     ProcessCenter = pSC->ProcessTop;
3493     ProcessRight = pSC->ProcessTopRight;
3494     Transform = pSC->m_param.cSubVersion == CODEC_SUBVERSION ?
3495         invTransformMacroblock : invTransformMacroblock_alteredOperators_hard;
3496 #endif // REENTRANT_MODE
3497 
3498 #ifdef REENTRANT_MODE
3499     for (pSC->cRow = pSC->WMIBI.uiFirstMBRow; pSC->cRow <= pSC->WMIBI.uiLastMBRow; pSC->cRow++)
3500     {
3501         // const COLORFORMAT cfExt = (pSC->m_param.cfColorFormat == Y_ONLY ? Y_ONLY : pSC->WMII.cfColorFormat);
3502 
3503         if (0 == pSC->cRow)
3504         {
3505             ProcessLeft = pSC->ProcessTopLeft;
3506             ProcessCenter = pSC->ProcessTop;
3507             ProcessRight = pSC->ProcessTopRight;
3508             Transform = pSC->m_param.cSubVersion == CODEC_SUBVERSION ?
3509                 invTransformMacroblock : invTransformMacroblock_alteredOperators_hard;
3510         }
3511         else if (cMBRow == pSC->cRow)
3512         {
3513             //================================
3514             // bottom row
3515             ProcessLeft = pSC->ProcessBottomLeft;
3516             ProcessCenter = pSC->ProcessBottom;
3517             ProcessRight = pSC->ProcessBottomRight;
3518             Transform = pSC->m_param.cSubVersion == CODEC_SUBVERSION ?
3519                 invTransformMacroblock : invTransformMacroblock_alteredOperators_hard;
3520         }
3521         else { // middle rows
3522             ProcessLeft = pSC->ProcessLeft;
3523             ProcessCenter = pSC->ProcessCenter;
3524             ProcessRight = pSC->ProcessRight;
3525             Transform = pSC->TransformCenter;
3526         }
3527 #else
3528     //================================
3529     // central rows
3530     for(pSC->cRow = 0; pSC->cRow <= cMBRow; pSC->cRow++)
3531     {
3532 #endif // REENTRANT_MODE
3533         pSC->cColumn = 0;
3534         initMRPtr(pSC);
3535         /** zero out the transform coefficients (pull this out to once per MB row) **/
3536         memset(pSC->p1MBbuffer[0], 0, sizeof(PixelI) * 16 * 16 * pSC->cmbWidth);
3537         for (k = 1; k < pSC->m_param.cNumChannels; k++) {
3538             memset(pSC->p1MBbuffer[k], 0, sizeof(PixelI) * iChromaElements * pSC->cmbWidth);
3539         }
3540         if (pSC->m_pNextSC != NULL) {  // alpha channel
3541             memset(pSC->m_pNextSC->p1MBbuffer[0], 0, sizeof(PixelI) * 16 * 16 * pSC->m_pNextSC->cmbWidth);
3542         }
3543 
3544         if(ProcessLeft(pSC) != ICERR_OK)
3545             return ICERR_ERROR;
3546         advanceMRPtr(pSC);
3547 
3548         pSC->Transform = Transform;
3549         for (pSC->cColumn = 1; pSC->cColumn < pSC->cmbWidth; ++pSC->cColumn)
3550         {
3551             if(ProcessCenter(pSC) != ICERR_OK)
3552                 return ICERR_ERROR;
3553             advanceMRPtr(pSC);
3554         }
3555         pSC->Transform = pSC->m_param.cSubVersion == CODEC_SUBVERSION ?
3556             invTransformMacroblock : invTransformMacroblock_alteredOperators_hard;
3557 
3558         if(ProcessRight(pSC) != ICERR_OK)
3559             return ICERR_ERROR;
3560 
3561         if (pSC->cRow) {
3562             if(pSC->m_Dparam->cThumbnailScale < 2 && (pSC->m_Dparam->bDecodeFullFrame ||
3563                 ((pSC->cRow * 16 > pSC->m_Dparam->cROITopY) && (pSC->cRow * 16 <= pSC->m_Dparam->cROIBottomY + 16)))) {
3564                 if( pSC->Load(pSC) != ICERR_OK ) // bypass CC for thumbnail decode
3565             		return ICERR_ERROR;
3566             }
3567 
3568             if(pSC->m_Dparam->cThumbnailScale >= 2) // decode thumbnail
3569                 decodeThumbnail(pSC);
3570         }
3571 
3572         advanceOneMBRow(pSC);
3573         swapMRPtr(pSC);
3574 #ifdef REENTRANT_MODE
3575         *pcDecodedLines = pSC->WMIBI.cLinesDecoded;
3576 #else
3577         if (pSC->cRow == cMBRow - 1) {
3578         //================================
3579         // bottom row
3580             ProcessLeft = pSC->ProcessBottomLeft;
3581             ProcessCenter = pSC->ProcessBottom;
3582             ProcessRight = pSC->ProcessBottomRight;
3583             Transform = pSC->m_param.cSubVersion == CODEC_SUBVERSION ?
3584                 invTransformMacroblock : invTransformMacroblock_alteredOperators_hard;
3585         }
3586         else {
3587             ProcessLeft = pSC->ProcessLeft;
3588             ProcessCenter = pSC->ProcessCenter;
3589             ProcessRight = pSC->ProcessRight;
3590             Transform = pSC->TransformCenter;
3591         }
3592 #endif // REENTRANT_MODE
3593     }
3594 
3595 #ifndef REENTRANT_MODE
3596     fixup_Y_ONLY_to_Others(pSC, pBI);
3597 #endif // REENTRANT_MODE
3598 
3599     PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
3600     return ICERR_OK;
3601 }
3602 
3603 Int ImageStrDecTerm(
3604     CTXSTRCODEC ctxSC)
3605 {
3606     CWMImageStrCodec* pSC = (CWMImageStrCodec*)ctxSC;
3607     if (NULL == pSC)
3608     {
3609         return ICERR_OK;
3610     }
3611     if (sizeof(*pSC) != pSC->cbStruct)
3612     {
3613         return ICERR_ERROR;
3614     }
3615 
3616     PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
3617 
3618     StrDecTerm(pSC);
3619     PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
3620     PERFTIMER_REPORT(pSC->m_fMeasurePerf, pSC);
3621     PERFTIMER_DELETE(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
3622     PERFTIMER_DELETE(pSC->m_fMeasurePerf, pSC->m_ptEndToEndPerf);
3623 
3624     free(pSC);
3625 
3626     return ICERR_OK;
3627 }
3628 
3629