#202 FI 3.15.1 - FreeImageLib - PluginDDS - no page access

open
nobody
None
5
2012-10-31
2012-02-23
Alexandre TROG
No

Short explanation :
The plugin does not implement a proper DDS page access.

Detailed explanation :
For page access to work, it misses 2 things :
* a function implementing the pagecount_proc (and its affectation within InitDDS( xxx ) , all located in PluginDDS.cpp )
* a block of code ( in Load( xxx ), also located in PluginDDS.cpp ) to offset the memory loading at the selected page start

Proposed solution :
Use the given code

{{{
//--------------------------------------------------------------------------------------------------------
// 1. add page count feature

static int DLL_CALLCONV
PageCount(FreeImageIO io, fi_handle handle, void data) {
if( data == NULL ) {
return 0;
}

DDSHEADER header;
memset(&header, 0, sizeof(header));
io->read_proc(&header, 1, sizeof(header), handle);

int iPageCount = ( 0 != ( header.surfaceDesc.ddsCaps.dwCaps2 & DDSCAPS2_CUBEMAP ) ) ? 6 : 1;

return iPageCount;

}

// within the InitDDS( xxx ) function
{
// ... truncated for easier reading
plugin->pagecount_proc = PageCount; //NULL; // PATCH
// ... truncated for easier reading
}

//--------------------------------------------------------------------------------------------------------
// 2. add page jump feature

// calculates size of uncompressed RGB texture in bytes
static int CalculateSizeRGB( unsigned int width, unsigned int height, DDSURFACEDESC2 &desc )
{
return height * ( (desc.dwFlags & DDSD_PITCH) ?
(int)desc.dwPitchOrLinearSize : CalculateLine( width, (int)desc.ddpfPixelFormat.dwRGBBitCount ) );
}

// calculates size of DXTC texture in bytes
static int CalculateSizeDXTC( unsigned int width, unsigned int height, DDSURFACEDESC2 &desc )
{
return ((width+3)/4)((height+3)/4)
( FOURCC_DXT1 == desc.ddpfPixelFormat.dwFourCC ? 8 : 16);
}

// within the Load( xxx ) function
{
// ... truncated for easier reading

memset(&header, 0, sizeof(header));
io->read_proc(&header, 1, sizeof(header), handle);

ifdef FREEIMAGE_BIGENDIAN

SwapHeader(&header);

endif

// PATCH START ----------------------------------------
// set at the right position for the given page

int iOffset = 0;

int width   = (int)header.surfaceDesc.dwWidth & ~3;
int height  = (int)header.surfaceDesc.dwHeight & ~3;

int iMipLevels  = ( 0 != header.surfaceDesc.dwMipMapCount ) ? header.surfaceDesc.dwMipMapCount : 1;

for( int iPage = 0; iPage < page; iPage++)
{   
    int iMipHeight  = height;
    int iMipWidth   = width;

    for( int iMip = 0; iMip < iMipLevels; iMip++)
    {
        int iMipSize = (header.surfaceDesc.ddpfPixelFormat.dwFlags & DDPF_RGB) ? 
            CalculateSizeRGB( iMipWidth, iMipHeight, header.surfaceDesc ) : CalculateSizeDXTC( iMipWidth, iMipHeight, header.surfaceDesc );

        iOffset += iMipSize;

        iMipHeight  = iMipHeight >> 1;
        iMipWidth   = iMipWidth >> 1;
    }
}
io->seek_proc (handle, iOffset, SEEK_CUR);

// PATCH STOP ----------------------------------------

if (header.surfaceDesc.ddpfPixelFormat.dwFlags & DDPF_RGB)

// ... truncated for easier reading}
}
}}}

Discussion