title: PHP wrong result for imagetruecolortopalette with PNG with transparency
body: <p>I'm trying to write a PHP script that resizes a PNG image and then converts it to PNG-8 bit mode. So the size of the resulting file will be smaller but without too much quality loss.</p>
  <p>The resize works perfectly, preserving also image transparency:</p>
  <p><a href="https://pixabay.com/it/vectors/pinguino-uccello-animale-natura-42936/" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Q1avX.png" alt="originalImage" /></a></p>
  <p>The problem is when I convert the image in 8 bit:</p>
  <pre><code>imagetruecolortopalette($resizedImg, true, 255);
  
  imagealphablending($resizedImg, false);
  
  $transparent = imagecolorallocatealpha($resizedImg, 255, 255, 255, 127);
  if(!imagefill($resizedImg, 0, 0, $transparent)) return false;
  
  imagesavealpha($resizedImg, true);
  </code></pre>
  <p>The resulting image is this, with the transparency all around and a little inside the image:</p>
  <p><a href="https://i.stack.imgur.com/CdMHQ.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/CdMHQ.png" alt="enter image description here" /></a></p>
  <p>If I set 256 colors instead of 255:</p>
  <pre><code>imagetruecolortopalette($resizedImg, true, 256);
  </code></pre>
  <p>the image will be with black background:</p>
  <p><a href="https://i.stack.imgur.com/WGH7Y.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/WGH7Y.png" alt="enter image description here" /></a></p>
  <p>A similar result occurs with this image (note the half transparency for the case with 255 colors):</p>
  <p>Original:   <a href="https://i.stack.imgur.com/Hvr76.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Hvr76.png" alt="enter image description here" /></a>
  255 colors: <a href="https://i.stack.imgur.com/5Dnff.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/5Dnff.png" alt="enter image description here" /></a>
  256 colors: <a href="https://i.stack.imgur.com/7hn5D.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/7hn5D.png" alt="enter image description here" /></a></p>
  <p>The complete function's code:</p>
  <pre><code>function resizePng($originalPath, $xImgNew='', $yImgNew='', $newPath='')
  {
      if(!trim($originalPath) || !$xyOriginalPath = getimagesize(&quot;$originalPath&quot;)) return false;
      list($xImg, $yImg) = $xyOriginalPath;
      
      if(!$originalImg = imagecreatefrompng($originalPath)) return false;
      
      if(!$resizedImg = imagecreatetruecolor($xImgNew, $yImgNew)) return false;
      
      // preserve alpha
      imagealphablending($resizedImg, false);
      $transparent = imagecolorallocatealpha($resizedImg, 255, 255, 255, 127);
      if(!imagefill($resizedImg, 0, 0, $transparent)) return false;
      imagesavealpha($resizedImg, true);
      
      // copy content from originalImg to resizedImg
      if(!imagecopyresampled($resizedImg, $originalImg, 0, 0, 0, 0, $xImgNew, $yImgNew, $xImg, $yImg)) return false;
      
      // PNG-8 bit conversion
      imagetruecolortopalette($resizedImg, true, 255);
      
      // preserve alpha
      imagealphablending($resizedImg, false);
      $transparent = imagecolorallocatealpha($resizedImg, 255, 255, 255, 127);
      if(!imagefill($resizedImg, 0, 0, $transparent)) return false;
      imagesavealpha($resizedImg, true);
      
      if(!imagepng($resizedImg, ($newPath) ?: null, 8)) return false;
  
      return true;
  }
  </code></pre>
  <p>What I tried:</p>
  <p><a href="https://stackoverflow.com/a/8144620/2342558">https://stackoverflow.com/a/8144620/2342558</a></p>
  <pre><code>// PNG-8 bit conversion
  imagetruecolortopalette($resizedImg, true, 255);
  
  imagesavealpha($resizedImg, true);
  imagecolortransparent($resizedImg, imagecolorat($resizedImg,0,0));
  
  // preserve alpha
  imagealphablending($resizedImg, false);
  $transparent = imagecolorallocatealpha($resizedImg, 255, 255, 255, 127);
  if(!imagefill($resizedImg, 0, 0, $transparent)) return false;
  imagesavealpha($resizedImg, true);
  
  if(!imagepng($resizedImg, ($newPath) ?: null, 8)) return false;
  </code></pre>
  <p>Results:</p>
  <p><a href="https://i.stack.imgur.com/LhFp5.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/LhFp5.png" alt="enter image description here" /></a>
  <a href="https://i.stack.imgur.com/kbIwj.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/kbIwj.png" alt="enter image description here" /></a></p>
  <p>Also: <a href="https://stackoverflow.com/a/55402802/2342558">https://stackoverflow.com/a/55402802/2342558</a></p>
  <p>Nothing changed.</p>
  <p>Also: others SO posts and some on the Web</p>
  <p>Also without resizing the image (removing <code>imagecopyresampled</code> and adapting the variables name) the result is the same.</p>
  <p>How can I make it work and to understand the reason for this strange behaviour?</p>
  <p>Some info in <code>phpinfo()</code>:</p>
  <ul>
  <li>PHP <code>7.0.33</code></li>
  <li><code>GD</code> bundled (2.1.0 compatible)</li>
  <li><code>PNG Support</code> enabled</li>
  <li><code>libPNG</code> 1.5.13.</li>
  </ul>
  <p><em>Edit</em>:</p>
  <p>In GIMP v.2.8.22 I can save an image for Web with these properties:</p>
  <pre><code>PNG-8
  256 colors palette
  Dither: Floyd-Steinberg / Floyd-Steinberg 2 / positioned
  </code></pre>
  <p><a href="https://i.stack.imgur.com/jQeDZ.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/jQeDZ.png" alt="enter image description here" /></a>
  <a href="https://i.stack.imgur.com/7QUeN.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/7QUeN.png" alt="enter image description here" /></a></p>
  <p>and it produce a reduced image almost identical of the original.</p>
  <p>Also pngquant, tinypng, and many others do the same work, but <strong>I need to do it with PHP</strong>.</p>
  <p><em>Edit 2</em>:</p>
  <p>Unfortunately, <strong>I can't use ImageMagick</strong> because my code is in a shared hosting without it installed.</p>
  <p><em>Edit 3</em>:</p>
  <p>in <code>phpinfo()</code> results that the <code>imagemagick</code> module isn't installed.</p>
  <p><em>Edit 4</em>:</p>
  <p>Let me do some tests with your responses, maybe there is a solution with only PHP.</p>
  <p><em>Edit 5</em>:</p>
  <p>These are my attempts with your answers.</p>
  <p><em>Note: I put an underlying grid to better show the alpha.</em></p>
  <p><a href="https://stackoverflow.com/a/58075858/2342558">Thomas Huijzer's answer</a>:</p>
  <p><a href="https://i.stack.imgur.com/1fruW.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/1fruW.png" alt="enter image description here" /></a>
  <a href="https://i.stack.imgur.com/Z4LxB.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Z4LxB.png" alt="enter image description here" /></a></p>
  <p>There are visible color banding in the penguin but the duck its ok (although sometimes the color tone is darker).</p>
  <p><a href="https://stackoverflow.com/a/58126977/2342558">EPB's answer</a>:</p>
  <p><a href="https://i.stack.imgur.com/LHVzO.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/LHVzO.png" alt="enter image description here" /></a>
  <a href="https://i.stack.imgur.com/Z4LxB.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Z4LxB.png" alt="enter image description here" /></a></p>
  <p>Only if the image has only pixels already completely transparent does it work very well (e.g. the duck).</p>
  <p><a href="https://stackoverflow.com/a/58132349/2342558">Mark Setchell's answer</a>:</p>
  <p><a href="https://i.stack.imgur.com/sgmKN.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/sgmKN.png" alt="enter image description here" /></a>
  <a href="https://i.stack.imgur.com/oXuva.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/oXuva.png" alt="enter image description here" /></a></p>
  <p>It makes completely transparent all pixels with an alpha, also if this alpha is very low, see the shadow below the penguin. Also some pixel at the edge of the duck are converted in black pixel or in full-transparent pixel.</p>