]> granicus.if.org Git - imagemagick/blobdiff - coders/png.c
(no commit message)
[imagemagick] / coders / png.c
index e4fcfac4b9ba1c052b5d52fa1d87e5fe5f19b3a8..26380352b1beb92b6d2849f26c07ed52e5aa4e81 100644 (file)
 #endif
 #if !defined(RGBColorMatchExact)
 #define IsPNGColorEqual(color,target) \
-   (((color).red == (target).red) && \
-    ((color).green == (target).green) && \
-    ((color).blue == (target).blue))
+       (((color).red == (target).red) && \
+        ((color).green == (target).green) && \
+        ((color).blue == (target).blue))
 #endif
 
+/* Convenience macros for copying RGB or RGB+opacity components
+ * between a pixel and a PixelPacket.
+ */
+
+#define GetRGBOPixelComponents(pixel, packet) \
+        (packet).red = GetRedPixelComponent((pixel)); \
+        (packet).green = GetGreenPixelComponent((pixel)); \
+        (packet).red = GetBluePixelComponent((pixel)); \
+        (packet).opacity = GetOpacityPixelComponent((pixel)); \
+
+#define SetRGBOPixelComponents(pixel, packet) \
+        SetRedPixelComponent((pixel),(packet).red); \
+        SetGreenPixelComponent((pixel),(packet).green); \
+        SetBluePixelComponent((pixel),(packet).blue); \
+        SetOpacityPixelComponent((pixel),(packet).opacity); \
+
+
+#define GetRGBPixelComponents(pixel, packet) \
+        (packet).red = GetRedPixelComponent((pixel)); \
+        (packet).green = GetGreenPixelComponent((pixel)); \
+        (packet).red = GetBluePixelComponent((pixel));
+
+#define SetRGBPixelComponents(pixel, packet) \
+        SetRedPixelComponent((pixel),(packet).red); \
+        SetGreenPixelComponent((pixel),(packet).green); \
+        SetBluePixelComponent((pixel),(packet).blue);
+
 /*
   Establish thread safety.
   setjmp/longjmp is claimed to be safe on these platforms:
@@ -501,14 +528,16 @@ LosslessReduceDepthOK(Image *image)
      *
      * This is true if the high byte and the next highest byte of
      * each sample of the image, the colormap, and the background color
-     * are equal to each other.
+     * are equal to each other.  We check this by seeing if the samples
+     * are unchanged when we scale them down to 8 and back up to Quantum.
      *
      * We don't use the method GetImageDepth() because it doesn't check
-     * background * and doesn't handle PseudoClass specially.  Also
-     * GetImageDepth() uses multiplication and division by 257 instead of
-     * shifting, so it might be slower.
+     * background and doesn't handle PseudoClass specially.
      */
 
+#define QuantumToCharToQuantumEqQuantum(quantum) \
+  ((ScaleCharToQuantum((unsigned char) ScaleQuantumToChar(quantum))) == quantum)
+
     MagickBooleanType
       ok_to_reduce=MagickFalse;
 
@@ -518,18 +547,11 @@ LosslessReduceDepthOK(Image *image)
         const PixelPacket
           *p;
 
-        const int
-          pnghi= MAGICKCORE_QUANTUM_DEPTH - 8,
-          pnglo= MAGICKCORE_QUANTUM_DEPTH - 16;
-
         ok_to_reduce=
-          (((((size_t) image->background_color.red >> pnghi) & 0xff)
-          == (((size_t) image->background_color.red >> pnglo) & 0xff)) &&
-           ((((size_t) image->background_color.green >> pnghi) & 0xff)
-          == (((size_t) image->background_color.green >> pnglo) & 0xff)) &&
-           ((((size_t) image->background_color.blue >> pnghi) & 0xff)
-          == (((size_t) image->background_color.blue >> pnglo) & 0xff))) ?
-          MagickTrue : MagickFalse;
+           QuantumToCharToQuantumEqQuantum(image->background_color.red) &&
+           QuantumToCharToQuantumEqQuantum(image->background_color.green) &&
+           QuantumToCharToQuantumEqQuantum(image->background_color.blue) ?
+           MagickTrue : MagickFalse;
 
         if (ok_to_reduce != MagickFalse && image->storage_class == PseudoClass)
           {
@@ -537,19 +559,17 @@ LosslessReduceDepthOK(Image *image)
 
             for (indx=0; indx < (ssize_t) image->colors; indx++)
               {
-                ok_to_reduce=
-                 (((((size_t) image->colormap[indx].red >> pnghi) & 0xff)
-                  == (((size_t) image->colormap[indx].red >> pnglo) & 0xff)) &&
-                  ((((size_t) image->colormap[indx].green >> pnghi) & 0xff)
-                  == (((size_t) image->colormap[indx].green >> pnglo) & 0xff))
-                  && ((((size_t) image->colormap[indx].blue >> pnghi) & 0xff)
-                  == (((size_t) image->colormap[indx].blue >> pnglo) & 0xff)) &&
-                  (image->matte == MagickFalse ||
-                  (((size_t) image->colormap[indx].opacity >> pnghi) & 0xff)
-                  == (((size_t) image->colormap[indx].opacity >> pnglo)
-                  & 0xff))) ?  MagickTrue : MagickFalse;
+                ok_to_reduce=(
+                   QuantumToCharToQuantumEqQuantum(
+                   image->colormap[indx].red) &&
+                   QuantumToCharToQuantumEqQuantum(
+                   image->colormap[indx].green) &&
+                   QuantumToCharToQuantumEqQuantum(
+                   image->colormap[indx].blue)) ?
+                   MagickTrue : MagickFalse;
+
                 if (ok_to_reduce == MagickFalse)
-                  break;
+                   break;
               }
           }
 
@@ -574,17 +594,11 @@ LosslessReduceDepthOK(Image *image)
 
               for (x=(ssize_t) image->columns-1; x >= 0; x--)
               {
-                ok_to_reduce=(
-                  ((((size_t) p->red >> pnghi) & 0xff) ==
-                  (((size_t) p->red >> pnglo) & 0xff)) &&
-                  ((((size_t) p->green >> pnghi) & 0xff) ==
-                  (((size_t) p->green >> pnglo) & 0xff)) &&
-                  ((((size_t) p->blue >> pnghi) & 0xff) ==
-                  (((size_t) p->blue >> pnglo) & 0xff)) &&
-                  (((image->matte == MagickFalse ||
-                  (((size_t) p->opacity >> pnghi) & 0xff) ==
-                  (((size_t) p->opacity >> pnglo) & 0xff))))) ?
-                  MagickTrue : MagickFalse;
+                ok_to_reduce=
+                   QuantumToCharToQuantumEqQuantum(GetRedPixelComponent(p)) &&
+                   QuantumToCharToQuantumEqQuantum(GetGreenPixelComponent(p)) &&
+                   QuantumToCharToQuantumEqQuantum(GetBluePixelComponent(p)) ?
+                   MagickTrue : MagickFalse;
 
                 if (ok_to_reduce == MagickFalse)
                   break;
@@ -2045,6 +2059,9 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
                       background.blue=(png_uint_16)
                         mng_info->global_plte[background.index].blue;
 
+                      background.gray=(png_uint_16)
+                        mng_info->global_plte[background.index].green;
+
                       png_set_bKGD(ping,ping_info,&background);
                     }
 #endif
@@ -2451,10 +2468,6 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
           if (q == (PixelPacket *) NULL)
             break;
 
-#if  (0 && (MAGICKCORE_QUANTUM_DEPTH == 8) && !defined(MAGICKCORE_HDRI_SUPPORT))
-/* code deleted from version 6.6.6-8 */
-#else  /* (MAGICKCORE_QUANTUM_DEPTH != 8) */
-
           if ((int) ping_color_type == PNG_COLOR_TYPE_GRAY)
             (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
               GrayQuantum,ping_pixels+row_offset,exception);
@@ -2474,7 +2487,7 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
           else /* ping_color_type == PNG_COLOR_TYPE_RGB */
             (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
               RGBQuantum,ping_pixels+row_offset,exception);
-#endif
+
           if (found_transparent_pixel == MagickFalse)
             {
               /* Is there a transparent pixel in the row? */
@@ -2486,7 +2499,7 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
               {
                 if ((ping_color_type == PNG_COLOR_TYPE_RGBA ||
                     ping_color_type == PNG_COLOR_TYPE_GRAY_ALPHA) &&
-                   (q->opacity != OpaqueOpacity))
+                   (GetOpacityPixelComponent(q) != OpaqueOpacity))
                   {
                     if (logging != MagickFalse)
                       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -2497,9 +2510,12 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
                   }
                 if ((ping_color_type == PNG_COLOR_TYPE_RGB ||
                     ping_color_type == PNG_COLOR_TYPE_GRAY) &&
-                    (ScaleQuantumToShort(q->red) == transparent_color.red &&
-                    ScaleQuantumToShort(q->green) == transparent_color.green &&
-                    ScaleQuantumToShort(q->blue) == transparent_color.blue))
+                    (ScaleQuantumToShort(GetRedPixelComponent(q))
+                    == transparent_color.red &&
+                    ScaleQuantumToShort(GetGreenPixelComponent(q))
+                    == transparent_color.green &&
+                    ScaleQuantumToShort(GetBluePixelComponent(q))
+                    == transparent_color.blue))
                   {
                     if (logging != MagickFalse)
                       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -2639,8 +2655,9 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
                  * In a PNG datastream, Opaque is QuantumRange
                  * and Transparent is 0.
                  */
-                q->opacity=ScaleCharToQuantum((unsigned char) (255-(*p++)));
-                if (q->opacity != OpaqueOpacity)
+                SetOpacityPixelComponent(q,
+                    ScaleCharToQuantum((unsigned char) (255-(*p++))));
+                if (GetOpacityPixelComponent(q) != OpaqueOpacity)
                   found_transparent_pixel = MagickTrue;
                 q++;
               }
@@ -2675,8 +2692,8 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
                 {
                   quantum=((*p++) << 8);
                   quantum|=(*p++);
-                  q->opacity=(Quantum) (QuantumRange-quantum);
-                  if (q->opacity != OpaqueOpacity)
+                  SetOpacityPixelComponent(q,(Quantum) (QuantumRange-quantum));
+                  if (GetOpacityPixelComponent(q) != OpaqueOpacity)
                     found_transparent_pixel = MagickTrue;
                   q++;
                 }
@@ -2698,10 +2715,11 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
 
               if (ping_color_type == 4)
                 {
-                  q->opacity=(*p << 8) | *(p+1);
-                  q->opacity*=65537L;
-                  q->opacity=(Quantum) GetAlphaPixelComponent(q);
-                  if (q->opacity != OpaqueOpacity)
+                  quantum=(*p << 8) | *(p+1);
+                  quantum*=65537L;
+                  SetOpacityPixelComponent(q,
+                    (Quantum) GetAlphaPixelComponent(q));
+                  if (GetOpacityPixelComponent(q) != OpaqueOpacity)
                     found_transparent_pixel = MagickTrue;
                   p+=2;
                   q++;
@@ -2713,8 +2731,8 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
 
               if (ping_color_type == 4)
                 {
-                  q->opacity=(Quantum) (QuantumRange-(*p++));
-                  if (q->opacity != OpaqueOpacity)
+                  SetOpacityPixelComponent(q,(Quantum) (QuantumRange-(*p++)));
+                  if (GetOpacityPixelComponent(q) != OpaqueOpacity)
                     found_transparent_pixel = MagickTrue;
                   p++;
                   q++;
@@ -2729,13 +2747,14 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
           default:
             break;
         }
+
         /*
           Transfer image scanline.
         */
         r=quantum_scanline;
 
         for (x=0; x < (ssize_t) image->columns; x++)
-          indexes[x]=(IndexPacket) (*r++);
+          SetIndexPixelComponent(indexes+x,*r++);
 
         if (SyncAuthenticPixels(image,exception) == MagickFalse)
           break;
@@ -2743,7 +2762,7 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
         if ((image->previous == (Image *) NULL) && (num_passes == 1))
           {
             status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
-                image->rows);
+              image->rows);
 
             if (status == MagickFalse)
               break;
@@ -2868,17 +2887,20 @@ static Image *ReadOnePNGImage(MngInfo *mng_info,
              */
             for (x=(ssize_t) image->columns-1; x >= 0; x--)
             {
-              if (ScaleQuantumToShort(q->red) == transparent_color.red &&
-                  ScaleQuantumToShort(q->green) == transparent_color.green &&
-                  ScaleQuantumToShort(q->blue) == transparent_color.blue)
+              if (ScaleQuantumToShort(GetRedPixelComponent(q))
+                  == transparent_color.red &&
+                  ScaleQuantumToShort(GetGreenPixelComponent(q))
+                  == transparent_color.green &&
+                  ScaleQuantumToShort(GetBluePixelComponent(q))
+                  == transparent_color.blue)
                 {
-                  q->opacity=(Quantum) TransparentOpacity;
+                  SetOpacityPixelComponent(q,TransparentOpacity);
                 }
 
 #if 0 /* I have not found a case where this is needed. */
               else
                 {
-                  q->opacity=(Quantum) OpaqueOpacity;
+                  SetOpacityPixelComponent(q)=(Quantum) OpaqueOpacity;
                 }
 #endif
 
@@ -3268,6 +3290,7 @@ static Image *ReadPNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
       ThrowReaderException(CorruptImageError,"CorruptImage");
     }
 
+#if 0 /* This is probably redundant now */
   if (LocaleCompare(image_info->magick,"PNG8") == 0)
     {
       (void) SetImageType(image,PaletteType);
@@ -3277,6 +3300,7 @@ static Image *ReadPNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
           /* To do: Reduce to binary transparency */
         }
     }
+#endif
 
   if (LocaleCompare(image_info->magick,"PNG24") == 0)
     {
@@ -3950,13 +3974,15 @@ static Image *ReadOneJNGImage(MngInfo *mng_info,
 
              if (image->matte != MagickFalse)
                for (x=(ssize_t) image->columns; x != 0; x--,q++,s++)
-                  q->opacity=(Quantum) QuantumRange-s->red;
+                  SetOpacityPixelComponent(q,(Quantum) QuantumRange-
+                      GetRedPixelComponent(s));
 
              else
                for (x=(ssize_t) image->columns; x != 0; x--,q++,s++)
                {
-                  q->opacity=(Quantum) QuantumRange-s->red;
-                  if (q->opacity != OpaqueOpacity)
+                  SetOpacityPixelComponent(q,(Quantum) QuantumRange-
+                      GetRedPixelComponent(s));
+                  if (GetOpacityPixelComponent(q) != OpaqueOpacity)
                     image->matte=MagickTrue;
                }
 
@@ -5764,7 +5790,7 @@ static Image *ReadMNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
                 magn_methx=mng_info->magn_methx;
                 magn_methy=mng_info->magn_methy;
 
-#if (MAGICKCORE_QUANTUM_DEPTH == 32)
+#if (MAGICKCORE_QUANTUM_DEPTH > 16)
 #define QM unsigned short
                 if (magn_methx != 1 || magn_methy != 1)
                   {
@@ -5779,10 +5805,14 @@ static Image *ReadMNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
 
                        for (x=(ssize_t) image->columns-1; x >= 0; x--)
                        {
-                          q->red=ScaleQuantumToShort(q->red);
-                          q->green=ScaleQuantumToShort(q->green);
-                          q->blue=ScaleQuantumToShort(q->blue);
-                          q->opacity=ScaleQuantumToShort(q->opacity);
+                          SetRedPixelComponent(q,ScaleQuantumToShort(
+                            GetRedPixelComponent(q));
+                          SetGreenPixelComponent(q,ScaleQuantumToShort(
+                            GetGreenPixelComponent(q));
+                          SetBluePixelComponent(q,ScaleQuantumToShort(
+                            GetBluePixelComponent(q));
+                          SetOpacityPixelComponent(q,ScaleQuantumToShort(
+                            GetOpacityPixelComponent(q));
                           q++;
                        }
 
@@ -5868,6 +5898,7 @@ static Image *ReadMNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
 
                   for (i=0; i < m; i++, yy++)
                   {
+                    /* To do: Rewrite using Get/Set***PixelComponent() */
                     register PixelPacket
                       *pixels;
 
@@ -5875,7 +5906,7 @@ static Image *ReadMNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
                     pixels=prev;
                     n=next;
                     q=GetAuthenticPixels(large_image,0,yy,large_image->columns,
-                          1,exception);
+                      1,exception);
                     q+=(large_image->columns-image->columns);
 
                     for (x=(ssize_t) image->columns-1; x >= 0; x--)
@@ -5980,12 +6011,15 @@ static Image *ReadMNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
                     *pixels;
 
                   q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
+                  /* To do: Rewrite using Get/Set***PixelComponent() */
                   pixels=q+(image->columns-length);
                   n=pixels+1;
 
                   for (x=(ssize_t) (image->columns-length);
                     x < (ssize_t) image->columns; x++)
                   {
+                    /* To do: Rewrite using Get/Set***PixelComponent() */
+
                     if (x == (ssize_t) (image->columns-length))
                       m=(ssize_t) mng_info->magn_ml;
 
@@ -6006,6 +6040,7 @@ static Image *ReadMNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
                       if (magn_methx <= 1)
                         {
                           /* replicate previous */
+                          /* To do: Rewrite using Get/Set***PixelComponent() */
                           *q=(*pixels);
                         }
 
@@ -6068,7 +6103,7 @@ static Image *ReadMNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
                   if (SyncAuthenticPixels(image,exception) == MagickFalse)
                     break;
                 }
-#if (MAGICKCORE_QUANTUM_DEPTH == 32)
+#if (MAGICKCORE_QUANTUM_DEPTH > 16)
               if (magn_methx != 1 || magn_methy != 1)
                 {
                 /*
@@ -6080,10 +6115,14 @@ static Image *ReadMNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
 
                      for (x=(ssize_t) image->columns-1; x >= 0; x--)
                      {
-                        q->red=ScaleShortToQuantum(q->red);
-                        q->green=ScaleShortToQuantum(q->green);
-                        q->blue=ScaleShortToQuantum(q->blue);
-                        q->opacity=ScaleShortToQuantum(q->opacity);
+                        SetRedPixelComponent(q,ScaleShortToQuantum(
+                            GetRedPixelComponent(q));
+                        SetGreenPixelComponent(q,ScaleShortToQuantum(
+                            GetGreenPixelComponent(q));
+                        SetBluePixelComponent(q,ScaleShortToQuantum(
+                            GetBluePixelComponent(q));
+                        SetOpacityPixelComponent(q,ScaleShortToQuantum(
+                            GetOpacityPixelComponent(q));
                         q++;
                      }
 
@@ -6186,7 +6225,7 @@ static Image *ReadMNGImage(const ImageInfo *image_info,ExceptionInfo *exception)
          image->depth=16;
 #endif
 
-#if (MAGICKCORE_QUANTUM_DEPTH >= 16)
+#if (MAGICKCORE_QUANTUM_DEPTH > 8)
       if (LosslessReduceDepthOK(image) != MagickFalse)
          image->depth = 8;
 #endif
@@ -7096,14 +7135,17 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
           "    storage_class=PseudoClass");
     }
 
-  if (image->storage_class != PseudoClass && image->colormap != NULL)
+  if (ping_preserve_colormap == MagickFalse)
     {
-      /* Free the bogus colormap; it can cause trouble later */
-       if (logging != MagickFalse)
-          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
-          "    Freeing bogus colormap");
-       (void *) RelinquishMagickMemory(image->colormap);
-       image->colormap=NULL;
+      if (image->storage_class != PseudoClass && image->colormap != NULL)
+        {
+          /* Free the bogus colormap; it can cause trouble later */
+           if (logging != MagickFalse)
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+              "    Freeing bogus colormap");
+           (void *) RelinquishMagickMemory(image->colormap);
+           image->colormap=NULL;
+        }
     }
    
   if (image->colorspace != RGBColorspace)
@@ -7133,7 +7175,7 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
     }
 #endif
 
-#if 0 /* To do: honor -depth */
+#if 0 /* To do: respect the -depth option */
   if (image->depth < MAGICKCORE_QUANTUM_DEPTH)
     {
     }
@@ -7151,7 +7193,7 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
       image->depth=16;
 #endif
 
-#if (MAGICKCORE_QUANTUM_DEPTH >= 16)
+#if (MAGICKCORE_QUANTUM_DEPTH > 8)
   if (image->depth == 16 && mng_info->write_png_depth != 16)
     if (mng_info->write_png8 || LosslessReduceDepthOK(image) != MagickFalse)
       image->depth = 8;
@@ -7192,9 +7234,6 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
      * we need to check for bogus non-opaque values, at least.
      */
 
-#  define PNGK (MAGICKCORE_QUANTUM_DEPTH-8) /* Shift */
-#  define PNGM (ScaleCharToQuantum((unsigned char) 0x01)) /* Scale */
-
    ExceptionInfo
      *exception;
 
@@ -7292,20 +7331,21 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
 
        for (x=0; x < (ssize_t) image->columns; x++)
        {
-           if (image->matte == MagickFalse || q->opacity == OpaqueOpacity)
+           if (image->matte == MagickFalse ||
+              GetOpacityPixelComponent(q) == OpaqueOpacity)
              {
                if (number_opaque < 259)
                  {
                    if (number_opaque == 0)
                      {
-                       opaque[0]=*q;
+                       GetRGBPixelComponents(q, opaque[0]);
                        opaque[0].opacity=OpaqueOpacity;
                        number_opaque=1;
                      }
 
                    for (i=0; i< (ssize_t) number_opaque; i++)
                      {
-                       if (IsColorEqual(opaque+i, (PixelPacket *) q))
+                       if (IsColorEqual(q, opaque+i))
                          break;
                      }
 
@@ -7313,8 +7353,8 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
                        number_opaque < 259)
                      {
                        number_opaque++;
-                       opaque[i] = *q;
-                       opaque[i].opacity = OpaqueOpacity;
+                       GetRGBPixelComponents(q, opaque[i]);
+                       opaque[i].opacity=OpaqueOpacity;
                      }
                  }
              }
@@ -7324,17 +7364,21 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
                  {
                    if (number_transparent == 0)
                      {
-                       transparent[0]=*q;
-                       ping_trans_color.red=(unsigned short)(q->red);
-                       ping_trans_color.green=(unsigned short) (q->green);
-                       ping_trans_color.blue=(unsigned short) (q->blue);
-                       ping_trans_color.gray=(unsigned short) (q->blue);
+                       GetRGBOPixelComponents(q, transparent[0]);
+                       ping_trans_color.red=
+                         (unsigned short) GetRedPixelComponent(q);
+                       ping_trans_color.green=
+                         (unsigned short) GetGreenPixelComponent(q);
+                       ping_trans_color.blue=
+                         (unsigned short) GetBluePixelComponent(q);
+                       ping_trans_color.gray=
+                         (unsigned short) GetRedPixelComponent(q);
                        number_transparent = 1;
                      }
 
                    for (i=0; i< (ssize_t) number_transparent; i++)
                      {
-                       if (IsColorEqual(transparent+i, (PixelPacket *) q))
+                       if (IsColorEqual(q, transparent+i))
                          break;
                      }
 
@@ -7342,7 +7386,7 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
                        number_transparent < 259)
                      {
                        number_transparent++;
-                       transparent[i] = *q;
+                       GetRGBOPixelComponents(q, transparent[i]);
                      }
                  }
              }
@@ -7352,15 +7396,15 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
                  {
                    if (number_semitransparent == 0)
                      {
-                       semitransparent[0]=*q;
+                       GetRGBOPixelComponents(q, semitransparent[0]);
                        number_semitransparent = 1;
                      }
 
                    for (i=0; i< (ssize_t) number_semitransparent; i++)
                      {
-                       if (IsColorEqual(semitransparent+i,
-                          (PixelPacket *) q) &&
-                          q->opacity == semitransparent[i].opacity)
+                       if (IsColorEqual(q, semitransparent+i)
+                           && GetOpacityPixelComponent(q) ==
+                           semitransparent[i].opacity)
                          break;
                      }
 
@@ -7368,7 +7412,7 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
                        number_semitransparent < 259)
                      {
                        number_semitransparent++;
-                       semitransparent[i] = *q;
+                       GetRGBOPixelComponents(q, semitransparent[i]);
                      }
                  }
              }
@@ -7381,17 +7425,31 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
          /* Add the background color to the palette, if it
           * isn't already there.
           */
+          if (logging != MagickFalse)
+            {
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                  "      Check colormap for background (%d,%d,%d)",
+                  (int) image->background_color.red,
+                  (int) image->background_color.green,
+                  (int) image->background_color.blue);
+            }
           for (i=0; i<number_opaque; i++)
           {
-             if (IsColorEqual(opaque+i, &image->background_color))
-             break;
+             if (opaque[i].red == image->background_color.red &&
+                 opaque[i].green == image->background_color.green &&
+                 opaque[i].blue == image->background_color.blue)
+               break;
           }
-
           if (number_opaque < 259 && i == number_opaque)
             {
-               opaque[i]=image->background_color;
-               opaque[i].opacity = OpaqueOpacity;
-               number_opaque++;
+               opaque[i] = image->background_color;
+               ping_background.index = i;
+               if (logging != MagickFalse)
+                 {
+                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                       "      background_color index is %d",(int) i);
+                 }
+
             }
           else if (logging != MagickFalse)
               (void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -7418,10 +7476,8 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
                   "      image has %d colors",image_colors);
        }
 
-#if 1 /* To do */
      if (ping_preserve_colormap != MagickFalse)
        break;
-#endif
 
      if (mng_info->write_png_colortype != 7) /* We won't need this info */
        {
@@ -7446,7 +7502,8 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
                    s=q;
                    for (x=0; x < (ssize_t) image->columns; x++)
                    {
-                     if (s->red != s->green || s->red != s->blue)
+                     if (GetRedPixelComponent(s) != GetGreenPixelComponent(s)
+                        || GetRedPixelComponent(s) != GetBluePixelComponent(s))
                        {
                           ping_have_color=MagickTrue;
                           ping_have_non_bw=MagickTrue;
@@ -7461,7 +7518,8 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
                    s=q;
                    for (x=0; x < (ssize_t) image->columns; x++)
                    {
-                     if (s->red != 0 && s->red != QuantumRange)
+                     if (GetRedPixelComponent(s) != 0 &&
+                         GetRedPixelComponent(s) != QuantumRange)
                        {
                          ping_have_non_bw=MagickTrue;
                        }
@@ -7498,6 +7556,8 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
          for (i=0; i<number_opaque; i++)
             colormap[n++] = opaque[i];
 
+         ping_background.index +=
+           (number_transparent + number_semitransparent);
          
          /* image_colors < 257; search the colormap instead of the pixels
           * to get ping_have_color and ping_have_non_bw
@@ -7543,7 +7603,8 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
 
             if (AcquireImageColormap(image,image_colors) ==
                 MagickFalse)
-               ThrowWriterException(ResourceLimitError, "MemoryAllocationFailed");
+               ThrowWriterException(ResourceLimitError,
+                   "MemoryAllocationFailed");
 
             for (i=0; i< (ssize_t) image_colors; i++)
                image->colormap[i] = colormap[i];
@@ -7575,11 +7636,16 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
                 for (i=0; i< (ssize_t) image_colors; i++)
                 {
                   if ((image->matte == MagickFalse ||
-                      image->colormap[i].opacity == q->opacity) &&
-                      (IsColorEqual(&image->colormap[i],
-                         (PixelPacket *) q)))
+                      image->colormap[i].opacity == 
+                      GetOpacityPixelComponent(q)) &&
+                      image->colormap[i].red == 
+                      GetRedPixelComponent(q) &&
+                      image->colormap[i].green == 
+                      GetGreenPixelComponent(q) &&
+                      image->colormap[i].blue == 
+                      GetBluePixelComponent(q))
                   {
-                    indexes[x]=(IndexPacket) i;
+                    SetIndexPixelComponent(indexes+x,i);
                     break;
                   }
                 }
@@ -7688,8 +7754,9 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
 
           for (x=0; x < (ssize_t) image->columns; x++)
           {
-              r->opacity = r->opacity > TransparentOpacity/2 ?
-                   TransparentOpacity : OpaqueOpacity;
+              SetOpacityPixelComponent(r,
+              (GetOpacityPixelComponent(r) > TransparentOpacity/2) ?
+                   TransparentOpacity : OpaqueOpacity);
               r++;
           }
   
@@ -7720,20 +7787,17 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
         tried_444 = MagickTrue;
 
         image->background_color.red=
-            ((((((size_t)
-            image->background_color.red) >> PNGK) & 0xf0)     )  |
-            (((((size_t)
-            image->background_color.red) >> PNGK) & 0xf0) >> 4)) * PNGM;
+            ScaleCharToQuantum(
+            (ScaleQuantumToChar(image->background_color.red) & 0xf0) |
+            (ScaleQuantumToChar(image->background_color.red) & 0xf0) >> 4);
         image->background_color.green=
-            ((((((size_t)
-            image->background_color.green) >> PNGK) & 0xf0)     )  |
-            (((((size_t)
-            image->background_color.green) >> PNGK) & 0xf0) >> 4)) * PNGM;
+            ScaleCharToQuantum(
+            (ScaleQuantumToChar(image->background_color.green) & 0xf0) |
+            (ScaleQuantumToChar(image->background_color.green) & 0xf0) >> 4);
         image->background_color.blue=
-            ((((((size_t)
-            image->background_color.blue) >> PNGK) & 0xf0)     )  |
-            (((((size_t)
-            image->background_color.blue) >> PNGK) & 0xf0) >> 4)) * PNGM;
+            ScaleCharToQuantum(
+            (ScaleQuantumToChar(image->background_color.blue) & 0xf0) |
+            (ScaleQuantumToChar(image->background_color.blue) & 0xf0) >> 4);
 
         if (logging != MagickFalse)
           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -7751,23 +7815,23 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
 
             for (x=0; x < (ssize_t) image->columns; x++)
             {
-              if (r->opacity == TransparentOpacity)
+              if (GetOpacityPixelComponent(r) == TransparentOpacity)
                 {
-                  r->red = image->background_color.red;
-                  r->green = image->background_color.green;
-                  r->blue = image->background_color.blue;
+                  SetRGBPixelComponents(r,image->background_color);
                 }
               else
                 {
-                  r->red=
-                       ((((((size_t) r->red) >> PNGK) & 0xf0)    )  |
-                       (((((size_t) r->red) >> PNGK) & 0xf0) >> 4)) * PNGM;
-                  r->green=
-                       ((((((size_t) r->green) >> PNGK) & 0xf0)    )  |
-                       (((((size_t) r->green) >> PNGK) & 0xf0) >> 4)) * PNGM;
-                  r->blue=
-                       ((((((size_t) r->blue) >> PNGK) & 0xf0)    )  |
-                       (((((size_t) r->blue) >> PNGK) & 0xf0) >> 4)) * PNGM;
+                  SetRedPixelComponent(r,ScaleCharToQuantum(
+                    (ScaleQuantumToChar(GetRedPixelComponent(r)) & 0xf0) |
+                    (ScaleQuantumToChar(GetRedPixelComponent(r)) & 0xf0) >> 4));
+                  SetGreenPixelComponent(r,ScaleCharToQuantum(
+                    (ScaleQuantumToChar(GetGreenPixelComponent(r)) & 0xf0) |
+                    (ScaleQuantumToChar(GetGreenPixelComponent(r)) & 0xf0) >>
+                    4));
+                  SetBluePixelComponent(r,ScaleCharToQuantum(
+                    (ScaleQuantumToChar(GetBluePixelComponent(r)) & 0xf0) |
+                    (ScaleQuantumToChar(GetBluePixelComponent(r)) & 0xf0) >>
+                    4));
                 }
               r++;
             }
@@ -7785,21 +7849,15 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
               "    Quantizing the colormap to 4-4-4");
           for (i=0; i<image_colors; i++)
           {
-              image->colormap[i].red=
-                  ((((((size_t)
-                  image->colormap[i].red) >> PNGK) & 0xf0)     )  |
-                  (((((size_t)
-                  image->colormap[i].red) >> PNGK) & 0xf0) >> 4)) * PNGM;
-              image->colormap[i].green=
-                  ((((((size_t)
-                  image->colormap[i].green) >> PNGK) & 0xf0)     )  |
-                  (((((size_t)
-                  image->colormap[i].green) >> PNGK) & 0xf0) >> 4)) * PNGM;
-              image->colormap[i].blue=
-                  ((((((size_t)
-                  image->colormap[i].blue) >> PNGK) & 0xf0)     )  |
-                  (((((size_t)
-                  image->colormap[i].blue) >> PNGK) & 0xf0) >> 4)) * PNGM;
+            image->colormap[i].red=ScaleCharToQuantum(
+                 (ScaleQuantumToChar(image->colormap[i].red) & 0xf0) |
+                 (ScaleQuantumToChar(image->colormap[i].red) & 0xf0) >> 4);
+            image->colormap[i].green=ScaleCharToQuantum(
+                 (ScaleQuantumToChar(image->colormap[i].green) & 0xf0) |
+                 (ScaleQuantumToChar(image->colormap[i].green) & 0xf0) >> 4);
+            image->colormap[i].blue=ScaleCharToQuantum(
+                 (ScaleQuantumToChar(image->colormap[i].blue) & 0xf0) |
+                 (ScaleQuantumToChar(image->colormap[i].blue) & 0xf0 >> 4));
           }
         }
         continue;
@@ -7814,26 +7872,20 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
         tried_333 = MagickTrue;
 
         image->background_color.red=
-            ((((((size_t)
-            image->background_color.red) >> PNGK) & 0xe0)     )  |
-            (((((size_t)
-            image->background_color.red) >> PNGK) & 0xe0) >> 3)  |
-            (((((size_t)
-            image->background_color.red) >> PNGK) & 0xc0) >> 6)) * PNGM;
+            ScaleCharToQuantum(
+            (ScaleQuantumToChar(image->background_color.red) & 0xe0) |
+            (ScaleQuantumToChar(image->background_color.red) & 0xe0) >> 3 |
+            (ScaleQuantumToChar(image->background_color.red) & 0xc0) >> 6);
         image->background_color.green=
-            ((((((size_t)
-            image->background_color.green) >> PNGK) & 0xe0)     )  |
-            (((((size_t)
-            image->background_color.green) >> PNGK) & 0xe0) >> 3)  |
-            (((((size_t)
-            image->background_color.green) >> PNGK) & 0xc0) >> 6)) * PNGM;
+            ScaleCharToQuantum(
+            (ScaleQuantumToChar(image->background_color.green) & 0xe0) |
+            (ScaleQuantumToChar(image->background_color.green) & 0xe0) >> 3 |
+            (ScaleQuantumToChar(image->background_color.green) & 0xc0) >> 6);
         image->background_color.blue=
-            ((((((size_t)
-            image->background_color.blue) >> PNGK) & 0xe0)     )  |
-            (((((size_t)
-            image->background_color.blue) >> PNGK) & 0xe0) >> 3)  |
-            (((((size_t)
-            image->background_color.blue) >> PNGK) & 0xc0) >> 6)) * PNGM;
+            ScaleCharToQuantum(
+            (ScaleQuantumToChar(image->background_color.blue) & 0xe0) |
+            (ScaleQuantumToChar(image->background_color.blue) & 0xe0) >> 3 |
+            (ScaleQuantumToChar(image->background_color.blue) & 0xc0) >> 6);
 
         if (logging != MagickFalse)
           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -7851,26 +7903,28 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
 
             for (x=0; x < (ssize_t) image->columns; x++)
             {
-              if (r->opacity == TransparentOpacity)
+              if (GetOpacityPixelComponent(r) == TransparentOpacity)
                 {
-                  r->red = image->background_color.red;
-                  r->green = image->background_color.green;
-                  r->blue = image->background_color.blue;
+                  SetRGBPixelComponents(r,image->background_color);
                 }
               else
                 {
-                  r->red=
-                       ((((((size_t) r->red) >> PNGK) & 0xe0)    )  |
-                       (((((size_t) r->red) >> PNGK) & 0xe0) >> 3)  |
-                       (((((size_t) r->red) >> PNGK) & 0xc0) >> 6)) * PNGM;
-                  r->green=
-                       ((((((size_t) r->green) >> PNGK) & 0xe0)    )  |
-                       (((((size_t) r->green) >> PNGK) & 0xe0) >> 3)  |
-                       (((((size_t) r->green) >> PNGK) & 0xc0) >> 6)) * PNGM;
-                  r->blue=
-                       ((((((size_t) r->blue) >> PNGK) & 0xe0)    )  |
-                       (((((size_t) r->blue) >> PNGK) & 0xe0) >> 3)  |
-                       (((((size_t) r->blue) >> PNGK) & 0xc0) >> 6)) * PNGM;
+                  SetRedPixelComponent(r,ScaleCharToQuantum(
+                    (ScaleQuantumToChar(GetRedPixelComponent(r)) & 0xe0) |
+                    (ScaleQuantumToChar(GetRedPixelComponent(r)) & 0xe0) >> 3 |
+                    (ScaleQuantumToChar(GetRedPixelComponent(r)) & 0xc0) >>
+                    6));
+                  SetGreenPixelComponent(r,ScaleCharToQuantum(
+                    (ScaleQuantumToChar(GetGreenPixelComponent(r)) & 0xe0) |
+                    (ScaleQuantumToChar(GetGreenPixelComponent(r)) & 0xe0) >>
+                    3 |
+                    (ScaleQuantumToChar(GetGreenPixelComponent(r)) & 0xc0) >>
+                    6));
+                  SetBluePixelComponent(r,ScaleCharToQuantum(
+                    (ScaleQuantumToChar(GetBluePixelComponent(r)) & 0xe0) |
+                    (ScaleQuantumToChar(GetBluePixelComponent(r)) & 0xe0) >> 3 |
+                    (ScaleQuantumToChar(GetBluePixelComponent(r)) & 0xc0) >>
+                    6));
                 }
               r++;
             }
@@ -7888,27 +7942,18 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
               "    Quantizing the colormap to 3-3-3-1");
           for (i=0; i<image_colors; i++)
           {
-              image->colormap[i].red=
-                  ((((((size_t)
-                  image->colormap[i].red) >> PNGK) & 0xe0)     )  |
-                  (((((size_t)
-                  image->colormap[i].red) >> PNGK) & 0xe0) >> 3)  |
-                  (((((size_t)
-                  image->colormap[i].red) >> PNGK) & 0xc0) >> 6)) * PNGM;
-              image->colormap[i].green=
-                  ((((((size_t)
-                  image->colormap[i].green) >> PNGK) & 0xe0)     )  |
-                  (((((size_t)
-                  image->colormap[i].green) >> PNGK) & 0xe0) >> 3)  |
-                  (((((size_t)
-                  image->colormap[i].green) >> PNGK) & 0xc0) >> 6)) * PNGM;
-              image->colormap[i].blue=
-                  ((((((size_t)
-                  image->colormap[i].blue) >> PNGK) & 0xe0)     )  |
-                  (((((size_t)
-                  image->colormap[i].blue) >> PNGK) & 0xe0) >> 3)  |
-                  (((((size_t)
-                  image->colormap[i].blue) >> PNGK) & 0xc0) >> 6)) * PNGM;
+              image->colormap[i].red=ScaleCharToQuantum(
+                   (ScaleQuantumToChar(image->colormap[i].red) & 0xe0) |
+                   (ScaleQuantumToChar(image->colormap[i].red) & 0xe0) >> 3 |
+                   (ScaleQuantumToChar(image->colormap[i].red) & 0xc0) >> 6);
+              image->colormap[i].green=ScaleCharToQuantum(
+                   (ScaleQuantumToChar(image->colormap[i].green) & 0xe0) |
+                   (ScaleQuantumToChar(image->colormap[i].green) & 0xe0) >> 3 |
+                   (ScaleQuantumToChar(image->colormap[i].green) & 0xc0) >> 6);
+              image->colormap[i].blue=ScaleCharToQuantum(
+                   (ScaleQuantumToChar(image->colormap[i].blue) & 0xe0) |
+                   (ScaleQuantumToChar(image->colormap[i].blue) & 0xe0) >> 3 |
+                   (ScaleQuantumToChar(image->colormap[i].blue) & 0xc0) >> 6);
           }
         }
         continue;
@@ -7920,29 +7965,15 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
                "    Quantizing the background color to 3-3-2");
 
-        image->background_color.red=
-            ((((((size_t)
-            image->background_color.red) >> PNGK) & 0xe0)     )  |
-            (((((size_t)
-            image->background_color.red) >> PNGK) & 0xe0) >> 3)  |
-            (((((size_t)
-            image->background_color.red) >> PNGK) & 0xc0) >> 6)) * PNGM;
-        image->background_color.green=
-            ((((((size_t)
-            image->background_color.green) >> PNGK) & 0xe0)     )  |
-            (((((size_t)
-            image->background_color.green) >> PNGK) & 0xe0) >> 3)  |
-            (((((size_t)
-            image->background_color.green) >> PNGK) & 0xc0) >> 6)) * PNGM;
-        image->background_color.blue=
-            ((((((size_t)
-            image->background_color.blue) >> PNGK) & 0xc0)     )  |
-            (((((size_t)
-            image->background_color.blue) >> PNGK) & 0xc0) >> 2)  |
-            (((((size_t)
-            image->background_color.blue) >> PNGK) & 0xc0) >> 4)  |
-            (((((size_t)
-            image->background_color.blue) >> PNGK) & 0xc0) >> 6)) * PNGM;
+        /* Red and green were already done so we only quantize the blue
+         * channel
+         */
+
+        image->background_color.blue=ScaleCharToQuantum(
+            (ScaleQuantumToChar(image->background_color.blue) & 0xc0) |
+            (ScaleQuantumToChar(image->background_color.blue) & 0xc0) >> 2 |
+            (ScaleQuantumToChar(image->background_color.blue) & 0xc0) >> 4 |
+            (ScaleQuantumToChar(image->background_color.blue) & 0xc0) >> 6);
 
         if (logging != MagickFalse)
           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
@@ -7960,27 +7991,18 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
 
             for (x=0; x < (ssize_t) image->columns; x++)
             {
-              if (r->opacity == TransparentOpacity)
+              if (GetOpacityPixelComponent(r) == TransparentOpacity)
                 {
-                  r->red = image->background_color.red;
-                  r->green = image->background_color.green;
-                  r->blue = image->background_color.blue;
+                  SetRGBPixelComponents(r,image->background_color);
                 }
               else
                 {
-                  r->red=
-                       ((((((size_t) r->red) >> PNGK) & 0xe0)    )  |
-                       (((((size_t) r->red) >> PNGK) & 0xe0) >> 3)  |
-                       (((((size_t) r->red) >> PNGK) & 0xc0) >> 6)) * PNGM;
-                  r->green=
-                       ((((((size_t) r->green) >> PNGK) & 0xe0)    )  |
-                       (((((size_t) r->green) >> PNGK) & 0xe0) >> 3)  |
-                       (((((size_t) r->green) >> PNGK) & 0xc0) >> 6)) * PNGM;
-                  r->blue=
-                       ((((((size_t) r->blue) >> PNGK) & 0xc0)    )  |
-                       (((((size_t) r->blue) >> PNGK) & 0xc0) >> 2)  |
-                       (((((size_t) r->blue) >> PNGK) & 0xc0) >> 4)  |
-                       (((((size_t) r->blue) >> PNGK) & 0xc0) >> 6)) * PNGM;
+                  SetBluePixelComponent(r,ScaleCharToQuantum(
+                    (ScaleQuantumToChar(GetBluePixelComponent(r)) & 0xc0) |
+                    (ScaleQuantumToChar(GetBluePixelComponent(r)) & 0xc0) >> 2 |
+                    (ScaleQuantumToChar(GetBluePixelComponent(r)) & 0xc0) >> 4 |
+                    (ScaleQuantumToChar(GetBluePixelComponent(r)) & 0xc0) >>
+                    6));
                 }
               r++;
             }
@@ -7998,29 +8020,11 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
               "    Quantizing the colormap to 3-3-2-1");
           for (i=0; i<image_colors; i++)
           {
-              image->colormap[i].red=
-                  ((((((size_t)
-                  image->colormap[i].red) >> PNGK) & 0xe0)     )  |
-                  (((((size_t)
-                  image->colormap[i].red) >> PNGK) & 0xe0) >> 3)  |
-                  (((((size_t)
-                  image->colormap[i].red) >> PNGK) & 0xc0) >> 6)) * PNGM;
-              image->colormap[i].green=
-                  ((((((size_t)
-                  image->colormap[i].green) >> PNGK) & 0xe0)     )  |
-                  (((((size_t)
-                  image->colormap[i].green) >> PNGK) & 0xe0) >> 3)  |
-                  (((((size_t)
-                  image->colormap[i].green) >> PNGK) & 0xc0) >> 6)) * PNGM;
-              image->colormap[i].blue=
-                  ((((((size_t)
-                  image->colormap[i].blue) >> PNGK) & 0xc0)     )  |
-                  (((((size_t)
-                  image->colormap[i].blue) >> PNGK) & 0xc0) >> 2)  |
-                  (((((size_t)
-                  image->colormap[i].blue) >> PNGK) & 0xc0) >> 4)  |
-                  (((((size_t)
-                  image->colormap[i].blue) >> PNGK) & 0xc0) >> 6)) * PNGM;
+              image->colormap[i].blue=ScaleCharToQuantum(
+                  (ScaleQuantumToChar(image->colormap[i].blue) & 0xc0) |
+                  (ScaleQuantumToChar(image->colormap[i].blue) & 0xc0) >> 2 |
+                  (ScaleQuantumToChar(image->colormap[i].blue) & 0xc0) >> 4 |
+                  (ScaleQuantumToChar(image->colormap[i].blue) & 0xc0) >> 6);
           }
       }
       continue;
@@ -8036,7 +8040,7 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
   if (mng_info->ping_exclude_tRNS != MagickFalse &&
      (number_transparent != 0 || number_semitransparent != 0))
     {
-      int colortype=mng_info->write_png_colortype;
+      unsigned int colortype=mng_info->write_png_colortype;
 
       if (ping_have_color == MagickFalse)
         mng_info->write_png_colortype = 5;
@@ -8045,7 +8049,7 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
         mng_info->write_png_colortype = 7;
 
       if (colortype != 0 &&
-         mng_info->write_png_colortype != (ssize_t) colortype)
+         mng_info->write_png_colortype != colortype)
         ping_need_colortype_warning=MagickTrue;
 
     }
@@ -8086,9 +8090,12 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
              for (x=0; x < (ssize_t) image->columns; x++)
              {
                  if (q->opacity != TransparentOpacity &&
-                     (unsigned short) q->red == ping_trans_color.red &&
-                     (unsigned short) q->green == ping_trans_color.green &&
-                     (unsigned short) q->blue == ping_trans_color.blue)
+                     (unsigned short) GetRedPixelComponent(q) ==
+                     ping_trans_color.red &&
+                     (unsigned short) GetGreenPixelComponent(q) ==
+                     ping_trans_color.green &&
+                     (unsigned short) GetBluePixelComponent(q) ==
+                     ping_trans_color.blue)
                    {
                      ping_have_cheap_transparency = MagickFalse;
                      break;
@@ -8327,12 +8334,17 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
 
        ping_background.blue=(png_uint_16)
          (ScaleQuantumToShort(image->background_color.blue) & mask);
+
+       ping_background.gray=(png_uint_16) ping_background.green;
     }
 
   if (logging != MagickFalse)
     {
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
           "    Setting up bKGD chunk (1)");
+      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+          "      background_color index is %d",
+          (int) ping_background.index);
 
       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
           "    ping_bit_depth=%d",ping_bit_depth);
@@ -8420,6 +8432,13 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
             break;
 
         ping_background.index=(png_byte) i;
+
+        if (logging != MagickFalse)
+          {
+            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                 "      background_color index is %d",
+                 (int) ping_background.index);
+          }
       }
     } /* end of write_png8 */
 
@@ -8720,7 +8739,8 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
         if (image_depth > MAGICKCORE_QUANTUM_DEPTH)
           image_depth=MAGICKCORE_QUANTUM_DEPTH;
 
-        if ((image_colors == 0) || ((ssize_t) image_colors-1 > MaxColormapSize))
+        if ((image_colors == 0) ||
+             ((ssize_t) (image_colors-1) > (ssize_t) MaxColormapSize))
           image_colors=(int) (one << image_depth);
 
         if (image_depth > 8)
@@ -8829,7 +8849,7 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
                 ping_bit_depth=1;
                 one=1;
 
-                while ((one << ping_bit_depth) < number_colors)
+                while ((one << ping_bit_depth) < (ssize_t) number_colors)
                   ping_bit_depth <<= 1;
               }
 
@@ -8926,6 +8946,9 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
          if (logging != MagickFalse)
            (void) LogMagickEvent(CoderEvent,GetMagickModule(),
              "  Setting up bKGD chunk (2)");
+         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+             "      background_color index is %d",
+             (int) ping_background.index);
 
          ping_have_bKGD = MagickTrue;
          }
@@ -9325,7 +9348,23 @@ static MagickBooleanType WriteOnePNGImage(MngInfo *mng_info,
   if (ping_exclude_bKGD == MagickFalse)
     {
       if (ping_have_bKGD != MagickFalse)
+        {
           png_set_bKGD(ping,ping_info,&ping_background);
+          if (logging)
+            {
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                   "    Setting up bKGD chunk");
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                   "      background color = (%d,%d,%d)",
+                        (int) ping_background.red,
+                        (int) ping_background.green,
+                        (int) ping_background.blue);
+              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
+                   "      index = %d, gray=%d",
+                        (int) ping_background.index,
+                        (int) ping_background.gray);
+            }
+         }
     }
 
   if (ping_exclude_pHYs == MagickFalse)