Skip to content

Instantly share code, notes, and snippets.

@tgfrerer
Created November 27, 2018 17:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tgfrerer/ba7903935da335a985f6311cef97e9f5 to your computer and use it in GitHub Desktop.
Save tgfrerer/ba7903935da335a985f6311cef97e9f5 to your computer and use it in GitHub Desktop.
Calculate miplevels for image input data
// 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