📄 huffc.c
字号:
/* * huffc.c -- * * Code for JPEG lossless encoding. Many parts are grabbed from the IJG * software, so: * * Copyright (C) 1991, 1992, Thomas G. Lane. * Part of the Independent JPEG Group's software. * See the file Copyright for more details. * * Copyright (c) 1993 Brian C. Smith, The Regents of the University * of California * All rights reserved. * * Copyright (c) 1994 Kongji Huang and Brian C. Smith. * Cornell University * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice and the following * two paragraphs appear in all copies of this software. * * IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <malloc.h>#include <assert.h>#include "jpeg.h"#include "mcu.h"#include "io.h"#include "proto.h"#include "predictor.h"#include "pnmtoljpg.h"#define RST0 0xD0 /* RST0 marker code */#define MIN_BUF_FREE 512 /* Min Buffer free for EncodeOneBlock */#define NUM_HUFF_TBLS 4 /* Max # of Huffman tables can be */ /* used in one scan. *//* * Lookup table for number of bits is a 8 bit value. Initialized * in HuffEncoderInit. */int numBitsTable [256];static int bmask[] = {0x0000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF};/* * Static variables for output buffering. */static int huffPutBuffer; /* current bit-accumulation buffer */static int huffPutBits; /* # of bits now in it *//* * Global variables for output buffering. */char outputBuffer[JPEG_BUF_SIZE]; /* output buffer */int numOutputBytes; /* bytes in the output buffer *//* * Static varible to count the times each category symbol occurs. * Array freqCountPtrs[i][tblNo] is the frequency table of PSV (i-1) * to build the Huffman table tblNo. */static long *freqCountPtrs[7][NUM_HUFF_TBLS];/* *-------------------------------------------------------------- * * FlushBytes -- * * Output the bytes we've accumulated so far to the output * file. * * Results: * None. * * Side effects: * The numOutputBytes is reset. * *-------------------------------------------------------------- */void FlushBytes (){ if (numOutputBytes) WriteJpegData (outputBuffer, numOutputBytes); numOutputBytes = 0;}/* *-------------------------------------------------------------- * * EmitByteNoFlush -- * * Write a single byte out to the output buffer. * Assumes the caller is checking for flushing the buffer. * * Results: * None. * * Side effects: * The output buffer may get flushed. * *-------------------------------------------------------------- */#define EmitByteNoFlush(val) { \ if (numOutputBytes >= JPEG_BUF_SIZE) \ FlushBytes(); \ outputBuffer[numOutputBytes++] = (char)(val); \}/* *-------------------------------------------------------------- * * EmitBits -- * * Code for outputting bits to the file * * Only the right 24 bits of huffPutBuffer are used; the valid * bits are left-justified in this part. At most 16 bits can be * passed to EmitBits in one call, and we never retain more than 7 * bits in huffPutBuffer between calls, so 24 bits are * sufficient. * * Results: * None. * * Side effects: * huffPutBuffer and huffPutBits are updated. * *-------------------------------------------------------------- */static voidEmitBits(code, size) Ushort code; int size;{ int putBuffer; int putBits; /* * if size is 0, caller used an invalid Huffman table entry */ assert (size != 0); /* * Mask off any excess bits in code. */ putBits = (size); putBuffer = ((code) & bmask[putBits]); putBits += huffPutBits; putBuffer <<= 24 - putBits; putBuffer |= huffPutBuffer; while (putBits >= 8) { int c; c = (putBuffer >> 16) & 0xFF; /* * Output whole bytes we've accumulated with byte stuffing */ EmitByteNoFlush (c); if (c == 0xFF) { EmitByteNoFlush (0); } putBuffer <<= 8; putBits -= 8; } /* * Update global variables */ huffPutBuffer = putBuffer; huffPutBits = putBits;}/* *-------------------------------------------------------------- * * FlushBits -- * * Flush any remaining bits in the bit buffer. Used before emitting * a marker. * * Results: * None. * * Side effects: * huffPutBuffer and huffPutBits are reset * *-------------------------------------------------------------- */static void FlushBits (){ /* * The first call forces output of any partial bytes. * We can then zero the buffer. */ EmitBits ((Ushort) 0x7F, 7); huffPutBuffer = 0; huffPutBits = 0;}/* *-------------------------------------------------------------- * * EncodeOneDiff -- * * Encode a single difference value. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */static void EncodeOneDiff (diff, dctbl) int diff; HuffmanTable *dctbl;{ register int temp, temp2; register short nbits; /* * Encode the DC coefficient difference per section F.1.2.1 */ temp = temp2 = diff; if (temp < 0) { temp = -temp; /* * For a negative input, want temp2 = bitwise complement of * abs(input). This code assumes we are on a two's complement * machine. */ temp2--; } /* * Find the number of bits needed for the magnitude of the coefficient */ nbits=0; if (temp) { while (temp >= 256) { nbits += 8; temp >>= 8; } nbits += numBitsTable[temp&0xff]; } /* * Emit the Huffman-coded symbol for the number of bits */ EmitBits (dctbl->ehufco[nbits], dctbl->ehufsi[nbits]); /* * Emit that number of bits of the value, if positive, * or the complement of its magnitude, if negative. */ if (nbits) EmitBits ((Ushort) temp2, nbits);}/* *-------------------------------------------------------------- * * HuffEncoderInit -- * * Initialize for a Huffman-compressed scan. * * Results: * None * * Side effects: * None * *-------------------------------------------------------------- */void HuffEncoderInit (cPtr) CompressInfo *cPtr;{ short ci, i, nbits, temp; JpegComponentInfo *compptr; /* * Initialize static variables */ huffPutBuffer = 0; huffPutBits = 0; /* * Initialize the output buffer */ numOutputBytes = 0; /* * Initialize restart stuff */ cPtr->restartRowsToGo = cPtr->restartInRows; cPtr->nextRestartNum = 0; /* * Initialize number of bits lookup table. */ for (i=0; i<256; i++) { temp = i; nbits = 1; while (temp >>= 1) { nbits++; } numBitsTable[i] = nbits; }}/* *-------------------------------------------------------------- * * EmitRestart -- * * Emit a restart marker & resynchronize predictions. * * Results: * None. * * Side effects: * Any remaining bits are flushed. * *-------------------------------------------------------------- */static void EmitRestart (cPtr) CompressInfo *cPtr;{ short ci; FlushBits (); EmitByteNoFlush (0xFF); EmitByteNoFlush (RST0 + cPtr->nextRestartNum); /* * Update restart state */ cPtr->restartRowsToGo = cPtr->restartInRows; cPtr->nextRestartNum++; cPtr->nextRestartNum &= 7;}/* *-------------------------------------------------------------- * * EncodeFirstRow -- * * Encode the first raster line of samples at the start of * the scan and at the beginning of each restart interval. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */voidEncodeFirstRow(cPtr,curRowBuf) CompressInfo * cPtr; MCU *curRowBuf;{ register short curComp,ci; register int col,compsInScan,numCOL; register JpegComponentInfo *compptr; int Pr,Pt,diff; Pr=cPtr->dataPrecision; Pt=cPtr->Pt; compsInScan=cPtr->compsInScan; numCOL=cPtr->imageWidth; /* * At the start of the scan or at the beginning of restart interval, * 1<<(Pr-Pt-1) is the predictor. */ for (curComp = 0; curComp < compsInScan; curComp++) { ci = cPtr->MCUmembership[curComp]; compptr = cPtr->curCompInfo[ci]; diff = curRowBuf[0][curComp] - (1<<(Pr-Pt-1)); EncodeOneDiff(diff,cPtr->dcHuffTblPtrs[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]; diff = curRowBuf[col][curComp]-curRowBuf[col-1][curComp]; EncodeOneDiff (diff, cPtr->dcHuffTblPtrs[compptr->dcTblNo]); } } if (cPtr->restartInRows) { cPtr->restartRowsToGo--; }}/* *-------------------------------------------------------------- * * HuffEncode -- * * Encode and output Huffman-compressed image data. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */voidHuffEncode (cPtr) CompressInfo * cPtr;{ register short curComp, ci; register int col,row; register JpegComponentInfo *compptr; register int diff; int predictor; int numCOL,numROW,compsInScan; MCU *prevRowBuf,*curRowBuf,*tempRowBuf; int psv; numCOL=cPtr->imageWidth; numROW=cPtr->imageHeight; compsInScan=cPtr->compsInScan; psv=cPtr->Ss; prevRowBuf=NULL; curRowBuf=mcuTable; EncodeFirstRow(cPtr,curRowBuf); prevRowBuf=curRowBuf; curRowBuf+=numCOL; for (row=1; row<numROW; row++) { if (cPtr->restartInRows) { if (cPtr->restartRowsToGo == 0) { EmitRestart (cPtr); EncodeFirstRow(cPtr,curRowBuf); prevRowBuf=curRowBuf; curRowBuf+=numCOL; continue; } cPtr->restartRowsToGo--; } /* * In the first column, the upper neighboring pixel * is the predictor. */ for (curComp = 0; curComp < compsInScan; curComp++) { ci = cPtr->MCUmembership[curComp]; compptr = cPtr->curCompInfo[ci]; diff = curRowBuf[0][curComp]-prevRowBuf[0][curComp]; EncodeOneDiff (diff, cPtr->dcHuffTblPtrs[compptr->dcTblNo]); } /* * In the rest of the column on this row, predictor is * calculated according to psv. */ for (col=1; col<numCOL; col++) { for (curComp = 0; curComp < compsInScan; curComp++) { ci = cPtr->MCUmembership[curComp]; compptr = cPtr->curCompInfo[ci]; QuickPredict(col,curComp,curRowBuf,prevRowBuf,psv,&predictor); diff=curRowBuf[col][curComp]-predictor; EncodeOneDiff (diff, cPtr->dcHuffTblPtrs[compptr->dcTblNo]); } } prevRowBuf=curRowBuf; curRowBuf+=numCOL; }}/* *--------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -