Mercurial > libavcodec.hg
comparison imgconvert.c @ 989:fe9083c56733 libavcodec
simplified code (need automatic testing) - added primitive new format support.
author | bellard |
---|---|
date | Sat, 11 Jan 2003 00:08:48 +0000 |
parents | ef769ec24115 |
children | 895d3b01c6f4 |
comparison
equal
deleted
inserted
replaced
988:001b7d3045e5 | 989:fe9083c56733 |
---|---|
1 /* | 1 /* |
2 * Misc image convertion routines | 2 * Misc image convertion routines |
3 * Copyright (c) 2001, 2002 Fabrice Bellard. | 3 * Copyright (c) 2001, 2002, 2003 Fabrice Bellard. |
4 * | 4 * |
5 * This library is free software; you can redistribute it and/or | 5 * This library is free software; you can redistribute it and/or |
6 * modify it under the terms of the GNU Lesser General Public | 6 * modify it under the terms of the GNU Lesser General Public |
7 * License as published by the Free Software Foundation; either | 7 * License as published by the Free Software Foundation; either |
8 * version 2 of the License, or (at your option) any later version. | 8 * version 2 of the License, or (at your option) any later version. |
24 #endif | 24 #endif |
25 | 25 |
26 #ifdef HAVE_MMX | 26 #ifdef HAVE_MMX |
27 #include "i386/mmx.h" | 27 #include "i386/mmx.h" |
28 #endif | 28 #endif |
29 | |
30 typedef struct PixFmtInfo { | |
31 const char *name; | |
32 UINT8 nb_components; /* number of components in AVPicture array */ | |
33 UINT8 is_yuv : 1; /* true if YUV instead of RGB color space */ | |
34 UINT8 is_packed : 1; /* true if multiple components in same word */ | |
35 UINT8 is_paletted : 1; /* true if paletted */ | |
36 UINT8 is_alpha : 1; /* true if alpha can be specified */ | |
37 UINT8 is_gray : 1; /* true if gray or monochrome format */ | |
38 UINT8 x_chroma_shift; /* X chroma subsampling factor is 2 ^ shift */ | |
39 UINT8 y_chroma_shift; /* Y chroma subsampling factor is 2 ^ shift */ | |
40 } PixFmtInfo; | |
41 | |
42 /* this table gives more information about formats */ | |
43 static PixFmtInfo pix_fmt_info[PIX_FMT_NB] = { | |
44 /* YUV formats */ | |
45 [PIX_FMT_YUV420P] = { | |
46 name: "yuv420p", | |
47 nb_components: 3, is_yuv: 1, | |
48 x_chroma_shift: 1, y_chroma_shift: 1, | |
49 }, | |
50 [PIX_FMT_YUV422P] = { | |
51 name: "yuv422p", | |
52 nb_components: 3, is_yuv: 1, | |
53 x_chroma_shift: 1, y_chroma_shift: 0, | |
54 }, | |
55 [PIX_FMT_YUV444P] = { | |
56 name: "yuv444p", | |
57 nb_components: 3, is_yuv: 1, | |
58 x_chroma_shift: 0, y_chroma_shift: 0, | |
59 }, | |
60 [PIX_FMT_YUV422] = { | |
61 name: "yuv422", | |
62 nb_components: 1, is_yuv: 1, is_packed: 1, | |
63 x_chroma_shift: 1, y_chroma_shift: 0, | |
64 }, | |
65 [PIX_FMT_YUV410P] = { | |
66 name: "yuv410p", | |
67 nb_components: 3, is_yuv: 1, | |
68 x_chroma_shift: 2, y_chroma_shift: 2, | |
69 }, | |
70 [PIX_FMT_YUV411P] = { | |
71 name: "yuv411p", | |
72 nb_components: 3, is_yuv: 1, | |
73 x_chroma_shift: 2, y_chroma_shift: 0, | |
74 }, | |
75 | |
76 /* RGB formats */ | |
77 [PIX_FMT_RGB24] = { | |
78 name: "rgb24", | |
79 nb_components: 1, is_packed: 1, | |
80 }, | |
81 [PIX_FMT_BGR24] = { | |
82 name: "bgr24", | |
83 nb_components: 1, is_packed: 1, | |
84 }, | |
85 [PIX_FMT_RGBA32] = { | |
86 name: "rgba32", | |
87 nb_components: 1, is_packed: 1, is_alpha: 1, | |
88 }, | |
89 [PIX_FMT_RGB565] = { | |
90 name: "rgb565", | |
91 nb_components: 1, is_packed: 1, | |
92 }, | |
93 [PIX_FMT_RGB555] = { | |
94 name: "rgb555", | |
95 nb_components: 1, is_packed: 1, is_alpha : 1, | |
96 }, | |
97 | |
98 /* gray / mono formats */ | |
99 [PIX_FMT_GRAY8] = { | |
100 name: "gray", | |
101 nb_components: 1, is_gray: 1, | |
102 }, | |
103 [PIX_FMT_MONOWHITE] = { | |
104 name: "monow", | |
105 nb_components: 1, is_packed: 1, is_gray: 1, | |
106 }, | |
107 [PIX_FMT_MONOBLACK] = { | |
108 name: "monob", | |
109 nb_components: 1, is_packed: 1, is_gray: 1, | |
110 }, | |
111 }; | |
112 | |
113 void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift) | |
114 { | |
115 if (pix_fmt_info[pix_fmt].is_yuv) { | |
116 *h_shift = pix_fmt_info[pix_fmt].x_chroma_shift; | |
117 *v_shift = pix_fmt_info[pix_fmt].y_chroma_shift; | |
118 } else { | |
119 *h_shift=0; | |
120 *v_shift=0; | |
121 } | |
122 } | |
123 | |
124 const char *avcodec_get_pix_fmt_name(int pix_fmt) | |
125 { | |
126 if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB) | |
127 return "???"; | |
128 else | |
129 return pix_fmt_info[pix_fmt].name; | |
130 } | |
131 | |
29 /* XXX: totally non optimized */ | 132 /* XXX: totally non optimized */ |
30 | 133 |
31 static void yuv422_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr, | 134 static void yuv422_to_yuv420p(AVPicture *dst, AVPicture *src, |
32 UINT8 *src, int width, int height) | 135 int width, int height) |
33 { | 136 { |
137 UINT8 *lum, *cb, *cr; | |
34 int x, y; | 138 int x, y; |
35 UINT8 *p = src; | 139 const UINT8 *p; |
36 | 140 |
141 lum = dst->data[0]; | |
142 cb = dst->data[1]; | |
143 cr = dst->data[2]; | |
144 p = src->data[0]; | |
145 | |
37 for(y=0;y<height;y+=2) { | 146 for(y=0;y<height;y+=2) { |
38 for(x=0;x<width;x+=2) { | 147 for(x=0;x<width;x+=2) { |
39 lum[0] = p[0]; | 148 lum[0] = p[0]; |
40 cb[0] = p[1]; | 149 cb[0] = p[1]; |
41 lum[1] = p[2]; | 150 lum[1] = p[2]; |
55 } | 164 } |
56 | 165 |
57 #define SCALEBITS 8 | 166 #define SCALEBITS 8 |
58 #define ONE_HALF (1 << (SCALEBITS - 1)) | 167 #define ONE_HALF (1 << (SCALEBITS - 1)) |
59 #define FIX(x) ((int) ((x) * (1L<<SCALEBITS) + 0.5)) | 168 #define FIX(x) ((int) ((x) * (1L<<SCALEBITS) + 0.5)) |
60 | |
61 static void rgb24_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr, | |
62 UINT8 *src, int width, int height) | |
63 { | |
64 int wrap, wrap3, x, y; | |
65 int r, g, b, r1, g1, b1; | |
66 UINT8 *p; | |
67 | |
68 wrap = width; | |
69 wrap3 = width * 3; | |
70 p = src; | |
71 for(y=0;y<height;y+=2) { | |
72 for(x=0;x<width;x+=2) { | |
73 r = p[0]; | |
74 g = p[1]; | |
75 b = p[2]; | |
76 r1 = r; | |
77 g1 = g; | |
78 b1 = b; | |
79 lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + | |
80 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; | |
81 r = p[3]; | |
82 g = p[4]; | |
83 b = p[5]; | |
84 r1 += r; | |
85 g1 += g; | |
86 b1 += b; | |
87 lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + | |
88 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; | |
89 p += wrap3; | |
90 lum += wrap; | |
91 | |
92 r = p[0]; | |
93 g = p[1]; | |
94 b = p[2]; | |
95 r1 += r; | |
96 g1 += g; | |
97 b1 += b; | |
98 lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + | |
99 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; | |
100 r = p[3]; | |
101 g = p[4]; | |
102 b = p[5]; | |
103 r1 += r; | |
104 g1 += g; | |
105 b1 += b; | |
106 lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + | |
107 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; | |
108 | |
109 cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + | |
110 FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128; | |
111 cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - | |
112 FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128; | |
113 | |
114 cb++; | |
115 cr++; | |
116 p += -wrap3 + 2 * 3; | |
117 lum += -wrap + 2; | |
118 } | |
119 p += wrap3; | |
120 lum += wrap; | |
121 } | |
122 } | |
123 | |
124 static void rgba32_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr, | |
125 UINT8 *src, int width, int height) | |
126 { | |
127 int wrap, wrap4, x, y; | |
128 int r, g, b, r1, g1, b1; | |
129 UINT8 *p; | |
130 | |
131 wrap = width; | |
132 wrap4 = width * 4; | |
133 p = src; | |
134 for(y=0;y<height;y+=2) { | |
135 for(x=0;x<width;x+=2) { | |
136 r = p[0]; | |
137 g = p[1]; | |
138 b = p[2]; | |
139 r1 = r; | |
140 g1 = g; | |
141 b1 = b; | |
142 lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + | |
143 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; | |
144 r = p[4]; | |
145 g = p[5]; | |
146 b = p[6]; | |
147 r1 += r; | |
148 g1 += g; | |
149 b1 += b; | |
150 lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + | |
151 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; | |
152 p += wrap4; | |
153 lum += wrap; | |
154 | |
155 r = p[0]; | |
156 g = p[1]; | |
157 b = p[2]; | |
158 r1 += r; | |
159 g1 += g; | |
160 b1 += b; | |
161 lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + | |
162 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; | |
163 r = p[4]; | |
164 g = p[5]; | |
165 b = p[6]; | |
166 r1 += r; | |
167 g1 += g; | |
168 b1 += b; | |
169 lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + | |
170 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; | |
171 | |
172 cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + | |
173 FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128; | |
174 cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - | |
175 FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128; | |
176 | |
177 cb++; | |
178 cr++; | |
179 p += -wrap4 + 2 * 4; | |
180 lum += -wrap + 2; | |
181 } | |
182 p += wrap4; | |
183 lum += wrap; | |
184 } | |
185 } | |
186 | |
187 #define rgb565_to_yuv420p(lum,cb,cr,src,width,height) rgbmisc_to_yuv420p((lum),(cb),(cr),(src),(width),(height),0x0800,31, 0x0020,63,0x0001,31) | |
188 #define rgb555_to_yuv420p(lum,cb,cr,src,width,height) rgbmisc_to_yuv420p((lum),(cb),(cr),(src),(width),(height),0x0400,31, 0x0020,31,0x0001,31) | |
189 #define rgb5551_to_yuv420p(lum,cb,cr,src,width,height) rgbmisc_to_yuv420p((lum),(cb),(cr),(src),(width),(height),0x0800,31, 0x0040,31,0x0002,31) | |
190 #define bgr565_to_yuv420p(lum,cb,cr,src,width,height) rgbmisc_to_yuv420p((lum),(cb),(cr),(src),(width),(height),0x0001,31, 0x0020,63,0x0800,31) | |
191 #define bgr555_to_yuv420p(lum,cb,cr,src,width,height) rgbmisc_to_yuv420p((lum),(cb),(cr),(src),(width),(height),0x0001,31, 0x0020,31,0x0400,31) | |
192 #define gbr565_to_yuv420p(lum,cb,cr,src,width,height) rgbmisc_to_yuv420p((lum),(cb),(cr),(src),(width),(height),0x0001,31, 0x0800,31,0x0040,63) | |
193 #define gbr555_to_yuv420p(lum,cb,cr,src,width,height) rgbmisc_to_yuv420p((lum),(cb),(cr),(src),(width),(height),0x0001,31, 0x0400,31,0x0020,31) | |
194 | |
195 static void rgbmisc_to_yuv420p | |
196 (UINT8 *lum, UINT8 *cb, UINT8 *cr, | |
197 UINT8 *src, int width, int height, | |
198 | |
199 UINT16 R_LOWMASK, UINT16 R_MAX, | |
200 UINT16 G_LOWMASK, UINT16 G_MAX, | |
201 UINT16 B_LOWMASK, UINT16 B_MAX | |
202 ) | |
203 { | |
204 int wrap, wrap2, x, y; | |
205 int r, g, b, r1, g1, b1; | |
206 UINT8 *p; | |
207 UINT16 pixel; | |
208 | |
209 wrap = width; | |
210 wrap2 = width * 2; | |
211 p = src; | |
212 for(y=0;y<height;y+=2) { | |
213 for(x=0;x<width;x+=2) { | |
214 pixel = p[0] | (p[1]<<8); | |
215 r = (((pixel/R_LOWMASK) & R_MAX) * (0x100 / (R_MAX+1))); | |
216 g = (((pixel/G_LOWMASK) & G_MAX) * (0x100 / (G_MAX+1))); | |
217 b = (((pixel/B_LOWMASK) & B_MAX) * (0x100 / (B_MAX+1))); | |
218 r1 = r; | |
219 g1 = g; | |
220 b1 = b; | |
221 lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + | |
222 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; | |
223 | |
224 pixel = p[2] | (p[3]<<8); | |
225 r = (((pixel/R_LOWMASK) & R_MAX) * (0x100 / (R_MAX+1))); | |
226 g = (((pixel/G_LOWMASK) & G_MAX) * (0x100 / (G_MAX+1))); | |
227 b = (((pixel/B_LOWMASK) & B_MAX) * (0x100 / (B_MAX+1))); | |
228 r1 += r; | |
229 g1 += g; | |
230 b1 += b; | |
231 lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + | |
232 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; | |
233 p += wrap2; | |
234 lum += wrap; | |
235 | |
236 pixel = p[0] | (p[1]<<8); | |
237 r = (((pixel/R_LOWMASK) & R_MAX) * (0x100 / (R_MAX+1))); | |
238 g = (((pixel/G_LOWMASK) & G_MAX) * (0x100 / (G_MAX+1))); | |
239 b = (((pixel/B_LOWMASK) & B_MAX) * (0x100 / (B_MAX+1))); | |
240 r1 += r; | |
241 g1 += g; | |
242 b1 += b; | |
243 lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + | |
244 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; | |
245 pixel = p[2] | (p[3]<<8); | |
246 r = (((pixel/R_LOWMASK) & R_MAX) * (0x100 / (R_MAX+1))); | |
247 g = (((pixel/G_LOWMASK) & G_MAX) * (0x100 / (G_MAX+1))); | |
248 b = (((pixel/B_LOWMASK) & B_MAX) * (0x100 / (B_MAX+1))); | |
249 r1 += r; | |
250 g1 += g; | |
251 b1 += b; | |
252 lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + | |
253 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; | |
254 | |
255 cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + | |
256 FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128; | |
257 cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - | |
258 FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128; | |
259 | |
260 cb++; | |
261 cr++; | |
262 p += -wrap2 + 2 * 2; | |
263 lum += -wrap + 2; | |
264 } | |
265 p += wrap2; | |
266 lum += wrap; | |
267 } | |
268 } | |
269 | |
270 | |
271 static void bgr24_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr, | |
272 UINT8 *src, int width, int height) | |
273 { | |
274 int wrap, wrap3, x, y; | |
275 int r, g, b, r1, g1, b1; | |
276 UINT8 *p; | |
277 | |
278 wrap = width; | |
279 wrap3 = width * 3; | |
280 p = src; | |
281 for(y=0;y<height;y+=2) { | |
282 for(x=0;x<width;x+=2) { | |
283 b = p[0]; | |
284 g = p[1]; | |
285 r = p[2]; | |
286 r1 = r; | |
287 g1 = g; | |
288 b1 = b; | |
289 lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + | |
290 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; | |
291 b = p[3]; | |
292 g = p[4]; | |
293 r = p[5]; | |
294 r1 += r; | |
295 g1 += g; | |
296 b1 += b; | |
297 lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + | |
298 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; | |
299 p += wrap3; | |
300 lum += wrap; | |
301 | |
302 b = p[0]; | |
303 g = p[1]; | |
304 r = p[2]; | |
305 r1 += r; | |
306 g1 += g; | |
307 b1 += b; | |
308 lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + | |
309 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; | |
310 b = p[3]; | |
311 g = p[4]; | |
312 r = p[5]; | |
313 r1 += r; | |
314 g1 += g; | |
315 b1 += b; | |
316 lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + | |
317 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; | |
318 | |
319 cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + | |
320 FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128; | |
321 cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - | |
322 FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128; | |
323 | |
324 cb++; | |
325 cr++; | |
326 p += -wrap3 + 2 * 3; | |
327 lum += -wrap + 2; | |
328 } | |
329 p += wrap3; | |
330 lum += wrap; | |
331 } | |
332 } | |
333 | |
334 static void bgra32_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr, | |
335 UINT8 *src, int width, int height) | |
336 { | |
337 int wrap, wrap4, x, y; | |
338 int r, g, b, r1, g1, b1; | |
339 UINT8 *p; | |
340 | |
341 wrap = width; | |
342 wrap4 = width * 4; | |
343 p = src; | |
344 for(y=0;y<height;y+=2) { | |
345 for(x=0;x<width;x+=2) { | |
346 b = p[0]; | |
347 g = p[1]; | |
348 r = p[2]; | |
349 r1 = r; | |
350 g1 = g; | |
351 b1 = b; | |
352 lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + | |
353 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; | |
354 b = p[4]; | |
355 g = p[5]; | |
356 r = p[6]; | |
357 r1 += r; | |
358 g1 += g; | |
359 b1 += b; | |
360 lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + | |
361 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; | |
362 p += wrap4; | |
363 lum += wrap; | |
364 | |
365 b = p[0]; | |
366 g = p[1]; | |
367 r = p[2]; | |
368 r1 += r; | |
369 g1 += g; | |
370 b1 += b; | |
371 lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + | |
372 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; | |
373 b = p[4]; | |
374 g = p[5]; | |
375 r = p[6]; | |
376 r1 += r; | |
377 g1 += g; | |
378 b1 += b; | |
379 lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + | |
380 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; | |
381 | |
382 cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + | |
383 FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128; | |
384 cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - | |
385 FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128; | |
386 | |
387 cb++; | |
388 cr++; | |
389 p += -wrap4 + 2 * 4; | |
390 lum += -wrap + 2; | |
391 } | |
392 p += wrap4; | |
393 lum += wrap; | |
394 } | |
395 } | |
396 | 169 |
397 /* XXX: use generic filter ? */ | 170 /* XXX: use generic filter ? */ |
398 /* 1x2 -> 1x1 */ | 171 /* 1x2 -> 1x1 */ |
399 static void shrink2(UINT8 *dst, int dst_wrap, | 172 static void shrink2(UINT8 *dst, int dst_wrap, |
400 UINT8 *src, int src_wrap, | 173 UINT8 *src, int src_wrap, |
485 src += src_wrap; | 258 src += src_wrap; |
486 dst += dst_wrap; | 259 dst += dst_wrap; |
487 } | 260 } |
488 } | 261 } |
489 | 262 |
490 /* 1x2 -> 2x1. width and height are given for the source picture */ | 263 /* 1x2 -> 2x1 */ |
491 static void conv411(UINT8 *dst, int dst_wrap, | 264 static void conv411(UINT8 *dst, int dst_wrap, |
492 UINT8 *src, int src_wrap, | 265 UINT8 *src, int src_wrap, |
493 int width, int height) | 266 int width, int height) |
494 { | 267 { |
495 int w, c; | 268 int w, c; |
496 UINT8 *s1, *s2, *d; | 269 UINT8 *s1, *s2, *d; |
497 | 270 |
498 for(;height > 0; height -= 2) { | 271 for(;height > 0; height--) { |
499 s1 = src; | 272 s1 = src; |
500 s2 = src + src_wrap; | 273 s2 = src + src_wrap; |
501 d = dst; | 274 d = dst; |
502 for(w = width;w > 0; w--) { | 275 for(w = width;w > 0; w--) { |
503 c = (s1[0] + s2[0]) >> 1; | 276 c = (s1[0] + s2[0]) >> 1; |
529 #define C_RV (117504 >> (16 - SCALE_BITS)) | 302 #define C_RV (117504 >> (16 - SCALE_BITS)) |
530 #define C_BU (138453 >> (16 - SCALE_BITS)) | 303 #define C_BU (138453 >> (16 - SCALE_BITS)) |
531 #define C_GU (13954 >> (16 - SCALE_BITS)) | 304 #define C_GU (13954 >> (16 - SCALE_BITS)) |
532 #define C_GV (34903 >> (16 - SCALE_BITS)) | 305 #define C_GV (34903 >> (16 - SCALE_BITS)) |
533 | 306 |
534 #define RGBOUT(r, g, b, y1)\ | 307 #define YUV_TO_RGB2(r, g, b, y1)\ |
535 {\ | 308 {\ |
536 y = (y1 - 16) * C_Y;\ | 309 y = (y1 - 16) * C_Y;\ |
537 r = cm[(y + r_add) >> SCALE_BITS];\ | 310 r = cm[(y + r_add) >> SCALE_BITS];\ |
538 g = cm[(y + g_add) >> SCALE_BITS];\ | 311 g = cm[(y + g_add) >> SCALE_BITS];\ |
539 b = cm[(y + b_add) >> SCALE_BITS];\ | 312 b = cm[(y + b_add) >> SCALE_BITS];\ |
540 } | 313 } |
541 | 314 |
542 /* XXX: no chroma interpolating is done */ | 315 /* XXX: no chroma interpolating is done */ |
543 static void yuv420p_to_bgra32(AVPicture *dst, AVPicture *src, | 316 #define RGB_FUNCTIONS(rgb_name) \ |
544 int width, int height) | 317 \ |
545 { | 318 static void yuv420p_to_ ## rgb_name (AVPicture *dst, AVPicture *src, \ |
546 UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2; | 319 int width, int height) \ |
547 int w, y, cb, cr, r_add, g_add, b_add, width2; | 320 { \ |
548 UINT8 *cm = cropTbl + MAX_NEG_CROP; | 321 UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2; \ |
549 | 322 int w, y, cb, cr, r_add, g_add, b_add, width2; \ |
550 d = dst->data[0]; | 323 UINT8 *cm = cropTbl + MAX_NEG_CROP; \ |
551 y1_ptr = src->data[0]; | 324 unsigned int r, g, b; \ |
552 cb_ptr = src->data[1]; | 325 \ |
553 cr_ptr = src->data[2]; | 326 d = dst->data[0]; \ |
554 width2 = width >> 1; | 327 y1_ptr = src->data[0]; \ |
555 for(;height > 0; height -= 2) { | 328 cb_ptr = src->data[1]; \ |
556 d1 = d; | 329 cr_ptr = src->data[2]; \ |
557 d2 = d + dst->linesize[0]; | 330 width2 = width >> 1; \ |
558 y2_ptr = y1_ptr + src->linesize[0]; | 331 for(;height > 0; height -= 2) { \ |
559 for(w = width2; w > 0; w --) { | 332 d1 = d; \ |
560 cb = cb_ptr[0] - 128; | 333 d2 = d + dst->linesize[0]; \ |
561 cr = cr_ptr[0] - 128; | 334 y2_ptr = y1_ptr + src->linesize[0]; \ |
562 r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); | 335 for(w = width2; w > 0; w --) { \ |
563 g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); | 336 cb = cb_ptr[0] - 128; \ |
564 b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); | 337 cr = cr_ptr[0] - 128; \ |
338 r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \ | |
339 g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \ | |
340 b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \ | |
341 \ | |
342 /* output 4 pixels */ \ | |
343 YUV_TO_RGB2(r, g, b, y1_ptr[0]); \ | |
344 RGB_OUT(d1, r, g, b); \ | |
345 \ | |
346 YUV_TO_RGB2(r, g, b, y1_ptr[1]); \ | |
347 RGB_OUT(d1 + BPP, r, g, b); \ | |
348 \ | |
349 YUV_TO_RGB2(r, g, b, y2_ptr[0]); \ | |
350 RGB_OUT(d2, r, g, b); \ | |
351 \ | |
352 YUV_TO_RGB2(r, g, b, y2_ptr[1]); \ | |
353 RGB_OUT(d2 + BPP, r, g, b); \ | |
354 \ | |
355 d1 += 2 * BPP; \ | |
356 d2 += 2 * BPP; \ | |
357 \ | |
358 y1_ptr += 2; \ | |
359 y2_ptr += 2; \ | |
360 cb_ptr++; \ | |
361 cr_ptr++; \ | |
362 } \ | |
363 d += 2 * dst->linesize[0]; \ | |
364 y1_ptr += 2 * src->linesize[0] - width; \ | |
365 cb_ptr += src->linesize[1] - width2; \ | |
366 cr_ptr += src->linesize[2] - width2; \ | |
367 } \ | |
368 } \ | |
369 \ | |
370 /* XXX: no chroma interpolating is done */ \ | |
371 static void yuv422p_to_ ## rgb_name (AVPicture *dst, AVPicture *src, \ | |
372 int width, int height) \ | |
373 { \ | |
374 UINT8 *y1_ptr, *cb_ptr, *cr_ptr, *d, *d1; \ | |
375 int w, y, cb, cr, r_add, g_add, b_add, width2; \ | |
376 UINT8 *cm = cropTbl + MAX_NEG_CROP; \ | |
377 unsigned int r, g, b; \ | |
378 \ | |
379 d = dst->data[0]; \ | |
380 y1_ptr = src->data[0]; \ | |
381 cb_ptr = src->data[1]; \ | |
382 cr_ptr = src->data[2]; \ | |
383 width2 = width >> 1; \ | |
384 for(;height > 0; height --) { \ | |
385 d1 = d; \ | |
386 for(w = width2; w > 0; w --) { \ | |
387 cb = cb_ptr[0] - 128; \ | |
388 cr = cr_ptr[0] - 128; \ | |
389 r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \ | |
390 g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \ | |
391 b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \ | |
392 \ | |
393 /* output 2 pixels */ \ | |
394 YUV_TO_RGB2(r, g, b, y1_ptr[0]); \ | |
395 RGB_OUT(d, r, g, b); \ | |
396 \ | |
397 YUV_TO_RGB2(r, g, b, y1_ptr[1]); \ | |
398 RGB_OUT(d + BPP, r, g, b); \ | |
399 \ | |
400 d += 2 * BPP; \ | |
401 \ | |
402 y1_ptr += 2; \ | |
403 cb_ptr++; \ | |
404 cr_ptr++; \ | |
405 } \ | |
406 d += dst->linesize[0]; \ | |
407 y1_ptr += src->linesize[0] - width; \ | |
408 cb_ptr += src->linesize[1] - width2; \ | |
409 cr_ptr += src->linesize[2] - width2; \ | |
410 } \ | |
411 } \ | |
412 \ | |
413 static void rgb_name ## _to_yuv420p(AVPicture *dst, AVPicture *src, \ | |
414 int width, int height) \ | |
415 { \ | |
416 int wrap, wrap3, x, y; \ | |
417 int r, g, b, r1, g1, b1; \ | |
418 UINT8 *lum, *cb, *cr; \ | |
419 const UINT8 *p; \ | |
420 \ | |
421 lum = dst->data[0]; \ | |
422 cb = dst->data[1]; \ | |
423 cr = dst->data[2]; \ | |
424 \ | |
425 wrap = width; \ | |
426 wrap3 = width * 3; \ | |
427 p = src->data[0]; \ | |
428 for(y=0;y<height;y+=2) { \ | |
429 for(x=0;x<width;x+=2) { \ | |
430 RGB_IN(r, g, b, p); \ | |
431 r1 = r; \ | |
432 g1 = g; \ | |
433 b1 = b; \ | |
434 lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + \ | |
435 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \ | |
436 RGB_IN(r, g, b, p + BPP); \ | |
437 r1 += r; \ | |
438 g1 += g; \ | |
439 b1 += b; \ | |
440 lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + \ | |
441 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \ | |
442 p += wrap3; \ | |
443 lum += wrap; \ | |
444 \ | |
445 RGB_IN(r, g, b, p); \ | |
446 r1 += r; \ | |
447 g1 += g; \ | |
448 b1 += b; \ | |
449 lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + \ | |
450 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \ | |
451 \ | |
452 RGB_IN(r, g, b, p + BPP); \ | |
453 r1 += r; \ | |
454 g1 += g; \ | |
455 b1 += b; \ | |
456 lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + \ | |
457 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \ | |
458 \ | |
459 cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \ | |
460 FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> \ | |
461 (SCALEBITS + 2)) + 128; \ | |
462 cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \ | |
463 FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> \ | |
464 (SCALEBITS + 2)) + 128; \ | |
465 \ | |
466 cb++; \ | |
467 cr++; \ | |
468 p += -wrap3 + 2 * 3; \ | |
469 lum += -wrap + 2; \ | |
470 } \ | |
471 p += wrap3; \ | |
472 lum += wrap; \ | |
473 } \ | |
474 } | |
475 | |
476 /* copy bit n to bits 0 ... n - 1 */ | |
477 static inline unsigned int bitcopy_n(unsigned int a, int n) | |
478 { | |
479 int mask; | |
480 mask = (1 << n) - 1; | |
481 return (a & (0xff & ~mask)) | ((-((a >> n) & 1)) & mask); | |
482 } | |
483 | |
484 /* rgb555 handling */ | |
485 | |
486 #define RGB_IN(r, g, b, s)\ | |
487 {\ | |
488 unsigned int v = ((UINT16 *)(s))[0];\ | |
489 r = bitcopy_n(v >> (10 - 3), 3);\ | |
490 g = bitcopy_n(v >> (5 - 3), 3);\ | |
491 b = bitcopy_n(v << 3, 3);\ | |
492 } | |
493 | |
494 #define RGB_OUT(d, r, g, b)\ | |
495 {\ | |
496 ((UINT16 *)(d))[0] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | 0x8000;\ | |
497 } | |
498 | |
499 #define BPP 2 | |
500 | |
501 RGB_FUNCTIONS(rgb555) | |
502 | |
503 #undef RGB_IN | |
504 #undef RGB_OUT | |
505 #undef BPP | |
506 | |
507 /* rgb565 handling */ | |
508 | |
509 #define RGB_IN(r, g, b, s)\ | |
510 {\ | |
511 unsigned int v = ((UINT16 *)(s))[0];\ | |
512 r = bitcopy_n(v >> (11 - 3), 3);\ | |
513 g = bitcopy_n(v >> (5 - 2), 2);\ | |
514 b = bitcopy_n(v << 3, 3);\ | |
515 } | |
516 | |
517 #define RGB_OUT(d, r, g, b)\ | |
518 {\ | |
519 ((UINT16 *)(d))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);\ | |
520 } | |
521 | |
522 #define BPP 2 | |
523 | |
524 RGB_FUNCTIONS(rgb565) | |
525 | |
526 #undef RGB_IN | |
527 #undef RGB_OUT | |
528 #undef BPP | |
529 | |
530 /* bgr24 handling */ | |
531 | |
532 #define RGB_IN(r, g, b, s)\ | |
533 {\ | |
534 b = (s)[0];\ | |
535 g = (s)[1];\ | |
536 r = (s)[2];\ | |
537 } | |
538 | |
539 #define RGB_OUT(d, r, g, b)\ | |
540 {\ | |
541 (d)[0] = b;\ | |
542 (d)[1] = g;\ | |
543 (d)[2] = r;\ | |
544 } | |
545 | |
546 #define BPP 3 | |
547 | |
548 RGB_FUNCTIONS(bgr24) | |
549 | |
550 #undef RGB_IN | |
551 #undef RGB_OUT | |
552 #undef BPP | |
553 | |
554 /* rgb24 handling */ | |
555 | |
556 #define RGB_IN(r, g, b, s)\ | |
557 {\ | |
558 r = (s)[0];\ | |
559 g = (s)[1];\ | |
560 b = (s)[2];\ | |
561 } | |
562 | |
563 #define RGB_OUT(d, r, g, b)\ | |
564 {\ | |
565 (d)[0] = r;\ | |
566 (d)[1] = g;\ | |
567 (d)[2] = b;\ | |
568 } | |
569 | |
570 #define BPP 3 | |
571 | |
572 RGB_FUNCTIONS(rgb24) | |
573 | |
574 #undef RGB_IN | |
575 #undef RGB_OUT | |
576 #undef BPP | |
577 | |
578 /* rgba32 handling */ | |
579 | |
580 #define RGB_IN(r, g, b, s)\ | |
581 {\ | |
582 unsigned int v = ((UINT32 *)(s))[0];\ | |
583 r = (v >> 16) & 0xff;\ | |
584 g = (v >> 8) & 0xff;\ | |
585 b = v & 0xff;\ | |
586 } | |
587 | |
588 #define RGB_OUT(d, r, g, b)\ | |
589 {\ | |
590 ((UINT32 *)(d))[0] = (0xff << 24) | (r << 16) | (g << 8) | b;\ | |
591 } | |
592 | |
593 #define BPP 4 | |
594 | |
595 RGB_FUNCTIONS(rgba32) | |
596 | |
597 #undef RGB_IN | |
598 #undef RGB_OUT | |
599 #undef BPP | |
600 | |
601 | |
602 static void rgb24_to_rgb565(AVPicture *dst, AVPicture *src, | |
603 int width, int height) | |
604 { | |
605 const unsigned char *p; | |
606 unsigned char *q; | |
607 int r, g, b, dst_wrap, src_wrap; | |
608 int x, y; | |
609 | |
610 p = src->data[0]; | |
611 src_wrap = src->linesize[0] - 3 * width; | |
612 | |
613 q = dst->data[0]; | |
614 dst_wrap = dst->linesize[0] - 2 * width; | |
615 | |
616 for(y=0;y<height;y++) { | |
617 for(x=0;x<width;x++) { | |
618 r = p[0]; | |
619 g = p[1]; | |
620 b = p[2]; | |
621 | |
622 ((unsigned short *)q)[0] = | |
623 ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); | |
624 q += 2; | |
625 p += 3; | |
626 } | |
627 p += src_wrap; | |
628 q += dst_wrap; | |
629 } | |
630 } | |
631 | |
632 /* NOTE: we also add a dummy alpha bit */ | |
633 static void rgb24_to_rgb555(AVPicture *dst, AVPicture *src, | |
634 int width, int height) | |
635 { | |
636 const unsigned char *p; | |
637 unsigned char *q; | |
638 int r, g, b, dst_wrap, src_wrap; | |
639 int x, y; | |
640 | |
641 p = src->data[0]; | |
642 src_wrap = src->linesize[0] - 3 * width; | |
643 | |
644 q = dst->data[0]; | |
645 dst_wrap = dst->linesize[0] - 2 * width; | |
646 | |
647 for(y=0;y<height;y++) { | |
648 for(x=0;x<width;x++) { | |
649 r = p[0]; | |
650 g = p[1]; | |
651 b = p[2]; | |
652 | |
653 ((unsigned short *)q)[0] = | |
654 ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | 0x8000; | |
655 q += 2; | |
656 p += 3; | |
657 } | |
658 p += src_wrap; | |
659 q += dst_wrap; | |
660 } | |
661 } | |
662 | |
663 static void rgb24_to_gray(AVPicture *dst, AVPicture *src, | |
664 int width, int height) | |
665 { | |
666 const unsigned char *p; | |
667 unsigned char *q; | |
668 int r, g, b, dst_wrap, src_wrap; | |
669 int x, y; | |
670 | |
671 p = src->data[0]; | |
672 src_wrap = src->linesize[0] - 3 * width; | |
673 | |
674 q = dst->data[0]; | |
675 dst_wrap = dst->linesize[0] - width; | |
676 | |
677 for(y=0;y<height;y++) { | |
678 for(x=0;x<width;x++) { | |
679 r = p[0]; | |
680 g = p[1]; | |
681 b = p[2]; | |
682 | |
683 q[0] = (FIX(0.29900) * r + FIX(0.58700) * g + | |
684 FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; | |
685 q++; | |
686 p += 3; | |
687 } | |
688 p += src_wrap; | |
689 q += dst_wrap; | |
690 } | |
691 } | |
692 | |
693 static void gray_to_rgb24(AVPicture *dst, AVPicture *src, | |
694 int width, int height) | |
695 { | |
696 const unsigned char *p; | |
697 unsigned char *q; | |
698 int r, dst_wrap, src_wrap; | |
699 int x, y; | |
700 | |
701 p = src->data[0]; | |
702 src_wrap = src->linesize[0] - width; | |
703 | |
704 q = dst->data[0]; | |
705 dst_wrap = dst->linesize[0] - 3 * width; | |
706 | |
707 for(y=0;y<height;y++) { | |
708 for(x=0;x<width;x++) { | |
709 r = p[0]; | |
710 | |
711 q[0] = r; | |
712 q[1] = r; | |
713 q[2] = r; | |
565 | 714 |
566 /* output 4 pixels */ | 715 q += 3; |
567 RGBOUT(d1[2], d1[1], d1[0], y1_ptr[0]); | 716 p ++; |
568 RGBOUT(d1[6], d1[5], d1[4], y1_ptr[1]); | 717 } |
569 RGBOUT(d2[2], d2[1], d2[0], y2_ptr[0]); | 718 p += src_wrap; |
570 RGBOUT(d2[6], d2[5], d2[4], y2_ptr[1]); | 719 q += dst_wrap; |
571 | 720 } |
572 d1[3] = d1[7] = d2[3] = d2[7] = 255; | 721 } |
573 | 722 |
574 d1 += 8; | 723 static void monowhite_to_rgb24(AVPicture *dst, AVPicture *src, |
575 d2 += 8; | 724 int width, int height) |
576 y1_ptr += 2; | 725 { |
577 y2_ptr += 2; | 726 const unsigned char *p; |
578 cb_ptr++; | 727 unsigned char *q; |
579 cr_ptr++; | 728 int v, dst_wrap, src_wrap; |
580 } | 729 int y, w; |
581 d += 2 * dst->linesize[0]; | 730 |
582 y1_ptr += 2 * src->linesize[0] - width; | 731 p = src->data[0]; |
583 cb_ptr += src->linesize[1] - width2; | 732 src_wrap = src->linesize[0] - ((width + 7) >> 3); |
584 cr_ptr += src->linesize[2] - width2; | 733 |
585 } | 734 q = dst->data[0]; |
586 } | 735 dst_wrap = dst->linesize[0] - 3 * width; |
587 | 736 |
588 /* XXX: no chroma interpolating is done */ | 737 for(y=0;y<height;y++) { |
589 static void yuv420p_to_rgba32(AVPicture *dst, AVPicture *src, | 738 w = width; |
590 int width, int height) | 739 while (w >= 8) { |
591 { | 740 v = *p++ ^ 0xff; |
592 UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2; | 741 q[0] = q[1] = q[2] = -(v >> 7); q += 3; |
593 int w, y, cb, cr, r_add, g_add, b_add, width2; | 742 q[0] = q[1] = q[2] = -((v >> 6) & 1); q += 3; |
594 UINT8 *cm = cropTbl + MAX_NEG_CROP; | 743 q[0] = q[1] = q[2] = -((v >> 5) & 1); q += 3; |
595 | 744 q[0] = q[1] = q[2] = -((v >> 4) & 1); q += 3; |
596 d = dst->data[0]; | 745 q[0] = q[1] = q[2] = -((v >> 3) & 1); q += 3; |
597 y1_ptr = src->data[0]; | 746 q[0] = q[1] = q[2] = -((v >> 2) & 1); q += 3; |
598 cb_ptr = src->data[1]; | 747 q[0] = q[1] = q[2] = -((v >> 1) & 1); q += 3; |
599 cr_ptr = src->data[2]; | 748 q[0] = q[1] = q[2] = -((v >> 0) & 1); q += 3; |
600 width2 = width >> 1; | 749 w -= 8; |
601 for(;height > 0; height -= 2) { | 750 } |
602 d1 = d; | 751 if (w > 0) { |
603 d2 = d + dst->linesize[0]; | 752 v = *p++ ^ 0xff; |
604 y2_ptr = y1_ptr + src->linesize[0]; | 753 do { |
605 for(w = width2; w > 0; w --) { | 754 q[0] = q[1] = q[2] = -((v >> 7) & 1); q += 3; |
606 cb = cb_ptr[0] - 128; | 755 v <<= 1; |
607 cr = cr_ptr[0] - 128; | 756 } while (--w); |
608 r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); | 757 } |
609 g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); | 758 p += src_wrap; |
610 b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); | 759 q += dst_wrap; |
611 | 760 } |
612 /* output 4 pixels */ | 761 } |
613 RGBOUT(d1[0], d1[1], d1[2], y1_ptr[0]); | 762 |
614 RGBOUT(d1[4], d1[5], d1[6], y1_ptr[1]); | 763 static void monoblack_to_rgb24(AVPicture *dst, AVPicture *src, |
615 RGBOUT(d2[0], d2[1], d2[2], y2_ptr[0]); | 764 int width, int height) |
616 RGBOUT(d2[4], d2[5], d2[6], y2_ptr[1]); | 765 { |
617 | 766 const unsigned char *p; |
618 d1[3] = d1[7] = d2[3] = d2[7] = 255; | 767 unsigned char *q; |
619 | 768 int v, dst_wrap, src_wrap; |
620 d1 += 8; | 769 int y, w; |
621 d2 += 8; | 770 |
622 y1_ptr += 2; | 771 p = src->data[0]; |
623 y2_ptr += 2; | 772 src_wrap = src->linesize[0] - ((width + 7) >> 3); |
624 cb_ptr++; | 773 |
625 cr_ptr++; | 774 q = dst->data[0]; |
626 } | 775 dst_wrap = dst->linesize[0] - 3 * width; |
627 d += 2 * dst->linesize[0]; | 776 |
628 y1_ptr += 2 * src->linesize[0] - width; | 777 for(y=0;y<height;y++) { |
629 cb_ptr += src->linesize[1] - width2; | 778 w = width; |
630 cr_ptr += src->linesize[2] - width2; | 779 while (w >= 8) { |
631 } | 780 v = *p++; |
632 } | 781 q[0] = q[1] = q[2] = -(v >> 7); q += 3; |
633 | 782 q[0] = q[1] = q[2] = -((v >> 6) & 1); q += 3; |
634 /* XXX: no chroma interpolating is done */ | 783 q[0] = q[1] = q[2] = -((v >> 5) & 1); q += 3; |
635 static void yuv420p_to_rgb24(AVPicture *dst, AVPicture *src, | 784 q[0] = q[1] = q[2] = -((v >> 4) & 1); q += 3; |
636 int width, int height) | 785 q[0] = q[1] = q[2] = -((v >> 3) & 1); q += 3; |
637 { | 786 q[0] = q[1] = q[2] = -((v >> 2) & 1); q += 3; |
638 UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2; | 787 q[0] = q[1] = q[2] = -((v >> 1) & 1); q += 3; |
639 int w, y, cb, cr, r_add, g_add, b_add, width2; | 788 q[0] = q[1] = q[2] = -((v >> 0) & 1); q += 3; |
640 UINT8 *cm = cropTbl + MAX_NEG_CROP; | 789 w -= 8; |
641 | 790 } |
642 d = dst->data[0]; | 791 if (w > 0) { |
643 y1_ptr = src->data[0]; | 792 v = *p++; |
644 cb_ptr = src->data[1]; | 793 do { |
645 cr_ptr = src->data[2]; | 794 q[0] = q[1] = q[2] = -((v >> 7) & 1); q += 3; |
646 width2 = width >> 1; | 795 v <<= 1; |
647 for(;height > 0; height -= 2) { | 796 } while (--w); |
648 d1 = d; | 797 } |
649 d2 = d + dst->linesize[0]; | 798 p += src_wrap; |
650 y2_ptr = y1_ptr + src->linesize[0]; | 799 q += dst_wrap; |
651 for(w = width2; w > 0; w --) { | 800 } |
652 cb = cb_ptr[0] - 128; | 801 } |
653 cr = cr_ptr[0] - 128; | 802 |
654 r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); | 803 typedef struct ConvertEntry { |
655 g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); | 804 void (*convert)(AVPicture *dst, AVPicture *src, int width, int height); |
656 b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); | 805 } ConvertEntry; |
657 | 806 |
658 /* output 4 pixels */ | 807 /* add each new convertion function in this table */ |
659 RGBOUT(d1[0], d1[1], d1[2], y1_ptr[0]); | 808 /* constraints; |
660 RGBOUT(d1[3], d1[4], d1[5], y1_ptr[1]); | 809 - all non YUV modes must convert at least to and from PIX_FMT_RGB24 |
661 RGBOUT(d2[0], d2[1], d2[2], y2_ptr[0]); | 810 */ |
662 RGBOUT(d2[3], d2[4], d2[5], y2_ptr[1]); | 811 static ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB] = { |
663 | 812 [PIX_FMT_YUV420P] = { |
664 d1 += 6; | 813 [PIX_FMT_RGB555] = { |
665 d2 += 6; | 814 convert: yuv420p_to_rgb555 |
666 y1_ptr += 2; | 815 }, |
667 y2_ptr += 2; | 816 [PIX_FMT_RGB565] = { |
668 cb_ptr++; | 817 convert: yuv420p_to_rgb565 |
669 cr_ptr++; | 818 }, |
670 } | 819 [PIX_FMT_BGR24] = { |
671 d += 2 * dst->linesize[0]; | 820 convert: yuv420p_to_bgr24 |
672 y1_ptr += 2 * src->linesize[0] - width; | 821 }, |
673 cb_ptr += src->linesize[1] - width2; | 822 [PIX_FMT_RGB24] = { |
674 cr_ptr += src->linesize[2] - width2; | 823 convert: yuv420p_to_rgb24 |
675 } | 824 }, |
676 } | 825 [PIX_FMT_RGBA32] = { |
677 | 826 convert: yuv420p_to_rgba32 |
678 /* XXX: no chroma interpolating is done */ | 827 }, |
679 static void yuv422p_to_rgb24(AVPicture *dst, AVPicture *src, | 828 }, |
680 int width, int height) | 829 [PIX_FMT_YUV422P] = { |
681 { | 830 [PIX_FMT_RGB555] = { |
682 UINT8 *y1_ptr, *cb_ptr, *cr_ptr, *d, *d1; | 831 convert: yuv422p_to_rgb555 |
683 int w, y, cb, cr, r_add, g_add, b_add, width2; | 832 }, |
684 UINT8 *cm = cropTbl + MAX_NEG_CROP; | 833 [PIX_FMT_RGB565] = { |
685 | 834 convert: yuv422p_to_rgb565 |
686 d = dst->data[0]; | 835 }, |
687 y1_ptr = src->data[0]; | 836 [PIX_FMT_BGR24] = { |
688 cb_ptr = src->data[1]; | 837 convert: yuv422p_to_bgr24 |
689 cr_ptr = src->data[2]; | 838 }, |
690 width2 = width >> 1; | 839 [PIX_FMT_RGB24] = { |
691 for(;height > 0; height --) { | 840 convert: yuv422p_to_rgb24 |
692 d1 = d; | 841 }, |
693 for(w = width2; w > 0; w --) { | 842 [PIX_FMT_RGBA32] = { |
694 cb = cb_ptr[0] - 128; | 843 convert: yuv422p_to_rgba32 |
695 cr = cr_ptr[0] - 128; | 844 }, |
696 r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); | 845 }, |
697 g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); | 846 [PIX_FMT_YUV422] = { |
698 b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); | 847 [PIX_FMT_YUV420P] = { |
699 | 848 convert: yuv422_to_yuv420p, |
700 /* output 2 pixels */ | 849 }, |
701 RGBOUT(d1[0], d1[1], d1[2], y1_ptr[0]); | 850 }, |
702 RGBOUT(d1[3], d1[4], d1[5], y1_ptr[1]); | 851 |
703 | 852 [PIX_FMT_RGB24] = { |
704 d1 += 6; | 853 [PIX_FMT_YUV420P] = { |
705 y1_ptr += 2; | 854 convert: rgb24_to_yuv420p |
706 cb_ptr++; | 855 }, |
707 cr_ptr++; | 856 [PIX_FMT_RGB565] = { |
708 } | 857 convert: rgb24_to_rgb565 |
709 d += dst->linesize[0]; | 858 }, |
710 y1_ptr += src->linesize[0] - width; | 859 [PIX_FMT_RGB555] = { |
711 cb_ptr += src->linesize[1] - width2; | 860 convert: rgb24_to_rgb555 |
712 cr_ptr += src->linesize[2] - width2; | 861 }, |
713 } | 862 [PIX_FMT_GRAY8] = { |
863 convert: rgb24_to_gray | |
864 }, | |
865 }, | |
866 [PIX_FMT_RGBA32] = { | |
867 [PIX_FMT_YUV420P] = { | |
868 convert: rgba32_to_yuv420p | |
869 }, | |
870 }, | |
871 [PIX_FMT_BGR24] = { | |
872 [PIX_FMT_YUV420P] = { | |
873 convert: bgr24_to_yuv420p | |
874 }, | |
875 }, | |
876 [PIX_FMT_RGB555] = { | |
877 [PIX_FMT_YUV420P] = { | |
878 convert: rgb555_to_yuv420p | |
879 }, | |
880 }, | |
881 [PIX_FMT_RGB565] = { | |
882 [PIX_FMT_YUV420P] = { | |
883 convert: rgb565_to_yuv420p | |
884 }, | |
885 }, | |
886 [PIX_FMT_GRAY8] = { | |
887 [PIX_FMT_RGB24] = { | |
888 convert: gray_to_rgb24 | |
889 }, | |
890 }, | |
891 [PIX_FMT_MONOWHITE] = { | |
892 [PIX_FMT_RGB24] = { | |
893 convert: monowhite_to_rgb24 | |
894 }, | |
895 }, | |
896 [PIX_FMT_MONOBLACK] = { | |
897 [PIX_FMT_RGB24] = { | |
898 convert: monoblack_to_rgb24 | |
899 }, | |
900 }, | |
901 }; | |
902 | |
903 static int avpicture_alloc(AVPicture *picture, | |
904 int pix_fmt, int width, int height) | |
905 { | |
906 int size; | |
907 void *ptr; | |
908 | |
909 size = avpicture_get_size(pix_fmt, width, height); | |
910 if (size < 0) | |
911 goto fail; | |
912 ptr = av_malloc(size); | |
913 if (!ptr) | |
914 goto fail; | |
915 avpicture_fill(picture, ptr, pix_fmt, width, height); | |
916 return 0; | |
917 fail: | |
918 memset(picture, 0, sizeof(AVPicture)); | |
919 return -1; | |
920 } | |
921 | |
922 static void avpicture_free(AVPicture *picture) | |
923 { | |
924 free(picture->data[0]); | |
714 } | 925 } |
715 | 926 |
716 /* XXX: always use linesize. Return -1 if not supported */ | 927 /* XXX: always use linesize. Return -1 if not supported */ |
717 int img_convert(AVPicture *dst, int dst_pix_fmt, | 928 int img_convert(AVPicture *dst, int dst_pix_fmt, |
718 AVPicture *src, int pix_fmt, | 929 AVPicture *src, int src_pix_fmt, |
719 int width, int height) | 930 int src_width, int src_height) |
720 { | 931 { |
721 int i; | 932 int i, ret, dst_width, dst_height; |
722 | 933 PixFmtInfo *src_pix, *dst_pix; |
723 if (dst_pix_fmt == pix_fmt) { | 934 ConvertEntry *ce; |
724 switch(pix_fmt) { | 935 AVPicture tmp1, *tmp = &tmp1; |
725 case PIX_FMT_YUV420P: | 936 |
726 for(i=0;i<3;i++) { | 937 if (src_pix_fmt < 0 || src_pix_fmt >= PIX_FMT_NB || |
727 if (i == 1) { | 938 dst_pix_fmt < 0 || dst_pix_fmt >= PIX_FMT_NB) |
728 width >>= 1; | 939 return -1; |
729 height >>= 1; | 940 if (src_width <= 0 || src_height <= 0) |
730 } | 941 return 0; |
731 img_copy(dst->data[i], dst->linesize[i], | 942 |
732 src->data[i], src->linesize[i], | 943 dst_width = src_width; |
733 width, height); | 944 dst_height = src_height; |
945 | |
946 dst_pix = &pix_fmt_info[dst_pix_fmt]; | |
947 src_pix = &pix_fmt_info[src_pix_fmt]; | |
948 if (src_pix_fmt == dst_pix_fmt) { | |
949 /* same format: just copy */ | |
950 for(i = 0; i < dst_pix->nb_components; i++) { | |
951 int w, h; | |
952 w = dst_width; | |
953 h = dst_height; | |
954 if (dst_pix->is_yuv && (i == 1 || i == 2)) { | |
955 w >>= dst_pix->x_chroma_shift; | |
956 h >>= dst_pix->y_chroma_shift; | |
734 } | 957 } |
735 break; | 958 img_copy(dst->data[i], dst->linesize[i], |
736 default: | 959 src->data[i], src->linesize[i], |
960 w, h); | |
961 } | |
962 return 0; | |
963 } | |
964 | |
965 ce = &convert_table[src_pix_fmt][dst_pix_fmt]; | |
966 if (ce->convert) { | |
967 /* specific convertion routine */ | |
968 ce->convert(dst, src, dst_width, dst_height); | |
969 return 0; | |
970 } | |
971 | |
972 /* if both format are not YUV, try to use RGB24 as common | |
973 format */ | |
974 if (!dst_pix->is_yuv && !src_pix->is_yuv) { | |
975 if (avpicture_alloc(tmp, PIX_FMT_RGB24, dst_width, dst_height) < 0) | |
737 return -1; | 976 return -1; |
738 } | 977 ret = -1; |
739 } else if (dst_pix_fmt == PIX_FMT_YUV420P) { | 978 if (img_convert(tmp, PIX_FMT_RGB24, |
740 | 979 src, src_pix_fmt, src_width, src_height) < 0) |
741 switch(pix_fmt) { | 980 goto fail1; |
742 case PIX_FMT_YUV411P: | 981 if (img_convert(dst, dst_pix_fmt, |
743 img_copy(dst->data[0], dst->linesize[0], | 982 tmp, PIX_FMT_RGB24, dst_width, dst_height) < 0) |
744 src->data[0], src->linesize[0], | 983 goto fail1; |
745 width, height); | 984 ret = 0; |
746 conv411(dst->data[1], dst->linesize[1], | 985 fail1: |
747 src->data[1], src->linesize[1], | 986 avpicture_free(tmp); |
748 width / 4, height); | 987 return ret; |
749 conv411(dst->data[2], dst->linesize[2], | 988 } |
750 src->data[2], src->linesize[2], | 989 |
751 width / 4, height); | 990 /* gray to YUV */ |
752 break; | 991 if (dst_pix->is_yuv && src_pix_fmt == PIX_FMT_GRAY8) { |
753 case PIX_FMT_YUV410P: | 992 int w, h, y; |
754 img_copy(dst->data[0], dst->linesize[0], | 993 uint8_t *d; |
755 src->data[0], src->linesize[0], | 994 |
756 width, height); | 995 img_copy(dst->data[0], dst->linesize[0], |
757 grow22(dst->data[1], dst->linesize[1], | 996 src->data[0], src->linesize[0], |
758 src->data[1], src->linesize[1], | 997 dst_width, dst_height); |
759 width/2, height/2); | 998 /* fill U and V with 128 */ |
760 grow22(dst->data[2], dst->linesize[2], | 999 w = dst_width; |
761 src->data[2], src->linesize[2], | 1000 h = dst_height; |
762 width/2, height/2); | 1001 w >>= dst_pix->x_chroma_shift; |
763 break; | 1002 h >>= dst_pix->y_chroma_shift; |
764 case PIX_FMT_YUV420P: | 1003 for(i = 1; i <= 2; i++) { |
765 for(i=0;i<3;i++) { | 1004 d = dst->data[i]; |
766 img_copy(dst->data[i], dst->linesize[i], | 1005 for(y = 0; y<h; y++) { |
767 src->data[i], src->linesize[i], | 1006 memset(d, 128, 0); |
768 width, height); | 1007 d += dst->linesize[i]; |
769 } | 1008 } |
770 break; | 1009 } |
771 case PIX_FMT_YUV422P: | 1010 return 0; |
772 img_copy(dst->data[0], dst->linesize[0], | 1011 } |
773 src->data[0], src->linesize[0], | 1012 |
774 width, height); | 1013 /* YUV to gray */ |
775 width >>= 1; | 1014 if (src_pix->is_yuv && dst_pix_fmt == PIX_FMT_GRAY8) { |
776 height >>= 1; | 1015 img_copy(dst->data[0], dst->linesize[0], |
777 for(i=1;i<3;i++) { | 1016 src->data[0], src->linesize[0], |
778 shrink2(dst->data[i], dst->linesize[i], | 1017 dst_width, dst_height); |
779 src->data[i], src->linesize[i], | 1018 return 0; |
780 width, height); | 1019 } |
781 } | 1020 |
782 break; | 1021 /* YUV to YUV */ |
783 case PIX_FMT_YUV444P: | 1022 if (dst_pix->is_yuv && src_pix->is_yuv) { |
784 img_copy(dst->data[0], dst->linesize[0], | 1023 int x_shift, y_shift, w, h; |
785 src->data[0], src->linesize[0], | 1024 void (*resize_func)(UINT8 *dst, int dst_wrap, |
786 width, height); | 1025 UINT8 *src, int src_wrap, |
787 width >>= 1; | 1026 int width, int height); |
788 height >>= 1; | 1027 |
789 for(i=1;i<3;i++) { | 1028 /* compute chroma size of the smallest dimensions */ |
790 shrink22(dst->data[i], dst->linesize[i], | 1029 w = dst_width; |
791 src->data[i], src->linesize[i], | 1030 h = dst_height; |
792 width, height); | 1031 if (dst_pix->x_chroma_shift >= src_pix->x_chroma_shift) |
793 } | 1032 w >>= dst_pix->x_chroma_shift; |
794 break; | 1033 else |
795 case PIX_FMT_YUV422: | 1034 w >>= src_pix->x_chroma_shift; |
796 yuv422_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], | 1035 if (dst_pix->y_chroma_shift >= src_pix->y_chroma_shift) |
797 src->data[0], width, height); | 1036 h >>= dst_pix->y_chroma_shift; |
798 break; | 1037 else |
799 case PIX_FMT_RGB24: | 1038 h >>= src_pix->y_chroma_shift; |
800 rgb24_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], | 1039 |
801 src->data[0], width, height); | 1040 x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift); |
802 break; | 1041 y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift); |
803 case PIX_FMT_RGBA32: | 1042 if (x_shift == 0 && y_shift == 0) { |
804 rgba32_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], | 1043 resize_func = img_copy; /* should never happen */ |
805 src->data[0], width, height); | 1044 } else if (x_shift == 0 && y_shift == 1) { |
806 break; | 1045 resize_func = shrink2; |
807 case PIX_FMT_BGR24: | 1046 } else if (x_shift == 1 && y_shift == 1) { |
808 bgr24_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], | 1047 resize_func = shrink22; |
809 src->data[0], width, height); | 1048 } else if (x_shift == -1 && y_shift == -1) { |
810 break; | 1049 resize_func = grow22; |
811 case PIX_FMT_BGRA32: | 1050 } else if (x_shift == -1 && y_shift == 1) { |
812 bgra32_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], | 1051 resize_func = conv411; |
813 src->data[0], width, height); | 1052 } else { |
814 break; | 1053 /* currently not handled */ |
815 case PIX_FMT_RGB565: | |
816 rgb565_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], | |
817 src->data[0], width, height); | |
818 break; | |
819 case PIX_FMT_RGB555: | |
820 rgb555_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], | |
821 src->data[0], width, height); | |
822 break; | |
823 /* case PIX_FMT_RGB5551: | |
824 rgb5551_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], | |
825 src->data[0], width, height); | |
826 break;*/ | |
827 case PIX_FMT_BGR565: | |
828 bgr565_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], | |
829 src->data[0], width, height); | |
830 break; | |
831 case PIX_FMT_BGR555: | |
832 bgr555_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], | |
833 src->data[0], width, height); | |
834 break; | |
835 /* case PIX_FMT_GBR565: | |
836 gbr565_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], | |
837 src->data[0], width, height); | |
838 break; | |
839 case PIX_FMT_GBR555: | |
840 gbr555_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], | |
841 src->data[0], width, height); | |
842 break;*/ | |
843 default: | |
844 return -1; | 1054 return -1; |
845 } | 1055 } |
846 } else if (dst_pix_fmt == PIX_FMT_RGB24) { | 1056 |
847 switch(pix_fmt) { | 1057 img_copy(dst->data[0], dst->linesize[0], |
848 case PIX_FMT_YUV420P: | 1058 src->data[0], src->linesize[0], |
849 yuv420p_to_rgb24(dst, src, width, height); | 1059 dst_width, dst_height); |
850 break; | 1060 for(i = 1;i <= 2; i++) |
851 case PIX_FMT_YUV422P: | 1061 resize_func(dst->data[1], dst->linesize[1], |
852 yuv422p_to_rgb24(dst, src, width, height); | 1062 src->data[1], src->linesize[1], |
853 break; | 1063 w, h); |
854 default: | 1064 } |
855 return -1; | 1065 |
856 } | 1066 /* cannot convert yet */ |
857 } else if (dst_pix_fmt == PIX_FMT_RGBA32) { | 1067 |
858 switch(pix_fmt) { | 1068 return -1; |
859 case PIX_FMT_YUV420P: | |
860 yuv420p_to_rgba32(dst, src, width, height); | |
861 break; | |
862 default: | |
863 return -1; | |
864 } | |
865 } else if (dst_pix_fmt == PIX_FMT_BGRA32) { | |
866 switch(pix_fmt) { | |
867 case PIX_FMT_YUV420P: | |
868 yuv420p_to_bgra32(dst, src, width, height); | |
869 break; | |
870 default: | |
871 return -1; | |
872 } | |
873 } else { | |
874 return -1; | |
875 } | |
876 return 0; | |
877 } | 1069 } |
878 | 1070 |
879 | 1071 |
880 #ifdef HAVE_MMX | 1072 #ifdef HAVE_MMX |
881 #define DEINT_INPLACE_LINE_LUM \ | 1073 #define DEINT_INPLACE_LINE_LUM \ |