警告:这篇文章的演示可能会阻塞您的浏览器。
不久前,我发布了一个名为 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 的最佳解决方案。
恐慌之前…
这只是一个概念证明帖子——不是万能的、最终的解决方案。一个简单的打印屏幕将允许您
“捕捉”图像。这些解决方案都有些低效。
现在……
没有什么能阻止它……带来痛苦。