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