1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
|
/*
* Copyright (C) 2007 Free Software Foundation, Inc.
*
* 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; version 2.
*
* 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-1307, USA.
*
* Author: Wolfgang Beck <bewo at users.berlios.de> 2007
*/
#include <libv4l1-videodev.h>
/*
* RGB to YUV420P conversion taken from
* en.wikipedia.org/wiki/YUV
*/
static inline unsigned char get_u(const unsigned char * const rgb)
{
return ((-38 * rgb[0] - 74 * rgb[1] + 112 * rgb[2] + 128) >> 8) + 128;
}
static inline unsigned char get_v(const unsigned char * const rgb)
{
return ((112 * rgb[0] - 94 * rgb[1] - 18 * rgb[2] + 128) >> 8) + 128;
}
int rgb24toyuv420p(
const unsigned char *rgb,
unsigned char *dst,
int w,
int h
)
{
int i;
int j;
const unsigned char *s;
const unsigned char *t;
unsigned char *d;
unsigned char *ud;
unsigned char *vd;
unsigned char y;
unsigned char u;
unsigned char v;
for(i = 0, s = rgb, t = rgb + 3 * w,
d = dst, vd = dst + (w * h), ud = vd + (w * h) / 4;
i < h;
++i) {
for(j = 0; j < w; ++j) {
y = ((66 * s[0] + 129 * s[1] + 25 * s[2] + 128) >> 8) + 16;
*d = y;
++d;
if (((i | j) & 0x1) == 0) {
u = (get_u(s) + get_u(s + 3) + get_u(t) + get_u(t + 3)) / 4;
*ud = u;
++ud;
v = (get_v(s) + get_v(s + 3) + get_v(t) + get_v(t + 3)) / 4;
*vd = v;
++vd;
}
s += 3;
t += 3;
}
}
return ud - dst;
}
int get_depth(int palette)
{
switch(palette) {
case VIDEO_PALETTE_RGB24:
return 24;
case VIDEO_PALETTE_YUV420P:
return 3;
default:
return 3;
}
}
|