如同先前的評論所述,GD 在轉換成雙色圖像方面表現不佳,尤其是在處理照片時。以下程序將圖像轉換為兩種顏色,我認為是使用誤差擴散法(演算法取自新聞)。它很慢,但對於小圖像和低負載來說勉強夠用。我懷疑它可以變得更有效率 :-)
function ImageColorFloydSteinberg($dst_img, $src_img) {
ImageColorAllocate($dst_img, 0, 0, 0); // 配置黑色
ImageColorAllocate($dst_img, 255, 255, 255); // 配置白色
$grey_img = ImageCreate(ImageSX($src_img), ImageSY($src_img)); // 建立灰階圖片
for ($a = 0; $a <= 255; $a++) ImageColorAllocate($grey_img, $a, $a, $a); // 配置灰階色盤
for($x = 0; $x <= ImageSX($src_img); $x++) {
for($y = 0; $y <= ImageSY($src_img); $y++) {
$color = ImageColorsForIndex($src_img, ImageColorAt($src_img, $x, $y)); // 取得來源圖片像素的顏色資訊
$greyscale = .299 * $color["red"] + .587 * $color["green"] + .114 * $color["blue"]; // 計算灰階值
ImageSetPixel($grey_img, $x, $y, ImageColorClosest($grey_img, $greyscale, $greyscale, $greyscale)); // 設定灰階圖片像素
}
}
for($x = 0; $x <= ImageSX($src_img); $x++) {
for($y = 0; $y <= ImageSY($src_img); $y++) {
$color = ImageColorsForIndex($grey_img, ImageColorAt($grey_img, $x, $y)); // 取得灰階圖片像素的顏色資訊
if ($color["red"] > 128) { // 灰階值大於 128 則設為白色
ImageSetPixel($dst_img, $x, $y, ImageColorClosest($dst_img, 255, 255, 255)); // 設定目標圖片像素為白色
$err = $color["red"] - 255; // 計算誤差值
} else { // 灰階值小於等於 128 則設為黑色
ImageSetPixel($dst_img, $x, $y, ImageColorClosest($dst_img, 0, 0, 0)); // 設定目標圖片像素為黑色
$err = $color["red"]; // 計算誤差值
}
if ($x != ImageSx($src_img)) {
$color2 = ImageColorsForIndex($grey_img, ImageColorAt($grey_img, $x + 1, $y)); // 取得右邊像素顏色資訊
$newgrey = $color2["red"] + $err * 7 / 16; // 計算新的灰階值
ImageSetPixel($grey_img, $x + 1, $y, ImageColorClosest($grey_img, $newgrey, $newgrey, $newgrey)); // 設定右邊像素
}
if ($x != 0) { // 擴散誤差至左邊像素 (若非最左邊像素)
$color2 = ImageColorsForIndex($grey_img, ImageColorAt($grey_img, $x-1, $y)); // 取得左邊像素顏色資訊
$newgrey = $color2["red"] + $err * 3 / 16; // 計算新的灰階值
ImageSetPixel($grey_img, $x-1, $y, ImageColorClosest($grey_img,$newgrey, $newgrey, $newgrey)); // 設定左邊像素
}
if ($y != ImageSy($src_img)) {
$color2 = ImageColorsForIndex($grey_img, ImageColorAt($grey_img, $x, $y+1)); // 取得下方像素顏色資訊
$newgrey = $color2["red"] + $err * 5 / 16; // 計算新的灰階值
ImageSetPixel($grey_img, $x, $y+1, ImageColorClosest($grey_img,$newgrey, $newgrey, $newgrey)); // 設定下方像素
}
if ($x != ImageSx($src_img) && $y != ImageSy($src_img)) {
$color2 = ImageColorsForIndex($grey_img, ImageColorAt($grey_img, $x + 1, $y + 1)); // 取得右下方像素顏色資訊
$newgrey = $color2["red"] + $err / 16; // 計算新的灰階值
ImageSetPixel($grey_img, $x + 1, $y + 1, ImageColorClosest($grey_img, $newgrey, $newgrey, $newgrey)); // 設定右下方像素
}
}
}
imagedestroy($grey_img); // 銷毀灰階圖片
}
要輸出 WBMP 圖像,請使用
ImageWBMP($final_img, "", ImageColorClosest(255, 255, 255));