<?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
0 B
|👍
/👎