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