Hi,

currently, there's only SplashBitmap able to export to PBM/PGM/PPM.
I just created a PNMWriter to provide generic export capabilities, even 
when not using Splash(Bitmap) directly.
References:
- PBM: http://netpbm.sourceforge.net/doc/pbm.html
- PGM: http://netpbm.sourceforge.net/doc/pgm.html
- PPM: http://netpbm.sourceforge.net/doc/ppm.html

Attached there's a small patch for pdftoppm to use the new export 
filter, instead of the own SplashBitmap PNM exporting method.

-- 
Pino Toscano
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c61b76a..e59e34c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -228,6 +228,7 @@ set(poppler_SRCS
   goo/TiffWriter.cc
   goo/JpegWriter.cc
   goo/ImgWriter.cc
+  goo/PNMWriter.cc
   goo/gstrtod.cc
   fofi/FoFiBase.cc
   fofi/FoFiEncodings.cc
@@ -465,6 +466,7 @@ if(ENABLE_XPDF_HEADERS)
     goo/gfile.h
     goo/FixedPoint.h
     goo/ImgWriter.h
+    goo/PNMWriter.h
     goo/GooLikely.h
     goo/gstrtod.h
     DESTINATION include/poppler/goo)
diff --git a/goo/Makefile.am b/goo/Makefile.am
index be791ee..2bd348e 100644
--- a/goo/Makefile.am
+++ b/goo/Makefile.am
@@ -16,6 +16,7 @@ poppler_goo_include_HEADERS =			\
 	PNGWriter.h				\
 	JpegWriter.h				\
 	TiffWriter.h				\
+	PNMWriter.h				\
 	ImgWriter.h				\
 	GooLikely.h				\
 	gstrtod.h
@@ -42,5 +43,6 @@ libgoo_la_SOURCES =				\
 	PNGWriter.cc				\
 	JpegWriter.cc				\
 	TiffWriter.cc				\
+	PNMWriter.cc				\
 	ImgWriter.cc				\
 	gstrtod.cc
diff --git a/goo/PNMWriter.cc b/goo/PNMWriter.cc
new file mode 100644
index 0000000..ec8609a
--- /dev/null
+++ b/goo/PNMWriter.cc
@@ -0,0 +1,117 @@
+//========================================================================
+//
+// PNMWriter.cc
+//
+// This file is licensed under the GPLv2 or later
+//
+// Copyright (C) 2010 Pino Toscano <[email protected]>
+//
+//========================================================================
+
+#include "PNMWriter.h"
+
+#include <vector>
+
+PNMWriter::PNMWriter(OutFormat formatArg)
+  : format(formatArg)
+  , file(0)
+  , imgWidth(0)
+  , rowSize(0)
+{
+}
+
+PNMWriter::~PNMWriter()
+{
+}
+
+bool PNMWriter::init(FILE *f, int width, int height, int /*hDPI*/, int /*vDPI*/)
+{
+  file = f;
+  imgWidth = width;
+
+  switch (format)
+  {
+    case PNMWriter::PBM:
+      fprintf(file, "P4\n%d %d\n", width, height);
+      rowSize = (width + 7) >> 3;
+      break;
+    case PNMWriter::PGM:
+      fprintf(file, "P5\n%d %d\n255\n", width, height);
+      rowSize = width;
+      break;
+    case PNMWriter::PPM:
+      fprintf(file, "P6\n%d %d\n255\n", width, height);
+      rowSize = width * 3;
+      break;
+  }
+
+  return true;
+}
+
+bool PNMWriter::writePointers(unsigned char **rowPointers, int rowCount)
+{
+  bool ret = true;
+  for (int i = 0; ret && (i < rowCount); ++i) {
+    ret = writeRow(&(rowPointers[i]));
+  }
+
+  return ret;
+}
+
+bool PNMWriter::writeRow(unsigned char **row)
+{
+  std::vector<unsigned char> newRow;
+  unsigned char *rowPtr = *row;
+  unsigned char *p = *row;
+
+  switch (format)
+  {
+    case PNMWriter::PBM:
+      newRow.resize(rowSize, 0);
+      rowPtr = &newRow[0];
+      for (int i = 0; i < imgWidth; ++i) {
+        unsigned char pixel = p[0];
+        if (p[0] == p[1] && p[1] == p[2]) {
+          // gray, stored already
+        } else {
+          pixel = static_cast<unsigned char>((p[0] * 11 + p[1] * 16 + p[2] * 5) / 32);
+        }
+        if (pixel < 0x7F) {
+          *(rowPtr + (i >> 3)) |= (1 << (i & 7));
+        }
+        p += 3;
+      }
+      break;
+    case PNMWriter::PGM:
+      newRow.resize(rowSize, 0);
+      rowPtr = &newRow[0];
+      for (int i = 0; i < imgWidth; ++i) {
+        if (p[0] == p[1] && p[1] == p[2]) {
+          // gray, store directly
+          newRow[i] = p[0];
+        } else {
+          // calculate the gray value
+          newRow[i] = static_cast<unsigned char>((p[0] * 11 + p[1] * 16 + p[2] * 5) / 32);
+        }
+        p += 3;
+      }
+      break;
+    case PNMWriter::PPM:
+      break;
+  }
+
+  if (int(fwrite(rowPtr, 1, rowSize, file)) < rowSize) {
+    return false;
+  }
+
+  return true;
+}
+
+bool PNMWriter::close()
+{
+  file = 0;
+  imgWidth = 0;
+  rowSize = 0;
+
+  return true;
+}
diff --git a/goo/PNMWriter.h b/goo/PNMWriter.h
new file mode 100644
index 0000000..afcc189
--- /dev/null
+++ b/goo/PNMWriter.h
@@ -0,0 +1,38 @@
+//========================================================================
+//
+// PNMWriter.h
+//
+// This file is licensed under the GPLv2 or later
+//
+// Copyright (C) 2010 Pino Toscano <[email protected]>
+//
+//========================================================================
+
+#ifndef PNMWRITER_H
+#define PNMWRITER_H
+
+#include "ImgWriter.h"
+
+class PNMWriter : public ImgWriter
+{
+  public:
+    enum OutFormat { PBM, PGM, PPM };
+
+    PNMWriter(OutFormat formatArg);
+    ~PNMWriter();
+
+    bool init(FILE *f, int width, int height, int hDPI, int vDPI);
+
+    bool writePointers(unsigned char **rowPointers, int rowCount);
+    bool writeRow(unsigned char **row);
+
+    bool close();
+
+  private:
+    const OutFormat format;
+    FILE *file;
+    int imgWidth;
+    int rowSize;
+};
+
+#endif
diff --git a/splash/SplashBitmap.cc b/splash/SplashBitmap.cc
index 7c26e54..60684d4 100644
--- a/splash/SplashBitmap.cc
+++ b/splash/SplashBitmap.cc
@@ -41,6 +41,7 @@
 #include "goo/JpegWriter.h"
 #include "goo/PNGWriter.h"
 #include "goo/TiffWriter.h"
+#include "goo/PNMWriter.h"
 #include "goo/ImgWriter.h"
 
 //------------------------------------------------------------------------
@@ -317,6 +318,32 @@ SplashError SplashBitmap::writeImgFile(SplashImageFileFormat format, FILE *f, in
       break;
     #endif
 
+    case splashFormatPnm: {
+      PNMWriter::OutFormat fmt = PNMWriter::PPM;
+      switch (mode) {
+        case splashModeMono1:
+          fmt = PNMWriter::PBM;
+          break;
+        case splashModeMono8:
+          fmt = PNMWriter::PGM;
+          break;
+        case splashModeRGB8:
+        case splashModeBGR8:
+        case splashModeXBGR8:
+          fmt = PNMWriter::PPM;
+          break;
+#if SPLASH_CMYK
+        case splashModeCMYK8:
+          // PNM doesn't support CMYK
+          error(-1, "unsupported SplashBitmap mode");
+          return splashErrGeneric;
+          break;
+#endif
+      }
+      writer = new PNMWriter(fmt);
+      break;
+    }
+
     default:
       // Not the greatest error message, but users of this function should
       // have already checked whether their desired format is compiled in.
diff --git a/splash/SplashTypes.h b/splash/SplashTypes.h
index 273c32d..fea15bf 100644
--- a/splash/SplashTypes.h
+++ b/splash/SplashTypes.h
@@ -162,7 +162,8 @@ typedef int SplashError;
 enum SplashImageFileFormat {
   splashFormatJpeg,
   splashFormatPng,
-  splashFormatTiff
+  splashFormatTiff,
+  splashFormatPnm
 };
 
 #endif
diff --git a/utils/pdftoppm.cc b/utils/pdftoppm.cc
index 8a7c702..b9ec5dc 100644
--- a/utils/pdftoppm.cc
+++ b/utils/pdftoppm.cc
@@ -194,7 +194,7 @@ static void savePageSlice(PDFDoc *doc,
     } else if (tiff) {
       bitmap->writeImgFile(splashFormatTiff, ppmFile, x_resolution, y_resolution, TiffCompressionStr);
     } else {
-      bitmap->writePNMFile(ppmFile);
+      bitmap->writeImgFile(splashFormatPnm, ppmFile, x_resolution, y_resolution);
     }
   } else {
 #ifdef _WIN32
@@ -208,7 +208,7 @@ static void savePageSlice(PDFDoc *doc,
     } else if (tiff) {
       bitmap->writeImgFile(splashFormatTiff, stdout, x_resolution, y_resolution, TiffCompressionStr);
     } else {
-      bitmap->writePNMFile(stdout);
+      bitmap->writeImgFile(splashFormatPnm, stdout, x_resolution, y_resolution);
     }
   }
 }

Attachment: signature.asc
Description: This is a digitally signed message part.

_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler

Reply via email to