使用这个小程序,便可以将图像转化为骰子图像,可以自定义采样精度,还可输出点数的分布图,如果你真的买那么多骰子去摆的话用这个会更方便 :orz:

DICE PAINTING 演示:http://xia.im/upload/dice-painting.html

骰 (tou2) 子作画,类似于 ASCII ART,可以去骰子作画的算法 - 阮一峰的网络日志看介绍。

任何一张图片都可以用骰子模拟出来,算法非常简单:将图片分成若干个区域,每个区域经过计算以后,用 1~6 之间的一个整数表示,代表骰子的一个面。这种将连续的量转化成不连续的整数的算法,属于 vector quantization(矢量量化)的一个应用。整数 1,表示骰子朝上的一面有 1 个黑点;整数 2,表示有 2 个黑点;以此类推。黑点越少,表示这个区域越接近全白;黑点越多,表示越接近全黑。根据黑点值,将骰子依次放入,就能模拟出全图。

原文中需要将图像分割成 16X16 的单元(采样精度)这步,我用 PHP 的imagecopyresampled将图像边长缩放到原来的 1/16,这样计算像素的灰度时就不用取 16X16 个像素的平均值了。生成的骰子图像精度本身就很低,所以应该没有影响,但是如果缩放时使用的是imagecopyresized,图像质量就会降低很多。

主程序:

<?php
 
$filename='example.jpg';// 要处理的原始图像
$cell=5;// 采样精度
 
// 打开图像
if(preg_match("/\.gif$/",$filename)){$res_img=imagecreatefromgif($filename);}
if(preg_match("/\.(jpg|jpeg)$/",$filename)){$res_img=imagecreatefromjpeg($filename);}
if(preg_match("/\.png$/",$filename)){$res_img=imagecreatefrompng($filename);}
// 获取图像长宽值,并计算出 resize 图像的长宽值
$res_x=imagesx($res_img);
$res_y=imagesy($res_img);
$dst_x=round($res_x/$cell);
$dst_y=round($res_y/$cell);
$dst_img=imagecreatetruecolor($dst_x,$dst_y); 
imagecopyresampled($dst_img,$res_img,0,0,0,0,$dst_x,$dst_y,$res_x,$res_y);
imagedestroy($res_img);
// 新建输出图像,每个骰子大小为 8X8 像素,所以乘 8
$final_img=imagecreatetruecolor($dst_x*8,$dst_y*8);
// 打开 dice.gif,骰子 6 个面的图像
$dice_img=imagecreatefromgif('dice.gif');
// 对 resize 图像像素进行计算
for($i=0;$i <$dst_y;$i++){
	for($j=0;$j <$dst_x;$j++){
		// 计算每个像素点的 RGB,并转换为灰度
		$rgb=imagecolorat($dst_img,$j,$i);
		$r=($rgb>>16);
		$g=($rgb & 0x00ff00)>>8;
		$b=$rgb & 0x0000ff;
		$t=($r*3+$g*6+$b)/10;
		$t=floor($t);
		// 根据灰度截取 dice.gif 中的图像,拼贴到输出图像中
		switch($t){
			case $t<=42:imagecopyresized($final_img,$dice_img,$j*8,$i*8,16,8,8,8,8,8);break;
			case $t<=84:imagecopyresized($final_img,$dice_img,$j*8,$i*8,8,8,8,8,8,8);break;
			case $t<=126:imagecopyresized($final_img,$dice_img,$j*8,$i*8,0,8,8,8,8,8);break;
			case $t<=168:imagecopyresized($final_img,$dice_img,$j*8,$i*8,16,0,8,8,8,8);break;
			case $t<=212:imagecopyresized($final_img,$dice_img,$j*8,$i*8,8,0,8,8,8,8);break;
			case $t<=256:imagecopyresized($final_img,$dice_img,$j*8,$i*8,0,0,8,8,8,8);break;
			default:imagecopyresized($final_img,$dice_img,$j*8,$i*8,16,8,8,8,8,8);// 解决 t<=1 的情况下拼贴出现错误
		};
	};
};
imagedestroy($dice_img);
imagedestroy($dst_img);
header("Content-type:image/gif");
imagegif($final_img);
imagedestroy($final_img);
?>
  1. 你好,看到你的微博,对骰子画很感兴趣,希望你可以提供一下 dice.gif 这个文件,可以吗

  2. 有些想咨询你的。我想做这个当毕业创作。

    • @吃瘦子的肥肉
      你好,这个玩意随便用,代码也是可以给你的(页面上的代码只是最核心的内容)。
      有问题可以留言,或者给我发电子邮件。

    • @小虾
      谢谢,那我就尽量问了哦。 :smile: 七阶和六阶有什么区别?我不懂这些专业术语,大学专业是学前教育,和这些电脑程序的东西不擦边。

    • @吃瘦子的肥肉
      把白色 ->灰色 ->黑色的过渡分成 256 个级别(256 种颜色深浅)。

      六阶把 256 个颜色简化为 6 种颜色表示:白色、非常浅的灰、浅灰、深灰、非常深的灰、
      黑色,每个颜色对应了(256 ÷ 6)个级别。

      七阶把 256 个颜色简化为 7 种颜色表示:白色、非常浅的灰、浅灰、中灰、深灰、非常深的灰、
      黑色,每个颜色对应了(256 ÷ 7)个级别。实际表现就是图片纯黑或纯白的地方不用骰子 (因为骰子只有 6 个面,只能表示 6 种深浅,在这里用背景颜色来表示第 7 种深浅)

  3. 谢谢 真是造福人类了