changeset 2092:614b161c0aa5

Initial support for reading PPM/PGM.
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 28 Feb 2019 12:30:21 +0200
parents 3b3acb6b4ba0
children d17512dbb4ef
files tools/libgfx.c tools/libgfx.h
diffstat 2 files changed, 103 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/tools/libgfx.c	Thu Feb 28 12:18:27 2019 +0200
+++ b/tools/libgfx.c	Thu Feb 28 12:30:21 2019 +0200
@@ -106,6 +106,7 @@
 {
     switch (format)
     {
+        case DM_COLFMT_GRAYSCALE : return 1;
         case DM_COLFMT_PALETTE   : return 1;
         case DM_COLFMT_RGB       : return 3;
         case DM_COLFMT_RGBA      : return 4;
@@ -243,6 +244,7 @@
             switch (spec->format)
             {
                 case DM_COLFMT_PALETTE:
+                case DM_COLFMT_GRAYSCALE:
                     for (xscale = 0; xscale < spec->scaleX; xscale++)
                         *ptr1++ = c;
                     break;
@@ -511,10 +513,32 @@
 int dmWritePPMImage(DMResource *fp, const DMImage *img, const DMImageConvSpec *spec)
 {
     DMImageConvSpec tmpSpec;
+    char *tmpFmt;
+
+    memcpy(&tmpSpec, spec, sizeof(DMImageConvSpec));
+
+    switch (spec->format)
+    {
+        case DM_COLFMT_RGB:
+        case DM_COLFMT_RGBA:
+        case DM_COLFMT_PALETTE:
+            tmpSpec.format = DM_COLFMT_RGB;
+            tmpFmt = "6";
+            break;
+
+        case DM_COLFMT_GRAYSCALE:
+            tmpFmt = "5";
+            break;
+
+        default:
+            return dmError(DMERR_NOT_SUPPORTED,
+                "PPM: Not a supported color format for PPM/PGM format image.\n");
+    }
 
     // Write PPM header
     char *tmp = dm_strdup_printf(
-        "P6\n%d %d\n255\n",
+        "P%s\n%d %d\n255\n",
+        tmpFmt,
         img->width * spec->scaleX,
         img->height * spec->scaleY);
 
@@ -525,12 +549,84 @@
     dmFree(tmp);
 
     // Write image data
-    memcpy(&tmpSpec, spec, sizeof(DMImageConvSpec));
-    tmpSpec.format = DM_COLFMT_RGB;
     return dmWriteImageData(img, (void *) fp, dmWritePPMRow, &tmpSpec);
 }
 
 
+int dmReadPPMImage(DMResource *fp, DMImage **pimg)
+{
+    DMImage *img = NULL;
+    unsigned int width, height;
+    int itype, res = DMERR_OK;
+    char hdr1[8], hdr2[32], hdr3[16];
+
+    // Read PPM header
+    if (dmfgets(hdr1, sizeof(hdr1), fp) == NULL ||
+        dmfgets(hdr2, sizeof(hdr2), fp) == NULL ||
+        dmfgets(hdr3, sizeof(hdr3), fp) == NULL)
+    {
+        res = dmError(DMERR_FREAD,
+            "PPM: Could not read image header data.\n");
+        goto error;
+    }
+
+    if (hdr1[0] != 'P' || !isdigit(hdr1[1]) ||
+        !isdigit(hdr2[0]) || !isdigit(hdr3[0]))
+    {
+        res = dmError(DMERR_NOT_SUPPORTED,
+            "PPM: Not a supported PPM/PGM format image.\n");
+        goto error;
+    }
+
+    switch (hdr1[1])
+    {
+        case '6': itype = DM_COLFMT_RGB; break;
+        case '5': itype = DM_COLFMT_GRAYSCALE; break;
+        default:
+            res = dmError(DMERR_NOT_SUPPORTED,
+                "PPM: Unsupported PPM/PGM subtype.\n");
+            goto error;
+    }
+
+    if (sscanf(hdr2, "%u %u", &width, &height) != 2)
+    {
+        res = dmError(DMERR_INVALID_DATA,
+            "PPM: Invalid PPM/PGM image dimensions.\n");
+        goto error;
+    }
+
+    if ((*pimg = img = dmImageAlloc(width, height, itype, -1)) == NULL)
+    {
+        res = dmError(DMERR_MALLOC,
+            "PPM: Could not allocate image data.\n");
+        goto error;
+    }
+
+    if (dmf_read_str(fp, img->data, img->size))
+    {
+        res = dmError(DMERR_FREAD,
+            "PPM: Could not read image data.\n");
+        goto error;
+    }
+
+error:
+
+    return res;
+}
+
+
+static int fmtProbePPM(const Uint8 *buf, const size_t len)
+{
+    if (len > 32 &&
+        buf[0] == 'P' &&
+        buf[1] == '5' &&
+        buf[2] == 0x0a && isdigit(buf[3]))
+        return DM_PROBE_SCORE_MAX;
+
+    return DM_PROBE_SCORE_FALSE;
+}
+
+
 #ifdef DM_USE_LIBPNG
 static int fmtProbePNG(const Uint8 *buf, const size_t len)
 {
@@ -2518,8 +2614,8 @@
 #endif
     {
         "ppm", "Portable PixMap",
-        DM_IMGFMT_PPM, DM_FMT_WR,
-        NULL, NULL, dmWritePPMImage,
+        DM_IMGFMT_PPM, DM_FMT_RDWR,
+        fmtProbePPM, dmReadPPMImage, dmWritePPMImage,
     },
     {
         "pcx", "Z-Soft Paintbrush",
--- a/tools/libgfx.h	Thu Feb 28 12:18:27 2019 +0200
+++ b/tools/libgfx.h	Thu Feb 28 12:30:21 2019 +0200
@@ -34,6 +34,7 @@
 enum
 {
     DM_COLFMT_PALETTE,
+    DM_COLFMT_GRAYSCALE,
     DM_COLFMT_RGB,
     DM_COLFMT_RGBA,
 };
@@ -135,6 +136,7 @@
 int dmWriteRAWImage(DMResource *fp, const DMImage *img, const DMImageConvSpec *spec);
 
 int dmWritePPMImage(DMResource *fp, const DMImage *img, const DMImageConvSpec *spec);
+int dmReadPPMImage(DMResource *fp, DMImage **pimg);
 
 #ifdef DM_USE_LIBPNG
 int dmWritePNGImage(DMResource *fp, const DMImage *img, const DMImageConvSpec *spec);