Introduce mipgen frontend. (#120)
* Introduce mipgen frontend. For now this is fairly simple although it does let you choose a filter. Another cool feature is that an HTML file is generated which makes it easy to review the generated miplevels. This does not expose the Boundary enum to users because it has not yet been implemented in the core Image library. * Fix up mipgen per code review.
This commit is contained in:
@@ -19,9 +19,11 @@
|
||||
|
||||
#include <math/vec3.h>
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/CString.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
using namespace image;
|
||||
|
||||
@@ -320,4 +322,48 @@ void computeSingleSample(const LinearImage& source, float x, float y, SingleSamp
|
||||
}
|
||||
}
|
||||
|
||||
// Unlike traditional mipmap generation, our implementation generates all levels from the original
|
||||
// image, under the premise that this produces a higher quality result.
|
||||
void generateMipmaps(const LinearImage& source, Filter filter, LinearImage* result, uint32_t mips) {
|
||||
mips = std::min(mips, getMipmapCount(source));
|
||||
uint32_t width = source.getWidth();
|
||||
uint32_t height = source.getHeight();
|
||||
for (uint32_t n = 0; n < mips; ++n) {
|
||||
width = std::max(width >> 1, 1u);
|
||||
height = std::max(height >> 1, 1u);
|
||||
result[n] = resampleImage(source, width, height, filter);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t getMipmapCount(const LinearImage& source) {
|
||||
uint32_t width = source.getWidth();
|
||||
uint32_t height = source.getHeight();
|
||||
uint32_t count = 0;
|
||||
while (width > 1 || height > 1) {
|
||||
++count;
|
||||
width = std::max(width >> 1, 1u);
|
||||
height = std::max(height >> 1, 1u);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
Filter filterFromString(const char* rawname) {
|
||||
using namespace utils;
|
||||
using namespace std;
|
||||
static const unordered_map<StaticString, Filter> map = {
|
||||
{ "BOX", Filter::BOX},
|
||||
{ "NEAREST", Filter::NEAREST},
|
||||
{ "HERMITE", Filter::HERMITE},
|
||||
{ "GAUSSIAN", Filter::GAUSSIAN_SCALARS},
|
||||
{ "NORMALS", Filter::GAUSSIAN_NORMALS},
|
||||
{ "MITCHELL", Filter::MITCHELL},
|
||||
{ "LANCZOS", Filter::LANCZOS},
|
||||
{ "MINIMUM", Filter::MINIMUM},
|
||||
};
|
||||
string name = rawname;
|
||||
for (auto& c: name) c = toupper((unsigned char) c);
|
||||
auto iter = map.find({ name.c_str(), name.size() });
|
||||
return iter == map.end() ? Filter::DEFAULT : iter->second;
|
||||
}
|
||||
|
||||
} // namespace image
|
||||
|
||||
Reference in New Issue
Block a user