home *** CD-ROM | disk | FTP | other *** search
- // VirtualDub - Video processing and capture application
- // Graphics support library
- // Copyright (C) 1998-2004 Avery Lee
- //
- // This program is free software; you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation; either version 2 of the License, or
- // (at your option) any later version.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program; if not, write to the Free Software
- // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- #include <float.h>
- #include <math.h>
- #include <vd2/system/vdalloc.h>
- #include <vd2/system/vdstl.h>
- #include <vd2/system/memory.h>
- #include <vd2/system/math.h>
- #include <vd2/system/cpuaccel.h>
- #include <vd2/Kasumi/pixmap.h>
- #include <vd2/Kasumi/pixmaputils.h>
- #include <vd2/Kasumi/resample.h>
- #include "uberblit_gen.h"
-
- ///////////////////////////////////////////////////////////////////////////
- //
- // the resampler (finally)
- //
- ///////////////////////////////////////////////////////////////////////////
-
- class VDPixmapResampler : public IVDPixmapResampler {
- public:
- VDPixmapResampler();
- ~VDPixmapResampler();
-
- void SetSplineFactor(double A) { mSplineFactor = A; }
- void SetFilters(FilterMode h, FilterMode v, bool interpolationOnly);
- bool Init(uint32 dw, uint32 dh, int dstformat, uint32 sw, uint32 sh, int srcformat);
- bool Init(const vdrect32f& dstrect, uint32 dw, uint32 dh, int dstformat, const vdrect32f& srcrect, uint32 sw, uint32 sh, int srcformat);
- void Shutdown();
-
- void Process(const VDPixmap& dst, const VDPixmap& src);
-
- protected:
- void ApplyFilters(VDPixmapUberBlitterGenerator& gen, uint32 dw, uint32 dh, float xoffset, float yoffset, float xfactor, float yfactor);
-
- vdautoptr<IVDPixmapBlitter> mpBlitter;
- vdautoptr<IVDPixmapBlitter> mpBlitter2;
- double mSplineFactor;
- FilterMode mFilterH;
- FilterMode mFilterV;
- bool mbInterpOnly;
-
- vdrect32 mDstRectPlane0;
- vdrect32 mDstRectPlane12;
- };
-
- IVDPixmapResampler *VDCreatePixmapResampler() { return new VDPixmapResampler; }
-
- VDPixmapResampler::VDPixmapResampler()
- : mSplineFactor(-0.6)
- , mFilterH(kFilterCubic)
- , mFilterV(kFilterCubic)
- , mbInterpOnly(false)
- {
- }
-
- VDPixmapResampler::~VDPixmapResampler() {
- Shutdown();
- }
-
- void VDPixmapResampler::SetFilters(FilterMode h, FilterMode v, bool interpolationOnly) {
- mFilterH = h;
- mFilterV = v;
- mbInterpOnly = interpolationOnly;
- }
-
- bool VDPixmapResampler::Init(uint32 dw, uint32 dh, int dstformat, uint32 sw, uint32 sh, int srcformat) {
- vdrect32f rSrc(0.0f, 0.0f, (float)sw, (float)sh);
- vdrect32f rDst(0.0f, 0.0f, (float)dw, (float)dh);
- return Init(rDst, dw, dh, dstformat, rSrc, sw, sh, srcformat);
- }
-
- bool VDPixmapResampler::Init(const vdrect32f& dstrect0, uint32 dw, uint32 dh, int dstformat, const vdrect32f& srcrect0, uint32 sw, uint32 sh, int srcformat) {
- Shutdown();
-
- if (dstformat != srcformat || (
- srcformat != nsVDPixmap::kPixFormat_XRGB8888 &&
- srcformat != nsVDPixmap::kPixFormat_Y8 &&
- srcformat != nsVDPixmap::kPixFormat_YUV444_Planar &&
- srcformat != nsVDPixmap::kPixFormat_YUV422_Planar &&
- srcformat != nsVDPixmap::kPixFormat_YUV420_Planar &&
- srcformat != nsVDPixmap::kPixFormat_YUV411_Planar &&
- srcformat != nsVDPixmap::kPixFormat_YUV410_Planar
- ))
- return false;
-
- // convert destination flips to source flips
- vdrect32f dstrect(dstrect0);
- vdrect32f srcrect(srcrect0);
-
- if (dstrect.left > dstrect.right) {
- std::swap(dstrect.left, dstrect.right);
- std::swap(srcrect.left, srcrect.right);
- }
-
- if (dstrect.top > dstrect.bottom) {
- std::swap(dstrect.top, dstrect.bottom);
- std::swap(srcrect.top, srcrect.bottom);
- }
-
- // compute source step factors
- float xfactor = (float)srcrect.width() / (float)dstrect.width();
- float yfactor = (float)srcrect.height() / (float)dstrect.height();
-
- // clip destination rect
- if (dstrect.left < 0) {
- float clipx1 = -dstrect.left;
- srcrect.left += xfactor * clipx1;
- dstrect.left = 0.0f;
- }
-
- if (dstrect.top < 0) {
- float clipy1 = -dstrect.top;
- srcrect.top += yfactor * clipy1;
- dstrect.top = 0.0f;
- }
-
- float clipx2 = dstrect.right - (float)dw;
- if (clipx2 > 0) {
- srcrect.right -= xfactor * clipx2;
- dstrect.right = (float)dw;
- }
-
- float clipy2 = dstrect.bottom - (float)dh;
- if (clipy2 > 0) {
- srcrect.bottom -= yfactor * clipy2;
- dstrect.bottom = (float)dh;
- }
-
- // compute plane 0 dest rect in integral quanta
- const VDPixmapFormatInfo& formatInfo = VDPixmapGetInfo(dstformat);
- mDstRectPlane0.left = VDCeilToInt(dstrect.left - 0.5f);
- mDstRectPlane0.top = VDCeilToInt(dstrect.top - 0.5f);
- mDstRectPlane0.right = VDCeilToInt(dstrect.right - 0.5f);
- mDstRectPlane0.bottom = VDCeilToInt(dstrect.bottom - 0.5f);
-
- // compute plane 0 stepping parameters
- float xoffset = (((float)mDstRectPlane0.left + 0.5f) - dstrect.left) * xfactor + srcrect.left;
- float yoffset = (((float)mDstRectPlane0.top + 0.5f) - dstrect.top ) * yfactor + srcrect.top;
-
- // compute plane 1/2 dest rect and stepping parameters
- float xoffset2 = 0.0f;
- float yoffset2 = 0.0f;
-
- if (formatInfo.auxbufs > 0) {
- float xf2 = (float)(1 << formatInfo.auxwbits);
- float yf2 = (float)(1 << formatInfo.auxhbits);
- float invxf2 = 1.0f / xf2;
- float invyf2 = 1.0f / yf2;
-
- // convert source and dest rects to plane 1/2 space
- vdrect32f srcrect2(srcrect);
- vdrect32f dstrect2(dstrect);
-
- srcrect2.scale(invxf2, invyf2);
- dstrect2.scale(invxf2, invyf2);
-
- switch(srcformat) {
- case nsVDPixmap::kPixFormat_YUV444_Planar:
- break;
- case nsVDPixmap::kPixFormat_YUV422_Planar:
- srcrect2.translate(0.25f, 0.0f);
- dstrect2.translate(0.25f, 0.0f);
- break;
- case nsVDPixmap::kPixFormat_YUV420_Planar:
- srcrect2.translate(0.25f, 0.0f);
- dstrect2.translate(0.25f, 0.0f);
- break;
- case nsVDPixmap::kPixFormat_YUV411_Planar:
- srcrect2.translate(0.375f, 0.0f);
- dstrect2.translate(0.375f, 0.0f);
- break;
- case nsVDPixmap::kPixFormat_YUV410_Planar:
- break;
- default:
- VDASSERT(false);
- }
-
- mDstRectPlane12.left = VDCeilToInt(dstrect2.left - 0.5f);
- mDstRectPlane12.top = VDCeilToInt(dstrect2.top - 0.5f);
- mDstRectPlane12.right = VDCeilToInt(dstrect2.right - 0.5f);
- mDstRectPlane12.bottom = VDCeilToInt(dstrect2.bottom - 0.5f);
-
- xoffset2 = (((float)mDstRectPlane12.left + 0.5f) - dstrect2.left) * xfactor + srcrect2.left;
- yoffset2 = (((float)mDstRectPlane12.top + 0.5f) - dstrect2.top ) * yfactor + srcrect2.top;
- }
-
- VDPixmapUberBlitterGenerator gen;
-
- switch(srcformat) {
- case nsVDPixmap::kPixFormat_XRGB8888:
- gen.ldsrc(0, 0, 0, 0, sw, sh, VDPixmapGetFormatTokenFromFormat(srcformat), sw*4);
- ApplyFilters(gen, mDstRectPlane0.width(), mDstRectPlane0.height(), xoffset, yoffset, xfactor, yfactor);
- break;
-
- case nsVDPixmap::kPixFormat_Y8:
- gen.ldsrc(0, 0, 0, 0, sw, sh, kVDPixType_8, sw);
- ApplyFilters(gen, mDstRectPlane0.width(), mDstRectPlane0.height(), xoffset, yoffset, xfactor, yfactor);
- break;
-
- case nsVDPixmap::kPixFormat_YUV444_Planar:
- case nsVDPixmap::kPixFormat_YUV422_Planar:
- case nsVDPixmap::kPixFormat_YUV420_Planar:
- case nsVDPixmap::kPixFormat_YUV411_Planar:
- case nsVDPixmap::kPixFormat_YUV410_Planar:
- gen.ldsrc(0, 0, 0, 0, sw, sh, kVDPixType_8, sw);
- ApplyFilters(gen, mDstRectPlane0.width(), mDstRectPlane0.height(), xoffset, yoffset, xfactor, yfactor);
-
- {
- const VDPixmapFormatInfo& info = VDPixmapGetInfo(dstformat);
- uint32 subsw = -(-(sint32)sw >> info.auxwbits);
- uint32 subsh = -(-(sint32)sh >> info.auxhbits);
-
- VDPixmapUberBlitterGenerator gen2;
- gen2.ldsrc(0, 0, 0, 0, subsw, subsh, kVDPixType_8, subsw);
- ApplyFilters(gen2, mDstRectPlane12.width(), mDstRectPlane12.height(), xoffset2, yoffset2, xfactor, yfactor);
- mpBlitter2 = gen2.create();
- if (!mpBlitter2)
- return false;
- }
- break;
- }
-
- mpBlitter = gen.create();
- if (!mpBlitter)
- return false;
-
- return true;
- }
-
- void VDPixmapResampler::Shutdown() {
- mpBlitter = NULL;
- mpBlitter2 = NULL;
- }
-
- void VDPixmapResampler::Process(const VDPixmap& dst, const VDPixmap& src) {
- if (!mpBlitter)
- return;
-
- switch(dst.format) {
- case nsVDPixmap::kPixFormat_XRGB8888:
- case nsVDPixmap::kPixFormat_Y8:
- mpBlitter->Blit(dst, &mDstRectPlane0, src);
- break;
-
- case nsVDPixmap::kPixFormat_YUV444_Planar:
- case nsVDPixmap::kPixFormat_YUV422_Planar:
- case nsVDPixmap::kPixFormat_YUV420_Planar:
- case nsVDPixmap::kPixFormat_YUV411_Planar:
- case nsVDPixmap::kPixFormat_YUV410_Planar:
- // blit primary plane
- mpBlitter->Blit(dst, &mDstRectPlane0, src);
-
- // slice and blit secondary planes
- {
- const VDPixmapFormatInfo& formatInfo = VDPixmapGetInfo(dst.format);
- VDPixmap pxdst;
- pxdst.format = nsVDPixmap::kPixFormat_Y8;
- pxdst.w = -(-dst.w >> formatInfo.auxwbits);
- pxdst.h = -(-dst.h >> formatInfo.auxhbits);
- pxdst.pitch = dst.pitch2;
- pxdst.data = dst.data2;
-
- VDPixmap pxsrc;
- pxsrc.format = nsVDPixmap::kPixFormat_Y8;
- pxsrc.w = -(-src.w >> formatInfo.auxwbits);
- pxsrc.h = -(-src.h >> formatInfo.auxhbits);
- pxsrc.pitch = src.pitch2;
- pxsrc.data = src.data2;
-
- mpBlitter2->Blit(pxdst, &mDstRectPlane12, pxsrc);
-
- pxdst.pitch = dst.pitch3;
- pxdst.data = dst.data3;
- pxsrc.pitch = src.pitch3;
- pxsrc.data = src.data3;
- mpBlitter2->Blit(pxdst, &mDstRectPlane12, pxsrc);
- }
- break;
- }
- }
-
- void VDPixmapResampler::ApplyFilters(VDPixmapUberBlitterGenerator& gen, uint32 dw, uint32 dh, float xoffset, float yoffset, float xfactor, float yfactor) {
- switch(mFilterH) {
- case kFilterPoint:
- gen.pointh(xoffset, xfactor, dw);
- break;
-
- case kFilterLinear:
- gen.linearh(xoffset, xfactor, dw, mbInterpOnly);
- break;
-
- case kFilterCubic:
- gen.cubich(xoffset, xfactor, dw, (float)mSplineFactor, mbInterpOnly);
- break;
-
- case kFilterLanczos3:
- gen.lanczos3h(xoffset, xfactor, dw);
- break;
- }
-
- switch(mFilterV) {
- case kFilterPoint:
- gen.pointv(yoffset, yfactor, dh);
- break;
-
- case kFilterLinear:
- gen.linearv(yoffset, yfactor, dh, mbInterpOnly);
- break;
-
- case kFilterCubic:
- gen.cubicv(yoffset, yfactor, dh, (float)mSplineFactor, mbInterpOnly);
- break;
-
- case kFilterLanczos3:
- gen.lanczos3v(yoffset, yfactor, dh);
- break;
- }
- }
-
- bool VDPixmapResample(const VDPixmap& dst, const VDPixmap& src, IVDPixmapResampler::FilterMode filter) {
- VDPixmapResampler r;
-
- r.SetFilters(filter, filter, false);
-
- if (!r.Init(dst.w, dst.h, dst.format, src.w, src.h, src.format))
- return false;
-
- r.Process(dst, src);
- return true;
- }
-