Can I swap colors in image using GD library in PHP?

前端 未结 8 1276
遇见更好的自我
遇见更好的自我 2020-12-03 08:18

I got the image like this (it\'s a graph):


(source: kitconet.com)

I want to change the colours, so the white is black, the graph line is li

相关标签:
8条回答
  • 2020-12-03 08:30

    I had trouble making this solution work. The image cannot be a true color image. Convert it first with imagetruecolortopalette();

    $imgname = "test.gif";
    $im = imagecreatefromgif ($imgname);
    
    imagetruecolortopalette($im,false, 255);
    
    $index = imagecolorclosest ( $im,  255,255,255 ); // get White COlor
    imagecolorset($im,$index,92,92,92); // SET NEW COLOR
    
    $imgname = "result.gif";
    imagegif($im, $imgname ); // save image as gif
    imagedestroy($im);
    
    0 讨论(0)
  • 2020-12-03 08:33

    I know this is late and after the fact, but I've put together a script that will do this on a slightly larger scale. Hopefully someone who comes across this post can use it. It takes an number of source images that are one-color layers (your choice). You provide it with a source color and the tint of each layer and the script returns a composite image (with full transparency) colored specifically to your provided hex code.

    Check out the code below. A more detailed explanation can be found on my blog.

    function hexLighter($hex, $factor = 30) {
        $new_hex = '';
    
        $base['R'] = hexdec($hex{0}.$hex{1});
        $base['G'] = hexdec($hex{2}.$hex{3});
        $base['B'] = hexdec($hex{4}.$hex{5});
    
        foreach ($base as $k => $v) {
            $amount = 255 - $v;
            $amount = $amount / 100;
            $amount = round($amount * $factor);
            $new_decimal = $v + $amount;
    
            $new_hex_component = dechex($new_decimal);
    
            $new_hex .= sprintf('%02.2s', $new_hex_component);
        }
    
        return $new_hex;
    }
    
    // Sanitize/Validate provided color variable
    if (!isset($_GET['color']) || strlen($_GET['color']) != 6) {
        header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request', true, 400);
    
        exit(0);
    }
    
    if (file_exists( "cache/{$_GET['color']}.png" )) {
        header( 'Content-Type: image/png' );
        readfile( "cache/{$_GET['color']}.png" );
    
        exit(0);
    }
    
    // Desired final size of image
    $n_width = 50;
    $n_height = 50;
    
    // Actual size of source images
    $width = 125;
    $height = 125;
    
    $image =    imagecreatetruecolor($width, $height);
                imagesavealpha($image, true);
                imagealphablending($image, false);
    
    $n_image =  imagecreatetruecolor($n_width, $n_height);
                imagesavealpha($n_image, true);
                imagealphablending($n_image, false);
    
    $black = imagecolorallocate($image, 0, 0, 0);
    $transparent = imagecolorallocatealpha($image, 255, 255, 255, 127);
    
    imagefilledrectangle($image, 0, 0, $width, $height, $transparent);
    
    $layers = array();
    $layers_processed = array();
    
    $layers[] = array( 'src' => 'layer01.gif', 'level' => 0 );  // Border
    $layers[] = array( 'src' => 'layer02.gif', 'level' => 35 );     // Background
    $layers[] = array( 'src' => 'layer03.gif', 'level' => 100 );    // White Quotes
    
    foreach ($layers as $idx => $layer) {
        $img = imagecreatefromgif( $layer['src'] );
        $processed = imagecreatetruecolor($width, $height);
    
        imagesavealpha($processed, true);
        imagealphablending($processed, false);
    
        imagefilledrectangle($processed, 0, 0, $width, $height, $transparent);
    
        $color = hexLighter( $_GET['color'], $layer['level'] );
        $color = imagecolorallocate($image,
            hexdec( $color{0} . $color{1} ),
            hexdec( $color{2} . $color{3} ),
            hexdec( $color{4} . $color{5} )
        );
    
        for ($x = 0; $x < $width; $x++)
            for ($y = 0; $y < $height; $y++)
                if ($black === imagecolorat($img, $x, $y))
                    imagesetpixel($processed, $x, $y, $color);
    
        imagecolortransparent($processed, $transparent);
        imagealphablending($processed, true);
    
        array_push($layers_processed, $processed);
    
        imagedestroy( $img );
    }
    
    foreach ($layers_processed as $processed) {
        imagecopymerge($image, $processed, 0, 0, 0, 0, $width, $height, 100);
    
        imagedestroy( $processed );
    }
    
    imagealphablending($image, true);
    
    imagecopyresampled($n_image, $image, 0, 0, 0, 0, $n_width, $n_height, $width, $height);
    
    imagealphablending($n_image, true);
    
    header( 'Content-Type: image/png' );
    imagepng( $n_image, "cache/{$_GET['color']}.png" );
    imagepng( $n_image );
    
    // Free up memory
    imagedestroy( $n_image );
    imagedestroy( $image );
    
    0 讨论(0)
  • 2020-12-03 08:33

    I haven't tried it myself but you can look at the function imagecolorset() in the GD library It does a color fill like effect, that could help with the white background.

    0 讨论(0)
  • 2020-12-03 08:36

    I'm not aware of any ready-made functions. But I suppose you could go trough every pixel of the image and change it's colour...

    0 讨论(0)
  • 2020-12-03 08:50

    You could try the imagefilter function http://lv.php.net/imagefilter - but that will not give your direct access to replace one color with another, just changing the r/g/b components.

    A very low level solution could be implemented using imagesetpixel http://nl2.php.net/imagesetpixel to set the new pixel values.

    0 讨论(0)
  • 2020-12-03 08:51

    The slow but sure approach, iterating over every pixel.

    function ReplaceColour($img, $r1, $g1, $b1, $r2, $g2, $b2)
    {
        if(!imageistruecolor($img))
            imagepalettetotruecolor($img);
        $col1 = (($r1 & 0xFF) << 16) + (($g1 & 0xFF) << 8) + ($b1 & 0xFF);
        $col2 = (($r2 & 0xFF) << 16) + (($g2 & 0xFF) << 8) + ($b2 & 0xFF);
    
        $width = imagesx($img); 
        $height = imagesy($img);
        for($x=0; $x < $width; $x++)
            for($y=0; $y < $height; $y++)
            {
                $colrgb = imagecolorat($img, $x, $y);
                if($col1 !== $colrgb)
                    continue; 
                imagesetpixel ($img, $x , $y , $col2);
            }   
    }
    
    0 讨论(0)
提交回复
热议问题