]> git.cworth.org Git - apitrace/commitdiff
image: Support reading PFM images.
authorJosé Fonseca <jfonseca@vmware.com>
Thu, 12 Sep 2013 16:25:04 +0000 (17:25 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Thu, 12 Sep 2013 16:25:04 +0000 (17:25 +0100)
gui/retracer.cpp
image/image.hpp
image/image_pnm.cpp

index cb0bad35abcfb5284a79ee971a7be9f679a01c28..b42446bdd6af2ca064f3b522466dc3b778105cc2 100644 (file)
@@ -395,9 +395,7 @@ void Retracer::run()
              */
 
             while (!io.atEnd()) {
-                unsigned channels = 0;
-                unsigned width = 0;
-                unsigned height = 0;
+                image::PNMInfo info;
 
                 char header[512];
                 qint64 headerSize = 0;
@@ -414,14 +412,19 @@ void Retracer::run()
                     headerSize += headerRead;
                 }
 
-                const char *headerEnd = image::readPNMHeader(header, headerSize, &channels, &width, &height);
+                const char *headerEnd = image::readPNMHeader(header, headerSize, info);
 
                 // if invalid PNM header was encountered, ...
-                if (header == headerEnd) {
+                if (headerEnd == NULL ||
+                    info.channelType != image::TYPE_UNORM8) {
                     qDebug() << "error: invalid snapshot stream encountered";
                     break;
                 }
 
+                unsigned channels = info.channels;
+                unsigned width = info.width;
+                unsigned height = info.height;
+
                 // qDebug() << "channels: " << channels << ", width: " << width << ", height: " << height";
 
                 QImage snapshot = QImage(width, height, channels == 1 ? QImage::Format_Mono : QImage::Format_RGB888);
index 1b21acd1e2e5a51d004b6df605ed7a68cde520ae..857e0621c1386e5d9a72eb9dba6e9ff467a35322 100644 (file)
@@ -126,8 +126,20 @@ readPNG(std::istream &is);
 Image *
 readPNG(const char *filename);
 
+
+struct PNMInfo
+{
+    unsigned width;
+    unsigned height;
+    unsigned channels;
+    ChannelType channelType;
+};
+
 const char *
-readPNMHeader(const char *buffer, size_t size, unsigned *channels, unsigned *width, unsigned *height);
+readPNMHeader(const char *buffer, size_t size, PNMInfo &info);
+
+Image *
+readPNM(const char *buffer, size_t bufferSize);
 
 
 } /* namespace image */
index a0638dc59356c58840b03a539e80a7dead4049ba..df88c58cb50a17b1d4e330fb8422b90b63805d55 100644 (file)
@@ -67,6 +67,8 @@ Image::writePNM(std::ostream &os, const char *comment) const
             outChannels = 3;
         }
         break;
+    default:
+        assert(0);
     }
 
     os << identifier << "\n";
@@ -189,24 +191,49 @@ Image::writePNM(const char *filename, const char *comment) const
 }
 
 
+/**
+ * Parse PNM header.
+ *
+ * Returns pointer to data start, or NULL on failure.
+ */
 const char *
-readPNMHeader(const char *buffer, size_t bufferSize, unsigned *channels, unsigned *width, unsigned *height)
+readPNMHeader(const char *buffer, size_t bufferSize, PNMInfo &info)
 {
-    *channels = 0;
-    *width = 0;
-    *height = 0;
+    info.channels = 0;
+    info.width = 0;
+    info.height = 0;
 
     const char *currentBuffer = buffer;
     const char *nextBuffer;
 
     // parse number of channels
-    int scannedChannels = sscanf(currentBuffer, "P%d\n", channels);
+    char c;
+    int scannedChannels = sscanf(currentBuffer, "P%c\n", &c);
     if (scannedChannels != 1) { // validate scanning of channels
         // invalid channel line
-        return buffer;
+        return NULL;
     }
     // convert channel token to number of channels
-    *channels = (*channels == 5) ? 1 : 3;
+    switch (c) {
+    case '5':
+        info.channels = 1;
+        info.channelType = TYPE_UNORM8;
+        break;
+    case '6':
+        info.channels = 3;
+        info.channelType = TYPE_UNORM8;
+        break;
+    case 'f':
+        info.channels = 1;
+        info.channelType = TYPE_FLOAT;
+        break;
+    case 'F':
+        info.channels = 3;
+        info.channelType = TYPE_FLOAT;
+        break;
+    default:
+        return NULL;
+    }
 
     // advance past channel line
     nextBuffer = (const char *) memchr((const void *) currentBuffer, '\n', bufferSize) + 1;
@@ -222,10 +249,10 @@ readPNMHeader(const char *buffer, size_t bufferSize, unsigned *channels, unsigne
     }
 
     // parse dimensions of image
-    int scannedDimensions = sscanf(currentBuffer, "%d %d\n", width, height);
+    int scannedDimensions = sscanf(currentBuffer, "%u %u\n", &info.width, &info.height);
     if (scannedDimensions != 2) { // validate scanning of dimensions
         // invalid dimension line
-        return buffer;
+        return NULL;
     }
 
     // advance past dimension line
@@ -233,11 +260,40 @@ readPNMHeader(const char *buffer, size_t bufferSize, unsigned *channels, unsigne
     bufferSize -= nextBuffer - currentBuffer;
     currentBuffer = nextBuffer;
 
-    // skip over "255\n" at end of header
-    nextBuffer = (const char *) memchr((const void *) currentBuffer, '\n', bufferSize) + 1;
+    if (info.channelType == TYPE_UNORM8) {
+        // skip over "255\n" at end of header
+        nextBuffer = (const char *) memchr((const void *) currentBuffer, '\n', bufferSize) + 1;
+    }
 
     // return start of image data
     return nextBuffer;
 }
 
+
+Image *
+readPNM(const char *buffer, size_t bufferSize)
+{
+    PNMInfo info;
+
+    const char *headerEnd = readPNMHeader(buffer, bufferSize, info);
+
+    // if invalid PNM header was encountered, ...
+    if (headerEnd == NULL) {
+        std::cerr << "error: invalid PNM header";
+        return NULL;
+    }
+
+    Image *image = new Image(info.width, info.height, info.channels, false, info.channelType);
+
+    size_t rowBytes = info.width * image->bytesPerPixel;
+    for (unsigned char *row = image->start(); row != image->end(); row += image->stride()) {
+        memcpy(row, headerEnd, rowBytes);
+        headerEnd += rowBytes;
+    }
+
+    return image;
+}
+
+
+
 } /* namespace image */