AyrA icon

Image Anonymizer in PHP

AyrA | PRO | 12/14/20 10:03:11 AM UTC | 0 ⭐ | 436 👁️ | Never ⏰ | []
PHP |

3.71 KB

|

None

|

0 👍

/

0 👎

<?php
    define('ANONYMIZE_PNG',1);
    define('ANONYMIZE_JPG',ANONYMIZE_PNG+1);
    define('ANONYMIZE_GIF',ANONYMIZE_JPG+1);
    
    //Anonymizes an image by making all color channel values even.
    //It also removes color information from regions that are almost or completely transparent.
    //This defeats steganography in the least significant bits of color channels and steganography
    //that uses the color bytes of completely transparent pixels.
    //
    //Note: Will kill animation in gif files
    //
    //$data(string):               Image data
    //$format(int=ANONYMIZE_PNG):  Output a jpeg instead of PNG. Recommended if the source is jpeg
    //returns:                     Anonymized image data
    function anonymize_image($data,$format=ANONYMIZE_PNG){
        //Default to PNG if the programmer that calls this function is stupid (or a smartass)
        if(!in_array($format,array(ANONYMIZE_PNG,ANONYMIZE_JPG,ANONYMIZE_GIF))){
            $format=ANONYMIZE_PNG;
        }
        
        //Read as image
        $img=@imageCreateFromString($data);
        if(!$img){
            //bail if we failed to load
            return NULL;
        }
        //If we don't do this, PHP will read alpha values, but discards them when writing
        imageSaveAlpha($img,TRUE);
        
        $colors=imageColorsTotal($img);
        if($colors>0){
            //Palette based images are much easier to deal with.
            //We don't set the pixel values, we merely tweak the values in the palette
            //This doesn't makes sense with jpg, so we use GIF instead.
            if($format===ANONYMIZE_JPG){
                $format=ANONYMIZE_GIF;
            }
            for($i=0;$i<$colors;$i++){
                $col=imageColorsForIndex($img,$i);
                if($col['alpha']>0x70){
                    //Make almost completely transparent regions fully transparent
                    imageColorSet($img,$i,0xFF,0xFF,0xFF,0x7F);
                }
                elseif($col['alpha']<0x8){
                    //Make almost completely opaque regions fully opaque
                    imageColorSet($img,$i,$col['red']&0xFE,$col['green']&0xFE,$col['blue']&0xFE,0x00);
                }
                else{
                    //Make colors even
                    imageColorSet($img,$i,$col['red']&0xFE,$col['green']&0xFE,$col['blue']&0xFE,$col['alpha']&0xFE);
                }
            }
        }
        else{
            $w=imageSX($img);
            $h=imageSY($img);
            for($x=0;$x<$w;$x++){
                for($y=0;$y<$h;$y++){
                    //Get color and make RGB even but don't touch alpha channel yet
                    $c=imageColorAt($img,$x,$y)&0xFFFEFEFE;
                    //Format of $c is 0xAARRGGBB
                    //The alpha component can only range from 0x00 (opaque) to 0x7F (transparent) because this is PHP
                    if($c>0xFFFFFF){
                        //This pixel has alpha information.
                        if(($c>>24)>=0x70){
                            //Strip all color information from almost/completely transparent region
                            $c=0x7FFFFFFF;
                        }
                        elseif(($c>>24)<=0x8){
                            //Make fully opaque
                            $c&=0x00FFFFFF;
                        }
                    }
                    imageSetPixel($img,$x,$y,$c);
                }
            }
        }
        //Return new image data
        ob_start();
        switch($format){
            case ANONYMIZE_JPG:
                //75 is the default quality. Higher is better
                imageJpeg($img,NULL,90);
                break;
            case ANONYMIZE_GIF:
                //This has no options
                imageGif($img);
                break;
            default:
                //6 is the default compression. Higher is better
                imagePng($img,NULL,9);
                break;
        }
        imageDestroy($img);
        return ob_get_clean();
    }
    //Replace the file with one of your own for this demo
    $raw=file_get_contents('F:/test.png');
    $png=anonymize_image($raw,ANONYMIZE_PNG);
    $jpg=anonymize_image($raw,ANONYMIZE_JPG);
    $gif=anonymize_image($raw,ANONYMIZE_GIF);
?>
<style>*{font-family:sans-serif;}img{border:2px solid #000;margin:0.5em;padding:0.5em;display:block;}</style>
<p>PNG</p>
<img src="data:image/png;base64,<?=base64_encode($png);?>" />
<p>JPG</p>
<img src="data:image/jpg;base64,<?=base64_encode($jpg);?>" />
<p>GIF</p>
<img src="data:image/gif;base64,<?=base64_encode($gif);?>" />

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎