Created
November 27, 2018 17:09
-
-
Save tgfrerer/ba7903935da335a985f6311cef97e9f5 to your computer and use it in GitHub Desktop.
Calculate miplevels for image input data
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Generate mipmap from input data | |
// adapted from https://github.com/ValveSoftware/openvr/blob/1fb1030f2ac238456dca7615a4408fb2bb42afb6/samples/hellovr_vulkan/hellovr_vulkan_main.cpp#L2271 | |
template <typename PixelType, const size_t numChannels> | |
static void generate_mipmap( const PixelType *pSrc, PixelType *pDst, uint32_t const nSrcWidth, uint32_t const nSrcHeight, uint32_t *pDstWidthOut, uint32_t *pDstHeightOut ) { | |
*pDstWidthOut = nSrcWidth / 2; | |
if ( *pDstWidthOut <= 0 ) { | |
*pDstWidthOut = 1; | |
} | |
*pDstHeightOut = nSrcHeight / 2; | |
if ( *pDstHeightOut <= 0 ) { | |
*pDstHeightOut = 1; | |
} | |
for ( uint32_t y = 0; y != *pDstHeightOut; y++ ) { | |
for ( uint32_t x = 0; x != *pDstWidthOut; x++ ) { | |
// We use floats to accumulate pixel values. | |
// | |
// TODO: if pixels arrive in non-linear SRGB format, we must convert them to linear when | |
// we read them, and convert them back to non-linear when we write them back after averaging. | |
// | |
float channel[ numChannels ]{}; | |
uint32_t nSrcIndex[ 4 ]; // we reduce 4 neighbouring pixels to 1 | |
// Get pixel indices | |
nSrcIndex[ 0 ] = ( ( ( y * 2 ) * nSrcWidth ) + ( x * 2 ) ) * 4; | |
nSrcIndex[ 1 ] = ( ( ( y * 2 ) * nSrcWidth ) + ( x * 2 + 1 ) ) * 4; | |
nSrcIndex[ 2 ] = ( ( ( ( y * 2 ) + 1 ) * nSrcWidth ) + ( x * 2 ) ) * 4; | |
nSrcIndex[ 3 ] = ( ( ( ( y * 2 ) + 1 ) * nSrcWidth ) + ( x * 2 + 1 ) ) * 4; | |
// Sum all pixels | |
for ( uint32_t nSample = 0; nSample != 4; nSample++ ) { | |
for ( uint32_t c = 0; c != numChannels; c++ ) { | |
channel[ c ] += pSrc[ nSrcIndex[ nSample ] + c ]; | |
} | |
} | |
// Average results | |
for ( uint32_t c = 0; c != numChannels; c++ ) { | |
channel[ c ] /= 4.f; | |
} | |
// Store resulting pixels | |
for ( uint32_t c = 0; c != numChannels; c++ ) { | |
pDst[ ( y * ( *pDstWidthOut ) + x ) * numChannels + c ] = static_cast<PixelType>( channel[ c ] ); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment