home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / Kasumi / source / resample.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  10.8 KB  |  349 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Graphics support library
  3. //    Copyright (C) 1998-2004 Avery Lee
  4. //
  5. //    This program is free software; you can redistribute it and/or modify
  6. //    it under the terms of the GNU General Public License as published by
  7. //    the Free Software Foundation; either version 2 of the License, or
  8. //    (at your option) any later version.
  9. //
  10. //    This program 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
  13. //    GNU General Public License for more details.
  14. //
  15. //    You should have received a copy of the GNU General Public License
  16. //    along with this program; if not, write to the Free Software
  17. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19. #include <float.h>
  20. #include <math.h>
  21. #include <vd2/system/vdalloc.h>
  22. #include <vd2/system/vdstl.h>
  23. #include <vd2/system/memory.h>
  24. #include <vd2/system/math.h>
  25. #include <vd2/system/cpuaccel.h>
  26. #include <vd2/Kasumi/pixmap.h>
  27. #include <vd2/Kasumi/pixmaputils.h>
  28. #include <vd2/Kasumi/resample.h>
  29. #include "uberblit_gen.h"
  30.  
  31. ///////////////////////////////////////////////////////////////////////////
  32. //
  33. // the resampler (finally)
  34. //
  35. ///////////////////////////////////////////////////////////////////////////
  36.  
  37. class VDPixmapResampler : public IVDPixmapResampler {
  38. public:
  39.     VDPixmapResampler();
  40.     ~VDPixmapResampler();
  41.  
  42.     void SetSplineFactor(double A) { mSplineFactor = A; }
  43.     void SetFilters(FilterMode h, FilterMode v, bool interpolationOnly);
  44.     bool Init(uint32 dw, uint32 dh, int dstformat, uint32 sw, uint32 sh, int srcformat);
  45.     bool Init(const vdrect32f& dstrect, uint32 dw, uint32 dh, int dstformat, const vdrect32f& srcrect, uint32 sw, uint32 sh, int srcformat);
  46.     void Shutdown();
  47.  
  48.     void Process(const VDPixmap& dst, const VDPixmap& src);
  49.  
  50. protected:
  51.     void ApplyFilters(VDPixmapUberBlitterGenerator& gen, uint32 dw, uint32 dh, float xoffset, float yoffset, float xfactor, float yfactor);
  52.  
  53.     vdautoptr<IVDPixmapBlitter> mpBlitter;
  54.     vdautoptr<IVDPixmapBlitter> mpBlitter2;
  55.     double                mSplineFactor;
  56.     FilterMode            mFilterH;
  57.     FilterMode            mFilterV;
  58.     bool                mbInterpOnly;
  59.  
  60.     vdrect32            mDstRectPlane0;
  61.     vdrect32            mDstRectPlane12;
  62. };
  63.  
  64. IVDPixmapResampler *VDCreatePixmapResampler() { return new VDPixmapResampler; }
  65.  
  66. VDPixmapResampler::VDPixmapResampler()
  67.     : mSplineFactor(-0.6)
  68.     , mFilterH(kFilterCubic)
  69.     , mFilterV(kFilterCubic)
  70.     , mbInterpOnly(false)
  71. {
  72. }
  73.  
  74. VDPixmapResampler::~VDPixmapResampler() {
  75.     Shutdown();
  76. }
  77.  
  78. void VDPixmapResampler::SetFilters(FilterMode h, FilterMode v, bool interpolationOnly) {
  79.     mFilterH = h;
  80.     mFilterV = v;
  81.     mbInterpOnly = interpolationOnly;
  82. }
  83.  
  84. bool VDPixmapResampler::Init(uint32 dw, uint32 dh, int dstformat, uint32 sw, uint32 sh, int srcformat) {
  85.     vdrect32f rSrc(0.0f, 0.0f, (float)sw, (float)sh);
  86.     vdrect32f rDst(0.0f, 0.0f, (float)dw, (float)dh);
  87.     return Init(rDst, dw, dh, dstformat, rSrc, sw, sh, srcformat);
  88. }
  89.  
  90. bool VDPixmapResampler::Init(const vdrect32f& dstrect0, uint32 dw, uint32 dh, int dstformat, const vdrect32f& srcrect0, uint32 sw, uint32 sh, int srcformat) {
  91.     Shutdown();
  92.  
  93.     if (dstformat != srcformat || (
  94.             srcformat != nsVDPixmap::kPixFormat_XRGB8888 &&
  95.             srcformat != nsVDPixmap::kPixFormat_Y8 &&
  96.             srcformat != nsVDPixmap::kPixFormat_YUV444_Planar &&
  97.             srcformat != nsVDPixmap::kPixFormat_YUV422_Planar &&
  98.             srcformat != nsVDPixmap::kPixFormat_YUV420_Planar &&
  99.             srcformat != nsVDPixmap::kPixFormat_YUV411_Planar &&
  100.             srcformat != nsVDPixmap::kPixFormat_YUV410_Planar
  101.             ))
  102.         return false;
  103.  
  104.     // convert destination flips to source flips
  105.     vdrect32f dstrect(dstrect0);
  106.     vdrect32f srcrect(srcrect0);
  107.  
  108.     if (dstrect.left > dstrect.right) {
  109.         std::swap(dstrect.left, dstrect.right);
  110.         std::swap(srcrect.left, srcrect.right);
  111.     }
  112.  
  113.     if (dstrect.top > dstrect.bottom) {
  114.         std::swap(dstrect.top, dstrect.bottom);
  115.         std::swap(srcrect.top, srcrect.bottom);
  116.     }
  117.  
  118.     // compute source step factors
  119.     float xfactor = (float)srcrect.width()  / (float)dstrect.width();
  120.     float yfactor = (float)srcrect.height() / (float)dstrect.height();
  121.  
  122.     // clip destination rect
  123.     if (dstrect.left < 0) {
  124.         float clipx1 = -dstrect.left;
  125.         srcrect.left += xfactor * clipx1;
  126.         dstrect.left = 0.0f;
  127.     }
  128.  
  129.     if (dstrect.top < 0) {
  130.         float clipy1 = -dstrect.top;
  131.         srcrect.top += yfactor * clipy1;
  132.         dstrect.top = 0.0f;
  133.     }
  134.  
  135.     float clipx2 = dstrect.right - (float)dw;
  136.     if (clipx2 > 0) {
  137.         srcrect.right -= xfactor * clipx2;
  138.         dstrect.right = (float)dw;
  139.     }
  140.  
  141.     float clipy2 = dstrect.bottom - (float)dh;
  142.     if (clipy2 > 0) {
  143.         srcrect.bottom -= yfactor * clipy2;
  144.         dstrect.bottom = (float)dh;
  145.     }
  146.  
  147.     // compute plane 0 dest rect in integral quanta
  148.     const VDPixmapFormatInfo& formatInfo = VDPixmapGetInfo(dstformat);
  149.     mDstRectPlane0.left        = VDCeilToInt(dstrect.left     - 0.5f);
  150.     mDstRectPlane0.top        = VDCeilToInt(dstrect.top     - 0.5f);
  151.     mDstRectPlane0.right    = VDCeilToInt(dstrect.right     - 0.5f);
  152.     mDstRectPlane0.bottom    = VDCeilToInt(dstrect.bottom - 0.5f);
  153.  
  154.     // compute plane 0 stepping parameters
  155.     float xoffset = (((float)mDstRectPlane0.left + 0.5f) - dstrect.left) * xfactor + srcrect.left;
  156.     float yoffset = (((float)mDstRectPlane0.top  + 0.5f) - dstrect.top ) * yfactor + srcrect.top;
  157.  
  158.     // compute plane 1/2 dest rect and stepping parameters
  159.     float xoffset2 = 0.0f;
  160.     float yoffset2 = 0.0f;
  161.  
  162.     if (formatInfo.auxbufs > 0) {
  163.         float xf2 = (float)(1 << formatInfo.auxwbits);
  164.         float yf2 = (float)(1 << formatInfo.auxhbits);
  165.         float invxf2 = 1.0f / xf2;
  166.         float invyf2 = 1.0f / yf2;
  167.  
  168.         // convert source and dest rects to plane 1/2 space
  169.         vdrect32f srcrect2(srcrect);
  170.         vdrect32f dstrect2(dstrect);
  171.  
  172.         srcrect2.scale(invxf2, invyf2);
  173.         dstrect2.scale(invxf2, invyf2);
  174.  
  175.         switch(srcformat) {
  176.         case nsVDPixmap::kPixFormat_YUV444_Planar:
  177.             break;
  178.         case nsVDPixmap::kPixFormat_YUV422_Planar:
  179.             srcrect2.translate(0.25f, 0.0f);
  180.             dstrect2.translate(0.25f, 0.0f);
  181.             break;
  182.         case nsVDPixmap::kPixFormat_YUV420_Planar:
  183.             srcrect2.translate(0.25f, 0.0f);
  184.             dstrect2.translate(0.25f, 0.0f);
  185.             break;
  186.         case nsVDPixmap::kPixFormat_YUV411_Planar:
  187.             srcrect2.translate(0.375f, 0.0f);
  188.             dstrect2.translate(0.375f, 0.0f);
  189.             break;
  190.         case nsVDPixmap::kPixFormat_YUV410_Planar:
  191.             break;
  192.         default:
  193.             VDASSERT(false);
  194.         }
  195.  
  196.         mDstRectPlane12.left    = VDCeilToInt(dstrect2.left        - 0.5f);
  197.         mDstRectPlane12.top        = VDCeilToInt(dstrect2.top        - 0.5f);
  198.         mDstRectPlane12.right    = VDCeilToInt(dstrect2.right    - 0.5f);
  199.         mDstRectPlane12.bottom    = VDCeilToInt(dstrect2.bottom    - 0.5f);
  200.  
  201.         xoffset2 = (((float)mDstRectPlane12.left + 0.5f) - dstrect2.left) * xfactor + srcrect2.left;
  202.         yoffset2 = (((float)mDstRectPlane12.top  + 0.5f) - dstrect2.top ) * yfactor + srcrect2.top;
  203.     }
  204.  
  205.     VDPixmapUberBlitterGenerator gen;
  206.  
  207.     switch(srcformat) {
  208.         case nsVDPixmap::kPixFormat_XRGB8888:
  209.             gen.ldsrc(0, 0, 0, 0, sw, sh, VDPixmapGetFormatTokenFromFormat(srcformat), sw*4);
  210.             ApplyFilters(gen, mDstRectPlane0.width(), mDstRectPlane0.height(), xoffset, yoffset, xfactor, yfactor);
  211.             break;
  212.  
  213.         case nsVDPixmap::kPixFormat_Y8:
  214.             gen.ldsrc(0, 0, 0, 0, sw, sh, kVDPixType_8, sw);
  215.             ApplyFilters(gen, mDstRectPlane0.width(), mDstRectPlane0.height(), xoffset, yoffset, xfactor, yfactor);
  216.             break;
  217.  
  218.         case nsVDPixmap::kPixFormat_YUV444_Planar:
  219.         case nsVDPixmap::kPixFormat_YUV422_Planar:
  220.         case nsVDPixmap::kPixFormat_YUV420_Planar:
  221.         case nsVDPixmap::kPixFormat_YUV411_Planar:
  222.         case nsVDPixmap::kPixFormat_YUV410_Planar:
  223.             gen.ldsrc(0, 0, 0, 0, sw, sh, kVDPixType_8, sw);
  224.             ApplyFilters(gen, mDstRectPlane0.width(), mDstRectPlane0.height(), xoffset, yoffset, xfactor, yfactor);
  225.  
  226.             {
  227.                 const VDPixmapFormatInfo& info = VDPixmapGetInfo(dstformat);
  228.                 uint32 subsw = -(-(sint32)sw >> info.auxwbits);
  229.                 uint32 subsh = -(-(sint32)sh >> info.auxhbits);
  230.  
  231.                 VDPixmapUberBlitterGenerator gen2;
  232.                 gen2.ldsrc(0, 0, 0, 0, subsw, subsh, kVDPixType_8, subsw);
  233.                 ApplyFilters(gen2, mDstRectPlane12.width(), mDstRectPlane12.height(), xoffset2, yoffset2, xfactor, yfactor);
  234.                 mpBlitter2 = gen2.create();
  235.                 if (!mpBlitter2)
  236.                     return false;
  237.             }
  238.             break;
  239.     }
  240.  
  241.     mpBlitter = gen.create();
  242.     if (!mpBlitter)
  243.         return false;
  244.  
  245.     return true;
  246. }
  247.  
  248. void VDPixmapResampler::Shutdown() {
  249.     mpBlitter = NULL;
  250.     mpBlitter2 = NULL;
  251. }
  252.  
  253. void VDPixmapResampler::Process(const VDPixmap& dst, const VDPixmap& src) {
  254.     if (!mpBlitter)
  255.         return;
  256.  
  257.     switch(dst.format) {
  258.         case nsVDPixmap::kPixFormat_XRGB8888:
  259.         case nsVDPixmap::kPixFormat_Y8:
  260.             mpBlitter->Blit(dst, &mDstRectPlane0, src);
  261.             break;
  262.  
  263.         case nsVDPixmap::kPixFormat_YUV444_Planar:
  264.         case nsVDPixmap::kPixFormat_YUV422_Planar:
  265.         case nsVDPixmap::kPixFormat_YUV420_Planar:
  266.         case nsVDPixmap::kPixFormat_YUV411_Planar:
  267.         case nsVDPixmap::kPixFormat_YUV410_Planar:
  268.             // blit primary plane
  269.             mpBlitter->Blit(dst, &mDstRectPlane0, src);
  270.  
  271.             // slice and blit secondary planes
  272.             {
  273.                 const VDPixmapFormatInfo& formatInfo = VDPixmapGetInfo(dst.format);
  274.                 VDPixmap pxdst;
  275.                 pxdst.format    = nsVDPixmap::kPixFormat_Y8;
  276.                 pxdst.w            = -(-dst.w >> formatInfo.auxwbits);
  277.                 pxdst.h            = -(-dst.h >> formatInfo.auxhbits);
  278.                 pxdst.pitch        = dst.pitch2;
  279.                 pxdst.data        = dst.data2;
  280.  
  281.                 VDPixmap pxsrc;
  282.                 pxsrc.format    = nsVDPixmap::kPixFormat_Y8;
  283.                 pxsrc.w            = -(-src.w >> formatInfo.auxwbits);
  284.                 pxsrc.h            = -(-src.h >> formatInfo.auxhbits);
  285.                 pxsrc.pitch        = src.pitch2;
  286.                 pxsrc.data        = src.data2;
  287.  
  288.                 mpBlitter2->Blit(pxdst, &mDstRectPlane12, pxsrc);
  289.  
  290.                 pxdst.pitch        = dst.pitch3;
  291.                 pxdst.data        = dst.data3;
  292.                 pxsrc.pitch        = src.pitch3;
  293.                 pxsrc.data        = src.data3;
  294.                 mpBlitter2->Blit(pxdst, &mDstRectPlane12, pxsrc);
  295.             }
  296.             break;
  297.     }
  298. }
  299.  
  300. void VDPixmapResampler::ApplyFilters(VDPixmapUberBlitterGenerator& gen, uint32 dw, uint32 dh, float xoffset, float yoffset, float xfactor, float yfactor) {
  301.     switch(mFilterH) {
  302.         case kFilterPoint:
  303.             gen.pointh(xoffset, xfactor, dw);
  304.             break;
  305.  
  306.         case kFilterLinear:
  307.             gen.linearh(xoffset, xfactor, dw, mbInterpOnly);
  308.             break;
  309.  
  310.         case kFilterCubic:
  311.             gen.cubich(xoffset, xfactor, dw, (float)mSplineFactor, mbInterpOnly);
  312.             break;
  313.  
  314.         case kFilterLanczos3:
  315.             gen.lanczos3h(xoffset, xfactor, dw);
  316.             break;
  317.     }
  318.  
  319.     switch(mFilterV) {
  320.         case kFilterPoint:
  321.             gen.pointv(yoffset, yfactor, dh);
  322.             break;
  323.  
  324.         case kFilterLinear:
  325.             gen.linearv(yoffset, yfactor, dh, mbInterpOnly);
  326.             break;
  327.  
  328.         case kFilterCubic:
  329.             gen.cubicv(yoffset, yfactor, dh, (float)mSplineFactor, mbInterpOnly);
  330.             break;
  331.  
  332.         case kFilterLanczos3:
  333.             gen.lanczos3v(yoffset, yfactor, dh);
  334.             break;
  335.     }
  336. }
  337.  
  338. bool VDPixmapResample(const VDPixmap& dst, const VDPixmap& src, IVDPixmapResampler::FilterMode filter) {
  339.     VDPixmapResampler r;
  340.  
  341.     r.SetFilters(filter, filter, false);
  342.  
  343.     if (!r.Init(dst.w, dst.h, dst.format, src.w, src.h, src.format))
  344.         return false;
  345.  
  346.     r.Process(dst, src);
  347.     return true;
  348. }
  349.