looking better all the time! motion compensation is starting to work
[libav.git] / libavcodec / imgconvert.c
CommitLineData
de6d9b64
FB
1/*
2 * Misc image convertion routines
524c6b63 3 * Copyright (c) 2001, 2002, 2003 Fabrice Bellard.
de6d9b64 4 *
ff4ec49e
FB
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
de6d9b64 9 *
ff4ec49e 10 * This library is distributed in the hope that it will be useful,
de6d9b64 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ff4ec49e
FB
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
de6d9b64 14 *
ff4ec49e
FB
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
de6d9b64 18 */
983e3246
MN
19
20/**
1ab3d669 21 * @file imgconvert.c
983e3246
MN
22 * Misc image convertion routines.
23 */
24
c50c0bc8
FB
25/* TODO:
26 * - write 'ffimg' program to test all the image related stuff
27 * - move all api to slice based system
28 * - integrate deinterlacing, postprocessing and scaling in the conversion process
29 */
983e3246 30
de6d9b64 31#include "avcodec.h"
85c242d8 32#include "dsputil.h"
de6d9b64 33
54329dd5
NK
34#ifdef USE_FASTMEMCPY
35#include "fastmemcpy.h"
36#endif
5981f4e6
F
37
38#ifdef HAVE_MMX
39#include "i386/mmx.h"
40#endif
524c6b63 41
7e7e5940
FB
42#define xglue(x, y) x ## y
43#define glue(x, y) xglue(x, y)
44
b6147995
FB
45#define FF_COLOR_RGB 0 /* RGB color space */
46#define FF_COLOR_GRAY 1 /* gray color space */
47#define FF_COLOR_YUV 2 /* YUV color space. 16 <= Y <= 235, 16 <= U, V <= 240 */
48#define FF_COLOR_YUV_JPEG 3 /* YUV color space. 0 <= Y <= 255, 0 <= U, V <= 255 */
49
7e7e5940
FB
50#define FF_PIXEL_PLANAR 0 /* each channel has one component in AVPicture */
51#define FF_PIXEL_PACKED 1 /* only one components containing all the channels */
52#define FF_PIXEL_PALETTE 2 /* one components containing indexes for a palette */
53
524c6b63
FB
54typedef struct PixFmtInfo {
55 const char *name;
7e7e5940
FB
56 uint8_t nb_channels; /* number of channels (including alpha) */
57 uint8_t color_type; /* color type (see FF_COLOR_xxx constants) */
58 uint8_t pixel_type; /* pixel storage type (see FF_PIXEL_xxx constants) */
0c1a9eda 59 uint8_t is_alpha : 1; /* true if alpha can be specified */
7e7e5940
FB
60 uint8_t x_chroma_shift; /* X chroma subsampling factor is 2 ^ shift */
61 uint8_t y_chroma_shift; /* Y chroma subsampling factor is 2 ^ shift */
62 uint8_t depth; /* bit depth of the color components */
524c6b63
FB
63} PixFmtInfo;
64
65/* this table gives more information about formats */
66static PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
67 /* YUV formats */
68 [PIX_FMT_YUV420P] = {
ef9f7306 69 .name = "yuv420p",
7e7e5940 70 .nb_channels = 3,
b6147995 71 .color_type = FF_COLOR_YUV,
7e7e5940 72 .pixel_type = FF_PIXEL_PLANAR,
b6147995 73 .depth = 8,
ef9f7306 74 .x_chroma_shift = 1, .y_chroma_shift = 1,
524c6b63
FB
75 },
76 [PIX_FMT_YUV422P] = {
ef9f7306 77 .name = "yuv422p",
7e7e5940 78 .nb_channels = 3,
b6147995 79 .color_type = FF_COLOR_YUV,
7e7e5940 80 .pixel_type = FF_PIXEL_PLANAR,
b6147995 81 .depth = 8,
ef9f7306 82 .x_chroma_shift = 1, .y_chroma_shift = 0,
524c6b63
FB
83 },
84 [PIX_FMT_YUV444P] = {
ef9f7306 85 .name = "yuv444p",
7e7e5940 86 .nb_channels = 3,
b6147995 87 .color_type = FF_COLOR_YUV,
7e7e5940 88 .pixel_type = FF_PIXEL_PLANAR,
b6147995 89 .depth = 8,
ef9f7306 90 .x_chroma_shift = 0, .y_chroma_shift = 0,
524c6b63
FB
91 },
92 [PIX_FMT_YUV422] = {
ef9f7306 93 .name = "yuv422",
7e7e5940 94 .nb_channels = 1,
b6147995 95 .color_type = FF_COLOR_YUV,
7e7e5940 96 .pixel_type = FF_PIXEL_PACKED,
b6147995 97 .depth = 8,
ef9f7306 98 .x_chroma_shift = 1, .y_chroma_shift = 0,
524c6b63
FB
99 },
100 [PIX_FMT_YUV410P] = {
ef9f7306 101 .name = "yuv410p",
7e7e5940 102 .nb_channels = 3,
b6147995 103 .color_type = FF_COLOR_YUV,
7e7e5940 104 .pixel_type = FF_PIXEL_PLANAR,
b6147995 105 .depth = 8,
ef9f7306 106 .x_chroma_shift = 2, .y_chroma_shift = 2,
524c6b63
FB
107 },
108 [PIX_FMT_YUV411P] = {
ef9f7306 109 .name = "yuv411p",
7e7e5940 110 .nb_channels = 3,
b6147995 111 .color_type = FF_COLOR_YUV,
7e7e5940 112 .pixel_type = FF_PIXEL_PLANAR,
b6147995 113 .depth = 8,
ef9f7306 114 .x_chroma_shift = 2, .y_chroma_shift = 0,
524c6b63
FB
115 },
116
b6147995
FB
117 /* JPEG YUV */
118 [PIX_FMT_YUVJ420P] = {
119 .name = "yuvj420p",
7e7e5940 120 .nb_channels = 3,
b6147995 121 .color_type = FF_COLOR_YUV_JPEG,
7e7e5940 122 .pixel_type = FF_PIXEL_PLANAR,
b6147995
FB
123 .depth = 8,
124 .x_chroma_shift = 1, .y_chroma_shift = 1,
125 },
126 [PIX_FMT_YUVJ422P] = {
127 .name = "yuvj422p",
7e7e5940 128 .nb_channels = 3,
b6147995 129 .color_type = FF_COLOR_YUV_JPEG,
7e7e5940 130 .pixel_type = FF_PIXEL_PLANAR,
b6147995
FB
131 .depth = 8,
132 .x_chroma_shift = 1, .y_chroma_shift = 0,
133 },
134 [PIX_FMT_YUVJ444P] = {
135 .name = "yuvj444p",
7e7e5940 136 .nb_channels = 3,
b6147995 137 .color_type = FF_COLOR_YUV_JPEG,
7e7e5940 138 .pixel_type = FF_PIXEL_PLANAR,
b6147995
FB
139 .depth = 8,
140 .x_chroma_shift = 0, .y_chroma_shift = 0,
141 },
142
524c6b63
FB
143 /* RGB formats */
144 [PIX_FMT_RGB24] = {
ef9f7306 145 .name = "rgb24",
7e7e5940 146 .nb_channels = 3,
b6147995 147 .color_type = FF_COLOR_RGB,
7e7e5940 148 .pixel_type = FF_PIXEL_PACKED,
b6147995 149 .depth = 8,
524c6b63
FB
150 },
151 [PIX_FMT_BGR24] = {
ef9f7306 152 .name = "bgr24",
7e7e5940 153 .nb_channels = 3,
b6147995 154 .color_type = FF_COLOR_RGB,
7e7e5940 155 .pixel_type = FF_PIXEL_PACKED,
b6147995 156 .depth = 8,
524c6b63
FB
157 },
158 [PIX_FMT_RGBA32] = {
ef9f7306 159 .name = "rgba32",
7e7e5940 160 .nb_channels = 4, .is_alpha = 1,
b6147995 161 .color_type = FF_COLOR_RGB,
7e7e5940 162 .pixel_type = FF_PIXEL_PACKED,
b6147995 163 .depth = 8,
524c6b63
FB
164 },
165 [PIX_FMT_RGB565] = {
ef9f7306 166 .name = "rgb565",
7e7e5940 167 .nb_channels = 3,
b6147995 168 .color_type = FF_COLOR_RGB,
7e7e5940 169 .pixel_type = FF_PIXEL_PACKED,
b6147995 170 .depth = 5,
524c6b63
FB
171 },
172 [PIX_FMT_RGB555] = {
ef9f7306 173 .name = "rgb555",
7e7e5940 174 .nb_channels = 4, .is_alpha = 1,
b6147995 175 .color_type = FF_COLOR_RGB,
7e7e5940 176 .pixel_type = FF_PIXEL_PACKED,
b6147995 177 .depth = 5,
524c6b63
FB
178 },
179
180 /* gray / mono formats */
181 [PIX_FMT_GRAY8] = {
ef9f7306 182 .name = "gray",
7e7e5940 183 .nb_channels = 1,
b6147995 184 .color_type = FF_COLOR_GRAY,
7e7e5940 185 .pixel_type = FF_PIXEL_PLANAR,
b6147995 186 .depth = 8,
524c6b63
FB
187 },
188 [PIX_FMT_MONOWHITE] = {
ef9f7306 189 .name = "monow",
7e7e5940 190 .nb_channels = 1,
b6147995 191 .color_type = FF_COLOR_GRAY,
7e7e5940 192 .pixel_type = FF_PIXEL_PLANAR,
b6147995 193 .depth = 1,
524c6b63
FB
194 },
195 [PIX_FMT_MONOBLACK] = {
ef9f7306 196 .name = "monob",
7e7e5940 197 .nb_channels = 1,
b6147995 198 .color_type = FF_COLOR_GRAY,
7e7e5940 199 .pixel_type = FF_PIXEL_PLANAR,
b6147995 200 .depth = 1,
524c6b63 201 },
7e6d70d0
FB
202
203 /* paletted formats */
204 [PIX_FMT_PAL8] = {
205 .name = "pal8",
7e7e5940 206 .nb_channels = 4, .is_alpha = 1,
b6147995 207 .color_type = FF_COLOR_RGB,
7e7e5940 208 .pixel_type = FF_PIXEL_PALETTE,
b6147995 209 .depth = 8,
7e6d70d0 210 },
524c6b63
FB
211};
212
213void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift)
214{
b6147995
FB
215 *h_shift = pix_fmt_info[pix_fmt].x_chroma_shift;
216 *v_shift = pix_fmt_info[pix_fmt].y_chroma_shift;
524c6b63
FB
217}
218
219const char *avcodec_get_pix_fmt_name(int pix_fmt)
220{
221 if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB)
222 return "???";
223 else
224 return pix_fmt_info[pix_fmt].name;
225}
226
2a877875 227/* Picture field are filled with 'ptr' addresses. Also return size */
0c1a9eda 228int avpicture_fill(AVPicture *picture, uint8_t *ptr,
2a877875
FB
229 int pix_fmt, int width, int height)
230{
4c7e8619
FB
231 int size, w2, h2, size2;
232 PixFmtInfo *pinfo;
233
234 pinfo = &pix_fmt_info[pix_fmt];
2a877875
FB
235 size = width * height;
236 switch(pix_fmt) {
237 case PIX_FMT_YUV420P:
4c7e8619
FB
238 case PIX_FMT_YUV422P:
239 case PIX_FMT_YUV444P:
240 case PIX_FMT_YUV410P:
241 case PIX_FMT_YUV411P:
c50c0bc8
FB
242 case PIX_FMT_YUVJ420P:
243 case PIX_FMT_YUVJ422P:
244 case PIX_FMT_YUVJ444P:
4c7e8619
FB
245 w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift;
246 h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift;
247 size2 = w2 * h2;
2a877875
FB
248 picture->data[0] = ptr;
249 picture->data[1] = picture->data[0] + size;
4c7e8619 250 picture->data[2] = picture->data[1] + size2;
2a877875 251 picture->linesize[0] = width;
4c7e8619
FB
252 picture->linesize[1] = w2;
253 picture->linesize[2] = w2;
254 return size + 2 * size2;
2a877875
FB
255 case PIX_FMT_RGB24:
256 case PIX_FMT_BGR24:
257 picture->data[0] = ptr;
258 picture->data[1] = NULL;
259 picture->data[2] = NULL;
260 picture->linesize[0] = width * 3;
261 return size * 3;
2a877875
FB
262 case PIX_FMT_RGBA32:
263 picture->data[0] = ptr;
264 picture->data[1] = NULL;
265 picture->data[2] = NULL;
266 picture->linesize[0] = width * 4;
267 return size * 4;
2a877875
FB
268 case PIX_FMT_RGB555:
269 case PIX_FMT_RGB565:
270 case PIX_FMT_YUV422:
271 picture->data[0] = ptr;
272 picture->data[1] = NULL;
273 picture->data[2] = NULL;
274 picture->linesize[0] = width * 2;
275 return size * 2;
276 case PIX_FMT_GRAY8:
277 picture->data[0] = ptr;
278 picture->data[1] = NULL;
279 picture->data[2] = NULL;
280 picture->linesize[0] = width;
281 return size;
282 case PIX_FMT_MONOWHITE:
283 case PIX_FMT_MONOBLACK:
284 picture->data[0] = ptr;
285 picture->data[1] = NULL;
286 picture->data[2] = NULL;
287 picture->linesize[0] = (width + 7) >> 3;
288 return picture->linesize[0] * height;
7e6d70d0
FB
289 case PIX_FMT_PAL8:
290 size2 = (size + 3) & ~3;
291 picture->data[0] = ptr;
292 picture->data[1] = ptr + size2; /* palette is stored here as 256 32 bit words */
293 picture->data[2] = NULL;
294 picture->linesize[0] = width;
295 picture->linesize[1] = 4;
296 return size2 + 256 * 4;
2a877875
FB
297 default:
298 picture->data[0] = NULL;
299 picture->data[1] = NULL;
300 picture->data[2] = NULL;
7e6d70d0 301 picture->data[3] = NULL;
2a877875
FB
302 return -1;
303 }
304}
305
306int avpicture_get_size(int pix_fmt, int width, int height)
307{
308 AVPicture dummy_pict;
309 return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height);
310}
311
b6147995
FB
312/**
313 * compute the loss when converting from a pixel format to another
314 */
315int avcodec_get_pix_fmt_loss(int dst_pix_fmt, int src_pix_fmt,
316 int has_alpha)
317{
318 const PixFmtInfo *pf, *ps;
319 int loss;
320
321 ps = &pix_fmt_info[src_pix_fmt];
322 pf = &pix_fmt_info[dst_pix_fmt];
323
324 /* compute loss */
325 loss = 0;
326 pf = &pix_fmt_info[dst_pix_fmt];
0a9ad8d1
FB
327 if (pf->depth < ps->depth ||
328 (dst_pix_fmt == PIX_FMT_RGB555 && src_pix_fmt == PIX_FMT_RGB565))
b6147995 329 loss |= FF_LOSS_DEPTH;
0a9ad8d1
FB
330 if (pf->x_chroma_shift > ps->x_chroma_shift ||
331 pf->y_chroma_shift > ps->y_chroma_shift)
b6147995
FB
332 loss |= FF_LOSS_RESOLUTION;
333 switch(pf->color_type) {
334 case FF_COLOR_RGB:
335 if (ps->color_type != FF_COLOR_RGB &&
336 ps->color_type != FF_COLOR_GRAY)
337 loss |= FF_LOSS_COLORSPACE;
338 break;
339 case FF_COLOR_GRAY:
340 if (ps->color_type != FF_COLOR_GRAY)
341 loss |= FF_LOSS_COLORSPACE;
342 break;
343 case FF_COLOR_YUV:
344 if (ps->color_type != FF_COLOR_YUV)
345 loss |= FF_LOSS_COLORSPACE;
346 break;
347 case FF_COLOR_YUV_JPEG:
348 if (ps->color_type != FF_COLOR_YUV_JPEG &&
0a9ad8d1
FB
349 ps->color_type != FF_COLOR_YUV &&
350 ps->color_type != FF_COLOR_GRAY)
b6147995
FB
351 loss |= FF_LOSS_COLORSPACE;
352 break;
353 default:
354 /* fail safe test */
355 if (ps->color_type != pf->color_type)
356 loss |= FF_LOSS_COLORSPACE;
357 break;
358 }
359 if (pf->color_type == FF_COLOR_GRAY &&
360 ps->color_type != FF_COLOR_GRAY)
361 loss |= FF_LOSS_CHROMA;
362 if (!pf->is_alpha && (ps->is_alpha && has_alpha))
363 loss |= FF_LOSS_ALPHA;
7e7e5940
FB
364 if (pf->pixel_type == FF_PIXEL_PALETTE &&
365 (ps->pixel_type != FF_PIXEL_PALETTE && ps->color_type != FF_COLOR_GRAY))
b6147995
FB
366 loss |= FF_LOSS_COLORQUANT;
367 return loss;
368}
369
370static int avg_bits_per_pixel(int pix_fmt)
371{
372 int bits;
373 const PixFmtInfo *pf;
374
375 pf = &pix_fmt_info[pix_fmt];
7e7e5940
FB
376 switch(pf->pixel_type) {
377 case FF_PIXEL_PACKED:
b6147995 378 switch(pix_fmt) {
7e7e5940 379 case PIX_FMT_YUV422:
b6147995
FB
380 case PIX_FMT_RGB565:
381 case PIX_FMT_RGB555:
382 bits = 16;
b6147995
FB
383 break;
384 default:
7e7e5940 385 bits = pf->depth * pf->nb_channels;
b6147995
FB
386 break;
387 }
7e7e5940
FB
388 break;
389 case FF_PIXEL_PLANAR:
390 if (pf->x_chroma_shift == 0 && pf->y_chroma_shift == 0) {
391 bits = pf->depth * pf->nb_channels;
392 } else {
393 bits = pf->depth + ((2 * pf->depth) >>
394 (pf->x_chroma_shift + pf->y_chroma_shift));
395 }
396 break;
397 case FF_PIXEL_PALETTE:
398 bits = 8;
399 break;
400 default:
401 bits = -1;
402 break;
b6147995
FB
403 }
404 return bits;
405}
406
407static int avcodec_find_best_pix_fmt1(int pix_fmt_mask,
408 int src_pix_fmt,
409 int has_alpha,
410 int loss_mask)
411{
412 int dist, i, loss, min_dist, dst_pix_fmt;
413
414 /* find exact color match with smallest size */
415 dst_pix_fmt = -1;
416 min_dist = 0x7fffffff;
417 for(i = 0;i < PIX_FMT_NB; i++) {
418 if (pix_fmt_mask & (1 << i)) {
419 loss = avcodec_get_pix_fmt_loss(i, src_pix_fmt, has_alpha) & loss_mask;
420 if (loss == 0) {
421 dist = avg_bits_per_pixel(i);
422 if (dist < min_dist) {
423 min_dist = dist;
424 dst_pix_fmt = i;
425 }
426 }
427 }
428 }
429 return dst_pix_fmt;
430}
431
432/**
433 * find best pixel format to convert to. Return -1 if none found
434 */
435int avcodec_find_best_pix_fmt(int pix_fmt_mask, int src_pix_fmt,
436 int has_alpha, int *loss_ptr)
437{
438 int dst_pix_fmt, loss_mask, i;
439 static const int loss_mask_order[] = {
440 ~0, /* no loss first */
441 ~FF_LOSS_ALPHA,
442 ~FF_LOSS_RESOLUTION,
443 ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION),
444 ~FF_LOSS_COLORQUANT,
445 ~FF_LOSS_DEPTH,
446 0,
447 };
448
449 /* try with successive loss */
450 i = 0;
451 for(;;) {
452 loss_mask = loss_mask_order[i++];
453 dst_pix_fmt = avcodec_find_best_pix_fmt1(pix_fmt_mask, src_pix_fmt,
454 has_alpha, loss_mask);
455 if (dst_pix_fmt >= 0)
456 goto found;
457 if (loss_mask == 0)
458 break;
459 }
460 return -1;
461 found:
462 if (loss_ptr)
463 *loss_ptr = avcodec_get_pix_fmt_loss(dst_pix_fmt, src_pix_fmt, has_alpha);
464 return dst_pix_fmt;
465}
466
7e7e5940 467static void img_copy_plane(uint8_t *dst, int dst_wrap,
e352ff08
FB
468 const uint8_t *src, int src_wrap,
469 int width, int height)
7e7e5940
FB
470{
471 for(;height > 0; height--) {
472 memcpy(dst, src, width);
473 dst += dst_wrap;
474 src += src_wrap;
475 }
476}
477
0469baf1
FB
478/**
479 * Copy image 'src' to 'dst'.
480 */
7e7e5940
FB
481void img_copy(AVPicture *dst, AVPicture *src,
482 int pix_fmt, int width, int height)
483{
484 int bwidth, bits, i;
485 PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
486
487 pf = &pix_fmt_info[pix_fmt];
488 switch(pf->pixel_type) {
489 case FF_PIXEL_PACKED:
490 switch(pix_fmt) {
491 case PIX_FMT_YUV422:
492 case PIX_FMT_RGB565:
493 case PIX_FMT_RGB555:
494 bits = 16;
495 break;
496 default:
497 bits = pf->depth * pf->nb_channels;
498 break;
499 }
500 bwidth = (width * bits + 7) >> 3;
501 img_copy_plane(dst->data[0], dst->linesize[0],
502 src->data[0], src->linesize[0],
503 bwidth, height);
504 break;
505 case FF_PIXEL_PLANAR:
506 for(i = 0; i < pf->nb_channels; i++) {
507 int w, h;
508 w = width;
509 h = height;
510 if (i == 1 || i == 2) {
511 w >>= pf->x_chroma_shift;
512 h >>= pf->y_chroma_shift;
513 }
514 bwidth = (w * pf->depth + 7) >> 3;
515 img_copy_plane(dst->data[i], dst->linesize[i],
516 src->data[i], src->linesize[i],
517 bwidth, h);
518 }
519 break;
520 case FF_PIXEL_PALETTE:
521 img_copy_plane(dst->data[0], dst->linesize[0],
522 src->data[0], src->linesize[0],
523 width, height);
524 /* copy the palette */
525 img_copy_plane(dst->data[1], dst->linesize[1],
526 src->data[1], src->linesize[1],
527 4, 256);
528 break;
529 }
530}
2a877875 531
de6d9b64
FB
532/* XXX: totally non optimized */
533
524c6b63
FB
534static void yuv422_to_yuv420p(AVPicture *dst, AVPicture *src,
535 int width, int height)
de6d9b64 536{
c50c0bc8
FB
537 const uint8_t *p, *p1;
538 uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
539 int x;
524c6b63 540
c50c0bc8
FB
541 p1 = src->data[0];
542 lum1 = dst->data[0];
0a05e494
FB
543 cb1 = dst->data[1];
544 cr1 = dst->data[2];
c50c0bc8
FB
545
546 for(;height >= 2; height -= 2) {
547 p = p1;
548 lum = lum1;
549 cb = cb1;
550 cr = cr1;
de6d9b64 551 for(x=0;x<width;x+=2) {
e78df699
MN
552 lum[0] = p[0];
553 cb[0] = p[1];
554 lum[1] = p[2];
555 cr[0] = p[3];
de6d9b64
FB
556 p += 4;
557 lum += 2;
558 cb++;
559 cr++;
560 }
c50c0bc8
FB
561 p1 += src->linesize[0];
562 lum1 += dst->linesize[0];
563 p = p1;
564 lum = lum1;
de6d9b64 565 for(x=0;x<width;x+=2) {
e78df699
MN
566 lum[0] = p[0];
567 lum[1] = p[2];
de6d9b64
FB
568 p += 4;
569 lum += 2;
570 }
c50c0bc8
FB
571 p1 += src->linesize[0];
572 lum1 += dst->linesize[0];
573 cb1 += dst->linesize[1];
574 cr1 += dst->linesize[2];
575 }
576}
577
578static void yuv422_to_yuv422p(AVPicture *dst, AVPicture *src,
579 int width, int height)
580{
581 const uint8_t *p, *p1;
582 uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
583 int w;
584
585 p1 = src->data[0];
586 lum1 = dst->data[0];
0a05e494
FB
587 cb1 = dst->data[1];
588 cr1 = dst->data[2];
589 for(;height > 0; height--) {
c50c0bc8
FB
590 p = p1;
591 lum = lum1;
592 cb = cb1;
593 cr = cr1;
594 for(w = width; w >= 2; w -= 2) {
595 lum[0] = p[0];
596 cb[0] = p[1];
597 lum[1] = p[2];
598 cr[0] = p[3];
599 p += 4;
600 lum += 2;
601 cb++;
602 cr++;
603 }
604 p1 += src->linesize[0];
605 lum1 += dst->linesize[0];
606 cb1 += dst->linesize[1];
607 cr1 += dst->linesize[2];
de6d9b64
FB
608 }
609}
610
c50c0bc8
FB
611static void yuv422p_to_yuv422(AVPicture *dst, AVPicture *src,
612 int width, int height)
613{
614 uint8_t *p, *p1;
615 const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1;
616 int w;
617
618 p1 = dst->data[0];
619 lum1 = src->data[0];
0a05e494
FB
620 cb1 = src->data[1];
621 cr1 = src->data[2];
622 for(;height > 0; height--) {
c50c0bc8
FB
623 p = p1;
624 lum = lum1;
625 cb = cb1;
626 cr = cr1;
627 for(w = width; w >= 2; w -= 2) {
628 p[0] = lum[0];
629 p[1] = cb[0];
630 p[2] = lum[1];
631 p[3] = cr[0];
632 p += 4;
633 lum += 2;
634 cb++;
635 cr++;
636 }
0a05e494
FB
637 p1 += dst->linesize[0];
638 lum1 += src->linesize[0];
639 cb1 += src->linesize[1];
640 cr1 += src->linesize[2];
c50c0bc8
FB
641 }
642}
643
644#define SCALEBITS 10
de6d9b64 645#define ONE_HALF (1 << (SCALEBITS - 1))
c50c0bc8 646#define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
de6d9b64 647
c50c0bc8
FB
648#define YUV_TO_RGB1_CCIR(cb1, cr1)\
649{\
650 cb = (cb1) - 128;\
651 cr = (cr1) - 128;\
652 r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF;\
653 g_add = - FIX(0.34414*255.0/224.0) * cb - FIX(0.71414*255.0/224.0) * cr + \
654 ONE_HALF;\
655 b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;\
656}
b6147995 657
c50c0bc8
FB
658#define YUV_TO_RGB2_CCIR(r, g, b, y1)\
659{\
660 y = ((y1) - 16) * FIX(255.0/219.0);\
661 r = cm[(y + r_add) >> SCALEBITS];\
662 g = cm[(y + g_add) >> SCALEBITS];\
663 b = cm[(y + b_add) >> SCALEBITS];\
664}
665
666#define YUV_TO_RGB1(cb1, cr1)\
667{\
668 cb = (cb1) - 128;\
669 cr = (cr1) - 128;\
670 r_add = FIX(1.40200) * cr + ONE_HALF;\
671 g_add = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;\
672 b_add = FIX(1.77200) * cb + ONE_HALF;\
673}
b6147995
FB
674
675#define YUV_TO_RGB2(r, g, b, y1)\
676{\
c50c0bc8
FB
677 y = (y1) << SCALEBITS;\
678 r = cm[(y + r_add) >> SCALEBITS];\
679 g = cm[(y + g_add) >> SCALEBITS];\
680 b = cm[(y + b_add) >> SCALEBITS];\
b6147995
FB
681}
682
c50c0bc8 683#define Y_CCIR_TO_JPEG(y)\
b6147995
FB
684 cm[((y) * FIX(255.0/219.0) + (ONE_HALF - 16 * FIX(255.0/219.0))) >> SCALEBITS]
685
c50c0bc8 686#define Y_JPEG_TO_CCIR(y)\
b6147995
FB
687 (((y) * FIX(219.0/255.0) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
688
c50c0bc8
FB
689#define C_CCIR_TO_JPEG(y)\
690 cm[(((y) - 128) * FIX(127.0/112.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS]
691
692/* NOTE: the clamp is really necessary! */
693#define C_JPEG_TO_CCIR(y)\
694({\
695 int __y;\
696 __y = ((((y) - 128) * FIX(112.0/127.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS);\
697 if (__y < 16)\
698 __y = 16;\
699 __y;\
700})
701
b6147995
FB
702#define RGB_TO_Y(r, g, b) \
703((FIX(0.29900) * (r) + FIX(0.58700) * (g) + \
704 FIX(0.11400) * (b) + ONE_HALF) >> SCALEBITS)
705
c50c0bc8 706#define RGB_TO_U(r1, g1, b1, shift)\
b6147995 707(((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \
c50c0bc8 708 FIX(0.50000) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
b6147995 709
c50c0bc8 710#define RGB_TO_V(r1, g1, b1, shift)\
b6147995 711(((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \
c50c0bc8 712 FIX(0.08131) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
b6147995
FB
713
714#define RGB_TO_Y_CCIR(r, g, b) \
715((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \
716 FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
717
c50c0bc8 718#define RGB_TO_U_CCIR(r1, g1, b1, shift)\
b6147995 719(((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \
c50c0bc8 720 FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
b6147995 721
c50c0bc8 722#define RGB_TO_V_CCIR(r1, g1, b1, shift)\
b6147995 723(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \
c50c0bc8 724 FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
b6147995 725
c50c0bc8
FB
726static uint8_t y_ccir_to_jpeg[256];
727static uint8_t y_jpeg_to_ccir[256];
728static uint8_t c_ccir_to_jpeg[256];
729static uint8_t c_jpeg_to_ccir[256];
730
731/* init various conversion tables */
732static void img_convert_init(void)
b6147995 733{
c50c0bc8 734 int i;
b6147995
FB
735 uint8_t *cm = cropTbl + MAX_NEG_CROP;
736
c50c0bc8
FB
737 for(i = 0;i < 256; i++) {
738 y_ccir_to_jpeg[i] = Y_CCIR_TO_JPEG(i);
739 y_jpeg_to_ccir[i] = Y_JPEG_TO_CCIR(i);
740 c_ccir_to_jpeg[i] = C_CCIR_TO_JPEG(i);
741 c_jpeg_to_ccir[i] = C_JPEG_TO_CCIR(i);
b6147995
FB
742 }
743}
744
c50c0bc8
FB
745/* apply to each pixel the given table */
746static void img_apply_table(uint8_t *dst, int dst_wrap,
747 const uint8_t *src, int src_wrap,
748 int width, int height, const uint8_t *table1)
b6147995
FB
749{
750 int n;
751 const uint8_t *s;
752 uint8_t *d;
c50c0bc8 753 const uint8_t *table;
b6147995 754
c50c0bc8 755 table = table1;
b6147995
FB
756 for(;height > 0; height--) {
757 s = src;
758 d = dst;
759 n = width;
760 while (n >= 4) {
c50c0bc8
FB
761 d[0] = table[s[0]];
762 d[1] = table[s[1]];
763 d[2] = table[s[2]];
764 d[3] = table[s[3]];
b6147995
FB
765 d += 4;
766 s += 4;
767 n -= 4;
768 }
769 while (n > 0) {
c50c0bc8 770 d[0] = table[s[0]];
b6147995
FB
771 d++;
772 s++;
773 n--;
774 }
775 dst += dst_wrap;
776 src += src_wrap;
777 }
778}
779
85c242d8 780/* XXX: use generic filter ? */
e352ff08
FB
781/* XXX: in most cases, the sampling position is incorrect */
782
783/* 4x1 -> 1x1 */
784static void shrink41(uint8_t *dst, int dst_wrap,
785 const uint8_t *src, int src_wrap,
786 int width, int height)
787{
788 int w;
789 const uint8_t *s;
790 uint8_t *d;
791
792 for(;height > 0; height--) {
793 s = src;
794 d = dst;
795 for(w = width;w > 0; w--) {
796 d[0] = (s[0] + s[1] + s[2] + s[3] + 2) >> 2;
797 s += 4;
798 d++;
799 }
800 src += src_wrap;
801 dst += dst_wrap;
802 }
803}
804
805/* 2x1 -> 1x1 */
806static void shrink21(uint8_t *dst, int dst_wrap,
807 const uint8_t *src, int src_wrap,
808 int width, int height)
809{
810 int w;
811 const uint8_t *s;
812 uint8_t *d;
813
814 for(;height > 0; height--) {
815 s = src;
816 d = dst;
817 for(w = width;w > 0; w--) {
818 d[0] = (s[0] + s[1]) >> 1;
819 s += 2;
820 d++;
821 }
822 src += src_wrap;
823 dst += dst_wrap;
824 }
825}
826
85c242d8 827/* 1x2 -> 1x1 */
e352ff08
FB
828static void shrink12(uint8_t *dst, int dst_wrap,
829 const uint8_t *src, int src_wrap,
830 int width, int height)
85c242d8
FB
831{
832 int w;
e352ff08
FB
833 uint8_t *d;
834 const uint8_t *s1, *s2;
85c242d8
FB
835
836 for(;height > 0; height--) {
837 s1 = src;
838 s2 = s1 + src_wrap;
839 d = dst;
840 for(w = width;w >= 4; w-=4) {
841 d[0] = (s1[0] + s2[0]) >> 1;
842 d[1] = (s1[1] + s2[1]) >> 1;
843 d[2] = (s1[2] + s2[2]) >> 1;
844 d[3] = (s1[3] + s2[3]) >> 1;
845 s1 += 4;
846 s2 += 4;
847 d += 4;
848 }
849 for(;w > 0; w--) {
850 d[0] = (s1[0] + s2[0]) >> 1;
851 s1++;
852 s2++;
853 d++;
854 }
855 src += 2 * src_wrap;
856 dst += dst_wrap;
857 }
858}
859
860/* 2x2 -> 1x1 */
0c1a9eda 861static void shrink22(uint8_t *dst, int dst_wrap,
e352ff08 862 const uint8_t *src, int src_wrap,
85c242d8
FB
863 int width, int height)
864{
865 int w;
e352ff08
FB
866 const uint8_t *s1, *s2;
867 uint8_t *d;
85c242d8
FB
868
869 for(;height > 0; height--) {
870 s1 = src;
871 s2 = s1 + src_wrap;
872 d = dst;
873 for(w = width;w >= 4; w-=4) {
0a9ad8d1
FB
874 d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
875 d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2;
876 d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2;
877 d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2;
85c242d8
FB
878 s1 += 8;
879 s2 += 8;
880 d += 4;
881 }
882 for(;w > 0; w--) {
0a9ad8d1 883 d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2;
85c242d8
FB
884 s1 += 2;
885 s2 += 2;
886 d++;
887 }
888 src += 2 * src_wrap;
889 dst += dst_wrap;
890 }
891}
892
e352ff08
FB
893/* 4x4 -> 1x1 */
894static void shrink44(uint8_t *dst, int dst_wrap,
895 const uint8_t *src, int src_wrap,
6742d95d
FR
896 int width, int height)
897{
898 int w;
e352ff08
FB
899 const uint8_t *s1, *s2, *s3, *s4;
900 uint8_t *d;
6742d95d
FR
901
902 for(;height > 0; height--) {
903 s1 = src;
e352ff08
FB
904 s2 = s1 + src_wrap;
905 s3 = s2 + src_wrap;
906 s4 = s3 + src_wrap;
6742d95d 907 d = dst;
e352ff08
FB
908 for(w = width;w > 0; w--) {
909 d[0] = (s1[0] + s1[1] + s1[2] + s1[3] +
910 s2[0] + s2[1] + s2[2] + s2[3] +
911 s3[0] + s3[1] + s3[2] + s3[3] +
912 s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4;
913 s1 += 4;
914 s2 += 4;
915 s3 += 4;
916 s4 += 4;
6742d95d
FR
917 d++;
918 }
e352ff08
FB
919 src += 4 * src_wrap;
920 dst += dst_wrap;
921 }
922}
923
924static void grow21_line(uint8_t *dst, const uint8_t *src,
925 int width)
926{
927 int w;
928 const uint8_t *s1;
929 uint8_t *d;
930
931 s1 = src;
932 d = dst;
933 for(w = width;w >= 4; w-=4) {
934 d[1] = d[0] = s1[0];
935 d[3] = d[2] = s1[1];
936 s1 += 2;
937 d += 4;
938 }
939 for(;w >= 2; w -= 2) {
940 d[1] = d[0] = s1[0];
941 s1 ++;
942 d += 2;
943 }
944 /* only needed if width is not a multiple of two */
945 /* XXX: veryfy that */
946 if (w) {
947 d[0] = s1[0];
948 }
949}
950
951static void grow41_line(uint8_t *dst, const uint8_t *src,
952 int width)
953{
954 int w, v;
955 const uint8_t *s1;
956 uint8_t *d;
957
958 s1 = src;
959 d = dst;
960 for(w = width;w >= 4; w-=4) {
961 v = s1[0];
962 d[0] = v;
963 d[1] = v;
964 d[2] = v;
965 d[3] = v;
966 s1 ++;
967 d += 4;
968 }
969}
970
971/* 1x1 -> 2x1 */
972static void grow21(uint8_t *dst, int dst_wrap,
973 const uint8_t *src, int src_wrap,
974 int width, int height)
975{
976 for(;height > 0; height--) {
977 grow21_line(dst, src, width);
978 src += src_wrap;
979 dst += dst_wrap;
980 }
981}
982
983/* 1x1 -> 2x2 */
984static void grow22(uint8_t *dst, int dst_wrap,
985 const uint8_t *src, int src_wrap,
986 int width, int height)
987{
988 for(;height > 0; height--) {
989 grow21_line(dst, src, width);
6742d95d
FR
990 if (height%2)
991 src += src_wrap;
992 dst += dst_wrap;
993 }
994}
995
e352ff08
FB
996/* 1x1 -> 4x1 */
997static void grow41(uint8_t *dst, int dst_wrap,
998 const uint8_t *src, int src_wrap,
999 int width, int height)
1000{
1001 for(;height > 0; height--) {
1002 grow41_line(dst, src, width);
1003 src += src_wrap;
1004 dst += dst_wrap;
1005 }
1006}
1007
1008/* 1x1 -> 4x4 */
1009static void grow44(uint8_t *dst, int dst_wrap,
1010 const uint8_t *src, int src_wrap,
1011 int width, int height)
1012{
1013 for(;height > 0; height--) {
1014 grow41_line(dst, src, width);
1015 if ((height & 3) == 1)
1016 src += src_wrap;
1017 dst += dst_wrap;
1018 }
1019}
1020
524c6b63 1021/* 1x2 -> 2x1 */
0c1a9eda 1022static void conv411(uint8_t *dst, int dst_wrap,
e352ff08 1023 const uint8_t *src, int src_wrap,
789587d5
FB
1024 int width, int height)
1025{
1026 int w, c;
e352ff08
FB
1027 const uint8_t *s1, *s2;
1028 uint8_t *d;
789587d5 1029
50643575
MN
1030 width>>=1;
1031
524c6b63 1032 for(;height > 0; height--) {
789587d5
FB
1033 s1 = src;
1034 s2 = src + src_wrap;
1035 d = dst;
1036 for(w = width;w > 0; w--) {
1037 c = (s1[0] + s2[0]) >> 1;
1038 d[0] = c;
1039 d[1] = c;
1040 s1++;
1041 s2++;
1042 d += 2;
1043 }
1044 src += src_wrap * 2;
1045 dst += dst_wrap;
1046 }
1047}
1048
7e7e5940
FB
1049/* XXX: add jpeg quantize code */
1050
1051#define TRANSP_INDEX (6*6*6)
1052
1053/* this is maybe slow, but allows for extensions */
1054static inline unsigned char gif_clut_index(uint8_t r, uint8_t g, uint8_t b)
85c242d8 1055{
7e7e5940 1056 return ((((r)/47)%6)*6*6+(((g)/47)%6)*6+(((b)/47)%6));
85c242d8
FB
1057}
1058
7e7e5940
FB
1059static void build_rgb_palette(uint8_t *palette, int has_alpha)
1060{
1061 uint32_t *pal;
1062 static const uint8_t pal_value[6] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff };
1063 int i, r, g, b;
1064
1065 pal = (uint32_t *)palette;
1066 i = 0;
1067 for(r = 0; r < 6; r++) {
1068 for(g = 0; g < 6; g++) {
1069 for(b = 0; b < 6; b++) {
1070 pal[i++] = (0xff << 24) | (pal_value[r] << 16) |
1071 (pal_value[g] << 8) | pal_value[b];
1072 }
1073 }
1074 }
1075 if (has_alpha)
1076 pal[i++] = 0;
1077 while (i < 256)
1078 pal[i++] = 0xff000000;
524c6b63
FB
1079}
1080
1081/* copy bit n to bits 0 ... n - 1 */
1082static inline unsigned int bitcopy_n(unsigned int a, int n)
b71472eb 1083{
524c6b63
FB
1084 int mask;
1085 mask = (1 << n) - 1;
1086 return (a & (0xff & ~mask)) | ((-((a >> n) & 1)) & mask);
1087}
1088
1089/* rgb555 handling */
1090
7e7e5940
FB
1091#define RGB_NAME rgb555
1092
524c6b63
FB
1093#define RGB_IN(r, g, b, s)\
1094{\
0c1a9eda 1095 unsigned int v = ((const uint16_t *)(s))[0];\
524c6b63
FB
1096 r = bitcopy_n(v >> (10 - 3), 3);\
1097 g = bitcopy_n(v >> (5 - 3), 3);\
1098 b = bitcopy_n(v << 3, 3);\
1099}
1100
7e7e5940 1101#define RGBA_IN(r, g, b, a, s)\
524c6b63 1102{\
7e7e5940
FB
1103 unsigned int v = ((const uint16_t *)(s))[0];\
1104 r = bitcopy_n(v >> (10 - 3), 3);\
1105 g = bitcopy_n(v >> (5 - 3), 3);\
1106 b = bitcopy_n(v << 3, 3);\
b5ff5e22 1107 a = (-(v >> 15)) & 0xff;\
7e7e5940
FB
1108}
1109
1110#define RGBA_OUT(d, r, g, b, a)\
1111{\
1112 ((uint16_t *)(d))[0] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | \
1113 ((a << 8) & 0x8000);\
524c6b63
FB
1114}
1115
1116#define BPP 2
1117
7e7e5940 1118#include "imgconvert_template.h"
524c6b63
FB
1119
1120/* rgb565 handling */
1121
7e7e5940
FB
1122#define RGB_NAME rgb565
1123
524c6b63
FB
1124#define RGB_IN(r, g, b, s)\
1125{\
0c1a9eda 1126 unsigned int v = ((const uint16_t *)(s))[0];\
524c6b63
FB
1127 r = bitcopy_n(v >> (11 - 3), 3);\
1128 g = bitcopy_n(v >> (5 - 2), 2);\
1129 b = bitcopy_n(v << 3, 3);\
1130}
1131
1132#define RGB_OUT(d, r, g, b)\
1133{\
0c1a9eda 1134 ((uint16_t *)(d))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);\
524c6b63
FB
1135}
1136
1137#define BPP 2
1138
7e7e5940 1139#include "imgconvert_template.h"
524c6b63
FB
1140
1141/* bgr24 handling */
1142
7e7e5940
FB
1143#define RGB_NAME bgr24
1144
524c6b63
FB
1145#define RGB_IN(r, g, b, s)\
1146{\
1147 b = (s)[0];\
1148 g = (s)[1];\
1149 r = (s)[2];\
1150}
1151
1152#define RGB_OUT(d, r, g, b)\
1153{\
1154 (d)[0] = b;\
1155 (d)[1] = g;\
1156 (d)[2] = r;\
1157}
1158
1159#define BPP 3
1160
7e7e5940 1161#include "imgconvert_template.h"
524c6b63
FB
1162
1163#undef RGB_IN
1164#undef RGB_OUT
1165#undef BPP
1166
1167/* rgb24 handling */
1168
7e7e5940
FB
1169#define RGB_NAME rgb24
1170#define FMT_RGB24
1171
524c6b63
FB
1172#define RGB_IN(r, g, b, s)\
1173{\
1174 r = (s)[0];\
1175 g = (s)[1];\
1176 b = (s)[2];\
1177}
1178
1179#define RGB_OUT(d, r, g, b)\
1180{\
1181 (d)[0] = r;\
1182 (d)[1] = g;\
1183 (d)[2] = b;\
1184}
1185
1186#define BPP 3
1187
7e7e5940 1188#include "imgconvert_template.h"
524c6b63
FB
1189
1190/* rgba32 handling */
1191
7e7e5940
FB
1192#define RGB_NAME rgba32
1193#define FMT_RGBA32
1194
524c6b63
FB
1195#define RGB_IN(r, g, b, s)\
1196{\
0c1a9eda 1197 unsigned int v = ((const uint32_t *)(s))[0];\
524c6b63
FB
1198 r = (v >> 16) & 0xff;\
1199 g = (v >> 8) & 0xff;\
1200 b = v & 0xff;\
1201}
1202
7e7e5940 1203#define RGBA_IN(r, g, b, a, s)\
524c6b63 1204{\
7e7e5940
FB
1205 unsigned int v = ((const uint32_t *)(s))[0];\
1206 a = (v >> 24) & 0xff;\
1207 r = (v >> 16) & 0xff;\
1208 g = (v >> 8) & 0xff;\
1209 b = v & 0xff;\
524c6b63
FB
1210}
1211
7e7e5940
FB
1212#define RGBA_OUT(d, r, g, b, a)\
1213{\
1214 ((uint32_t *)(d))[0] = (a << 24) | (r << 16) | (g << 8) | b;\
b71472eb
PG
1215}
1216
7e7e5940 1217#define BPP 4
524c6b63 1218
7e7e5940 1219#include "imgconvert_template.h"
b71472eb 1220
2a877875
FB
1221static void mono_to_gray(AVPicture *dst, AVPicture *src,
1222 int width, int height, int xor_mask)
524c6b63
FB
1223{
1224 const unsigned char *p;
1225 unsigned char *q;
1226 int v, dst_wrap, src_wrap;
1227 int y, w;
1228
1229 p = src->data[0];
1230 src_wrap = src->linesize[0] - ((width + 7) >> 3);
1231
1232 q = dst->data[0];
2a877875 1233 dst_wrap = dst->linesize[0] - width;
524c6b63
FB
1234 for(y=0;y<height;y++) {
1235 w = width;
1236 while (w >= 8) {
2a877875
FB
1237 v = *p++ ^ xor_mask;
1238 q[0] = -(v >> 7);
1239 q[1] = -((v >> 6) & 1);
1240 q[2] = -((v >> 5) & 1);
1241 q[3] = -((v >> 4) & 1);
1242 q[4] = -((v >> 3) & 1);
1243 q[5] = -((v >> 2) & 1);
1244 q[6] = -((v >> 1) & 1);
1245 q[7] = -((v >> 0) & 1);
524c6b63 1246 w -= 8;
2a877875 1247 q += 8;
524c6b63
FB
1248 }
1249 if (w > 0) {
2a877875 1250 v = *p++ ^ xor_mask;
524c6b63 1251 do {
2a877875
FB
1252 q[0] = -((v >> 7) & 1);
1253 q++;
524c6b63
FB
1254 v <<= 1;
1255 } while (--w);
85c242d8 1256 }
524c6b63
FB
1257 p += src_wrap;
1258 q += dst_wrap;
85c242d8
FB
1259 }
1260}
1261
2a877875 1262static void monowhite_to_gray(AVPicture *dst, AVPicture *src,
524c6b63
FB
1263 int width, int height)
1264{
2a877875
FB
1265 mono_to_gray(dst, src, width, height, 0xff);
1266}
524c6b63 1267
2a877875
FB
1268static void monoblack_to_gray(AVPicture *dst, AVPicture *src,
1269 int width, int height)
1270{
1271 mono_to_gray(dst, src, width, height, 0x00);
1272}
524c6b63 1273
2a877875
FB
1274static void gray_to_mono(AVPicture *dst, AVPicture *src,
1275 int width, int height, int xor_mask)
1276{
1277 int n;
0c1a9eda
ZK
1278 const uint8_t *s;
1279 uint8_t *d;
2a877875
FB
1280 int j, b, v, n1, src_wrap, dst_wrap, y;
1281
1282 s = src->data[0];
1283 src_wrap = src->linesize[0] - width;
1284
1285 d = dst->data[0];
1286 dst_wrap = dst->linesize[0] - ((width + 7) >> 3);
524c6b63
FB
1287
1288 for(y=0;y<height;y++) {
2a877875
FB
1289 n = width;
1290 while (n >= 8) {
1291 v = 0;
1292 for(j=0;j<8;j++) {
1293 b = s[0];
1294 s++;
1295 v = (v << 1) | (b >> 7);
1296 }
1297 d[0] = v ^ xor_mask;
1298 d++;
1299 n -= 8;
524c6b63 1300 }
2a877875
FB
1301 if (n > 0) {
1302 n1 = n;
1303 v = 0;
1304 while (n > 0) {
1305 b = s[0];
1306 s++;
1307 v = (v << 1) | (b >> 7);
1308 n--;
1309 }
1310 d[0] = (v << (8 - (n1 & 7))) ^ xor_mask;
1311 d++;
524c6b63 1312 }
2a877875
FB
1313 s += src_wrap;
1314 d += dst_wrap;
524c6b63
FB
1315 }
1316}
1317
2a877875
FB
1318static void gray_to_monowhite(AVPicture *dst, AVPicture *src,
1319 int width, int height)
1320{
1321 gray_to_mono(dst, src, width, height, 0xff);
1322}
1323
1324static void gray_to_monoblack(AVPicture *dst, AVPicture *src,
1325 int width, int height)
1326{
1327 gray_to_mono(dst, src, width, height, 0x00);
1328}
1329
524c6b63
FB
1330typedef struct ConvertEntry {
1331 void (*convert)(AVPicture *dst, AVPicture *src, int width, int height);
1332} ConvertEntry;
1333
c50c0bc8
FB
1334/* Add each new convertion function in this table. In order to be able
1335 to convert from any format to any format, the following constraints
1336 must be satisfied:
1337
1338 - all FF_COLOR_RGB formats must convert to and from PIX_FMT_RGB24
1339
1340 - all FF_COLOR_GRAY formats must convert to and from PIX_FMT_GRAY8
1341
1342 - all FF_COLOR_RGB formats with alpha must convert to and from PIX_FMT_RGBA32
1343
e352ff08 1344 - PIX_FMT_YUV444P and PIX_FMT_YUVJ444P must convert to and from
c50c0bc8
FB
1345 PIX_FMT_RGB24.
1346
1347 - PIX_FMT_422 must convert to and from PIX_FMT_422P.
e352ff08
FB
1348
1349 The other conversion functions are just optimisations for common cases.
524c6b63
FB
1350*/
1351static ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB] = {
1352 [PIX_FMT_YUV420P] = {
1353 [PIX_FMT_RGB555] = {
ef9f7306 1354 .convert = yuv420p_to_rgb555
524c6b63
FB
1355 },
1356 [PIX_FMT_RGB565] = {
ef9f7306 1357 .convert = yuv420p_to_rgb565
524c6b63
FB
1358 },
1359 [PIX_FMT_BGR24] = {
ef9f7306 1360 .convert = yuv420p_to_bgr24
524c6b63
FB
1361 },
1362 [PIX_FMT_RGB24] = {
ef9f7306 1363 .convert = yuv420p_to_rgb24
524c6b63
FB
1364 },
1365 [PIX_FMT_RGBA32] = {
ef9f7306 1366 .convert = yuv420p_to_rgba32
524c6b63
FB
1367 },
1368 },
c50c0bc8
FB
1369 [PIX_FMT_YUV422P] = {
1370 [PIX_FMT_YUV422] = {
1371 .convert = yuv422p_to_yuv422,
1372 },
1373 },
1374 [PIX_FMT_YUV444P] = {
1375 [PIX_FMT_RGB24] = {
1376 .convert = yuv444p_to_rgb24
1377 },
1378 },
1379 [PIX_FMT_YUVJ420P] = {
524c6b63 1380 [PIX_FMT_RGB555] = {
c50c0bc8 1381 .convert = yuvj420p_to_rgb555
524c6b63
FB
1382 },
1383 [PIX_FMT_RGB565] = {
c50c0bc8 1384 .convert = yuvj420p_to_rgb565
524c6b63
FB
1385 },
1386 [PIX_FMT_BGR24] = {
c50c0bc8 1387 .convert = yuvj420p_to_bgr24
524c6b63
FB
1388 },
1389 [PIX_FMT_RGB24] = {
c50c0bc8 1390 .convert = yuvj420p_to_rgb24
524c6b63
FB
1391 },
1392 [PIX_FMT_RGBA32] = {
c50c0bc8
FB
1393 .convert = yuvj420p_to_rgba32
1394 },
1395 },
1396 [PIX_FMT_YUVJ444P] = {
1397 [PIX_FMT_RGB24] = {
1398 .convert = yuvj444p_to_rgb24
524c6b63
FB
1399 },
1400 },
1401 [PIX_FMT_YUV422] = {
1402 [PIX_FMT_YUV420P] = {
ef9f7306 1403 .convert = yuv422_to_yuv420p,
524c6b63 1404 },
c50c0bc8
FB
1405 [PIX_FMT_YUV422P] = {
1406 .convert = yuv422_to_yuv422p,
1407 },
524c6b63
FB
1408 },
1409
1410 [PIX_FMT_RGB24] = {
1411 [PIX_FMT_YUV420P] = {
ef9f7306 1412 .convert = rgb24_to_yuv420p
524c6b63
FB
1413 },
1414 [PIX_FMT_RGB565] = {
ef9f7306 1415 .convert = rgb24_to_rgb565
524c6b63
FB
1416 },
1417 [PIX_FMT_RGB555] = {
ef9f7306 1418 .convert = rgb24_to_rgb555
524c6b63 1419 },
7e7e5940
FB
1420 [PIX_FMT_RGBA32] = {
1421 .convert = rgb24_to_rgba32
1422 },
1423 [PIX_FMT_BGR24] = {
1424 .convert = rgb24_to_bgr24
1425 },
524c6b63 1426 [PIX_FMT_GRAY8] = {
ef9f7306 1427 .convert = rgb24_to_gray
524c6b63 1428 },
7e7e5940 1429 [PIX_FMT_PAL8] = {
7e6d70d0
FB
1430 .convert = rgb24_to_pal8
1431 },
c50c0bc8
FB
1432 [PIX_FMT_YUV444P] = {
1433 .convert = rgb24_to_yuv444p
1434 },
1435 [PIX_FMT_YUVJ420P] = {
1436 .convert = rgb24_to_yuvj420p
1437 },
1438 [PIX_FMT_YUVJ444P] = {
1439 .convert = rgb24_to_yuvj444p
1440 },
524c6b63
FB
1441 },
1442 [PIX_FMT_RGBA32] = {
7e7e5940
FB
1443 [PIX_FMT_RGB24] = {
1444 .convert = rgba32_to_rgb24
1445 },
1446 [PIX_FMT_RGB555] = {
1447 .convert = rgba32_to_rgb555
1448 },
1449 [PIX_FMT_PAL8] = {
1450 .convert = rgba32_to_pal8
1451 },
524c6b63 1452 [PIX_FMT_YUV420P] = {
ef9f7306 1453 .convert = rgba32_to_yuv420p
524c6b63 1454 },
69572401
FB
1455 [PIX_FMT_GRAY8] = {
1456 .convert = rgba32_to_gray
1457 },
524c6b63
FB
1458 },
1459 [PIX_FMT_BGR24] = {
7e7e5940
FB
1460 [PIX_FMT_RGB24] = {
1461 .convert = bgr24_to_rgb24
1462 },
524c6b63 1463 [PIX_FMT_YUV420P] = {
ef9f7306 1464 .convert = bgr24_to_yuv420p
524c6b63 1465 },
69572401
FB
1466 [PIX_FMT_GRAY8] = {
1467 .convert = bgr24_to_gray
1468 },
524c6b63
FB
1469 },
1470 [PIX_FMT_RGB555] = {
7e7e5940
FB
1471 [PIX_FMT_RGB24] = {
1472 .convert = rgb555_to_rgb24
1473 },
1474 [PIX_FMT_RGBA32] = {
1475 .convert = rgb555_to_rgba32
1476 },
524c6b63 1477 [PIX_FMT_YUV420P] = {
ef9f7306 1478 .convert = rgb555_to_yuv420p
524c6b63 1479 },
69572401
FB
1480 [PIX_FMT_GRAY8] = {
1481 .convert = rgb555_to_gray
1482 },
524c6b63
FB
1483 },
1484 [PIX_FMT_RGB565] = {
7e7e5940
FB
1485 [PIX_FMT_RGB24] = {
1486 .convert = rgb565_to_rgb24
1487 },
524c6b63 1488 [PIX_FMT_YUV420P] = {
ef9f7306 1489 .convert = rgb565_to_yuv420p
524c6b63 1490 },
69572401
FB
1491 [PIX_FMT_GRAY8] = {
1492 .convert = rgb565_to_gray
1493 },
524c6b63
FB
1494 },
1495 [PIX_FMT_GRAY8] = {
69572401
FB
1496 [PIX_FMT_RGB555] = {
1497 .convert = gray_to_rgb555
1498 },
1499 [PIX_FMT_RGB565] = {
1500 .convert = gray_to_rgb565
1501 },
524c6b63 1502 [PIX_FMT_RGB24] = {
ef9f7306 1503 .convert = gray_to_rgb24
524c6b63 1504 },
69572401
FB
1505 [PIX_FMT_BGR24] = {
1506 .convert = gray_to_bgr24
1507 },
1508 [PIX_FMT_RGBA32] = {
1509 .convert = gray_to_rgba32
1510 },
2a877875 1511 [PIX_FMT_MONOWHITE] = {
ef9f7306 1512 .convert = gray_to_monowhite
2a877875
FB
1513 },
1514 [PIX_FMT_MONOBLACK] = {
ef9f7306 1515 .convert = gray_to_monoblack
2a877875 1516 },
524c6b63
FB
1517 },
1518 [PIX_FMT_MONOWHITE] = {
2a877875 1519 [PIX_FMT_GRAY8] = {
ef9f7306 1520 .convert = monowhite_to_gray
524c6b63
FB
1521 },
1522 },
1523 [PIX_FMT_MONOBLACK] = {
2a877875 1524 [PIX_FMT_GRAY8] = {
ef9f7306 1525 .convert = monoblack_to_gray
524c6b63
FB
1526 },
1527 },
7e6d70d0
FB
1528 [PIX_FMT_PAL8] = {
1529 [PIX_FMT_RGB555] = {
1530 .convert = pal8_to_rgb555
1531 },
1532 [PIX_FMT_RGB565] = {
1533 .convert = pal8_to_rgb565
1534 },
1535 [PIX_FMT_BGR24] = {
1536 .convert = pal8_to_bgr24
1537 },
1538 [PIX_FMT_RGB24] = {
1539 .convert = pal8_to_rgb24
1540 },
1541 [PIX_FMT_RGBA32] = {
1542 .convert = pal8_to_rgba32
1543 },
1544 },
524c6b63
FB
1545};
1546
1547static int avpicture_alloc(AVPicture *picture,
1548 int pix_fmt, int width, int height)
1549{
5c91a675 1550 unsigned int size;
524c6b63
FB
1551 void *ptr;
1552
1553 size = avpicture_get_size(pix_fmt, width, height);
1554 if (size < 0)
1555 goto fail;
1556 ptr = av_malloc(size);
1557 if (!ptr)
1558 goto fail;
1559 avpicture_fill(picture, ptr, pix_fmt, width, height);
1560 return 0;
1561 fail:
1562 memset(picture, 0, sizeof(AVPicture));
1563 return -1;
1564}
1565
1566static void avpicture_free(AVPicture *picture)
1567{
8e1e6f31 1568 av_free(picture->data[0]);
524c6b63
FB
1569}
1570
c50c0bc8
FB
1571/* return true if yuv planar */
1572static inline int is_yuv_planar(PixFmtInfo *ps)
1573{
1574 return (ps->color_type == FF_COLOR_YUV ||
7e7e5940
FB
1575 ps->color_type == FF_COLOR_YUV_JPEG) &&
1576 ps->pixel_type == FF_PIXEL_PLANAR;
c50c0bc8
FB
1577}
1578
85c242d8
FB
1579/* XXX: always use linesize. Return -1 if not supported */
1580int img_convert(AVPicture *dst, int dst_pix_fmt,
524c6b63
FB
1581 AVPicture *src, int src_pix_fmt,
1582 int src_width, int src_height)
85c242d8 1583{
c50c0bc8 1584 static int inited;
2a877875 1585 int i, ret, dst_width, dst_height, int_pix_fmt;
524c6b63
FB
1586 PixFmtInfo *src_pix, *dst_pix;
1587 ConvertEntry *ce;
1588 AVPicture tmp1, *tmp = &tmp1;
1589
1590 if (src_pix_fmt < 0 || src_pix_fmt >= PIX_FMT_NB ||
1591 dst_pix_fmt < 0 || dst_pix_fmt >= PIX_FMT_NB)
1592 return -1;
1593 if (src_width <= 0 || src_height <= 0)
1594 return 0;
69572401 1595
c50c0bc8
FB
1596 if (!inited) {
1597 inited = 1;
1598 img_convert_init();
1599 }
1600
524c6b63
FB
1601 dst_width = src_width;
1602 dst_height = src_height;
69572401 1603
524c6b63
FB
1604 dst_pix = &pix_fmt_info[dst_pix_fmt];
1605 src_pix = &pix_fmt_info[src_pix_fmt];
1606 if (src_pix_fmt == dst_pix_fmt) {
7e7e5940
FB
1607 /* no conversion needed: just copy */
1608 img_copy(dst, src, dst_pix_fmt, dst_width, dst_height);
524c6b63
FB
1609 return 0;
1610 }
1611
1612 ce = &convert_table[src_pix_fmt][dst_pix_fmt];
1613 if (ce->convert) {
1614 /* specific convertion routine */
1615 ce->convert(dst, src, dst_width, dst_height);
1616 return 0;
1617 }
1618
524c6b63 1619 /* gray to YUV */
c50c0bc8 1620 if (is_yuv_planar(dst_pix) &&
b6147995 1621 src_pix_fmt == PIX_FMT_GRAY8) {
524c6b63
FB
1622 int w, h, y;
1623 uint8_t *d;
1624
b6147995 1625 if (dst_pix->color_type == FF_COLOR_YUV_JPEG) {
7e7e5940 1626 img_copy_plane(dst->data[0], dst->linesize[0],
b6147995
FB
1627 src->data[0], src->linesize[0],
1628 dst_width, dst_height);
1629 } else {
c50c0bc8
FB
1630 img_apply_table(dst->data[0], dst->linesize[0],
1631 src->data[0], src->linesize[0],
1632 dst_width, dst_height,
1633 y_jpeg_to_ccir);
b6147995 1634 }
524c6b63
FB
1635 /* fill U and V with 128 */
1636 w = dst_width;
1637 h = dst_height;
1638 w >>= dst_pix->x_chroma_shift;
1639 h >>= dst_pix->y_chroma_shift;
1640 for(i = 1; i <= 2; i++) {
1641 d = dst->data[i];
2a877875
FB
1642 for(y = 0; y< h; y++) {
1643 memset(d, 128, w);
524c6b63
FB
1644 d += dst->linesize[i];
1645 }
b71472eb 1646 }
524c6b63
FB
1647 return 0;
1648 }
1649
1650 /* YUV to gray */
c50c0bc8 1651 if (is_yuv_planar(src_pix) &&
b6147995
FB
1652 dst_pix_fmt == PIX_FMT_GRAY8) {
1653 if (src_pix->color_type == FF_COLOR_YUV_JPEG) {
7e7e5940 1654 img_copy_plane(dst->data[0], dst->linesize[0],
b6147995
FB
1655 src->data[0], src->linesize[0],
1656 dst_width, dst_height);
1657 } else {
c50c0bc8
FB
1658 img_apply_table(dst->data[0], dst->linesize[0],
1659 src->data[0], src->linesize[0],
1660 dst_width, dst_height,
1661 y_ccir_to_jpeg);
b6147995 1662 }
524c6b63
FB
1663 return 0;
1664 }
1665
c50c0bc8
FB
1666 /* YUV to YUV planar */
1667 if (is_yuv_planar(dst_pix) && is_yuv_planar(src_pix)) {
e352ff08 1668 int x_shift, y_shift, w, h, xy_shift;
0c1a9eda 1669 void (*resize_func)(uint8_t *dst, int dst_wrap,
e352ff08 1670 const uint8_t *src, int src_wrap,
524c6b63
FB
1671 int width, int height);
1672
1673 /* compute chroma size of the smallest dimensions */
1674 w = dst_width;
1675 h = dst_height;
1676 if (dst_pix->x_chroma_shift >= src_pix->x_chroma_shift)
1677 w >>= dst_pix->x_chroma_shift;
1678 else
1679 w >>= src_pix->x_chroma_shift;
1680 if (dst_pix->y_chroma_shift >= src_pix->y_chroma_shift)
1681 h >>= dst_pix->y_chroma_shift;
1682 else
1683 h >>= src_pix->y_chroma_shift;
1684
1685 x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift);
1686 y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift);
e352ff08
FB
1687 xy_shift = ((x_shift & 0xf) << 4) | (y_shift & 0xf);
1688 /* there must be filters for conversion at least from and to
1689 YUV444 format */
1690 switch(xy_shift) {
1691 case 0x00:
7e7e5940 1692 resize_func = img_copy_plane;
e352ff08
FB
1693 break;
1694 case 0x10:
1695 resize_func = shrink21;
1696 break;
1697 case 0x20:
1698 resize_func = shrink41;
1699 break;
1700 case 0x01:
1701 resize_func = shrink12;
1702 break;
1703 case 0x11:
524c6b63 1704 resize_func = shrink22;
e352ff08
FB
1705 break;
1706 case 0x22:
1707 resize_func = shrink44;
1708 break;
1709 case 0xf0:
1710 resize_func = grow21;
1711 break;
1712 case 0xe0:
1713 resize_func = grow41;
1714 break;
1715 case 0xff:
524c6b63 1716 resize_func = grow22;
e352ff08
FB
1717 break;
1718 case 0xee:
1719 resize_func = grow44;
1720 break;
1721 case 0xf1:
524c6b63 1722 resize_func = conv411;
e352ff08
FB
1723 break;
1724 default:
524c6b63 1725 /* currently not handled */
e352ff08 1726 goto no_chroma_filter;
85c242d8 1727 }
524c6b63 1728
7e7e5940
FB
1729 img_copy_plane(dst->data[0], dst->linesize[0],
1730 src->data[0], src->linesize[0],
1731 dst_width, dst_height);
566986ee 1732
524c6b63 1733 for(i = 1;i <= 2; i++)
566986ee
MK
1734 resize_func(dst->data[i], dst->linesize[i],
1735 src->data[i], src->linesize[i],
185fdc54 1736 dst_width>>dst_pix->x_chroma_shift, dst_height>>dst_pix->y_chroma_shift);
c50c0bc8
FB
1737 /* if yuv color space conversion is needed, we do it here on
1738 the destination image */
1739 if (dst_pix->color_type != src_pix->color_type) {
1740 const uint8_t *y_table, *c_table;
1741 if (dst_pix->color_type == FF_COLOR_YUV) {
1742 y_table = y_jpeg_to_ccir;
1743 c_table = c_jpeg_to_ccir;
1744 } else {
1745 y_table = y_ccir_to_jpeg;
1746 c_table = c_ccir_to_jpeg;
1747 }
1748 img_apply_table(dst->data[0], dst->linesize[0],
1749 dst->data[0], dst->linesize[0],
1750 dst_width, dst_height,
1751 y_table);
1752
1753 for(i = 1;i <= 2; i++)
1754 img_apply_table(dst->data[i], dst->linesize[i],
1755 dst->data[i], dst->linesize[i],
1756 dst_width>>dst_pix->x_chroma_shift,
1757 dst_height>>dst_pix->y_chroma_shift,
1758 c_table);
1759 }
1760 return 0;
85c242d8 1761 }
e352ff08 1762 no_chroma_filter:
524c6b63 1763
2a877875 1764 /* try to use an intermediate format */
c50c0bc8
FB
1765 if (src_pix_fmt == PIX_FMT_YUV422 ||
1766 dst_pix_fmt == PIX_FMT_YUV422) {
1767 /* specific case: convert to YUV422P first */
1768 int_pix_fmt = PIX_FMT_YUV422P;
1769 } else if ((src_pix->color_type == FF_COLOR_GRAY &&
1770 src_pix_fmt != PIX_FMT_GRAY8) ||
1771 (dst_pix->color_type == FF_COLOR_GRAY &&
1772 dst_pix_fmt != PIX_FMT_GRAY8)) {
1773 /* gray8 is the normalized format */
2a877875 1774 int_pix_fmt = PIX_FMT_GRAY8;
c50c0bc8
FB
1775 } else if ((is_yuv_planar(src_pix) &&
1776 src_pix_fmt != PIX_FMT_YUV444P &&
1777 src_pix_fmt != PIX_FMT_YUVJ444P)) {
1778 /* yuv444 is the normalized format */
1779 if (src_pix->color_type == FF_COLOR_YUV_JPEG)
1780 int_pix_fmt = PIX_FMT_YUVJ444P;
1781 else
1782 int_pix_fmt = PIX_FMT_YUV444P;
1783 } else if ((is_yuv_planar(dst_pix) &&
1784 dst_pix_fmt != PIX_FMT_YUV444P &&
1785 dst_pix_fmt != PIX_FMT_YUVJ444P)) {
1786 /* yuv444 is the normalized format */
1787 if (dst_pix->color_type == FF_COLOR_YUV_JPEG)
1788 int_pix_fmt = PIX_FMT_YUVJ444P;
1789 else
1790 int_pix_fmt = PIX_FMT_YUV444P;
2a877875 1791 } else {
c50c0bc8
FB
1792 /* the two formats are rgb or gray8 or yuv[j]444p */
1793 if (src_pix->is_alpha && dst_pix->is_alpha)
1794 int_pix_fmt = PIX_FMT_RGBA32;
1795 else
1796 int_pix_fmt = PIX_FMT_RGB24;
2a877875
FB
1797 }
1798 if (avpicture_alloc(tmp, int_pix_fmt, dst_width, dst_height) < 0)
1799 return -1;
1800 ret = -1;
1801 if (img_convert(tmp, int_pix_fmt,
1802 src, src_pix_fmt, src_width, src_height) < 0)
1803 goto fail1;
1804 if (img_convert(dst, dst_pix_fmt,
1805 tmp, int_pix_fmt, dst_width, dst_height) < 0)
1806 goto fail1;
1807 ret = 0;
1808 fail1:
1809 avpicture_free(tmp);
1810 return ret;
85c242d8
FB
1811}
1812
0469baf1
FB
1813/* NOTE: we scan all the pixels to have an exact information */
1814static int get_alpha_info_pal8(AVPicture *src, int width, int height)
1815{
1816 const unsigned char *p;
1817 int src_wrap, ret, x, y;
1818 unsigned int a;
1819 uint32_t *palette = (uint32_t *)src->data[1];
1820
1821 p = src->data[0];
1822 src_wrap = src->linesize[0] - width;
1823 ret = 0;
1824 for(y=0;y<height;y++) {
1825 for(x=0;x<width;x++) {
1826 a = palette[p[0]] >> 24;
1827 if (a == 0x00) {
1828 ret |= FF_ALPHA_TRANSP;
1829 } else if (a != 0xff) {
1830 ret |= FF_ALPHA_SEMI_TRANSP;
1831 }
1832 p++;
1833 }
1834 p += src_wrap;
1835 }
1836 return ret;
1837}
1838
1839/**
1840 * Tell if an image really has transparent alpha values.
1841 * @return ored mask of FF_ALPHA_xxx constants
1842 */
1843int img_get_alpha_info(AVPicture *src, int pix_fmt, int width, int height)
1844{
1845 PixFmtInfo *pf = &pix_fmt_info[pix_fmt];
1846 int ret;
1847
1848 pf = &pix_fmt_info[pix_fmt];
1849 /* no alpha can be represented in format */
1850 if (!pf->is_alpha)
1851 return 0;
1852 switch(pix_fmt) {
1853 case PIX_FMT_RGBA32:
1854 ret = get_alpha_info_rgba32(src, width, height);
1855 break;
1856 case PIX_FMT_RGB555:
1857 ret = get_alpha_info_rgb555(src, width, height);
1858 break;
1859 case PIX_FMT_PAL8:
1860 ret = get_alpha_info_pal8(src, width, height);
1861 break;
1862 default:
1863 /* we do not know, so everything is indicated */
1864 ret = FF_ALPHA_TRANSP | FF_ALPHA_SEMI_TRANSP;
1865 break;
1866 }
1867 return ret;
1868}
5981f4e6
F
1869
1870#ifdef HAVE_MMX
1871#define DEINT_INPLACE_LINE_LUM \
1872 movd_m2r(lum_m4[0],mm0);\
1873 movd_m2r(lum_m3[0],mm1);\
1874 movd_m2r(lum_m2[0],mm2);\
1875 movd_m2r(lum_m1[0],mm3);\
1876 movd_m2r(lum[0],mm4);\
1877 punpcklbw_r2r(mm7,mm0);\
1878 movd_r2m(mm2,lum_m4[0]);\
1879 punpcklbw_r2r(mm7,mm1);\
1880 punpcklbw_r2r(mm7,mm2);\
1881 punpcklbw_r2r(mm7,mm3);\
1882 punpcklbw_r2r(mm7,mm4);\
1883 paddw_r2r(mm3,mm1);\
1884 psllw_i2r(1,mm2);\
1885 paddw_r2r(mm4,mm0);\
1886 psllw_i2r(2,mm1);\
1887 paddw_r2r(mm6,mm2);\
1888 paddw_r2r(mm2,mm1);\
1889 psubusw_r2r(mm0,mm1);\
1890 psrlw_i2r(3,mm1);\
1891 packuswb_r2r(mm7,mm1);\
1892 movd_r2m(mm1,lum_m2[0]);
1893
1894#define DEINT_LINE_LUM \
1895 movd_m2r(lum_m4[0],mm0);\
1896 movd_m2r(lum_m3[0],mm1);\
1897 movd_m2r(lum_m2[0],mm2);\
1898 movd_m2r(lum_m1[0],mm3);\
1899 movd_m2r(lum[0],mm4);\
1900 punpcklbw_r2r(mm7,mm0);\
1901 punpcklbw_r2r(mm7,mm1);\
1902 punpcklbw_r2r(mm7,mm2);\
1903 punpcklbw_r2r(mm7,mm3);\
1904 punpcklbw_r2r(mm7,mm4);\
1905 paddw_r2r(mm3,mm1);\
1906 psllw_i2r(1,mm2);\
1907 paddw_r2r(mm4,mm0);\
1908 psllw_i2r(2,mm1);\
1909 paddw_r2r(mm6,mm2);\
1910 paddw_r2r(mm2,mm1);\
1911 psubusw_r2r(mm0,mm1);\
1912 psrlw_i2r(3,mm1);\
1913 packuswb_r2r(mm7,mm1);\
1914 movd_r2m(mm1,dst[0]);
1915#endif
1916
85c242d8 1917/* filter parameters: [-1 4 2 4 -1] // 8 */
0c1a9eda 1918static void deinterlace_line(uint8_t *dst, uint8_t *lum_m4, uint8_t *lum_m3, uint8_t *lum_m2, uint8_t *lum_m1, uint8_t *lum,
5981f4e6 1919 int size)
85c242d8 1920{
5981f4e6 1921#ifndef HAVE_MMX
0c1a9eda 1922 uint8_t *cm = cropTbl + MAX_NEG_CROP;
85c242d8 1923 int sum;
85c242d8
FB
1924
1925 for(;size > 0;size--) {
5981f4e6
F
1926 sum = -lum_m4[0];
1927 sum += lum_m3[0] << 2;
1928 sum += lum_m2[0] << 1;
1929 sum += lum_m1[0] << 2;
1930 sum += -lum[0];
85c242d8 1931 dst[0] = cm[(sum + 4) >> 3];
5981f4e6
F
1932 lum_m4++;
1933 lum_m3++;
1934 lum_m2++;
1935 lum_m1++;
1936 lum++;
85c242d8 1937 dst++;
85c242d8 1938 }
5981f4e6
F
1939#else
1940
782c5984
MN
1941 {
1942 mmx_t rounder;
1943 rounder.uw[0]=4;
1944 rounder.uw[1]=4;
1945 rounder.uw[2]=4;
1946 rounder.uw[3]=4;
1947 pxor_r2r(mm7,mm7);
1948 movq_m2r(rounder,mm6);
1949 }
5981f4e6
F
1950 for (;size > 3; size-=4) {
1951 DEINT_LINE_LUM
1952 lum_m4+=4;
1953 lum_m3+=4;
1954 lum_m2+=4;
1955 lum_m1+=4;
1956 lum+=4;
1957 dst+=4;
1958 }
1959#endif
1960}
0c1a9eda 1961static void deinterlace_line_inplace(uint8_t *lum_m4, uint8_t *lum_m3, uint8_t *lum_m2, uint8_t *lum_m1, uint8_t *lum,
5981f4e6
F
1962 int size)
1963{
1964#ifndef HAVE_MMX
0c1a9eda 1965 uint8_t *cm = cropTbl + MAX_NEG_CROP;
5981f4e6
F
1966 int sum;
1967
1968 for(;size > 0;size--) {
1969 sum = -lum_m4[0];
1970 sum += lum_m3[0] << 2;
1971 sum += lum_m2[0] << 1;
1972 lum_m4[0]=lum_m2[0];
1973 sum += lum_m1[0] << 2;
1974 sum += -lum[0];
1975 lum_m2[0] = cm[(sum + 4) >> 3];
1976 lum_m4++;
1977 lum_m3++;
1978 lum_m2++;
1979 lum_m1++;
1980 lum++;
1981 }
1982#else
1983
782c5984
MN
1984 {
1985 mmx_t rounder;
1986 rounder.uw[0]=4;
1987 rounder.uw[1]=4;
1988 rounder.uw[2]=4;
1989 rounder.uw[3]=4;
1990 pxor_r2r(mm7,mm7);
1991 movq_m2r(rounder,mm6);
1992 }
5981f4e6
F
1993 for (;size > 3; size-=4) {
1994 DEINT_INPLACE_LINE_LUM
1995 lum_m4+=4;
1996 lum_m3+=4;
1997 lum_m2+=4;
1998 lum_m1+=4;
1999 lum+=4;
2000 }
2001#endif
85c242d8
FB
2002}
2003
2004/* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
2005 top field is copied as is, but the bottom field is deinterlaced
2006 against the top field. */
0c1a9eda
ZK
2007static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
2008 uint8_t *src1, int src_wrap,
5981f4e6 2009 int width, int height)
85c242d8 2010{
0c1a9eda 2011 uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
5981f4e6
F
2012 int y;
2013
2014 src_m2 = src1;
2015 src_m1 = src1;
2016 src_0=&src_m1[src_wrap];
2017 src_p1=&src_0[src_wrap];
2018 src_p2=&src_p1[src_wrap];
2019 for(y=0;y<(height-2);y+=2) {
2020 memcpy(dst,src_m1,width);
85c242d8 2021 dst += dst_wrap;
5981f4e6
F
2022 deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
2023 src_m2 = src_0;
2024 src_m1 = src_p1;
2025 src_0 = src_p2;
2026 src_p1 += 2*src_wrap;
2027 src_p2 += 2*src_wrap;
85c242d8 2028 dst += dst_wrap;
85c242d8 2029 }
5981f4e6
F
2030 memcpy(dst,src_m1,width);
2031 dst += dst_wrap;
2032 /* do last line */
2033 deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
2034}
2035
0c1a9eda 2036static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
5981f4e6
F
2037 int width, int height)
2038{
0c1a9eda 2039 uint8_t *src_m1, *src_0, *src_p1, *src_p2;
5981f4e6 2040 int y;
0c1a9eda
ZK
2041 uint8_t *buf;
2042 buf = (uint8_t*)av_malloc(width);
5981f4e6
F
2043
2044 src_m1 = src1;
2045 memcpy(buf,src_m1,width);
2046 src_0=&src_m1[src_wrap];
2047 src_p1=&src_0[src_wrap];
2048 src_p2=&src_p1[src_wrap];
2049 for(y=0;y<(height-2);y+=2) {
2050 deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
2051 src_m1 = src_p1;
2052 src_0 = src_p2;
2053 src_p1 += 2*src_wrap;
2054 src_p2 += 2*src_wrap;
2055 }
2056 /* do last line */
2057 deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
6000abfa 2058 av_free(buf);
85c242d8
FB
2059}
2060
2061
5981f4e6 2062/* deinterlace - if not supported return -1 */
85c242d8 2063int avpicture_deinterlace(AVPicture *dst, AVPicture *src,
de6d9b64
FB
2064 int pix_fmt, int width, int height)
2065{
85c242d8
FB
2066 int i;
2067
2068 if (pix_fmt != PIX_FMT_YUV420P &&
2069 pix_fmt != PIX_FMT_YUV422P &&
2070 pix_fmt != PIX_FMT_YUV444P)
2071 return -1;
5981f4e6 2072 if ((width & 3) != 0 || (height & 3) != 0)
85c242d8 2073 return -1;
5981f4e6 2074
85c242d8
FB
2075 for(i=0;i<3;i++) {
2076 if (i == 1) {
2077 switch(pix_fmt) {
2078 case PIX_FMT_YUV420P:
2079 width >>= 1;
2080 height >>= 1;
2081 break;
2082 case PIX_FMT_YUV422P:
2083 width >>= 1;
2084 break;
2085 default:
2086 break;
2087 }
2088 }
5981f4e6
F
2089 if (src == dst) {
2090 deinterlace_bottom_field_inplace(src->data[i], src->linesize[i],
85c242d8 2091 width, height);
5981f4e6
F
2092 } else {
2093 deinterlace_bottom_field(dst->data[i],dst->linesize[i],
2094 src->data[i], src->linesize[i],
2095 width, height);
2096 }
de6d9b64 2097 }
5981f4e6
F
2098#ifdef HAVE_MMX
2099 emms();
2100#endif
85c242d8 2101 return 0;
de6d9b64 2102}
cd4af68a
ZK
2103
2104#undef FIX