Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

moutput.c

Go to the documentation of this file.
00001 /*===========================================================================*
00002  * moutput.c                                                                 *
00003  *                                                                           *
00004  *      Procedures concerned with quantization and RLE                       *
00005  *                                                                           *
00006  * EXPORTED PROCEDURES:                                                      *
00007  *      mp_quant_zig_block                                                   *
00008  *      mp_rle_huff_block                                                    *
00009  *      mp_rle_huff_pblock                                                   *
00010  *                                                                           *
00011  *===========================================================================*/
00012 
00013 /*
00014  * Copyright (c) 1995 The Regents of the University of California.
00015  * All rights reserved.
00016  *
00017  * Permission to use, copy, modify, and distribute this software and its
00018  * documentation for any purpose, without fee, and without written agreement is
00019  * hereby granted, provided that the above copyright notice and the following
00020  * two paragraphs appear in all copies of this software.
00021  *
00022  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
00023  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
00024  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
00025  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  *
00027  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
00028  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00029  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
00030  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
00031  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
00032  */
00033 
00034 /*
00035  *  $Header: /misc/elrond0/share/cvs/AFNI/src/mpeg_encodedir/moutput.c,v 1.4 2004/04/02 15:12:40 rwcox Exp $
00036  *  $Log: moutput.c,v $
00037  *  Revision 1.4  2004/04/02 15:12:40  rwcox
00038  *  Cput
00039  *
00040  *  Revision 1.3  2003/12/23 13:50:08  rwcox
00041  *  Cput
00042  *
00043  *  Revision 1.2  2003/12/03 14:46:14  rwcox
00044  *  Cput
00045  *
00046  *  Revision 1.1  2001/12/17 16:11:54  rwcox
00047  *  Cadd
00048  *
00049  * Revision 1.12  1995/01/19  23:08:49  eyhung
00050  * Changed copyrights
00051  *
00052  * Revision 1.11  1993/07/22  22:23:43  keving
00053  * nothing
00054  *
00055  * Revision 1.10  1993/06/30  20:06:09  keving
00056  * nothing
00057  *
00058  * Revision 1.9  1993/06/03  21:08:08  keving
00059  * nothing
00060  *
00061  * Revision 1.8  1993/02/24  18:57:19  keving
00062  * nothing
00063  *
00064  * Revision 1.7  1993/02/23  22:58:36  keving
00065  * nothing
00066  *
00067  * Revision 1.6  1993/02/23  22:54:56  keving
00068  * nothing
00069  *
00070  * Revision 1.5  1993/02/17  23:18:20  dwallach
00071  * checkin prior to keving's joining the project
00072  *
00073  * Revision 1.4  1993/01/18  10:20:02  dwallach
00074  * *** empty log message ***
00075  *
00076  * Revision 1.3  1993/01/18  10:17:29  dwallach
00077  * RCS headers installed, code indented uniformly
00078  *
00079  * Revision 1.3  1993/01/18  10:17:29  dwallach
00080  * RCS headers installed, code indented uniformly
00081  *
00082  */
00083 
00084 
00085 /*==============*
00086  * HEADER FILES *
00087  *==============*/
00088 
00089 #include "all.h"
00090 #include "mtypes.h"
00091 #include "mproto.h"
00092 #include "huff.h"
00093 
00094 
00095 /*==================*
00096  * STATIC VARIABLES *
00097  *==================*/
00098 
00099 /* ZAG[i] is the natural-order position of the i'th element of zigzag order. */
00100 static int ZAG[] =
00101 {
00102     0, 1, 8, 16, 9, 2, 3, 10,
00103     17, 24, 32, 25, 18, 11, 4, 5,
00104     12, 19, 26, 33, 40, 48, 41, 34,
00105     27, 20, 13, 6, 7, 14, 21, 28,
00106     35, 42, 49, 56, 57, 50, 43, 36,
00107     29, 22, 15, 23, 30, 37, 44, 51,
00108     58, 59, 52, 45, 38, 31, 39, 46,
00109     53, 60, 61, 54, 47, 55, 62, 63
00110 };
00111 
00112 
00113 /*
00114  * possible optimization: reorder the qtable in the correct zigzag order, to
00115  * reduce the number of necessary lookups
00116  *
00117  * this table comes from the MPEG draft, p. D-16, Fig. 2-D.15.
00118  */
00119 static int qtable[] =
00120 {
00121     8, 16, 19, 22, 26, 27, 29, 34,
00122     16, 16, 22, 24, 27, 29, 34, 37,
00123     19, 22, 26, 27, 29, 34, 34, 38,
00124     22, 22, 26, 27, 29, 34, 37, 40,
00125     22, 26, 27, 29, 32, 35, 40, 48,
00126     26, 27, 29, 32, 35, 40, 48, 58,
00127     26, 27, 29, 34, 38, 46, 56, 69,
00128     27, 29, 35, 38, 46, 56, 69, 83};
00129 
00130 
00131 /*=====================*
00132  * EXPORTED PROCEDURES *
00133  *=====================*/
00134 
00135 
00136 void    UnQuantZig(FlatBlock in, Block out, int qscale, boolean iblock)
00137 {
00138     register int index;
00139     int     start;
00140     int     position;
00141     register int            qentry;
00142     int     level, coeff;
00143     register int16 temp;
00144 
00145     if ( iblock )
00146     {
00147         ((int16 *)out)[0] = (int16)(in[0]*qtable[0]);
00148 
00149         start = 1;
00150     }
00151     else
00152         start = 0;
00153 
00154     for ( index = start; index < DCTSIZE_SQ; index++ )
00155     {
00156         position = ZAG[index];
00157 
00158         if (iblock)
00159             qentry = qtable[position] * qscale;
00160         else
00161             qentry = 16 * qscale;
00162 
00163         level = in[index];
00164         coeff = (level * qentry) >> 3;
00165         if (level < 0) {
00166             coeff += (coeff & 1);
00167         } else {
00168             coeff -= (coeff & 1);
00169         }
00170 
00171         ((int16 *)out)[position] = coeff;
00172     }
00173 
00174 #ifdef BLEAH
00175     for ( index = 0; index < 64; index++ )
00176         fprintf(stdout, "DCT[%d] = %d\n", index, 
00177                 ((int16 *)out)[index]);
00178 #endif
00179 }
00180 
00181 
00182 /*
00183  * --------------------------------------------------------------
00184  *
00185  * mp_quant_zig_block --
00186  *
00187  * Quantizes and zigzags a block -- removing information
00188  *
00189  * Results: TRUE iff resulting 'out' is non-zero, FALSE if all
00190  *          zero
00191  *
00192  * Side effects: Modifies the out block.
00193  *
00194  * --------------------------------------------------------------
00195  */
00196 boolean mp_quant_zig_block(Block in, FlatBlock out, int qscale, int iblock)
00197 {
00198     register int i;
00199     register int y, x;
00200     register int16 temp;
00201     register int qentry;
00202     int start;
00203     boolean nonZero = FALSE;
00204 
00205     DBG_PRINT(("mp_quant_zig_block...\n"));
00206     if (iblock) {
00207         /*
00208          * the DC coefficient is handled specially -- it's not
00209          * sensitive to qscale, but everything else is
00210          */
00211         temp = ((int16 *) in)[ZAG[0]];
00212         qentry = qtable[ZAG[0]];
00213         if (temp < 0) {
00214             temp = -temp;
00215             temp += qentry >> 1;
00216             temp /= qentry;
00217             temp = -temp;
00218         } else {
00219             temp += qentry >> 1;
00220             temp /= qentry;
00221         }
00222         if ( temp != 0 )
00223             nonZero = TRUE;
00224         out[0] = temp;
00225         start = 1;
00226     } else
00227         start = 0;
00228 
00229     for (i = start; i < DCTSIZE_SQ; i++) {
00230         x = ZAG[i] % 8;
00231         y = ZAG[i] / 8;
00232         temp = in[y][x];
00233         DBG_PRINT(("    in[%d][%d] = %d;  ", y, x, temp));
00234 
00235         if (iblock)
00236             qentry = qtable[ZAG[i]] * qscale;
00237         else
00238             qentry = 16 * qscale;
00239 
00240         DBG_PRINT(("quantized with %d = ", qentry));
00241 
00242         if (temp < 0) {
00243             temp = -temp;
00244             temp *= 8;
00245             temp += qentry >> 1;
00246             temp /= qentry;
00247             temp = -temp;
00248         } else {
00249             temp *= 8;
00250             temp += qentry >> 1;
00251             temp /= qentry;
00252         }
00253         if ( temp != 0 )
00254             nonZero = TRUE;
00255         out[i] = temp;
00256         DBG_PRINT(("%d\n", temp));
00257     }
00258 
00259     return nonZero;
00260 }
00261 
00262 
00263 
00264 /*
00265  * --------------------------------------------------------------
00266  *
00267  * mp_rle_huff_block --
00268  *
00269  * Given a FlatBlock, generates the Huffman bits
00270  *
00271  * Results: None.
00272  *
00273  * Side effects: Output bits changed
00274  *
00275  * --------------------------------------------------------------
00276  */
00277 
00278 void    mp_rle_huff_block(FlatBlock in, BitBucket *out)
00279 {
00280     register int i;
00281     register int nzeros = 0;
00282     register int16 cur;
00283     register int16 acur;
00284     register uint32 code;
00285     register int nbits;
00286 
00287     /*
00288      * yes, Virginia, we start at 1.  The DC coefficient is handled
00289      * specially, elsewhere.  Not here.
00290      */
00291     for (i = 1; i < DCTSIZE_SQ; i++) {
00292         cur = in[i];
00293         acur = ABS(cur);
00294         if (cur) {
00295             if (nzeros < HUFF_MAXRUN && acur < huff_maxlevel[nzeros]) {
00296                 /*
00297                  * encode using the Huffman tables
00298                  */
00299 
00300                 DBG_PRINT(("rle_huff %02d: Run %02d, Level %02d\n", i, nzeros, cur));
00301                 assert(cur);
00302 
00303                 code = (huff_table[nzeros])[acur];
00304                 nbits = (huff_bits[nzeros])[acur];
00305 
00306                 assert(nbits);
00307 
00308                 if (cur < 0)
00309                     code |= 1;  /* the sign bit */
00310                 Bitio_Write(out, code, nbits);
00311             } else {
00312                 /*
00313                  * encode using the escape code
00314                  */
00315                 DBG_PRINT(("Escape\n"));
00316                 Bitio_Write(out, 0x1, 6);       /* ESCAPE */
00317                 DBG_PRINT(("Run Length\n"));
00318                 Bitio_Write(out, nzeros, 6);    /* Run-Length */
00319 
00320                 assert(cur != 0);
00321 
00322                 /*
00323                  * this shouldn't happen, but the other
00324                  * choice is to bomb out and dump core...
00325                  */
00326                 if (cur < -255)
00327                     cur = -255;
00328                 else if (cur > 255)
00329                     cur = 255;
00330 
00331                 DBG_PRINT(("Level\n"));
00332                 if (acur < 128) {
00333                     Bitio_Write(out, cur, 8);
00334                 } else {
00335                     if (cur < 0) {
00336                         Bitio_Write(out, 0x8001 + cur + 255, 16);
00337                     } else
00338                         Bitio_Write(out, cur, 16);
00339                 }
00340             }
00341             nzeros = 0;
00342         } else
00343             nzeros++;
00344     }
00345     DBG_PRINT(("End of block\n"));
00346     Bitio_Write(out, 0x2, 2);   /* end of block marker */
00347 }
00348 
00349 
00350 /*
00351  * --------------------------------------------------------------
00352  *
00353  * mp_rle_huff_pblock --
00354  *
00355  * Given a FlatBlock, generates the Huffman bits for P DCT
00356  *
00357  * Results: None.
00358  *
00359  * Side effects: Output bits changed
00360  *
00361  * --------------------------------------------------------------
00362  */
00363 
00364 void    mp_rle_huff_pblock(FlatBlock in, BitBucket *out)
00365 {
00366     register int i;
00367     register int nzeros = 0;
00368     register int16 cur;
00369     register int16 acur;
00370     register uint32 code;
00371     register int nbits;
00372     boolean first_dct = TRUE;
00373 
00374     /*
00375      * yes, Virginia, we start at 0.
00376      */
00377     for (i = 0; i < DCTSIZE_SQ; i++) {
00378         cur = in[i];
00379         acur = ABS(cur);
00380         if (cur) {
00381             if (nzeros < HUFF_MAXRUN && acur < huff_maxlevel[nzeros]) {
00382                 /*
00383                  * encode using the Huffman tables
00384                  */
00385 
00386                 DBG_PRINT(("rle_huff %02d: Run %02d, Level %02d\n", i, nzeros, cur));
00387                 assert(cur);
00388 
00389                 if ( first_dct && (nzeros == 0) && (acur == 1) )
00390                 {
00391                     /* actually, only needs = 0x2 */
00392                     code = (cur == 1) ? 0x2 : 0x3;
00393                     nbits = 2;
00394                 }
00395                 else
00396                 {
00397                     code = (huff_table[nzeros])[acur];
00398                     nbits = (huff_bits[nzeros])[acur];
00399                 }
00400 
00401                 assert(nbits);
00402 
00403                 if (cur < 0)
00404                     code |= 1;  /* the sign bit */
00405                 Bitio_Write(out, code, nbits);
00406                 first_dct = FALSE;
00407             } else {
00408                 /*
00409                  * encode using the escape code
00410                  */
00411                 DBG_PRINT(("Escape\n"));
00412                 Bitio_Write(out, 0x1, 6);       /* ESCAPE */
00413                 DBG_PRINT(("Run Length\n"));
00414                 Bitio_Write(out, nzeros, 6);    /* Run-Length */
00415 
00416                 assert(cur != 0);
00417 
00418                 /*
00419                  * this shouldn't happen, but the other
00420                  * choice is to bomb out and dump core...
00421                  */
00422                 if (cur < -255)
00423                     cur = -255;
00424                 else if (cur > 255)
00425                     cur = 255;
00426 
00427                 DBG_PRINT(("Level\n"));
00428                 if (acur < 128) {
00429                     Bitio_Write(out, cur, 8);
00430                 } else {
00431                     if (cur < 0) {
00432                         Bitio_Write(out, 0x8001 + cur + 255, 16);
00433                     } else
00434                         Bitio_Write(out, cur, 16);
00435                 }
00436 
00437                 first_dct = FALSE;
00438             }
00439             nzeros = 0;
00440         } else
00441             nzeros++;
00442     }
00443 
00444     /* actually, should REALLY return FALSE and not use this! */
00445     if ( first_dct )    /* have to give a first_dct even if all 0's */
00446     {
00447         fprintf(stdout, "HUFF called with all-zero coefficients\n");
00448         fprintf(stdout, "exiting...\n");
00449         exit(1);
00450     }
00451 
00452     DBG_PRINT(("End of block\n"));
00453     Bitio_Write(out, 0x2, 2);   /* end of block marker */
00454 }
 

Powered by Plone

This site conforms to the following standards: