{"id":29593813,"url":"https://github.com/manu-sh/opnm","last_synced_at":"2026-06-24T06:34:48.569Z","repository":{"id":303671044,"uuid":"1016280542","full_name":"Manu-sh/opnm","owner":"Manu-sh","description":"pnm image file formats implementation","archived":false,"fork":false,"pushed_at":"2025-11-19T22:23:16.000Z","size":51,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-11-20T00:15:46.008Z","etag":null,"topics":["image-format","pgm-format","pnm-format","ppm-format"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Manu-sh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-07-08T19:04:22.000Z","updated_at":"2025-11-19T22:23:20.000Z","dependencies_parsed_at":"2025-08-03T23:24:25.309Z","dependency_job_id":"f1446ba2-6ed6-45da-a356-bac9b7572606","html_url":"https://github.com/Manu-sh/opnm","commit_stats":null,"previous_names":["manu-sh/pnm","manu-sh/opnm"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Manu-sh/opnm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Manu-sh%2Fopnm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Manu-sh%2Fopnm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Manu-sh%2Fopnm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Manu-sh%2Fopnm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Manu-sh","download_url":"https://codeload.github.com/Manu-sh/opnm/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Manu-sh%2Fopnm/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34720920,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-24T02:00:07.484Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["image-format","pgm-format","pnm-format","ppm-format"],"created_at":"2025-07-20T07:38:35.326Z","updated_at":"2026-06-24T06:34:48.546Z","avatar_url":"https://github.com/Manu-sh.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"### Output Pnm :framed_picture:\n###### common pnm file formats\n\nThis mini-library is for dealing with common PNM format.\n\n#### Future (?)\n- :white_check_mark: ~~add `PNM\u003cT\u003e(filename)` constructors or a factory method to read files from disk into a `PNM\u003cT\u003e` object~~\n- :white_check_mark: ~~add `write_content(ostream\u0026)`~~\n\n\nExamples: [see here](https://github.com/Manu-sh/example-opnm)\n\nThe library was originally written for [this project](https://github.com/Manu-sh/cuda-mandelbrot), i decided to create a separate repository to be able to reuse the code more easily. \n\nThere is duplicate code and the reason is that originally it was supposed to be only extremely efficient in creating and writing a pbm rgb type file only later it was expanded to include pbm and pgm, the correct approach would have been to avoid any kind of static polymorphism (template) and to use dynamic polymorphism (interfaces, vtable etc) and class inheritance. \n\nThe in-memory representation of PNM\u003cT\u003e files is always binary, and include a padding when required by the format, see pbm. The raster data (aka pixmap) of an image w=3 h=2 in pbm format will occupy 2 bytes in memory. Any conversion to ascii occurs later when write_content() is called.\n\n\nLearning resources\n\n- https://en.wikipedia.org/wiki/Netpbm\n- https://netpbm.sourceforge.net/doc/pbm.html\n- https://netpbm.sourceforge.net/doc/pgm.html\n- https://netpbm.sourceforge.net/doc/ppm.html\n\n```cpp\n// chessboard pattern\nPNM\u003cpnm::monochrome_t\u003e chessboard{1920, 1080};\nbool color = pnm::monochrome_t::BLACK;\n\nfor (int h = 0; h \u003c chessboard.height(); ++h, color = !color)\n    for (int w = 0; w \u003c chessboard.width(); ++w, color = !color)\n        chessboard(h, w, color);\n\nchessboard.write_file_content(\"chessboard-bin.pbm\");\n\n{ // read the file again from disk but this time save as ascii file\n    static const auto \u0026ifstream_open = [](const char *filename) -\u003e std::ifstream {\n        using std::literals::string_literals::operator\"\"s, std::ios_base;\n        std::ifstream fpnm;\n        fpnm.exceptions(ios_base::badbit);\n        fpnm.open(filename, ios_base::in|ios_base::binary);\n        if (!fpnm) throw std::invalid_argument{\"Unable to open file: \"s + filename};\n        return fpnm;\n    };\n\n    bool use_asci_fmt = 1;\n    auto is = ifstream_open(\"chessboard-bin.pbm\");\n\n    // you can parse any TPixel (pnm::monochrome_t, pnm::rgb\u003cpnm::BIT_8\u003e, pnm::grayscale\u003cpnm::BIT_8\u003e)\n    auto image = PNM\u003cpnm::monochrome_t\u003e::parse(is);\n    image.write_file_content(\"chessboard-ascii.pbm\", use_asci_fmt);\n}\n\n\nPNM\u003cpnm::monochrome_t\u003e pbm{3, 2};\n\npbm(0,0, {255, 0,   0}); // since bits aren't addressable you will use a different syntax\npbm(0,1, {0,   255, 0});\npbm(0,2, {0,   255, 0});\n\npbm(1,0, {255, 255, 0});\npbm(1,1, {255, 255, 255});\npbm(1,2, {0,   0,   0});\n\npbm.write_file_content(\"bin.pbm\");\npbm.write_file_content(\"ascii.pbm\", 1);\n\nPNM\u003cpnm::rgb\u003cpnm::BIT_8\u003e\u003e ppm{3, 2};\n\nppm(0,0) = {255, 0,   0};  // here you can assign since a reference to an addressable pixel (\u003e= 1 byte) is returned\nppm(0,1) = {0,   255, 0};\nppm(0,2) = {0,   0,   255};\n\nppm(1,0) = {255, 255, 0};\nppm(1,1) = {255, 255, 255};\nppm(1,2) = {0,   0,   0};\n\n\nppm.write_file_content(\"bin.ppm\");\nppm.write_file_content(\"ascii.ppm\", 1);\n\nPNM\u003cpnm::grayscale\u003cpnm::BIT_8\u003e\u003e pgm{3, 2};\n\npgm(0,0) = {255, 0,   0};\npgm(0,1) = {0,   255, 0};\npgm(0,2) = {0,   0,   255};\n\npgm(1,0) = {255, 255, 0};\npgm(1,1) = {255, 255, 255};\npgm(1,2) = {0,   0,   0};\n\npgm.write_file_content(\"bin.pgm\");\npgm.write_file_content(\"ascii.pgm\", 1);\n\n```\n\n###### Copyright © 2025, [Manu-sh](https://github.com/Manu-sh), s3gmentationfault@gmail.com. Released under the [MIT license](LICENSE).\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmanu-sh%2Fopnm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmanu-sh%2Fopnm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmanu-sh%2Fopnm/lists"}