about summary refs log tree commit diff
path: root/converter/ppm/ppmtompeg/moutput.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/ppm/ppmtompeg/moutput.c')
-rw-r--r--converter/ppm/ppmtompeg/moutput.c442
1 files changed, 442 insertions, 0 deletions
diff --git a/converter/ppm/ppmtompeg/moutput.c b/converter/ppm/ppmtompeg/moutput.c
new file mode 100644
index 00000000..b682efab
--- /dev/null
+++ b/converter/ppm/ppmtompeg/moutput.c
@@ -0,0 +1,442 @@
+/*===========================================================================*
+ * moutput.c								     *
+ *									     *
+ *	Procedures concerned with quantization and RLE			     *
+ *									     *
+ * EXPORTED PROCEDURES:							     *
+ *	mp_quant_zig_block						     *
+ *	mp_rle_huff_block						     *
+ *	mp_rle_huff_pblock						     *
+ *									     *
+ *===========================================================================*/
+
+/*
+ * Copyright (c) 1995 The Regents of the University of California.
+ * 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 THE UNIVERSITY OF CALIFORNIA 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 THE UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE UNIVERSITY OF CALIFORNIA 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 THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+/*
+ *  $Header: /n/charlie-brown/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/moutput.c,v 1.12 1995/01/19 23:08:49 eyhung Exp $
+ *  $Log: moutput.c,v $
+ * Revision 1.12  1995/01/19  23:08:49  eyhung
+ * Changed copyrights
+ *
+ * Revision 1.11  1993/07/22  22:23:43  keving
+ * nothing
+ *
+ * Revision 1.10  1993/06/30  20:06:09  keving
+ * nothing
+ *
+ * Revision 1.9  1993/06/03  21:08:08  keving
+ * nothing
+ *
+ * Revision 1.8  1993/02/24  18:57:19  keving
+ * nothing
+ *
+ * Revision 1.7  1993/02/23  22:58:36  keving
+ * nothing
+ *
+ * Revision 1.6  1993/02/23  22:54:56  keving
+ * nothing
+ *
+ * Revision 1.5  1993/02/17  23:18:20  dwallach
+ * checkin prior to keving's joining the project
+ *
+ * Revision 1.4  1993/01/18  10:20:02  dwallach
+ * *** empty log message ***
+ *
+ * Revision 1.3  1993/01/18  10:17:29  dwallach
+ * RCS headers installed, code indented uniformly
+ *
+ * Revision 1.3  1993/01/18  10:17:29  dwallach
+ * RCS headers installed, code indented uniformly
+ *
+ */
+
+
+/*==============*
+ * HEADER FILES *
+ *==============*/
+
+#include "all.h"
+#include "mtypes.h"
+#include "mproto.h"
+#include "huff.h"
+
+
+/*==================*
+ * STATIC VARIABLES *
+ *==================*/
+
+/* ZAG[i] is the natural-order position of the i'th element of zigzag order. */
+static int ZAG[] =
+{
+    0, 1, 8, 16, 9, 2, 3, 10,
+    17, 24, 32, 25, 18, 11, 4, 5,
+    12, 19, 26, 33, 40, 48, 41, 34,
+    27, 20, 13, 6, 7, 14, 21, 28,
+    35, 42, 49, 56, 57, 50, 43, 36,
+    29, 22, 15, 23, 30, 37, 44, 51,
+    58, 59, 52, 45, 38, 31, 39, 46,
+    53, 60, 61, 54, 47, 55, 62, 63
+};
+
+
+/*
+ * possible optimization: reorder the qtable in the correct zigzag order, to
+ * reduce the number of necessary lookups
+ *
+ * this table comes from the MPEG draft, p. D-16, Fig. 2-D.15.
+ */
+static int qtable[] =
+{
+    8, 16, 19, 22, 26, 27, 29, 34,
+    16, 16, 22, 24, 27, 29, 34, 37,
+    19, 22, 26, 27, 29, 34, 34, 38,
+    22, 22, 26, 27, 29, 34, 37, 40,
+    22, 26, 27, 29, 32, 35, 40, 48,
+    26, 27, 29, 32, 35, 40, 48, 58,
+    26, 27, 29, 34, 38, 46, 56, 69,
+    27, 29, 35, 38, 46, 56, 69, 83};
+
+
+/*=====================*
+ * EXPORTED PROCEDURES *
+ *=====================*/
+
+
+void	UnQuantZig(FlatBlock in, Block out, int qscale, boolean iblock)
+{
+    register int index;
+    int	    start;
+    int	    position;
+    register int	    qentry;
+    int	    level, coeff;
+    register int16 temp;
+
+    if ( iblock )
+    {
+	((int16 *)out)[0] = (int16)(in[0]*qtable[0]);
+
+	start = 1;
+    }
+    else
+	start = 0;
+
+    for ( index = start; index < DCTSIZE_SQ; index++ )
+    {
+	position = ZAG[index];
+
+	if (iblock)
+	    qentry = qtable[position] * qscale;
+	else
+	    qentry = 16 * qscale;
+
+	level = in[index];
+        coeff = (level * qentry) >> 3;
+        if (level < 0) {
+            coeff += (coeff & 1);
+	} else {
+            coeff -= (coeff & 1);
+	}
+
+	((int16 *)out)[position] = coeff;
+    }
+
+#ifdef BLEAH
+    for ( index = 0; index < 64; index++ )
+	fprintf(stdout, "DCT[%d] = %d\n", index, 
+		((int16 *)out)[index]);
+#endif
+}
+
+
+/*
+ * --------------------------------------------------------------
+ *
+ * mp_quant_zig_block --
+ *
+ * Quantizes and zigzags a block -- removing information
+ *
+ * Results: TRUE iff resulting 'out' is non-zero, FALSE if all
+ *	    zero
+ *
+ * Side effects: Modifies the out block.
+ *
+ * --------------------------------------------------------------
+ */
+boolean mp_quant_zig_block(Block in, FlatBlock out, int qscale, int iblock)
+{
+    register int i;
+    register int y, x;
+    register int16 temp;
+    register int qentry;
+    int start;
+    boolean nonZero = FALSE;
+
+    DBG_PRINT(("mp_quant_zig_block...\n"));
+    if (iblock) {
+	/*
+	 * the DC coefficient is handled specially -- it's not
+	 * sensitive to qscale, but everything else is
+	 */
+	temp = ((int16 *) in)[ZAG[0]];
+	qentry = qtable[ZAG[0]];
+	if (temp < 0) {
+	    temp = -temp;
+	    temp += qentry >> 1;
+	    temp /= qentry;
+	    temp = -temp;
+	} else {
+	    temp += qentry >> 1;
+	    temp /= qentry;
+	}
+	if ( temp != 0 )
+	    nonZero = TRUE;
+	out[0] = temp;
+	start = 1;
+    } else
+	start = 0;
+
+    for (i = start; i < DCTSIZE_SQ; i++) {
+	x = ZAG[i] % 8;
+	y = ZAG[i] / 8;
+	temp = in[y][x];
+	DBG_PRINT(("    in[%d][%d] = %d;  ", y, x, temp));
+
+	if (iblock)
+	    qentry = qtable[ZAG[i]] * qscale;
+	else
+	    qentry = 16 * qscale;
+
+	DBG_PRINT(("quantized with %d = ", qentry));
+
+	if (temp < 0) {
+	    temp = -temp;
+	    temp *= 8;
+	    temp += qentry >> 1;
+	    temp /= qentry;
+	    temp = -temp;
+	} else {
+	    temp *= 8;
+	    temp += qentry >> 1;
+	    temp /= qentry;
+	}
+	if ( temp != 0 )
+	    nonZero = TRUE;
+	out[i] = temp;
+	DBG_PRINT(("%d\n", temp));
+    }
+
+    return nonZero;
+}
+
+
+
+/*
+ * --------------------------------------------------------------
+ *
+ * mp_rle_huff_block --
+ *
+ * Given a FlatBlock, generates the Huffman bits
+ *
+ * Results: None.
+ *
+ * Side effects: Output bits changed
+ *
+ * --------------------------------------------------------------
+ */
+
+void	mp_rle_huff_block(FlatBlock in, BitBucket *out)
+{
+    register int i;
+    register int nzeros = 0;
+    register int16 cur;
+    register int16 acur;
+    register uint32 code;
+    register int nbits;
+
+    /*
+     * yes, Virginia, we start at 1.  The DC coefficient is handled
+     * specially, elsewhere.  Not here.
+     */
+    for (i = 1; i < DCTSIZE_SQ; i++) {
+	cur = in[i];
+	acur = ABS(cur);
+	if (cur) {
+	    if (nzeros < HUFF_MAXRUN && acur < huff_maxlevel[nzeros]) {
+	        /*
+		 * encode using the Huffman tables
+		 */
+
+		DBG_PRINT(("rle_huff %02d: Run %02d, Level %02d\n", i, nzeros, cur));
+		assert(cur);
+
+		code = (huff_table[nzeros])[acur];
+		nbits = (huff_bits[nzeros])[acur];
+
+		assert(nbits);
+
+		if (cur < 0)
+		    code |= 1;	/* the sign bit */
+		Bitio_Write(out, code, nbits);
+	    } else {
+		/*
+		 * encode using the escape code
+		 */
+		DBG_PRINT(("Escape\n"));
+		Bitio_Write(out, 0x1, 6);	/* ESCAPE */
+		DBG_PRINT(("Run Length\n"));
+		Bitio_Write(out, nzeros, 6);	/* Run-Length */
+
+		assert(cur != 0);
+
+		/*
+	         * this shouldn't happen, but the other
+	         * choice is to bomb out and dump core...
+	         */
+		if (cur < -255)
+		    cur = -255;
+		else if (cur > 255)
+		    cur = 255;
+
+		DBG_PRINT(("Level\n"));
+		if (acur < 128) {
+		    Bitio_Write(out, cur, 8);
+		} else {
+		    if (cur < 0) {
+			Bitio_Write(out, 0x8001 + cur + 255, 16);
+		    } else
+			Bitio_Write(out, cur, 16);
+		}
+	    }
+	    nzeros = 0;
+	} else
+	    nzeros++;
+    }
+    DBG_PRINT(("End of block\n"));
+    Bitio_Write(out, 0x2, 2);	/* end of block marker */
+}
+
+
+/*
+ * --------------------------------------------------------------
+ *
+ * mp_rle_huff_pblock --
+ *
+ * Given a FlatBlock, generates the Huffman bits for P DCT
+ *
+ * Results: None.
+ *
+ * Side effects: Output bits changed
+ *
+ * --------------------------------------------------------------
+ */
+
+void	mp_rle_huff_pblock(FlatBlock in, BitBucket *out)
+{
+    register int i;
+    register int nzeros = 0;
+    register int16 cur;
+    register int16 acur;
+    register uint32 code;
+    register int nbits;
+    boolean first_dct = TRUE;
+
+    /*
+     * yes, Virginia, we start at 0.
+     */
+    for (i = 0; i < DCTSIZE_SQ; i++) {
+	cur = in[i];
+	acur = ABS(cur);
+	if (cur) {
+	    if (nzeros < HUFF_MAXRUN && acur < huff_maxlevel[nzeros]) {
+	        /*
+		 * encode using the Huffman tables
+		 */
+
+		DBG_PRINT(("rle_huff %02d: Run %02d, Level %02d\n", i, nzeros, cur));
+		assert(cur);
+
+		if ( first_dct && (nzeros == 0) && (acur == 1) )
+		{
+		    /* actually, only needs = 0x2 */
+		    code = (cur == 1) ? 0x2 : 0x3;
+		    nbits = 2;
+		}
+		else
+		{
+		    code = (huff_table[nzeros])[acur];
+		    nbits = (huff_bits[nzeros])[acur];
+		}
+
+		assert(nbits);
+
+		if (cur < 0)
+		    code |= 1;	/* the sign bit */
+		Bitio_Write(out, code, nbits);
+		first_dct = FALSE;
+	    } else {
+		/*
+		 * encode using the escape code
+		 */
+		DBG_PRINT(("Escape\n"));
+		Bitio_Write(out, 0x1, 6);	/* ESCAPE */
+		DBG_PRINT(("Run Length\n"));
+		Bitio_Write(out, nzeros, 6);	/* Run-Length */
+
+		assert(cur != 0);
+
+		/*
+	         * this shouldn't happen, but the other
+	         * choice is to bomb out and dump core...
+	         */
+		if (cur < -255)
+		    cur = -255;
+		else if (cur > 255)
+		    cur = 255;
+
+		DBG_PRINT(("Level\n"));
+		if (acur < 128) {
+		    Bitio_Write(out, cur, 8);
+		} else {
+		    if (cur < 0) {
+			Bitio_Write(out, 0x8001 + cur + 255, 16);
+		    } else
+			Bitio_Write(out, cur, 16);
+		}
+
+		first_dct = FALSE;
+	    }
+	    nzeros = 0;
+	} else
+	    nzeros++;
+    }
+
+    /* actually, should REALLY return FALSE and not use this! */
+    if ( first_dct )	/* have to give a first_dct even if all 0's */
+    {
+	fprintf(stdout, "HUFF called with all-zero coefficients\n");
+	fprintf(stdout, "exiting...\n");
+	exit(1);
+    }
+
+    DBG_PRINT(("End of block\n"));
+    Bitio_Write(out, 0x2, 2);	/* end of block marker */
+}