PHP Conference Japan 2024

imagesetpixel

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

imagesetpixel設定單一像素

說明

imagesetpixel(
    GdImage $image,
    int $x,
    int $y,
    int $color
): bool

imagesetpixel() 會在指定的座標繪製一個像素。

參數

image

一個 GdImage 物件,由其中一個影像建立函式返回,例如 imagecreatetruecolor()

x

x 座標。

y

y 座標。

color

使用 imagecolorallocate() 建立的顏色識別碼。

傳回值

成功時返回 true,失敗時返回 false

更新日誌

版本 說明
8.0.0 image 參數現在需要一個 GdImage 實例;先前需要一個有效的 gd 資源

範例

範例 #1 imagesetpixel() 範例

隨機繪製,最後會呈現一張正常的圖片。

<?php

$x
= 200;
$y = 200;

$gd = imagecreatetruecolor($x, $y);

$corners[0] = array('x' => 100, 'y' => 10);
$corners[1] = array('x' => 0, 'y' => 190);
$corners[2] = array('x' => 200, 'y' => 190);

$red = imagecolorallocate($gd, 255, 0, 0);

for (
$i = 0; $i < 100000; $i++) {
imagesetpixel($gd, round($x), round($y), $red);
$a = rand(0, 2);
$x = ($x + $corners[$a]['x']) / 2;
$y = ($y + $corners[$a]['y']) / 2;
}

header('Content-Type: image/png');
imagepng($gd);

?>

以上範例會輸出類似以下的圖形:

Output of example : imagesetpixel()

另請參閱

新增筆記

使用者貢獻的筆記 24 則筆記

d [AT] sprid [DOT] de
19 年前
這段程式碼會產生一個 RGB 立方體(有無邊框皆可)。因為它只渲染可見像素,所以速度明顯很快(大約 1 到 2 秒)。透過更改 $order 變數,您可以從不同角度觀看立方體。輸入雙重或三重值(例如 rrg 或 ggg)將提供您單一通道的其他規格。如有任何建議,請寄信至我的電子郵件信箱。

<?php
$borders
= true;
$order = 'rgb';

set_time_limit(0);
$img = imageCreateTrueColor(510, 510);

$bg = imageColorAllocate($img, 255, 255, 255);
$black = imageColorAllocate($img, 255, 255, 255);

for (
$r=0; $r<256; $r++) {
for (
$g=0; $g<256; $g++) {
for (
$b=0; $b<256; $b++) {
$rN = ${$order{0}};
$gN = ${$order{1}};
$bN = ${$order{2}};

$col = imageColorAllocate($img, $rN, $gN, $bN);
imagesetpixel($img, $b+($r*0.5)+(255/4), $g+($r*0.5)+(255/4), $col);
if (
$r < 255 && $g > 0) break;
}
}

if (
$borders) {
imagesetpixel($img, ($r*0.5+(255/4)), ($r*0.5)+(255/4), $black);
imagesetpixel($img, ($r*0.5)+255+(255/4), ($r*0.5)+(255/4), $black);
imagesetpixel($img, ($r*0.5)+(255/4), ($r*0.5)+255+(255/4), $black);
}
}

if (
$borders) {
imageline($img, 255/4, 255/4, 255+(255/4), 255/4, $black);
imageline($img, 255/4, 255/4, 255/4, 255+(255/4), $black);
imageline($img, 255*0.5+(255/4), 255*0.5+(255/4), 255*0.5+(255/4), 255*0.5 + 509*0.5+(255/4), $black);
imageline($img, 255*0.5+(255/4), 255*0.5+(255/4), 255*0.5 + 509*0.5+(255/4), 255*0.5+(255/4), $black);
imageline($img, 255*0.5+(255/4), 255*0.5 + 509*0.5+(255/4), 255*0.5 + 509*0.5+(255/4), 255*0.5 + 509*0.5+(255/4), $black);
imageline($img, 255*0.5 + 509*0.5+(255/4), 255*0.5+(255/4), 255*0.5 + 509*0.5+(255/4), 255*0.5 + 509*0.5+(255/4), $black);
}

header("Content-Type: image/png");
imagepng($img);
imagedestroy($img);
?>
guy032 at gmail dot com
12 年前
將具有白色(或接近白色)背景的影像設為透明

<?
function FloodFill($im, $x, $y)
{
$rgb = imagecolorat($im, $x, $y);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;

$counter=0;
$counter2=0;
if($r >= 245){ $counter++;}
if($g >= 245){ $counter++;}
if($b >= 245){ $counter++;}
if($r >= 240){ $counter2++;}
if($g >= 240){ $counter2++;}
if($b >= 240){ $counter2++;}

if($counter >= 1 && $counter2 == 3){
$background = imagecolorallocate($im, 180, 0, 255);
imagesetpixel($im, $x, $y, $background);

FloodFill ($im, $x, $y+1);
FloodFill ($im, $x+1, $y);
FloodFill ($im, $x, $y-1);
}
}

$src = $_GET["src"];
$im = imagecreatefromjpeg($src);

// 繪製邊框
$border = imagecolorallocate($im, 180, 0, 255);
drawBorder($im, $border, 1);

// 繪製邊框
function drawBorder($im, $color, $thickness = 1)
{
$x1 = 0;
$y1 = 0;
$x2 = ImageSX($im) - 1;
$y2 = ImageSY($im) - 1;

for($i = 0; $i < $thickness; $i++)
{
ImageRectangle($im, $x1++, $y1++, $x2--, $y2--, $color);
}
}

$rgb = imagecolorat($im, 0, 0);
FloodFill($im, 0, 0);
$color = imagecolorallocate($im, 180, 0, 255);
imagecolortransparent($im, $color);
header("Content-type: image/png");
imagepng($im);
imagedestroy($im);
?>
odin<spam inside(C)>dtdm.org
20 年前
只是 Bresenham 演算法的一個簡單實現(教學用途....)

您可以在這裡找到更多關於這個以及許多其他圖形教學: http://brand107.home.comcast.net/pc-gpe/

<?php

/****************************************************
Bresenham Line Algorythm PHP/GD implementation
****************************************************/
function line($im,$x1,$y1,$x2,$y2,$color){

$deltax=abs($x2-$x1);
$deltay=abs($y2-$y1);

if (
$deltax>$deltay) {
$numpixels=$deltax+1;
$d=(2*$deltay)-$deltax;
$dinc1=$deltay << 1; $dinc2=($deltay-$deltax) << 1;
$xinc1=1; $xinc2=1;
$yinc1=0; $yinc2=1;
} else {
$numpixels=$deltay+1;
$d=(2*$deltax)-$deltay;
$dinc1=$deltax << 1; $dinc2=($deltax-$deltay)<<1;
$xinc1=0; $xinc2=1;
$yinc1=1; $yinc2=1;
}

if (
$x1>$x2) {
$xinc1=-$xinc1;
$xinc2=-$xinc2;
}

if (
$y1>$y2) {
$yinc1=-$yinc1;
$yinc2=-$yinc2;
}
$x=$x1;
$y=$y1;

for (
$i=0;$i<$numpixels;$i++) {
imagesetpixel($im,$x,$y,$color);
if (
$d<0) {
$d+=$dinc1;
$x+=$xinc1;
$y+=$yinc1;
} else {
$d+=$dinc2;
$x+=$xinc2;
$y+=$yinc2;
}
}
return ;
}

?>
mail AT kkapsner DOT de
14 年前
在 PHP 中原生「刪除」影像中的像素是可行的 - 關鍵函數是 imageAlphaBlending
<?php

$image
= imagecreatetruecolor(101, 101);
imagesavealpha($image, true);

# 繪製一個帶 Alpha 混合的紅色圓形
$red = imagecolorallocatealpha($image, 255, 0, 0, 30);
imagefilledellipse($image, 50, 50, 100, 100, $red);

# 為了清除圖形,停用 Alpha 混合
imagealphablending($image, false);

# 使用完全不透明的顏色繪製
$trans = imagecolorallocatealpha($image, 0, 0, 0, 127);

# 你可以清除任何你想要的形狀
imagefilledrectangle($image, 30, 30, 70, 70, $trans);

# 再次啟用 Alpha 混合
imagealphablending($image, true);

# 繪製一個帶 Alpha 混合的綠色矩形
$green = imagecolorallocatealpha($image, 0, 255, 0, 40);
imagefilledrectangle($image, 40, 20, 90, 80, $green);

header("Content-Type: image/png");
imagepng($image);

?>
bpgordon at gmail dot com
19 年前
這段程式碼將文字區塊轉換成圖片,文字區塊中的每個字元定義圖片中的一個像素,而區塊中的每一行(以 \n 分隔)則構成圖片中的一整列像素。
用法:放置 0 來建立白色像素。放置 1 來建立黑色像素。
範例:輸入以下數字(包含換行符號)將建立一個 3x3 的正方形,並帶有 1 像素的白色邊框。
00000
01110
01110
01110
00000

<?php
if (isset($_POST["sendtxt"])) {
header("Content-type: image/png");
$splitted = explode("\n", $_POST["sendtxt"]);
foreach (
$splitted as $tcurkey => $curval) $tsplitted[$tcurkey] = rtrim($curval);
$splitted = $tsplitted; //由於某些原因,引用無法正常運作...
$image = imagecreate(strlen($splitted[1]), count($splitted));
$white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF); // 不要刪除這一行
$black = imagecolorallocate($image, 0x00, 0x00, 0x00);
foreach(
$splitted as $curkey => $opelement) {
$subsplitten = preg_split("//", $opelement);
foreach(
$subsplitten as $subcurkey => $subopelement) {
if (
$subopelement == "1" || $subopelement == ".") imagesetpixel($image, $subcurkey-1, $curkey, $black);
}
}
imagepng($image);
imagedestroy($image);
} else {
echo <<<end
<table width="1" border="0"><td>
<form method="post" action="#">
<textarea cols="30" rows="7" name="sendtxt"></textarea><br>
<input type="submit" value="渲染">
</form></td></table>
end; }
?>
gerben at gerbs dot net
6 年前
請注意,您不必使用 imagecolorallocate 來繪製像素。您可以直接指定顏色,這樣速度也會更快
<?php
imagesetpixel
($img, $x, $y, $r << 16 | $g << 8 | $b);
?>
CR@SH
10 年前
imagesetpixel ($image, $x, $y, IMG_COLOR_BRUSHED);
cyberhorse at users dot sourceforge dot net
14 年前
給定一個影像 $src 和遮罩 $mask,這個函式會將遮罩應用於影像上,並正確地使用不同程度的透明度。

<?php
function image_mask(&$src, &$mask) {
imagesavealpha($src, true);
imagealphablending($src, false);
// 掃描影像像素
for ($x = 0; $x < imagesx($src); $x++) {
for (
$y = 0; $y < imagesy($src); $y++) {
$mask_pix = imagecolorat($mask,$x,$y);
$mask_pix_color = imagecolorsforindex($mask, $mask_pix);
if (
$mask_pix_color['alpha'] < 127) {
$src_pix = imagecolorat($src,$x,$y);
$src_pix_array = imagecolorsforindex($src, $src_pix);
imagesetpixel($src, $x, $y, imagecolorallocatealpha($src, $src_pix_array['red'], $src_pix_array['green'], $src_pix_array['blue'], 127 - $mask_pix_color['alpha']));
}
}
}
}
?>

如果您的遮罩是反向的,請將 127 - $mask_pix_color['alpha'] 改為 $mask_pix_color['alpha']
aelitadelarobia at gmail dot com
15 年前
另一個漸層範例,可以製作水平或垂直漸層

<?php
$width
=$_GET['width'];
$height=$_GET['height'];
$starts=explode(",",$_GET['startcolor']);
$ends=explode(",",$_GET['endcolor']);
$rstart=$starts[0];
$gstart=$starts[1];
$bstart=$starts[2];
$rend=$ends[0];
$gend=$ends[1];
$bend=$ends[2];
$r=$rstart;
$g=$gstart;
$b=$bstart;
$bigger=imagecreatetruecolor($width,$height);
for (
$y=0;$y<=265;$y++) {
if (
$mode == 'horiz') { //if doing a horizontal gradient, reset to the starting color every row
$r=$rstart;
$g=$gstart;
$b=$bstart;
}
for (
$x=0;$x<=464;$x++) {
imagesetpixel($bigger,$x,$y,imagecolorallocate($bigger,$r,$g,$b));
if (
$mode=="horiz") {
if (
$r != $rend) {
$r=$r+(($rend-$rstart)/$width);
}
if (
$g != $gend) {
$g=$g+(($gend-$gstart)/$width);
}
if (
$b != $bend) {
$b=$b+(($bend-$bstart)/$width);
}
}
}
if (
$mode == "vert") {
if (
$r != $rend) {
$r=$r+(($rend-$rstart)/$height);
}
if (
$g != $gend) {
$g=$g+(($gend-$gstart)/$height);
}
if (
$b != $bend) {
$b=$b+(($bend-$bstart)/$height);
}
}
}
header("Content-type: image/jpeg");
header('Content-Disposition: inline; filename="gradient.jpg"');

imagejpeg($bigger,NULL,99);
imagedestroy($bigger);
?>
Scott Evernden (doctor3d at gmail)
15 年前
關於 imagecreatefromtga() .. 我剛才用我認為有效的 Targa-24 和 Targa-32 位元影像做了一些測試,並修改了內部邏輯如下

<?php
if ($bytes_per_pixel == 2) // TARGA 16 - ARRRRRGG GGGBBBBB
{
$word = fileint($data, $pointer, 2);
$r = ($word & 0x7C00) >> 7;
$g = ($word & 0x03E0) >> 2;
$b = ($word & 0x001F) << 3;
$a = ($word & 0x8000) ? 127 : 0;
$color = imagecolorallocatealpha($image, $r, $g, $b, $a);
imagesetpixel($image, $x, $y, $color); }
else if (
$bytes_per_pixel == 3) // TARGA 24 - BBBBBBBB GGGGGGGG RRRRRRRR
{
$r = fileint($data, $pointer, 1);
$b = fileint($data, $pointer+1, 1);
$g = fileint($data, $pointer+2, 1);
$color = imagecolorallocate($image, $r, $g, $b);
imagesetpixel($image, $x, $y, $color);
}
else if (
$bytes_per_pixel == 4) // TARGA 32 - BBBBBBBB GGGGGGGG RRRRRRRR AAAAAAAA
{
$b = fileint($data, $pointer, 1);
$g = fileint($data, $pointer+1, 1);
$r = fileint($data, $pointer+2, 1);
$a = (255 - fileint($data, $pointer+3, 1)) >> 1;
$color = imagecolorallocatealpha($image, $r, $g, $b, $a);
imagesetpixel($image, $x, $y, $color);
}
?>

紅色和藍色的色調問題似乎已透過此方法修復...
Scott Evernden (doctor3d at gmail)
16 年前
我最後的註記沒有正確處理 Alpha 值,所以請對相關的行做出以下更改

$r = ($word & 0x7C00) >> 7;
$g = ($word & 0x03E0) >> 2;
$b = ($word & 0x001F) << 3;
$a = ($word & 0x8000) ? 127 : 0;
$color = imagecolorallocatealpha($image, $r, $g, $b, $a);
imagesetpixel($image, $x, $y, $color);
Scott Evernden (doctor3d at gmail)
16 年前
這是我的 imagecreatefromtga() 版本,已經過測試,適用於 16 位元 Targa 圖檔…改編自 zehao dot chang at gmail dot com 的版本

function imagecreatefromtga($filename)
{
$data = file_get_contents($filename);

// 提取標頭資訊
$string_length = fileint($data, 1, 1);
$data_type = fileint($data, 2, 1);
$width = fileint($data, 12, 2);
$height = fileint($data, 14, 2);
$bits_per_pixel = fileint($data, 16, 1);

$bytes_per_pixel = (int) $bits_per_pixel / 8;

// 目前僅支援 RGB 資料類型
switch ($data_type) // 標頭資訊取自 http://astronomy.swin.edu.au/~pbourke/dataformats/tga/
{
case 2: // 未壓縮的 RGB 影像
break;
case 0: // 無附加影像資料
case 1: // 未壓縮的顏色映射影像
case 3: // 未壓縮的黑白影像
case 9: // 色彩映射影像,採用行程編碼
case 10: // RGB 影像,採用行程編碼
case 11: // 黑白影像,已壓縮
case 32: // 壓縮的顏色映射資料,使用霍夫曼、Delta 和行程編碼
case 33: // 壓縮的顏色映射資料,使用霍夫曼、Delta 和行程編碼。4 通道四元樹類型處理
default:
return NULL; // 不支援任何這些類型
}

// 根據標頭資訊計算所需數值
$pointer = 18 + $string_length;
$x = 0; $y = $height - 1;

$image = imagecreatetruecolor($width, $height);

while ($pointer < strlen($data))
{
if ($bytes_per_pixel == 2) // TARGA 16 - ARRRRRGG GGGBBBBB
{
$word = fileint($data, $pointer, 2);
$r = ($word & 0x7C00) >> 10;
$g = ($word & 0x03E0) >> 5;
$b = ($word & 0x001F);
imagesetpixel($image, $x, $y, $r << 19 | $g << 11 | $b << 3);
}
else if ($bytes_per_pixel == 3) // TARGA 24 - RRRRRRRR GGGGGGGG BBBBBBBB
{
imagesetpixel($image, $x, $y, fileint($data, $pointer, 3));
}
else if ($bytes_per_pixel == 4) // TARGA 32 - AAAAAAAA RRRRRRRR GGGGGGGG BBBBBBBB
{
imagesetpixel($image, $x, $y, fileint($data, $pointer + 1, 3));
}

if (++$x == $width)
{
$y--;
$x = 0;
}
$pointer += $bytes_per_pixel;
}

return $image;
}

function fileint($data, $pos, $len)
{
return base_convert(bin2hex(strrev(substr($data, $pos, $len))), 16, 10);
}
zehao dot chang at gmail dot com
18 年前
這是我嘗試編寫的 imagecreatefromtga 函式。我使用了來自 send at mail dot 2aj dot net 和其他人的程式碼作為基礎,並增加了對 Targa 16、Targa 24 和 Targa 32 的支援。然而,我只支援未壓縮的 RGB 資料類型,因為這是我唯一需要的。(我刪除了 return_array 功能,因為您可以直接使用 imagesx() 和 imagesy() 來取得影像大小)。

請注意,我還沒有用 Targa 16 測試過,因為我目前手邊沒有。

<?php

function imagecreatefromtga( $filename )
{
$handle = fopen( $filename, 'rb' );
$data = fread( $handle, filesize( $filename ) );
fclose( $handle );

// Extract header information
$string_length = base_convert( bin2hex( substr($data,1,1) ), 16, 10 );
$data_type = base_convert( bin2hex( substr($data,2,1) ), 16, 10 );
$width = base_convert( bin2hex( strrev( substr($data,12,2) ) ), 16, 10 );
$height = base_convert( bin2hex( strrev( substr($data,14,2) ) ), 16, 10 );
$bits_per_pixel = base_convert( bin2hex( substr($data,16,1) ), 16, 10 );

// Currenly I'm only supporting RGB Data type
switch( $data_type ) // Header information taken from http://astronomy.swin.edu.au/~pbourke/dataformats/tga/
{
case
2: // Uncompressed RGB image
break;
case
0: // No attached image data
case 1: // Uncompressed color-mapped image
case 3: // Uncompressed black and white image
case 9: // Runlength encoded color-mapped image
case 10: // Runlength encoded RGB image
case 11: // Compressed black and white image
case 32: // Compressed color-mapped data, using Huffman, Delta, and runlength encoding
case 33: // Compressed color-mapped data, using Huffman, Delta, and runlength encoding. 4-pass quadtree-type process
default:
return
NULL; // No support for any of these types
}

// Compute things we need from the header information
$pointer = 18 + $string_length;
$bytes_per_pixel = (int) $bits_per_pixel/8;
$x = 0; $y = $height;

$image = imagecreatetruecolor($width, $height);

while (
$pointer < strlen($data) )
{
if(
$bytes_per_pixel == 2 ) // TARGA 16 - ARRRRRGG GGGBBBBB
{
$low_byte = bin2hex( strrev( substr($data, $pointer, $bytes_per_pixel)));
$high_byte = bin2hex( strrev( substr($data, $pointer, $bytes_per_pixel)));
$r = base_convert( ($high_byte & 0x7C)>>2, 16, 10);
$g = base_convert( (($high_byte & 0x03)<<3) | (($low_byte & 0xE0)>>5), 16, 10);
$b = base_convert( $low_byte & 0x1F, 16, 10);
imagesetpixel( $image, $x, $y, $r<<16 | $g<<8 | $b);
}
else if(
$bytes_per_pixel == 3 ) // TARGA 24 - RRRRRRRR GGGGGGGG BBBBBBBB
{
imagesetpixel( $image, $x, $y, base_convert( bin2hex( strrev( substr($data, $pointer, $bytes_per_pixel))), 16, 10));
}
else if(
$bytes_per_pixel == 4 ) // TARGA 32 - AAAAAAAA RRRRRRRR GGGGGGGG BBBBBBBB
{
imagesetpixel( $image, $x, $y, base_convert( bin2hex( strrev( substr($data, $pointer, $bytes_per_pixel-1))), 16, 10));
}

if(++
$x == $width)
{
$y--;
$x=0;
}
$pointer += $bytes_per_pixel;
}

return
$image;
}

?>
T. Dekker
19 年前
回覆 weitheism at gmail.com

在您早期的嘗試中,您應該使用 ImageAlphaBlending($image, false);。這樣,任何繪製/填充操作都會取代目標的 Alpha 值。
chris at drunkenpirates dot co dot uk
21 年前
<?php

/*
An example combining the use of ImageColorAllocate, Imagesetpixel, Imagecopyresized and some basic Trig

By chris@drunkenpirates.co.uk

*/

Header("Content-type: image/png");

$height = 128;
$width = 128;

$imA = ImageCreate($width, $height);
$imB = ImageCreate($width*4, $height*4);
$bckA = ImageColorAllocate($imA, 0,0,0);
$bckB = ImageColorAllocate($imB, 0,0,0);

//GENERATE GRAY SCALE PALLETE

for($c=0;$c<256;$c++){
ImageColorAllocate($imA, $c, $c, $c);
}

//PRODUCE DATA

$m=rand(0,10);
for(
$c=0;$c<128;$c++){
$s= (sin( deg2rad($c*360*$m/128) )+1)*127;
$col_arr[$c]=$s;
}
for(
$y=0;$y<$height;$y++){
for(
$x=0;$x<$width;$x++){
$imgA[$x][$y]=$col_arr[$x];
}
}
for(
$y=0;$y<$height;$y++){
for(
$x=0;$x<$width;$x++){
$imgB[$x][$y]=$col_arr[$y];
}
}

//SET PIXELS

for($y=0;$y<$height;$y++){
for(
$x=0;$x<$width;$x++){
$imgC[$x][$y]=$imgA[$x][$y]+$imgB[$x][$y];
$s=$imgC[$x][$y]/2;
Imagesetpixel($imA,$x,$y,$s);
}
}

//RESIZE IMAGE FOR DISPLAY

Imagecopyresized ($imB, $imA, 0, 0, 0, 0, $width*4, $height*4, $width, $width);
ImagePNG($imB);
?>
dino at nordmark dot dk
22 年前
上面的範例無效,因為有一些錯誤。
這樣可以運作,而且速度更快,因為只有一個 512*512 的迴圈。(但它仍然很慢)

<?
$filename="lena.raw";
$width=512;
$height=512;
$fp=fopen($filename, "r");
$contents=fread($fp,filesize($filename));
fclose($fp);

$image=imagecreate($width,$height);

// 建立灰階調色盤,因為影像限制為 256 色
for ($i=0;$i<256;$i++){ ImageColorAllocate($image,$i,$i,$i);}

// 這個方法很慢,但可能是唯一的方法
for ($i=0;$i<512;$i++){
for ($j=0;$j<512;$j++){
imagesetpixel ($image,$i,$j,ord($contents[$i+$j*512]));
}
}

imagepng($image,"result.png");
imagedestroy($image);

echo "<img src=result.png></img>";
?>

--

Dino Patti
caffinated
15 年前
想用這個函式玩點花樣嗎?試試邊緣偵測吧!(移植自 http://bitecode.co.uk/2008/07/edge-detection-in-python/

<?php
function edge($input, $output)
{
$in_im = imageCreateFromJpeg($input);
$gx = array(array(-1, 0, 1), array(-2, 0, 2), array(-1, 0, 1));
$gy = array(array(-1, -2, -1), array(0, 0, 0), array(1, 2, 1));
$x = imagesx($in_im);
$y = imagesy($in_im);
$out_im = imagecreatetruecolor($x, $y);
$colors = array(255 => imagecolorallocate($out_im, 255, 255, 255));
for (
$row = 1; $row < $x; $row++)
{
for (
$col = 1; $col < $y; $col++)
{
$eyedropper =imagecolorat($in_im, $x, $y);
$color =imagecolorsforindex($in_im, $eyedropper);
$pxval = ($color['red'] + $color['green'] + $color['blue']) / 3;
$pixel_gx = $pixel_gy = 0;
for (
$i = -1; $i < 2; $i++)
{
for (
$j = -1; $j < 2; $j++)
{
$eyedropper =imagecolorat($in_im, $row+$i, $col+$j);
$color =imagecolorsforindex($in_im, $eyedropper);
$val = ($color['red'] + $color['green'] + $color['blue']) / 3;
$pixel_gx += $gx[$i+1][$j+1] * $val;
$pixel_gy += $gy[$i+1][$j+1] * $val;
}
}
$pixel = sqrt($pixel_gx * $pixel_gx + $pixel_gy * $pixel_gy);
$pixel = abs(255 - (int)$pixel);
if (!isset(
$colors[$pixel])) $colors[$pixel] = imagecolorallocate($out_im, $pixel, $pixel, $pixel);
imageSetPixel($out_im, $row, $col, $colors[$pixel]);
}
}
imagejpeg($out_im,$output, 75);
}

edge('input.jpg', 'output.jpg');

?>
CPHaxer
15 年前
很抱歉我的函式介紹這麼長,但我只是想說明它是如何運作的,以及有時候想出這些函式的點子有多麼愚蠢。玩得開心 ;D

<?php

//@FunctionName: drawPlot
//@Parameters: drawPlot(img &$image, int $red, int $green, int $blue, int $x, int $y)
//
// img $image
// The Image it will draw on. The Image will be modified; there is no return value.
//
// int $red, int $green, int $blue
// The Colorvalues to draw with
//
// int $x, int $y
// The Location to draw the Plot.
// And this is the Mainpart, because $x and $y
// NEED NOT be rounded!
// If you want to make a Plot at [253.643891, 482];
// It will draw the Plot there. Exact at the Coordinates.
// You could use this to make smooth lines.
// They have rational Coordinates, too.
//
//@Author: Alexander Rath (*Feb 9th, 1996 ; 13 Years old)
//
//@Idea: We have in Math Geometrie now. And as the only Computerfreak
// In the class, i asked me: "How would it be, to mirror something
// At a NOT FLAT LINE."
// So I started thinking about it. First i tought about degresses - Nah!
// Then i saw:
// A point to mirror, has the SHORTEST way to the Line;
// so i just needed to make the result smooth.
// Unlike the other ways to draw pixels.
// ~I started developing this:
// PS: Sorry for bad english ( I am german )

//Lets create a TrueColor Image Resource
$image = imagecreatetruecolor(640, 480);

//Lets make it Alpha
imagealphablending($image, true);
imagesavealpha($image, true);

//...with White Background to draw on.
imagefilledrectangle($image, 0, 0, 640, 480, imagecolorallocate($image, 255, 255, 255));

//This is my little "Example"-Script
for($x = 0; $x <= 640; $x = $x + 0.01) {
$y = $x / (tan($x) + 1);
drawPlot($image, 0, 0, 0, $x, $y);
}

header("Content-type: image/png");
imagepng($image);

function
drawPlot(&$func_image, $func_red, $func_green, $func_blue, $func_x, $func_y) {
$func_Right = $func_x - floor($func_x);
$func_Left = 1 - $func_Right;

$func_Bottom = $func_y - floor($func_y);
$func_Top = 1 - $func_Bottom;

$func_RightAlpha = $func_Right * 127;
$func_LeftAlpha = $func_Left * 127;

$func_LeftTop = $func_LeftAlpha * $func_Top;
$func_RightTop = $func_RightAlpha * $func_Top;
$func_LeftBottom = $func_LeftAlpha * $func_Bottom;
$func_RightBottom = $func_RightAlpha * $func_Bottom;

$func_x = floor($func_x);
$func_y = floor($func_y);

imagesetpixel($func_image, $func_x, $func_y, imagecolorallocatealpha($func_image, $func_red, $func_green, $func_blue, 127 - $func_LeftTop));
imagesetpixel($func_image, $func_x + 1, $func_y, imagecolorallocatealpha($func_image, $func_red, $func_green, $func_blue, 127 - $func_RightTop));
imagesetpixel($func_image, $func_x + 1, $func_y + 1, imagecolorallocatealpha($func_image, $func_red, $func_green, $func_blue, 127 - $func_RightBottom));
imagesetpixel($func_image, $func_x, $func_y + 1, imagecolorallocatealpha($func_image, $func_red, $func_green, $func_blue, 127 - $func_LeftBottom));
}

?>

玩得開心 ;D
mm
15 年前
@ Scott Evernden

Scott,你的函式適用於未壓縮的 TGA 影像檔,但根據我的測試,TGA 32 含 Alpha 色板的結果並不正確。如果 Alpha 全部是白色,產生的影像會帶有紅色調。如果是黑色,產生的影像則會帶有藍色調。我不知道如何讓它忽略 Alpha 色板,但那樣會很方便...
Gusts Kaksis
17 年前
這段程式碼產生一個簡單的顏色表 - 並不是很精確的顏色表(最好能定義顏色的漸變 - 更多漸變)

<?php
set_time_limit
(200);
/*
Custommize this to see some nice changes:
*/
$width = 360; // degrees
$height = 18; // byte
$offset = -60; // offset of color hue

/*
Main programm:
Here comes transformations - width to degrees and height to intesity
*/
$w2deg = $width/360;
$h2byte = $height/255;
$byte2deg = 255/360;
$im = imagecreatetruecolor($width,$height);
for (
$x = 0; $x < $width; $x ++){
/*
Transform X to degrees
*/
$x_pos = $x/$w2deg;
/*
Intensity position (where max intensity is 255) on 360 degree scale.
0 = red
1 = green
2 = blue
*/
$rgb_pos[0] = sin(deg2rad($x_pos) - deg2rad($offset + 0));
$rgb_pos[1] = sin(deg2rad($x_pos) - deg2rad($offset + 120));
$rgb_pos[2] = sin(deg2rad($x_pos) - deg2rad($offset + 240));
/*
Calculate intesity at current point 0 - 255
*/
$rgb_col[0] = 127 + 127 * $rgb_pos[0];
$rgb_col[1] = 127 + 127 * $rgb_pos[1];
$rgb_col[2] = 127 + 127 * $rgb_pos[2];

/*
White -> color -> Black loop
*/
for ($y = 0; $y < $height; $y ++){
/*
Transform Y to intensity (-255 to 255)
*/
$y_pos = -255 + ($y/$h2byte) * 2;
$rgb_out[0] = $rgb_col[0] - $y_pos;
$rgb_out[1] = $rgb_col[1] - $y_pos;
$rgb_out[2] = $rgb_col[2] - $y_pos;

/*
If we go over 255 or under 0 we normalize it
*/
foreach($rgb_out as $key => $col){
if (
$col > 255){
$rgb_out[$key] = 255;
} else if (
$col < 0){
$rgb_out[$key] = 0;
}
}
/*
Put a pixel
*/
$col = imagecolorallocate($im,$rgb_out[0],$rgb_out[1],$rgb_out[2]);
imagesetpixel($im,$x,$y,$col);
}
}
/*
Test output
*/
imagejpeg($im,'colortable.jpg');
echo
'<img src="colortable.jpg">';
?>
Brian Vaughn [php at boynamedbri dot com]
19 年前
我找了很久,但找不到任何範例程式碼可以用包含 Alpha 透明度的浮水印來標記影像。所以下面的類別就是做這件事的。它接受兩個影像物件作為參數:主要影像和浮水印影像(可以是 gif、png 等任何格式) - 以及可選的 Alpha 設定(浮水印影像的 Alpha 值為 0-100%)。然後它會建立並返回一個新的影像,其中包含置中對齊、疊加在較大影像上的 Alpha 透明浮水印。

<?php
class watermark{

function
create_watermark( $dst_img, $watermark_img, $alpha = 100 ) {
$alpha /= 100; # convert 0-100% user-friendly alpha to decimal

# calculate our images dimensions
$dst_img_w = imagesx( $dst_img );
$dst_img_h = imagesy( $dst_img );
$watermark_img_w = imagesx( $watermark_img );
$watermark_img_h = imagesy( $watermark_img );

# create new image to hold merged changes
$return_img = imagecreatetruecolor( $dst_img_w, $dst_img_h );
# $return_img = imagecreate( $dst_img_w, $dst_img_h );

# determine center position coordinates
$dst_img_min_x = floor( ( $dst_img_w / 2 ) - ( $watermark_img_w / 2 ) );
$dst_img_max_x = ceil( ( $dst_img_w / 2 ) + ( $watermark_img_w / 2 ) );
$dst_img_min_y = floor( ( $dst_img_h / 2 ) - ( $watermark_img_h / 2 ) );
$dst_img_max_y = ceil( ( $dst_img_h / 2 ) + ( $watermark_img_h / 2 ) );

# walk through main image
for( $y = 0; $y < $dst_img_h; $y++ ) {
for(
$x = 0; $x < $dst_img_w; $x++ ) {
$return_color = NULL;

# determine the correct pixel location within our watermark
$watermark_x = $x - $dst_img_min_x;
$watermark_y = $y - $dst_img_min_y;

# fetch color information for both of our images
$dst_rgb = imagecolorsforindex( $dst_img, imagecolorat( $dst_img, $x, $y ) );

# if our watermark has a non-transparent value at this pixel intersection
# and we're still within the bounds of the watermark image
if ( $watermark_x >= 0 && $watermark_x < $watermark_img_w &&
$watermark_y >= 0 && $watermark_y < $watermark_img_h ) {
$watermark_rbg = imagecolorsforindex( $watermark_img, imagecolorat( $watermark_img, $watermark_x, $watermark_y ) );

# using image alpha, and user specified alpha, calculate average
$watermark_alpha = round( ( ( 127 - $watermark_rbg['alpha'] ) / 127 ), 2 );
$watermark_alpha = $watermark_alpha * $alpha;

# calculate the color 'average' between the two - taking into account the specified alpha level
$avg_red = $this->get_ave_color( $dst_rgb['red'], $watermark_rbg['red'], $watermark_alpha );
$avg_green = $this->get_ave_color( $dst_rgb['green'], $watermark_rbg['green'], $watermark_alpha );
$avg_blue = $this->get_ave_color( $dst_rgb['blue'], $watermark_rbg['blue'], $watermark_alpha );

# calculate a color index value using the average RGB values we've determined
$return_color = $this->imagegetcolor( $return_img, $avg_red, $avg_green, $avg_blue );

# if we're not dealing with an average color here, then let's just copy over the main color
} else {
$return_color = imagecolorat( $dst_img, $x, $y );

}
# END if watermark

# draw the appropriate color onto the return image
imagesetpixel( $return_img, $x, $y, $return_color );

}
# END for each X pixel
} # END for each Y pixel

# return the resulting, watermarked image for display
return $return_img;

}
# END create_watermark()

# average two colors given an alpha
function get_ave_color( $color_a, $color_b, $alpha ) {
return
round( ( ( $color_a * ( 1 - $alpha ) ) + ( $color_b * $alpha ) ) );
}
# END get_ave_color()

# return closest pallette-color match for RGB values
function imagegetcolor($im, $r, $g, $b) {
$c=imagecolorexact($im, $r, $g, $b);
if (
$c!=-1) return $c;
$c=imagecolorallocate($im, $r, $g, $b);
if (
$c!=-1) return $c;
return
imagecolorclosest($im, $r, $g, $b);
}
# EBD imagegetcolor()

} # END watermark API
?>
weitheism at gmail.com
19 年前
我一直在尋找一種方法可以從影像資源中實際刪除像素、正方形或影像的一部分,一開始我以為 imagesetpixel 可以做到這一點。不幸的是,它只是在那個像素上塗抹顏色,據我所知,PHP 沒有任何原生方法可以從影像中刪除區段 - 所以這個小方法應該可以處理刪除圖片的矩形部分!

function deleteRectangle(&$oldImage,$leftX,$leftY,$rightX,$rightY)
{
// 因為 PHP 沒有原生方法可以刪除影像的部分
// 我們必須將影像分成四個不同的部分,然後手動複製到新的
// 影像

$xSize = imagesx($oldImage);
$ySize = imagesy($oldImage);

// 將影像分成四個區段以進行複製
$imagesection = array();
$imagesection[] = array(0,0,$leftX,$ySize);
$imagesection[] = array($leftX,0,$rightX+1,$leftY);
$imagesection[] = array($leftX,$rightY+1,$rightX+1,$ySize);
$imagesection[] = array($rightX+1,0,$xSize,$ySize);

// 建立新的複製影像
$newImage = imagecreatetruecolor($xSize,$ySize);
// 對於透明度至關重要
imagesavealpha($newImage, true);

// 將背景填滿透明色
$transparentBackground = imagecolorallocatealpha($newImage, 255, 255, 255, 127);
imagefill($newImage, 0, 0, $transparentBackground);

// 將四個影像區塊各自複製到原本的位置
for ($i = 0; $i < count($imagesection); $i++)
imagecopyresampled($newImage, $oldImage, $imagesection[$i][0], $imagesection[$i][1], $imagesection[$i][0], $imagesection[$i][1], $imagesection[$i][2] - $imagesection[$i][0], $imagesection[$i][3] - $imagesection[$i][1], $imagesection[$i][2] - $imagesection[$i][0], $imagesection[$i][3] - $imagesection[$i][1]);

// 或者,您可以循環遍歷影像中的每個像素,並查看該像素是否在區域內
// 但這可能更耗資源
imagedestroy($oldImage);

// 將舊影像設定為新的、已清除的影像
$oldImage = $newImage;
}

它是在考慮透明背景的情況下製作的,但您可以通過將 imagecreatetruecolor 更改為 imagecreate 並刪除處理透明度的程式碼來輕鬆更改它。希望它有幫助!
richard at mf2fm dot co dot uk
20 年前
以下是一個函式,它接受一個影像($im)並返回對比度最大化的影像...

<?php
function contrast($im) {
$brightness=0;
$maxb=0;
$minb=255;
$imagesize=getimagesize($im);
$w=$imagesize[0];
$h=$imagesize[1];
for (
$x=0; $x<$w; $x++) {
for (
$y=0; $y<$h; $y++) {
$rgb=imagecolorat($im, $x, $y);
$rgb=imagecolorsforindex($im, $rgb);
$grey=0.2125*$rgb['red']+
0.7154*$rgb['green']+
0.0721*$rgb['blue'];
$brightness+=$grey;
if (
$grey>$maxb) $maxb=$grey;
if (
$grey<$minb) $minb=$grey;
}
}
$brightness=$brightness/($w*$h);
$minb=$brightness/($brightness-$minb);
$maxb=(255-$brightness)/($maxb-$brightness);
$contrast=min($minb, $maxb);
for (
$x=0; $x<$w; $x++) {
for (
$y=0; $y<$h; $y++) {
$rgb=imagecolorat($im, $x, $y);
$rgb=imagecolorsforindex($im, $rgb);
imagesetpixel($im, $x, $y,
65536*floor(min($rgb['red']*$contrast, 255))+
256*floor(min($rgb['green']*$contrast, 255))+
floor(min($rgb['blue']*$contrast, 255)));
}
}
return (
$im);
}
?>

用法示例如下
<?php
$imagefile
="/path/filename";
$image=imagecreatefromjpeg($imagefile);
$image=contrast($image);
imagejpeg($image, $imagefile);
?>
匿名
16 年前
此程式碼片段根據 RGB 組件的值建立漸變影像。漸變允許您的頁面具有陰影效果。

<?php
try{
if(!
$image=imagecreatetruecolor(50,10)){
throw new
Exception('建立影像時發生錯誤');
}

for(
$y=0;$y<10;++$y)
{
$color=imagecolorallocate($image, 75+($y*5),75+($y*11),75+($y*9));
for(
$x=0;$x<50;++$x)
{
imagesetpixel($image,$x,$y,$color);
}
}

//header("Content-type: image/jpeg");
imagejpeg($image,'footerShadow.jpg');
// 釋放記憶體
imagedestroy($image);

}
catch(
Exception $e){
echo
$e->getMessage();
exit();
}
?>
To Top