home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wvis0626.zip / warpvision_20020626.zip / libavcodec / imgconvert.c < prev    next >
C/C++ Source or Header  |  2002-06-19  |  17KB  |  553 lines

  1. /*
  2.  * Misc image convertion routines
  3.  * Copyright (c) 2001, 2002 Fabrice Bellard.
  4.  *
  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.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * Lesser General Public License for more details.
  14.  *
  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
  18.  */
  19. #include "avcodec.h"
  20. #include "dsputil.h"
  21.  
  22. #ifdef USE_FASTMEMCPY
  23. #include "fastmemcpy.h"
  24. #endif
  25. /* XXX: totally non optimized */
  26.  
  27. static void yuv422_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
  28.                               UINT8 *src, int width, int height)
  29. {
  30.     int x, y;
  31.     UINT8 *p = src;
  32.  
  33.     for(y=0;y<height;y+=2) {
  34.         for(x=0;x<width;x+=2) {
  35.             lum[0] = p[0];
  36.             cb[0] = p[1];
  37.             lum[1] = p[2];
  38.             cr[0] = p[3];
  39.             p += 4;
  40.             lum += 2;
  41.             cb++;
  42.             cr++;
  43.         }
  44.         for(x=0;x<width;x+=2) {
  45.             lum[0] = p[0];
  46.             lum[1] = p[2];
  47.             p += 4;
  48.             lum += 2;
  49.         }
  50.     }
  51. }
  52.  
  53. #define SCALEBITS 8
  54. #define ONE_HALF  (1 << (SCALEBITS - 1))
  55. #define FIX(x)        ((int) ((x) * (1L<<SCALEBITS) + 0.5))
  56.  
  57. static void rgb24_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
  58.                               UINT8 *src, int width, int height)
  59. {
  60.     int wrap, wrap3, x, y;
  61.     int r, g, b, r1, g1, b1;
  62.     UINT8 *p;
  63.  
  64.     wrap = width;
  65.     wrap3 = width * 3;
  66.     p = src;
  67.     for(y=0;y<height;y+=2) {
  68.         for(x=0;x<width;x+=2) {
  69.             r = p[0];
  70.             g = p[1];
  71.             b = p[2];
  72.             r1 = r;
  73.             g1 = g;
  74.             b1 = b;
  75.             lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
  76.                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  77.             r = p[3];
  78.             g = p[4];
  79.             b = p[5];
  80.             r1 += r;
  81.             g1 += g;
  82.             b1 += b;
  83.             lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
  84.                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  85.             p += wrap3;
  86.             lum += wrap;
  87.  
  88.             r = p[0];
  89.             g = p[1];
  90.             b = p[2];
  91.             r1 += r;
  92.             g1 += g;
  93.             b1 += b;
  94.             lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
  95.                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  96.             r = p[3];
  97.             g = p[4];
  98.             b = p[5];
  99.             r1 += r;
  100.             g1 += g;
  101.             b1 += b;
  102.             lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
  103.                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  104.             
  105.             cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + 
  106.                       FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  107.             cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - 
  108.                      FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  109.  
  110.             cb++;
  111.             cr++;
  112.             p += -wrap3 + 2 * 3;
  113.             lum += -wrap + 2;
  114.         }
  115.         p += wrap3;
  116.         lum += wrap;
  117.     }
  118. }
  119.  
  120. static void bgr24_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
  121.                               UINT8 *src, int width, int height)
  122. {
  123.     int wrap, wrap3, x, y;
  124.     int r, g, b, r1, g1, b1;
  125.     UINT8 *p;
  126.  
  127.     wrap = width;
  128.     wrap3 = width * 3;
  129.     p = src;
  130.     for(y=0;y<height;y+=2) {
  131.         for(x=0;x<width;x+=2) {
  132.             b = p[0];
  133.             g = p[1];
  134.             r = p[2];
  135.             r1 = r;
  136.             g1 = g;
  137.             b1 = b;
  138.             lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
  139.                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  140.             b = p[3];
  141.             g = p[4];
  142.             r = p[5];
  143.             r1 += r;
  144.             g1 += g;
  145.             b1 += b;
  146.             lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
  147.                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  148.             p += wrap3;
  149.             lum += wrap;
  150.  
  151.             b = p[0];
  152.             g = p[1];
  153.             r = p[2];
  154.             r1 += r;
  155.             g1 += g;
  156.             b1 += b;
  157.             lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + 
  158.                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  159.             b = p[3];
  160.             g = p[4];
  161.             r = p[5];
  162.             r1 += r;
  163.             g1 += g;
  164.             b1 += b;
  165.             lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + 
  166.                       FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  167.             
  168.             cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + 
  169.                       FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  170.             cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - 
  171.                      FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  172.  
  173.             cb++;
  174.             cr++;
  175.             p += -wrap3 + 2 * 3;
  176.             lum += -wrap + 2;
  177.         }
  178.         p += wrap3;
  179.         lum += wrap;
  180.     }
  181. }
  182.  
  183. /* XXX: use generic filter ? */
  184. /* 1x2 -> 1x1 */
  185. static void shrink2(UINT8 *dst, int dst_wrap, 
  186.                     UINT8 *src, int src_wrap,
  187.                     int width, int height)
  188. {
  189.     int w;
  190.     UINT8 *s1, *s2, *d;
  191.  
  192.     for(;height > 0; height--) {
  193.         s1 = src;
  194.         s2 = s1 + src_wrap;
  195.         d = dst;
  196.         for(w = width;w >= 4; w-=4) {
  197.             d[0] = (s1[0] + s2[0]) >> 1;
  198.             d[1] = (s1[1] + s2[1]) >> 1;
  199.             d[2] = (s1[2] + s2[2]) >> 1;
  200.             d[3] = (s1[3] + s2[3]) >> 1;
  201.             s1 += 4;
  202.             s2 += 4;
  203.             d += 4;
  204.         }
  205.         for(;w > 0; w--) {
  206.             d[0] = (s1[0] + s2[0]) >> 1;
  207.             s1++;
  208.             s2++;
  209.             d++;
  210.         }
  211.         src += 2 * src_wrap;
  212.         dst += dst_wrap;
  213.     }
  214. }
  215.  
  216. /* 2x2 -> 1x1 */
  217. static void shrink22(UINT8 *dst, int dst_wrap, 
  218.                      UINT8 *src, int src_wrap,
  219.                      int width, int height)
  220. {
  221.     int w;
  222.     UINT8 *s1, *s2, *d;
  223.  
  224.     for(;height > 0; height--) {
  225.         s1 = src;
  226.         s2 = s1 + src_wrap;
  227.         d = dst;
  228.         for(w = width;w >= 4; w-=4) {
  229.             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1;
  230.             d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 1;
  231.             d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 1;
  232.             d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 1;
  233.             s1 += 8;
  234.             s2 += 8;
  235.             d += 4;
  236.         }
  237.         for(;w > 0; w--) {
  238.             d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1;
  239.             s1 += 2;
  240.             s2 += 2;
  241.             d++;
  242.         }
  243.         src += 2 * src_wrap;
  244.         dst += dst_wrap;
  245.     }
  246. }
  247.  
  248. static void img_copy(UINT8 *dst, int dst_wrap, 
  249.                      UINT8 *src, int src_wrap,
  250.                      int width, int height)
  251. {
  252.     for(;height > 0; height--) {
  253.         memcpy(dst, src, width);
  254.         dst += dst_wrap;
  255.         src += src_wrap;
  256.     }
  257. }
  258.  
  259. #define SCALE_BITS 10
  260.  
  261. #define C_Y  (76309 >> (16 - SCALE_BITS))
  262. #define C_RV (117504 >> (16 - SCALE_BITS))
  263. #define C_BU (138453 >> (16 - SCALE_BITS))
  264. #define C_GU (13954 >> (16 - SCALE_BITS))
  265. #define C_GV (34903 >> (16 - SCALE_BITS))
  266.  
  267. #define RGBOUT(r, g, b, y1)\
  268. {\
  269.     y = (y1 - 16) * C_Y;\
  270.     r = cm[(y + r_add) >> SCALE_BITS];\
  271.     g = cm[(y + g_add) >> SCALE_BITS];\
  272.     b = cm[(y + b_add) >> SCALE_BITS];\
  273. }
  274.  
  275. /* XXX: no chroma interpolating is done */
  276. static void yuv420p_to_rgb24(AVPicture *dst, AVPicture *src, 
  277.                              int width, int height)
  278. {
  279.     UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2;
  280.     int w, y, cb, cr, r_add, g_add, b_add, width2;
  281.     UINT8 *cm = cropTbl + MAX_NEG_CROP;
  282.  
  283.     d = dst->data[0];
  284.     y1_ptr = src->data[0];
  285.     cb_ptr = src->data[1];
  286.     cr_ptr = src->data[2];
  287.     width2 = width >> 1;
  288.     for(;height > 0; height -= 2) {
  289.         d1 = d;
  290.         d2 = d + dst->linesize[0];
  291.         y2_ptr = y1_ptr + src->linesize[0];
  292.         for(w = width2; w > 0; w --) {
  293.             cb = cb_ptr[0] - 128;
  294.             cr = cr_ptr[0] - 128;
  295.             r_add = C_RV * cr + (1 << (SCALE_BITS - 1));
  296.             g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));
  297.             b_add = C_BU * cb + (1 << (SCALE_BITS - 1));
  298.             
  299.             /* output 4 pixels */
  300.             RGBOUT(d1[0], d1[1], d1[2], y1_ptr[0]);
  301.             RGBOUT(d1[3], d1[4], d1[5], y1_ptr[1]);
  302.             RGBOUT(d2[0], d2[1], d2[2], y2_ptr[0]);
  303.             RGBOUT(d2[3], d2[4], d2[5], y2_ptr[1]);
  304.  
  305.             d1 += 6;
  306.             d2 += 6;
  307.             y1_ptr += 2;
  308.             y2_ptr += 2;
  309.             cb_ptr++;
  310.             cr_ptr++;
  311.         }
  312.         d += 2 * dst->linesize[0];
  313.         y1_ptr += 2 * src->linesize[0] - width;
  314.         cb_ptr += src->linesize[1] - width2;
  315.         cr_ptr += src->linesize[2] - width2;
  316.     }
  317. }
  318.  
  319. /* XXX: no chroma interpolating is done */
  320. static void yuv422p_to_rgb24(AVPicture *dst, AVPicture *src, 
  321.                              int width, int height)
  322. {
  323.     UINT8 *y1_ptr, *cb_ptr, *cr_ptr, *d, *d1;
  324.     int w, y, cb, cr, r_add, g_add, b_add, width2;
  325.     UINT8 *cm = cropTbl + MAX_NEG_CROP;
  326.  
  327.     d = dst->data[0];
  328.     y1_ptr = src->data[0];
  329.     cb_ptr = src->data[1];
  330.     cr_ptr = src->data[2];
  331.     width2 = width >> 1;
  332.     for(;height > 0; height --) {
  333.         d1 = d;
  334.         for(w = width2; w > 0; w --) {
  335.             cb = cb_ptr[0] - 128;
  336.             cr = cr_ptr[0] - 128;
  337.             r_add = C_RV * cr + (1 << (SCALE_BITS - 1));
  338.             g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));
  339.             b_add = C_BU * cb + (1 << (SCALE_BITS - 1));
  340.             
  341.             /* output 2 pixels */
  342.             RGBOUT(d1[0], d1[1], d1[2], y1_ptr[0]);
  343.             RGBOUT(d1[3], d1[4], d1[5], y1_ptr[1]);
  344.  
  345.             d1 += 6;
  346.             y1_ptr += 2;
  347.             cb_ptr++;
  348.             cr_ptr++;
  349.         }
  350.         d += dst->linesize[0];
  351.         y1_ptr += src->linesize[0] - width;
  352.         cb_ptr += src->linesize[1] - width2;
  353.         cr_ptr += src->linesize[2] - width2;
  354.     }
  355. }
  356.  
  357. /* XXX: always use linesize. Return -1 if not supported */
  358. int img_convert(AVPicture *dst, int dst_pix_fmt,
  359.                 AVPicture *src, int pix_fmt, 
  360.                 int width, int height)
  361. {
  362.     int i;
  363.  
  364.     assert(pix_fmt != PIX_FMT_ANY && dst_pix_fmt != PIX_FMT_ANY);
  365.  
  366.     if (dst_pix_fmt == pix_fmt) {
  367.         switch(pix_fmt) {
  368.         case PIX_FMT_YUV420P:
  369.             for(i=0;i<3;i++) {
  370.                 if (i == 1) {
  371.                     width >>= 1;
  372.                     height >>= 1;
  373.                 }
  374.                 img_copy(dst->data[i], dst->linesize[i],
  375.                          src->data[i], src->linesize[i],
  376.                          width, height);
  377.             }
  378.             break;
  379.         default:
  380.             return -1;
  381.         }
  382.     } else if (dst_pix_fmt == PIX_FMT_YUV420P) {
  383.         
  384.         switch(pix_fmt) {
  385.         case PIX_FMT_YUV420P:
  386.             for(i=0;i<3;i++) {
  387.                 img_copy(dst->data[i], dst->linesize[i],
  388.                          src->data[i], src->linesize[i],
  389.                          width, height);
  390.             }
  391.             break;
  392.         case PIX_FMT_YUV422P:
  393.             img_copy(dst->data[0], dst->linesize[0],
  394.                      src->data[0], src->linesize[0],
  395.                      width, height);
  396.             width >>= 1;
  397.             height >>= 1;
  398.             for(i=1;i<3;i++) {
  399.                 shrink2(dst->data[i], dst->linesize[i],
  400.                         src->data[i], src->linesize[i],
  401.                         width, height);
  402.             }
  403.             break;
  404.         case PIX_FMT_YUV444P:
  405.             img_copy(dst->data[0], dst->linesize[0],
  406.                      src->data[0], src->linesize[0],
  407.                      width, height);
  408.             width >>= 1;
  409.             height >>= 1;
  410.             for(i=1;i<3;i++) {
  411.                 shrink22(dst->data[i], dst->linesize[i],
  412.                          src->data[i], src->linesize[i],
  413.                          width, height);
  414.             }
  415.             break;
  416.         case PIX_FMT_YUV422:
  417.             yuv422_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], 
  418.                               src->data[0], width, height);
  419.             break;
  420.         case PIX_FMT_RGB24:
  421.             rgb24_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], 
  422.                              src->data[0], width, height);
  423.             break;
  424.         case PIX_FMT_BGR24:
  425.             bgr24_to_yuv420p(dst->data[0], dst->data[1], dst->data[2], 
  426.                              src->data[0], width, height);
  427.             break;
  428.         default:
  429.             return -1;
  430.         }
  431.     } else if (dst_pix_fmt == PIX_FMT_RGB24) {
  432.         switch(pix_fmt) {
  433.         case PIX_FMT_YUV420P:
  434.             yuv420p_to_rgb24(dst, src, width, height);
  435.             break;
  436.         case PIX_FMT_YUV422P:
  437.             yuv422p_to_rgb24(dst, src, width, height);
  438.             break;
  439.         default:
  440.             return -1;
  441.         }
  442.     } else {
  443.         return -1;
  444.     }
  445.     return 0;
  446. }
  447.  
  448. /* filter parameters: [-1 4 2 4 -1] // 8 */
  449. static void deinterlace_line(UINT8 *dst, UINT8 *src, int src_wrap,
  450.                              int size)
  451. {
  452.     UINT8 *cm = cropTbl + MAX_NEG_CROP;
  453.     int sum;
  454.     UINT8 *s;
  455.  
  456.     for(;size > 0;size--) {
  457.         s = src;
  458.         sum = -s[0];
  459.         s += src_wrap;
  460.         sum += s[0] << 2;
  461.         s += src_wrap;
  462.         sum += s[0] << 1;
  463.         s += src_wrap;
  464.         sum += s[0] << 2;
  465.         s += src_wrap;
  466.         sum += -s[0];
  467.         dst[0] = cm[(sum + 4) >> 3];
  468.         dst++;
  469.         src++;
  470.     }
  471. }
  472.  
  473. /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
  474.    top field is copied as is, but the bottom field is deinterlaced
  475.    against the top field. */
  476. static void deinterlace_bottom_field(UINT8 *dst, int dst_wrap,
  477.                                      UINT8 *src1, int src_wrap,
  478.                                      int width, int height)
  479. {
  480.     UINT8 *src, *ptr;
  481.     int y, y1, i;
  482.     UINT8 *buf;
  483.  
  484.     buf = (UINT8*)av_malloc(5 * width);
  485.  
  486.     src = src1;
  487.     for(y=0;y<height;y+=2) {
  488.         /* copy top field line */
  489.         memcpy(dst, src, width);
  490.         dst += dst_wrap;
  491.         src += (1 - 2) * src_wrap;
  492.         y1 = y - 2;
  493.         if (y1 >= 0 && (y1 + 4) < height) {
  494.             /* fast case : no edges */
  495.             deinterlace_line(dst, src, src_wrap, width);
  496.         } else {
  497.             /* in order to use the same function, we use an intermediate buffer */
  498.             ptr = buf;
  499.             for(i=0;i<5;i++) {
  500.                 if (y1 < 0)
  501.                     memcpy(ptr, src1, width);
  502.                 else if (y1 >= height) 
  503.                     memcpy(ptr, src1 + (height - 1) * src_wrap, width);
  504.                 else
  505.                     memcpy(ptr, src1 + y1 * src_wrap, width);
  506.                 y1++;
  507.                 ptr += width;
  508.             }
  509.             deinterlace_line(dst, buf, width, width);
  510.         }
  511.         dst += dst_wrap;
  512.         src += (2 + 1) * src_wrap;
  513.     }
  514.     av_free(buf);
  515. }
  516.  
  517.  
  518. /* deinterlace, return -1 if format not handled */
  519. int avpicture_deinterlace(AVPicture *dst, AVPicture *src,
  520.                           int pix_fmt, int width, int height)
  521. {
  522.     int i;
  523.  
  524.     if (pix_fmt != PIX_FMT_YUV420P &&
  525.         pix_fmt != PIX_FMT_YUV422P &&
  526.         pix_fmt != PIX_FMT_YUV444P)
  527.         return -1;
  528.     if ((width & 1) != 0 || (height & 3) != 0)
  529.         return -1;
  530.     
  531.     for(i=0;i<3;i++) {
  532.         if (i == 1) {
  533.             switch(pix_fmt) {
  534.             case PIX_FMT_YUV420P:
  535.                 width >>= 1;
  536.                 height >>= 1;
  537.                 break;
  538.             case PIX_FMT_YUV422P:
  539.                 width >>= 1;
  540.                 break;
  541.             default:
  542.                 break;
  543.             }
  544.         }
  545.         deinterlace_bottom_field(dst->data[i], dst->linesize[i],
  546.                                  src->data[i], src->linesize[i],
  547.                                  width, height);
  548.     }
  549.     return 0;
  550. }
  551.  
  552. #undef FIX
  553.