about summary refs log tree commit diff
path: root/lib/libppm2.c
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-08-19 03:12:28 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-08-19 03:12:28 +0000
commit1fd361a1ea06e44286c213ca1f814f49306fdc43 (patch)
tree64c8c96cf54d8718847339a403e5e67b922e8c3f /lib/libppm2.c
downloadnetpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.gz
netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.xz
netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.zip
Create Subversion repository
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'lib/libppm2.c')
-rw-r--r--lib/libppm2.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/lib/libppm2.c b/lib/libppm2.c
new file mode 100644
index 00000000..52c4ab16
--- /dev/null
+++ b/lib/libppm2.c
@@ -0,0 +1,208 @@
+/* libppm2.c - ppm utility library part 2
+**
+** Copyright (C) 1989 by Jef Poskanzer.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation.  This software is provided "as is" without express or
+** implied warranty.
+*/
+
+#include <string.h>
+#include <errno.h>
+
+
+#include "pm_c_util.h"
+#include "mallocvar.h"
+#include "ppm.h"
+#include "libppm.h"
+
+void
+ppm_writeppminit(FILE*  const fileP, 
+                 int    const cols, 
+                 int    const rows, 
+                 pixval const maxval, 
+                 int    const forceplain) {
+
+    bool const plainFormat = forceplain || pm_plain_output;
+
+    if (maxval > PPM_OVERALLMAXVAL && !plainFormat) 
+        pm_error("too-large maxval passed to ppm_writeppminit(): %d."
+                 "Maximum allowed by the PPM format is %d.",
+                 maxval, PPM_OVERALLMAXVAL);
+
+    fprintf(fileP, "%c%c\n%d %d\n%d\n", 
+            PPM_MAGIC1, 
+            plainFormat || maxval >= 1<<16 ? PPM_MAGIC2 : RPPM_MAGIC2, 
+            cols, rows, maxval );
+#ifdef VMS
+    if (!plainFormat)
+        set_outfile_binary();
+#endif
+}
+
+
+
+static void
+putus(unsigned short const n,
+      FILE *         const fileP) {
+
+    if (n >= 10)
+        putus(n / 10, fileP);
+    putc('0' + n % 10, fileP);
+}
+
+
+
+static void
+format1bpsRow(const pixel *   const pixelrow,
+              unsigned int    const cols,
+              unsigned char * const rowBuffer) {
+
+    /* single byte samples. */
+
+    unsigned int col;
+    unsigned int bufferCursor;
+
+    bufferCursor = 0;
+
+    for (col = 0; col < cols; ++col) {
+        rowBuffer[bufferCursor++] = PPM_GETR(pixelrow[col]);
+        rowBuffer[bufferCursor++] = PPM_GETG(pixelrow[col]);
+        rowBuffer[bufferCursor++] = PPM_GETB(pixelrow[col]);
+    }
+}
+
+
+
+
+static void
+format2bpsRow(const pixel *   const pixelrow,
+              unsigned int    const cols,
+              unsigned char * const rowBuffer) {
+    
+    /* two byte samples. */
+
+    unsigned int col;
+    unsigned int bufferCursor;
+
+    bufferCursor = 0;
+
+    for (col = 0; col < cols; ++col) {
+        pixval const r = PPM_GETR(pixelrow[col]);
+        pixval const g = PPM_GETG(pixelrow[col]);
+        pixval const b = PPM_GETB(pixelrow[col]);
+        
+        rowBuffer[bufferCursor++] = r >> 8;
+        rowBuffer[bufferCursor++] = (unsigned char)r;
+        rowBuffer[bufferCursor++] = g >> 8;
+        rowBuffer[bufferCursor++] = (unsigned char)g;
+        rowBuffer[bufferCursor++] = b >> 8;
+        rowBuffer[bufferCursor++] = (unsigned char)b;
+    }
+}
+
+
+
+static void
+ppm_writeppmrowraw(FILE *        const fileP,
+                   const pixel * const pixelrow,
+                   unsigned int  const cols,
+                   pixval        const maxval ) {
+
+    unsigned int const bytesPerSample = maxval < 256 ? 1 : 2;
+    unsigned int const bytesPerRow    = cols * 3 * bytesPerSample;
+
+    unsigned char * rowBuffer;
+    ssize_t rc;
+
+    MALLOCARRAY(rowBuffer, bytesPerRow);
+
+    if (rowBuffer == NULL)
+        pm_error("Unable to allocate memory for row buffer "
+                 "for %u columns", cols);
+
+    if (maxval < 256)
+        format1bpsRow(pixelrow, cols, rowBuffer);
+    else
+        format2bpsRow(pixelrow, cols, rowBuffer);
+
+    rc = fwrite(rowBuffer, 1, bytesPerRow, fileP);
+
+    if (rc < 0)
+        pm_error("Error writing row.  fwrite() errno=%d (%s)",
+                 errno, strerror(errno));
+    else if (rc != bytesPerRow)
+        pm_error("Error writing row.  Short write of %u bytes "
+                 "instead of %u", rc, bytesPerRow);
+
+    free(rowBuffer);
+}
+
+
+
+
+static void
+ppm_writeppmrowplain(FILE *       const fileP,
+                     pixel *      const pixelrow,
+                     unsigned int const cols,
+                     pixval       const maxval) {
+
+    unsigned int col;
+    unsigned int charcount;
+
+    charcount = 0;
+
+    for (col = 0; col < cols; ++col) {
+        if (charcount >= 65) {
+            putc('\n', fileP);
+            charcount = 0;
+        } else if (charcount > 0) {
+            putc(' ', fileP);
+            putc(' ', fileP);
+            charcount += 2;
+        }
+        putus(PPM_GETR(pixelrow[col]), fileP);
+        putc(' ', fileP);
+        putus(PPM_GETG(pixelrow[col]), fileP);
+        putc(' ', fileP);
+        putus(PPM_GETB(pixelrow[col]), fileP);
+        charcount += 11;
+    }
+    if (charcount > 0)
+        putc('\n', fileP);
+}
+
+
+
+void
+ppm_writeppmrow(FILE *  const fileP, 
+                pixel * const pixelrow, 
+                int     const cols, 
+                pixval  const maxval, 
+                int     const forceplain) {
+
+    if (forceplain || pm_plain_output || maxval >= 1<<16) 
+        ppm_writeppmrowplain(fileP, pixelrow, cols, maxval);
+    else 
+        ppm_writeppmrowraw(fileP, pixelrow, cols, maxval);
+}
+
+
+
+void
+ppm_writeppm(FILE *  const file, 
+             pixel** const pixels, 
+             int     const cols, 
+             int     const rows, 
+             pixval  const maxval, 
+             int     const forceplain)  {
+    int row;
+    
+    ppm_writeppminit(file, cols, rows, maxval, forceplain);
+    
+    for (row = 0; row < rows; ++row)
+        ppm_writeppmrow(file, pixels[row], cols, maxval, forceplain);
+}