/* Copyright (c) 2005,2006 Dirk Jagdmann This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ // https://llg.cubic.org/tools/#pgm2cip // version 2005-06-18 // - initial release // version 2006-05-20 // - set max length of title and prompt string to 32 chars // - get pgm input from command line or stdin #include #include #include #include #include #include const int readerr=-12345678; std::string comment; void skipws(std::istream& is) { int c; do { c=is.get(); } while(isspace(c)); is.unget(); } int readnum(std::istream& is) { readnumagain: skipws(is); int p=is.peek(); if(p=='#') { is.get(); // read # comment.erase(); getline(is, comment); goto readnumagain; } if(is>>p) return p; return readerr; } int readpix(int n, std::istream& is) { int p=is.get(); if(p==EOF) return readerr; if(n==2) { int q=is.get(); if(q==EOF) return readerr; return p*256+q; } return p; } std::string escape(const std::string& s) { std::string a; for(std::string::const_iterator i=s.begin(); i!=s.end(); ++i) switch(*i) { case '<': a+="<"; break; case '>': a+=">"; break; case '&': a+="&"; break; case '"': a+="""; break; case '\'': a+="'"; break; default: a+=*i; } return a; } int main(int argc, char **argv) { std::string magic, title, prompt; int x=-1, y=-1; char *t; // decide if we read pgm from file or stdin std::ifstream fs; if(argc>1) { fs.open(argv[1]); if(!fs) { std::cerr << "could not open " << argv[1] << std::endl; return 1; } } std::istream& is=(argc>1) ? fs : std::cin; // read pgm header if(!(is>>magic)) { std::cerr << "could not read magic\n"; return 1; } if(!(magic=="P2" || magic=="P5")) { std::cerr << "wrong magic. This is not an ascii pgm file\n"; return 2; } const int width=readnum(is); if(width==readerr) { std::cerr << "could not read width\n"; return 3; } if(width<=0 || width>133) { std::cerr << "width<=0 || width>133\n"; return 4; } const int height=readnum(is); if(height==readerr) { std::cerr << "could not read height\n"; return 5; } if(height<=0 || height>65) { std::cerr << "height<=0 || height>65\n"; return 6; } const int max=readnum(is); if(max==readerr) { std::cerr << "could not read max\n"; return 7; } if(max<=0 || max>=65536) { std::cerr << "max <= 0 || max>=65536\n"; return 8; } skipws(is); // get cip variables if(comment.size()) title=comment; t=getenv("CIP_TITLE"); if(t) title=t; t=getenv("CIP_PROMPT"); if(t) prompt=t; t=getenv("CIP_X"); if(t) x=strtol(t,0,0); t=getenv("CIP_Y"); if(t) y=strtol(t,0,0); // title and header max length const int maxlength=32; if(title.size()>maxlength) title.erase(maxlength); if(prompt.size()>maxlength) prompt.erase(maxlength); // print cip header std::cout << "\n" "\n" " " << escape(title) << "\n" " " << escape(prompt) << "\n" " " << x << "\n" " " << y << "\n" " " << width << "\n" " " << height << "\n" " 2\n" " " << std::flush; // convert image int z=0; unsigned char acc=0; while(is && z255)?2:1, is); if(pix==readerr) { std::cerr << "error while reading pixels\n"; break; } const double val=static_cast(pix)/static_cast(max); if(val<=0.25) acc|=128+64; else if(val<=0.5) acc|=128; else if(val<=0.75) acc|=64; if((z&3) == 3) { printf("%02X", acc); acc=0; } else acc>>=2; ++z; } if((z&3) != 0) { while((z&3) != 3) acc>>=2, ++z; printf("%02X", acc); } // print footer std::cout << "\n" "" << std::endl; return 0; }