pixmap.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:9k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * Common pixel/chroma manipulation routines.
  3.  *****************************************************************************
  4.  * Copyright (C) 2003, 2004 VideoLAN
  5.  * $Id: pixmap.c 6961 2004-03-05 17:34:23Z sam $
  6.  *
  7.  * Author: Rocky Bernstein
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. #include <vlc/vlc.h>
  24. #include <vlc/vout.h>
  25. #include "pixmap.h"
  26. /* FIXME: This is copied from modules/video_chroma/i420_rgb.h. 
  27.    Include from a more common location.
  28.  */
  29. /*****************************************************************************
  30.  * chroma_sys_t: chroma method descriptor
  31.  *****************************************************************************
  32.  * This structure is part of the chroma transformation descriptor, it
  33.  * describes the yuv2rgb specific properties.
  34.  *****************************************************************************/
  35. struct chroma_sys_t
  36. {
  37.     uint8_t  *p_buffer;
  38.     int *p_offset;
  39.     /* Pre-calculated conversion tables */
  40.     void *p_base;                         /* base for all conversion tables */
  41.     uint8_t   *p_rgb8;                    /* RGB 8 bits table */
  42.     uint16_t  *p_rgb16;                   /* RGB 16 bits table */
  43.     uint32_t  *p_rgb32;                   /* RGB 32 bits table */
  44.     /* To get RGB value for palette entry i, use (p_rgb_r[i], p_rgb_g[i],
  45.        p_rgb_b[i])
  46.      */
  47.     uint16_t  p_rgb_r[CMAP_RGB2_SIZE];    /* Red values of palette */
  48.     uint16_t  p_rgb_g[CMAP_RGB2_SIZE];    /* Green values of palette */
  49.     uint16_t  p_rgb_b[CMAP_RGB2_SIZE];    /* Blue values of palette */
  50. };
  51. /* 
  52.     From
  53.     http://www.inforamp.net/~poynton/notes/colour_and_gamma/ColorFAQ.html#RTFToC11
  54.     http://people.ee.ethz.ch/~buc/brechbuehler/mirror/color/ColorFAQ.html#RTFToC1
  55.  
  56.     11. What is "luma"?
  57.     It is useful in a video system to convey a component representative of
  58.     luminance and two other components representative of colour. It is
  59.     important to convey the component representative of luminance in such
  60.     a way that noise (or quantization) introduced in transmission,
  61.     processing and storage has a perceptually similar effect across the
  62.     entire tone scale from black to white. The ideal way to accomplish
  63.     these goals would be to form a luminance signal by matrixing RGB, then
  64.     subjecting luminance to a nonlinear transfer function similar to the
  65.     L* function.
  66.     There are practical reasons in video to perform these operations
  67.     in the opposite order. First a nonlinear transfer function - gamma
  68.     correction - is applied to each of the linear R, G and B. Then a
  69.     weighted sum of the nonlinear components is computed to form a
  70.     signal representative of luminance. The resulting component is
  71.     related to brightness but is not CIE luminance. Many video
  72.     engineers call it luma and give it the symbol Y'. It is often
  73.     carelessly called luminance and given the symbol Y. You must be
  74.     careful to determine whether a particular author assigns a linear
  75.     or nonlinear interpretation to the term luminance and the symbol
  76.     Y.
  77.     The coefficients that correspond to the "NTSC" red, green and blue
  78.     CRT phosphors of 1953 are standardized in ITU-R Recommendation BT.
  79.     601-2 (formerly CCIR Rec.  601-2). I call it Rec.  601. To compute
  80.     nonlinear video luma from nonlinear red, green and blue:
  81.     Y'601 = 0.299R' 0.587G' + 0.114B'
  82.     We will use the integer scaled versions of these numbers below
  83.     as RED_COEF, GREEN_COEF and BLUE_COEF.
  84.  */
  85. /* 19 = round(0.299 * 64) */
  86. #define RED_COEF   ((int32_t) 19)
  87. /* 38 = round(0.587 * 64) */
  88. #define GREEN_COEF ((int32_t) 37)
  89. /* 7 = round(0.114 * 64) */
  90. #define BLUE_COEF  ((int32_t)  7)
  91. /** 
  92.    Find the nearest colormap entry in p_vout (assumed to have RGB2
  93.    chroma, i.e. 256 RGB 8bpp entries) that is closest in color to p_rgb.  Set
  94.    out_rgb to the color found and return the colormap index.
  95.    INVALID_CMAP_ENTRY is returned if there is some error.
  96.    The closest match is determined by the the Euclidean distance
  97.    using integer-scaled 601-2 coefficients described above.
  98.    Actually, we use the square of the Euclidean distance; but in
  99.    comparisons it amounts to the same thing.
  100. */
  101. cmap_t
  102. find_cmap_rgb8_nearest(const vout_thread_t *p_vout, const uint8_t *rgb,
  103.        uint8_t *out_rgb) 
  104. {
  105.   uint16_t *p_cmap_r;
  106.   uint16_t *p_cmap_g;
  107.   uint16_t *p_cmap_b;
  108.   
  109.   int i;
  110.   cmap_t i_bestmatch = INVALID_CMAP_ENTRY;
  111.   uint32_t i_mindist = 0xFFFFFFFF; /* The largest number here. */
  112.   /* Check that we really have RGB2. */
  113.   
  114.   if ( !p_vout && p_vout->output.i_chroma  != VLC_FOURCC('R','G','B','2') )
  115.     return INVALID_CMAP_ENTRY;
  116.   p_cmap_r=p_vout->chroma.p_sys->p_rgb_r;
  117.   p_cmap_g=p_vout->chroma.p_sys->p_rgb_g;
  118.   p_cmap_b=p_vout->chroma.p_sys->p_rgb_b;
  119.   for (i = 0; i < CMAP_RGB2_SIZE; i++) {
  120.     /* Interval range calculations to show that we don't overflow the
  121.        word sizes below. pixels component values start out 8
  122.        bits. When we subtract two components we get 9 bits, then
  123.        square to 10 bits.  Next we scale by 6 to give 16
  124.        bits. XXX_COEF all fit into 5 bits, so when we multiply we
  125.        should have 21 bits maximum. So computations can be done using
  126.        32-bit precision. However before storing back distance
  127.        components we scale back down by 12 bits making the precision 9
  128.        bits. (This checks out since it is basically the range of the
  129.        square of the initial 8-bit value.)
  130.        The squared distance is the sum of three of the 9-bit components
  131.        described above. This then uses 27-bits and also fits in a
  132.        32-bit word.
  133.      */
  134.     /* We use in integer fixed-point fractions rather than floating
  135.        point for speed. We multiply by 64 (= 1 << 6) before computing
  136.        the product, and divide the result by 64*64 (= 1 >> (6*2)).
  137.     */
  138. #define SCALEBITS 6 
  139. #define int32_sqr(x) ( ((int32_t) (x)) * ((int32_t) x) )
  140.     /* colormap entires are scaled to 16 bits, so we need to shift
  141.        them back down to 8. */
  142. #define CMAP8_RED(i) (p_cmap_r[i]>>8)
  143. #define CMAP8_GREEN(i) (p_cmap_g[i]>>8)
  144. #define CMAP8_BLUE(i) (p_cmap_b[i]>>8)
  145.     uint32_t dr = ( RED_COEF   * ( int32_sqr(rgb[RED_PIXEL]   - CMAP8_RED(i))
  146.  << SCALEBITS ) ) >> (SCALEBITS*2);
  147.     uint32_t dg = ( GREEN_COEF * ( int32_sqr(rgb[GREEN_PIXEL] - CMAP8_GREEN(i))
  148.  << SCALEBITS ) ) >> (SCALEBITS*2);
  149.     uint32_t db = ( BLUE_COEF  * ( int32_sqr(rgb[BLUE_PIXEL]  - CMAP8_BLUE(i))
  150.  << SCALEBITS ) ) >> (SCALEBITS*2);
  151.     uint32_t i_dist = dr + dg + db;
  152.     if (i_dist < i_mindist) {
  153.       i_bestmatch = i;
  154.       i_mindist = i_dist;
  155. #if 0      
  156.       printf("+++Change dist to %d RGB cmap %d (%0x, %0x, %0x)n", 
  157.              i_dist, i, p_cmap_r[ i ], p_cmap_g[ i ], p_cmap_b[ i ]);
  158. #endif
  159.     }
  160.   }
  161.   if (out_rgb) 
  162.     {
  163.       out_rgb[RED_PIXEL]   = CMAP8_RED(i_bestmatch);
  164.       out_rgb[GREEN_PIXEL] = CMAP8_GREEN(i_bestmatch);
  165.       out_rgb[BLUE_PIXEL]  = CMAP8_BLUE(i_bestmatch);
  166.     }
  167.   return i_bestmatch;
  168. }
  169. /**
  170.    Get the the rgb value for a given colormap entry for p_vout (which is'
  171.    assumed to have RGB2 chroma). 
  172.    VLC_FALSE is returned if there was some error.
  173. */
  174. vlc_bool_t
  175. query_color(const vout_thread_t *p_vout, cmap_t i_cmap,
  176.             /*out*/ uint8_t *out_rgb) 
  177. {
  178.   uint16_t *p_cmap_r;
  179.   uint16_t *p_cmap_g;
  180.   uint16_t *p_cmap_b;
  181.   /* Check that we really have RGB2. */
  182.   
  183.   if ( !p_vout && p_vout->output.i_chroma  != VLC_FOURCC('R','G','B','2') )
  184.     return VLC_FALSE;
  185.   if ( !out_rgb ) 
  186.     return VLC_FALSE;
  187.   p_cmap_r=p_vout->chroma.p_sys->p_rgb_r;
  188.   p_cmap_g=p_vout->chroma.p_sys->p_rgb_g;
  189.   p_cmap_b=p_vout->chroma.p_sys->p_rgb_b;
  190.   out_rgb[RED_PIXEL]   = CMAP8_RED(i_cmap);
  191.   out_rgb[GREEN_PIXEL] = CMAP8_GREEN(i_cmap);
  192.   out_rgb[BLUE_PIXEL]  = CMAP8_BLUE(i_cmap);
  193.   return VLC_TRUE;
  194. }
  195. /* 
  196.  * Local variables:
  197.  *  c-file-style: "gnu"
  198.  *  tab-width: 8
  199.  *  indent-tabs-mode: nil
  200.  * End:
  201.  */