]> git.sesse.net Git - ffmpeg/blob - libavcodec/imgconvert.c
01289d4d83f6f081bcf234f77d02fe20b22a27d7
[ffmpeg] / libavcodec / imgconvert.c
1 /*
2  * Misc image convertion routines
3  * Copyright (c) 2001 Gerard Lantau.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include "avcodec.h"
23
24 /* XXX: totally non optimized */
25
26 static void yuv422_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
27                               UINT8 *src, int width, int height)
28 {
29     int x, y;
30     UINT8 *p = src;
31
32     for(y=0;y<height;y+=2) {
33         for(x=0;x<width;x+=2) {
34             lum[0] = p[0];
35             cb[0] = p[1];
36             lum[1] = p[2];
37             cr[0] = p[3];
38             p += 4;
39             lum += 2;
40             cb++;
41             cr++;
42         }
43         for(x=0;x<width;x+=2) {
44             lum[0] = p[0];
45             lum[1] = p[2];
46             p += 4;
47             lum += 2;
48         }
49     }
50 }
51
52 #define SCALEBITS 8
53 #define ONE_HALF  (1 << (SCALEBITS - 1))
54 #define FIX(x)          ((int) ((x) * (1L<<SCALEBITS) + 0.5))
55
56 static void rgb24_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
57                               UINT8 *src, int width, int height)
58 {
59     int wrap, wrap3, x, y;
60     int r, g, b, r1, g1, b1;
61     UINT8 *p;
62
63     wrap = width;
64     wrap3 = width * 3;
65     p = src;
66     for(y=0;y<height;y+=2) {
67         for(x=0;x<width;x+=2) {
68             r = p[0];
69             g = p[1];
70             b = p[2];
71             r1 = r;
72             g1 = g;
73             b1 = b;
74             lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
75                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
76             r = p[3];
77             g = p[4];
78             b = p[5];
79             r1 += r;
80             g1 += g;
81             b1 += b;
82             lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
83                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
84             p += wrap3;
85             lum += wrap;
86
87             r = p[0];
88             g = p[1];
89             b = p[2];
90             r1 += r;
91             g1 += g;
92             b1 += b;
93             lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
94                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
95             r = p[3];
96             g = p[4];
97             b = p[5];
98             r1 += r;
99             g1 += g;
100             b1 += b;
101             lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
102                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
103             
104             cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + 
105                       FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
106             cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - 
107                      FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
108
109             cb++;
110             cr++;
111             p += -wrap3 + 2 * 3;
112             lum += -wrap + 2;
113         }
114         p += wrap3;
115         lum += wrap;
116     }
117 }
118
119 static void bgr24_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
120                               UINT8 *src, int width, int height)
121 {
122     int wrap, wrap3, x, y;
123     int r, g, b, r1, g1, b1;
124     UINT8 *p;
125
126     wrap = width;
127     wrap3 = width * 3;
128     p = src;
129     for(y=0;y<height;y+=2) {
130         for(x=0;x<width;x+=2) {
131             b = p[0];
132             g = p[1];
133             r = p[2];
134             r1 = r;
135             g1 = g;
136             b1 = b;
137             lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
138                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
139             b = p[3];
140             g = p[4];
141             r = p[5];
142             r1 += r;
143             g1 += g;
144             b1 += b;
145             lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
146                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
147             p += wrap3;
148             lum += wrap;
149
150             b = p[0];
151             g = p[1];
152             r = p[2];
153             r1 += r;
154             g1 += g;
155             b1 += b;
156             lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
157                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
158             b = p[3];
159             g = p[4];
160             r = p[5];
161             r1 += r;
162             g1 += g;
163             b1 += b;
164             lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
165                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
166             
167             cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + 
168                       FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
169             cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - 
170                      FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
171
172             cb++;
173             cr++;
174             p += -wrap3 + 2 * 3;
175             lum += -wrap + 2;
176         }
177         p += wrap3;
178         lum += wrap;
179     }
180 }
181
182 int img_convert_to_yuv420(UINT8 *img_out, UINT8 *img, 
183                           int pix_fmt, int width, int height)
184 {
185     UINT8 *pict;
186     int size, size_out;
187     UINT8 *picture[3];
188
189     pict = img_out;
190     size = width * height;
191     size_out = (size * 3) / 2;
192     picture[0] = pict;
193     picture[1] = pict + size;
194     picture[2] = picture[1] + (size / 4);
195
196     switch(pix_fmt) {
197     case PIX_FMT_YUV420P:
198         memcpy(pict, img, size_out);
199         break;
200     case PIX_FMT_YUV422:
201         yuv422_to_yuv420p(picture[0], picture[1], picture[2], 
202                           img, width, height);
203         break;
204     case PIX_FMT_RGB24:
205         rgb24_to_yuv420p(picture[0], picture[1], picture[2], 
206                          img, width, height);
207         break;
208     case PIX_FMT_BGR24:
209         bgr24_to_yuv420p(picture[0], picture[1], picture[2], 
210                          img, width, height);
211         break;
212     }
213     return size_out;
214 }