about summary refs log tree commit diff
path: root/converter/ppm/ppmtompeg/rgbtoycc.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/ppm/ppmtompeg/rgbtoycc.c')
-rw-r--r--converter/ppm/ppmtompeg/rgbtoycc.c204
1 files changed, 204 insertions, 0 deletions
diff --git a/converter/ppm/ppmtompeg/rgbtoycc.c b/converter/ppm/ppmtompeg/rgbtoycc.c
new file mode 100644
index 00000000..766b8902
--- /dev/null
+++ b/converter/ppm/ppmtompeg/rgbtoycc.c
@@ -0,0 +1,204 @@
+/*===========================================================================*
+ * rgbtoycc.c                                    *
+ *                                       *
+ *  Procedures to convert from RGB space to YUV space            *
+ *                                       *
+ * EXPORTED PROCEDURES:                              *
+ *  PNMtoYUV                                 *
+ *  PPMtoYUV                                 *
+ *                                       *
+ *===========================================================================*/
+
+/*
+ * 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 FILES *
+ *==============*/
+
+#include "pnm.h"
+#include "all.h"
+#include "frame.h"
+#include "rgbtoycc.h"
+
+
+static float *mult299, *mult587, *mult114, *mult16874, *mult33126,
+    *mult5, *mult41869, *mult08131;  /* malloc'ed */
+    /* These are tables we use for fast arithmetic */
+static pixval table_maxval = 0;
+    /* The maxval used to compute the above arrays.  Zero means
+       the above arrays don't exist yet
+    */
+
+static void
+compute_mult_tables(const pixval maxval) {
+
+    /* For speed, we do the arithmetic with eight tables that reduce a
+       bunch of multiplications and divisions to a simple table lookup.
+       
+       Because a large maxval could require a significant amount of
+       table space, we allocate the space dynamically.
+
+       If we had to compute the tables for every frame, it wouldn't be 
+       fast at all, but since all the frames normally have the same
+       maxval, we only need to compute them once.  But just in case,
+       we check each frame to see if it has a different maxval and
+       recompute the tables if so.
+    */
+    
+    if (table_maxval != maxval) {
+        /* We need to compute or re-compute the multiplication tables */
+        if (table_maxval != 0) {
+            free(mult299); free(mult587); free(mult114); free(mult16874);
+            free(mult33126); free(mult5); free(mult41869); free(mult08131);  
+        } 
+        table_maxval = maxval;
+
+        mult299   = malloc((table_maxval+1)*sizeof(float));
+        mult587   = malloc((table_maxval+1)*sizeof(float));
+        mult114   = malloc((table_maxval+1)*sizeof(float));
+        mult16874 = malloc((table_maxval+1)*sizeof(float));
+        mult33126 = malloc((table_maxval+1)*sizeof(float));
+        mult5     = malloc((table_maxval+1)*sizeof(float));
+        mult41869 = malloc((table_maxval+1)*sizeof(float));
+        mult08131 = malloc((table_maxval+1)*sizeof(float));
+
+        if (mult299 == NULL || mult587 == NULL || mult114 == NULL ||
+            mult16874 == NULL || mult33126 == NULL || mult5 == NULL ||
+            mult41869 == NULL || mult08131 == NULL) 
+            pm_error("Unable to allocate storage for arithmetic tables.\n"
+                     "We need %d bytes, which is the maxval of the input "
+                     "image, plus 1,\n"
+                     "times the storage size of a floating point value.", 
+                     8 * (table_maxval+1)*sizeof(float));
+
+        {
+            int index;
+
+            for (index = 0; index <= table_maxval; index++ ) {
+                mult299[index]   = index*0.29900  * 255 / table_maxval; 
+                mult587[index]   = index*0.58700  * 255 / table_maxval;
+                mult114[index]   = index*0.11400  * 255 / table_maxval;
+                mult16874[index] = -0.16874*index * 255 / table_maxval;
+                mult33126[index] = -0.33126*index * 255 / table_maxval;
+                mult5[index]     = index*0.50000  * 255 / table_maxval;
+                mult41869[index] = -0.41869*index * 255 / table_maxval;
+                mult08131[index] = -0.08131*index * 255 / table_maxval;
+            }
+        }
+    }
+}
+
+
+/*=====================*
+ * EXPORTED PROCEDURES *
+ *=====================*/
+
+
+void
+PNMtoYUV(MpegFrame *  const frameP,
+         xel **       const xels,
+         unsigned int const cols,
+         unsigned int const rows,
+         xelval       const maxval) {
+/*----------------------------------------------------------------------------
+   Set the raster of the MPEG frame *frameP from the libnetpbm input
+   'xels'.  Note that the raster information in a MpegFrame is in YUV
+   form.
+-----------------------------------------------------------------------------*/
+    int x, y;
+    uint8 *dy0, *dy1;
+    uint8 *dcr, *dcb;
+    pixel *src0, *src1;
+
+    compute_mult_tables(maxval);  /* This sets up mult299[], etc. */
+
+    Frame_AllocYCC(frameP);
+
+    /*
+     * okay.  Now, convert everything into YCbCr space. (the specific
+     * numbers come from the JPEG source, jccolor.c) The conversion
+     * equations to be implemented are therefore
+     *
+     * Y  =  0.29900 * R + 0.58700 * G + 0.11400 * B
+     * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B
+     * Cr =  0.50000 * R - 0.41869 * G - 0.08131 * B
+     *
+     * With Y, Cb, and Cr then normalized to the range 0 - 255.
+     */
+
+    for (y = 0; y < rows; y += 2) {
+        for (x = 0, src0 = xels[y], src1 = xels[y + 1],
+                 dy0 = frameP->orig_y[y], dy1 = frameP->orig_y[y + 1],
+                 dcr = frameP->orig_cr[y >> 1], dcb = frameP->orig_cb[y >> 1];
+             x < cols;
+             x += 2, dy0 += 2, dy1 += 2, dcr++,
+                 dcb++, src0 += 2, src1 += 2) {
+
+            *dy0 = (mult299[PPM_GETR(*src0)] +
+                    mult587[PPM_GETG(*src0)] +
+                    mult114[PPM_GETB(*src0)]);
+
+            *dy1 = (mult299[PPM_GETR(*src1)] +
+                    mult587[PPM_GETG(*src1)] +
+                    mult114[PPM_GETB(*src1)]);
+
+            dy0[1] = (mult299[PPM_GETR(src0[1])] +
+                      mult587[PPM_GETG(src0[1])] +
+                      mult114[PPM_GETB(src0[1])]);
+
+            dy1[1] = (mult299[PPM_GETR(src1[1])] +
+                      mult587[PPM_GETG(src1[1])] +
+                      mult114[PPM_GETB(src1[1])]);
+
+            *dcb = ((mult16874[PPM_GETR(*src0)] +
+                     mult33126[PPM_GETG(*src0)] +
+                     mult5[PPM_GETB(*src0)] +
+                     mult16874[PPM_GETR(*src1)] +
+                     mult33126[PPM_GETG(*src1)] +
+                     mult5[PPM_GETB(*src1)] +
+                     mult16874[PPM_GETR(src0[1])] +
+                     mult33126[PPM_GETG(src0[1])] +
+                     mult5[PPM_GETB(src0[1])] +
+                     mult16874[PPM_GETR(src1[1])] +
+                     mult33126[PPM_GETG(src1[1])] +
+                     mult5[PPM_GETB(src1[1])]) / 4) + 128;
+
+            *dcr = ((mult5[PPM_GETR(*src0)] +
+                     mult41869[PPM_GETG(*src0)] +
+                     mult08131[PPM_GETB(*src0)] +
+                     mult5[PPM_GETR(*src1)] +
+                     mult41869[PPM_GETG(*src1)] +
+                     mult08131[PPM_GETB(*src1)] +
+                     mult5[PPM_GETR(src0[1])] +
+                     mult41869[PPM_GETG(src0[1])] +
+                     mult08131[PPM_GETB(src0[1])] +
+                     mult5[PPM_GETR(src1[1])] +
+                     mult41869[PPM_GETG(src1[1])] +
+                     mult08131[PPM_GETB(src1[1])]) / 4) + 128;
+
+            DBG_PRINT(("%3d,%3d: (%3d,%3d,%3d) --> (%3d,%3d,%3d)\n", 
+                       x, y, 
+                       PPM_GETR(*src0), PPM_GETG(*src0), PPM_GETB(*src0), 
+                       *dy0, *dcb, *dcr));
+        }
+    }
+}