diff options
Diffstat (limited to 'converter/ppm/ppmtompeg/moutput.c')
-rw-r--r-- | converter/ppm/ppmtompeg/moutput.c | 442 |
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 */ +} |