警告:这篇文章的演示可能会阻塞您的浏览器。
不久前,我发布了一个名为 dwProtector 的 MooTools 插件,旨在使图像盗窃更加困难——不是完全防止它——但让新手到普通用户更难下载图像。尽管受到公开侮辱,并且只是为了开玩笑,我还是创建了另一种方法:读入图像,存储每个像素,并提供一种方法将该信息转换为图像的 HTML 版本。
本文提出了两种解决方案:一种是我自己提出的,另一种是 MooTools 的创建者 Valerio Proietti 提出的。每个都有其优点和缺点。
CSS(两种解决方案)
.image { position:relative; overflow:hidden; }
.pixel { width:1px; height:1px; position:absolute; }
#pixels .pixel { float:left; position:relative; width:1px; height:1px; }
我们设置了一个容器和像素。我需要添加溢出:隐藏;因为 IE6 有问题。
PHP:存储像素
// settings
$image = 'top-logo-pixel.png';
// get the image size
list($width,$height) = getimagesize($image);
$img = imagecreatefrompng($image);
// data array
$data = array('height'=>$height,'width'=>$width,'pixels'=>array());
// start the height loop
for ($y = 0; $y < $height; $y++){
for ($x = 0; $x < $width; $x++){
$color_index = imagecolorat($img, $x, $y);
$a = ($color_index & 0x7F000000) >> 24;
$r = ($color_index >> 16) & 0xFF;
$g = ($color_index >> 8) & 0xFF;
$b = $color_index & 0xFF;
if ($a > 0){
$a = abs(($a / 127) - 1);
$a = hex(round($a * 255));
} else {
$a = '';
}
$r = hex($r);
$g = hex($g);
$b = hex($b);
$data['pixels'][] = "$r$g$b$a";
}
}
// clean up
imagedestroy($img);
/* utility function */
function hex($v){
$bit = dechex($v);
if (strlen($bit) == 1) $bit = "0$bit";
return $bit;
}
上述功能只是将图像信息存储在一个数组中。到目前为止没有输出。
PHP:输出方法一:HTML/DIV
/* output as divs */
$top = $left = 0;
echo '<div >';
foreach($data['pixels'] as $index=>$pixel) {
echo '<div ></div>';
if($index && ($index % $data['width'] == 0)) { $top++; $left = 0; } else { $left++; }
}
echo '</div>';
我的方法是两者中较简单的一个:对于每个像素,输出一个背景颜色等于该像素的 DIV。
PHP:输出方式一:JSON -> MooTools -> DIVs
<?php
function optimize_data($data){
$image = array(
'colors' => array(),
'data' => array(),
'height' => $data['height'],
'width' => $data['width']
);
$iterator = array();
$i = 0;
$gidx = 0;
$num = 1;
foreach($data['pixels'] as $color){
if (!isset($image['colors'][$color])) $image['colors'][$color] = dechex($i++);
$di = $image['colors'][$color];
if ($pdi['c'] == $di){
$num++;
$image['data'][$pdi['i']] = $di.'-'.$num;
} else {
$num = 1;
$image['data'][$gidx] = $di;
$pdi = array('c' => $di, 'i' => $gidx);
$gidx++;
}
}
$image['data'] = implode($image['data'], ';');
foreach($image['colors'] as $c => $v) $k[] = $v.':'.$c;
$image['colors'] = implode($k, ';');
return json_encode($image);
}
?>
<script type="text/javascript">
/* kamicane's version */
var image = <?php print_r(optimize_data($data)); ?>;
var colors = image.colors;
var data = image.data;
var height = image.height;
var width = image.width;
colors = colors.split(';');
var ch = {};
colors.each(function(c){
var b = c.split(':');
ch[b[0]] = b[1];
});
data = data.split(';');
var pixels = [];
data.each(function(d){
d = d.split('-');
if (d[1] == null) d[1] = 1;
Number(d[1]).times(function(i){
pixels.push(ch[d[0]]);
});
});
document.addEvent('domready', function(){
var pixelsE = $('pixels');
pixelsE.setStyles({'height': image.height, 'width': image.width });
pixels.each(function(p){
var d = new Element('div', {'class': 'pixel'});
d.style.backgroundColor = '#' + p;
d.inject(pixelsE);
});
});
</script>
<div id="pixels"></div>
Valerio 选择获取像素数组并使用简单的压缩方法将像素输出为 JSON。然后他
创建 MooTools JavaScript 代码以读取算法并输出一系列 DIV 以创建图像。
Sebastian Markbåge 的方法
还有 Sebastian Markbåge,他投下了这个炸弹:http://blog.calyptus.eu/seb/2009/05/png-parser-in-javascript/。 MooTools 有一些才华横溢的贡献者,不是吗?查看 Sebastian 的 Parsing Base64 Encoded Binary PNG Images in JavaScript 帖子! Sebastian 的可能是将图像输出为 HTML 的最佳解决方案。
恐慌之前…
这只是一个概念证明帖子——不是万能的、最终的解决方案。一个简单的打印屏幕将允许您
“捕捉”图像。这些解决方案都有些低效。
现在……
没有什么能阻止它……带来痛苦。
