2 * templates for image conversion routines
3 * Copyright (c) 2001, 2002, 2003 Fabrice Bellard.
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 /* This header intentionally has no multiple inclusion guards. It is meant to
23 * be included multiple times and generates different code depending on the
24 * value of certain #defines. */
27 #define RGB_OUT(d, r, g, b) RGBA_OUT(d, r, g, b, 0xff)
30 static void glue(yuv420p_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
31 int width, int height)
33 const uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr;
35 int w, y, cb, cr, r_add, g_add, b_add, width2;
36 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
40 y1_ptr = src->data[0];
41 cb_ptr = src->data[1];
42 cr_ptr = src->data[2];
43 width2 = (width + 1) >> 1;
44 for(;height >= 2; height -= 2) {
46 d2 = d + dst->linesize[0];
47 y2_ptr = y1_ptr + src->linesize[0];
48 for(w = width; w >= 2; w -= 2) {
49 YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]);
51 YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
54 YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[1]);
55 RGB_OUT(d1 + BPP, r, g, b);
57 YUV_TO_RGB2_CCIR(r, g, b, y2_ptr[0]);
60 YUV_TO_RGB2_CCIR(r, g, b, y2_ptr[1]);
61 RGB_OUT(d2 + BPP, r, g, b);
71 /* handle odd width */
73 YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]);
74 YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
77 YUV_TO_RGB2_CCIR(r, g, b, y2_ptr[0]);
86 d += 2 * dst->linesize[0];
87 y1_ptr += 2 * src->linesize[0] - width;
88 cb_ptr += src->linesize[1] - width2;
89 cr_ptr += src->linesize[2] - width2;
91 /* handle odd height */
94 for(w = width; w >= 2; w -= 2) {
95 YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]);
97 YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
100 YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[1]);
101 RGB_OUT(d1 + BPP, r, g, b);
111 YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]);
112 /* output 2 pixels */
113 YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
114 RGB_OUT(d1, r, g, b);
124 static void glue(yuvj420p_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
125 int width, int height)
127 const uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr;
128 uint8_t *d, *d1, *d2;
129 int w, y, cb, cr, r_add, g_add, b_add, width2;
130 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
131 unsigned int r, g, b;
134 y1_ptr = src->data[0];
135 cb_ptr = src->data[1];
136 cr_ptr = src->data[2];
137 width2 = (width + 1) >> 1;
138 for(;height >= 2; height -= 2) {
140 d2 = d + dst->linesize[0];
141 y2_ptr = y1_ptr + src->linesize[0];
142 for(w = width; w >= 2; w -= 2) {
143 YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]);
144 /* output 4 pixels */
145 YUV_TO_RGB2(r, g, b, y1_ptr[0]);
146 RGB_OUT(d1, r, g, b);
148 YUV_TO_RGB2(r, g, b, y1_ptr[1]);
149 RGB_OUT(d1 + BPP, r, g, b);
151 YUV_TO_RGB2(r, g, b, y2_ptr[0]);
152 RGB_OUT(d2, r, g, b);
154 YUV_TO_RGB2(r, g, b, y2_ptr[1]);
155 RGB_OUT(d2 + BPP, r, g, b);
165 /* handle odd width */
167 YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]);
168 YUV_TO_RGB2(r, g, b, y1_ptr[0]);
169 RGB_OUT(d1, r, g, b);
171 YUV_TO_RGB2(r, g, b, y2_ptr[0]);
172 RGB_OUT(d2, r, g, b);
180 d += 2 * dst->linesize[0];
181 y1_ptr += 2 * src->linesize[0] - width;
182 cb_ptr += src->linesize[1] - width2;
183 cr_ptr += src->linesize[2] - width2;
185 /* handle odd height */
188 for(w = width; w >= 2; w -= 2) {
189 YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]);
190 /* output 2 pixels */
191 YUV_TO_RGB2(r, g, b, y1_ptr[0]);
192 RGB_OUT(d1, r, g, b);
194 YUV_TO_RGB2(r, g, b, y1_ptr[1]);
195 RGB_OUT(d1 + BPP, r, g, b);
205 YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]);
206 /* output 2 pixels */
207 YUV_TO_RGB2(r, g, b, y1_ptr[0]);
208 RGB_OUT(d1, r, g, b);
218 static void glue(RGB_NAME, _to_yuv420p)(AVPicture *dst, const AVPicture *src,
219 int width, int height)
221 int wrap, wrap3, width2;
222 int r, g, b, r1, g1, b1, w;
223 uint8_t *lum, *cb, *cr;
230 width2 = (width + 1) >> 1;
231 wrap = dst->linesize[0];
232 wrap3 = src->linesize[0];
234 for(;height>=2;height -= 2) {
235 for(w = width; w >= 2; w -= 2) {
240 lum[0] = RGB_TO_Y_CCIR(r, g, b);
242 RGB_IN(r, g, b, p + BPP);
246 lum[1] = RGB_TO_Y_CCIR(r, g, b);
254 lum[0] = RGB_TO_Y_CCIR(r, g, b);
256 RGB_IN(r, g, b, p + BPP);
260 lum[1] = RGB_TO_Y_CCIR(r, g, b);
262 cb[0] = RGB_TO_U_CCIR(r1, g1, b1, 2);
263 cr[0] = RGB_TO_V_CCIR(r1, g1, b1, 2);
267 p += -wrap3 + 2 * BPP;
275 lum[0] = RGB_TO_Y_CCIR(r, g, b);
282 lum[0] = RGB_TO_Y_CCIR(r, g, b);
283 cb[0] = RGB_TO_U_CCIR(r1, g1, b1, 1);
284 cr[0] = RGB_TO_V_CCIR(r1, g1, b1, 1);
290 p += wrap3 + (wrap3 - width * BPP);
291 lum += wrap + (wrap - width);
292 cb += dst->linesize[1] - width2;
293 cr += dst->linesize[2] - width2;
295 /* handle odd height */
297 for(w = width; w >= 2; w -= 2) {
302 lum[0] = RGB_TO_Y_CCIR(r, g, b);
304 RGB_IN(r, g, b, p + BPP);
308 lum[1] = RGB_TO_Y_CCIR(r, g, b);
309 cb[0] = RGB_TO_U_CCIR(r1, g1, b1, 1);
310 cr[0] = RGB_TO_V_CCIR(r1, g1, b1, 1);
318 lum[0] = RGB_TO_Y_CCIR(r, g, b);
319 cb[0] = RGB_TO_U_CCIR(r, g, b, 0);
320 cr[0] = RGB_TO_V_CCIR(r, g, b, 0);
325 static void glue(RGB_NAME, _to_gray)(AVPicture *dst, const AVPicture *src,
326 int width, int height)
328 const unsigned char *p;
330 int r, g, b, dst_wrap, src_wrap;
334 src_wrap = src->linesize[0] - BPP * width;
337 dst_wrap = dst->linesize[0] - width;
339 for(y=0;y<height;y++) {
340 for(x=0;x<width;x++) {
342 q[0] = RGB_TO_Y(r, g, b);
351 static void glue(gray_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
352 int width, int height)
354 const unsigned char *p;
356 int r, dst_wrap, src_wrap;
360 src_wrap = src->linesize[0] - width;
363 dst_wrap = dst->linesize[0] - BPP * width;
365 for(y=0;y<height;y++) {
366 for(x=0;x<width;x++) {
377 static void glue(pal8_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
378 int width, int height)
380 const unsigned char *p;
382 int r, g, b, dst_wrap, src_wrap;
385 const uint32_t *palette;
388 src_wrap = src->linesize[0] - width;
389 palette = (uint32_t *)src->data[1];
392 dst_wrap = dst->linesize[0] - BPP * width;
394 for(y=0;y<height;y++) {
395 for(x=0;x<width;x++) {
397 r = (v >> 16) & 0xff;
403 a = (v >> 24) & 0xff;
404 RGBA_OUT(q, r, g, b, a);
417 // RGB24 has optimized routines
418 #if !defined(FMT_RGB32) && !defined(FMT_RGB24)
421 static void glue(rgb32_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
422 int width, int height)
426 int src_wrap, dst_wrap, j, y;
427 unsigned int v, r, g, b;
433 src_wrap = src->linesize[0] - width * 4;
436 dst_wrap = dst->linesize[0] - width * BPP;
438 for(y=0;y<height;y++) {
439 for(j = 0;j < width; j++) {
440 v = ((const uint32_t *)(s))[0];
441 r = (v >> 16) & 0xff;
445 a = (v >> 24) & 0xff;
446 RGBA_OUT(d, r, g, b, a);
458 static void glue(RGB_NAME, _to_rgb32)(AVPicture *dst, const AVPicture *src,
459 int width, int height)
463 int src_wrap, dst_wrap, j, y;
464 unsigned int r, g, b;
470 src_wrap = src->linesize[0] - width * BPP;
473 dst_wrap = dst->linesize[0] - width * 4;
475 for(y=0;y<height;y++) {
476 for(j = 0;j < width; j++) {
478 RGBA_IN(r, g, b, a, s);
479 ((uint32_t *)(d))[0] = (a << 24) | (r << 16) | (g << 8) | b;
482 ((uint32_t *)(d))[0] = (0xff << 24) | (r << 16) | (g << 8) | b;
492 #endif /* !defined(FMT_RGB32) */
496 static void glue(rgb24_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
497 int width, int height)
501 int src_wrap, dst_wrap, j, y;
502 unsigned int r, g, b;
505 src_wrap = src->linesize[0] - width * 3;
508 dst_wrap = dst->linesize[0] - width * BPP;
510 for(y=0;y<height;y++) {
511 for(j = 0;j < width; j++) {
524 static void glue(RGB_NAME, _to_rgb24)(AVPicture *dst, const AVPicture *src,
525 int width, int height)
529 int src_wrap, dst_wrap, j, y;
530 unsigned int r, g , b;
533 src_wrap = src->linesize[0] - width * BPP;
536 dst_wrap = dst->linesize[0] - width * 3;
538 for(y=0;y<height;y++) {
539 for(j = 0;j < width; j++) {
552 #endif /* !FMT_RGB24 */
556 static void yuv444p_to_rgb24(AVPicture *dst, const AVPicture *src,
557 int width, int height)
559 const uint8_t *y1_ptr, *cb_ptr, *cr_ptr;
561 int w, y, cb, cr, r_add, g_add, b_add;
562 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
563 unsigned int r, g, b;
566 y1_ptr = src->data[0];
567 cb_ptr = src->data[1];
568 cr_ptr = src->data[2];
569 for(;height > 0; height --) {
571 for(w = width; w > 0; w--) {
572 YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]);
574 YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
575 RGB_OUT(d1, r, g, b);
582 d += dst->linesize[0];
583 y1_ptr += src->linesize[0] - width;
584 cb_ptr += src->linesize[1] - width;
585 cr_ptr += src->linesize[2] - width;
589 static void yuvj444p_to_rgb24(AVPicture *dst, const AVPicture *src,
590 int width, int height)
592 const uint8_t *y1_ptr, *cb_ptr, *cr_ptr;
594 int w, y, cb, cr, r_add, g_add, b_add;
595 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
596 unsigned int r, g, b;
599 y1_ptr = src->data[0];
600 cb_ptr = src->data[1];
601 cr_ptr = src->data[2];
602 for(;height > 0; height --) {
604 for(w = width; w > 0; w--) {
605 YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]);
607 YUV_TO_RGB2(r, g, b, y1_ptr[0]);
608 RGB_OUT(d1, r, g, b);
615 d += dst->linesize[0];
616 y1_ptr += src->linesize[0] - width;
617 cb_ptr += src->linesize[1] - width;
618 cr_ptr += src->linesize[2] - width;
622 static void rgb24_to_yuv444p(AVPicture *dst, const AVPicture *src,
623 int width, int height)
627 uint8_t *lum, *cb, *cr;
634 src_wrap = src->linesize[0] - width * BPP;
636 for(y=0;y<height;y++) {
637 for(x=0;x<width;x++) {
639 lum[0] = RGB_TO_Y_CCIR(r, g, b);
640 cb[0] = RGB_TO_U_CCIR(r, g, b, 0);
641 cr[0] = RGB_TO_V_CCIR(r, g, b, 0);
648 lum += dst->linesize[0] - width;
649 cb += dst->linesize[1] - width;
650 cr += dst->linesize[2] - width;
654 static void rgb24_to_yuvj420p(AVPicture *dst, const AVPicture *src,
655 int width, int height)
657 int wrap, wrap3, width2;
658 int r, g, b, r1, g1, b1, w;
659 uint8_t *lum, *cb, *cr;
666 width2 = (width + 1) >> 1;
667 wrap = dst->linesize[0];
668 wrap3 = src->linesize[0];
670 for(;height>=2;height -= 2) {
671 for(w = width; w >= 2; w -= 2) {
676 lum[0] = RGB_TO_Y(r, g, b);
678 RGB_IN(r, g, b, p + BPP);
682 lum[1] = RGB_TO_Y(r, g, b);
690 lum[0] = RGB_TO_Y(r, g, b);
692 RGB_IN(r, g, b, p + BPP);
696 lum[1] = RGB_TO_Y(r, g, b);
698 cb[0] = RGB_TO_U(r1, g1, b1, 2);
699 cr[0] = RGB_TO_V(r1, g1, b1, 2);
703 p += -wrap3 + 2 * BPP;
711 lum[0] = RGB_TO_Y(r, g, b);
718 lum[0] = RGB_TO_Y(r, g, b);
719 cb[0] = RGB_TO_U(r1, g1, b1, 1);
720 cr[0] = RGB_TO_V(r1, g1, b1, 1);
726 p += wrap3 + (wrap3 - width * BPP);
727 lum += wrap + (wrap - width);
728 cb += dst->linesize[1] - width2;
729 cr += dst->linesize[2] - width2;
731 /* handle odd height */
733 for(w = width; w >= 2; w -= 2) {
738 lum[0] = RGB_TO_Y(r, g, b);
740 RGB_IN(r, g, b, p + BPP);
744 lum[1] = RGB_TO_Y(r, g, b);
745 cb[0] = RGB_TO_U(r1, g1, b1, 1);
746 cr[0] = RGB_TO_V(r1, g1, b1, 1);
754 lum[0] = RGB_TO_Y(r, g, b);
755 cb[0] = RGB_TO_U(r, g, b, 0);
756 cr[0] = RGB_TO_V(r, g, b, 0);
761 static void rgb24_to_yuvj444p(AVPicture *dst, const AVPicture *src,
762 int width, int height)
766 uint8_t *lum, *cb, *cr;
773 src_wrap = src->linesize[0] - width * BPP;
775 for(y=0;y<height;y++) {
776 for(x=0;x<width;x++) {
778 lum[0] = RGB_TO_Y(r, g, b);
779 cb[0] = RGB_TO_U(r, g, b, 0);
780 cr[0] = RGB_TO_V(r, g, b, 0);
787 lum += dst->linesize[0] - width;
788 cb += dst->linesize[1] - width;
789 cr += dst->linesize[2] - width;
793 #endif /* FMT_RGB24 */
795 #if defined(FMT_RGB24) || defined(FMT_RGB32)
797 static void glue(RGB_NAME, _to_pal8)(AVPicture *dst, const AVPicture *src,
798 int width, int height)
800 const unsigned char *p;
802 int dst_wrap, src_wrap;
804 unsigned int r, g, b;
807 src_wrap = src->linesize[0] - BPP * width;
810 dst_wrap = dst->linesize[0] - width;
813 for(y=0;y<height;y++) {
814 for(x=0;x<width;x++) {
818 RGBA_IN(r, g, b, a, p);
819 /* crude approximation for alpha ! */
824 q[0] = gif_clut_index(r, g, b);
829 q[0] = gif_clut_index(r, g, b);
838 build_rgb_palette(dst->data[1], has_alpha);
841 #endif /* defined(FMT_RGB24) || defined(FMT_RGB32) */
845 static int glue(get_alpha_info_, RGB_NAME)(const AVPicture *src,
846 int width, int height)
848 const unsigned char *p;
849 int src_wrap, ret, x, y;
850 unsigned int r, g, b, a;
853 src_wrap = src->linesize[0] - BPP * width;
855 for(y=0;y<height;y++) {
856 for(x=0;x<width;x++) {
857 RGBA_IN(r, g, b, a, p);
859 ret |= FF_ALPHA_TRANSP;
860 } else if (a != 0xff) {
861 ret |= FF_ALPHA_SEMI_TRANSP;