2 * Templates for image convertion 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
23 #define RGB_OUT(d, r, g, b) RGBA_OUT(d, r, g, b, 0xff)
26 static void glue(yuv420p_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
27 int width, int height)
29 const uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr;
31 int w, y, cb, cr, r_add, g_add, b_add, width2;
32 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
36 y1_ptr = src->data[0];
37 cb_ptr = src->data[1];
38 cr_ptr = src->data[2];
39 width2 = (width + 1) >> 1;
40 for(;height >= 2; height -= 2) {
42 d2 = d + dst->linesize[0];
43 y2_ptr = y1_ptr + src->linesize[0];
44 for(w = width; w >= 2; w -= 2) {
45 YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]);
47 YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
50 YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[1]);
51 RGB_OUT(d1 + BPP, r, g, b);
53 YUV_TO_RGB2_CCIR(r, g, b, y2_ptr[0]);
56 YUV_TO_RGB2_CCIR(r, g, b, y2_ptr[1]);
57 RGB_OUT(d2 + BPP, r, g, b);
67 /* handle odd width */
69 YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]);
70 YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
73 YUV_TO_RGB2_CCIR(r, g, b, y2_ptr[0]);
82 d += 2 * dst->linesize[0];
83 y1_ptr += 2 * src->linesize[0] - width;
84 cb_ptr += src->linesize[1] - width2;
85 cr_ptr += src->linesize[2] - width2;
87 /* handle odd height */
90 for(w = width; w >= 2; w -= 2) {
91 YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]);
93 YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
96 YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[1]);
97 RGB_OUT(d1 + BPP, r, g, b);
107 YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]);
108 /* output 2 pixels */
109 YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
110 RGB_OUT(d1, r, g, b);
120 static void glue(yuvj420p_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
121 int width, int height)
123 const uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr;
124 uint8_t *d, *d1, *d2;
125 int w, y, cb, cr, r_add, g_add, b_add, width2;
126 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
127 unsigned int r, g, b;
130 y1_ptr = src->data[0];
131 cb_ptr = src->data[1];
132 cr_ptr = src->data[2];
133 width2 = (width + 1) >> 1;
134 for(;height >= 2; height -= 2) {
136 d2 = d + dst->linesize[0];
137 y2_ptr = y1_ptr + src->linesize[0];
138 for(w = width; w >= 2; w -= 2) {
139 YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]);
140 /* output 4 pixels */
141 YUV_TO_RGB2(r, g, b, y1_ptr[0]);
142 RGB_OUT(d1, r, g, b);
144 YUV_TO_RGB2(r, g, b, y1_ptr[1]);
145 RGB_OUT(d1 + BPP, r, g, b);
147 YUV_TO_RGB2(r, g, b, y2_ptr[0]);
148 RGB_OUT(d2, r, g, b);
150 YUV_TO_RGB2(r, g, b, y2_ptr[1]);
151 RGB_OUT(d2 + BPP, r, g, b);
161 /* handle odd width */
163 YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]);
164 YUV_TO_RGB2(r, g, b, y1_ptr[0]);
165 RGB_OUT(d1, r, g, b);
167 YUV_TO_RGB2(r, g, b, y2_ptr[0]);
168 RGB_OUT(d2, r, g, b);
176 d += 2 * dst->linesize[0];
177 y1_ptr += 2 * src->linesize[0] - width;
178 cb_ptr += src->linesize[1] - width2;
179 cr_ptr += src->linesize[2] - width2;
181 /* handle odd height */
184 for(w = width; w >= 2; w -= 2) {
185 YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]);
186 /* output 2 pixels */
187 YUV_TO_RGB2(r, g, b, y1_ptr[0]);
188 RGB_OUT(d1, r, g, b);
190 YUV_TO_RGB2(r, g, b, y1_ptr[1]);
191 RGB_OUT(d1 + BPP, r, g, b);
201 YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]);
202 /* output 2 pixels */
203 YUV_TO_RGB2(r, g, b, y1_ptr[0]);
204 RGB_OUT(d1, r, g, b);
214 static void glue(RGB_NAME, _to_yuv420p)(AVPicture *dst, const AVPicture *src,
215 int width, int height)
217 int wrap, wrap3, width2;
218 int r, g, b, r1, g1, b1, w;
219 uint8_t *lum, *cb, *cr;
226 width2 = (width + 1) >> 1;
227 wrap = dst->linesize[0];
228 wrap3 = src->linesize[0];
230 for(;height>=2;height -= 2) {
231 for(w = width; w >= 2; w -= 2) {
236 lum[0] = RGB_TO_Y_CCIR(r, g, b);
238 RGB_IN(r, g, b, p + BPP);
242 lum[1] = RGB_TO_Y_CCIR(r, g, b);
250 lum[0] = RGB_TO_Y_CCIR(r, g, b);
252 RGB_IN(r, g, b, p + BPP);
256 lum[1] = RGB_TO_Y_CCIR(r, g, b);
258 cb[0] = RGB_TO_U_CCIR(r1, g1, b1, 2);
259 cr[0] = RGB_TO_V_CCIR(r1, g1, b1, 2);
263 p += -wrap3 + 2 * BPP;
271 lum[0] = RGB_TO_Y_CCIR(r, g, b);
278 lum[0] = RGB_TO_Y_CCIR(r, g, b);
279 cb[0] = RGB_TO_U_CCIR(r1, g1, b1, 1);
280 cr[0] = RGB_TO_V_CCIR(r1, g1, b1, 1);
286 p += wrap3 + (wrap3 - width * BPP);
287 lum += wrap + (wrap - width);
288 cb += dst->linesize[1] - width2;
289 cr += dst->linesize[2] - width2;
291 /* handle odd height */
293 for(w = width; w >= 2; w -= 2) {
298 lum[0] = RGB_TO_Y_CCIR(r, g, b);
300 RGB_IN(r, g, b, p + BPP);
304 lum[1] = RGB_TO_Y_CCIR(r, g, b);
305 cb[0] = RGB_TO_U_CCIR(r1, g1, b1, 1);
306 cr[0] = RGB_TO_V_CCIR(r1, g1, b1, 1);
314 lum[0] = RGB_TO_Y_CCIR(r, g, b);
315 cb[0] = RGB_TO_U_CCIR(r, g, b, 0);
316 cr[0] = RGB_TO_V_CCIR(r, g, b, 0);
321 static void glue(RGB_NAME, _to_gray)(AVPicture *dst, const AVPicture *src,
322 int width, int height)
324 const unsigned char *p;
326 int r, g, b, dst_wrap, src_wrap;
330 src_wrap = src->linesize[0] - BPP * width;
333 dst_wrap = dst->linesize[0] - width;
335 for(y=0;y<height;y++) {
336 for(x=0;x<width;x++) {
338 q[0] = RGB_TO_Y(r, g, b);
347 static void glue(gray_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
348 int width, int height)
350 const unsigned char *p;
352 int r, dst_wrap, src_wrap;
356 src_wrap = src->linesize[0] - width;
359 dst_wrap = dst->linesize[0] - BPP * width;
361 for(y=0;y<height;y++) {
362 for(x=0;x<width;x++) {
373 static void glue(pal8_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
374 int width, int height)
376 const unsigned char *p;
378 int r, g, b, dst_wrap, src_wrap;
381 const uint32_t *palette;
384 src_wrap = src->linesize[0] - width;
385 palette = (uint32_t *)src->data[1];
388 dst_wrap = dst->linesize[0] - BPP * width;
390 for(y=0;y<height;y++) {
391 for(x=0;x<width;x++) {
393 r = (v >> 16) & 0xff;
399 a = (v >> 24) & 0xff;
400 RGBA_OUT(q, r, g, b, a);
413 // RGB24 has optimised routines
414 #if !defined(FMT_RGBA32) && !defined(FMT_RGB24)
417 static void glue(rgba32_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
418 int width, int height)
422 int src_wrap, dst_wrap, j, y;
423 unsigned int v, r, g, b;
429 src_wrap = src->linesize[0] - width * 4;
432 dst_wrap = dst->linesize[0] - width * BPP;
434 for(y=0;y<height;y++) {
435 for(j = 0;j < width; j++) {
436 v = ((const uint32_t *)(s))[0];
437 r = (v >> 16) & 0xff;
441 a = (v >> 24) & 0xff;
442 RGBA_OUT(d, r, g, b, a);
454 static void glue(RGB_NAME, _to_rgba32)(AVPicture *dst, const AVPicture *src,
455 int width, int height)
459 int src_wrap, dst_wrap, j, y;
460 unsigned int r, g, b;
466 src_wrap = src->linesize[0] - width * BPP;
469 dst_wrap = dst->linesize[0] - width * 4;
471 for(y=0;y<height;y++) {
472 for(j = 0;j < width; j++) {
474 RGBA_IN(r, g, b, a, s);
475 ((uint32_t *)(d))[0] = (a << 24) | (r << 16) | (g << 8) | b;
478 ((uint32_t *)(d))[0] = (0xff << 24) | (r << 16) | (g << 8) | b;
488 #endif /* !defined(FMT_RGBA32) */
492 static void glue(rgb24_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src,
493 int width, int height)
497 int src_wrap, dst_wrap, j, y;
498 unsigned int r, g, b;
501 src_wrap = src->linesize[0] - width * 3;
504 dst_wrap = dst->linesize[0] - width * BPP;
506 for(y=0;y<height;y++) {
507 for(j = 0;j < width; j++) {
520 static void glue(RGB_NAME, _to_rgb24)(AVPicture *dst, const AVPicture *src,
521 int width, int height)
525 int src_wrap, dst_wrap, j, y;
526 unsigned int r, g , b;
529 src_wrap = src->linesize[0] - width * BPP;
532 dst_wrap = dst->linesize[0] - width * 3;
534 for(y=0;y<height;y++) {
535 for(j = 0;j < width; j++) {
548 #endif /* !FMT_RGB24 */
552 static void yuv444p_to_rgb24(AVPicture *dst, const AVPicture *src,
553 int width, int height)
555 const uint8_t *y1_ptr, *cb_ptr, *cr_ptr;
557 int w, y, cb, cr, r_add, g_add, b_add;
558 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
559 unsigned int r, g, b;
562 y1_ptr = src->data[0];
563 cb_ptr = src->data[1];
564 cr_ptr = src->data[2];
565 for(;height > 0; height --) {
567 for(w = width; w > 0; w--) {
568 YUV_TO_RGB1_CCIR(cb_ptr[0], cr_ptr[0]);
570 YUV_TO_RGB2_CCIR(r, g, b, y1_ptr[0]);
571 RGB_OUT(d1, r, g, b);
578 d += dst->linesize[0];
579 y1_ptr += src->linesize[0] - width;
580 cb_ptr += src->linesize[1] - width;
581 cr_ptr += src->linesize[2] - width;
585 static void yuvj444p_to_rgb24(AVPicture *dst, const AVPicture *src,
586 int width, int height)
588 const uint8_t *y1_ptr, *cb_ptr, *cr_ptr;
590 int w, y, cb, cr, r_add, g_add, b_add;
591 uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
592 unsigned int r, g, b;
595 y1_ptr = src->data[0];
596 cb_ptr = src->data[1];
597 cr_ptr = src->data[2];
598 for(;height > 0; height --) {
600 for(w = width; w > 0; w--) {
601 YUV_TO_RGB1(cb_ptr[0], cr_ptr[0]);
603 YUV_TO_RGB2(r, g, b, y1_ptr[0]);
604 RGB_OUT(d1, r, g, b);
611 d += dst->linesize[0];
612 y1_ptr += src->linesize[0] - width;
613 cb_ptr += src->linesize[1] - width;
614 cr_ptr += src->linesize[2] - width;
618 static void rgb24_to_yuv444p(AVPicture *dst, const AVPicture *src,
619 int width, int height)
623 uint8_t *lum, *cb, *cr;
630 src_wrap = src->linesize[0] - width * BPP;
632 for(y=0;y<height;y++) {
633 for(x=0;x<width;x++) {
635 lum[0] = RGB_TO_Y_CCIR(r, g, b);
636 cb[0] = RGB_TO_U_CCIR(r, g, b, 0);
637 cr[0] = RGB_TO_V_CCIR(r, g, b, 0);
644 lum += dst->linesize[0] - width;
645 cb += dst->linesize[1] - width;
646 cr += dst->linesize[2] - width;
650 static void rgb24_to_yuvj420p(AVPicture *dst, const AVPicture *src,
651 int width, int height)
653 int wrap, wrap3, width2;
654 int r, g, b, r1, g1, b1, w;
655 uint8_t *lum, *cb, *cr;
662 width2 = (width + 1) >> 1;
663 wrap = dst->linesize[0];
664 wrap3 = src->linesize[0];
666 for(;height>=2;height -= 2) {
667 for(w = width; w >= 2; w -= 2) {
672 lum[0] = RGB_TO_Y(r, g, b);
674 RGB_IN(r, g, b, p + BPP);
678 lum[1] = RGB_TO_Y(r, g, b);
686 lum[0] = RGB_TO_Y(r, g, b);
688 RGB_IN(r, g, b, p + BPP);
692 lum[1] = RGB_TO_Y(r, g, b);
694 cb[0] = RGB_TO_U(r1, g1, b1, 2);
695 cr[0] = RGB_TO_V(r1, g1, b1, 2);
699 p += -wrap3 + 2 * BPP;
707 lum[0] = RGB_TO_Y(r, g, b);
714 lum[0] = RGB_TO_Y(r, g, b);
715 cb[0] = RGB_TO_U(r1, g1, b1, 1);
716 cr[0] = RGB_TO_V(r1, g1, b1, 1);
722 p += wrap3 + (wrap3 - width * BPP);
723 lum += wrap + (wrap - width);
724 cb += dst->linesize[1] - width2;
725 cr += dst->linesize[2] - width2;
727 /* handle odd height */
729 for(w = width; w >= 2; w -= 2) {
734 lum[0] = RGB_TO_Y(r, g, b);
736 RGB_IN(r, g, b, p + BPP);
740 lum[1] = RGB_TO_Y(r, g, b);
741 cb[0] = RGB_TO_U(r1, g1, b1, 1);
742 cr[0] = RGB_TO_V(r1, g1, b1, 1);
750 lum[0] = RGB_TO_Y(r, g, b);
751 cb[0] = RGB_TO_U(r, g, b, 0);
752 cr[0] = RGB_TO_V(r, g, b, 0);
757 static void rgb24_to_yuvj444p(AVPicture *dst, const AVPicture *src,
758 int width, int height)
762 uint8_t *lum, *cb, *cr;
769 src_wrap = src->linesize[0] - width * BPP;
771 for(y=0;y<height;y++) {
772 for(x=0;x<width;x++) {
774 lum[0] = RGB_TO_Y(r, g, b);
775 cb[0] = RGB_TO_U(r, g, b, 0);
776 cr[0] = RGB_TO_V(r, g, b, 0);
783 lum += dst->linesize[0] - width;
784 cb += dst->linesize[1] - width;
785 cr += dst->linesize[2] - width;
789 #endif /* FMT_RGB24 */
791 #if defined(FMT_RGB24) || defined(FMT_RGBA32)
793 static void glue(RGB_NAME, _to_pal8)(AVPicture *dst, const AVPicture *src,
794 int width, int height)
796 const unsigned char *p;
798 int dst_wrap, src_wrap;
800 unsigned int r, g, b;
803 src_wrap = src->linesize[0] - BPP * width;
806 dst_wrap = dst->linesize[0] - width;
809 for(y=0;y<height;y++) {
810 for(x=0;x<width;x++) {
814 RGBA_IN(r, g, b, a, p);
815 /* crude approximation for alpha ! */
820 q[0] = gif_clut_index(r, g, b);
825 q[0] = gif_clut_index(r, g, b);
834 build_rgb_palette(dst->data[1], has_alpha);
837 #endif /* defined(FMT_RGB24) || defined(FMT_RGBA32) */
841 static int glue(get_alpha_info_, RGB_NAME)(const AVPicture *src,
842 int width, int height)
844 const unsigned char *p;
845 int src_wrap, ret, x, y;
846 unsigned int r, g, b, a;
849 src_wrap = src->linesize[0] - BPP * width;
851 for(y=0;y<height;y++) {
852 for(x=0;x<width;x++) {
853 RGBA_IN(r, g, b, a, p);
855 ret |= FF_ALPHA_TRANSP;
856 } else if (a != 0xff) {
857 ret |= FF_ALPHA_SEMI_TRANSP;