about summary refs log tree commit diff
path: root/converter/pgm
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2015-01-20 03:49:14 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2015-01-20 03:49:14 +0000
commitc0162a145444aca87569ea24e0f6210281595183 (patch)
tree4a19c44a3c41f08267ab5624370d62a966cba65e /converter/pgm
parent01e256d86d0bd554ac34d847dfe70ae615e99537 (diff)
downloadnetpbm-mirror-c0162a145444aca87569ea24e0f6210281595183.tar.gz
netpbm-mirror-c0162a145444aca87569ea24e0f6210281595183.tar.xz
netpbm-mirror-c0162a145444aca87569ea24e0f6210281595183.zip
Add st4topgm, pgmtost4
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@2392 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'converter/pgm')
-rw-r--r--converter/pgm/Makefile4
-rw-r--r--converter/pgm/pgmtost4.c104
-rw-r--r--converter/pgm/st4topgm.c260
3 files changed, 366 insertions, 2 deletions
diff --git a/converter/pgm/Makefile b/converter/pgm/Makefile
index 2668a2a0..f7ff341e 100644
--- a/converter/pgm/Makefile
+++ b/converter/pgm/Makefile
@@ -8,8 +8,8 @@ VPATH=.:$(SRCDIR)/$(SUBDIR)
 include $(BUILDDIR)/config.mk
 
 PORTBINARIES =	asciitopgm bioradtopgm fstopgm hipstopgm \
-		lispmtopgm pgmtofs pgmtolispm pgmtopgm pgmtosbig \
-	        psidtopgm spottopgm sbigtopgm
+		lispmtopgm pgmtofs pgmtolispm pgmtopgm pgmtosbig pgmtost4 \
+	        psidtopgm spottopgm sbigtopgm st4topgm
 MATHBINARIES =	rawtopgm
 BINARIES =	$(PORTBINARIES) $(MATHBINARIES)
 
diff --git a/converter/pgm/pgmtost4.c b/converter/pgm/pgmtost4.c
new file mode 100644
index 00000000..fa101ac9
--- /dev/null
+++ b/converter/pgm/pgmtost4.c
@@ -0,0 +1,104 @@
+/*=============================================================================
+                                 pgmtost4
+===============================================================================
+
+  This program converts from PGM to a simple subset of SBIG ST-4.
+
+  By Bryan Henderson January 19, 2015.
+
+  Contributed to the public domain by its author.
+=============================================================================*/
+#include <string.h>
+
+#include "pm.h"
+#include "nstring.h"
+#include "pam.h"
+
+
+
+static unsigned int const st4Height = 165;
+static unsigned int const st4Width  = 192;
+static unsigned int const st4Maxval = 255;
+
+
+
+static void
+writeSt4Footer(FILE * const ofP) {
+
+    const char * const comment = "This was created by Pgmtost4";
+    char buffer[192];
+
+    memset(buffer, ' ', sizeof(buffer));  /* initial value */
+
+    buffer[0] = 'v';
+
+    memcpy(&buffer[  0], "v", 1);
+    memcpy(&buffer[  1], comment, strlen(comment));
+    memcpy(&buffer[ 79], "         7", 10);
+    memcpy(&buffer[ 89], "         8", 10);
+    memcpy(&buffer[ 99], "         9", 10);
+    memcpy(&buffer[109], "        10", 10);
+
+    fwrite(buffer, 1, sizeof(buffer), ofP);
+}
+
+
+
+int
+main(int argc, const char * argv[]) {
+
+    FILE * ifP;
+    tuple * tuplerow;
+    struct pam inpam;
+    unsigned int row;
+    const char * inputFile;
+
+    pm_proginit(&argc, argv);
+
+    if (argc-1 < 1)
+        inputFile = "-";
+    else {
+        inputFile = argv[1];
+
+        if (argc-1 > 2)
+            pm_error("Too many arguments.  The only argument is the optional "
+                     "input file name");
+    }
+
+    ifP = pm_openr(inputFile);
+
+    pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type));
+
+    if (inpam.height != st4Height)
+        pm_error("Image is wrong height for ST-4 SBIG: %u pixels.  "
+                 "Must be %u", inpam.height, st4Height);
+
+    if (inpam.width != st4Width)
+        pm_error("Image is wrong width for ST-4 SBIG: %u pixels.  "
+                 "Must be %u", inpam.width, st4Width);
+    
+    /* Really, we should just scale to maxval 255.  There are library routines
+       for that, but we're too lazy even for that, since nobody is really
+       going to use this program.
+    */
+    if (inpam.maxval != st4Maxval)
+        pm_error("Image is wrong maxval for ST-4 SBIG: %u.  "
+                 "Must be %u", (unsigned)inpam.maxval, st4Maxval);
+
+    tuplerow = pnm_allocpamrow(&inpam);
+
+    for (row = 0; row < inpam.height; ++row) {
+        unsigned int col;
+
+        pnm_readpamrow(&inpam, tuplerow);
+
+        for (col = 0; col < inpam.width; ++col)
+            pm_writechar(stdout, (char)tuplerow[col][0]);
+    }
+
+    writeSt4Footer(stdout);
+
+    pm_close(ifP);
+
+    return 0;
+}
diff --git a/converter/pgm/st4topgm.c b/converter/pgm/st4topgm.c
new file mode 100644
index 00000000..e763852c
--- /dev/null
+++ b/converter/pgm/st4topgm.c
@@ -0,0 +1,260 @@
+/*=============================================================================
+                               st4topgm
+===============================================================================
+
+  Convert an SBIG ST-4 image (not to be confused with the more sophisticated
+  SBIG format that every other SBIG camera produces) to PGM.
+
+  By Bryan Henderson January 2015.
+
+  Contributed to the public domain by its author.
+
+  This program was intended to substitute for the program of the same name in
+  the Debian version of Netpbm, by Justin Pryzby <justinpryzby@users.sf.net>
+  in December 2003.
+
+=============================================================================*/
+#include <string.h>
+
+#include "pm_config.h"
+#include "pm_c_util.h"
+#include "pm.h"
+#include "pam.h"
+
+
+
+static unsigned int const st4Height = 165;
+static unsigned int const st4Width  = 192;
+static unsigned int const st4Maxval = 255;
+
+
+
+static void
+validateFileSize(FILE * const ifP) {
+/*----------------------------------------------------------------------------
+   Abort program if *ifP is not the proper size for an ST-4 SBIG file.
+
+   Don't change file position.
+-----------------------------------------------------------------------------*/
+    pm_filepos const st4FileSize = (st4Height+1) * st4Width;
+
+    pm_filepos oldFilePos;
+    pm_filepos endFilePos;
+
+    pm_tell2(ifP, &oldFilePos, sizeof(endFilePos));
+
+    fseek(ifP, 0, SEEK_END);
+
+    pm_tell2(ifP, &endFilePos, sizeof(endFilePos));
+
+    pm_seek2(ifP, &oldFilePos, sizeof(oldFilePos));
+
+    if (endFilePos != st4FileSize)
+        pm_error("File is the wrong size for an ST-4 SBIG file.  "
+                 "It is %u bytes; it should be %u bytes",
+                 (unsigned)endFilePos, (unsigned)st4FileSize);
+}
+
+
+static void
+writeRaster(FILE *       const ifP,
+            struct pam * const pamP) {
+
+    tuple * tuplerow;
+    unsigned int row;
+
+    tuplerow = pnm_allocpamrow(pamP);
+
+    for (row = 0; row < st4Height; ++row) {
+        unsigned int col;
+
+        for (col = 0; col < st4Width; ++col) {
+            char c;
+
+            pm_readchar(ifP, &c);
+
+            tuplerow[col][0] = (unsigned char)c;
+        }
+        pnm_writepamrow(pamP, tuplerow);
+    }
+
+    pnm_freepamrow(tuplerow);
+}
+
+
+
+struct St4Footer {
+/*----------------------------------------------------------------------------
+   The information in an ST-4 SBIG footer.
+-----------------------------------------------------------------------------*/
+    /* Note that numerical information is in decimal text, because we're lazy.
+    */
+
+    char comment[78+1];
+    char exposureTime[10+1];
+    char focalLength[10+1];
+    char apertureArea[10+1];
+    char calibrationFactor[10+1];
+};
+
+
+
+static void
+stripTrailing(char * const arg) {
+
+    if (strlen(arg) > 0) {
+        char * p;
+        for (p = arg + strlen(arg); p > arg && *(p-1) == ' '; --p);
+
+        *p = '\0';
+    }
+}
+
+
+
+static void
+stripLeading(char * const arg) {
+
+    const char * p;
+
+    for (p = &arg[0]; *p == ' '; ++p);
+
+    if (p > arg)
+        memmove(arg, p, strlen(p) + 1);
+}
+
+
+
+static void
+readFooter(FILE *             const ifP,
+           struct St4Footer * const footerP) {
+/*----------------------------------------------------------------------------
+   Read the footer of the ST-4 image from *ifP, assuming *ifP is positioned
+   to the footer.
+
+   Return its contents as *footerP.
+-----------------------------------------------------------------------------*/
+    char buffer[192];
+    size_t bytesReadCt;
+
+    /* The footer is laid out as follows.
+
+       off len description
+       --- --- -----------
+       000   1 Signature: 'v'
+       001  78 Freeform comment
+       079  10 Exposure time in 1/100s of a second
+       089  10 Focal length in inches
+       099  10 Aperture area in square inches
+       109  10 Calibration factor
+       119  73 Reserved
+
+       Note tha the footer is the same length as a raster row.
+    */
+
+    bytesReadCt = fread(buffer, 1, sizeof(buffer), ifP);
+
+    if (bytesReadCt != 192)
+        pm_error("Failed to read footer of image");
+
+    if (buffer[0] != 'v')
+        pm_error("Input is not an ST-4 file.  We know because the "
+                 "signature byte (first byte of the footer) is not 'v'");
+
+    buffer[191] = '\0';
+    memmove(footerP->comment, &buffer[1], 78);
+    footerP->comment[78] = '\0';
+    stripTrailing(footerP->comment);
+
+    memmove(footerP->exposureTime, &buffer[79], 10);
+    footerP->exposureTime[10] = '\0';
+    stripLeading(footerP->exposureTime);
+
+    memmove(footerP->focalLength, &buffer[89], 10);
+    footerP->focalLength[10] = '\0';
+    stripLeading(footerP->focalLength);
+
+    memmove(footerP->apertureArea, &buffer[99], 10);
+    footerP->apertureArea[10] = '\0';
+    stripLeading(footerP->apertureArea);
+
+    memmove(footerP->calibrationFactor, &buffer[109], 10);
+    footerP->calibrationFactor[10] = '\0';
+    stripLeading(footerP->calibrationFactor);
+}
+
+
+
+static void
+reportFooter(struct St4Footer const footer) {
+
+	pm_message("Comment:                 %s", footer.comment);
+
+	pm_message("Exposure time (1/100 s): %s", footer.exposureTime);
+
+	pm_message("Focal length (in):       %s", footer.focalLength);
+
+	pm_message("Aperture area (sq in):   %s", footer.apertureArea);
+
+	pm_message("Calibration factor:      %s", footer.calibrationFactor);
+}
+
+
+
+int
+main(int argc, const char **argv) {
+
+    FILE * ifP;
+    const char * inputFileName;
+    struct pam outpam;
+    struct St4Footer footer;
+
+    pm_proginit(&argc, argv);
+
+    if (argc-1 < 1)
+        inputFileName = "'";
+    else {
+        inputFileName = argv[1];
+        if (argc-1 > 1)
+            pm_error("Too many arguments: %u.  "
+                     "The only possible argument is the "
+                     "optional input file name", argc-1);
+    }        
+
+    /* We check the file size to catch the common problem of the input not
+       being valid ST-4 SBIG input.  Unlike most formats, this one does not
+       have any signature at the head of the file.
+
+       More checks on the validity of the format happens when we process
+       the image footer.
+    */
+
+    ifP = pm_openr_seekable(inputFileName);
+
+    validateFileSize(ifP);
+
+    outpam.size = sizeof(outpam);
+    outpam.len = PAM_STRUCT_SIZE(maxval);
+    outpam.file = stdout;
+    outpam.format = PGM_FORMAT;
+    outpam.plainformat = false;
+    outpam.height = st4Height;
+    outpam.width = st4Width;
+    outpam.depth = 1;
+    outpam.maxval = st4Maxval;
+
+    pnm_writepaminit(&outpam);
+
+    writeRaster(ifP, &outpam);
+
+    readFooter(ifP, &footer);
+
+    reportFooter(footer);
+
+    pm_close(ifP);
+    pm_close(stdout);
+
+    return 0;
+}
+
+