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
;