about summary refs log tree commit diff
path: root/converter/pbm/pbmtodjvurle.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/pbm/pbmtodjvurle.c')
-rw-r--r--converter/pbm/pbmtodjvurle.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/converter/pbm/pbmtodjvurle.c b/converter/pbm/pbmtodjvurle.c
new file mode 100644
index 00000000..dbe96f31
--- /dev/null
+++ b/converter/pbm/pbmtodjvurle.c
@@ -0,0 +1,140 @@
+/*
+   Convert a PBM image into the DjVu Bitonal RLE format
+   described in the csepdjvu(1) documentation
+  
+   Copyright (c) 2004 Scott Pakin <scott+pbm@pakin.org>
+
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   
+   1. Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+   2. Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+   3. The name of the author may not be used to endorse or promote products
+      derived from this software without specific prior written permission.
+   
+   THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
+   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include "pbm.h"
+
+
+/* Write a byte to a file and check for errors. */
+static void
+writebyte(FILE *        const ofP,
+          unsigned char const c) {
+
+    if (fputc (c, ofP) == EOF)
+        pm_error ("failed to write to the RLE file.  Errno=%d (%s)",
+                  errno, strerror(errno));
+}
+
+
+/* Write a run length to the RLE file. */
+static void 
+write_rle (FILE *rlefile, uint32n tally)
+{
+  do {
+    /* Output a single run. */
+    if (tally < 192) {
+      /* Single-byte runs */
+      writebyte (rlefile, tally);
+      tally >>= 8;
+    }
+    else {
+      /* Two-byte runs */
+      writebyte (rlefile, ((tally>>8)&0x3F) + 0xC0);
+      writebyte (rlefile, tally&0xFF);
+      tally >>= 14;
+    }
+
+    /* Very large runs need to be split into smaller runs.  We
+     * therefore need to toggle back to the same color we had for the
+     * previous smaller run. */
+    if (tally > 0)
+      writebyte (rlefile, 0);
+  }
+  while (tally > 0);
+}
+
+
+
+int 
+main (int argc, char *argv[])
+{
+  FILE * const rlefile = stdout;    /* Generated Bitonal RLE file */
+
+  FILE *pbmfile;             /* PBM file to convert */
+  int numcols, numrows;      /* Width and height in pixels of the PBM file */
+  int format;                /* Original image type before conversion to PBM */
+  bit *pbmrow;               /* One row of the PBM file */
+  uint32n pixeltally = 0;    /* Run length of the current color */
+  int row, col;              /* Row and column loop variables */
+  const char * pbmfilename;  /* Name of input file */
+
+  /* Parse the command line. */
+  pbm_init (&argc, argv);
+
+  if (argc-1 < 1)
+      pbmfilename = "-";
+  else if (argc-1 == 1)
+      pbmfilename = argv[1];
+  else
+      pm_error("Program takes at most 1 argument -- the input file name.  "
+               "You specified %d", argc-1);
+
+  pbmfile = pm_openr(pbmfilename);
+
+  /* Write an RLE header. */
+  pbm_readpbminit (pbmfile, &numcols, &numrows, &format);
+  fprintf (rlefile, "R4\n");
+  fprintf (rlefile, "%d %d\n", numcols, numrows);
+
+  /* Write the RLE data. */
+  pbmrow = pbm_allocrow (numcols);
+  for (row=0; row<numrows; row++) {
+    bit prevpixel;        /* Previous pixel seen */
+
+    pbm_readpbmrow (pbmfile, pbmrow, numcols, format);
+    prevpixel = PBM_WHITE;   /* Bitonal RLE rows always start with white */
+    pixeltally = 0;
+    for (col=0; col<numcols; col++) {
+      bit newpixel = pbmrow[col];      /* Current pixel color */
+
+      if (newpixel == prevpixel)
+        pixeltally++;
+      else {
+        write_rle (rlefile, pixeltally);
+        pixeltally = 1;
+        prevpixel = newpixel;
+      }
+    }
+    write_rle (rlefile, pixeltally);
+  }
+
+  /* Finish up cleanly. */
+  pbm_freerow (pbmrow);
+  if (rlefile != stdout)
+    pm_close (rlefile);
+  if (pbmfile != stdin)
+    pm_close (pbmfile);
+  exit (0);
+}