1

I am trying to use GD in PHP to reduce an image to a fixed 60 color palette. (I am aware that the results will look poor, it's a small part of a program I'm writing to identify visually similar or duplicate images)

I have a 8x8 60 color png of my palette, here:

60 Color Palette http://6bf4752d2ea1006477e8-3cbc1620ffd57ce5e34c93b52b8ad439.r9.cf2.rackcdn.com/palette.png

and a test image (color gradient) here:

Test Image http://6bf4752d2ea1006477e8-3cbc1620ffd57ce5e34c93b52b8ad439.r9.cf2.rackcdn.com/test2.png

I'm running it through the following code, which should, as far as I understand, result in a version of test2.png that has been converted to my palette:

$palette = imagecreatefrompng("palette.png");
$source   = imagecreatefrompng("test2.png");
$source_w = imagesx($source);
$source_h = imagesy($source);
$result   = imagecreate($source_w, $source_h);
imagepalettecopy($result, $palette);
imagecopy($result, $source, 0, 0, 0, 0, $source_w, $source_h);

header('Content-type: image/gif');
imagegif($result);

Instead, the results seem to look like this:

Result http://6bf4752d2ea1006477e8-3cbc1620ffd57ce5e34c93b52b8ad439.r9.cf2.rackcdn.com/result.gif

Does anyone know why I'm getting more than 60 colors, and how to fix the issue?

Greg Schoppe
  • 576
  • 1
  • 7
  • 22
  • 3
    Vague guess: You set the palette BEFORE you do the image copy. even though there's 60 colors in your source palette, GD might feel free to use the other 195 empty slots to accommodate your source image as best as possible. Try doing the copy first, then impose the palette afterwards. There's no provision in GD to say "this image can only have 60 colors", or "save this gif with only 60 colors". – Marc B Dec 23 '13 at 14:53

1 Answers1

0

If you only set palette after copying the image, here is the result : with 9 colors (?!) .

<?php
$palette = imagecreatefrompng("palette.png");
$palette_w = imagesx($palette);
$palette_h = imagesy($palette);
$source   = imagecreatefrompng("test2.png");
$source_w = imagesx($source);
$source_h = imagesy($source);
$result   = imagecreate($source_w, $source_h);
imagecopy($result, $source, 0, 0, 0, 0, $source_w, $source_h);
imagepalettecopy($result, $palette);
header('Content-type: image/gif');
imagegif($result);

The real trick is to set both before AND after...

<?php
$palette = imagecreatefrompng("palette.png");
$palette_w = imagesx($palette);
$palette_h = imagesy($palette);
$source   = imagecreatefrompng("test2.png");
$source_w = imagesx($source);
$source_h = imagesy($source);
$result   = imagecreate($source_w, $source_h);
imagepalettecopy($result, $palette);
imagecopy($result, $source, 0, 0, 0, 0, $source_w, $source_h);
//here is the trick
imagepalettecopy($result, $palette);
header('Content-type: image/gif');
imagegif($result);

And now the result : enter image description here

Alexandre Tranchant
  • 4,426
  • 4
  • 43
  • 70
  • I gave you the check, because you are right, but oddly enough, it seems the real trick is to set both before AND after... I have no idea WHY it works, but I get a far more accurate gradient, with 14 colors or so. – Greg Schoppe Dec 23 '13 at 16:33