void WriteImage(const std::string &name, const Float *rgb, const Bounds2i &outputBounds, const Point2i &totalResolution, Float gamma) { if (name.size() >= 5) { size_t suffixOffset = name.size() - 4; if (!strcmp(name.c_str() + suffixOffset, ".exr") || !strcmp(name.c_str() + suffixOffset, ".EXR")) { WriteImageEXR(name, rgb, outputBounds.pMax.x - outputBounds.pMin.x, outputBounds.pMax.y - outputBounds.pMin.y, totalResolution.x, totalResolution.y, outputBounds.pMin.x, outputBounds.pMin.y); return; } if (!strcmp(name.c_str() + suffixOffset, ".pfm") || !strcmp(name.c_str() + suffixOffset, ".PFM")) { Vector2i resolution = outputBounds.Diagonal(); WriteImagePFM(name, rgb, resolution.x, resolution.y); return; } if (!strcmp(name.c_str() + suffixOffset, ".tga") || !strcmp(name.c_str() + suffixOffset, ".TGA") || !strcmp(name.c_str() + suffixOffset, ".png") || !strcmp(name.c_str() + suffixOffset, ".PNG")) { // 8-bit formats; apply gamma Vector2i resolution = outputBounds.Diagonal(); std::unique_ptr<uint8_t[]> rgb8( new uint8_t[3 * resolution.x * resolution.y]); uint8_t *dst = rgb8.get(); for (int y = 0; y < resolution.y; ++y) { for (int x = 0; x < resolution.x; ++x) { #define TO_BYTE(v) (uint8_t(Clamp(255.f * powf((v), 1.f / gamma), 0.f, 255.f))) dst[0] = TO_BYTE(rgb[3 * (y * resolution.x + x) + 0]); dst[1] = TO_BYTE(rgb[3 * (y * resolution.x + x) + 1]); dst[2] = TO_BYTE(rgb[3 * (y * resolution.x + x) + 2]); #undef TO_BYTE dst += 3; } } if (!strcmp(name.c_str() + suffixOffset, ".tga") || !strcmp(name.c_str() + suffixOffset, ".TGA")) WriteImageTGA(name, rgb8.get(), outputBounds.pMax.x - outputBounds.pMin.x, outputBounds.pMax.y - outputBounds.pMin.y, totalResolution.x, totalResolution.y, outputBounds.pMin.x, outputBounds.pMin.y); else if (stbi_write_png(name.c_str(), resolution.x, resolution.y, 3, rgb8.get(), 3 * resolution.x) == 0) Error("Error writing PNG \"%s\"", name.c_str()); return; } } Error("Can't determine image file type from suffix of filename \"%s\"", name.c_str()); }
void WriteImage(const std::string &name, const Float *rgb, const Bounds2i &outputBounds, const Point2i &totalResolution) { Vector2i resolution = outputBounds.Diagonal(); if (HasExtension(name, ".exr")) { WriteImageEXR(name, rgb, resolution.x, resolution.y, totalResolution.x, totalResolution.y, outputBounds.pMin.x, outputBounds.pMin.y); } else if (HasExtension(name, ".exr")) { WriteImagePFM(name, rgb, resolution.x, resolution.y); } else if (HasExtension(name, ".tga") || HasExtension(name, ".png")) { // 8-bit formats; apply gamma Vector2i resolution = outputBounds.Diagonal(); std::unique_ptr<uint8_t[]> rgb8( new uint8_t[3 * resolution.x * resolution.y]); uint8_t *dst = rgb8.get(); for (int y = 0; y < resolution.y; ++y) { for (int x = 0; x < resolution.x; ++x) { #define TO_BYTE(v) (uint8_t) Clamp(255.f * GammaCorrect(v) + 0.5f, 0.f, 255.f) dst[0] = TO_BYTE(rgb[3 * (y * resolution.x + x) + 0]); dst[1] = TO_BYTE(rgb[3 * (y * resolution.x + x) + 1]); dst[2] = TO_BYTE(rgb[3 * (y * resolution.x + x) + 2]); #undef TO_BYTE dst += 3; } } if (HasExtension(name, ".tga")) WriteImageTGA( name, rgb8.get(), outputBounds.pMax.x - outputBounds.pMin.x, outputBounds.pMax.y - outputBounds.pMin.y, totalResolution.x, totalResolution.y, outputBounds.pMin.x, outputBounds.pMin.y); else if (stbi_write_png(name.c_str(), resolution.x, resolution.y, 3, rgb8.get(), 3 * resolution.x) == 0) Error("Error writing PNG \"%s\"", name.c_str()); } else { Error("Can't determine image file type from suffix of filename \"%s\"", name.c_str()); } }