📄 test.cpp
字号:
// $image\test.cpp 1.5 milbo$ test image routines (not exhaustive)// Warning: this is raw research code -- expect it to be quite messy.//// TODO: add test of writing a bmp with and odd width//// milbo durban dec05#include <windows.h>#include <io.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <signal.h>#include <float.h>#include <math.h>#include <new.h>#include <direct.h>#include <sys/stat.h>#include <fstream.h>#include <iostream.h>#include <crtdbg.h>#include "mcommon.hpp"#include "mat.hpp"#include "matview.hpp"using namespace GslMat;#include "matvec.hpp"#include "mathutil.hpp"#include "image.hpp"#include "imutil.hpp"#include "imequalize.hpp"#include "rgbimutil.hpp"#include "imfile.hpp"#include "colors.hpp"#include "util.hpp"#include "err.hpp"#include "memstate.hpp"#define CONF_fCreateRefFiles 0 // 0 for normal testing, 1 to not do file compares (create ref files in out/)#define CONF_fDetailedErrors 0 // print detailed information when a check fails#define CONF_fAbortOnError 0 // 1 to enter debugger when any test fails#define CONF_AbortTestNbr -1 // -1 to not abort, else ngTests number to abort on#define CONF_nExpectedWarnings 3 // grep for "expect warning" below to see thesestatic bool fgVerbose = false;static int ngTests = 0; // number of testsstatic int ngFails = 0; // number of test failsstatic int ngWarnings = 0; // number of warnings//-----------------------------------------------------------------------------// Returns 0 if buffers matches roughly, 1 if no match//// Used for approximately matching images. The intent is to catch major problems// while still allowing us to compare images across format comversions.int ApproxMemCmp (const void *p1, const void *p2, size_t count){#define APPROX 5 // magic 5 is enough leeway for comparing converted jpeg file to bmpfor (size_t i = 0; i < count; i++) if (abs(((byte *)p1)[i] - ((byte *)p2)[i]) > APPROX) return 1; // buffers differentreturn 0; // buffers approximately the same}//-----------------------------------------------------------------------------static void DumpBytes (const byte *buf, int nLen){while (--nLen) lprintf("%2.2x ", *buf++);lprintf("\n");}static void DumpBytes (const tRGB *buf, int nLen){DumpBytes((byte *)buf, nLen);}static void DumpBytes (const LONG *buf, int nLen){DumpBytes((byte *)buf, nLen);}//-----------------------------------------------------------------------------// save images to compare directory so we can see how they differtemplate <typename T1, typename T2> // T1 and T2 are Image or RgbImageSaveImagesForComparism (const char sRefName[], T1 &Img, T2 &RefImg){char sDrive[_MAX_DRIVE], sDir[_MAX_DIR], sFname[_MAX_FNAME], sExt[_MAX_EXT], sPath[256];_splitpath(sRefName, sDrive, sDir, sFname, sExt);sprintf(sPath, "compare/%d_%s_OUT.bmp", ngTests, sFname); // we use ngTests so every filename is uniqueWriteBmp(Img, sPath, true);sprintf(sPath, "compare/%d_%s_REF.bmp", ngTests, sFname);WriteBmp(RefImg, sPath, true);}//-----------------------------------------------------------------------------template <typename T1, typename T2> // T1 and T2 are Image or RgbImagestatic void ErrHandler (const char sRefName[], T1 &Img, T2 &RefImg, int nLen){if (CONF_fDetailedErrors) { DumpBmpHeader(sRefName); lprintf("Img "); DumpBytes(Img.buf, nLen); lprintf("RefImg "); DumpBytes(RefImg.buf, nLen); }SaveImagesForComparism(sRefName, Img, RefImg);}//-----------------------------------------------------------------------------static void __cdecl TestFail (const char *pArgs, ...) // args like printf{ngFails++;va_list pArg;static char s[CONF_nMaxPrintfLen];va_start(pArg, pArgs);vsprintf(s, pArgs, pArg);va_end(pArg);printf("%s", s);fflush(stdout); // unneeded under Win98 but needed on epsilon under WinXPif (CONF_fAbortOnError) EnterDebugger;if (ngTests == CONF_AbortTestNbr) EnterDebugger;}//-----------------------------------------------------------------------------static void CompareImages (Image &Img, Image &RefImg, char sRefName[], int nLine){ngTests++;if (Img.width != RefImg.width || Img.height != RefImg.height) TestFail("Test %d FAIL: CompareImage sizes don't match GrayImage %dx%d GrayRefImage %s %dx%d\n", ngTests, Img.width, Img.height, sRefName, RefImg.width, RefImg.height);else if (0 != memcmp(Img.buf, RefImg.buf, Img.width * Img.height)) { if (0 == ApproxMemCmp(Img.buf, RefImg.buf, Img.width * Img.height)) { ngWarnings++; SaveImagesForComparism(sRefName, Img, RefImg); lprintf("Test %d line %d Warning: gray %s matches gray image only approximately\n", ngTests, nLine, sRefName); } else { ErrHandler(sRefName, Img, RefImg, Img.width * Img.height); TestFail("Test %d line %d FAIL: CompareImage contents don't match GrayImage %dx%d GrayRefImage %s %dx%d\n", ngTests, nLine, Img.width, Img.height, sRefName, RefImg.width, RefImg.height); } }}//-----------------------------------------------------------------------------static void CompareImages (RgbImage &Img, RgbImage &RefImg, char sRefName[], int nLine){ngTests++;if (Img.width != RefImg.width || Img.height != RefImg.height) TestFail("Test %d FAIL: CompareImage sizes don't match RgbImage %dx%d RefRgbImage %s %dx%d\n", ngTests, Img.width, Img.height, sRefName, RefImg.width, RefImg.height);else if (0 != memcmp(Img.buf, RefImg.buf, Img.width * Img.height * 3)) { if (0 == ApproxMemCmp(Img.buf, RefImg.buf, Img.width * Img.height)) { ngWarnings++; SaveImagesForComparism(sRefName, Img, RefImg); lprintf("Test %d line %d Warning: color %s matches color image only approximately\n", ngTests, nLine, sRefName); } else { ErrHandler(sRefName, Img, RefImg, 3 * Img.width * Img.height); TestFail("Test %d line %d FAIL: CompareImages contents don't match RgbImage %dx%d RefRgbImage %s %dx%d\n", ngTests, nLine, Img.width, Img.height, sRefName, RefImg.width, RefImg.height); } }}//-----------------------------------------------------------------------------static void CompareImages (Image &Img, RgbImage &RefImg, char sRefName[], int nLine){ngTests++;if (Img.width != RefImg.width || Img.height != RefImg.height) TestFail("Test %d line %d FAIL: CompareImage sizes don't match GrayImage %dx%d RefRgbImage %s %dx%d\n", ngTests, nLine, Img.width, Img.height, sRefName, RefImg.width, RefImg.height);else { Image TempImg; ConvertRgbImageToGray(TempImg, RefImg); if (0 != memcmp(Img.buf, TempImg.buf, Img.width * Img.height)) { if (0 == ApproxMemCmp(Img.buf, RefImg.buf, Img.width * Img.height)) { ngWarnings++; SaveImagesForComparism(sRefName, Img, RefImg); lprintf("Test %d Warning: color %s matches gray image only approximately\n", ngTests, sRefName); } else { ErrHandler(sRefName, Img, RefImg, Img.width * Img.height); TestFail("Test %d line %d FAIL: CompareImage contents don't match GrayImage %dx%d RefRgbImage %s %dx%d\n", ngTests, nLine, Img.width, Img.height, sRefName, RefImg.width, RefImg.height); } } }}//-----------------------------------------------------------------------------static void CompareImageToFile (Image &Img, char sFile[], int nLine){Image FileImg;if (!CONF_fCreateRefFiles) { sLoadImage(FileImg, sFile, fgVerbose); CompareImages(Img, FileImg, sFile, nLine); }}//-----------------------------------------------------------------------------static void CompareImageToFile (RgbImage &Img, char sFile[], int nLine){RgbImage FileImg;if (!CONF_fCreateRefFiles) { sLoadImage(FileImg, sFile, fgVerbose); CompareImages(Img, FileImg, sFile, nLine); }}//-----------------------------------------------------------------------------static void LoadTestImage(Image &Img){sLoadImage(Img, "ref/imtest.bmp", fgVerbose);}//-----------------------------------------------------------------------------static void LoadTestImage(RgbImage &Img){sLoadImage(Img, "ref/imtest.bmp", fgVerbose);}//-----------------------------------------------------------------------------// Write the image to a file, and compare it to its reference filestatic void Compare (Image &Img, char sFile[], int nLine){if (fgVerbose) lprintf("Checking %s\n", sFile);char sPath[128];sprintf(sPath, "out/%s", sFile);WriteBmp(Img, sPath, fgVerbose);sprintf(sPath, "ref/%s", sFile);CompareImageToFile(Img, sPath, nLine);}//-----------------------------------------------------------------------------static void Compare (RgbImage &Img, char sFile[], int nLine){if (fgVerbose) lprintf("Checking %s\n", sFile);char sPath[128];sprintf(sPath, "out/%s", sFile);WriteBmp(Img, sPath, fgVerbose);sprintf(sPath, "ref/%s", sFile);CompareImageToFile(Img, sPath, nLine);}//-----------------------------------------------------------------------------int __cdecl main (void){InitMallocDebug();// Expect the following warnings:// Warning: gray ref/imtest.bmp matches gray image only approximately// Warning: gray ref/imtest1.bmp matches gray image only approximately// Warning: color ref/imtest.bmp matches color image only approximatelylprintf("Expect %d warnings\n", CONF_nExpectedWarnings);Image Img;ASSERT(Img.width == 0 && Img.height == 0);RgbImage RgbImg;ASSERT(RgbImg.width == 0 && RgbImg.height == 0);// basic operations and file io: ImageImage Img1("ref/imtest.bmp", fgVerbose);CompareImageToFile(Img1, "ref/imtest.bmp", __LINE__);Image Img2(Img1); // test constructors and = and == and !=CompareImages(Img2, Img1, "image", __LINE__);Image Img3 = Img1; // copy constructorCompareImages(Img3, Img1, "image", __LINE__);ASSERT(Img1 == Img2);Img1(2,3) ^= 1;ASSERT(Img1 != Img2);Img3 = Img1; // assignmentASSERT(Img3 == Img1);int width, height;GetImageSize(width, height, "ref/imtest.bmp");ASSERT(width == 40 && height == 26);sLoadImage(Img, "ref/imtest.bmp", fgVerbose);ASSERT(Img.width == 40 && Img.height == 26);WriteBmp(Img, "out/0.bmp", fgVerbose);CompareImageToFile(Img, "out/0.bmp", __LINE__);CompareImageToFile(Img, "ref/imtest.bmp", __LINE__);sLoadImageGivenDirs(Img, "noSuchDirectory1;noSuchDirectory2;ref", "imtest.bmp", fgVerbose);ASSERT(Img.width == 40 && Img.height == 26);CompareImageToFile(Img, "ref/imtest.bmp", __LINE__);sLoadImage(Img, "ref/imtest.bmp", fgVerbose);ConvertGrayImageToRgb(RgbImg, Img);WriteBmp(RgbImg, "out/1.bmp", fgVerbose);CompareImageToFile(Img, "out/1.bmp", __LINE__);CompareImageToFile(Img, "ref/imtest.bmp", __LINE__);sLoadImage(Img, "ref/imtest1.jpg", fgVerbose);ASSERT(Img.width == 40 && Img.height == 26);WriteBmp(Img, "out/2.bmp", fgVerbose);CompareImageToFile(Img, "out/2.bmp", __LINE__);// don't expect JPEG image to match file exactly, so expect warning on next testCompareImageToFile(Img, "ref/imtest.bmp", __LINE__);// TODO slight differences found here (because of color conversion) cause unexpected warning, need to reexamine some timeCompareImageToFile(Img, "ref/imtest1.bmp", __LINE__); // imtest1.bmp is a bmp file created from the imtest1.jpgsLoadImage(Img, "ref/imtest2.pgm", fgVerbose);ASSERT(Img.width == 40 && Img.height == 26);WriteBmp(Img, "out/3.bmp", fgVerbose);CompareImageToFile(Img, "out/3.bmp", __LINE__);CompareImageToFile(Img, "ref/imtest2.bmp", __LINE__); // imtest2.bmp is a bmp file created from the imtest1.pgmCompareImageToFile(Img, "ref/imtest1.bmp", __LINE__);sLoadImage(Img, "ref/imtest3.ppm", fgVerbose);ASSERT(Img.width == 40 && Img.height == 26);WriteBmp(Img, "out/4.bmp", fgVerbose);CompareImageToFile(Img, "out/4.bmp", __LINE__);CompareImageToFile(Img, "ref/imtest.bmp", __LINE__);// basic operations and file io: RgbImageRgbImage RgbImg1("ref/imtest.bmp", fgVerbose); // test constructorsCompareImageToFile(RgbImg1, "ref/imtest.bmp", __LINE__);RgbImage RgbImg2 = RgbImg1;CompareImageToFile(RgbImg2, "ref/imtest.bmp", __LINE__);ASSERT(RgbImg1 == RgbImg2); // test == and !=RgbImg1(0,0).Red = 99;ASSERT(RgbImg1 != RgbImg2);sLoadImage(Img, "ref/imtest.bmp", fgVerbose); // test init of a color image with a gray imageRgbImage RgbImg3(Img); // gray to colorConvertRgbImageToGray(Img, RgbImg3); // color back to grayCompareImageToFile(Img, "ref/imtest.bmp", __LINE__);Img(0,0) ^= 1;Img = RgbImg3; // type conversionCompareImageToFile(Img, "ref/imtest.bmp", __LINE__);sLoadImage(RgbImg, "ref/imtest.bmp", fgVerbose);ASSERT(Img.width == 40 && Img.height == 26);WriteBmp(RgbImg, "out/5.bmp", fgVerbose);CompareImageToFile(RgbImg, "out/5.bmp", __LINE__);CompareImageToFile(RgbImg, "ref/imtest.bmp", __LINE__);sLoadImageGivenDirs(RgbImg, "noSuchDirectory1;ref;noSuchDirectory2;", "imtest.bmp", fgVerbose);ASSERT(Img.width == 40 && Img.height == 26);CompareImageToFile(RgbImg, "ref/imtest.bmp", __LINE__);sLoadImage(RgbImg, "ref/imtest1.jpg", fgVerbose);ASSERT(RgbImg.width == 40 && RgbImg.height == 26);WriteBmp(RgbImg, "out/6.bmp", fgVerbose);CompareImageToFile(RgbImg, "out/6.bmp", __LINE__);CompareImageToFile(Img, "ref/imtest1.bmp", __LINE__); // imtest1.bmp is a bmp file created from the imtest1.jpg// don't expect JPEG image to match file exactly, so expect warning on next testCompareImageToFile(RgbImg, "ref/imtest.bmp", __LINE__);sLoadImage(RgbImg, "ref/imtest2.pgm", fgVerbose);ASSERT(RgbImg.width == 40 && RgbImg.height == 26);WriteBmp(RgbImg, "out/7.bmp", fgVerbose);CompareImageToFile(RgbImg, "out/7.bmp", __LINE__);CompareImageToFile(Img, "ref/imtest2.bmp", __LINE__); // imtest2.bmp is a bmp file created from the imtest1.pgmCompareImageToFile(RgbImg, "ref/imtest2.bmp", __LINE__);sLoadImage(RgbImg, "ref/imtest3.ppm", fgVerbose);ASSERT(RgbImg.width == 40 && RgbImg.height == 26);WriteBmp(RgbImg, "out/8.bmp", fgVerbose);CompareImageToFile(RgbImg, "ref/imtest.bmp", __LINE__);CompareImageToFile(RgbImg, "out/8.bmp", __LINE__);// basic test of free()Img.free();ASSERT(Img.width == 0 && Img.height == 0);RgbImg.free();ASSERT(RgbImg.width == 0 && RgbImg.height == 0);// MoveImage: ImageLoadTestImage(Img);MoveImage(Img, 0, 0, false, IM_CLIP);Compare(Img, "mv0_0.bmp", __LINE__);LoadTestImage(Img);MoveImage(Img, 0, 0, false, IM_EXTEND);Compare(Img, "mv0_0e.bmp", __LINE__);LoadTestImage(Img);MoveImage(Img, 18, 0, false, IM_CLIP);Compare(Img, "mv18_0.bmp", __LINE__);LoadTestImage(Img);MoveImage(Img, 18, 0, false, IM_EXTEND);Compare(Img, "mv18_0e.bmp", __LINE__);LoadTestImage(Img);MoveImage(Img, -9, 0, false, IM_CLIP);Compare(Img, "mv-90_0.bmp", __LINE__);LoadTestImage(Img);MoveImage(Img, -9, 0, false, IM_EXTEND);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -