about summary refs log tree commit diff
path: root/converter/other/pamtoqoi.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/other/pamtoqoi.c')
-rw-r--r--converter/other/pamtoqoi.c247
1 files changed, 139 insertions, 108 deletions
diff --git a/converter/other/pamtoqoi.c b/converter/other/pamtoqoi.c
index 1e8cba49..13448f19 100644
--- a/converter/other/pamtoqoi.c
+++ b/converter/other/pamtoqoi.c
@@ -14,140 +14,171 @@
  * You should have received a copy of the GNU General Public License
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
-#include "pam.h"
 #include <string.h>
 #include <assert.h>
+#include "pam.h"
+#include "nstring.h"
 #include "qoi.h"
 
 #define QOI_MAXVAL 0xFF
 
 /* tuple row to qoi row */
-typedef void (*trqr_t)(const tuplen *tuprow,
-                       size_t len,
-                       unsigned char *qoi_row);
-
-static void trqr_ppm(const tuplen *tuprow,
-               size_t len,
-               unsigned char *qoi_row) {
-    size_t j = 0;
-    for(size_t i = 0; i < len; i++) {
-        qoi_row[j++] = tuprow[i][0] * QOI_MAXVAL;
-        qoi_row[j++] = tuprow[i][1] * QOI_MAXVAL;
-        qoi_row[j++] = tuprow[i][2] * QOI_MAXVAL;
+typedef void Trqr(const tuplen *  const tuplerown,
+                  unsigned int    const width,
+                  unsigned char * const qoiRow);
+
+static Trqr trqrRgb;
+
+static void
+trqrRgb(const tuplen *  const tuplerown,
+        unsigned int    const cols,
+        unsigned char * const qoiRow) {
+
+    size_t qoiRowCursor;
+    unsigned int col;
+
+    for (col = 0, qoiRowCursor = 0; col < cols; ++col) {
+        qoiRow[qoiRowCursor++] = tuplerown[col][PAM_RED_PLANE] * QOI_MAXVAL;
+        qoiRow[qoiRowCursor++] = tuplerown[col][PAM_GRN_PLANE] * QOI_MAXVAL;
+        qoiRow[qoiRowCursor++] = tuplerown[col][PAM_BLU_PLANE] * QOI_MAXVAL;
     }
 }
-static void trqr_ppma(const tuplen *tuprow,
-               size_t len,
-               unsigned char *qoi_row) {
-    size_t j = 0;
-    for(size_t i = 0; i < len; i++) {
-        qoi_row[j++] = tuprow[i][0] * QOI_MAXVAL;
-        qoi_row[j++] = tuprow[i][1] * QOI_MAXVAL;
-        qoi_row[j++] = tuprow[i][2] * QOI_MAXVAL;
-        qoi_row[j++] = tuprow[i][3] * QOI_MAXVAL;
+
+
+
+static Trqr trqrRgba;
+
+static void
+trqrRgba(const tuplen *  const tuplerown,
+         unsigned int    const cols,
+         unsigned char * const qoiRow) {
+
+    size_t qoiRowCursor;
+    unsigned int col;
+
+    for (col = 0, qoiRowCursor = 0; col < cols; ++col) {
+        qoiRow[qoiRowCursor++] = tuplerown[col][PAM_RED_PLANE] * QOI_MAXVAL;
+        qoiRow[qoiRowCursor++] = tuplerown[col][PAM_GRN_PLANE] * QOI_MAXVAL;
+        qoiRow[qoiRowCursor++] = tuplerown[col][PAM_BLU_PLANE] * QOI_MAXVAL;
+        qoiRow[qoiRowCursor++] = tuplerown[col][PAM_TRN_PLANE] * QOI_MAXVAL;
     }
 }
 
-static void trqr_pgm(const tuplen *tuprow,
-               size_t len,
-               unsigned char *qoi_row) {
-    size_t j = 0;
-    for(size_t i = 0; i < len; i++) {
-        unsigned char tmp = tuprow[i][0] * QOI_MAXVAL;
-        qoi_row[j++] = tmp;
-        qoi_row[j++] = tmp;
-        qoi_row[j++] = tmp;
+
+
+static Trqr trqrGray;
+
+static void
+trqrGray(const tuplen *  const tuplerown,
+         unsigned int    const cols,
+         unsigned char * const qoiRow) {
+
+    size_t qoiRowCursor;
+    unsigned int col;
+
+    for (col = 0, qoiRowCursor = 0; col < cols; ++col) {
+        unsigned char const qoiSample = tuplerown[col][0] * QOI_MAXVAL;
+
+        qoiRow[qoiRowCursor++] = qoiSample;
+        qoiRow[qoiRowCursor++] = qoiSample;
+        qoiRow[qoiRowCursor++] = qoiSample;
     }
 }
-static void trqr_pgma(const tuplen *tuprow,
-               size_t len,
-               unsigned char *qoi_row) {
-    size_t j = 0;
-    for(size_t i = 0; i < len; i++) {
-        unsigned char tmp = tuprow[i][0] * QOI_MAXVAL;
-        qoi_row[j++] = tmp;
-        qoi_row[j++] = tmp;
-        qoi_row[j++] = tmp;
-        qoi_row[j++] = tuprow[i][1] * QOI_MAXVAL;
+
+
+
+static Trqr trqrGrayAlpha;
+
+static void
+trqrGrayAlpha(const tuplen *  const tuplerown,
+              unsigned int    const cols,
+              unsigned char * const qoiRow) {
+
+    size_t qoiRowCursor;
+    unsigned int col;
+
+    for (col = 0, qoiRowCursor = 0; col < cols; ++col) {
+        unsigned char const qoiSample = tuplerown[col][0] * QOI_MAXVAL;
+
+        qoiRow[qoiRowCursor++] = qoiSample;
+        qoiRow[qoiRowCursor++] = qoiSample;
+        qoiRow[qoiRowCursor++] = qoiSample;
+        qoiRow[qoiRowCursor++] =
+            tuplerown[col][PAM_GRAY_TRN_PLANE] * QOI_MAXVAL;
     }
 }
 
-static trqr_t get_trqr(const char *tuple_type) {
 
-    if(!strcmp(tuple_type, PAM_PPM_TUPLETYPE))
-       return trqr_ppm;
 
-    if(!strcmp(tuple_type, PAM_PPM_ALPHA_TUPLETYPE))
-        return trqr_ppma;
+static Trqr *
+trqrForTupleType(const char * const tupleType) {
 
-    if(!strcmp(tuple_type, PAM_PBM_TUPLETYPE) ||
-       !strcmp(tuple_type, PAM_PGM_TUPLETYPE))
-        return trqr_pgm;
-
-    if(!strcmp(tuple_type, PAM_PBM_ALPHA_TUPLETYPE) ||
-       !strcmp(tuple_type, PAM_PGM_ALPHA_TUPLETYPE))
-        return trqr_pgma;
-    return NULL;
+    if (streq(tupleType, PAM_PPM_TUPLETYPE))
+        return &trqrRgb;
+    else if(streq(tupleType, PAM_PPM_ALPHA_TUPLETYPE))
+        return &trqrRgba;
+    else if(streq(tupleType, PAM_PBM_TUPLETYPE) ||
+            streq(tupleType, PAM_PGM_TUPLETYPE))
+        return &trqrGray;
+    else if(streq(tupleType, PAM_PBM_ALPHA_TUPLETYPE) ||
+            streq(tupleType, PAM_PGM_ALPHA_TUPLETYPE))
+        return &trqrGrayAlpha;
+    else {
+        pm_error("Don't know how to convert tuple type '%s'.", tupleType);
+        return NULL;  /* Suppress compiler warning */
+    }
 }
 
-int main(int argc, char **argv) {
-    struct pam input;
-    trqr_t trqr = NULL;
-    qoi_Desc qd = {
-        .colorspace = QOI_SRGB
-    };
-    tuplen *tr = NULL;
-    unsigned char *qb = NULL;
+
+
+int
+main(int argc, char **argv) {
+
+    struct pam inpam;
+    Trqr * trqr;
+    qoi_Desc qoiDesc;
+    tuplen * tuplerown;
+    unsigned char * qoiRaster;
+    unsigned char * qoiImage;
+    size_t qoiSz;
+    unsigned int row;
 
     pm_proginit(&argc, (const char **)argv);
 
-    pnm_readpaminit(stdin, &input, PAM_STRUCT_SIZE(tuple_type));
-    tr = pnm_allocpamrown(&input);
-
-    qd.width = input.width;
-    qd.height = input.height;
-    qd.channelCt = input.depth <= 3 ? 3 : 4;
-
-    qb = malloc(qd.width * qd.height * qd.channelCt);
-
-    trqr = get_trqr(input.tuple_type);
-    if(!trqr) {
-        pm_message("Unknown tuple type. Determining conversion by depth.");
-        switch(input.depth) {
-            case 1:
-            trqr = trqr_pgm;
-            pm_message("Conversion: like grayscale");
-            break;
-
-            case 2:
-            trqr = trqr_pgma;
-            pm_message("Conversion: like grayscale_alpha");
-            break;
-
-            case 3:
-            trqr = trqr_ppm;
-            pm_message("Conversion: like rgb");
-            break;
-
-            case 4:
-            trqr = trqr_ppma;
-            pm_message("Conversion: like rgb_alpha");
-            break;
-
-            default:
-            pm_error("Unsupported depth?");
-            break;
-        }
-    }
+    pnm_readpaminit(stdin, &inpam, PAM_STRUCT_SIZE(tuple_type));
+
+    tuplerown = pnm_allocpamrown(&inpam);
+
+    qoiDesc.colorspace = QOI_SRGB;
+    qoiDesc.width      = inpam.width;
+    qoiDesc.height     = inpam.height;
+    qoiDesc.channelCt  = inpam.depth <= 3 ? 3 : 4;
+
+    qoiRaster = malloc(qoiDesc.width * qoiDesc.height * qoiDesc.channelCt);
+
+    if (!qoiRaster)
+        pm_error("Unable to get memory for QOI raster %u x %u x %u",
+                 qoiDesc.width, qoiDesc.height, qoiDesc.channelCt);
+
+    trqr = trqrForTupleType(inpam.tuple_type);
+
     /* Read and convert rows. */
-    for(size_t i = 0; i < qd.height; i++) {
-        pnm_readpamrown(&input, tr);
-        trqr(tr, input.width, qb + i * input.width * qd.channelCt);
+    for (row = 0; row < inpam.height; ++row) {
+        pnm_readpamrown(&inpam, tuplerown);
+        trqr(tuplerown,
+             inpam.width,
+             &qoiRaster[row * inpam.width * qoiDesc.channelCt]);
     }
-    pnm_freepamrown(tr);
-    size_t ol;
-    unsigned char *buf = qoi_encode(qb, &qd, &ol);
-    free(qb);
-    fwrite(buf, ol, 1, stdout);
+    qoiImage = qoi_encode(qoiRaster, &qoiDesc, &qoiSz);
+
+    pm_writefile(stdout, qoiImage, qoiSz);
+
+    free(qoiImage);
+    free(qoiRaster);
+    pnm_freepamrown(tuplerown);
+
     return 0;
 }
+
+
+