Commit 5dab5a0d authored by Rocky Bernstein's avatar Rocky Bernstein

pixmap.[ch], Modules.am: provisional routine to find closest colormap

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.)
parent 2617285f
......@@ -5,6 +5,7 @@ SOURCES_svcdsub = \
ogt.c \
ogt.h \
ogt_parse.c \
pixmap.c \
pixmap.h \
render.c \
render.h \
......
......@@ -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
......
/*****************************************************************************
* 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;
}
/*
* Local variables:
* c-file-style: "gnu"
* tab-width: 8
* indent-tabs-mode: nil
* End:
*/
......@@ -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 */
/*
* Local variables:
* c-file-style: "gnu"
* tab-width: 8
* indent-tabs-mode: nil
* End:
*/
......@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment