about summary refs log tree commit diff
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2019-03-09 00:13:15 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2019-03-09 00:13:15 +0000
commit1eeb6948a31c87e40477c911795e09f4643c52ff (patch)
treefc68687f4736f337289a4a6a1bae270640d376e8
parent9febf050e9c421127601c62b3e539a4132d34820 (diff)
downloadnetpbm-mirror-1eeb6948a31c87e40477c911795e09f4643c52ff.tar.gz
netpbm-mirror-1eeb6948a31c87e40477c911795e09f4643c52ff.tar.xz
netpbm-mirror-1eeb6948a31c87e40477c911795e09f4643c52ff.zip
Fix sBit chunk, bit shift value
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@3562 9d0c8265-081b-0410-96cb-a4ca84ce46f8
-rw-r--r--converter/other/pamtopng.c121
1 files changed, 87 insertions, 34 deletions
diff --git a/converter/other/pamtopng.c b/converter/other/pamtopng.c
index ece94c86..b4896125 100644
--- a/converter/other/pamtopng.c
+++ b/converter/other/pamtopng.c
@@ -333,6 +333,62 @@ parseAndScaleColor(const char * const colorString,
 
 
 
+static png_color_8
+sigBitsFmImgType(unsigned int const pnmBitDepth,
+                 int          const pngColorType) {
+/*----------------------------------------------------------------------------
+   A representation used in PNG of color resolutions in an original image.
+-----------------------------------------------------------------------------*/
+    png_color_8 retval;
+
+    /* Initial values */
+    if (pnmBitDepth < 8) {
+        switch (pngColorType) {
+        case PNG_COLOR_TYPE_RGB:
+            retval.red   = pnmBitDepth;
+            retval.green = pnmBitDepth;
+            retval.blue  = pnmBitDepth;
+            retval.gray  = 0;
+            retval.alpha = 0;
+            break;
+        case PNG_COLOR_TYPE_RGB_ALPHA:
+            retval.red   = pnmBitDepth;
+            retval.green = pnmBitDepth;
+            retval.blue  = pnmBitDepth;
+            retval.gray  = 0;
+            retval.alpha = pnmBitDepth;
+            break;
+        case PNG_COLOR_TYPE_GRAY:
+            /* PNG can (so presumably will) use original bit depth */
+            retval.red   = 0;
+            retval.green = 0;
+            retval.blue  = 0;
+            retval.gray  = 0;
+            retval.alpha = 0;
+            break;
+        case PNG_COLOR_TYPE_GRAY_ALPHA:
+            retval.red   = 0;
+            retval.green = 0;
+            retval.blue  = 0;
+            retval.gray  = pnmBitDepth;
+            retval.alpha = pnmBitDepth;
+            break;
+        default:
+            assert(false);
+        }
+    } else {
+        /* PNG can (so presumably will) use original bit depth */
+        retval.red   = 0;
+        retval.green = 0;
+        retval.blue  = 0;
+        retval.gray  = 0;
+        retval.alpha = 0;
+    }
+    return retval;
+}
+
+
+
 static void
 doTrnsChunk(const struct pam * const pamP,
             struct pngx *      const pngxP,
@@ -399,30 +455,12 @@ doGamaChunk(struct pngx *  const pngxP,
 
 static void
 doSbitChunk(const struct pam * const pamP,
-            struct pngx *      const pngxP) {
-
-    unsigned int const pnmBitDepth = pm_maxvaltobits(pamP->maxval);
-
-    /* A restriction on the PAM input: must power of 2 minus 1 maxval: */
-    assert(pm_bitstomaxval(pnmBitDepth) == pamP->maxval);
+            struct pngx *      const pngxP,
+            png_color_8        const sigBits) {
 
-    /* create SBIT chunk in case of 1,2,4 bit deep images stored in 8 bit
-       format PNG files
-    */
-    if (pngx_colorType(pngxP) != PNG_COLOR_TYPE_GRAY && pnmBitDepth < 8) {
-        png_color_8 sBit;
-
-        if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_RGB ||
-            pngx_colorType(pngxP) == PNG_COLOR_TYPE_RGB_ALPHA) {
-            sBit.red = sBit.green = sBit.blue = pnmBitDepth;
-        } else {
-            sBit.gray = pnmBitDepth;
-        }
-        if (pngx_colorType(pngxP) == PNG_COLOR_TYPE_RGB_ALPHA ||
-            pngx_colorType(pngxP) == PNG_COLOR_TYPE_GRAY_ALPHA) {
-            sBit.alpha = pnmBitDepth;
-        }
-        pngx_setSbit(pngxP, sBit);
+    if (sigBits.red + sigBits.green + sigBits.blue +
+        sigBits.gray + sigBits.alpha > 0) {
+        pngx_setSbit(pngxP, sigBits);
     }
 }
 
@@ -661,7 +699,8 @@ pngBitDepth(unsigned int const pnmBitDepth,
 static void
 addAncillaryChunks(struct pam *       const pamP,
                    struct pngx *      const pngxP,
-                   struct CmdlineInfo const cmdline) {
+                   struct CmdlineInfo const cmdline,
+                   png_color_8        const sigBits) {
 /*----------------------------------------------------------------------------
   Where requested, add ancillary chunks.
 -----------------------------------------------------------------------------*/
@@ -676,7 +715,7 @@ addAncillaryChunks(struct pam *       const pamP,
 
     /* no iccp */
 
-    doSbitChunk(pamP, pngxP);
+    doSbitChunk(pamP, pngxP, sigBits);
 
     if (cmdline.srgbintentSpec)
         doSrgbChunk(pngxP, cmdline.srgbintent);
@@ -709,15 +748,29 @@ addAncillaryChunks(struct pam *       const pamP,
 
 
 static void
+setShift(struct pngx * const pngxP,
+         png_color_8   const sigBits) {
+
+    if (sigBits.red + sigBits.green + sigBits.blue +
+        sigBits.gray + sigBits.alpha > 0) {
+
+        /* Move the 1, 2, 4 bits to most significant bits */
+        pngx_setShift(pngxP, sigBits);
+    }
+}
+
+
+
+static void
 pamtopng(FILE *             const ifP,
          FILE *             const ofP,
          struct CmdlineInfo const cmdline) {
 
-    unsigned int pnmBitDepth;
-    int          pngColorType;
+    unsigned int  pnmBitDepth;
+    int           pngColorType;
     struct pngx * pngxP;
-    png_color_8 sBit;
-    struct pam pam;
+    png_color_8   sigBits;
+    struct pam    pam;
 
     pnm_readpaminit(ifP, &pam, PAM_STRUCT_SIZE(tuple_type));
 
@@ -737,12 +790,12 @@ pamtopng(FILE *             const ifP,
                  PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
                  PNG_FILTER_TYPE_BASE);
 
-    addAncillaryChunks(&pam, pngxP, cmdline);
+    sigBits = sigBitsFmImgType(pnmBitDepth, pngColorType);
+
+    addAncillaryChunks(&pam, pngxP, cmdline, sigBits);
+
+    setShift(pngxP, sigBits);
 
-    if (pngColorType != PNG_COLOR_TYPE_GRAY && pnmBitDepth < 8) {
-        /* Move the 1, 2, 4 bits to most significant bits */
-        pngx_setShift(pngxP, sBit);
-    }
     if ((pngColorType == PNG_COLOR_TYPE_GRAY) && (pnmBitDepth < 8)) {
         /* Pack multiple pixels in a byte */
         pngx_setPacking(pngxP);