// 40250 EterImageLib (CImage, CTGAImage, CDXTCImage), verbatim on the platform. #include "EterImageLib/StdAfx.h" #include "EterImageLib/TGAImage.h" #include "EterImageLib/DXTCImage.h" #include #include #include #include namespace { // "DDS " + a 124-byte DDSURFACEDESC2 (linear size, FourCC) + the blocks of one 4x4 level. std::vector MakeDDS(const char* fourcc, const std::vector& blocks) { std::vector dds(4 + 124, 0); memcpy(&dds[0], "DDS ", 4); DWORD* h = reinterpret_cast(&dds[4]); h[0] = 124; h[1] = 0x1 | 0x2 | 0x4 | 0x1000 | 0x80000; // CAPS|HEIGHT|WIDTH|PIXELFORMAT|LINEARSIZE h[2] = 4; h[3] = 4; h[4] = DWORD(blocks.size()); h[18] = 32; // ddpfPixelFormat.dwSize (offset 72) h[19] = 0x4; // DDPF_FOURCC memcpy(&h[20], fourcc, 4); dds.insert(dds.end(), blocks.begin(), blocks.end()); return dds; } } int main() { int failures = 0; auto check = [&failures](bool ok, const char *name) { if (!ok) { std::fprintf(stderr, "FAIL %s\n", name); ++failures; } }; // CImage: Clear, PutImage clips nothing, FlipTopToBottom swaps rows. { CImage a, b; a.Create(4, 2); a.Clear(0x11111111); b.Create(2, 1); b.Clear(0x22222222); a.PutImage(1, 1, &b); check(a.GetLinePointer(1)[1] == 0x22222222 && a.GetLinePointer(1)[3] == 0x11111111 && a.GetLinePointer(0)[1] == 0x11111111, "PutImage"); a.FlipTopToBottom(); check(a.GetLinePointer(0)[2] == 0x22222222 && a.GetLinePointer(1)[2] == 0x11111111, "FlipTopToBottom"); check(!a.IsEmpty() && a.GetWidth() == 4 && a.GetHeight() == 2, "CImage size"); } // CTGAImage: SaveToDiskFile writes the rows as stored with a bottom-left origin (desc 0x08), so loading // the file back flips it (the CTGAImage(CImage&) constructor pre-flips for that). RLE saving is not // exercised: 40250 never sets m_pdwEndPtr (no caller saves compressed; TargaResource only loads). { CTGAImage img; img.Create(5, 3); DWORD* p = img.GetBasePointer(); for (int i = 0; i < 15; ++i) p[i] = 0x80000000u + DWORD(i); char path[] = "/tmp/mt_tga_XXXXXX"; close(mkstemp(path)); check(img.SaveToDiskFile(path), "TGA SaveToDiskFile"); CTGAImage back; check(back.LoadFromDiskFile(path), "TGA LoadFromDiskFile"); bool flipped = back.GetWidth() == 5 && back.GetHeight() == 3; for (int y = 0; flipped && y < 3; ++y) for (int x = 0; x < 5; ++x) flipped = flipped && back.GetLinePointer(y)[x] == p[(2 - y) * 5 + x]; check(flipped, "TGA raw round trip is flipped"); check(back.GetHeader().width == 5 && back.GetHeader().colorBits == 32, "TGA header"); remove(path); } // RLE (type 10), 32-bit, top-left origin: a run packet then a raw packet, BGRA bytes. { std::vector tga(18, 0); tga[2] = 10; tga[12] = 5; tga[14] = 1; tga[16] = 32; tga[17] = 0x28; const BYTE body[] = {0x82, 1, 2, 3, 4, 0x01, 5, 6, 7, 8, 9, 10, 11, 12}; tga.insert(tga.end(), body, body + sizeof(body)); CTGAImage img; check(img.LoadFromMemory(int(tga.size()), tga.data()), "TGA RLE load"); DWORD* p = img.GetBasePointer(); check(p[0] == 0x04030201 && p[2] == 0x04030201 && p[3] == 0x08070605 && p[4] == 0x0C0B0A09, "TGA RLE pixels"); } // CDXTCImage DXT1: 565 endpoints shifted to 888 without replication, 4-colour mode thirds, rows LSB first. { std::vector block = {0x00, 0xF8, 0x1F, 0x00, 0xE4, 0x00, 0x00, 0x00}; std::vector dds = MakeDDS("DXT1", block); CDXTCImage image; check(image.LoadFromMemory(dds.data()), "DXT1 LoadFromMemory"); check(image.m_CompFormat == PF_DXT1 && image.m_nWidth == 4 && image.m_dwMipMapCount == 1, "DXT1 header"); DWORD px[16] = {}; image.Decompress(0, px); check(px[0] == 0xFFF80000 && px[1] == 0xFF0000F8 && px[2] == 0xFFA50052 && px[3] == 0xFF5200A5, "DXT1 row 0"); check(px[4] == 0xFFF80000 && px[15] == 0xFFF80000, "DXT1 index 0 rows"); } // CDXTCImage DXT5: alpha0/alpha1 with 3-bit indices, then the colour block. { std::vector block = {0x80, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00}; std::vector dds = MakeDDS("DXT5", block); CDXTCImage image; check(image.LoadFromMemory(dds.data()) && image.m_CompFormat == PF_DXT5, "DXT5 load"); DWORD px[16] = {}; image.Decompress(0, px); check(px[0] == 0x10F80000 && px[1] == 0x80F80000 && px[15] == 0x80F80000, "DXT5 alpha"); } // A format other than DXT1/3/5 is refused. { std::vector dds = MakeDDS("ATI2", std::vector(16, 0)); CDXTCImage image; check(!image.LoadFromMemory(dds.data()), "unknown FourCC refused"); } return failures ? 1 : 0; }