// // libavg - Media Playback Engine. // Copyright (C) 2003-2014 Ulrich von Zadow // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library 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 // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // Current versions can be found at www.libavg.de // #include "GraphicsTest.h" #include "Bitmap.h" #include "BitmapLoader.h" #include "Pixel32.h" #include "Pixel24.h" #include "Pixel16.h" #include "Filtercolorize.h" #include "Filtergrayscale.h" #include "Filterfill.h" #include "Filterflip.h" #include "Filterfliprgb.h" #include "Filterflipuv.h" #include "Filter3x3.h" #include "FilterConvol.h" #include "HistoryPreProcessor.h" #include "FilterHighpass.h" #include "FilterFastBandpass.h" #include "FilterGauss.h" #include "FilterBlur.h" #include "FilterBandpass.h" #include "FilterFastDownscale.h" #include "FilterMask.h" #include "FilterThreshold.h" #include "FilterFloodfill.h" #include "FilterDilation.h" #include "FilterErosion.h" #include "FilterGetAlpha.h" #include "FilterResizeBilinear.h" #include "FilterUnmultiplyAlpha.h" #include "../base/TestSuite.h" #include "../base/Exception.h" #include "../base/MathHelper.h" #ifdef _WIN32 #pragma warning(push) #pragma warning(disable: 4251) #endif #ifdef _WIN32 #pragma warning(pop) #endif #include #include #include #include #include using namespace avg; using namespace std; BitmapPtr initBmp(PixelFormat pf) { int height; if (pf == YCbCr422) { height = 10; } else { height = 7; } BitmapPtr pBmp(new Bitmap(IntPoint(4, height), pf)); int bpp = pBmp->getBytesPerPixel(); for (int y = 0; y < height; ++y) { for (int x = 0; x < 4; ++x) { unsigned char * pPixel = pBmp->getPixels()+y*pBmp->getStride()+x*pBmp->getBytesPerPixel(); *(pPixel) = x; if (bpp > 1) { *(pPixel+1) = 0; } if (bpp > 2) { *(pPixel+2) = x; *(pPixel) = 16*y; } if (bpp > 3) { *(pPixel+3) = 0x80; } } } return pBmp; } // TODO: This is very incomplete! class PixelTest: public GraphicsTest { public: PixelTest() : GraphicsTest("PixelTest", 2) { } void runTests() { float h, s, l; Pixel32(255, 0, 0).toHSL(h, s, l); TEST(h == 0 && almostEqual(s, 1.0f) && almostEqual(l, 0.5f)); Pixel32(0, 255, 0).toHSL(h, s, l); TEST(h == 120 && almostEqual(s, 1.0f) && almostEqual(l, 0.5f)); Pixel32(0, 0, 255).toHSL(h, s, l); TEST(h == 240 && almostEqual(s, 1.0f) && almostEqual(l, 0.5f)); Pixel32(255, 255, 0).toHSL(h, s, l); TEST(h == 60 && almostEqual(s, 1.0f) && almostEqual(l, 0.5f)); Pixel32(255, 0, 255).toHSL(h, s, l); TEST(h == 300 && almostEqual(s, 1.0f) && almostEqual(l, 0.5f)); Pixel32(0, 255, 255).toHSL(h, s, l); TEST(h == 180 && almostEqual(s, 1.0f) && almostEqual(l, 0.5f)); Pixel32(0, 0, 0).toHSL(h, s, l); TEST(s == 0.0f && l == 0.0f); Pixel32(255, 255, 255).toHSL(h, s, l); TEST(s == 0.0f && l == 1.0f); Pixel32(128, 128, 128).toHSL(h, s, l); TEST(s == 0.0f && almostEqual(l, 0.5f, 0.02f)); } }; class BitmapTest: public GraphicsTest { public: BitmapTest() : GraphicsTest("BitmapTest", 2) { } void runTests() { runPFTests(B8G8R8A8); runPFTests(R8G8B8A8); runPFTests(R8G8B8X8); runPFTests(R8G8B8); runPFTests(I8); runPFTests(I16); runPFTests(YCbCr422); runLineTest(B8G8R8A8, Pixel32(0,0,255,255)); runLineTest(B8G8R8, Pixel24(0,0,255)); runLineTest(I8, Pixel8(255)); cerr << " Testing OwnsBits." << endl; unsigned char pData[4*7*3]; for (int i = 0; i < 4*7*3; ++i) { pData[i] = i; } Bitmap Bmp1 = Bitmap(IntPoint(4,7), R8G8B8, pData, 12, true, ""); Bitmap Bmp2 = Bitmap(IntPoint(4,7), R8G8B8, pData, 12, false, ""); testEqual(Bmp1, Bmp2, "BmpOwnsBits"); { cerr << " Testing copyPixels - R8G8B8X8->R8G8B8->R8G8B8X8." << endl; BitmapPtr pBmp = initBmp(R8G8B8X8); Bitmap Bmp1(IntPoint(4,7), R8G8B8); Bmp1.copyPixels(*pBmp); Bitmap Bmp2(IntPoint(4,7), R8G8B8X8); Bmp2.copyPixels(Bmp1); for(int y = 0; y < 7; ++y) { for (int x = 0; x < 4; ++x) { *(Bmp2.getPixels()+y*Bmp2.getStride()+x *Bmp2.getBytesPerPixel()+3) = 0x80; } } testEqual(Bmp2, *pBmp, "BmpCopyPixels_1"); } { cerr << " Testing copyPixels - R8G8B8A8->R8G8B8->R8G8B8A8." << endl; BitmapPtr pBmp = initBmp(R8G8B8A8); BitmapPtr pBaselineBmp = initBmp(R8G8B8A8); BitmapPtr pCopyBmp = BitmapPtr(new Bitmap(IntPoint(4,7), R8G8B8)); pCopyBmp->copyPixels(*pBmp); pBmp->copyPixels(*pCopyBmp); for(int y = 0; y < 7; ++y) { for (int x = 0; x < 4; ++x) { *(pBmp->getPixels()+y*pBmp->getStride()+x *pBmp->getBytesPerPixel()+3) = 0x80; } } testEqual(*pBmp, *pBaselineBmp, "BmpCopyPixels_2"); } { cerr << " Testing copyPixels - I8->I16->I8." << endl; BitmapPtr pBmp = initBmp(I8); BitmapPtr pBaselineBmp = initBmp(I8); BitmapPtr pCopyBmp = BitmapPtr(new Bitmap(IntPoint(4,7), I16)); pCopyBmp->copyPixels(*pBmp); pBmp->copyPixels(*pCopyBmp); testEqual(*pBmp, *pBaselineBmp, "BmpCopyPixels_3"); } { cerr << " Testing copyPixels - R8G8B8A8->R32G32B32A32F->R8G8B8A8." << endl; BitmapPtr pBmp = initBmp(R8G8B8A8); BitmapPtr pBaselineBmp = initBmp(R8G8B8A8); BitmapPtr pCopyBmp = BitmapPtr(new Bitmap(IntPoint(4,7), R32G32B32A32F)); pCopyBmp->copyPixels(*pBmp); pBmp->copyPixels(*pCopyBmp); testEqual(*pBmp, *pBaselineBmp, "BmpCopyPixels_3"); } { cerr << " Testing copyPixels - B5G6R5->B8G8R8->B5G6R5." << endl; BitmapPtr pBmp = initBmp(B5G6R5); BitmapPtr pBaselineBmp = initBmp(B5G6R5); BitmapPtr pCopyBmp = BitmapPtr(new Bitmap(IntPoint(4,7), B8G8R8)); pCopyBmp->copyPixels(*pBmp); pBmp->copyPixels(*pCopyBmp); testEqual(*pBmp, *pBaselineBmp, "BmpCopyPixels_4"); } testCopyToGreyscale(R8G8B8X8); testCopyToGreyscale(B8G8R8X8); testSubtract(); { cerr << " Testing statistics." << endl; cerr << " I8" << endl; testStatistics(I8, Pixel8(0), Pixel8(0), Pixel8(2), Pixel8(2)); cerr << " R8G8B8A8" << endl; testStatistics(R8G8B8A8, Pixel32(0,0,0,0), Pixel32(0,0,0,0), Pixel32(255,255,255,255), Pixel32(255,255,255,255), 127.5, 90.1561); cerr << " R8G8B8X8" << endl; testStatistics(R8G8B8X8, Pixel32(0,0,0,255), Pixel32(0,0,0,255), Pixel32(2,2,2,255), Pixel32(2,2,2,255)); cerr << " R8G8B8" << endl; testStatistics(R8G8B8, Pixel24(0,0,0), Pixel24(0,0,0), Pixel24(2,2,2), Pixel24(2,2,2)); cerr << " ChannelAvg" << endl; testChannelAvg(); } { cerr << " Testing YUV->RGB conversion." << endl; testYUV2RGB(); } runSaveTest(B8G8R8A8); runSaveTest(B8G8R8X8); } private: void runPFTests(PixelFormat pf) { cerr << " Testing " << pf << endl; BitmapPtr pBmp = initBmp(pf); { cerr << " Testing size." <getSize() == IntPoint(4,10)); } else { TEST(pBmp->getSize() == IntPoint(4,7)); } } { cerr << " Testing copy constructor." << endl; Bitmap bmpCopy1(*pBmp); testEqual(bmpCopy1, *pBmp, "BmpCopyConstructor"); } { cerr << " Testing assignment operator." << endl; Bitmap bmpCopy2 = *pBmp; testEqual(bmpCopy2, *pBmp, "BmpAssignment"); } { cerr << " Testing sub-bitmap constructor." << endl; Bitmap bmpCopy3 (*pBmp, IntRect(IntPoint(0,0), pBmp->getSize())); testEqual(bmpCopy3, *pBmp, "BmpSubBmpCtor"); } if (pf == I8) { cerr << " Testing getHistogram." << endl; HistogramPtr pHist = pBmp->getHistogram(); TEST((*pHist)[0] == 7); TEST((*pHist)[1] == 7); TEST((*pHist)[2] == 7); TEST((*pHist)[3] == 7); bool bOk = true; for (int i = 4; i < 256; ++i) { if (bOk) { bOk = ((*pHist)[i] == 0); } } TEST(bOk); } } void runSaveTest(PixelFormat pf) { cerr << " Testing save for " << pf << endl; BitmapPtr pBmp = initBmp(pf); pBmp->save("test.png"); BitmapPtr pLoadedBmp = loadBitmap("test.png"); ::remove("test.png"); testEqual(*pLoadedBmp, *pBmp, "BmpSave"); } template void runLineTest(PixelFormat pf, PIXEL color) { cerr << " Testing line drawing for " << pf << endl; Bitmap bmp(IntPoint(15, 15), pf); memset(bmp.getPixels(), 0, bmp.getStride()*15); bmp.drawLine(IntPoint(7,7), IntPoint( 0, 2), color); bmp.drawLine(IntPoint(7,7), IntPoint( 0,12), color); bmp.drawLine(IntPoint(7,7), IntPoint( 2, 0), color); bmp.drawLine(IntPoint(7,7), IntPoint( 2,14), color); bmp.drawLine(IntPoint(7,7), IntPoint(12, 0), color); bmp.drawLine(IntPoint(7,7), IntPoint(12,14), color); bmp.drawLine(IntPoint(7,7), IntPoint(14, 2), color); bmp.drawLine(IntPoint(7,7), IntPoint(14,12), color); string sFName = getSrcDirName() + "baseline/LineResult" + getPixelFormatString(pf) + ".png"; BitmapPtr pBaselineBmp = loadBitmap(sFName, pf); testEqual(bmp, *pBaselineBmp, "BmpLineDraw"); } void testCopyToGreyscale(PixelFormat pf) { cerr << " Testing copyPixels - " << pf << "->I8." << endl; BitmapPtr pBmp(new Bitmap(IntPoint(4,4), pf)); for (int y=0; y<4; ++y) { for (int x=0; x<4; ++x) { unsigned char * pPixel = pBmp->getPixels()+y*pBmp->getStride()+x*pBmp->getBytesPerPixel(); pPixel[0] = x*64; pPixel[1] = 128; pPixel[2] = y*64; pPixel[3] = 255; } } BitmapPtr pCopyBmp = BitmapPtr(new Bitmap(IntPoint(4,4), I8)); pCopyBmp->copyPixels(*pBmp); testEqual(*pCopyBmp, string("copyPixels_")+getPixelFormatString(pf)+"_I8", I8, 0.5, 0.5); } void testSubtract() { BitmapPtr pBmp1(new Bitmap(IntPoint(4,1), I8)); BitmapPtr pBmp2(new Bitmap(IntPoint(4,1), I8)); for (int x=0; x<4; ++x) { pBmp1->getPixels()[x] = x; pBmp2->getPixels()[x] = 0; } BitmapPtr pDiffBmp = pBmp1->subtract(*pBmp2); testEqual(*pDiffBmp, *pBmp1, "BmpSubtract1"); pDiffBmp = pBmp2->subtract(*pBmp1); testEqual(*pDiffBmp, *pBmp1, "BmpSubtract2"); } template void testStatistics(PixelFormat pf, const PIXEL& p00, const PIXEL& p01, const PIXEL& p10, const PIXEL& p11, float avg=1, float stdDev=1) { BitmapPtr pBmp = BitmapPtr(new Bitmap(IntPoint(2,2), pf)); pBmp->setPixel(IntPoint(0,0), p00); pBmp->setPixel(IntPoint(0,1), p01); pBmp->setPixel(IntPoint(1,0), p10); pBmp->setPixel(IntPoint(1,1), p11); TEST(almostEqual(pBmp->getAvg(), avg, 0.001)); TEST(almostEqual(pBmp->getStdDev(), stdDev, 0.001)); } void testChannelAvg() { BitmapPtr pBmp = BitmapPtr(new Bitmap(IntPoint(2,2), R8G8B8)); pBmp->setPixel(IntPoint(0,0), Pixel24(0,0,0)); pBmp->setPixel(IntPoint(0,1), Pixel24(128,0,0)); pBmp->setPixel(IntPoint(1,0), Pixel24(128,128,0)); pBmp->setPixel(IntPoint(1,1), Pixel24(128,128,128)); TEST(almostEqual(pBmp->getChannelAvg(0), 96)); TEST(almostEqual(pBmp->getChannelAvg(1), 64)); TEST(almostEqual(pBmp->getChannelAvg(2), 32)); } void testYUV2RGB() { BitmapPtr pYBmp = BitmapPtr(new Bitmap(IntPoint(16, 16), I8)); for (int x=0; x<16; ++x) { FilterFillRect(IntRect(x, 0, x+1, 16), 255-x*16).applyInPlace(pYBmp); } BitmapPtr pUBmp = BitmapPtr(new Bitmap(IntPoint(8, 8), I8)); BitmapPtr pVBmp = BitmapPtr(new Bitmap(IntPoint(8, 8), I8)); FilterFillRect(IntRect(0, 0, 8, 4), 128).applyInPlace(pUBmp); FilterFillRect(IntRect(0, 0, 8, 4), 128).applyInPlace(pVBmp); for (int y=4; y<8; ++y) { FilterFillRect(IntRect(0, y, 8, y+1), y*64).applyInPlace(pUBmp); FilterFillRect(IntRect(0, y, 8, y+1), 255-y*64).applyInPlace(pVBmp); } BitmapPtr pRGBBmp = BitmapPtr(new Bitmap(IntPoint(16, 16), B8G8R8X8)); FilterFill(Pixel32(255,0,0,255)).applyInPlace(pRGBBmp); pRGBBmp->copyYUVPixels(*pYBmp, *pUBmp, *pVBmp, false); testEqual(*pRGBBmp, "YUV2RGBResult1", B8G8R8X8, 0.5, 0.5); } }; class FilterColorizeTest: public GraphicsTest { public: FilterColorizeTest() : GraphicsTest("FilterColorizeTest", 2) { } void runTests() { runPFTests(R8G8B8A8); runPFTests(R8G8B8); } private: void runPFTests(PixelFormat pf) { BitmapPtr pBmp = initBmp(pf); FilterColorize(15, 0).applyInPlace(pBmp); FilterColorize(100, 50).applyInPlace(pBmp); FilterColorize(50, 100).applyInPlace(pBmp); } }; class FilterGrayscaleTest: public GraphicsTest { public: FilterGrayscaleTest() : GraphicsTest("FilterGrayscaleTest", 2) { } void runTests() { runPFTests(R8G8B8A8); runPFTests(R8G8B8); runPFTests(I8); } private: void runPFTests(PixelFormat pf) { BitmapPtr pBmp = initBmp(pf); FilterGrayscale().applyInPlace(pBmp); } }; class FilterFillTest: public GraphicsTest { public: FilterFillTest() : GraphicsTest("FilterFillTest", 2) { } void runTests() { runPFTests(R8G8B8A8, Pixel32(255,80,0,255)); runPFTests(R8G8B8, Pixel24(255,80,0)); } private: template void runPFTests(PixelFormat pf, PixelC color) { BitmapPtr pBmp = initBmp(pf); FilterFill(color).applyInPlace(pBmp); } }; class FilterFlipTest: public GraphicsTest { public: FilterFlipTest() : GraphicsTest("FilterFlipTest", 2) { } void runTests() { runPFTests(R8G8B8A8); runPFTests(B8G8R8X8); runPFTests(R8G8B8); runPFTests(I8); } private: void runPFTests(PixelFormat pf) { BitmapPtr pBmp = initBmp(pf); { BitmapPtr pBmp1 = FilterFlip().apply(pBmp); BitmapPtr pBmp2 = FilterFlip().apply(pBmp1); TEST(*pBmp == *pBmp2); } pBmp = initBmp(pf); { Bitmap baselineBmp = *pBmp; FilterFlip().applyInPlace(pBmp); FilterFlip().applyInPlace(pBmp); TEST(*pBmp == baselineBmp); } } }; class FilterFlipRGBTest: public GraphicsTest { public: FilterFlipRGBTest() : GraphicsTest("FilterFlipRGBTest", 2) { } void runTests() { runPFTests(B8G8R8A8); runPFTests(R8G8B8A8); runPFTests(R8G8B8); } private: void runPFTests(PixelFormat pf) { BitmapPtr pBmp = initBmp(pf); { BitmapPtr pBmp1 = FilterFlipRGB().apply(pBmp); BitmapPtr pBmp2 = FilterFlipRGB().apply(pBmp1); TEST(*pBmp == *pBmp2); } { Bitmap baselineBmp = *pBmp; FilterFlipRGB().applyInPlace(pBmp); FilterFlipRGB().applyInPlace(pBmp); TEST(*pBmp == baselineBmp); } } }; class FilterFlipUVTest: public GraphicsTest { public: FilterFlipUVTest() : GraphicsTest("FilterFlipUVTest", 2) { } void runTests() { BitmapPtr pBmp = initBmp(YCbCr422); { BitmapPtr pBmp1 = FilterFlipUV().apply(pBmp); BitmapPtr pBmp2 = FilterFlipUV().apply(pBmp1); TEST(*pBmp == *pBmp2); } { Bitmap baselineBmp = *pBmp; FilterFlipUV().applyInPlace(pBmp); FilterFlipUV().applyInPlace(pBmp); TEST(*pBmp == baselineBmp); } } }; class FilterComboTest: public GraphicsTest { public: FilterComboTest() : GraphicsTest("FilterComboTest", 2) { } void runTests() { try { char * pSrcDir = getenv("srcdir"); string sFilename; if (pSrcDir) { sFilename = (string)pSrcDir+"/"; } sFilename += "../test/media/rgb24-64x64.png"; BitmapPtr pBmp = loadBitmap(sFilename, R8G8B8); FilterColorize(15, 50).applyInPlace(pBmp); FilterFlipRGB().applyInPlace(pBmp); } catch (Exception & ex) { cerr << ex.getStr() << endl; setFailed(); } } private: BitmapPtr createBmp(const IntPoint& size, PixelFormat pf) { BitmapPtr pBmp; pBmp = BitmapPtr(new Bitmap(size, pf)); return pBmp; } }; class FilterConvolTest: public GraphicsTest { public: FilterConvolTest() : GraphicsTest("FilterConvolTest", 2) { } void runTests() { runPFTests(R8G8B8); runPFTests(R8G8B8X8); //FIXME runPFTests(I8); } private: template void runPFTests(PixelFormat pf) { BitmapPtr pBmp(new Bitmap(IntPoint(4, 4), pf)); initBmp(pBmp); float mat[9] = {1,0,2, 0,1,0, 3,0,4}; BitmapPtr pNewBmp = FilterConvol(&(mat[0]),3,3).apply(pBmp); TEST(pNewBmp->getSize() == IntPoint(2,2)); unsigned char * pLine0 = pNewBmp->getPixels(); TEST(*(PIXEL*)pLine0 == PIXEL(1,0,0)); TEST(*(((PIXEL*)pLine0)+1) == PIXEL(4,0,0)); unsigned char * pLine1 = pNewBmp->getPixels()+pNewBmp->getStride(); TEST(*(PIXEL*)(pLine1) == PIXEL(0,0,9)); TEST(*((PIXEL*)(pLine1)+1) == PIXEL(0,0,16)); } template void initBmp(BitmapPtr pBmp) { PIXEL * pPixels = (PIXEL *)(pBmp->getPixels()); PIXEL color = PIXEL(0,0,0); FilterFill(color).applyInPlace(pBmp); pPixels[0] = PIXEL(1,0,0); pPixels[3] = PIXEL(2,0,0); pPixels = (PIXEL*)((char *)pPixels+3*pBmp->getStride()); pPixels[0] = PIXEL(0,0,3); pPixels[3] = PIXEL(0,0,4); } }; class Filter3x3Test: public GraphicsTest { public: Filter3x3Test() : GraphicsTest("Filter3x3Test", 2) { } void runTests() { runPFTests(R8G8B8); runPFTests(R8G8B8X8); } private: template void runPFTests(PixelFormat pf) { BitmapPtr pBmp(new Bitmap(IntPoint(4, 4), pf)); initBmp(pBmp); float mat[3][3] = {{1,0,2}, {0,1,0}, {3,0,4}}; BitmapPtr pNewBmp = Filter3x3(mat).apply(pBmp); TEST(pNewBmp->getSize() == IntPoint(2,2)); unsigned char * pLine0 = pNewBmp->getPixels(); TEST(*(PIXEL*)pLine0 == PIXEL(1,0,0)); TEST(*(((PIXEL*)pLine0)+1) == PIXEL(4,0,0)); unsigned char * pLine1 = pNewBmp->getPixels()+pNewBmp->getStride(); TEST(*(PIXEL*)(pLine1) == PIXEL(0,0,9)); TEST(*((PIXEL*)(pLine1)+1) == PIXEL(0,0,16)); } template void initBmp(BitmapPtr pBmp) { PIXEL * pPixels = (PIXEL *)(pBmp->getPixels()); PIXEL color = PIXEL(0,0,0); FilterFill(color).applyInPlace(pBmp); pPixels[0] = PIXEL(1,0,0); pPixels[3] = PIXEL(2,0,0); pPixels = (PIXEL*)((char *)pPixels+3*pBmp->getStride()); pPixels[0] = PIXEL(0,0,3); pPixels[3] = PIXEL(0,0,4); } }; class HistoryPreProcessorTest: public GraphicsTest { public: HistoryPreProcessorTest() : GraphicsTest("HistoryPreProcessor", 2) { } void runTests() { BitmapPtr pBaseBmp = initBmp(I8); BitmapPtr pBmp = BitmapPtr(new Bitmap(*pBaseBmp)); BitmapPtr nullBmp = FilterFill(0).apply(pBmp); pBmp->copyPixels(*pBaseBmp); HistoryPreProcessor filt(pBaseBmp->getSize(), 1, true); pBmp = filt.apply(pBaseBmp); testEqual(*pBmp, *nullBmp, "HistoryPreprocessor1"); for(int i=0;i<1;i++){ pBmp = filt.apply(pBaseBmp); testEqual(*pBmp, *nullBmp, "HistoryPreprocessor2"); } } }; class FilterFastBandpassTest: public GraphicsTest { public: FilterFastBandpassTest() : GraphicsTest("FilterFastBandpassTest", 2) { } void runTests() { BitmapPtr pBmp = BitmapPtr(new Bitmap(IntPoint(16,16), I8)); FilterFill(0).applyInPlace(pBmp); *(pBmp->getPixels()+pBmp->getStride()*7+7) = 255; BitmapPtr pDestBmp = FilterFastBandpass().apply(pBmp); testEqual(*pDestBmp, "FastBandpassResult", I8); } }; class FilterHighpassTest: public GraphicsTest { public: FilterHighpassTest() : GraphicsTest("FilterHighpassTest", 2) { } void runTests() { BitmapPtr pBmp = BitmapPtr(new Bitmap(IntPoint(16,16), I8)); FilterFill(0).applyInPlace(pBmp); *(pBmp->getPixels()+pBmp->getStride()*7+7) = 255; BitmapPtr pDestBmp = FilterHighpass().apply(pBmp); testEqual(*pDestBmp, "HighpassResult", I8); } }; class FilterGaussTest: public GraphicsTest { public: FilterGaussTest() : GraphicsTest("FilterGaussTest", 2) { } void runTests() { BitmapPtr pBmp = BitmapPtr(new Bitmap(IntPoint(16,16), I8)); FilterFill(0).applyInPlace(pBmp); *(pBmp->getPixels()+pBmp->getStride()*7+7) = 255; BitmapPtr pDestBmp = FilterGauss(3).apply(pBmp); testEqual(*pDestBmp, "Gauss3Result", I8); pDestBmp = FilterGauss(1).apply(pBmp); testEqual(*pDestBmp, "Gauss1Result", I8); pDestBmp = FilterGauss(1.5).apply(pBmp); testEqual(*pDestBmp, "Gauss15Result", I8); pDestBmp = FilterGauss(5).apply(pBmp); testEqual(*pDestBmp, "Gauss5Result", I8); } }; class FilterBlurTest: public GraphicsTest { public: FilterBlurTest() : GraphicsTest("FilterBlurTest", 2) { } void runTests() { BitmapPtr pBmp = BitmapPtr(new Bitmap(IntPoint(16,16), I8)); FilterFill(0).applyInPlace(pBmp); *(pBmp->getPixels()+pBmp->getStride()*7+7) = 255; BitmapPtr pDestBmp = FilterBlur().apply(pBmp); testEqual(*pDestBmp, "BlurResult", I8); } }; class FilterBandpassTest: public GraphicsTest { public: FilterBandpassTest() : GraphicsTest("FilterBandpassTest", 2) { } void runTests() { BitmapPtr pBmp = BitmapPtr(new Bitmap(IntPoint(16,16), I8)); FilterFill(0).applyInPlace(pBmp); *(pBmp->getPixels()+pBmp->getStride()*7+7) = 255; BitmapPtr pDestBmp = FilterBandpass(1.9,3).apply(pBmp); testEqual(*pDestBmp, "BandpassResult", I8); } }; class FilterFastDownscaleTest: public GraphicsTest { public: FilterFastDownscaleTest() : GraphicsTest("FilterFastDownscaleTest", 2) { } void runTests() { BitmapPtr pBmp = BitmapPtr(new Bitmap(IntPoint(4,4), I8)); FilterFill(0).applyInPlace(pBmp); *(pBmp->getPixels()+pBmp->getStride()*3+3) = 252; BitmapPtr pDestBmp = FilterFastDownscale(2).apply(pBmp); testEqual(*pDestBmp, "FastDownscaleResult", I8); } }; class FilterMaskTest: public GraphicsTest { public: FilterMaskTest() : GraphicsTest("FilterMaskTest", 2) { } void runTests() { runTestsWithBmp(initBmp(I8), "I8"); runTestsWithBmp(initBmp(B8G8R8), "B8G8R8"); runTestsWithBmp(initBmp(B8G8R8X8), "B8G8R8X8"); } private: void runTestsWithBmp(BitmapPtr pBmp, const string& sName) { BitmapPtr pMaskBmp = BitmapPtr(new Bitmap(pBmp->getSize(), I8)); FilterFill(0).applyInPlace(pMaskBmp); for (int y = 0; y < pBmp->getSize().y; y++) { pMaskBmp->setPixel(IntPoint(1, y), Pixel8(128)); pMaskBmp->setPixel(IntPoint(2, y), Pixel8(255)); pMaskBmp->setPixel(IntPoint(3, y), Pixel8(255)); } BitmapPtr pDestBmp = FilterMask(pMaskBmp).apply(pBmp); string sFName = string("baseline/MaskResult")+sName+".png"; // pDestBmp->save(sFName); sFName = getSrcDirName()+sFName; BitmapPtr pBaselineBmp = loadBitmap(sFName, pBmp->getPixelFormat()); TEST(*pDestBmp == *pBaselineBmp); } }; class FilterThresholdTest: public GraphicsTest { public: FilterThresholdTest() : GraphicsTest("FilterThresholdTest", 2) { } void runTests() { BitmapPtr pBmp(initBmp(I8)); BitmapPtr pDestBmp = FilterThreshold(1).apply(pBmp); string sFName = "baseline/ThresholdResult.png"; // pDestBmp->save(sFName); sFName = getSrcDirName()+sFName; BitmapPtr pBaselineBmp = loadBitmap(sFName, pBmp->getPixelFormat()); TEST(*pDestBmp == *pBaselineBmp); } }; class FilterFloodfillTest: public GraphicsTest { public: FilterFloodfillTest() : GraphicsTest("FilterFloodfillTest", 2) { } void runTests() { BitmapPtr pBmp = loadTestBmp("floodfill"); BitmapPtr pDestBmp = FilterFloodfill( ColorTester(Pixel32(255,255,255,255)), IntPoint(4,3)).apply(pBmp); testEqual(*pDestBmp, "FloodfillResult", B8G8R8A8, 0, 0); } }; class FilterDilationTest: public GraphicsTest { public: FilterDilationTest() : GraphicsTest("FilterDilationTest", 2) { } void runTests() { BitmapPtr pBmp = loadTestBmp("dilation", I8); BitmapPtr pDestBmp = FilterDilation().apply(pBmp); testEqual(*pDestBmp, "DilationResult", I8, 0, 0); } }; class FilterErosionTest: public GraphicsTest { public: FilterErosionTest() : GraphicsTest("FilterErosionTest", 2) { } void runTests() { BitmapPtr pBmp = loadTestBmp("erosion", I8); BitmapPtr pDestBmp = FilterErosion().apply(pBmp); testEqual(*pDestBmp, "ErosionResult", I8, 0, 0); } }; class FilterAlphaTest: public GraphicsTest { public: FilterAlphaTest() : GraphicsTest("FilterAlphaTest", 2) { } void runTests() { BitmapPtr pBmp = loadTestBmp("rgb24alpha-64x64", R8G8B8A8); BitmapPtr pAlphaBmp = FilterGetAlpha().apply(pBmp); testEqual(*pAlphaBmp, "GetAlphaResult", I8, 0, 0); BitmapPtr pDestBmp(new Bitmap(*pBmp)); pDestBmp->setAlpha(*pAlphaBmp); testEqual(*pDestBmp, *pBmp, "SetAlphaResult", 0, 0); } }; class FilterResizeBilinearTest: public GraphicsTest { public: FilterResizeBilinearTest() : GraphicsTest("FilterResizeBilinearTest", 2) { } void runTests() { BitmapPtr pBmp = loadTestBmp("rgb24alpha-64x64", B8G8R8A8); runTestWithBitmap(pBmp); pBmp = loadTestBmp("rgb24-64x64", B8G8R8X8); runTestWithBitmap(pBmp); pBmp = loadTestBmp("rgb24-65x65", B8G8R8); runTestWithBitmap(pBmp); } private: void runTestWithBitmap(BitmapPtr pBmp) { BitmapPtr pDestBmp = FilterResizeBilinear(IntPoint(32,32)).apply(pBmp); string sName = string("ResizeBilinearResult") +getPixelFormatString(pBmp->getPixelFormat()); testEqual(*pDestBmp, sName, pBmp->getPixelFormat()); } }; class FilterUnmultiplyAlphaTest: public GraphicsTest { public: FilterUnmultiplyAlphaTest() : GraphicsTest("FilterUnmultiplyAlphaTest", 2) { } void runTests() { BitmapPtr pBmp(new Bitmap(IntPoint(16, 1), B8G8R8A8)); for (int x = 0; x < 16; ++x) { unsigned char * pPixel = pBmp->getPixels()+x*4; unsigned char val = 17*x; *(pPixel+REDPOS) = val; *(pPixel+GREENPOS) = val; *(pPixel+BLUEPOS) = val; *(pPixel+ALPHAPOS) = val; } FilterUnmultiplyAlpha().applyInPlace(pBmp); QUIET_TEST(*(pBmp->getPixels()+ALPHAPOS) == 0); for (int x = 1; x < 16; ++x) { unsigned char * pPixel = pBmp->getPixels()+x*4; QUIET_TEST(*(pPixel+REDPOS) == 255); QUIET_TEST(*(pPixel+GREENPOS) == 255); QUIET_TEST(*(pPixel+BLUEPOS) == 255); QUIET_TEST(*(pPixel+ALPHAPOS) == 17*x); } } private: }; class GraphicsTestSuite: public TestSuite { public: GraphicsTestSuite() : TestSuite("GraphicsTestSuite") { addTest(TestPtr(new PixelTest)); addTest(TestPtr(new BitmapTest)); addTest(TestPtr(new Filter3x3Test)); addTest(TestPtr(new FilterConvolTest)); addTest(TestPtr(new FilterColorizeTest)); addTest(TestPtr(new FilterGrayscaleTest)); addTest(TestPtr(new FilterFillTest)); addTest(TestPtr(new FilterFlipTest)); addTest(TestPtr(new FilterFlipRGBTest)); addTest(TestPtr(new FilterFlipUVTest)); addTest(TestPtr(new FilterComboTest)); addTest(TestPtr(new HistoryPreProcessorTest)); addTest(TestPtr(new FilterHighpassTest)); addTest(TestPtr(new FilterGaussTest)); addTest(TestPtr(new FilterBlurTest)); addTest(TestPtr(new FilterBandpassTest)); addTest(TestPtr(new FilterFastBandpassTest)); addTest(TestPtr(new FilterFastDownscaleTest)); addTest(TestPtr(new FilterMaskTest)); addTest(TestPtr(new FilterThresholdTest)); addTest(TestPtr(new FilterFloodfillTest)); addTest(TestPtr(new FilterDilationTest)); addTest(TestPtr(new FilterErosionTest)); addTest(TestPtr(new FilterAlphaTest)); addTest(TestPtr(new FilterResizeBilinearTest)); addTest(TestPtr(new FilterUnmultiplyAlphaTest)); } }; int main(int nargs, char** args) { BitmapLoader::init(true); GraphicsTest::createResultImgDir(); GraphicsTestSuite suite; suite.runTests(); bool bOK = suite.isOk(); if (bOK) { return 0; } else { return 1; } }