32 #ifndef SPL_pnmCodec_hpp
33 #define SPL_pnmCodec_hpp
39 #include <SPL/config.hpp>
58 pnmMagicTxtPbm = 0x5031,
59 pnmMagicTxtPgm = 0x5032,
60 pnmMagicTxtPpm = 0x5033,
61 pnmMagicBinPbm = 0x5034,
62 pnmMagicBinPgm = 0x5035,
63 pnmMagicBinPpm = 0x5036,
83 const int pnmMaxLineLen = 80;
107 PnmType pnmGetType(PnmMagic magic);
112 PnmFmt pnmGetFmt(PnmMagic magic);
117 int pnmMaxValToPrec(
int maxVal);
122 int pnmGetNumComps(PnmType type);
124 int pnmMinVal(
bool sgnd,
int maxVal);
125 int pnmMaxVal(
bool sgnd,
int maxVal);
131 inline long pnmOnes(
int n)
133 return (1UL << n) - 1;
137 T pnmClipVal(T x, T minVal, T maxVal)
139 assert(minVal <= maxVal);
142 }
else if (x > maxVal) {
155 int pnmGetHeader(std::istream& in, PnmHeader& header);
160 int pnmPutHeader(std::ostream& out, PnmHeader& header);
165 int pnmGetChar(std::istream& in);
170 int pnmGetTxtBit(std::istream& in);
175 long pnmGetTxtInt(std::istream& in,
bool sgnd,
int& status);
180 long pnmGetBinInt(std::istream& in,
int wordSize,
bool sgnd,
int& status);
185 int pnmPutBinInt(std::ostream& out,
int wordSize,
bool sgnd,
long val);
194 template <
class GetData>
195 int pnmEncode(std::ostream& outStream,
int width,
int height,
int numComps,
196 int maxVal,
bool sgnd, GetData& getData,
bool binaryFormat)
201 header.magic = binaryFormat ? pnmMagicBinPbm : pnmMagicTxtPbm;
203 header.magic = binaryFormat ? pnmMagicBinPgm : pnmMagicTxtPgm;
205 }
else if (numComps == 3) {
206 header.magic = binaryFormat ? pnmMagicBinPpm : pnmMagicTxtPpm;
210 header.width = width;
211 header.height = height;
212 header.maxVal = maxVal;
215 if (pnmPutHeader(outStream, header)) {
218 if (putData(outStream, header, getData)) {
227 template <
class GetData>
228 int putData(std::ostream& out, PnmHeader& header, GetData& getData)
230 int prec = pnmMaxValToPrec(header.maxVal);
231 int fmt = pnmGetFmt(header.magic);
232 PnmType type = pnmGetType(header.magic);
233 int numComps = pnmGetNumComps(type);
236 for (
int y = header.height - 1; y >= 0; --y) {
237 if (fmt == pnmFmtBin) {
238 if (type == pnmTypePbm) {
241 for (
int x = 0; x < header.width; ++x) {
243 val = (val << 1) | (b & 1);
246 if (!out.put(static_cast<unsigned char>(val))) {
254 assert(numBits <= 8);
256 if (!out.put(static_cast<unsigned char>(val))) {
261 for (
int x = 0; x < header.width; ++x) {
262 for (
int c = 0; c < numComps; ++c) {
264 long val = getData();
265 if (pnmPutBinInt(out, prec, header.sgnd, val)) {
272 for (
int x = 0; x < header.width; ++x) {
273 for (
int c = 0; c < numComps; ++c) {
275 long val = getData();
276 std::ostringstream buf;
278 int n = buf.str().length();
279 if (lineLen && lineLen + n + 2 > pnmMaxLineLen) {
283 if (lineLen && prec > 1) {
292 if (fmt == pnmFmtTxt && lineLen) {
308 template <
class Initialize>
309 int pnmDecode(std::istream& inStream, Initialize& initialize)
312 if (pnmGetHeader(inStream, header)) {
315 #if defined(PNM_DEBUG)
317 <<
"magic " << std::hex << header.magic <<
" "
318 << std::dec <<
" width " << header.width <<
" "
319 <<
"height " << header.height <<
" "
320 <<
"maxVal " << header.maxVal <<
"\n"
323 int numComps = pnmGetNumComps(pnmGetType(header.magic));
324 typename Initialize::PutData putData;
325 initialize(header.width, header.height, numComps, header.maxVal,
326 header.sgnd, putData);
327 if (getData(inStream, header, putData)) {
336 template <
class PutData>
337 int getData(std::istream& in, PnmHeader& header, PutData& putData)
339 PnmType type = pnmGetType(header.magic);
340 PnmFmt fmt = pnmGetFmt(header.magic);
341 int numComps = pnmGetNumComps(type);
342 int prec = pnmMaxValToPrec(header.maxVal);
344 int minVal = pnmMinVal(header.sgnd, header.maxVal);
345 int maxVal = pnmMaxVal(header.sgnd, header.maxVal);
347 for (
int y = header.height - 1; y >= 0; --y) {
348 if (type == pnmTypePbm) {
349 if (fmt == pnmFmtBin) {
350 for (
int x = 0; x < header.width;) {
352 if ((c = in.get()) == std::char_traits<char>::eof()) {
356 while (n > 0 && x < header.width) {
358 putData((c >> 7) & 1);
365 for (
int x = 0; x < header.width; ++x) {
367 if ((val = pnmGetTxtBit(in)) < 0) {
375 if (fmt == pnmFmtBin) {
376 for (
int x = 0; x < header.width; ++x) {
377 for (
int c = 0; c < numComps; ++c) {
380 if (val = pnmGetBinInt(in, prec, header.sgnd, status),
386 if (val < minVal || val > maxVal) {
387 std::cerr <<
"warning: clipping out of range sample value\n";
389 val = pnmClipVal<int>(val, minVal, maxVal);
391 assert(val >= minVal && val <= maxVal);
398 for (
int x = 0; x < header.width; ++x) {
399 for (
int c = 0; c < numComps; ++c) {
402 if (val = pnmGetTxtInt(in, header.sgnd, status), status) {
407 if (val < minVal || val > maxVal) {
408 std::cerr <<
"warning: clipping out of range sample value\n";
410 val = pnmClipVal<int>(val, minVal, maxVal);
412 assert(val >= minVal && val <= maxVal);
Definition: Arcball.hpp:48