about summary refs log tree commit diff
path: root/editor/ppmdither.c
diff options
context:
space:
mode:
Diffstat (limited to 'editor/ppmdither.c')
-rw-r--r--editor/ppmdither.c142
1 files changed, 76 insertions, 66 deletions
diff --git a/editor/ppmdither.c b/editor/ppmdither.c
index ec1b9771..2619c8b7 100644
--- a/editor/ppmdither.c
+++ b/editor/ppmdither.c
@@ -1,5 +1,5 @@
 /*=============================================================================
-                                 pamdither
+                                 ppmdither
 ===============================================================================
   By Bryan Henderson, July 2006.
 
@@ -23,7 +23,7 @@
 #define MAX_DITH_POWER (((unsigned)sizeof(unsigned int)*8 - 1) / 2)
 
 
-struct colorResolution {
+struct ColorResolution {
     unsigned int c[3];
         /* comp[PAM_RED_PLANE] is number of distinct red levels, etc. */
 };
@@ -32,13 +32,13 @@ struct colorResolution {
 #define GRN PAM_GRN_PLANE
 #define BLU PAM_BLU_PLANE
 
-struct cmdlineInfo {
+struct CmdlineInfo {
     /* All the information the user supplied in the command line,
        in a form easy for the program to use.
     */
     const char * inputFileName;  /* File name of input file */
     unsigned int dim;
-    struct colorResolution colorRes;
+    struct ColorResolution colorRes;
     unsigned int verbose;
 };
 
@@ -46,10 +46,10 @@ struct cmdlineInfo {
 
 static void
 parseCommandLine(int argc, const char ** const argv,
-                 struct cmdlineInfo * const cmdlineP) {
+                 struct CmdlineInfo * const cmdlineP) {
 /*----------------------------------------------------------------------------
    parse program command line described in Unix standard form by argc
-   and argv.  Return the information in the options as *cmdlineP.  
+   and argv.  Return the information in the options as *cmdlineP.
 
    If command line is internally inconsistent (invalid options, etc.),
    issue error message to stderr and abort program.
@@ -67,13 +67,13 @@ parseCommandLine(int argc, const char ** const argv,
     unsigned int dimSpec, redSpec, greenSpec, blueSpec;
 
     MALLOCARRAY_NOFAIL(option_def, 100);
-    
+
     option_def_index = 0;   /* incremented by OPTENT3 */
-    OPTENT3(0, "dim",          OPT_UINT, 
+    OPTENT3(0, "dim",          OPT_UINT,
             &cmdlineP->dim,            &dimSpec,                  0);
-    OPTENT3(0, "red",          OPT_UINT, 
+    OPTENT3(0, "red",          OPT_UINT,
             &cmdlineP->colorRes.c[RED],   &redSpec,       0);
-    OPTENT3(0, "green",        OPT_UINT, 
+    OPTENT3(0, "green",        OPT_UINT,
             &cmdlineP->colorRes.c[GRN],   &greenSpec,     0);
     OPTENT3(0, "blue",         OPT_UINT,
             &cmdlineP->colorRes.c[BLU],   &blueSpec,      0);
@@ -94,7 +94,7 @@ parseCommandLine(int argc, const char ** const argv,
         pm_error("Dithering matrix power %u (-dim) is too large.  "
                  "Must be <= %u",
                  cmdlineP->dim, MAX_DITH_POWER);
-        
+
     if (redSpec) {
         if (cmdlineP->colorRes.c[RED] < 2)
             pm_error("-red must be at least 2.  You specified %u",
@@ -139,7 +139,7 @@ typedef struct {
    0-3, and blue value of 0-1 to a tuple with maxval 255.  So you can
    ask it to scale (1,1,1) and it responds with (85, 85, 255).
 -----------------------------------------------------------------------------*/
-    struct colorResolution colorRes;
+    struct ColorResolution colorRes;
         /* Number of values of each color component possible, i.e. maxval
            plus 1
         */
@@ -148,7 +148,7 @@ typedef struct {
            certain function (see scaler_scale()) of the input red, green, and
            blue values.
         */
-} scaler;    
+} Scaler;
 
 
 
@@ -156,7 +156,7 @@ static tuple *
 allocScalerMap(unsigned int const size) {
     /* The tuple row data structure starts with 'size' pointers to
        the tuples, immediately followed by the 'size' tuples
-       themselves.  Each tuple consists of 3 samples.  
+       themselves.  Each tuple consists of 3 samples.
     */
 
     unsigned int const depth = 3;
@@ -165,14 +165,14 @@ allocScalerMap(unsigned int const size) {
     tuple * map;
 
     map = malloc(size * (sizeof(tuple *) + bytesPerTuple));
-                      
+
     if (map != NULL) {
         /* Now we initialize the pointers to the individual tuples
-           to make this a regulation C two dimensional array.  
+           to make this a regulation C two dimensional array.
         */
         char * p;
         unsigned int i;
-        
+
         p = (char*) (map + size);  /* location of Tuple 0 */
         for (i = 0; i < size; ++i) {
             map[i] = (tuple) p;
@@ -186,12 +186,12 @@ allocScalerMap(unsigned int const size) {
 
 static void
 scaler_create(sample                 const outputMaxval,
-              struct colorResolution const colorRes,
-              scaler **              const scalerPP) {
+              struct ColorResolution const colorRes,
+              Scaler **              const scalerPP) {
 
-    scaler * scalerP;
+    Scaler * scalerP;
     unsigned int mapSize;
-    
+
     if (UINT_MAX / colorRes.c[RED] / colorRes.c[GRN] / colorRes.c[BLU] < 1)
         pm_error("red/green/blue dimensions %u/%u/%u is uncomputably large",
                  colorRes.c[RED], colorRes.c[GRN], colorRes.c[BLU]);
@@ -223,10 +223,10 @@ scaler_create(sample                 const outputMaxval,
                         (r * colorRes.c[GRN] + g)
                         * colorRes.c[BLU] + b;
                     tuple const t = scalerP->out[index];
-                         
+
                     t[PAM_RED_PLANE] =
                         r * outputMaxval / (colorRes.c[RED] - 1);
-                    t[PAM_GRN_PLANE] = 
+                    t[PAM_GRN_PLANE] =
                         g * outputMaxval / (colorRes.c[GRN] - 1);
                     t[PAM_BLU_PLANE] =
                         b * outputMaxval / (colorRes.c[BLU] - 1);
@@ -240,7 +240,7 @@ scaler_create(sample                 const outputMaxval,
 
 
 static void
-scaler_destroy(scaler * const scalerP) {
+scaler_destroy(Scaler * const scalerP) {
 
     free(scalerP->out);
 
@@ -250,7 +250,7 @@ scaler_destroy(scaler * const scalerP) {
 
 
 static tuple
-scaler_scale(const scaler * const scalerP,
+scaler_scale(const Scaler * const scalerP,
              unsigned int   const red,
              unsigned int   const grn,
              unsigned int   const blu) {
@@ -275,7 +275,7 @@ dither(sample       const p,
        unsigned int const ditheredMaxval,
        unsigned int const ditherMatrixArea) {
 /*----------------------------------------------------------------------------
-  Return the dithered brightness for a component of a pixel whose real 
+  Return the dithered brightness for a component of a pixel whose real
   brightness for that component is 'p' based on a maxval of 'maxval'.
   The returned brightness is based on a maxval of ditheredMaxval.
 
@@ -292,7 +292,7 @@ dither(sample       const p,
         /* This is the input intensity P expressed with a maxval of
            'ditherSquareMaxval'
         */
-    
+
     /* Now we scale the intensity back down to the 'ditheredMaxval', and
        as that will involve rounding, we round up or down based on the position
        in the dithered square, as determined by 'd'
@@ -306,7 +306,7 @@ dither(sample       const p,
 static unsigned int
 dithValue(unsigned int const yArg,
           unsigned int const xArg,
-          unsigned int const dithPower) { 
+          unsigned int const dithPower) {
 /*----------------------------------------------------------------------------
   Return the value of a dither matrix which is 2 ** dithPower elements
   square at Row x, Column y.
@@ -336,45 +336,37 @@ dithValue(unsigned int const yArg,
 
 
 static unsigned int **
-dithMatrix(unsigned int const dithPower) {
+newDithMatrix(unsigned int const dithPower) {
 /*----------------------------------------------------------------------------
    Create the dithering matrix for dimension 'dithDim'.
 
    Return it in newly malloc'ed storage.
 
-   Note that we assume 'dithPower' is small enough that the 'dithMatSize'
-   computed within fits in an int.  Otherwise, results are undefined.
+   Note that we assume 'dithPower' is not greater than the number of bits in
+   an unsigned int.
 -----------------------------------------------------------------------------*/
     unsigned int const dithDim = 1 << dithPower;
 
     unsigned int ** dithMat;
+    unsigned int y;
 
     assert(dithPower < sizeof(unsigned int) * 8);
 
-    {
-        unsigned int const dithMatSize = 
-            (dithDim * sizeof(*dithMat)) + /* pointers */
-            (dithDim * dithDim * sizeof(**dithMat)); /* data */
-        
-        dithMat = malloc(dithMatSize);
-        
-        if (dithMat == NULL) 
-            pm_error("Out of memory.  "
-                     "Cannot allocate %u bytes for dithering matrix.",
-                     dithMatSize);
-    }
-    {
-        unsigned int * const rowStorage = (unsigned int *)&dithMat[dithDim];
-        unsigned int y;
-        for (y = 0; y < dithDim; ++y)
-            dithMat[y] = &rowStorage[y * dithDim];
-    }
-    {
-        unsigned int y;
+    MALLOCARRAY(dithMat, dithDim);
+    if (!dithMat)
+        pm_error("Cannot allocate %u-row dithering matrix index", dithDim);
+    else {
         for (y = 0; y < dithDim; ++y) {
-            unsigned int x;
-            for (x = 0; x < dithDim; ++x)
-                dithMat[y][x] = dithValue(y, x, dithPower);
+            MALLOCARRAY(dithMat[y], dithDim);
+            if (!dithMat[y])
+                pm_error("Failed to allocate %uth row of "
+                         "%ux%u dithering matrix", y, dithDim, dithDim);
+            else {
+                unsigned int x;
+
+                for (x = 0; x < dithDim; ++x)
+                    dithMat[y][x] = dithValue(y, x, dithPower);
+            }
         }
     }
     return dithMat;
@@ -383,9 +375,25 @@ dithMatrix(unsigned int const dithPower) {
 
 
 static void
+freeDithMatrix(unsigned int ** const dithMat,
+               unsigned int    const dithPower) {
+
+    unsigned int const dithDim = 1 << dithPower;
+
+    unsigned int y;
+
+    for (y = 0; y < dithDim; ++y)
+        free(dithMat[y]);
+
+    free(dithMat);
+}
+
+
+
+static void
 validateNoDitherOverflow(unsigned int           const ditherMatrixArea,
                          struct pam *           const inpamP,
-                         struct colorResolution const colorRes) {
+                         struct ColorResolution const colorRes) {
 /*----------------------------------------------------------------------------
    Validate that we'll be able to do the dithering calculations based on
    the parameters above without busting out of an integer.
@@ -409,10 +417,10 @@ validateNoDitherOverflow(unsigned int           const ditherMatrixArea,
 static void
 ditherRow(struct pam *           const inpamP,
           const tuple *          const inrow,
-          const scaler *         const scalerP,
+          const Scaler *         const scalerP,
           unsigned int **        const ditherMatrix,
           unsigned int           const ditherMatrixArea,
-          struct colorResolution const colorRes,
+          struct ColorResolution const colorRes,
           unsigned int           const row,
           unsigned int           const modMask,
           struct pam *           const outpamP,
@@ -447,9 +455,9 @@ ditherRow(struct pam *           const inpamP,
 
 static void
 ditherImage(struct pam *           const inpamP,
-            const scaler *         const scalerP,
+            const Scaler *         const scalerP,
             unsigned int           const dithPower,
-            struct colorResolution const colorRes,
+            struct ColorResolution const colorRes,
             struct pam *           const outpamP,
             tuple ***              const outTuplesP) {
 
@@ -460,17 +468,17 @@ ditherImage(struct pam *           const inpamP,
        /* And this into N to compute N % dithDim cheaply, since we
           know (though the compiler doesn't) that dithDim is a power of 2
        */
-    unsigned int ** const ditherMatrix = dithMatrix(dithPower);
+    unsigned int ** const ditherMatrix = newDithMatrix(dithPower);
 
     tuple * inrow;
     tuple ** outTuples;
-    unsigned int row; 
+    unsigned int row;
     struct pam ditherPam;
         /* Describes the tuples that ditherRow() sees */
 
     assert(dithPower < sizeof(unsigned int) * 8);
     assert(UINT_MAX / dithDim >= dithDim);
-    
+
     validateNoDitherOverflow(ditherMatrixArea, inpamP, colorRes);
 
     inrow = pnm_allocpamrow(inpamP);
@@ -490,7 +498,7 @@ ditherImage(struct pam *           const inpamP,
                   colorRes, row, modMask,
                   outpamP, outTuples[row]);
     }
-    free(ditherMatrix);
+    freeDithMatrix(ditherMatrix, dithPower);
     pnm_freepamrow(inrow);
     *outTuplesP = outTuples;
 }
@@ -501,10 +509,10 @@ int
 main(int           argc,
      const char ** argv) {
 
-    struct cmdlineInfo cmdline;
+    struct CmdlineInfo cmdline;
     FILE * ifP;
     tuple ** outTuples;        /* Output image */
-    scaler * scalerP;
+    Scaler * scalerP;
     struct pam inpam;
     struct pam outpam;
 
@@ -517,7 +525,7 @@ main(int           argc,
     pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(allocation_depth));
 
     pnm_setminallocationdepth(&inpam, 3);
-    
+
     outpam.size               = sizeof(outpam);
     outpam.len                = PAM_STRUCT_SIZE(tuple_type);
     outpam.file               = stdout;
@@ -549,3 +557,5 @@ main(int           argc,
 
     return 0;
 }
+
+