📄 huffc.c
字号:
numCOL=cPtr->imageWidth; numROW=cPtr->imageHeight; compsInScan=cPtr->compsInScan; Pr=cPtr->dataPrecision; Pt=cPtr->Pt; prevRowBuf=NULL; curRowBuf=mcuTable; for (row=0; row<numROW; row++) { for (col=0; col<numCOL; col++) { for (curComp = 0; curComp < compsInScan; curComp++) { ci = cPtr->MCUmembership[curComp]; compptr = cPtr->curCompInfo[ci]; tblNo=compptr->dcTblNo; for (i=0;i<numSelValue;i++) { Predict(row,col,curComp,curRowBuf,prevRowBuf,Pr,Pt, psvSet[i],&predictor); r = curRowBuf[col][curComp]-predictor; curCountTblNo=psvSet[i]-1; CountOneDiff(r,freqCountPtrs[curCountTblNo][tblNo]); } } } prevRowBuf=curRowBuf; curRowBuf+=numCOL; }}/* *-------------------------------------------------------------- * * FreqCountAllSelValue -- * * Count the times each category symbol occurs in this * image for all seven PSV. * To do this all together is even faster than to use * a loop to go through 4 only PSVs. * * Results: * None. * * Side effects: * The freqCountPtrs[i] has counted all category symbols * appeared in the image, where i goes from 0 to 6. * *-------------------------------------------------------------- */voidFreqCountAllSelValue(cPtr) CompressInfo *cPtr;{ register short curComp, ci; register int col,row; register JpegComponentInfo *compptr; register int r; int numCOL,numROW,compsInScan; int Pr,Pt,Ss,j; int predictor; MCU *prevRowBuf,*curRowBuf; numCOL=cPtr->imageWidth; numROW=cPtr->imageHeight; compsInScan=cPtr->compsInScan; Pr=cPtr->dataPrecision; Pt=cPtr->Pt; Ss=cPtr->Ss; prevRowBuf=NULL; curRowBuf=mcuTable; /* * Do some specical case checking such that we can reduce the * computations in the main loop. */ /* * For the very first mcu in the scan, predictor is 1<<(Pr-Pt-1). */ for (curComp = 0; curComp < compsInScan; curComp++) { ci = cPtr->MCUmembership[curComp]; compptr = cPtr->curCompInfo[ci]; r = curRowBuf[0][curComp] - (1<<(Pr-Pt-1)); AllPredCountOneDiff(r,compptr->dcTblNo); } /* * In rest of the first row, left neighboring pixel is the predictor. */ for (col=1; col<numCOL; col++) { for (curComp = 0; curComp < compsInScan; curComp++) { ci = cPtr->MCUmembership[curComp]; compptr = cPtr->curCompInfo[ci]; r = curRowBuf[col][curComp]-curRowBuf[col-1][curComp]; AllPredCountOneDiff(r,compptr->dcTblNo); } } prevRowBuf=curRowBuf; curRowBuf+=numCOL; for (row=1; row<numROW; row++) { /* * For the first column, upper neighbor is the predictor. */ for (curComp = 0; curComp < compsInScan; curComp++) { ci = cPtr->MCUmembership[curComp]; compptr = cPtr->curCompInfo[ci]; r = curRowBuf[0][curComp]-prevRowBuf[0][curComp]; AllPredCountOneDiff(r,compptr->dcTblNo); } /* * Call AllPredCountOneComp to count the rest samples on this row. */ for (col=1; col<numCOL; col++) { for (curComp = 0; curComp < compsInScan; curComp++) { ci = cPtr->MCUmembership[curComp]; compptr = cPtr->curCompInfo[ci]; AllPredCountOneComp(col,curComp,compptr->dcTblNo, curRowBuf,prevRowBuf); } } prevRowBuf=curRowBuf; curRowBuf+=numCOL; }}/* *-------------------------------------------------------------- * * FreqCountInit -- * * Allocate and zero the count tables. * * Results: * None. * * Side effects: * Seven tables pointed by freqCountPtrs[][] have been * allocated and initiallized. * *-------------------------------------------------------------- */voidFreqCountInit(cPtr) CompressInfo *cPtr;{ int i,j,tbl; for (i = 0; i < NUM_HUFF_TBLS; i++) { for (j=0;j<7;j++) freqCountPtrs[j][i] = NULL; } /* * Create seven count tables for each Huffman table. * Initialize the table entries to zero. * Note that GenHuffCoding expects 257 entries in each table, * although I think 17 will be enough. */ for (i = 0; i < cPtr->compsInScan; i++) { tbl = cPtr->curCompInfo[i]->dcTblNo; for (j=0;j<7;j++) { if (freqCountPtrs[j][tbl] == NULL) { freqCountPtrs[j][tbl] = (long *) malloc (257 *sizeof(long)); MEMSET((void *)(freqCountPtrs[j][tbl]), 0, 257*sizeof(long)); } } }}/* *-------------------------------------------------------------- * * EmitBitsSum -- * * Find the number of bits emiting for a PSV (curCountTblNo+1). * It includes the total bits of category symbols and additional * bits. * * Results: * Total "category symbol" and "additional bits" output bits * for this PSV. * * Side effects: * If in vervose mode, totalHuffSym and totalAddBits for * this PSV is stored. These data are later output as statistics * data. * *-------------------------------------------------------------- */longEmitBitsSum(curCountTblNo, htblPtr) int curCountTblNo; HuffmanTable *htblPtr[4];{ int i,tbl; long addBitSum,symLenSum,totalBits; addBitSum=0; symLenSum=0; /* * Count additional bits and Huffman symbol size. */ for (tbl = 0; tbl < NUM_HUFF_TBLS; tbl++) { if (freqCountPtrs[curCountTblNo][tbl] != NULL) { for (i=1;i<17;i++) { addBitSum+=freqCountPtrs[curCountTblNo][tbl][i]*i; } for (i=0;i<17;i++) { symLenSum+=freqCountPtrs[curCountTblNo][tbl][i]* htblPtr[tbl]->ehufsi[i]; } } } totalBits=symLenSum+addBitSum; if (verbose) { totalHuffSym[curCountTblNo]=symLenSum; totalAddBits[curCountTblNo]=addBitSum; } return (totalBits);}/* *-------------------------------------------------------------- * * HuffOptimize -- * * Find the best coding parameters for a Huffman-coded scan. * When called, the scan data has already been converted to * a sequence of MCU groups of source image samples, which * are stored in a "big" array, mcuTable. * * It counts the times each category symbol occurs. Based on * this counting, optimal Huffman tables are built. Then it * uses this optimal Huffman table and counting table to find * the best PSV. * * Results: * Optimal Huffman tables are retured in cPtr->dcHuffTblPtrs[tbl]. * Best PSV is retured in cPtr->Ss. * * Side effects: * None. * *-------------------------------------------------------------- */voidHuffOptimize (cPtr) CompressInfo *cPtr;{ int tbl,i; HuffmanTable *curHtblPtr[4]; long curTotalBits,bestTotalBits; long curFreqCount[257]; int curCountTblNo; FreqCountInit(cPtr); /* * Collect the frequency count in freqCountPtrs for each PSV. * Experiment data shows that when numSelValue > 4, * FreqCountAllSelValue does a better job than FreqCountSelValueSet. */ if (numSelValue>3) { FreqCountAllSelValue(cPtr); } else { FreqCountSelValueSet(cPtr); } /* * Generate optimal Huffman tables and find the best PSV. * Loop through each PSV is the psvSet. Whenever a better PSV * is found, its Huffman table is stored in cPtr->dcHuffTblPtrs; * and itself is stored in cPtr->Ss. */ /* * Set curCountTblNo to the first PSV. Allocate memory, * and point bestHtblPtr to cPtr->dcHuffTblPtrs, */ curCountTblNo=psvSet[0]-1; for (tbl = 0; tbl < NUM_HUFF_TBLS; tbl++) { curHtblPtr[tbl]=NULL; if (freqCountPtrs[curCountTblNo][tbl] != NULL) { curHtblPtr[tbl]=(HuffmanTable *) malloc (sizeof(HuffmanTable)); if (cPtr->dcHuffTblPtrs[tbl] == NULL) { cPtr->dcHuffTblPtrs[tbl]=(HuffmanTable *) malloc (sizeof(HuffmanTable)); } } } /* * Generate the Huffman tables for the first PSV and count the * total output bits of category symbols and additional bits. */ for (tbl = 0; tbl < NUM_HUFF_TBLS; tbl++) { if (freqCountPtrs[curCountTblNo][tbl] != NULL) { /* * Make an extra copy of the freqency tables since * GenHuffCoding destroys it. We need these tables * to count output bits next. */ MEMCPY(curFreqCount,freqCountPtrs[curCountTblNo][tbl], 257*sizeof(long)); GenHuffCoding(cPtr->dcHuffTblPtrs[tbl], curFreqCount); FixHuffTbl(cPtr->dcHuffTblPtrs[tbl]); } } bestTotalBits=EmitBitsSum(curCountTblNo,cPtr->dcHuffTblPtrs); cPtr->Ss=psvSet[0]; /* * Generate the Huffman tables and count the output bits for the * remaining PSVs. Store the best one in cPtr pionted structure. */ for (i=1; i<numSelValue; i++) { curCountTblNo=psvSet[i]-1; for (tbl=0; tbl<NUM_HUFF_TBLS; tbl++) { if (freqCountPtrs[curCountTblNo][tbl] != NULL) { MEMCPY(curFreqCount,freqCountPtrs[curCountTblNo][tbl], 257*sizeof(long)); GenHuffCoding(curHtblPtr[tbl],curFreqCount); FixHuffTbl(curHtblPtr[tbl]); } } curTotalBits=EmitBitsSum(curCountTblNo,curHtblPtr); if (curTotalBits<bestTotalBits) { for (tbl = 0; tbl < NUM_HUFF_TBLS; tbl++) { if (curHtblPtr[tbl] != NULL) { swap(HuffmanTable *,cPtr->dcHuffTblPtrs[tbl],curHtblPtr[tbl]); } } bestTotalBits=curTotalBits; cPtr->Ss=psvSet[i]; } } /* * Set sent_table FALSE so updated table will be * written to JPEG file. */ for (tbl = 0; tbl < NUM_HUFF_TBLS; tbl++) { if (cPtr->dcHuffTblPtrs[tbl] != NULL) { cPtr->dcHuffTblPtrs[tbl]->sentTable = 0; } } /* * Release the freqency Count tables, and temporary Huffman tables. */ for (tbl = 0; tbl < NUM_HUFF_TBLS; tbl++) { for (i=0;i<7;i++) { if (freqCountPtrs[i][tbl] != NULL) { free(freqCountPtrs[i][tbl]); } } if (curHtblPtr[tbl] != NULL) { free(curHtblPtr[tbl]); } }}/* *-------------------------------------------------------------- * * StdPickSelValue -- * * Select the best PSV from the psvSet. Default Huffman * tables and frequency counting tables are used in the * selection procedure. * * Results: * Chosen selection value is stored in cPtr->Ss * * Side effects: * None. * *-------------------------------------------------------------- */voidStdPickSelValue(cPtr) CompressInfo *cPtr;{ int tbl,i; long curTotalBits,bestTotalBits; long curFreqCount[257]; int curCountTblNo; FreqCountInit(cPtr); /* * Collect the frequency count in freqCountPtrs for each PSV. * Experiment data shows that when numSelValue > 4, * FreqCountAllSelValue does a better job than FreqCountSelValueSet. */ if (numSelValue>3) { FreqCountAllSelValue(cPtr); } else { FreqCountSelValueSet(cPtr); } /* * Loop through each PSV in the psvSet, and store the PSV * which generates the least output bits in cPtr->Ss. */ curCountTblNo=psvSet[0]-1; bestTotalBits=EmitBitsSum(curCountTblNo,cPtr->dcHuffTblPtrs); cPtr->Ss=psvSet[0]; for (i=1; i<numSelValue; i++) { curCountTblNo=psvSet[i]-1; curTotalBits=EmitBitsSum(curCountTblNo,cPtr->dcHuffTblPtrs); if (curTotalBits<bestTotalBits) { bestTotalBits=curTotalBits; cPtr->Ss=psvSet[i]; } } /* * Release frequency counting tables. */ for (tbl = 0; tbl < NUM_HUFF_TBLS; tbl++) { for (i=0;i<7;i++) { if (freqCountPtrs[i][tbl] != NULL) { free(freqCountPtrs[i][tbl]); } } }}/* *-------------------------------------------------------------- * * AddHuffTable -- * * Huffman table setup routines. Copy bits and val tables * into a Huffman table. * * Results: * bits and val are copied into htblprt. * (*htblptr)->sentTable is set to 0. * * Side effects: * None. * *-------------------------------------------------------------- */voidAddHuffTable (htblptr, bits, val) HuffmanTable **htblptr; Uchar *bits, *val;{ if (*htblptr == NULL) *htblptr = (HuffmanTable *) (malloc (sizeof(HuffmanTable))); MEMCPY((*htblptr)->bits, bits, sizeof((*htblptr)->bits)); MEMCPY((*htblptr)->huffval, val, sizeof((*htblptr)->huffval)); /* * Initialize sent_table FALSE so table will be written to JPEG file. * In an application where we are writing non-interchange JPEG files, * it might be desirable to save space by leaving default Huffman tables * out of the file. To do that, just initialize sent_table = TRUE... */ (*htblptr)->sentTable = 0;}/* *-------------------------------------------------------------- * * LoadStdHuffTables -- * * Load the standard Huffman tables (cf. JPEG standard * section K.3) into compression data structure pointed * by cPtr. * IMPORTANT: these are only valid for 8-bit data precision! * * Results: * Standard Huffman table, bits and val, are copied into * cPtr->dcHuffTblPtrs. * * Side effects: * None. * *-------------------------------------------------------------- */voidLoadStdHuffTables (cPtr) CompressInfo *cPtr;{ static Uchar dcLuminanceBits[17] = { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; static Uchar dcLuminanceVal[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; static Uchar dcChrominanceBits[17] = { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; static Uchar dcChrominanceVal[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; AddHuffTable(&(cPtr->dcHuffTblPtrs[0]),dcLuminanceBits,dcLuminanceVal); AddHuffTable(&(cPtr->dcHuffTblPtrs[1]),dcChrominanceBits,dcChrominanceVal);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -