PHP Conference Japan 2024

imagecopymergegray

(PHP 4 >= 4.0.6, PHP 5, PHP 7, PHP 8)

imagecopymergegray複製並合併部分影像,使用灰階

說明

imagecopymergegray(
    GdImage $dst_image,
    GdImage $src_image,
    int $dst_x,
    int $dst_y,
    int $src_x,
    int $src_y,
    int $src_width,
    int $src_height,
    int $pct
): bool

imagecopymergegray() 會將 src_image 的一部分複製到 dst_image 上,起始位置為 x, y 座標 src_x, src_y,寬度為 src_width,高度為 src_height。定義的部分將會複製到 x, y 座標 dst_xdst_y 上。

此函式與 imagecopymerge() 相同,不同之處在於合併時,它會在複製操作之前將目標像素轉換為灰階,以保留來源的色調。

參數

dst_image

目標影像資源。

src_image

來源影像資源。

dst_x

目標點的 x 座標。

dst_y

目標點的 y 座標。

src_x

來源點的 x 座標。

src_y

來源點的 y 座標。

src_width

來源寬度。

src_height

來源高度。

pct

src_image 將根據 pct 轉換為灰階,其中 0 為完全灰階,100 則不變。當 pct = 100 時,此函式對於調色盤影像的行為與 imagecopy() 完全相同,但會忽略 Alpha 色板,而對於真彩色影像則會實作 Alpha 透明度。

回傳值

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

更新日誌

版本 說明
8.0.0 dst_imagesrc_image 現在需要 GdImage 實例;以前需要的是 resource

範例

範例 #1 imagecopymergegray() 的用法

<?php
// 建立影像實例
$dest = imagecreatefromgif('php.gif');
$src = imagecreatefromgif('php.gif');

// 複製並合併 - 灰色 = 20%
imagecopymergegray($dest, $src, 10, 10, 0, 0, 100, 47, 20);

// 輸出並釋放記憶體
header('Content-Type: image/gif');
imagegif($dest);

imagedestroy($dest);
imagedestroy($src);
?>

新增註解

使用者貢獻的註解 8 則註解

amezghal at msn dot com
16 年前
灰色效果 :)
<?php
header
('content-type:image/png');
$url_img = 'my_image.png';
$img = imagecreatefrompng($url_img);
$x = imagesx($img);
$y = imagesy($img);
$gray_img = imagecreatetruecolor($x, $y);
imagecolorallocate($gray_img, 0, 0, 0);
for (
$i = 0; $i < $x; $i++) {
for (
$j = 0; $j < $y; $j++) {
$rgb = imagecolorat($img, $i, $j);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
//設定灰階模式 $r = $g = $b
$color = max(array($r, $g, $b));
$gray_color = imagecolorexact($new_img, $color, $color, $color);
imagesetpixel($gray_img, $i, $j, $gray_color);
}
}
?>
Mark Barba
19 年前
// 使用我在 php.net 上找到的相同程式碼,
// 我能夠找出如何將 GIF(或 GD 支援的任何其他
// 格式)轉換為 CIP 格式。CIP 是思科 IP 電話的影像
// 格式... 7905/7940 和 7960
// 型號... 希望有人覺得這很有用並使其
// 更好...

/////// GIF2CIP PHP 程式碼 ///////

// 將記憶體中的影像轉換為灰階
$img_width = imageSX($im2);
$img_height = imageSY($im2);

// 轉換為灰階
// 注意:這不會影響您的原始影像,除非
// originalFileName 和 destinationFileName 相同
for ($y = 0; $y <$img_height; $y++) {
for ($x = 0; $x <$img_width; $x++) {
$rgb = imagecolorat($im2, $x, $y);
$red = ($rgb >> 16) & 0xFF;
$green = ($rgb >> 8) & 0xFF;
$blue = $rgb & 0xFF;

$gray = round(.299*$red + .587*$green + .114*$blue);

// 將灰階值左移
$grayR = $gray << 16; // R:紅色
$grayG = $gray << 8; // G:綠色
$grayB = $gray; // B:藍色

// 使用 OR 運算計算灰階值
$grayColor = $grayR | $grayG | $grayB;

// 設定像素顏色
imagesetpixel ($im2, $x, $y, $grayColor);
imagecolorallocate ($im2, $gray, $gray, $gray);
}
}
/////////////////////////////////////////////////////////

// 修改調色板為僅 4 色(7905/7940 和 7960 上的 CIP 影像是 2 位元色彩)
ImageTrueColorToPalette2($im2,FALSE,4);

// CIP 影像檔的基本標頭...
header ("Content-type: text/xml");
echo "<CiscoIPPhoneImage> ";
echo "<LocationX>-1</LocationX> ";
echo "<LocationY>-1</LocationY> ";
echo "<Width>132</Width> ";
echo "<Height>65</Height> ";
echo "<Depth>2</Depth> ";
echo "<Data>";

// 取得影像尺寸(與上述程式碼幾乎相同)
$img_width = imageSX($im2);
$img_height = imageSY($im2);

// 轉換為灰階
// 注意:這不會影響您的原始影像,除非
// originalFileName 和 destinationFileName 相同
for ($y = 0; $y <$img_height; $y++) {
for ($x = 0; $x+4 < $img_width; $x = $x+4)
{
for ($ix = 0; $ix < 4; $ix++)
{
$rgb = imagecolorat($im2, $x + $ix, $y);

// 我自己想出了這個轉換方法
// 一些聰明的人一定能將它完善
if ($rgb=="2") {$rgb=0;$Gray1[$ix] = $rgb;continue;}
if ($rgb=="0") {$rgb=2;$Gray1[$ix] = $rgb;continue;}
if ($rgb=="1") {$rgb=1;$Gray1[$ix] = $rgb;continue;}
if ($rgb=="3") {$rgb=3;$Gray1[$ix] = $rgb;continue;}
}
$gray1 = $Gray1[0];
$gray2 = $Gray1[1] << 2;
$gray3 = $Gray1[2] << 4;
$gray4 = $Gray1[3] << 6;

// 將 4 個像素打包成單個位元組,用於 CIP 影像
$grey = $gray1 | $gray2 | $gray3 | $gray4;

// CIP 影像資料以十六進位制傳送,實際上不需要 strtoupper。
$code = strtoupper(dechex($grey));

// 我對單個十六進位制值進行填充的快速修復方法
if (strlen($code)==1) $code = "0".$code;
echo $code;

}

}
echo "</Data>";
echo "<Title>$myvar</Title> ";
echo "<Prompt>$city</Prompt> ";
echo "</CiscoIPPhoneImage>";
exit;
switch251 at netcourrier dot com
20 年前
補充 code_couturier 的程式碼:他的程式碼會產生藍色圖片,因為他用於設定像素顏色的值(程式碼不完整:我一開始認為應該是 $gray)介於 0 和 255 之間,這對應於藍色等級。

要將圖片轉換為灰階,請使用以下程式碼

<?php
// replace with your files
$originalFileName = "colorPicture.jpg";
$destinationFileName = "bwPicture.jpg";

// create a copy of the original image
// works with jpg images
// fell free to adapt to other formats ;)
$fullPath = explode(".",$originalFileName);
$lastIndex = sizeof($fullPath) - 1;
$extension = $fullPath[$lastIndex];
if (
preg_match("/jpg|jpeg|JPG|JPEG/", $extension)){
$sourceImage = imagecreatefromjpeg($originalFileName);
}

// get image dimensions
$img_width = imageSX($sourceImage);
$img_height = imageSY($sourceImage);

// convert to grayscale
// note: this will NOT affect your original image, unless
// originalFileName and destinationFileName are the same
for ($y = 0; $y <$img_height; $y++) {
for (
$x = 0; $x <$img_width; $x++) {
$rgb = imagecolorat($sourceImage, $x, $y);
$red = ($rgb >> 16) & 0xFF;
$green = ($rgb >> 8) & 0xFF;
$blue = $rgb & 0xFF;

$gray = round(.299*$red + .587*$green + .114*$blue);

// shift gray level to the left
$grayR = $gray << 16; // R: red
$grayG = $gray << 8; // G: green
$grayB = $gray; // B: blue

// OR operation to compute gray value
$grayColor = $grayR | $grayG | $grayB;

// set the pixel color
imagesetpixel ($sourceImage, $x, $y, $grayColor);
imagecolorallocate ($sourceImage, $gray, $gray, $gray);
}
}

// copy pixel values to new file buffer
$destinationImage = ImageCreateTrueColor($img_width, $img_height);
imagecopy($destinationImage, $sourceImage, 0, 0, 0, 0, $img_width, $img_height);

// create file on disk
imagejpeg($destinationImage, $destinationFileName);

// destroy temp image buffers
imagedestroy($destinationImage);
imagedestroy($sourceImage);
?>

複製貼上,替換頂部的檔名即可(圖片檔必須與此指令碼位於同一個資料夾中。如果不是,則必須自行進行檔案管理)。
mail at laeubi dot de
21 年前
這個函式對我的真彩色影像無法正常運作(尚未針對其他類型進行測試),它只產生部分灰階影像,並且某些顏色會混亂。
我在這裡找到了解決方法
http://www.phpbuilder.com/columns/cash20030526.php3?page=2

[引言]
GD 函式庫下的進階影像編輯
著色
為影像著色相當容易。為影像著色的最簡單方法相當容易理解。建立一個尺寸相同的影像,並用您想要更改的顏色填充該影像。然後將這個新影像放置在舊影像的頂部,使其呈現著色外觀。

<?php
function imagecolorize(&$im,&$col,$pct) {
// 取得圖片寬度
$im_w = imagesx($im);
// 取得圖片高度
$im_h = imagesy($im);
// 設定一個帶有顏色的像素,以便我們輕鬆取得它
$setpixel = imagesetpixel($im,$im_w,0,$col);
// 取得顏色
$index = imagecolorat($im,$im_w,0);
// 在索引中查找顏色
$rgb = imagecolorsforindex($im,$index);
// 取得紅色值
$r = $rgb["red"];
// 取得綠色值
$g = $rgb["green"];
// 取得藍色值
$b = $rgb["blue"];
// 建立覆蓋層
$layover = imagecreate($im_w,$im_h);
// 在此圖像上分配顏色
$color = imagecolorallocate($layover,$r,$g,$b);
// 使用新顏色填充圖像(這其實不是必需的)
$fill = imagefill($layover,0,0,$color);
// 將覆蓋層合併到舊圖像之上
$merge = imagecopymerge($im,$layover,0,0,0,0,$im_w,$im_h,$pct);
imagedestroy($layover); // 銷毀覆蓋層
}
?>

如果我們使用藍色覆蓋層 RGB(0,0,255),我們會得到以下結果
[/quote]

如果您使用黑色或灰色,它並不完美,但總比沒有好 ;)
szamil at ginf dot pl
17 年前
我稍微修改了 switch251 的程式碼,現在我們有了懷舊相片效果
<?php
// replace with your files
$originalFileName = $filename;
$destinationFileName = "2".$filename;

// create a copy of the original image
// works with jpg images
// fell free to adapt to other formats ;)
$fullPath = explode(".",$originalFileName);
$lastIndex = sizeof($fullPath) - 1;
$extension = $fullPath[$lastIndex];
if (
preg_match("/jpg|jpeg|JPG|JPEG/", $extension))
{
$sourceImage = imagecreatefromjpeg($originalFileName);
}

// get image dimensions
$img_width = imageSX($sourceImage);
$img_height = imageSY($sourceImage);

// convert to grayscale
// note: this will NOT affect your original image, unless
// originalFileName and destinationFileName are the same
for ($y = 0; $y <$img_height; $y++)
{
for (
$x = 0; $x <$img_width; $x++)
{
$rgb = imagecolorat($sourceImage, $x, $y);
$red = ($rgb >> 16) & 0xFF;
$green = ($rgb >> 8) & 0xFF;
$blue = $rgb & 0xFF;

//sephia
$red2 = min($red*.393 + $green*.769 + $blue*.189,255);
$green2 = min($red*.349 + $green*.686 + $blue*.168,255);
$blue2 = min($red*.272 + $green*.534 + $blue*.131,255);
// shift gray level to the left

$grayR = $red2 << 16; // R: red
$grayG = $green2 << 8 ; // G: green
$grayB = $blue2; // B: blue

// OR operation to compute gray value
$grayColor = $grayR | $grayG | $grayB;


// set the pixel color
imagesetpixel ($sourceImage, $x, $y, $grayColor);
imagecolorallocate ($sourceImage, $gray, $gray, $gray);
}
}

// copy pixel values to new file buffer
$destinationImage = ImageCreateTrueColor($img_width, $img_height);
imagecopy($destinationImage, $sourceImage, 0, 0, 0, 0, $img_width, $img_height);

// create file on disk
imagejpeg($destinationImage, $destinationFileName);

// destroy temp image buffers
imagedestroy($destinationImage);
imagedestroy($sourceImage);
?>
annonymous at example dot com
20 年前
除了 code_couturier 的方法外,試試這個公式以他「更精確」的方式計算灰階值(亮度)。

$gray = round(.299*$red + .587*$green + .114*$blue);
code_couturier at graffiti dot net
21 年前
# 快速產生灰階影像的方法
# 從真彩色影像產生灰階影像

#...

# --- 快速灰階影像
for ($y = 0; $y <$img_height; $y++) {
for ($x = 0; $x <$img_width; $x++) {

# 這裡我們提取 x,y 像素的綠色值,將其用作灰階值
#
$gray = (ImageColorAt($image, $x, $y) >> 8) & 0xFF;

# 更精確的方法如下
# $rgb = ImageColorAt($image, $x, $y);
# $red = ($rgb >> 16) & 0xFF;
# $green = ($rgb >> 8) & 0xFF;
# $blue = $rgb & 0xFF;
# $gray = (int)(($red+$green+$blue)/4);

<!--這裡似乎有誤,正確的計算方式應為(int)(0.299*$red + 0.587*$green + 0.114*$blue)-->

# 這裡我們設定新的像素/顏色
imagesetpixel ($image, $x, $y,
ImageColorAllocate ($image, $gray,$gray,$gray));
}
}

# ...
anonymous at domain dot com
15 年前
imagefilter() 內建了灰階轉換功能。

<?php
/* 其他程式碼 */

$image = imagecreatefromjpeg('some.jpg');
imagefilter($image, IMG_FILTER_GRAYSCALE);

/* 其他程式碼 (例如儲存) */

imagedestroy($image);

/* 其他程式碼 */
?>

您可以透過以下方式產生懷舊色調效果:

<?php
/* 其他程式碼 */

$image = imagecreatefromjpeg('some.jpg');
imagefilter($image, IMG_FILTER_GRAYSCALE);
imagefilter($image, IMG_FILTER_COLORIZE, 112, 66, 20);
//維基百科上關於懷舊色調的 RGB 定義

/* 其他程式碼 (例如儲存) */

imagedestroy($image);

/* 其他程式碼 */
?>
To Top