PHP Conference Japan 2024

imagecolorat

(PHP 4, PHP 5, PHP 7, PHP 8)

imagecolorat获取像素的颜色索引

描述

imagecolorat(GdImage $image, int $x, int $y): int|false

返回由 image 指定的图像中指定位置的像素的颜色索引。

如果图像为真彩色图像,则此函数返回该像素的 RGB 值作为整数。使用位移和掩码来访问不同的红色、绿色和蓝色分量值

参数

image

一个 GdImage 对象,由图像创建函数之一返回,例如 imagecreatetruecolor()

x

点的 x 坐标。

y

点的 y 坐标。

返回值

返回颜色索引或在失败时返回 false

警告

此函数可能会返回布尔值 false,但也可能返回计算结果为 false 的非布尔值。有关更多信息,请阅读有关 布尔值 的部分。使用 === 运算符 来测试此函数的返回值。

变更日志

版本 描述
8.0.0 image 现在需要一个 GdImage 实例;以前,需要一个有效的 gd 资源

示例

示例 #1 访问不同的 RGB 值

<?php
$im
= imagecreatefrompng("php.png");
$rgb = imagecolorat($im, 10, 15);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;

var_dump($r, $g, $b);
?>

以上示例将输出类似以下内容

int(119)
int(123)
int(180)

示例 #2 使用 imagecolorsforindex() 获取人类可读的 RGB 值

<?php
$im
= imagecreatefrompng("php.png");
$rgb = imagecolorat($im, 10, 15);

$colors = imagecolorsforindex($im, $rgb);

var_dump($colors);
?>

以上示例将输出类似以下内容

array(4) {
  ["red"]=>
  int(119)
  ["green"]=>
  int(123)
  ["blue"]=>
  int(180)
  ["alpha"]=>
  int(127)
}

参见

添加注释

用户贡献的注释 22 条注释

Luciano Ropero
18 年前
我编写了一个函数,计算给定图像资源的平均颜色并以“#rrggbb”格式(十六进制)返回。

function average($img) {
$w = imagesx($img);
$h = imagesy($img);
$r = $g = $b = 0;
for($y = 0; $y < $h; $y++) {
for($x = 0; $x < $w; $x++) {
$rgb = imagecolorat($img, $x, $y);
$r += $rgb >> 16;
$g += $rgb >> 8 & 255;
$b += $rgb & 255;
}
}
$pxls = $w * $h;
$r = dechex(round($r / $pxls));
$g = dechex(round($g / $pxls));
$b = dechex(round($b / $pxls));
if(strlen($r) < 2) {
$r = 0 . $r;
}
if(strlen($g) < 2) {
$g = 0 . $g;
}
if(strlen($b) < 2) {
$b = 0 . $b;
}
return "#" . $r . $g . $b;
}

虽然,我注意到您还可以通过使用 imagecopyresampled 生成一个 1px x 1px 的副本获得相当不错的平均颜色(生成的像素颜色为平均颜色)。
alan hogan dot com slash contact
17 年前
正如 creamdog 之前提到的,此函数确实提供了 alpha 通道!(手册可能应该更新以包含这一点!)

$rgba = imagecolorat($im,$x,$y);
$alpha = ($rgba & 0x7F000000) >> 24;

$alpha 然后将包含透明度(而不是不透明度)级别。因此,最大值 127 表示完全透明,而 0 表示完全不透明。

使用此信息,可以编写如下所示的抖动 png 到 gif 函数

<?php
$im
= imagecreatefrompng($pngRel);
$transparentColor = imagecolorallocate($im, 0xfe, 0x3, 0xf4 );
$height = imagesy($im);
$width = imagesx($im);
for(
$x = 0; $x < $width; $x++){
for(
$y = 0; $y < $height; $y++) {
$alpha = (imagecolorat($im,$x,$y) & 0x7F000000) >> 24;
//抖动!
if ($alpha > 3 && (
$alpha >=127-3 ||
(
rand(0,127))>=(127-$alpha)
)){
imagesetpixel($im,$x,$y,$transparentColor);
}

}
}
imagecolortransparent($im, $transparentColor);
imagegif($im, $gifRel);//保存
header("Content-type: image/gif");
readfile($gifRel); //传递到浏览器

?>
[email protected]
20年前
对于具有真彩色和调色板的png,imagecolorat() 的工作方式不同 - 对于真彩色,它返回颜色的值,对于调色板,它返回索引号,您必须使用 imagecolorsforindex() 获取 rgb 颜色值。
[email protected]
12年前
trimImage ( 资源 $image , 整数 $colour , 整数 $tolerance )

trimImage() 将返回图像所需像素的最顶部、最右侧、最底部和最左侧位置(即找到最小图像区域,以便您可以从图像的外边缘修剪给定的颜色)。

参数

image
图像资源,由图像创建函数之一返回,例如 imagecreatetruecolor()。

颜色
要“修剪”的颜色。允许范围 0(黑色)到 255(白色)。如果为空(或在 0 - 255 之外),将使用左上角颜色作为默认值。

容差
从颜色的 +- 可接受范围。0(仅修剪精确颜色)到 255(修剪所有颜色)。

返回值
返回超出颜色容差范围的最外层像素的数组。
数组( 整数 $top, 整数 $right, 整数 $bottom, 整数 $left )

示例(以及实际函数)
<?php
function trimImage($im,$c,$t) {
// 如果修剪颜色 ($c) 不是 0 到 255 之间的数字
if (!is_numeric($c) || $c < 0 || $c > 255) {
// 获取左上角的颜色并将其用作默认值
$rgb = imagecolorat($im, 2, 2); // 向内 2 个像素以避免杂乱的边缘
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
$c = round(($r+$g+$b)/3); // rgb 的平均值足以作为默认值
}
// 如果容差 ($t) 不是 0 到 255 之间的数字,则使用 10 作为默认值
if (!is_numeric($t) || $t < 0 || $t > 255) $t = 10;

$w = imagesx($im); // 图片宽度
$h = imagesy($im); // 图片高度
for($x = 0; $x < $w; $x++) {
for(
$y = 0; $y < $h; $y++) {
$rgb = imagecolorat($im, $x, $y);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
if (
(
$r < $c-$t || $r > $c+$t) && // 红色不在修剪颜色的容差范围内
($g < $c-$t || $g > $c+$t) && // 绿色不在修剪颜色的容差范围内
($b < $c-$t || $b > $c+$t) // 蓝色不在修剪颜色的容差范围内
) {
// 使用 x 和 y 作为键将所有行和所有列
// 压缩到一个 X 数组和一个 Y 数组中。
// 但是,键被视为文字,因此没有
// 数字顺序,因此我们需要对其进行排序以获取第一个
// 和最后一个 X 和 Y 出现的所需像素。
// 常规排序将删除键,因此我们也使用 x 和 y 作为值,
// 这样即使没有保留键,它们仍然可用。
$y_axis[$y] = $y;
$x_axis[$x] = $x;
// 注意:$y_axis[] = $y; 和 $x_axis[] = $x; 工作效果也很好
// 但会导致比必要的数组大得多
// array_unique 将再次减小大小,但此方法更快
}
}
}
// 对其进行排序,以便第一个和最后一个出现分别位于开头和结尾
sort($y_axis);
sort($x_axis);

$top = array_shift($y_axis); // Y 轴上的第一个所需像素
$right = array_pop($x_axis); // X 轴上的最后一个所需像素
$bottom = array_pop($y_axis); // Y 轴上的最后一个所需像素
$left = array_shift($x_axis); // X 轴上的第一个所需像素

return array($top,$right,$bottom,$left);
}

$image='test.jpg';
$im = imagecreatefromjpeg($image); // 我们需要资源

$c = (isset($_GET[c])) ? $_GET[c] : null; // 通过 GET 设置修剪颜色
$t = (isset($_GET[t])) ? $_GET[t] : null; // 通过 GET 设置容差

list($t,$r,$b,$l) = trimImage($im,$c,$t); // 查找顶部、右侧、底部和左侧

$w = $r-$l; // 查找宽度
$h = $b-$t; // 查找高度

imagedestroy($im); // 释放资源

// 下面仅用于直观测试函数 ---------------------------------

$html_display = <<<HTM

<style type="text/css">
#stage {
position: relative;
float: left; // 所以它与它包含的图像大小相同
}
#canvas {
border: solid 1px #FC3;
width:
{$w}px;
height:
{$h}px;
position: absolute;
top:
{$t}px;
left:
{$l}px;
}
img { border: solid 1px #EEE; }
</style>

HTM;

?>
<html>
<head>
<?=$html_display?>
</head>

<body>
<div id="stage">
<div id="canvas"></div>
<img src="test.jpg" />
</div>

</body>
</html>
Ray.Paseur 有时使用 Gmail
7 年前
imageColorAt() 会发出通知并在像素坐标超出范围时返回 FALSE。
justin at hoogs dot com dot au
11 年前
这改进了我之前的函数(该函数实际上只适用于少数灰度颜色)。颜色现在应该是十六进制颜色值。颜色和容差现在是可选参数。

trimImage ( resource $image [, str $colour [, int $tolerance]] )

trimImage() 将返回图像所需像素的最顶部、最右侧、最底部和最左侧位置(即找到最小图像区域,以便您可以从图像的外边缘修剪给定的颜色)。

参数

image
图像资源,由图像创建函数之一返回,例如 imagecreatetruecolor()。

颜色
要“修剪”的颜色十六进制值。如果省略,则将使用左上角的颜色作为默认值。

容差
从颜色的容差范围。允许范围为 0 到 255。如果省略,则将使用 10 作为默认值。

返回值
返回超出颜色容差范围的最外层像素的数组。
数组( 整数 $top, 整数 $right, 整数 $bottom, 整数 $left )

function trimImage($im,$c=null,$t=10) {
// 如果十六进制颜色 ($c) 存在,则尝试将其转换为十进制
if ($c) $rgb = @hexdec($c);
// 如果 hexdec 无法获取黑色 (0) 和白色 (16777215) 之间的值
// 获取左上角的颜色(向内 2 个像素以避免杂乱的边缘)
if (!is_numeric($rgb) || $rgb < 0 || $rgb > 16777215) $rgb = imagecolorat($im, 2, 2);
// 将 $rgb 分割成红色、绿色和蓝色
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
// 确保容差 ($t) 是 0 到 255 之间的数字
if (!is_numeric($t) || $t < 0) $t = 0;
elseif ($t > 255) $t = 255;

$w = imagesx($im); $h = imagesy($im); // 图片宽度和高度
for($x = 0; $x < $w; $x++) {
for($y = 0; $y < $h; $y++) {
$rgb = imagecolorat($im, $x, $y);
$red = ($rgb >> 16) & 0xFF;
$grn = ($rgb >> 8) & 0xFF;
$blu = $rgb & 0xFF;
如果 (
$red < $r-$t || $red > $r+$t || // 红色未裁剪(也不在容差范围内)
$grn < $g-$t || $grn > $g+$t || // 绿色未裁剪(也不在容差范围内)
$blu < $b-$t || $blu > $b+$t // 蓝色未裁剪(也不在容差范围内)
) {
$y_axis[$y] = $y; $x_axis[$x] = $x; // 存储所需的像素坐标
}
}
}
如果 (!$y_axis) $y_axis = $x_axis = array(0); // 如果所有像素都被裁剪,则避免错误
// 进行排序,以便第一次和最后一次出现分别位于开头和结尾
sort($y_axis); sort($x_axis);

$t = array_shift($y_axis); // Y 轴上第一个所需的像素(顶部)
$r = array_pop($x_axis); // X 轴上最后一个所需的像素(右侧)
$b = array_pop($y_axis); // Y 轴上最后一个所需的像素(底部)
$l = array_shift($x_axis); // X 轴上第一个所需的像素(左侧)

返回 array($t,$r,$b,$l);
}
dewi at dewimorgan dot com
10 年前
要测试是否将此函数的返回值作为 RGB 或调色板索引处理,请参阅 imageistruecolor(),或(对于 GD < 2.0.1 或 PHP 4 < 4.3.2)imagecolorstotal() == 0。

这里的一些注释似乎需要多行才能将 RGB 或 RGBA 值转换为十六进制字符串 #AARRGGBB。在大多数情况下,这只需要一行代码即可完成

$hex = sprintf("#%08X", imagecolorat($im32, $x, $y));
$hex = sprintf("#%08X", $rgb);
$hex = sprintf("#%08X", $argb);
$hex = sprintf("#%02X%06X", $rgba >> 24, $rgba & 0xFF000000);
$hex = sprintf("#00%02X%02X%02X", $r, $g, $b);
$hex = sprintf("#%02X%02X%02X%02X", $a, $r, $g, $b);

对于调色板图像,需要两行代码
$cols = imagecolorsforindex($imPal, imagecolorat($imPal, $x, $y));
$hex = sprintf("#%08X", $cols['alpha'], $cols['red'], $cols['green'], $cols['blue']);
chandrachur at elegantsystems dot net
13 年前
这是一个用于创建具有白色背景透明度的图像的有趣代码。它可以适用于任何背景,但您需要相应地调整颜色值。最适合纯双色图像。我搜索了很多此类代码,但都无法找到……看看这是否对其他人有所帮助。

<?php

function transparentImage($src){ // 创建具有白色背景透明度的图像
$r1=80;
$g1=80;
$b1=80;
for(
$x = 0; $x < imagesx($src); ++$x)
{
for(
$y = 0; $y < imagesy($src); ++$y)
{
$color=imagecolorat($src, $x, $y);
$r = ($color >> 16) & 0xFF;
$g = ($color >> 8) & 0xFF;
$b = $color & 0xFF;
for(
$i=0;$i<270;$i++){
if(
$r.$g.$b==($r1+$i).($g1+$i).($b1+$i)){
$trans_colour = imagecolorallocatealpha($src, 0, 0, 0, 127);
imagefill($src, $x, $y, $trans_colour);
}
}
}
}

return
$src;
}

$image='abc/abc.jpg';
$src = imagecreatefromjpeg($image);
$src=transparentImage($src); // 将 jpeg 设置为透明

?>
T. Dekker
19 年前
在 GD 2.x 中,支持真彩色图像,并包含 alpha 通道。GD 2.x 具有 7 位 (0-127) alpha 通道。

虽然大多数人都习惯了 8 位 (0-255) alpha 通道,但 GD 的 7 位 (0-127) 实际上非常方便。每个像素由一个 32 位有符号整数表示,四个 8 位字节的排列方式如下

高字节 <--> 低字节
{Alpha 通道} {红色} {绿色} {蓝色}

对于有符号整数,最左边的位或最高位用于指示值是否为负数,因此仅保留 31 位的实际信息。PHP 的默认整数值是有符号长整数,我们可以在其中存储单个 GD 调色板条目。该整数是正数还是负数告诉我们该调色板条目的抗锯齿是否启用。
Super Moi
19 年前
这是一个用于更改色调的贡献。

function colorize($path_image, $red, $green, $blue)
{
$im = imagecreatefrompng($path_image);
$pixel = array();

$n_im = imagecreatetruecolor(imagesx($im),imagesy($im));
$fond = imagecolorallocatealpha($n_im, 255, 255, 255, 0);
imagefill($n_im, 0, 0, $fond);

for($y=0;$y<imagesy($n_im);$y++)
{
for($x=0;$x<imagesx($n_im);$x++)
{
$rgb = imagecolorat($im, $x, $y);
$pixel = imagecolorsforindex($im, $rgb);

$r = min(round($red*$pixel['red']/169),255);
$g = min(round($green*$pixel['green']/169),255);
$b = min(round($blue*$pixel['blue']/169),255);
$a = $pixel['alpha'];
//echo('red : '.$pixel['red'].' => '.$r.', green : '.$pixel['green'].' => '.$g.', blue : '.$pixel['blue'].' => '.$b.', alpha : '.$pixel['alpha'].' => '.$a.'<br>');

$pixelcolor = imagecolorallocatealpha($n_im, $r, $g, $b, $a);

imagealphablending($n_im, TRUE);
imagesetpixel($n_im, $x, $y, $pixelcolor);
}
}

imagepng($n_im,'test.png');
imagedestroy($n_im);
}
Kae Cyphet
13 年前
如果您在尝试检索黑色像素(例如)时得到不一致的结果或毫无意义的结果

(红色、绿色、蓝色)
0,0,0
0,0,0
0,0,2
0,0,4
0,0,6
0,0,7
0,0,0
0,0,10
0,0,8
0,0,9
0,0,0
0,0,12
0,0,13
0,0,0

从使用 imagecreate() 切换到 imagecreatetruecolor()

在创建图形时发现此问题,其中像素的颜色会根据先前颜色和新数据而增加。
madtrader117 at gmail dot com
14 年前
这是我为查找某些电影缩略图周围黑色边框的大小而编写的函数,其中电影本身添加了黑色填充以保持纵横比。



<?php
define
("DEBUG_OUT",TRUE);
$border_size = find_border_size($path);
print_r($border_size);
/*
* $border = max(find_border_size("img.jpg"));
* $thumb_size_x = 180+(2*$border);
* $thumb_size_y = 240+(2*$border);
* $thumb_size = $thumb_size_x . "x" . $thumb_size_y; (用于 ffmpeg -s 参数的字符串)
* $crop_cmd = "-croptop $border -cropbottom $border -cropright $border -cropleft $border";
*/
function find_border_size($path)
{
/* pad 变量本质上是一个“羽化”值。除非 RGB 值之一超过 $pad,否则我们将认为需要继续。您可以尝试不同的值,但使用 10 我仍然可以获得一个相当大的边框,因为电影会渗透到帽子中。
*/
$pad = 20;
$border_y = 0;
$border_x = 0;

if(!
file_exists($path))
{
if(
DEBUG_OUT) echo("错误: $path 未找到。\n");
return
FALSE;
}
else
{
if(
DEBUG_OUT) echo("打开: $path ...\n");
}
$im = @imagecreatefromjpeg($path);
if(!
$im) return FALSE;
$height = imagesy($im);
$width = imagesx($im);

/* 从 (0, 0) 开始,一直到遇到颜色为止 */
if(DEBUG_OUT) echo("图像 - 高度: $height / 宽度: $width\n");
/* 边界高度(Y) */
$center_width = ceil($width/2);
for(
$i=0; $i<$height; $i++)
{
$rgb = imagecolorat($im,$center_width,$i);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
if(
DEBUG_OUT) echo("高度: ($center_width,$i) R: $r / G: $g / B: $b\n");
if(
$r >= $pad || $g >= $pad || $b >= $pad)
{
$border_y = $i;
if(
$border_y == $height) $border_y = 0;
break;
}
}

/* 边界宽度(X) */
$center_height = ceil($height/2);
for(
$i=0; $i<$width; $i++)
{
$rgb = imagecolorat($im,$i,$center_height);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
if(
DEBUG_OUT) echo("宽度: ($i,$center_width) R: $r / G: $g / B: $b\n");
if(
$r >= $pad || $g >= $pad || $b >= $pad)
{
$border_x = $i;
if(
$border_x == $width) $border_x = 0;
break;
}
}

/* 我将边框设置为 2 的倍数,因为我将这些值发送到 FFMpeg */
if($border_x != 0)
{
$border_x /= 2;
$border_x = round($border_x);
$border_x *= 2;
}
if(
$border_y != 0)
{
$border_y /= 2;
$border_y = round($border_y);
$border_y *= 2;
}
if(
DEBUG_OUT) echo("边界宽度: $border_x / 边界高度: $border_y\n");
return array(
$border_x,$border_y);
}
?>
Richard
16 年前
使用以下函数,您不仅可以将 24 位 RGB 整数转换为其对应的红色、绿色和蓝色值,还可以将 32 位 RGBA 整数转换为其对应的红色、绿色、蓝色和 ALPHA 值。

不仅如此,我还添加了一个函数,用于将这些红色、绿色、蓝色和 alpha 值转换回 32 位 RGBA 整数。

示例用法
<?php
$int
= rgba2int(255, 255, 255, 16);
echo
$int . "<br>";
$rgba = int2rgba($int);
print_r($rgba);
?>

预期输出
285212671
数组
(
[r] => 255
[g] => 255
[b] => 255
[a] => 16
)

<?php
function rgba2int($r, $g, $b, $a=1) {
/*
此函数从 4 个值构建一个 32 位整数,这些值必须是 0-255(8 位)
示例 32 位整数:00100000010001000000100000010000
前 8 位定义 alpha
接下来的 8 位定义蓝色
接下来的 8 位定义绿色
接下来的 8 位定义红色
*/
return ($a << 24) + ($b << 16) + ($g << 8) + $r;
}

function
int2rgba($int) {
$a = ($int >> 24) & 0xFF;
$r = ($int >> 16) & 0xFF;
$g = ($int >> 8) & 0xFF;
$b = $int & 0xFF;
return array(
'r'=>$r, 'g'=>$g, 'b'=>$b, 'a'=>$a);
}
?>
Scott Thompson (VBAssassin)
16 年前
当需要操作现有图像时,我发现这个函数非常有用。例如,只需翻转图像(源代码在此处:http://www.coderprofile.com/source-code/372/

我经常使用的原理是逐像素扫描图像,对每个像素执行某种操作……然后将新创建的像素保存到新的画布上,准备显示在浏览器中。

我发现唯一的问题是速度……因此,对于高流量使用,建议采用某种缓存机制和对处理图像的尺寸进行限制。

此致,
Scott
p h o c i s [a-t] g m a i l c o m
17 年前
我相信 GD 在处理透明蒙版和 Alpha 混合时存在问题。GD 似乎认为某些图像具有黑色蒙版透明度(意味着图像是在黑色蒙版而不是透明背景上构建的)。

虽然“alan hogan dot com slash contact”提供的解决方案确实解决了这个问题,但结果似乎……有点问题。每次执行操作时都会得到不同的结果,而且并不总是最佳的。

因此,我创建了一个不同的解决方案,虽然它在白色背景下看起来更好并且结果一致,但仍然通过将所有混合像素与透明颜色合并的方式稍微扭曲了图像。

// 加载图像
$img = imagecreatefrompng('my_broken_png.png');

// 创建蒙版画布
$matte = imagecreatetruecolor(16,16);
$trans_color = imagecolorallocatealpha($matte,254,254,254,0);
imagefill($matte, 0,0,$trans_color);

// 将旧图像放置在蒙版上
imagecopy($matte,$img,0,0,0,0,16,16);

// 将蒙版颜色转换为完全透明(混合像素不会受到影响)
imagecolortransparent($matte,$trans_color);

// 显示图像
header('Content-Type: image/gif');
imagegif($matte);
pocze_zsolt at hotmail dot com
17 年前
这是一个用于增强对比度的直方图拉伸函数

function contrast_stretch( $img ) {
$x = imagesx($img);
$y = imagesy($img);

$min=255.0;
$max=0.0;

for($i=0; $i<$y; $i++) {
for($j=0; $j<$x; $j++) {
$pos = imagecolorat($img, $j, $i);
$f = imagecolorsforindex($img, $pos);
$gst = $f["red"]*0.15 + $f["green"]*0.5 + $f["blue"]*0.35;
if($gst>$max) $max=$gst;
if($gst<$min) $min=$gst;
}
}

$distance = $max-$min;

for($i=0; $i<$y; $i++) {
for($j=0; $j<$x; $j++) {
$pos = imagecolorat($img, $j, $i);
$f = imagecolorsforindex($img, $pos);

$red = 255*($f["red"]-$min)/$distance;
$green = 255*($f["green"]-$min)/$distance;
$blue = 255*($f["blue"]-$min)/$distance;

if($red<0) $red = 0.0;
elseif($red>255) $red=255.0;

if($green<0) $green = 0.0;
elseif($green>255) $green=255.0;

if($blue<0) $blue = 0.0;
elseif($blue>255) $blue=255.0;

$color = imagecolorresolve($img, $red, $green, $blue);
imagesetpixel($img, $j, $i, $color);
}
}
}
Anonymous
18 年前
// 测试 JPEG 图像是否为灰度或彩色

function iscolor($pic_adress){


// 如果 R=B=G,则像素为灰度
// 例如:彩色像素 R=250,G=140,B=19;灰度像素 R=110,G=110,B=110

// 我们检查 10 个像素以确定图片是否为灰度
$tocheck = 10;

$iscolor=false;

$temp= getimagesize($pic_adress);

$x= $temp[0];
$y= $temp[1];

$im= imagecreatefromjpeg($pic_adress);

// 现在检查像素
for( $i = 0 ; $i< $tocheck && !$iscolor; $i++){


// 在此处选择随机像素
$color = imagecolorat($im,rand(0,$x),rand(0,$y));

// 问题:颜色是整数
// 该数字的十六进制视图是 RRGGBB
// 在此处获取像素的蓝色部分
$blue = 0x0000ff & $color;

$green = 0x00ff00 & $color;
// 绿色部分需要向右移 8 位才能获得可比较的结果
$green = $green >> 8;
$red =0xff0000 & $color;
// 红色部分需要向右移 16 位
$red = $red >> 16;
// 如果其中一个像素不是灰度,则中断,并且知道这是一张彩色图片
if( $red!= $green || $green!= $blue){
$iscolor = true;
break;
}
}
return $iscolor;

}
swimgod
19 年前
我编写的这个函数将比较两张($start-$finish)图像,并更改“finish”图像中颜色不同的像素
然后将这两张图像并排显示在一张图像中

另一个功能是“display”,它将回显文本
“50% on
50% off” - 像素计数(如果数字小于 1,则将进入一位小数计数)

或者键入“2”将是
“10023 on
3000 off” - 像素计数

最后一个功能是“color”
您在数组中定义它
$color = array("r" => "244","g" => "122","b" => "100");

为了完成描述,我将展示此函数的“映射”
compare($start, $finish[, $color[, $display[, $type]]])
image-url($start) - 基础图像 URL
image-url($finish) - 比较图像 URL
array($color) - 具有键“r”、“g”、“b”的数组,r 表示红色 0-255,g 表示绿色 0-255,b 表示蓝色 0-255
bool($display) - 1 或 TRUE 将返回比较的文本统计信息
int($type) - 1 或 0 | 1 表示百分比结果 | 0 表示像素结果

<?
function compare($start, $finish, $color, $display, $type){

$im = ImageCreateFrompng($start);
$im2 = ImageCreateFrompng($finish);
$img['x'] = imagesx($im);
$img['y'] = imagesy($im);
$img2['x'] = imagesx($im2);
$img2['y'] = imagesy($im2);
if(($img['x'] == $img2['x']) && ($img['y'] == $img2['y'])){

// 获取并设置图像高度和宽度
$i = array("width" => $img['x']*2, "height" => $img['y']);
$im3 = imagecreatetruecolor($i['width'], $i['height']);
if($color){
$color = imagecolorallocate($im3, $color['r'], $color['g'], $color['b']);
}else{

$color = imagecolorallocate($im3, 255, 255, 255);
}
for($y = $img['y'];$y > 0; $y--){
for($x = $img['x'];$x > 0; $x--){
if(ImageColorAt($im, $x, $y) == ImageColorAt($im2, $x, $y)){
$on = $on+1;
$rgb = ImageColorAt($im, $x, $y);
Imagesetpixel($im3, $img['x']+$x, $y, $rgb);
}else{
$off = $off+1;
imagesetpixel($im3, $img['x']+$x, $y , $color);
}
}
}
if($display == true){
if(($type == "1") || (!$type)){
$off2 = (round(($off / $on)*10));
if(($off2 == 0) && ($off > 0)){
$off2 = round(($off / $on)*10)*10;
}
$on2 = (100-$off2);
$off2 .="%";
$on2 .="%";
}else{
$off2 = $off;
$on2 = $on;
}
echo $off2 ." off<br>". $on2 ." on";
}else{
imagecopy($im3, $im, 0, 0, 0, 0, $img['x'], $img['y']);
@header("Content-type: image/png");
imagepng($im3);
imagedestroy($im3);
}
imagedestroy($im);
imagedestroy($im2);
return TRUE;
}else{
return False;
}
}
?>
Levi Cole
9 年前
因此,我编写了我想出的这个函数(imagecolorat)最无用的用途。

基本上,它将给定图像中的每个像素转换为<i>标签。您可以使用 $p 设置渲染的像素大小

<?php
$p
= 4; // 设置像素宽度/高度
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Image to DOM</title>
<style>
.canvas {position: relative;}
.pixel {width: <?= 1*$p; ?>px; height: <?= 1*$p; ?>px; position: absolute; display: block;}
</style>
</head>
<body>

<form action="/" method="post" enctype="multipart/form-data">
<input type="file" name="image">
<input type="submit">
</form>



<?php
如果 ($_FILES) {
$post_img = $_FILES['image'];
$filename = $post_img['name'];
$tmp_img = $post_img['tmp_name'];

如果 (
preg_match('/[.](jpg)$/', $filename)) {
$img = imagecreatefromjpeg($tmp_img);
} 否则如果 (
preg_match('/[.](gif)$/', $filename)) {
$img = imagecreatefromgif($tmp_img);
} 否则如果 (
preg_match('/[.](png)$/', $filename)) {
$img = imagecreatefrompng($tmp_img);
}

list(
$width, $height) = getimagesize($tmp_img);

echo
'<div class="canvas" style="width: '.$width*$p.'px; height: '.$height*$p.'px;">';
对于 (
$i = 0; $i < $height; $i++) {
$y = $i; // 获取 Y 坐标
对于 ($j = 0; $j < $width; $j++) {
$x = $j; // 获取 X 坐标

$rgb = imagecolorat($img, $x, $y); // 获取像素颜色
$rgba = imagecolorsforindex($img, $rgb);
unset(
$rgba['alpha']); // 移除 Alpha 通道

$bg_color = implode(', ', $rgba);
?>
<i class="pixel" style="background: rgb(<?= $bg_color; ?>); top: <?= $i*$p; ?>px; left: <?= $j*$p; ?>px;"></i>
<?php
}
}
echo
'</div>';
}
?>

</body>
</html>
morten at nilsen dot com
18 年前
一种更好的将颜色值编码为 #rrggbb 的方法

<?php
printf
('#%06x',$c);
?>

或者

<?php
$rgb
= sprintf('#%06x',$c);
?>
robert at future-vision dot nl
18 年前
看,妈妈,没有表格 :)

我修改了来自 'hazard AT krankteil DOTTILLYDO de' 的代码,使函数输出一个显示图像的 div。

关于输出文件的尺寸,我可以说原始 png 文件要小得多,但这对于小按钮等来说可能是一个不错的功能。

使用方法与来自 'hazard AT krankteil DOTTILLYDO de' 的代码相同。

小提示:每个 div 都包含一个虚假图像。如果不在 IE 中,这会搞乱输出。

<?
函数 hexcolor($c) {
$r = ($c >> 16) & 0xFF;
$g = ($c >> 8) & 0xFF;
$b = $c & 0xFF;
返回 '#'.str_pad(dechex($r), 2, '0', STR_PAD_LEFT).str_pad(dechex($g), 2, '0', STR_PAD_LEFT).str_pad(dechex($b), 2, '0', STR_PAD_LEFT);
}


函数 png2div($filename) {

$img = imagecreatefrompng($filename);
$width = imagesx($img);
$height = imagesy($img);
$div_width = 1;
$previous_color = 0;

$output = '<div style="position:relative;width:' . $width . 'px;height:'. $height .'px;">';

对于($y = 0;$y < $height;++$y){

对于($x = 0;$x < $width;++$x){

$current_color = ImageColorAt($img, $x, $y);

如果($current_color == $previous_color && $x < $width-1){
++$div_width;
}
否则{
$output .= '<div style="position:relative;float:left;width:' . $div_width . 'px;height:1px;background-color:' . hexcolor((($div_width > 1)? $previous_color:$current_color)) . '"><img src="bogus.gif" alt="" width="1" height="1" /></div>';
$previous_color = $current_color;
$div_width = 1;
}
}
ob_flush();
}

$output .= '</div>';

返回 $output;

}

?>
black at scene-si dot org
14 年前
如果图像填充了纯色(rgb 0,0,0),则平均颜色将为 0,0,0,并且直方图在 r[0]、g[0] 和 b[0] 处将具有最大值。由于我们使用容差(+- 16)删除了这些值,因此我们只保留了平均值之外的颜色。

如果删除的颜色占图像的 90% 以上(我们根据平均颜色删除直方图的 6.25-12.5%),则我们假设图像为空白。

这可以检测任何颜色的纯色填充图像,以及颜色变化非常小的图像(空白墙、没有云的蓝天、几乎褪色的图像、对比度非常低和颜色范围低的图像)。该函数非常适合检查视频帧是否为空白(如果您正在生成缩略图)。

<?php
function isBlank($gd_resource, $tolerance, $percent)
{
list(
$w,$h) = array(imagesx($gd_resource), imagesy($gd_resource));

$count = 0;
$hr = $hg = $hb = array();
for (
$i=0; $i<$h; $i++) {
for (
$j=0; $j<$w; $j++) {
$pos = imagecolorat($gd_resource, $j, $i);
$f = imagecolorsforindex($gd_resource, $pos);
$hr[$f['red']] = issetor($hr[$f['red']],0) + 1;
$hg[$f['green']] = issetor($hg[$f['green']],0) + 1;
$hb[$f['blue']] = issetor($hb[$f['blue']],0) + 1;
$count ++;
}
}

$rc = array_sum($hr);
$gc = array_sum($hg);
$bc = array_sum($hb);

$r = $rc/$count;
$g = $gc/$count;
$b = $bc/$count;

$ra = range(max(0,$r-$tolerance), min(255,$r+$tolerance));
$ga = range(max(0,$g-$tolerance), min(255,$g+$tolerance));
$ba = range(max(0,$b-$tolerance), min(255,$b+$tolerance));

foreach (
$ra as $rx) {
unset(
$hr[$rx]);
}
foreach (
$ga as $gx) {
unset(
$hg[$gx]);
}
foreach (
$ba as $bx) {
unset(
$hb[$bx]);
}

$red = floatval(array_sum($hr)+1) / floatval($rc);
$green = floatval(array_sum($hg)+1) / floatval($gc);
$blue = floatval(array_sum($hb)+1) / floatval($bc);

if (
$red<$percent && $green<$percent && $blue<$percent) {
return
true;
}
return
false;
}

// 示例;

isBlank($gd_resource, 16, 0.1);

?>
To Top