Subversion Repositories AndroidProjects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
204 chris 1
/*
2
   Colour conversion routines (RGB <-> YUV) in plain C
3
   (C) 2000 Nemosoft Unv.    nemosoft@smcc.demon.nl
4
 
5
   This program is free software; you can redistribute it and/or modify
6
   it under the terms of the GNU General Public License as published by
7
   the Free Software Foundation; either version 2 of the License, or
8
   (at your option) any later version.
9
 
10
   This program is distributed in the hope that it will be useful,
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
   GNU General Public License for more details.
14
 
15
   You should have received a copy of the GNU General Public License
16
   along with this program; if not, write to the Free Software
17
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
*/
19
 
20
 
21
#include "ccvt.h"
22
 
23
#define PUSH_RGB24      1
24
#define PUSH_BGR24      2
25
#define PUSH_RGB32      3
26
#define PUSH_BGR32      4
27
 
28
/* This is a really simplistic approach. Speedups are welcomed. */
29
static void ccvt_420i(int width, int height, unsigned char *src, unsigned char *dst, int push)
30
{
31
        int line, col, linewidth;
32
        int y, u, v, yy, vr, ug, vg, ub;
33
        int r, g, b;
34
        unsigned char *py, *pu, *pv;
35
 
36
        linewidth = width + (width >> 1);
37
        py = src;
38
        pu = py + 4;
39
        pv = pu + linewidth;
40
 
41
        y = *py++;
42
        yy = y << 8;
43
        u = *pu - 128;
44
        ug =   88 * u;
45
        ub =  454 * u;
46
        v = *pv - 128;
47
        vg =  183 * v;
48
        vr =  359 * v;
49
 
50
        /* The biggest problem is the interlaced data, and the fact that odd
51
           add even lines have V and U data, resp.
52
         */
53
        for (line = 0; line < height; line++) {
54
                for (col = 0; col < width; col++) {
55
                        r = (yy +      vr) >> 8;
56
                        g = (yy - ug - vg) >> 8;
57
                        b = (yy + ub     ) >> 8;
58
 
59
                        switch(push) {
60
                        case PUSH_RGB24:
61
                                *dst++ = r;
62
                                *dst++ = g;
63
                                *dst++ = b;
64
                                break;
65
 
66
                        case PUSH_BGR24:
67
                                *dst++ = b;
68
                                *dst++ = g;
69
                                *dst++ = r;
70
                                break;
71
 
72
                        case PUSH_RGB32:
73
                                *dst++ = r;
74
                                *dst++ = g;
75
                                *dst++ = b;
76
                                *dst++ = 0;
77
                                break;
78
 
79
                        case PUSH_BGR32:
80
                                *dst++ = b;
81
                                *dst++ = g;
82
                                *dst++ = r;
83
                                *dst++ = 0;
84
                                break;
85
                        }
86
 
87
                        y = *py++;
88
                        yy = y << 8;
89
                        if ((col & 3) == 3)
90
                                py += 2; // skip u/v
91
                        if (col & 1) {
92
                                if ((col & 3) == 3) {
93
                                        pu += 4; // skip y
94
                                        pv += 4;
95
                                }
96
                                else {
97
                                        pu++;
98
                                        pv++;
99
                                }
100
                                u = *pu - 128;
101
                                ug =   88 * u;
102
                                ub =  454 * u;
103
                                v = *pv - 128;
104
                                vg =  183 * v;
105
                                vr =  359 * v;
106
                        }
107
                } /* ..for col */
108
                if (line & 1) { // odd line: go to next band
109
                        pu += linewidth;
110
                        pv += linewidth;
111
                }
112
                else { // rewind u/v pointers
113
                        pu -= linewidth;
114
                        pv -= linewidth;
115
                }
116
        } /* ..for line */
117
}
118
 
119
void ccvt_420i_rgb24(int width, int height, void *src, void *dst)
120
{
121
        ccvt_420i(width, height, (unsigned char *)src, (unsigned char *)dst, PUSH_RGB24);
122
}
123
 
124
void ccvt_420i_bgr24(int width, int height, void *src, void *dst)
125
{
126
        ccvt_420i(width, height, (unsigned char *)src, (unsigned char *)dst, PUSH_BGR24);
127
}
128
 
129
void ccvt_420i_rgb32(int width, int height, void *src, void *dst)
130
{
131
        ccvt_420i(width, height, (unsigned char *)src, (unsigned char *)dst, PUSH_RGB32);
132
}
133
 
134
void ccvt_420i_bgr32(int width, int height, void *src, void *dst)
135
{
136
        ccvt_420i(width, height, (unsigned char *)src, (unsigned char *)dst, PUSH_BGR32);
137
}
138
 
139
 
140
void ccvt_420i_420p(int width, int height, void *src, void *dsty, void *dstu, void *dstv)
141
{
142
        short *s, *dy, *du, *dv;
143
        int line, col;
144
 
145
        s = (short *)src;
146
        dy = (short *)dsty;
147
        du = (short *)dstu;
148
        dv = (short *)dstv;
149
        for (line = 0; line < height; line++) {
150
                for (col = 0; col < width; col += 4) {
151
                        *dy++ = *s++;
152
                        *dy++ = *s++;
153
                        if (line & 1)
154
                                *dv++ = *s++;
155
                        else
156
                                *du++ = *s++;
157
                } /* ..for col */
158
        } /* ..for line */
159
}
160
 
161
void ccvt_420i_yuyv(int width, int height, void *src, void *dst)
162
{
163
        int line, col, linewidth;
164
        unsigned char *py, *pu, *pv, *d;
165
 
166
        linewidth = width + (width >> 1);
167
        py = (unsigned char *)src;
168
        pu = src + 4;
169
        pv = pu + linewidth;
170
        d = (unsigned char *)dst;
171
 
172
        for (line = 0; line < height; line++) {
173
                for (col = 0; col < width; col += 4) {
174
                        /* four pixels in one go */
175
                        *d++ = *py++;
176
                        *d++ = *pu++;
177
                        *d++ = *py++;
178
                        *d++ = *pv++;
179
 
180
                        *d++ = *py++;
181
                        *d++ = *pu++;
182
                        *d++ = *py++;
183
                        *d++ = *pv++;
184
 
185
                        py += 2;
186
                        pu += 4;
187
                        pv += 4;
188
                } /* ..for col */
189
                if (line & 1) { // odd line: go to next band
190
                        pu += linewidth;
191
                        pv += linewidth;
192
                }
193
                else { // rewind u/v pointers
194
                        pu -= linewidth;
195
                        pv -= linewidth;
196
                }
197
        } /* ..for line */
198
}
199