用php-GD实现单像素操作
首先我指的是前面的一个问题 我发现html5画布不适合,因为很难对源图像保密。这就是为什么我要用PHPGD库来实现我的目标。我从来没有在这个图书馆工作过,所以我遇到了一些困难。我想我需要以下功能用php-GD实现单像素操作,php,image-processing,php-gd,Php,Image Processing,Php Gd,首先我指的是前面的一个问题 我发现html5画布不适合,因为很难对源图像保密。这就是为什么我要用PHPGD库来实现我的目标。我从来没有在这个图书馆工作过,所以我遇到了一些困难。我想我需要以下功能 ImageCreateTureColor用于在浏览器中创建图像 imagecolorallocate用于从源图像返回rgb imagesetpixel用于绘制随机像素 $x = 200; //width of image $y = 200; //height of image $gd = image
- ImageCreateTureColor用于在浏览器中创建图像
- imagecolorallocate用于从源图像返回rgb
- imagesetpixel用于绘制随机像素
$x = 200; //width of image $y = 200; //height of image $gd = imagecreatetruecolor ($x, $y); $color = imagecolorallocate($gd, $r, $g, $b) //not sure how to retrieve the rgb from the source image Then I need a function for drawing random pixels with imagesetpixel. imagesetpixel($gd, $posx,$posy, $color); // not sure how to retrieve the x and y position of each pixel.
我不是PHP的明星,这就是为什么我的搜索被这些GD函数卡住了。希望您能给我一个启动用您的随机颜色值替换随机颜色 这将替换所有像素
for($i=0;$i < $x;$i++) {
for($e = 0;$e < $y;$e++) {
imagesetpixel($gd, $i,$e, $RANDOM_COLOR);
}
}
你可以在一个循环中使用它,在食人魔的帮助下,我让它部分工作 我所做的是操纵顶层,操纵后,将其与函数imagecopy和源图像合并。输出为jpg图像 顶层的操作是用这段代码完成的
for ($y = 0; $y < imagesy($img); $y++) {
for ($x = 0; $x < imagesx($img); $x++) {
$img = imagecreatefrompng("thecover.png");
imagealphablending($img, false); // Turn off blending
$white_color_transparent = imagecolorallocatealpha($img, 255, 255, 255, 127);
$rgb = imagecolorat($img, $x, $y);
$pixel_color = imagecolorsforindex($img, $rgb);
if ($pixel_color['red'] == 255 && $pixel_color['green'] == 255 && $pixel_color['blue'] == 255){
for ($i = 0; $i < 200; $i++) {
imagesetpixel($img, rand(0,300), rand(0,300), $white_color_transparent);
}
}
}
}
for($y=0;$y
顶层的颜色为白色,RGB(0,0,0)。脚本将检查该颜色,并在此时将200个随机像素设置为透明
它将很多像素设置为透明,但不是给定的200像素
有人能帮我解决问题。随机函数的一个“特点”是它是伪随机的,也就是说,给定相同的种子,它总是输出相同的序列
因此,您可以为每个“图像”存储:
因此,假设您希望输出图像$sourcefile
,其中包含可见像素百分比的种子$seed
和$position
。您甚至不需要使用alpha:
// Load image
$src = imageCreateFromPNG($sourcefile); // Assume image is PNG
// Create work image
$new = imageCreateTrueColor(ImageSX($src), ImageSY($src)); // new image of same size
mt_srand($seed); // Seed the Mersenne Twister generator
// Number of pixels to set: $position = 0: NONE, $position = 100: ALL
$pixels = round($position*imageSX($src)*imageSY($src)/100);
// Now we have a problem: if we do $pixels attempts, mt_rand might sometimes
// return the same pixel again. So we end up setting less than $pixels pixels.
// So we do this the expensive way, saving an array of yet-to-be-used pixels.
$max = ImageSX($src)*ImageSY($src);
$pixelid = array();
for ($i = 0; $i < $max; $i++)
$pixelid[] = $i;
$W = ImageSX($src);
while($pixels--)
{
// Extract one pixel
$chosen = $pixelid[$idx = mt_rand(0, $pixels)];
array_splice ($pixelid, $idx, 1); // Remove extracted pixel from array
$x = $chosen % $W;
$y = ($chosen - $x)/ $W;
$rgb = imagecolorat($src, $x, $y);
$pix = imagecolorsforindex($src, $rgb);
$rgb = imageColorAllocate($new, $pix['red'], $pix['green'], $pix['blue']);
imageSetPixel($new, $x, $y, $rgb);
}
ImageDestroy($src);
// $new has now exactly $pixels set to the same pixels of $src,
// the rest are undefined (you can fill $new with white beforehand...)
Header("Content-Type: image/png");
ImagePNG($new);
或者你可以。。。重试。但当图像几乎完成时,这可能会很昂贵
$cnt = count($pixelid);
while($pixels--)
{
// Extract one pixel
for ($idx = mt_rand(0, $cnt); $pixelid[$idx] != -1; $idx = mt_rand(0, $cnt))
;
$chosen = $pixelid[$idx];
$pixelid[$idx] = -1;
如果您不关心图像总是以不同的方式重建,则可以使用数组\u shuffle()
而不是mt\u rand()
,并在每次迭代时从$pixelid
提取第i个像素
最后一个选项是使用mt\u rand
重新实现array\u shuffle()
因此,您可以使用$seed
对$pixelid
调用array\u new\u shuffle()
,然后按顺序从无序数组中提取元素:
for ($idx = 0; $idx < $pixels; $idx++)
{
$chosen = $pixelid[$idx];
...
优化
您会注意到上面代码中有一个注释部分。如果碰巧$position
大于50%,比如70%,那么创建空图像并将70%的像素从良好图像复制到空图像是没有意义的。将30%的空像素从空图像复制到好图像上,使其“变黑”更有意义。这可以通过简单地交换$new
和$src
并调整$position
来实现。我还没有完全测试过这段代码;这就是我留下评论的原因。但是欢迎你尝试一下
实施
使用PRNG的优点是不需要保存任何图像,只需要种子
和位置
——通常总共八个字节
如果人员A接收到位置1,并要求接收最多5个位置(即图像可见的5%),并且您保存种子和该值5,并将其用于人员B,则人员B将看到与人员A相同的5%
除原始图像外,所有图像均未保存或加载
如果您可以在$\u GET参数中传递种子和位置,则可以在浏览器中显示不同阶段的图像(例如,image.php?seed=12345678&position=5
将显示设置了5%像素的图像。当然,您也可以指定像素数而不是百分比)
只要像素是随机选择的,这种方法就有效:如果一个人要选择他或她想要的确切像素,那么这种方法无效,你需要保存单个像素的位置,这可以通过几种方式实现:使用一个以二进制格式保存(x,y)对的平面文件,或者保存整个图像。后一种方法更容易理解,并且每一步都需要存储一个完整的图像,因此如果这是一个游戏,并且您想要“重放”它,那么您可能需要巨大的磁盘空间。第一种方法可能合理地要求每个像素有六个字节,即相当于具有相同高度且宽度为原始图像两倍的图像,或者每个像素只有四个字节。感谢食人魔的回复。但是颜色不一定是随机的。输出的每个像素值(rgb和x,y)都需要与源图像相同。唯一的问题是,imagesetpixel并不是在一个步骤中绘制整个图像,而是在每个步骤的随机位置绘制随机数量的像素(所谓步骤,我指的是人们从表单中选择的像素数量)。在每一步之后,图片都需要保存到数据库中,以便下次看到相同数量的像素。像素数量将增加,因此浏览器中的图像将与源图像相似。您可以使用imagecopy将图像的一部分复制到另一个图像中,这样您将向用户显示此复制的图像,然后保存显示的x/y,在表单提交后,您将增加x和y。。。最后
$cnt = count($pixelid);
while($pixels--)
{
// Extract one pixel
$idx = mt_rand(0, $cnt);
// If the extracted pixel is null, find next pixel that is unextracted
// and if there are none, restart from the beginning of the array.
while (-1 == ($chosen = $pixelid[$idx]))
if ($cnt == ++$idx)
$idx = 0;
$chosen = $pixelid[$idx];
$pixelid[$idx] = -1;
$cnt = count($pixelid);
while($pixels--)
{
// Extract one pixel
for ($idx = mt_rand(0, $cnt); $pixelid[$idx] != -1; $idx = mt_rand(0, $cnt))
;
$chosen = $pixelid[$idx];
$pixelid[$idx] = -1;
function array_new_shuffle(&$items, $seed)
{
mt_srand($seed);
for ($i = count($items) - 1; $i > 0; $i--)
{
$j = @mt_rand(0, $i);
list($items[$i], $items[$j]) = array($items[$j], $items[$i]);
}
}
for ($idx = 0; $idx < $pixels; $idx++)
{
$chosen = $pixelid[$idx];
...
$seed = 0;
$position = 2;
$sourcefile = '/home/lserni/Lena19721024-filtered.png';
mt_srand($seed); // Seed the Mersenne Twister generator
// Load image
$src = ImageCreateTrueColor(512,512);
// $src = imageCreateFromPNG($sourcefile); // Assume image is PNG
$W = ImageSX($src);
$H = ImageSY($src);
// Total number of pixels
$size = $W*$H;
if (($W > 4095) || ($H > 4095))
die("Image too big");
// Create work image
$new = imageCreateTrueColor($W, $H); // new image of same size
/*
if ($position > 50)
{
$position = 100-$position;
$tmp = $src;
$src = $new;
$new = $tmp;
}
*/
// Number of pixels to set: $position = 0: NONE, $position = 100: ALL
$pixels = round($position*$size/100.0);
// Create a temporary buffer image of the same size
$fix = imageCreateTrueColor($W, $H);
for ($i = 0; $i < $size; $i++)
{
$b = $i & 0xFF;
$g = ($i >> 8) & 0xFF;
$r = ($i >> 16) & 0xFF;
imageSetPixel($fix, $i % $W, floor($i / $W), imageColorAllocate($fix, $r, $g, $b));
}
while($pixels--)
{
// Recover one of the available pixel indexes
$idx = mt_rand(0, $size--);
// Recover index from image
$y = floor($idx / $W);
$x = $idx % $W;
$idx = imageColorAt($fix, $x, $y);
$lst = imageColorAt($fix, $size % $W, floor($size / $W));
$b = $lst & 0xff; $lst >>= 8;
$g = $lst & 0xff; $lst >>= 8;
$r = $lst & 0xff;
imageSetPixel($fix, $x, $y, imageColorAllocate($fix, $r, $g, $b));
// Whew. Now recover true x and y from new $idx
$y = floor($idx / $W);
$x = $idx % $W;
$rgb = imagecolorat($src, $x, $y);
$pix = imagecolorsforindex($src, $rgb);
$rgb = imageColorAllocate($new, $pix['red'], $pix['green'], $pix['blue']);
imageSetPixel($new, $x, $y, $rgb);
}
ImageDestroy($src);
// $new has now exactly $pixels set to the same pixels of $src,
// the rest are undefined (you can fill $new with white beforehand...)
// die("Memory: " . memory_get_peak_usage());
Header("Content-Type: image/png");
ImagePNG($new);