Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/jxr/image/decode/strdec.c
4393 views
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
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
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
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
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
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
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
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 */
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
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
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!
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
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
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
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
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
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
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 iOffsetY;\
1668
for(iColumn = iFirstColumn, iOffsetY = pOffsetY[iRow]; iColumn < cWidth; iColumn ++){\
1669
type *pT = (type*)(U8 *)pSC->WMIBI.pv + iOffsetY + 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
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
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
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 iOffsetY;\
2393
for(iColumn = iFirstColumn, iOffsetY = pOffsetY[iRow >> nBits]; iColumn < cWidth; iColumn += tScale){\
2394
type *pT = (type*)((U8 *)pSC->WMIBI.pv + pOffsetX[iColumn >> nBits] + iOffsetY);\
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
*************************************************************************/
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
//================================================================
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
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
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
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
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
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
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
*************************************************************************/
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
*************************************************************************/
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
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
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
*************************************************************************/
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
*************************************************************************/
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
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
3630