pixmap.[ch], Modules.am: provisional routine to find closest colormap
authorRocky Bernstein <rocky@videolan.org>
Fri, 30 Jan 2004 13:17:12 +0000 (13:17 +0000)
committerRocky Bernstein <rocky@videolan.org>
Fri, 30 Jan 2004 13:17:12 +0000 (13:17 +0000)
entry.

Rest: Mostly more shuffling of definitions for modularity; doc
improvements.

(Also I need to copy these changes between computers and this is the
most expedient way. RV24 transparancy has been tested on a big-endian
box.)

modules/codec/ogt/Modules.am
modules/codec/ogt/common.c
modules/codec/ogt/pixmap.c [new file with mode: 0644]
modules/codec/ogt/pixmap.h
modules/codec/ogt/subtitle.h

index 5acbfba..d844529 100644 (file)
@@ -5,6 +5,7 @@ SOURCES_svcdsub = \
        ogt.c \
        ogt.h \
        ogt_parse.c \
+       pixmap.c \
        pixmap.h \
        render.c \
        render.h \
index fe42611..3619d43 100644 (file)
@@ -2,7 +2,7 @@
  * Common SVCD and VCD subtitle routines.
  *****************************************************************************
  * Copyright (C) 2003, 2004 VideoLAN
- * $Id: common.c,v 1.10 2004/01/29 11:50:21 rocky Exp $
+ * $Id: common.c,v 1.11 2004/01/30 13:17:12 rocky Exp $
  *
  * Author: Rocky Bernstein <rocky@panix.com>
  *   based on code from:
@@ -489,25 +489,6 @@ void VCDSubDumpImage( uint8_t *p_image, uint32_t i_height, uint32_t i_width )
   printf("\n-------------------------------------\n");
 }
 
-/***************************************************
-   Color conversion from
-    http://www.inforamp.net/~poynton/notes/colour_and_gamma/ColorFAQ.html#RTFToC30
-    http://people.ee.ethz.ch/~buc/brechbuehler/mirror/color/ColorFAQ.html
-    Thanks to Billy Biggs <vektor@dumbterm.net> for the pointer and
-    the following conversion.
-    R' = [ 1.1644         0    1.5960 ]   ([ Y' ]   [  16 ])
-    G' = [ 1.1644   -0.3918   -0.8130 ] * ([ Cb ] - [ 128 ])
-    B' = [ 1.1644    2.0172         0 ]   ([ Cr ]   [ 128 ])
-
-  See also vlc/modules/video_chroma/i420_rgb.h and
-  vlc/modules/video_chroma/i420_rgb_c.h for a way to do this in a way
-  more optimized for integer arithmetic. Would be nice to merge the
-  two routines.
-***************************************************/
-
 #ifdef HAVE_LIBPNG
 
 #define PALETTE_SIZE  4
diff --git a/modules/codec/ogt/pixmap.c b/modules/codec/ogt/pixmap.c
new file mode 100644 (file)
index 0000000..b3fc09e
--- /dev/null
@@ -0,0 +1,199 @@
+/*****************************************************************************
+ * Common pixel/chroma manipulation routines.
+ *****************************************************************************
+ * Copyright (C) 2003, 2004 VideoLAN
+ * $Id: pixmap.c,v 1.1 2004/01/30 13:17:12 rocky Exp $
+ *
+ * Author: Rocky Bernstein
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+
+#include "pixmap.h"
+
+/* FIXME: This is copied from modules/video_chroma/i420_rgb.h. 
+   Include from a more common location.
+ */
+
+/*****************************************************************************
+ * chroma_sys_t: chroma method descriptor
+ *****************************************************************************
+ * This structure is part of the chroma transformation descriptor, it
+ * describes the yuv2rgb specific properties.
+ *****************************************************************************/
+struct chroma_sys_t
+{
+    uint8_t  *p_buffer;
+    int *p_offset;
+
+    /* Pre-calculated conversion tables */
+    void *p_base;                         /* base for all conversion tables */
+    uint8_t   *p_rgb8;                    /* RGB 8 bits table */
+    uint16_t  *p_rgb16;                   /* RGB 16 bits table */
+    uint32_t  *p_rgb32;                   /* RGB 32 bits table */
+
+    /* To get RGB value for palette entry i, use (p_rgb_r[i], p_rgb_g[i],
+       p_rgb_b[i])
+     */
+    uint8_t  *p_rgb_r;                   /* Red values of palette */
+    uint8_t  *p_rgb_g;                   /* Green values of palette */
+    uint8_t  *p_rgb_b;                   /* Blue values of palette */
+};
+
+
+/* Number of entries in RGB palette/colormap*/
+#define CMAP_SIZE 256
+
+/* 
+    From
+    http://www.inforamp.net/~poynton/notes/colour_and_gamma/ColorFAQ.html#RTFToC11
+    http://people.ee.ethz.ch/~buc/brechbuehler/mirror/color/ColorFAQ.html#RTFToC1
+    11. What is "luma"?
+
+    It is useful in a video system to convey a component representative of
+    luminance and two other components representative of colour. It is
+    important to convey the component representative of luminance in such
+    a way that noise (or quantization) introduced in transmission,
+    processing and storage has a perceptually similar effect across the
+    entire tone scale from black to white. The ideal way to accomplish
+    these goals would be to form a luminance signal by matrixing RGB, then
+    subjecting luminance to a nonlinear transfer function similar to the
+    L* function.
+
+    There are practical reasons in video to perform these operations
+    in the opposite order. First a nonlinear transfer function - gamma
+    correction - is applied to each of the linear R, G and B. Then a
+    weighted sum of the nonlinear components is computed to form a
+    signal representative of luminance. The resulting component is
+    related to brightness but is not CIE luminance. Many video
+    engineers call it luma and give it the symbol Y'. It is often
+    carelessly called luminance and given the symbol Y. You must be
+    careful to determine whether a particular author assigns a linear
+    or nonlinear interpretation to the term luminance and the symbol
+    Y.
+
+    The coefficients that correspond to the "NTSC" red, green and blue
+    CRT phosphors of 1953 are standardized in ITU-R Recommendation BT.
+    601-2 (formerly CCIR Rec.  601-2). I call it Rec.  601. To compute
+    nonlinear video luma from nonlinear red, green and blue:
+
+    Y'601 = 0.299R' 0.587G' + 0.114B'
+
+    We will use the integer scaled versions of these numbers below
+    as RED_COEF, GREEN_COEF and BLUE_COEF.
+ */
+
+/* 19 = round(0.299 * 64) */
+#define RED_COEF   ((int32_t) 19)
+
+/* 38 = round(0.587 * 64) */
+#define GREEN_COEF ((int32_t) 37)
+
+/* 7 = round(0.114 * 64) */
+#define BLUE_COEF  ((int32_t)  7)
+
+/** 
+   Find the nearest colormap entry in p_vout (assumed to have RGB2
+   chroma, i.e. 256 RGB entries) that is closest in color to p_yuv.  Set
+   RGB to the color found and return the colormap index. -1 is returned
+   if there is some error.
+
+   The closest match is determined by the the Euclidean distance
+   using integer-scaled 601-2 coefficients described above.
+
+   Actually, we use the square of the Euclidean distance; but in
+   comparisons it amounts to the same thing.
+*/
+
+int
+find_cmap_rgb8_nearest(const vout_thread_t *p_vout, const ogt_yuvt_t *p_yuv,
+                      uint8_t *out_rgb) 
+{
+  uint8_t *p_cmap_r;
+  uint8_t *p_cmap_g;
+  uint8_t *p_cmap_b;
+  uint8_t rgb[RGB_SIZE];
+  
+  int i;
+  int i_bestmatch=0;
+  uint32_t i_mindist = 0xFFFFFFFF; /* The largest number here. */
+
+  /* Check that we really have RGB2. */
+  
+  if ( !p_vout && p_vout->output.i_chroma  != VLC_FOURCC('R','G','B','2') )
+    return -1;
+
+  p_cmap_r=p_vout->chroma.p_sys->p_rgb_r;
+  p_cmap_g=p_vout->chroma.p_sys->p_rgb_g;
+  p_cmap_b=p_vout->chroma.p_sys->p_rgb_b;
+
+  yuv2rgb(p_yuv, rgb);
+
+  for (i = 0; i < CMAP_SIZE; i++) {
+    /* Interval range calculations to show that we don't overflow the
+       word sizes below. pixels component values start out 8
+       bits. When we subtract two components we get 9 bits, then
+       square to 10 bits.  Next we scale by 6 we get 16 bits. XXX_COEF
+       all fit into 5 bits, so when we multiply we should have 21 bits
+       maximum. So computations can be done using 32-bit
+       precision. However before storing back distance components we
+       scale back down by 12 bits making the precision 9 bits.
+
+       The squared distance is the sum of three of the 9-bit numbers
+       described above. This then uses 21-bits and also fits in a
+       32-bit word.
+     */
+
+    /* We use in integer fixed-point fractions rather than floating
+       point for speed. We multiply by 64 (= 1 << 6) before computing
+       the product, and divide the result by 64*64 (= 1 >> (6*2)).
+    */
+
+#define SCALEBITS 6 
+#define int32_sqr(x) ( ((int32_t) (x)) * ((int32_t) x) )
+
+    uint32_t dr = ( RED_COEF   * ( int32_sqr(rgb[RED_PIXEL]   - p_cmap_r[i])
+                                << SCALEBITS ) ) >> (SCALEBITS*2);
+    uint32_t dg = ( GREEN_COEF * ( int32_sqr(rgb[GREEN_PIXEL] - p_cmap_g[i])
+                                << SCALEBITS ) ) >> (SCALEBITS*2);
+    uint32_t db = ( BLUE_COEF  * ( int32_sqr(rgb[BLUE_PIXEL]  - p_cmap_b[i])
+                                 << SCALEBITS ) ) >> (SCALEBITS*2);
+
+    uint32_t i_dist = dr + dg + db;
+    if (i_dist < i_mindist) {
+      i_bestmatch = i;
+      i_mindist = i_dist;
+    }
+  }
+
+  out_rgb[RED_PIXEL]   = p_cmap_r[i_bestmatch];
+  out_rgb[GREEN_PIXEL] = p_cmap_g[i_bestmatch];
+  out_rgb[BLUE_PIXEL]  = p_cmap_b[i_bestmatch];
+
+  return i_bestmatch;
+}
+
+\f
+/* 
+ * Local variables:
+ *  c-file-style: "gnu"
+ *  tab-width: 8
+ *  indent-tabs-mode: nil
+ * End:
+ */
index f397392..9f59139 100644 (file)
@@ -2,7 +2,7 @@
  * Common pixel/chroma manipulation routines.
  *****************************************************************************
  * Copyright (C) 2003, 2004 VideoLAN
- * $Id: pixmap.h,v 1.3 2004/01/29 11:50:22 rocky Exp $
+ * $Id: pixmap.h,v 1.4 2004/01/30 13:17:12 rocky Exp $
  *
  * Author: Rocky Bernstein
  *
@@ -24,7 +24,8 @@
 #ifndef PIXMAP_H
 #define PIXMAP_H 
 
-/* Color and transparency of a pixel or a palette (CLUT) entry */
+/** Color and transparency of a pixel or a palette (CLUT) entry 
+*/
 typedef union {
   uint8_t plane[4];
   struct {
@@ -35,14 +36,37 @@ typedef union {
   } s;
 } ogt_yuvt_t;
 
-/* Force v in the range 0.255. In video_chroma/i420_rgb.c, this
+/**
+   Force v in the range 0..255. In video_chroma/i420_rgb.c, this
    is macro is called CLIP. FIXME: Combine with that.
 */
 #define clip_8_bit(v) \
   ((v < 0) ? 0 : (v > 255) ? 255 : v)
 
+/**
+   Color conversion from
+    http://www.inforamp.net/~poynton/notes/colour_and_gamma/ColorFAQ.html#RTFToC30
+    http://people.ee.ethz.ch/~buc/brechbuehler/mirror/color/ColorFAQ.html
+    Thanks to Billy Biggs <vektor@dumbterm.net> for the pointer and
+    the following conversion.
+    R' = [ 1.1644         0    1.5960 ]   ([ Y' ]   [  16 ])
+    G' = [ 1.1644   -0.3918   -0.8130 ] * ([ Cb ] - [ 128 ])
+    B' = [ 1.1644    2.0172         0 ]   ([ Cr ]   [ 128 ])
+
+  See also vlc/modules/video_chroma/i420_rgb.h and
+  vlc/modules/video_chroma/i420_rgb_c.h for a way to do this in a way
+  more optimized for integer arithmetic. Would be nice to merge the
+  two routines.
+*/
+
+/**
+   Convert a YUV pixel into an RGB pixel.
+ */
 static inline void
-yuv2rgb(ogt_yuvt_t *p_yuv, uint8_t *p_rgb_out )
+yuv2rgb(const ogt_yuvt_t *p_yuv, uint8_t *p_rgb_out )
 {
   
   int i_Y  = p_yuv->s.y - 16;
@@ -69,6 +93,9 @@ yuv2rgb(ogt_yuvt_t *p_yuv, uint8_t *p_rgb_out )
   
 }
 
+/* The byte storage of an RGB pixel. */ 
+#define RGB_SIZE 3
+
 #define GREEN_PIXEL 1
 #ifdef WORDS_BIGENDIAN
 #define RED_PIXEL   0
@@ -78,8 +105,15 @@ yuv2rgb(ogt_yuvt_t *p_yuv, uint8_t *p_rgb_out )
 #define RED_PIXEL   0
 #endif
 
+/**
+   Store an RGB pixel into the location of p_pixel, taking into
+   account the "Endian"-ness of the underlying machine.
+
+   (N.B. Not sure if I've got this right or this is the right thing
+   to do.)
+ */
 static inline void
-put_rgb24_pixel(uint8_t *rgb, uint8_t *p_pixel)
+put_rgb24_pixel(const uint8_t *rgb, uint8_t *p_pixel)
 {
 #ifdef WORDS_BIGENDIAN
   *p_pixel++;
@@ -89,5 +123,23 @@ put_rgb24_pixel(uint8_t *rgb, uint8_t *p_pixel)
   *p_pixel++ = rgb[BLUE_PIXEL];
 }
 
+/**
+ Find the nearest colormap entry in p_vout (assumed to have RGB2
+ chroma, i.e. 256 RGB entries) that is closest in color to p_yuv.  Set
+ rgb to the color found and return the colormap index. -1 is returned
+ if there is some error.
+*/
+int
+find_cmap_nearest(const vout_thread_t *p_vout, const ogt_yuvt_t *p_yuv,
+                 uint8_t *rgb);
 
 #endif /* PIXMAP_H */
+
+\f
+/* 
+ * Local variables:
+ *  c-file-style: "gnu"
+ *  tab-width: 8
+ *  indent-tabs-mode: nil
+ * End:
+ */
index 7adc648..81ad7f3 100644 (file)
@@ -2,7 +2,7 @@
  * subtitle.h : Common SVCD and CVD subtitles header
  *****************************************************************************
  * Copyright (C) 2003,2004 VideoLAN
- * $Id: subtitle.h,v 1.14 2004/01/29 11:50:22 rocky Exp $
+ * $Id: subtitle.h,v 1.15 2004/01/30 13:17:12 rocky Exp $
  *
  * Author: Rocky Bernstein
  *   based on code from:
@@ -115,9 +115,6 @@ typedef enum  {
   SUBTITLE_BLOCK_COMPLETE
 } packet_state_t;
 
-/* The byte storage of an RGB pixel. */ 
-#define RGB_SIZE 3
-
 /* The byte storage used by one pixel */
 #define PIXEL_SIZE 4