bool LegacyExpandScanline()

in DirectXTex/DirectXTexDDS.cpp [921:1224]


        bool LegacyExpandScanline(
            _Out_writes_bytes_(outSize) void* pDestination,
            size_t outSize,
            _In_ DXGI_FORMAT outFormat,
            _In_reads_bytes_(inSize) const void* pSource,
            size_t inSize,
            _In_ TEXP_LEGACY_FORMAT inFormat,
            _In_reads_opt_(256) const uint32_t* pal8,
            _In_ uint32_t tflags) noexcept
    {
        assert(pDestination && outSize > 0);
        assert(pSource && inSize > 0);
        assert(IsValid(outFormat) && !IsPlanar(outFormat) && !IsPalettized(outFormat));

        switch (inFormat)
        {
        case TEXP_LEGACY_R8G8B8:
            if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
                return false;

            // D3DFMT_R8G8B8 -> DXGI_FORMAT_R8G8B8A8_UNORM
            if (inSize >= 3 && outSize >= 4)
            {
                const uint8_t * __restrict sPtr = static_cast<const uint8_t*>(pSource);
                uint32_t * __restrict dPtr = static_cast<uint32_t*>(pDestination);

                for (size_t ocount = 0, icount = 0; ((icount < (inSize - 2)) && (ocount < (outSize - 3))); icount += 3, ocount += 4)
                {
                    // 24bpp Direct3D 9 files are actually BGR, so need to swizzle as well
                    uint32_t t1 = uint32_t(*(sPtr) << 16);
                    uint32_t t2 = uint32_t(*(sPtr + 1) << 8);
                    uint32_t t3 = uint32_t(*(sPtr + 2));

                    *(dPtr++) = t1 | t2 | t3 | 0xff000000;
                    sPtr += 3;
                }
                return true;
            }
            return false;

        case TEXP_LEGACY_R3G3B2:
            switch (outFormat)
            {
            case DXGI_FORMAT_R8G8B8A8_UNORM:
                // D3DFMT_R3G3B2 -> DXGI_FORMAT_R8G8B8A8_UNORM
                if (inSize >= 1 && outSize >= 4)
                {
                    const uint8_t* __restrict sPtr = static_cast<const uint8_t*>(pSource);
                    uint32_t * __restrict dPtr = static_cast<uint32_t*>(pDestination);

                    for (size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 3))); ++icount, ocount += 4)
                    {
                        uint8_t t = *(sPtr++);

                        uint32_t t1 = uint32_t((t & 0xe0) | ((t & 0xe0) >> 3) | ((t & 0xc0) >> 6));
                        uint32_t t2 = uint32_t(((t & 0x1c) << 11) | ((t & 0x1c) << 8) | ((t & 0x18) << 5));
                        uint32_t t3 = uint32_t(((t & 0x03) << 22) | ((t & 0x03) << 20) | ((t & 0x03) << 18) | ((t & 0x03) << 16));

                        *(dPtr++) = t1 | t2 | t3 | 0xff000000;
                    }
                    return true;
                }
                return false;

            case DXGI_FORMAT_B5G6R5_UNORM:
                // D3DFMT_R3G3B2 -> DXGI_FORMAT_B5G6R5_UNORM
                if (inSize >= 1 && outSize >= 2)
                {
                    const uint8_t* __restrict sPtr = static_cast<const uint8_t*>(pSource);
                    uint16_t * __restrict dPtr = static_cast<uint16_t*>(pDestination);

                    for (size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 1))); ++icount, ocount += 2)
                    {
                        unsigned t = *(sPtr++);

                        unsigned t1 = ((t & 0xe0u) << 8) | ((t & 0xc0u) << 5);
                        unsigned t2 = ((t & 0x1cu) << 6) | ((t & 0x1cu) << 3);
                        unsigned t3 = ((t & 0x03u) << 3) | ((t & 0x03u) << 1) | ((t & 0x02) >> 1);

                        *(dPtr++) = static_cast<uint16_t>(t1 | t2 | t3);
                    }
                    return true;
                }
                return false;

            default:
                return false;
            }

        case TEXP_LEGACY_A8R3G3B2:
            if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
                return false;

            // D3DFMT_A8R3G3B2 -> DXGI_FORMAT_R8G8B8A8_UNORM
            if (inSize >= 2 && outSize >= 4)
            {
                const uint16_t* __restrict sPtr = static_cast<const uint16_t*>(pSource);
                uint32_t * __restrict dPtr = static_cast<uint32_t*>(pDestination);

                for (size_t ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4)
                {
                    uint16_t t = *(sPtr++);

                    uint32_t t1 = uint32_t((t & 0x00e0) | ((t & 0x00e0) >> 3) | ((t & 0x00c0) >> 6));
                    uint32_t t2 = uint32_t(((t & 0x001c) << 11) | ((t & 0x001c) << 8) | ((t & 0x0018) << 5));
                    uint32_t t3 = uint32_t(((t & 0x0003) << 22) | ((t & 0x0003) << 20) | ((t & 0x0003) << 18) | ((t & 0x0003) << 16));
                    uint32_t ta = (tflags & TEXP_SCANLINE_SETALPHA) ? 0xff000000 : uint32_t((t & 0xff00) << 16);

                    *(dPtr++) = t1 | t2 | t3 | ta;
                }
                return true;
            }
            return false;

        case TEXP_LEGACY_P8:
            if ((outFormat != DXGI_FORMAT_R8G8B8A8_UNORM) || !pal8)
                return false;

            // D3DFMT_P8 -> DXGI_FORMAT_R8G8B8A8_UNORM
            if (inSize >= 1 && outSize >= 4)
            {
                const uint8_t* __restrict sPtr = static_cast<const uint8_t*>(pSource);
                uint32_t * __restrict dPtr = static_cast<uint32_t*>(pDestination);

                for (size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 3))); ++icount, ocount += 4)
                {
                    uint8_t t = *(sPtr++);

                    *(dPtr++) = pal8[t];
                }
                return true;
            }
            return false;

        case TEXP_LEGACY_A8P8:
            if ((outFormat != DXGI_FORMAT_R8G8B8A8_UNORM) || !pal8)
                return false;

            // D3DFMT_A8P8 -> DXGI_FORMAT_R8G8B8A8_UNORM
            if (inSize >= 2 && outSize >= 4)
            {
                const uint16_t* __restrict sPtr = static_cast<const uint16_t*>(pSource);
                uint32_t * __restrict dPtr = static_cast<uint32_t*>(pDestination);

                for (size_t ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4)
                {
                    uint16_t t = *(sPtr++);

                    uint32_t t1 = pal8[t & 0xff];
                    uint32_t ta = (tflags & TEXP_SCANLINE_SETALPHA) ? 0xff000000 : uint32_t((t & 0xff00) << 16);

                    *(dPtr++) = t1 | ta;
                }
                return true;
            }
            return false;

        case TEXP_LEGACY_A4L4:
            switch (outFormat)
            {
            case DXGI_FORMAT_B4G4R4A4_UNORM:
                // D3DFMT_A4L4 -> DXGI_FORMAT_B4G4R4A4_UNORM
                if (inSize >= 1 && outSize >= 2)
                {
                    const uint8_t * __restrict sPtr = static_cast<const uint8_t*>(pSource);
                    uint16_t * __restrict dPtr = static_cast<uint16_t*>(pDestination);

                    for (size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 1))); ++icount, ocount += 2)
                    {
                        unsigned t = *(sPtr++);

                        unsigned t1 = (t & 0x0fu);
                        unsigned ta = (tflags & TEXP_SCANLINE_SETALPHA) ? 0xf000u : ((t & 0xf0u) << 8);

                        *(dPtr++) = static_cast<uint16_t>(t1 | (t1 << 4) | (t1 << 8) | ta);
                    }
                    return true;
                }
                return false;

            case DXGI_FORMAT_R8G8B8A8_UNORM:
                // D3DFMT_A4L4 -> DXGI_FORMAT_R8G8B8A8_UNORM
                if (inSize >= 1 && outSize >= 4)
                {
                    const uint8_t * __restrict sPtr = static_cast<const uint8_t*>(pSource);
                    uint32_t * __restrict dPtr = static_cast<uint32_t*>(pDestination);

                    for (size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 3))); ++icount, ocount += 4)
                    {
                        uint8_t t = *(sPtr++);

                        uint32_t t1 = uint32_t(((t & 0x0f) << 4) | (t & 0x0f));
                        uint32_t ta = (tflags & TEXP_SCANLINE_SETALPHA) ? 0xff000000 : uint32_t(((t & 0xf0) << 24) | ((t & 0xf0) << 20));

                        *(dPtr++) = t1 | (t1 << 8) | (t1 << 16) | ta;
                    }
                    return true;
                }
                return false;

            default:
                return false;
            }

        case TEXP_LEGACY_B4G4R4A4:
            if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
                return false;

            // D3DFMT_A4R4G4B4 -> DXGI_FORMAT_R8G8B8A8_UNORM
            if (inSize >= 2 && outSize >= 4)
            {
                const uint16_t * __restrict sPtr = static_cast<const uint16_t*>(pSource);
                uint32_t * __restrict dPtr = static_cast<uint32_t*>(pDestination);

                for (size_t ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4)
                {
                    uint32_t t = *(sPtr++);

                    uint32_t t1 = uint32_t((t & 0x0f00) >> 4) | ((t & 0x0f00) >> 8);
                    uint32_t t2 = uint32_t((t & 0x00f0) << 8) | ((t & 0x00f0) << 4);
                    uint32_t t3 = uint32_t((t & 0x000f) << 20) | ((t & 0x000f) << 16);
                    uint32_t ta = uint32_t((tflags & TEXP_SCANLINE_SETALPHA) ? 0xff000000 : (((t & 0xf000) << 16) | ((t & 0xf000) << 12)));

                    *(dPtr++) = t1 | t2 | t3 | ta;
                }
                return true;
            }
            return false;

        case TEXP_LEGACY_L8:
            if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
                return false;

            // D3DFMT_L8 -> DXGI_FORMAT_R8G8B8A8_UNORM
            if (inSize >= 1 && outSize >= 4)
            {
                const uint8_t * __restrict sPtr = static_cast<const uint8_t*>(pSource);
                uint32_t * __restrict dPtr = static_cast<uint32_t*>(pDestination);

                for (size_t ocount = 0, icount = 0; ((icount < inSize) && (ocount < (outSize - 3))); ++icount, ocount += 4)
                {
                    uint32_t t1 = *(sPtr++);
                    uint32_t t2 = (t1 << 8);
                    uint32_t t3 = (t1 << 16);

                    *(dPtr++) = t1 | t2 | t3 | 0xff000000;
                }
                return true;
            }
            return false;

        case TEXP_LEGACY_L16:
            if (outFormat != DXGI_FORMAT_R16G16B16A16_UNORM)
                return false;

            // D3DFMT_L16 -> DXGI_FORMAT_R16G16B16A16_UNORM
            if (inSize >= 2 && outSize >= 8)
            {
                const uint16_t* __restrict sPtr = static_cast<const uint16_t*>(pSource);
                uint64_t * __restrict dPtr = static_cast<uint64_t*>(pDestination);

                for (size_t ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 7))); icount += 2, ocount += 8)
                {
                    uint16_t t = *(sPtr++);

                    uint64_t t1 = t;
                    uint64_t t2 = (t1 << 16);
                    uint64_t t3 = (t1 << 32);

                    *(dPtr++) = t1 | t2 | t3 | 0xffff000000000000;
                }
                return true;
            }
            return false;

        case TEXP_LEGACY_A8L8:
            if (outFormat != DXGI_FORMAT_R8G8B8A8_UNORM)
                return false;

            // D3DFMT_A8L8 -> DXGI_FORMAT_R8G8B8A8_UNORM
            if (inSize >= 2 && outSize >= 4)
            {
                const uint16_t* __restrict sPtr = static_cast<const uint16_t*>(pSource);
                uint32_t * __restrict dPtr = static_cast<uint32_t*>(pDestination);

                for (size_t ocount = 0, icount = 0; ((icount < (inSize - 1)) && (ocount < (outSize - 3))); icount += 2, ocount += 4)
                {
                    uint16_t t = *(sPtr++);

                    uint32_t t1 = uint32_t(t & 0xff);
                    uint32_t t2 = uint32_t(t1 << 8);
                    uint32_t t3 = uint32_t(t1 << 16);
                    uint32_t ta = (tflags & TEXP_SCANLINE_SETALPHA) ? 0xff000000 : uint32_t((t & 0xff00) << 16);

                    *(dPtr++) = t1 | t2 | t3 | ta;
                }
                return true;
            }
            return false;

        default:
            return false;
        }
    }