⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 huffc.c

📁 很好的JPEG图象解码器,基于VC环境开发。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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 + -