#include #include #include #include namespace psemek::gfx { pixmap_monochrome read_pbm(std::istream & is) { auto fail = [](std::string str) { throw std::runtime_error("Error loading PBM image: " + str); }; std::string line; std::getline(is, line); bool binary = true; if (line == "P1") { binary = false; } else if (line == "P4") { binary = true; } else fail("unknown format " + line); if (!binary) fail("P1 format is not supported"); std::getline(is, line); std::istringstream sline(line); std::size_t width, height; pixmap_monochrome pixmap; sline >> width >> height; pixmap.resize(width, height); std::size_t bytes = width * height; if ((bytes % 8) == 0) bytes = bytes / 8; else bytes = (bytes + 7) / 8; std::vector data(bytes); is.read(reinterpret_cast(data.data()), bytes); for (std::size_t i = 0; i < width * height; ++i) { std::size_t b = i / 8; std::size_t o = 7 - (i % 8); bool const white = (data[b] & (1 << o)) == 0; pixmap.data()[i] = white ? 255 : 0; } if (!is) fail("stream error"); return pixmap; } pixmap_monochrome read_pgm(std::istream & is) { auto fail = [](std::string str) { throw std::runtime_error("Error loading PGM image: " + str); }; std::string line; std::getline(is, line); bool binary = true; if (line == "P2") { binary = false; } else if (line == "P5") { binary = true; } else fail("unknown format " + line); std::getline(is, line); std::istringstream sline(line); std::size_t width, height; std::size_t max; pixmap_monochrome pixmap; sline >> width >> height; std::getline(is, line); sline.str(line); sline >> max; if (max != 255) fail("max value " + std::to_string(max) + " is not supported"); pixmap.resize(width, height); if (binary) is.read(reinterpret_cast(pixmap.data()), width * height * sizeof(pixmap.data()[0])); else fail("P2 format is not supported"); if (!is) fail("stream error"); return pixmap; } pixmap_rgb load_ppm(std::istream & is) { auto fail = [](std::string str) { throw std::runtime_error("Error loading PPM image: " + str); }; std::string line; std::getline(is, line); bool binary = true; if (line == "P3") { binary = false; } else if (line == "P6") { binary = true; } else fail("unknown format " + line); std::getline(is, line); std::istringstream sline(line); std::size_t width, height; std::size_t max; pixmap_rgb pixmap; sline >> width >> height; std::getline(is, line); sline.str(line); sline >> max; if (max != 255) fail("max value " + std::to_string(max) + " is not supported"); pixmap.resize(width, height); if (binary) is.read(reinterpret_cast(pixmap.data()), width * height * sizeof(pixmap.data()[0])); else fail("P3 format is not supported"); if (!is) fail("stream error"); return pixmap; } void write_pgm(pixmap_monochrome const & p, std::ostream & os) { os << "P5\n" << p.width() << " " << p.height() << "\n255\n"; os.write(reinterpret_cast(p.data()), p.width() * p.height() * sizeof(p.data()[0])); } void write_ppm(pixmap_rgb const & p, std::ostream & os) { os << "P6\n" << p.width() << " " << p.height() << "\n255\n"; os.write(reinterpret_cast(p.data()), p.width() * p.height() * sizeof(p.data()[0])); } }