BMP loading support, material parameter naming more uniform
parent
d4181b01fd
commit
d4ae5660cf
|
@ -40,9 +40,30 @@ public:
|
|||
props.getSpectrum("diffuseReflectance", Spectrum(0.0f)));
|
||||
m_specularReflectance = new ConstantTexture(
|
||||
props.getSpectrum("specularReflectance", Spectrum(1.0f)));
|
||||
|
||||
m_kd = props.getFloat("diffuseAmount", 1.0f);
|
||||
m_ks = props.getFloat("specularAmount", 1.0f);
|
||||
|
||||
bool verifyEnergyConservation = props.getBoolean("verifyEnergyConservation", true);
|
||||
|
||||
if (verifyEnergyConservation && (m_kd * m_diffuseReflectance->getMaximum().max()
|
||||
+ m_ks * m_specularReflectance->getMaximum().max() > 1.0f)) {
|
||||
Log(EWarn, "%s: Energy conservation is potentially violated!", props.getID().c_str());
|
||||
Log(EWarn, "Max. diffuse reflectance = %f * %f = %f", m_kd, m_diffuseReflectance->getMaximum().max(), m_kd*m_diffuseReflectance->getMaximum().max());
|
||||
Log(EWarn, "Max. specular reflectance = %f * %f = %f", m_ks, m_specularReflectance->getMaximum().max(), m_ks*m_specularReflectance->getMaximum().max());
|
||||
Float normalization = 1/(m_kd * m_diffuseReflectance->getMaximum().max() + m_ks * m_specularReflectance->getMaximum().max());
|
||||
Log(EWarn, "Reducing the albedo to %.1f%% of the original value to be on the safe side. "
|
||||
"Specify verifyEnergyConservation=false to prevent this.", normalization * 100);
|
||||
m_kd *= normalization; m_ks *= normalization;
|
||||
}
|
||||
|
||||
Float avgDiffReflectance = m_diffuseReflectance->getAverage().average() * m_kd;
|
||||
Float avgSpecularReflectance = m_specularReflectance->getAverage().average() * m_ks;
|
||||
|
||||
m_specularSamplingWeight = props.getFloat("specularSamplingWeight",
|
||||
std::max((Float) 0.3, 1-2*m_diffuseReflectance->getAverage().average()));
|
||||
avgSpecularReflectance / (avgDiffReflectance + avgSpecularReflectance));
|
||||
m_diffuseSamplingWeight = 1.0f - m_specularSamplingWeight;
|
||||
|
||||
m_alphaB = props.getFloat("alphaB", .1f);
|
||||
m_intIOR = props.getFloat("intIOR", 1.5f);
|
||||
m_extIOR = props.getFloat("extIOR", 1.0f);
|
||||
|
@ -62,6 +83,8 @@ public:
|
|||
m_diffuseReflectance = static_cast<Texture *>(manager->getInstance(stream));
|
||||
m_specularReflectance = static_cast<Texture *>(manager->getInstance(stream));
|
||||
m_alphaB = stream->readFloat();
|
||||
m_kd = stream->readFloat();
|
||||
m_ks = stream->readFloat();
|
||||
m_intIOR = stream->readFloat();
|
||||
m_extIOR = stream->readFloat();
|
||||
m_specularSamplingWeight = stream->readFloat();
|
||||
|
@ -82,7 +105,7 @@ public:
|
|||
}
|
||||
|
||||
Spectrum getDiffuseReflectance(const Intersection &its) const {
|
||||
return m_diffuseReflectance->getValue(its);
|
||||
return m_diffuseReflectance->getValue(its) * m_kd;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -162,9 +185,9 @@ public:
|
|||
Float F = fresnel(dot(bRec.wi, Hr), m_extIOR, m_intIOR);
|
||||
|
||||
if (hasGlossy)
|
||||
result += fSpec(bRec, Hr) * F;
|
||||
result += fSpec(bRec, Hr) * (F * m_ks);
|
||||
if (hasDiffuse)
|
||||
result += m_diffuseReflectance->getValue(bRec.its) * INV_PI * (1-F);
|
||||
result += m_diffuseReflectance->getValue(bRec.its) * (INV_PI * (1-F) * m_kd);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -268,6 +291,8 @@ public:
|
|||
manager->serialize(stream, m_diffuseReflectance.get());
|
||||
manager->serialize(stream, m_specularReflectance.get());
|
||||
stream->writeFloat(m_alphaB);
|
||||
stream->writeFloat(m_kd);
|
||||
stream->writeFloat(m_ks);
|
||||
stream->writeFloat(m_intIOR);
|
||||
stream->writeFloat(m_extIOR);
|
||||
stream->writeFloat(m_specularSamplingWeight);
|
||||
|
@ -295,6 +320,7 @@ private:
|
|||
Float m_alphaB, m_intIOR, m_extIOR;
|
||||
Float m_specularSamplingWeight;
|
||||
Float m_diffuseSamplingWeight;
|
||||
Float m_ks, m_kd;
|
||||
};
|
||||
|
||||
// ================ Hardware shader implementation ================
|
||||
|
@ -304,10 +330,12 @@ public:
|
|||
MicrofacetShader(Renderer *renderer,
|
||||
const Texture *diffuseReflectance,
|
||||
const Texture *specularReflectance,
|
||||
Float alphaB, Float etaInt, Float etaExt) : Shader(renderer, EBSDFShader),
|
||||
Float alphaB, Float etaInt, Float etaExt,
|
||||
Float ks, Float kd) : Shader(renderer, EBSDFShader),
|
||||
m_diffuseReflectance(diffuseReflectance),
|
||||
m_specularReflectance(specularReflectance),
|
||||
m_alphaB(alphaB), m_etaInt(etaInt), m_etaExt(etaExt) {
|
||||
m_alphaB(alphaB), m_etaInt(etaInt), m_etaExt(etaExt),
|
||||
m_ks(ks), m_kd(kd) {
|
||||
m_diffuseReflectanceShader = renderer->registerShaderForResource(m_diffuseReflectance.get());
|
||||
m_specularReflectanceShader = renderer->registerShaderForResource(m_specularReflectance.get());
|
||||
}
|
||||
|
@ -333,6 +361,8 @@ public:
|
|||
oss << "uniform float " << evalName << "_alphaB;" << endl
|
||||
<< "uniform float " << evalName << "_etaInt;" << endl
|
||||
<< "uniform float " << evalName << "_etaExt;" << endl
|
||||
<< "uniform float " << evalName << "_ks;" << endl
|
||||
<< "uniform float " << evalName << "_kd;" << endl
|
||||
<< endl
|
||||
<< "float " << evalName << "_beckmannD(vec3 m) {" << endl
|
||||
<< " float ex = tanTheta(m) / " << evalName << "_alphaB;" << endl
|
||||
|
@ -376,8 +406,8 @@ public:
|
|||
<< " vec3 hr = normalize(wi + wo);" << endl
|
||||
<< " float Fr = " << evalName << "_fresnel(wi, hr, " << evalName << "_etaExt, " << evalName << "_etaInt);"<< endl
|
||||
<< " float Ft = 1-Fr;"<< endl
|
||||
<< " return " << depNames[0] << "(uv) * (0.31831 * Ft)" << endl
|
||||
<< " + " << depNames[1] << "(uv) * (" << evalName << "_fSpec(wi, wo, hr) * Fr);" << endl
|
||||
<< " return " << depNames[0] << "(uv) * (0.31831 * Ft) * " << evalName << "_kd" << endl
|
||||
<< " + " << depNames[1] << "(uv) * (" << evalName << "_fSpec(wi, wo, hr) * Fr) * " << evalName << "_ks" << endl
|
||||
<< "}" << endl
|
||||
<< "vec3 " << evalName << "_diffuse(vec2 uv, vec3 wi, vec3 wo) {" << endl
|
||||
<< " if (wi.z <= 0 || wo.z <= 0)" << endl
|
||||
|
@ -390,12 +420,16 @@ public:
|
|||
parameterIDs.push_back(program->getParameterID(evalName + "_alphaB", false));
|
||||
parameterIDs.push_back(program->getParameterID(evalName + "_etaInt", false));
|
||||
parameterIDs.push_back(program->getParameterID(evalName + "_etaExt", false));
|
||||
parameterIDs.push_back(program->getParameterID(evalName + "_ks", false));
|
||||
parameterIDs.push_back(program->getParameterID(evalName + "_kd", false));
|
||||
}
|
||||
|
||||
void bind(GPUProgram *program, const std::vector<int> ¶meterIDs, int &textureUnitOffset) const {
|
||||
program->setParameter(parameterIDs[0], m_alphaB);
|
||||
program->setParameter(parameterIDs[1], m_etaInt);
|
||||
program->setParameter(parameterIDs[2], m_etaExt);
|
||||
program->setParameter(parameterIDs[3], m_ks);
|
||||
program->setParameter(parameterIDs[4], m_kd);
|
||||
}
|
||||
|
||||
MTS_DECLARE_CLASS()
|
||||
|
@ -404,12 +438,13 @@ private:
|
|||
ref<const Texture> m_specularReflectance;
|
||||
ref<Shader> m_diffuseReflectanceShader;
|
||||
ref<Shader> m_specularReflectanceShader;
|
||||
Float m_alphaB, m_etaInt, m_etaExt;
|
||||
Float m_alphaB, m_etaInt, m_etaExt, m_ks, m_kd;
|
||||
};
|
||||
|
||||
Shader *Microfacet::createShader(Renderer *renderer) const {
|
||||
return new MicrofacetShader(renderer, m_diffuseReflectance.get(),
|
||||
m_specularReflectance.get(), m_alphaB, m_intIOR, m_extIOR);
|
||||
m_specularReflectance.get(), m_alphaB, m_intIOR, m_extIOR,
|
||||
m_ks, m_kd);
|
||||
}
|
||||
|
||||
MTS_IMPLEMENT_CLASS(MicrofacetShader, false, Shader)
|
||||
|
|
|
@ -31,27 +31,32 @@ class Phong : public BSDF {
|
|||
public:
|
||||
Phong(const Properties &props)
|
||||
: BSDF(props) {
|
||||
m_diffuseColor = new ConstantTexture(
|
||||
props.getSpectrum("diffuseColor", Spectrum(1.0f)));
|
||||
m_specularColor = new ConstantTexture(
|
||||
props.getSpectrum("specularColor", Spectrum(1.0f)));
|
||||
m_diffuseReflectance = new ConstantTexture(
|
||||
props.getSpectrum("diffuseReflectance", Spectrum(0.5f)));
|
||||
m_specularReflectance = new ConstantTexture(
|
||||
props.getSpectrum("specularReflectance", Spectrum(0.2f)));
|
||||
|
||||
m_kd = props.getFloat("diffuseAmount", 1.0f);
|
||||
m_ks = props.getFloat("specularAmount", 1.0f);
|
||||
|
||||
m_kd = props.getFloat("diffuseReflectance", 0.5f);
|
||||
m_ks = props.getFloat("specularReflectance", 0.2f);
|
||||
m_exponent = props.getFloat("exponent", 10.0f);
|
||||
|
||||
if (m_kd * m_diffuseColor->getMaximum().max() + m_ks * m_specularColor->getMaximum().max() > 1.0f) {
|
||||
Log(EWarn, "%s: Energy conservation is violated!", props.getID().c_str());
|
||||
Log(EWarn, "Max. diffuse reflectance = %f * %f", m_kd, m_diffuseColor->getMaximum().max());
|
||||
Log(EWarn, "Max. specular reflectance = %f * %f", m_ks, m_specularColor->getMaximum().max());
|
||||
Float normalization = 1/(m_kd * m_diffuseColor->getMaximum().max() + m_ks * m_specularColor->getMaximum().max());
|
||||
Log(EWarn, "Reducing the albedo to %.1f%% of the original value", normalization * 100);
|
||||
bool verifyEnergyConservation = props.getBoolean("verifyEnergyConservation", true);
|
||||
|
||||
if (verifyEnergyConservation && (m_kd * m_diffuseReflectance->getMaximum().max()
|
||||
+ m_ks * m_specularReflectance->getMaximum().max() > 1.0f)) {
|
||||
Log(EWarn, "%s: Energy conservation is potentially violated!", props.getID().c_str());
|
||||
Log(EWarn, "Max. diffuse reflectance = %f * %f = %f", m_kd, m_diffuseReflectance->getMaximum().max(), m_kd*m_diffuseReflectance->getMaximum().max());
|
||||
Log(EWarn, "Max. specular reflectance = %f * %f = %f", m_ks, m_specularReflectance->getMaximum().max(), m_ks*m_specularReflectance->getMaximum().max());
|
||||
Float normalization = 1/(m_kd * m_diffuseReflectance->getMaximum().max() + m_ks * m_specularReflectance->getMaximum().max());
|
||||
Log(EWarn, "Reducing the albedo to %.1f%% of the original value to be on the safe side. "
|
||||
"Specify verifyEnergyConservation=false to prevent this.", normalization * 100);
|
||||
m_kd *= normalization; m_ks *= normalization;
|
||||
}
|
||||
|
||||
Float avgDiffReflectance = m_diffuseColor->getAverage().average() * m_kd;
|
||||
Float avgSpecularReflectance = m_specularColor->getAverage().average() * m_ks;
|
||||
|
||||
Float avgDiffReflectance = m_diffuseReflectance->getAverage().average() * m_kd;
|
||||
Float avgSpecularReflectance = m_specularReflectance->getAverage().average() * m_ks;
|
||||
|
||||
m_specularSamplingWeight = props.getFloat("specularSamplingWeight",
|
||||
avgSpecularReflectance / (avgDiffReflectance + avgSpecularReflectance));
|
||||
m_diffuseSamplingWeight = 1.0f - m_specularSamplingWeight;
|
||||
|
@ -66,8 +71,8 @@ public:
|
|||
|
||||
Phong(Stream *stream, InstanceManager *manager)
|
||||
: BSDF(stream, manager) {
|
||||
m_diffuseColor = static_cast<Texture *>(manager->getInstance(stream));
|
||||
m_specularColor = static_cast<Texture *>(manager->getInstance(stream));
|
||||
m_diffuseReflectance = static_cast<Texture *>(manager->getInstance(stream));
|
||||
m_specularReflectance = static_cast<Texture *>(manager->getInstance(stream));
|
||||
m_exponent = stream->readFloat();
|
||||
m_kd = stream->readFloat();
|
||||
m_ks = stream->readFloat();
|
||||
|
@ -80,8 +85,8 @@ public:
|
|||
m_type[1] = EGlossyReflection;
|
||||
m_combinedType = m_type[0] | m_type[1];
|
||||
m_usesRayDifferentials =
|
||||
m_diffuseColor->usesRayDifferentials() ||
|
||||
m_specularColor->usesRayDifferentials();
|
||||
m_diffuseReflectance->usesRayDifferentials() ||
|
||||
m_specularReflectance->usesRayDifferentials();
|
||||
}
|
||||
|
||||
virtual ~Phong() {
|
||||
|
@ -89,7 +94,7 @@ public:
|
|||
}
|
||||
|
||||
Spectrum getDiffuseReflectance(const Intersection &its) const {
|
||||
return m_diffuseColor->getValue(its) * m_kd;
|
||||
return m_diffuseReflectance->getValue(its) * m_kd;
|
||||
}
|
||||
|
||||
Spectrum f(const BSDFQueryRecord &bRec) const {
|
||||
|
@ -113,11 +118,11 @@ public:
|
|||
else
|
||||
specRef = (m_exponent + 2) * INV_TWOPI
|
||||
* std::pow(alpha, m_exponent) * m_ks;
|
||||
result += m_specularColor->getValue(bRec.its) * specRef;
|
||||
result += m_specularReflectance->getValue(bRec.its) * specRef;
|
||||
}
|
||||
|
||||
if (hasDiffuse)
|
||||
result += m_diffuseColor->getValue(bRec.its) * (INV_PI * m_kd);
|
||||
result += m_diffuseReflectance->getValue(bRec.its) * (INV_PI * m_kd);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -155,7 +160,7 @@ public:
|
|||
inline Spectrum sampleSpecular(BSDFQueryRecord &bRec) const {
|
||||
Vector R = Vector(-bRec.wi.x, -bRec.wi.y, bRec.wi.z);
|
||||
|
||||
/* Sample a cosine lobe centered around the normal */
|
||||
/* Sample from a Phong lobe centered around (0, 0, 1) */
|
||||
Float sinAlpha = std::sqrt(1-std::pow(bRec.sample.y, 2/(m_exponent + 1)));
|
||||
Float cosAlpha = std::pow(bRec.sample.y, 1/(m_exponent + 1));
|
||||
Float phi = (2.0f * M_PI) * bRec.sample.x;
|
||||
|
@ -218,11 +223,11 @@ public:
|
|||
|
||||
void addChild(const std::string &name, ConfigurableObject *child) {
|
||||
if (child->getClass()->derivesFrom(Texture::m_theClass) && name == "diffuseColor") {
|
||||
m_diffuseColor = static_cast<Texture *>(child);
|
||||
m_usesRayDifferentials |= m_diffuseColor->usesRayDifferentials();
|
||||
m_diffuseReflectance = static_cast<Texture *>(child);
|
||||
m_usesRayDifferentials |= m_diffuseReflectance->usesRayDifferentials();
|
||||
} else if (child->getClass()->derivesFrom(Texture::m_theClass) && name == "specularColor") {
|
||||
m_specularColor = static_cast<Texture *>(child);
|
||||
m_usesRayDifferentials |= m_specularColor->usesRayDifferentials();
|
||||
m_specularReflectance = static_cast<Texture *>(child);
|
||||
m_usesRayDifferentials |= m_specularReflectance->usesRayDifferentials();
|
||||
} else {
|
||||
BSDF::addChild(name, child);
|
||||
}
|
||||
|
@ -231,8 +236,8 @@ public:
|
|||
void serialize(Stream *stream, InstanceManager *manager) const {
|
||||
BSDF::serialize(stream, manager);
|
||||
|
||||
manager->serialize(stream, m_diffuseColor.get());
|
||||
manager->serialize(stream, m_specularColor.get());
|
||||
manager->serialize(stream, m_diffuseReflectance.get());
|
||||
manager->serialize(stream, m_specularReflectance.get());
|
||||
stream->writeFloat(m_exponent);
|
||||
stream->writeFloat(m_kd);
|
||||
stream->writeFloat(m_ks);
|
||||
|
@ -245,8 +250,8 @@ public:
|
|||
std::string toString() const {
|
||||
std::ostringstream oss;
|
||||
oss << "Phong[" << endl
|
||||
<< " diffuseColor = " << indent(m_diffuseColor->toString()) << "," << endl
|
||||
<< " specularColor = " << indent(m_specularColor->toString()) << "," << endl
|
||||
<< " diffuseColor = " << indent(m_diffuseReflectance->toString()) << "," << endl
|
||||
<< " specularColor = " << indent(m_specularReflectance->toString()) << "," << endl
|
||||
<< " exponent = " << m_exponent << endl
|
||||
<< "]";
|
||||
return oss.str();
|
||||
|
@ -255,8 +260,8 @@ public:
|
|||
|
||||
MTS_DECLARE_CLASS()
|
||||
private:
|
||||
ref<Texture> m_diffuseColor;
|
||||
ref<Texture> m_specularColor;
|
||||
ref<Texture> m_diffuseReflectance;
|
||||
ref<Texture> m_specularReflectance;
|
||||
Float m_exponent;
|
||||
Float m_kd, m_ks;
|
||||
Float m_specularSamplingWeight;
|
||||
|
@ -272,27 +277,27 @@ public:
|
|||
const Texture *specularColor,
|
||||
Float ks, Float kd,
|
||||
Float exponent) : Shader(renderer, EBSDFShader),
|
||||
m_diffuseColor(diffuseColor),
|
||||
m_specularColor(specularColor),
|
||||
m_diffuseReflectance(diffuseColor),
|
||||
m_specularReflectance(specularColor),
|
||||
m_ks(ks), m_kd(kd),
|
||||
m_exponent(exponent) {
|
||||
m_diffuseColorShader = renderer->registerShaderForResource(m_diffuseColor.get());
|
||||
m_specularColorShader = renderer->registerShaderForResource(m_specularColor.get());
|
||||
m_diffuseReflectanceShader = renderer->registerShaderForResource(m_diffuseReflectance.get());
|
||||
m_specularReflectanceShader = renderer->registerShaderForResource(m_specularReflectance.get());
|
||||
}
|
||||
|
||||
bool isComplete() const {
|
||||
return m_diffuseColorShader.get() != NULL &&
|
||||
m_specularColorShader.get() != NULL;
|
||||
return m_diffuseReflectanceShader.get() != NULL &&
|
||||
m_specularReflectanceShader.get() != NULL;
|
||||
}
|
||||
|
||||
void putDependencies(std::vector<Shader *> &deps) {
|
||||
deps.push_back(m_diffuseColorShader.get());
|
||||
deps.push_back(m_specularColorShader.get());
|
||||
deps.push_back(m_diffuseReflectanceShader.get());
|
||||
deps.push_back(m_specularReflectanceShader.get());
|
||||
}
|
||||
|
||||
void cleanup(Renderer *renderer) {
|
||||
renderer->unregisterShaderForResource(m_diffuseColor.get());
|
||||
renderer->unregisterShaderForResource(m_specularColor.get());
|
||||
renderer->unregisterShaderForResource(m_diffuseReflectance.get());
|
||||
renderer->unregisterShaderForResource(m_specularReflectance.get());
|
||||
}
|
||||
|
||||
void generateCode(std::ostringstream &oss,
|
||||
|
@ -335,17 +340,17 @@ public:
|
|||
|
||||
MTS_DECLARE_CLASS()
|
||||
private:
|
||||
ref<const Texture> m_diffuseColor;
|
||||
ref<const Texture> m_specularColor;
|
||||
ref<Shader> m_diffuseColorShader;
|
||||
ref<Shader> m_specularColorShader;
|
||||
ref<const Texture> m_diffuseReflectance;
|
||||
ref<const Texture> m_specularReflectance;
|
||||
ref<Shader> m_diffuseReflectanceShader;
|
||||
ref<Shader> m_specularReflectanceShader;
|
||||
Float m_ks, m_kd;
|
||||
Float m_exponent;
|
||||
};
|
||||
|
||||
Shader *Phong::createShader(Renderer *renderer) const {
|
||||
return new PhongShader(renderer, m_diffuseColor.get(),
|
||||
m_specularColor.get(), m_ks, m_kd, m_exponent);
|
||||
return new PhongShader(renderer, m_diffuseReflectance.get(),
|
||||
m_specularReflectance.get(), m_ks, m_kd, m_exponent);
|
||||
}
|
||||
|
||||
MTS_IMPLEMENT_CLASS(PhongShader, false, Shader)
|
||||
|
|
|
@ -613,13 +613,11 @@ void loadMaterial(GeometryConverter *cvt, std::ostream &os, domMaterial &mat, St
|
|||
os << "\t</bsdf>" << endl << endl;
|
||||
} else {
|
||||
os << "\t<bsdf id=\"" << identifier << "\" type=\"phong\">" << endl;
|
||||
os << "\t\t<float name=\"specularReflectance\" value=\"1\"/>" << endl;
|
||||
os << "\t\t<float name=\"diffuseReflectance\" value=\"1\"/>" << endl;
|
||||
loadMaterialParam(cvt, os, "diffuseColor", idToTexture, diffuse, false);
|
||||
loadMaterialParam(cvt, os, "specularColor", idToTexture, specular, false);
|
||||
loadMaterialParam(cvt, os, "diffuseReflectance", idToTexture, diffuse, false);
|
||||
loadMaterialParam(cvt, os, "specularReflectance", idToTexture, specular, false);
|
||||
loadMaterialParam(cvt, os, "exponent", idToTexture, shininess, false);
|
||||
loadMaterialParam(cvt, os, "diffuseColor", idToTexture, diffuse, true);
|
||||
loadMaterialParam(cvt, os, "specularColor", idToTexture, specular, true);
|
||||
loadMaterialParam(cvt, os, "diffuseReflectance", idToTexture, diffuse, true);
|
||||
loadMaterialParam(cvt, os, "specularReflectance", idToTexture, specular, true);
|
||||
loadMaterialParam(cvt, os, "exponent", idToTexture, shininess, true);
|
||||
os << "\t</bsdf>" << endl << endl;
|
||||
}
|
||||
|
|
|
@ -268,7 +268,7 @@ void Bitmap::loadBMP(Stream *stream) {
|
|||
{
|
||||
uint32_t header_sz;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
int32_t height;
|
||||
uint16_t nplanes;
|
||||
uint16_t bitspp;
|
||||
uint32_t compress_type;
|
||||
|
@ -301,17 +301,41 @@ void Bitmap::loadBMP(Stream *stream) {
|
|||
if (DIBHeader.bitspp != 8 && DIBHeader.bitspp != 24)
|
||||
Log(EError, "Only 8- and 24-bit BMP images are supported for now");
|
||||
|
||||
if (DIBHeader.compress_type != 0)
|
||||
Log(EError, "Only uncompressed BMP images are supported for now");
|
||||
|
||||
m_width = DIBHeader.width;
|
||||
m_height = DIBHeader.height;
|
||||
m_height = std::abs(DIBHeader.height);
|
||||
m_bpp = DIBHeader.bitspp;
|
||||
|
||||
m_size = m_width * m_height * (m_bpp / 8);
|
||||
m_data = static_cast<unsigned char *>(allocAligned(m_size));
|
||||
Log(ETrace, "Reading %ix%ix%i BMP file", m_width, m_height, m_bpp);
|
||||
|
||||
Log(ETrace, "Reading %ix%ix%i PNG file", m_width, m_height, m_bpp);
|
||||
int nChannels = m_bpp / 8;
|
||||
int lineWidth = m_width * nChannels;
|
||||
int paddedLineWidth = lineWidth + lineWidth % 4;
|
||||
|
||||
if (DIBHeader.compress_type != 0)
|
||||
Log(EError, "Only uncompressed BMP images are supported for now");
|
||||
uint8_t *line = new uint8_t[paddedLineWidth];
|
||||
|
||||
for (int y=0; y<m_height; ++y) {
|
||||
stream->read(line, paddedLineWidth);
|
||||
|
||||
int targetY = y;
|
||||
|
||||
if (DIBHeader.height > 0)
|
||||
targetY = m_height - 1 - y; // inverted rows
|
||||
|
||||
memcpy(&m_data[targetY * m_width * nChannels], line, lineWidth);
|
||||
|
||||
if (nChannels == 3) {
|
||||
for (int x=0; x<m_width; ++x)
|
||||
std::swap(m_data[(targetY * m_width + x) * nChannels],
|
||||
m_data[(targetY * m_width + x) * nChannels + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] line;
|
||||
}
|
||||
|
||||
void Bitmap::loadPNG(Stream *stream) {
|
||||
|
|
Loading…
Reference in New Issue