qboolean NET_GetPacket (void) { int ret; struct sockaddr_in from; int fromlen; fromlen = sizeof(from); ret = recvfrom (net_socket,(char *) huffbuff, sizeof(net_message_buffer), 0, (struct sockaddr *)&from, &fromlen); if (ret == -1) { int errno = WSAGetLastError(); if (errno == WSAEWOULDBLOCK) return false; Sys_Error ("NET_GetPacket: %s", strerror(errno)); } SockadrToNetadr (&from, &net_from); if (ret == sizeof(net_message_buffer) ) { Con_Printf ("Oversize packet from %s\n", NET_AdrToString (net_from)); return false; } LastCompMessageSize += ret;//keep track of bytes actually received for debugging HuffDecode(huffbuff, (unsigned char *)net_message_buffer,ret,&ret); net_message.cursize = ret; return ret; }
void HuffEncode (const unsigned char *in, unsigned char *out, int inlen, int *outlen) { int i, j, bitat; unsigned int t; #if _DEBUG_HUFFMAN unsigned char *buf; int tlen; #endif /* _DEBUG_HUFFMAN */ bitat = 0; for (i = 0; i < inlen; i++) { t = HuffLookup[in[i]].bits; for (j = 0; j < HuffLookup[in[i]].len; j++) { PutBit (out+1, bitat + HuffLookup[in[i]].len-j-1, t&1); t >>= 1; } bitat += HuffLookup[in[i]].len; } *outlen = 1 + (bitat + 7)/8; *out = 8 * ((*outlen)-1) - bitat; if (*outlen >= inlen+1) { *out = 0xff; memcpy (out+1, in, inlen); *outlen = inlen+1; } #if _DEBUG_HUFFMAN HuffIn += inlen; HuffOut += *outlen; HuffPrintf("in: %d out: %d ratio: %f\n", HuffIn, HuffOut, 1-(float)HuffOut/(float)HuffIn); CalcFreq(in, inlen); buf = (unsigned char *) malloc (inlen); HuffDecode (out, buf, *outlen, &tlen, inlen); if (tlen != inlen) Sys_Error("bogus compression"); for (i = 0; i < inlen; i++) { if (in[i] != buf[i]) Sys_Error("bogus compression"); } free (buf); #endif /* _DEBUG_HUFFMAN */ }
void HuffEncode(unsigned char *in,unsigned char *out,int inlen,int *outlen) { int i,j,bitat; unsigned int t; bitat=0; for (i=0;i<inlen;i++) { t=HuffLookup[in[i]].bits; for (j=0;j<HuffLookup[in[i]].len;j++) { PutBit(out+1,bitat+HuffLookup[in[i]].len-j-1,t&1); t>>=1; } bitat+=HuffLookup[in[i]].len; } *outlen=1+(bitat+7)/8; *out=8*((*outlen)-1)-bitat; if(*outlen >= inlen+1) { *out=0xff; memcpy(out+1,in,inlen); *outlen=inlen+1; } #if _DEBUG HuffIn+=inlen; HuffOut+=*outlen; { unsigned char *buf; int tlen; buf=malloc(inlen); HuffDecode(out,buf,*outlen,&tlen); if(!tlen==inlen) Sys_Error("bogus compression"); for (i=0;i<inlen;i++) { if(in[i]!=buf[i]) Sys_Error("bogus compression"); } free(buf); } #endif }
void LJpegPlain::decodeScanLeft4Comps() { uchar8 *draw = mRaw->getData(); // First line HuffmanTable *dctbl1 = &huff[frame.compInfo[0].dcTblNo]; HuffmanTable *dctbl2 = &huff[frame.compInfo[1].dcTblNo]; HuffmanTable *dctbl3 = &huff[frame.compInfo[2].dcTblNo]; HuffmanTable *dctbl4 = &huff[frame.compInfo[3].dcTblNo]; //Prepare slices (for CR2) uint32 slices = (uint32)slicesW.size() * (frame.h - skipY); offset = new uint32[slices+1]; uint32 t_y = 0; uint32 t_x = 0; uint32 t_s = 0; uint32 slice = 0; for (slice = 0; slice < slices; slice++) { offset[slice] = ((t_x + offX) * mRaw->getBpp() + ((offY + t_y) * mRaw->pitch)) | (t_s << 28); _ASSERTE((offset[slice]&0x0fffffff) < mRaw->pitch*mRaw->dim.y); t_y++; if (t_y == (frame.h - skipY)) { t_y = 0; t_x += slicesW[t_s++]; } } offset[slices] = offset[slices-1]; // Extra offset to avoid branch in loop. slice_width = new int[slices]; // This is divided by comps, since comps pixels are processed at the time for (uint32 i = 0 ; i < slicesW.size(); i++) slice_width[i] = slicesW[i] / COMPS; if (skipX) slice_width[slicesW.size()-1] -= skipX; // First pixels are obviously not predicted int p1; int p2; int p3; int p4; ushort16 *dest = (ushort16*) & draw[offset[0] & 0x0fffffff]; ushort16 *predict = dest; *dest++ = p1 = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl1); *dest++ = p2 = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl2); *dest++ = p3 = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl3); *dest++ = p4 = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl4); slice = 1; uint32 pixInSlice = slice_width[0] - 1; uint32 cw = (frame.w - skipX); uint32 x = 1; // Skip first pixels on first line. for (uint32 y = 0;y < (frame.h - skipY);y++) { for (; x < cw ; x++) { p1 += HuffDecode(dctbl1); *dest++ = (ushort16)p1; p2 += HuffDecode(dctbl2); *dest++ = (ushort16)p2; p3 += HuffDecode(dctbl3); *dest++ = (ushort16)p3; p4 += HuffDecode(dctbl4); *dest++ = (ushort16)p4; if (0 == --pixInSlice) { // Next slice if (slice > slices) ThrowRDE("LJpegPlain::decodeScanLeft: Ran out of slices"); uint32 o = offset[slice++]; dest = (ushort16*) & draw[o&0x0fffffff]; // Adjust destination for next pixel if((o&0x0fffffff) > mRaw->pitch*mRaw->dim.y) ThrowRDE("LJpegPlain::decodeScanLeft: Offset out of bounds"); pixInSlice = slice_width[o>>28]; } } if (skipX) { for (uint32 i = 0; i < skipX; i++) { HuffDecode(dctbl1); HuffDecode(dctbl2); HuffDecode(dctbl3); HuffDecode(dctbl4); } } bits->checkPos(); p1 = predict[0]; // Predictors for next row p2 = predict[1]; p3 = predict[2]; // Predictors for next row p4 = predict[3]; predict = dest; // Adjust destination for next prediction x = 0; } }
void LJpegPlain::decodeScanLeft4_2_2() { _ASSERTE(slicesW.size() < 16); // We only have 4 bits for slice number. _ASSERTE(!(slicesW.size() > 1 && skipX)); // Check if this is a valid state _ASSERTE(frame.compInfo[0].superH == 2); // Check if this is a valid state _ASSERTE(frame.compInfo[0].superV == 1); // Check if this is a valid state _ASSERTE(frame.compInfo[1].superH == 1); // Check if this is a valid state _ASSERTE(frame.compInfo[1].superV == 1); // Check if this is a valid state _ASSERTE(frame.compInfo[2].superH == 1); // Check if this is a valid state _ASSERTE(frame.compInfo[2].superV == 1); // Check if this is a valid state _ASSERTE(frame.cps == COMPS); _ASSERTE(skipX == 0); HuffmanTable *dctbl1 = &huff[frame.compInfo[0].dcTblNo]; HuffmanTable *dctbl2 = &huff[frame.compInfo[1].dcTblNo]; HuffmanTable *dctbl3 = &huff[frame.compInfo[2].dcTblNo]; mRaw->subsampling.x = 2; mRaw->subsampling.y = 1; ushort16 *predict; // Prediction pointer uchar8 *draw = mRaw->getData(); //Prepare slices (for CR2) uint32 slices = (uint32)slicesW.size() * (frame.h - skipY); offset = new uint32[slices+1]; uint32 t_y = 0; uint32 t_x = 0; uint32 t_s = 0; uint32 slice = 0; slice_width = new int[slices]; // This is divided by comps, since comps pixels are processed at the time for (uint32 i = 0 ; i < slicesW.size(); i++) slice_width[i] = slicesW[i] / 2; for (slice = 0; slice < slices; slice++) { offset[slice] = ((t_x + offX) * mRaw->getBpp() + ((offY + t_y) * mRaw->pitch)) | (t_s << 28); _ASSERTE((offset[slice]&0x0fffffff) < mRaw->pitch*mRaw->dim.y); t_y ++; if (t_y >= (frame.h - skipY)) { t_y = 0; t_x += slice_width[t_s++]; } } offset[slices] = offset[slices-1]; // Extra offset to avoid branch in loop. if (skipX) slice_width[slicesW.size()-1] -= skipX; // Predictors for components ushort16 *dest = (ushort16*) & draw[offset[0] & 0x0fffffff]; // Always points to next slice slice = 1; uint32 pixInSlice = slice_width[0]; // Initialize predictors and decode one group. uint32 x = 0; int p1; int p2; int p3; // First pixel is not predicted, all other are. *dest = p1 = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl1); p1 = dest[COMPS] = p1 + HuffDecode(dctbl1); predict = dest; dest[1] = p2 = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl2); dest[2] = p3 = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl3); // Skip to next dest += COMPS * 2; x = 2; pixInSlice -= 2; uint32 cw = (frame.w - skipX); for (uint32 y = 0;y < (frame.h - skipY);y++) { for (; x < cw ; x += 2) { if (0 == pixInSlice) { // Next slice if (slice > slices) ThrowRDE("LJpegPlain::decodeScanLeft: Ran out of slices"); uint32 o = offset[slice++]; dest = (ushort16*) & draw[o&0x0fffffff]; // Adjust destination for next pixel if((o&0x0fffffff) > mRaw->pitch*mRaw->dim.y) ThrowRDE("LJpegPlain::decodeScanLeft: Offset out of bounds"); pixInSlice = slice_width[o>>28]; // If new are at the start of a new line, also update predictors. if (x == 0) { predict = dest; } } p1 += HuffDecode(dctbl1); *dest = p1; p1 += HuffDecode(dctbl1); dest[COMPS] = p1; dest[1] = p2 = p2 + HuffDecode(dctbl2); dest[2] = p3 = p3 + HuffDecode(dctbl3); dest += COMPS * 2; pixInSlice -= 2; } // Update predictors p1 = predict[0]; p2 = predict[1]; p3 = predict[2]; predict = dest; x = 0; // Check if we are still within the file. bits->checkPos(); } }
void LJpegPlain::decodeScanLeftGeneric() { _ASSERTE(slicesW.size() < 16); // We only have 4 bits for slice number. _ASSERTE(!(slicesW.size() > 1 && skipX)); // Check if this is a valid state uint32 comps = frame.cps; // Components HuffmanTable *dctbl[4]; // Tables for up to 4 components ushort16 *predict; // Prediction pointer /* Fast access to supersampling component settings * this is the number of components in a given block. */ uint32 samplesH[4]; uint32 samplesV[4]; uchar8 *draw = mRaw->getData(); uint32 maxSuperH = 1; uint32 maxSuperV = 1; uint32 samplesComp[4]; // How many samples per group does this component have uint32 pixGroup = 0; // How many pixels per group. for (uint32 i = 0; i < comps; i++) { dctbl[i] = &huff[frame.compInfo[i].dcTblNo]; samplesH[i] = frame.compInfo[i].superH; if (!isPowerOfTwo(samplesH[i])) ThrowRDE("LJpegPlain::decodeScanLeftGeneric: Horizontal sampling is not power of two."); maxSuperH = max(samplesH[i], maxSuperH); samplesV[i] = frame.compInfo[i].superV; if (!isPowerOfTwo(samplesV[i])) ThrowRDE("LJpegPlain::decodeScanLeftGeneric: Vertical sampling is not power of two."); maxSuperV = max(samplesV[i], maxSuperV); samplesComp[i] = samplesV[i] * samplesH[i]; pixGroup += samplesComp[i]; } mRaw->subsampling.x = maxSuperH; mRaw->subsampling.y = maxSuperV; //Prepare slices (for CR2) uint32 slices = (uint32)slicesW.size() * (frame.h - skipY) / maxSuperV; offset = new uint32[slices+1]; uint32 t_y = 0; uint32 t_x = 0; uint32 t_s = 0; uint32 slice = 0; uint32 pitch_s = mRaw->pitch / 2; // Pitch in shorts slice_width = new int[slices]; // This is divided by comps, since comps pixels are processed at the time for (uint32 i = 0 ; i < slicesW.size(); i++) slice_width[i] = slicesW[i] / pixGroup / maxSuperH; // This is a guess, but works for sRaw1+2. for (slice = 0; slice < slices; slice++) { offset[slice] = ((t_x + offX) * mRaw->getBpp() + ((offY + t_y) * mRaw->pitch)) | (t_s << 28); _ASSERTE((offset[slice]&0x0fffffff) < mRaw->pitch*mRaw->dim.y); t_y += maxSuperV; if (t_y >= (frame.h - skipY)) { t_y = 0; t_x += slice_width[t_s++]; } } offset[slices] = offset[slices-1]; // Extra offset to avoid branch in loop. if (skipX) ThrowRDE("LJpegPlain::decodeScanLeftGeneric: Cannot skip right border in subsampled mode"); // Predictors for components int p[4]; ushort16 *dest = (ushort16*) & draw[offset[0] & 0x0fffffff]; // Always points to next slice slice = 1; uint32 pixInSlice = slice_width[0]; // Initialize predictors and decode one group. uint32 x = 0; predict = dest; for (uint32 i = 0; i < comps; i++) { for (uint32 y2 = 0; y2 < samplesV[i]; y2++) { for (uint32 x2 = 0; x2 < samplesH[i]; x2++) { // First pixel is not predicted, all other are. if (y2 == 0 && x2 == 0) { *dest = p[i] = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl[i]); } else { p[i] += HuffDecode(dctbl[i]); _ASSERTE(p[i] >= 0 && p[i] < 65536); dest[x2*comps+y2*pitch_s] = p[i]; } } } // Set predictor for this component // Next component dest++; } // Increment destination to next group dest += (maxSuperH - 1) * comps; x = maxSuperH; pixInSlice -= maxSuperH; uint32 cw = (frame.w - skipX); for (uint32 y = 0;y < (frame.h - skipY);y += maxSuperV) { for (; x < cw ; x += maxSuperH) { if (0 == pixInSlice) { // Next slice if (slice > slices) ThrowRDE("LJpegPlain::decodeScanLeft: Ran out of slices"); uint32 o = offset[slice++]; dest = (ushort16*) & draw[o&0x0fffffff]; // Adjust destination for next pixel if((o&0x0fffffff) > mRaw->pitch*mRaw->dim.y) ThrowRDE("LJpegPlain::decodeScanLeft: Offset out of bounds"); pixInSlice = slice_width[o>>28]; // If new are at the start of a new line, also update predictors. if (x == 0) predict = dest; } for (uint32 i = 0; i < comps; i++) { for (uint32 y2 = 0; y2 < samplesV[i]; y2++) { for (uint32 x2 = 0; x2 < samplesH[i]; x2++) { p[i] += HuffDecode(dctbl[i]); _ASSERTE(p[i] >= 0 && p[i] < 65536); dest[x2*comps+y2*pitch_s] = p[i]; } } dest++; } dest += (maxSuperH * comps) - comps; pixInSlice -= maxSuperH; } // Update predictors for (uint32 i = 0; i < comps; i++) { p[i] = predict[i]; // Ensure, that there is a slice shift at new line if (!(pixInSlice == 0 || maxSuperV == 1)) ThrowRDE("LJpegPlain::decodeScanLeftGeneric: Slice not placed at new line"); } // Check if we are still within the file. bits->checkPos(); predict = dest; x = 0; } }
void LJpegPlain::decodeScanLeft4Comps() { // First line HuffmanTable *dctbl1 = &huff[frame.compInfo[0].dcTblNo]; HuffmanTable *dctbl2 = &huff[frame.compInfo[1].dcTblNo]; HuffmanTable *dctbl3 = &huff[frame.compInfo[2].dcTblNo]; HuffmanTable *dctbl4 = &huff[frame.compInfo[3].dcTblNo]; if (mCanonDoubleHeight) { frame.h *= 2; mRaw->dim = iPoint2D(frame.w * 2, frame.h); mRaw->destroyData(); mRaw->createData(); } uchar8 *draw = mRaw->getData(); //Prepare slices (for CR2) uint32 slices = (uint32)slicesW.size() * (frame.h - skipY); offset = new uint32[slices+1]; uint32 t_y = 0; uint32 t_x = 0; uint32 t_s = 0; uint32 slice = 0; for (slice = 0; slice < slices; slice++) { offset[slice] = ((t_x + offX) * mRaw->getBpp() + ((offY + t_y) * mRaw->pitch)) | (t_s << 28); _ASSERTE((offset[slice]&0x0fffffff) < mRaw->pitch*mRaw->dim.y); t_y++; if (t_y == (frame.h - skipY)) { t_y = 0; t_x += slicesW[t_s++]; } } // We check the final position. If bad slice sizes are given we risk writing outside the image if ((offset[slices-1]&0x0fffffff) >= mRaw->pitch*mRaw->dim.y) { ThrowRDE("LJpegPlain::decodeScanLeft: Last slice out of bounds"); } offset[slices] = offset[slices-1]; // Extra offset to avoid branch in loop. slice_width = new int[slices]; // This is divided by comps, since comps pixels are processed at the time for (uint32 i = 0 ; i < slicesW.size(); i++) slice_width[i] = slicesW[i] / COMPS; if (skipX) slice_width[slicesW.size()-1] -= skipX; // First pixels are obviously not predicted int p1; int p2; int p3; int p4; ushort16 *dest = (ushort16*) & draw[offset[0] & 0x0fffffff]; ushort16 *predict = dest; *dest++ = p1 = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl1); *dest++ = p2 = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl2); *dest++ = p3 = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl3); *dest++ = p4 = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl4); slice = 1; uint32 pixInSlice = slice_width[0] - 1; uint32 cw = (frame.w - skipX); uint32 x = 1; // Skip first pixels on first line. if (mCanonDoubleHeight) skipY = frame.h >> 1; uint32 ch = (frame.h - skipY); // Fix for Canon 80D mraw format. // In that format, `frame` is 4032x3402, while `mRaw` is 4536x3024. // Consequently, the slices in `frame` wrap around (this is taken care of by // `offset`) and must be decoded fully (without skipY) to fill the image if (mWrappedCr2Slices) ch = frame.h; for (uint32 y = 0;y < ch;y++) { for (; x < cw ; x++) { p1 += HuffDecode(dctbl1); *dest++ = (ushort16)p1; p2 += HuffDecode(dctbl2); *dest++ = (ushort16)p2; p3 += HuffDecode(dctbl3); *dest++ = (ushort16)p3; p4 += HuffDecode(dctbl4); *dest++ = (ushort16)p4; if (0 == --pixInSlice) { // Next slice if (slice > slices) ThrowRDE("LJpegPlain::decodeScanLeft: Ran out of slices"); uint32 o = offset[slice++]; dest = (ushort16*) & draw[o&0x0fffffff]; // Adjust destination for next pixel if((o&0x0fffffff) > mRaw->pitch*mRaw->dim.y) ThrowRDE("LJpegPlain::decodeScanLeft: Offset out of bounds"); pixInSlice = slice_width[o>>28]; } } if (skipX) { for (uint32 i = 0; i < skipX; i++) { HuffDecode(dctbl1); HuffDecode(dctbl2); HuffDecode(dctbl3); HuffDecode(dctbl4); } } bits->checkPos(); p1 = predict[0]; // Predictors for next row p2 = predict[1]; p3 = predict[2]; // Predictors for next row p4 = predict[3]; predict = dest; // Adjust destination for next prediction x = 0; } }
void LJpegPlain::decodeScanLeft4_2_0() { _ASSERTE(slicesW.size() < 16); // We only have 4 bits for slice number. _ASSERTE(!(slicesW.size() > 1 && skipX)); // Check if this is a valid state _ASSERTE(frame.compInfo[0].superH == 2); // Check if this is a valid state _ASSERTE(frame.compInfo[0].superV == 2); // Check if this is a valid state _ASSERTE(frame.compInfo[1].superH == 1); // Check if this is a valid state _ASSERTE(frame.compInfo[1].superV == 1); // Check if this is a valid state _ASSERTE(frame.compInfo[2].superH == 1); // Check if this is a valid state _ASSERTE(frame.compInfo[2].superV == 1); // Check if this is a valid state _ASSERTE(frame.cps == COMPS); _ASSERTE(skipX == 0); HuffmanTable *dctbl1 = &huff[frame.compInfo[0].dcTblNo]; HuffmanTable *dctbl2 = &huff[frame.compInfo[1].dcTblNo]; HuffmanTable *dctbl3 = &huff[frame.compInfo[2].dcTblNo]; ushort16 *predict; // Prediction pointer mRaw->metadata.subsampling.x = 2; mRaw->metadata.subsampling.y = 2; uchar8 *draw = mRaw->getData(); // Fix for Canon 6D mRaw, which has flipped width & height uint32 real_h = mCanonFlipDim ? frame.w : frame.h; //Prepare slices (for CR2) uint32 slices = (uint32)slicesW.size() * (real_h - skipY) / 2; offset = new uint32[slices+1]; uint32 t_y = 0; uint32 t_x = 0; uint32 t_s = 0; uint32 slice = 0; uint32 pitch_s = mRaw->pitch / 2; // Pitch in shorts slice_width = new int[slices]; // This is divided by comps, since comps pixels are processed at the time for (uint32 i = 0 ; i < slicesW.size(); i++) slice_width[i] = slicesW[i] / COMPS; for (slice = 0; slice < slices; slice++) { offset[slice] = ((t_x + offX) * mRaw->getBpp() + ((offY + t_y) * mRaw->pitch)) | (t_s << 28); _ASSERTE((offset[slice]&0x0fffffff) < mRaw->pitch*mRaw->dim.y); t_y += 2; if (t_y >= (real_h- skipY)) { t_y = 0; t_x += slice_width[t_s++]; } } // We check the final position. If bad slice sizes are given we risk writing outside the image if ((offset[slices-1]&0x0fffffff) >= mRaw->pitch*mRaw->dim.y) { ThrowRDE("LJpegPlain::decodeScanLeft: Last slice out of bounds"); } offset[slices] = offset[slices-1]; // Extra offset to avoid branch in loop. if (skipX) slice_width[slicesW.size()-1] -= skipX; // Predictors for components ushort16 *dest = (ushort16*) & draw[offset[0] & 0x0fffffff]; // Always points to next slice slice = 1; uint32 pixInSlice = slice_width[0]; // Initialize predictors and decode one group. uint32 x = 0; int p1; int p2; int p3; // First pixel is not predicted, all other are. *dest = p1 = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl1); p1 = dest[COMPS] = p1 + HuffDecode(dctbl1); p1 = dest[pitch_s] = p1 + HuffDecode(dctbl1); p1 = dest[COMPS+pitch_s] = p1 + HuffDecode(dctbl1); predict = dest; dest[1] = p2 = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl2); dest[2] = p3 = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl3); // Skip next dest += COMPS * 2; x = 2; pixInSlice -= 2; uint32 cw = (frame.w - skipX); uint32 ch = (frame.h - skipY); // Fix for Canon 80D mraw format. // In that format, `frame` is 4032x3402, while `mRaw` is 4536x3024. // Consequently, the slices in `frame` wrap around (this is taken care of by // `offset`) and must be decoded fully (without skipY) to fill the image if (mWrappedCr2Slices) ch = frame.h; for (uint32 y = 0;y < ch;y += 2) { for (; x < cw ; x += 2) { if (0 == pixInSlice) { // Next slice if (slice > slices) ThrowRDE("LJpegPlain::decodeScanLeft: Ran out of slices"); uint32 o = offset[slice++]; dest = (ushort16*) & draw[o&0x0fffffff]; // Adjust destination for next pixel _ASSERTE((o&0x0fffffff) < mRaw->pitch*mRaw->dim.y); if((o&0x0fffffff) > mRaw->pitch*mRaw->dim.y) ThrowRDE("LJpegPlain::decodeScanLeft: Offset out of bounds"); pixInSlice = slice_width[o>>28]; // If new are at the start of a new line, also update predictors. if (x == 0) { predict = dest; } } p1 += HuffDecode(dctbl1); *dest = p1; p1 += HuffDecode(dctbl1); dest[COMPS] = p1; p1 += HuffDecode(dctbl1); dest[pitch_s] = p1; p1 += HuffDecode(dctbl1); dest[pitch_s+COMPS] = p1; dest[1] = p2 = p2 + HuffDecode(dctbl2); dest[2] = p3 = p3 + HuffDecode(dctbl3); dest += COMPS * 2; pixInSlice -= 2; } // Update predictors p1 = predict[0]; p2 = predict[1]; p3 = predict[2]; _ASSERTE(pixInSlice == 0); // Ensure, that there is a slice shift at new line // Check if we are still within the file. bits->checkPos(); x = 0; } }
void LJpegPlain::decodeScanLeftGeneric() { _ASSERTE(slicesW.size() < 16); // We only have 4 bits for slice number. _ASSERTE(!(slicesW.size() > 1 && skipX)); // Check if this is a valid state uint32 comps = frame.cps; // Components HuffmanTable *dctbl[4]; // Tables for up to 4 components ushort16 *predict; // Prediction pointer /* Fast access to supersampling component settings * this is the number of components in a given block. */ uint32 samplesH[4]; uint32 samplesV[4]; uchar8 *draw = mRaw->getData(); uint32 maxSuperH = 1; uint32 maxSuperV = 1; uint32 samplesComp[4]; // How many samples per group does this component have uint32 pixGroup = 0; // How many pixels per group. for (uint32 i = 0; i < comps; i++) { dctbl[i] = &huff[frame.compInfo[i].dcTblNo]; samplesH[i] = frame.compInfo[i].superH; if (!isPowerOfTwo(samplesH[i])) ThrowRDE("LJpegPlain::decodeScanLeftGeneric: Horizontal sampling is not power of two."); maxSuperH = max(samplesH[i], maxSuperH); samplesV[i] = frame.compInfo[i].superV; if (!isPowerOfTwo(samplesV[i])) ThrowRDE("LJpegPlain::decodeScanLeftGeneric: Vertical sampling is not power of two."); maxSuperV = max(samplesV[i], maxSuperV); samplesComp[i] = samplesV[i] * samplesH[i]; pixGroup += samplesComp[i]; } mRaw->metadata.subsampling.x = maxSuperH; mRaw->metadata.subsampling.y = maxSuperV; //Prepare slices (for CR2) uint32 slices = (uint32)slicesW.size() * (frame.h - skipY) / maxSuperV; ushort16** imagePos = new ushort16*[slices+1]; int* sliceWidth = new int[slices+1]; uint32 t_y = 0; uint32 t_x = 0; uint32 t_s = 0; uint32 slice = 0; uint32 pitch_s = mRaw->pitch / 2; // Pitch in shorts slice_width = new int[slices]; // This is divided by comps, since comps pixels are processed at the time for (uint32 i = 0 ; i < slicesW.size(); i++) slice_width[i] = slicesW[i] / pixGroup / maxSuperH; // This is a guess, but works for sRaw1+2. if (skipX && (maxSuperV > 1 || maxSuperH > 1)) { ThrowRDE("LJpegPlain::decodeScanLeftGeneric: Cannot skip right border in subsampled mode"); } if (skipX) { slice_width[slicesW.size()-1] -= skipX; } for (slice = 0; slice < slices; slice++) { imagePos[slice] = (ushort16*)&draw[(t_x + offX) * mRaw->getBpp() + ((offY + t_y) * mRaw->pitch)]; sliceWidth[slice] = slice_width[t_s]; t_y += maxSuperV; if (t_y >= (frame.h - skipY)) { t_y = 0; t_x += slice_width[t_s++]; } } delete[] slice_width; slice_width = NULL; // We check the final position. If bad slice sizes are given we risk writing outside the image if (imagePos[slices-1] >= (ushort16*)&mRaw->getData()[mRaw->pitch * mRaw->dim.y]) { ThrowRDE("LJpegPlain::decodeScanLeft: Last slice out of bounds"); } imagePos[slices] = imagePos[slices-1]; // Extra offset to avoid branch in loop. sliceWidth[slices] = sliceWidth[slices-1]; // Extra offset to avoid branch in loop. // Predictors for components int p[4]; ushort16 *dest = imagePos[0]; // Always points to next slice slice = 1; uint32 pixInSlice = sliceWidth[0]; // Initialize predictors and decode one group. uint32 x = 0; predict = dest; for (uint32 i = 0; i < comps; i++) { for (uint32 y2 = 0; y2 < samplesV[i]; y2++) { for (uint32 x2 = 0; x2 < samplesH[i]; x2++) { // First pixel is not predicted, all other are. if (y2 == 0 && x2 == 0) { *dest = p[i] = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl[i]); } else { p[i] += HuffDecode(dctbl[i]); _ASSERTE(p[i] >= 0 && p[i] < 65536); dest[x2*comps+y2*pitch_s] = p[i]; } } } // Set predictor for this component // Next component dest++; } // Increment destination to next group dest += (maxSuperH - 1) * comps; x = maxSuperH; pixInSlice -= maxSuperH; uint32 cw = (frame.w - skipX); uint32 ch = (frame.h - skipY); // Fix for Canon 80D mraw format. // In that format, `frame` is 4032x3402, while `mRaw` is 4536x3024. // Consequently, the slices in `frame` wrap around (this is taken care of by // `offset`) and must be decoded fully (without skipY) to fill the image if (mWrappedCr2Slices) ch = frame.h; for (uint32 y = 0;y < ch;y += maxSuperV) { for (; x < cw ; x += maxSuperH) { if (0 == pixInSlice) { // Next slice if (slice > slices) ThrowRDE("LJpegPlain::decodeScanLeft: Ran out of slices"); pixInSlice = sliceWidth[slice]; dest = imagePos[slice]; // Adjust destination for next pixel slice++; // If new are at the start of a new line, also update predictors. if (x == 0) predict = dest; } for (uint32 i = 0; i < comps; i++) { for (uint32 y2 = 0; y2 < samplesV[i]; y2++) { for (uint32 x2 = 0; x2 < samplesH[i]; x2++) { p[i] += HuffDecode(dctbl[i]); _ASSERTE(p[i] >= 0 && p[i] < 65536); dest[x2*comps+y2*pitch_s] = p[i]; } } dest++; } dest += (maxSuperH * comps) - comps; pixInSlice -= maxSuperH; } if (skipX) { for (uint32 sx = 0; sx < skipX; sx++) { for (uint32 i = 0; i < comps; i++) { HuffDecode(dctbl[i]); } } } // Update predictors for (uint32 i = 0; i < comps; i++) { p[i] = predict[i]; // Ensure, that there is a slice shift at new line if (!(pixInSlice == 0 || maxSuperV == 1)) ThrowRDE("LJpegPlain::decodeScanLeftGeneric: Slice not placed at new line"); } // Check if we are still within the file. bits->checkPos(); predict = dest; x = 0; } delete[] imagePos; delete[] sliceWidth; }
void LJpegPlain::decodeScanLeft2Comps() { _ASSERTE(slicesW.size() < 16); // We only have 4 bits for slice number. _ASSERTE(!(slicesW.size() > 1 && skipX)); // Check if this is a valid state uchar8 *draw = mRaw->getData(); // First line HuffmanTable *dctbl1 = &huff[frame.compInfo[0].dcTblNo]; HuffmanTable *dctbl2 = &huff[frame.compInfo[1].dcTblNo]; //Prepare slices (for CR2) uint32 slices = (uint32)slicesW.size() * (frame.h - skipY); offset = new uint32[slices+1]; uint32 t_y = 0; uint32 t_x = 0; uint32 t_s = 0; uint32 slice = 0; uint32 cw = (frame.w - skipX); for (slice = 0; slice < slices; slice++) { offset[slice] = ((t_x + offX) * mRaw->getBpp() + ((offY + t_y) * mRaw->pitch)) | (t_s << 28); _ASSERTE((offset[slice]&0x0fffffff) < mRaw->pitch*mRaw->dim.y); t_y++; if (t_y == (frame.h - skipY)) { t_y = 0; t_x += slicesW[t_s++]; } } // We check the final position. If bad slice sizes are given we risk writing outside the image if ((offset[slices-1]&0x0fffffff) >= mRaw->pitch*mRaw->dim.y) { ThrowRDE("LJpegPlain::decodeScanLeft: Last slice out of bounds"); } offset[slices] = offset[slices-1]; // Extra offset to avoid branch in loop. slice_width = new int[slices]; // This is divided by comps, since comps pixels are processed at the time for (uint32 i = 0 ; i < slicesW.size(); i++) slice_width[i] = slicesW[i] / COMPS; if (skipX) slice_width[slicesW.size()-1] -= skipX; // First pixels are obviously not predicted int p1; int p2; ushort16 *dest = (ushort16*) & draw[offset[0] & 0x0fffffff]; ushort16 *predict = dest; *dest++ = p1 = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl1); *dest++ = p2 = (1 << (frame.prec - Pt - 1)) + HuffDecode(dctbl2); slice = 1; // Always points to next slice uint32 pixInSlice = slice_width[0] - 1; // Skip first pixel uint32 x = 1; // Skip first pixels on first line. for (uint32 y = 0;y < (frame.h - skipY);y++) { for (; x < cw ; x++) { int diff = HuffDecode(dctbl1); p1 += diff; *dest++ = (ushort16)p1; // _ASSERTE(p1 >= 0 && p1 < 65536); diff = HuffDecode(dctbl2); p2 += diff; *dest++ = (ushort16)p2; // _ASSERTE(p2 >= 0 && p2 < 65536); if (0 == --pixInSlice) { // Next slice if (slice > slices) ThrowRDE("LJpegPlain::decodeScanLeft: Ran out of slices"); uint32 o = offset[slice++]; dest = (ushort16*) & draw[o&0x0fffffff]; // Adjust destination for next pixel if((o&0x0fffffff) > mRaw->pitch*mRaw->dim.y) ThrowRDE("LJpegPlain::decodeScanLeft: Offset out of bounds"); pixInSlice = slice_width[o>>28]; } } if (skipX) { for (uint32 i = 0; i < skipX; i++) { HuffDecode(dctbl1); HuffDecode(dctbl2); } } p1 = predict[0]; // Predictors for next row p2 = predict[1]; predict = dest; // Adjust destination for next prediction x = 0; bits->checkPos(); } }