PHP基于原生GD库, 获取图片中文字颜色, 匹配稀有度
一,获取文字颜色部分
如果背景有渐变色就不是很准, 如果对颜色没有特殊要求,建议使用调整图片对比度
二, 匹配对应的稀有度数据
这块不是很重要根据自己情况调整
/*** 根据文字颜色获取稀有度* @param Request $request* @return mixed|void|null*/public function getTextColor(Request $request){// 获得图片文件$file = $request->file('img');// 文件扩展$extension = $file->extension();// 文件尺寸信息(width, height)$imageSize = getimagesize($file);// 图片格式不同,需要调用不同的函数$image = null;if ($extension === 'png') {$image = imagecreatefrompng($file);}if ($extension === 'webp') {$image = imagecreatefromwebp($file);}if ($extension === 'jpg' || $extension === 'jpeg') {$image = imagecreatefromjpeg($file);}// 都没有匹配到返回提示信息if (is_null($image)) {exit(json_encode(['code' => 400, 'message' => '未知图片格式']));}// 调整对比度(重要)imagefilter($image, IMG_FILTER_CONTRAST, -50);// 文字颜色$result = $this->getTextColors($image, $imageSize[0], $imageSize[1]);// 稀有度return $this->getRarity($result);}/*** 获取文字颜色* @param $image* @param $imageWidth* @param $imageHeight* @return mixed*/public function getTextColors($image, $imageWidth, $imageHeight){// 假设图像中文字区域的左上角坐标为(100, 100),宽度为200,高度为50$textRegionX = 0;$textRegionY = 0;$textRegionWidth = $imageWidth;$textRegionHeight = $imageHeight;// 数组用于存储颜色及其数量$colors = array();// 循环遍历文字区域内的像素for ($x = $textRegionX; $x < $textRegionX + $textRegionWidth; $x++) {for ($y = $textRegionY; $y < $textRegionY + $textRegionHeight; $y++) {// 获取像素的颜色$color = @imagecolorat($image, $x, $y);// 将颜色转换为RGB值$rgb = imagecolorsforindex($image, $color);// 将颜色添加到数组中$colors[$color] = isset($colors[$color]) ? $colors[$color] + 1 : 1;}}// 根据颜色数量排序数组arsort($colors);// 获取前两种颜色$topColors = array_slice($colors, 0, 2, true);$colorArr = [];// 输出前两种颜色foreach ($topColors as $color => $count) {$rgb = imagecolorsforindex($image, $color);array_push($colorArr, "RGB({$rgb['red']},{$rgb['green']},{$rgb['blue']})");}return $colorArr[1];}/*** 获取稀有度* @param string $rgb* @return mixed|null*/public function getRarity(string $rgb){// 定义颜色的RGB范围$colors = [['color' => '灰色','rarity' => '粗糙','rgb' => 'RGB(146,146,146)',],['color' => '白色','rarity' => '普通','rgb' => 'RGB(255,255,255)',],['color' => '绿色','rarity' => '优秀','rgb' => 'RGB(160,255,0)',],['color' => '蓝色','rarity' => '稀有','rgb' => 'RGB(0,171,255)',],['color' => '紫色','rarity' => '史诗','rgb' => 'RGB(255,72,255)',],['color' => '橙色','rarity' => '传说','rgb' => 'RGB(255,196,0)',],['color' => '黄色','rarity' => '暗金','rgb' => 'RGB(255,255,187)',],];// 查找rgb相等的$result = collect($colors)->filter(function ($item) use ($rgb) {return $item['rgb'] === $rgb;})->values()->all();// 如果没有匹配到返回nullif (empty($result)) {return null;}return array_values($result)[0];}
有部分代码是使用
Laravel
框架的集合完成的
主要分为两部分
封装类
class GDTextColor
{/*** 获取图片文字区域*/public function getTextRegion($image, $ext, $x, $y){// 加载图片$image = self::load($image, $ext);// 裁剪图片return self::crop($image, $x, $y);}/*** 获取图片尺寸信息(width, height)*/public function getImageSize($file): array{$size = getimagesize($file);return ['width' => $size[0],'height' => $size[1],];}/*** 加载图片* @param $file* @return false|\GdImage|resource|void*/private static function load($file){$extension = $file->extension();// 图片格式不同,需要调用不同的函数$image = null;if ($extension === 'png') {$image = imagecreatefrompng($file);}if ($extension === 'webp') {$image = imagecreatefromwebp($file);}if ($extension === 'jpg' || $extension === 'jpeg') {$image = imagecreatefromjpeg($file);}// 都没有匹配到返回提示信息if (is_null($image)) {exit(json_encode(['code' => 400, 'message' => '未知图片格式']));}return $image;}/*** 裁剪图片文字区域* @param $image // 图片对象* @param int $x // 起始横坐标* @param int $y // 起始纵坐标* @param int $width // 宽* @param int $height // 高* @return false|\GdImage|resource*/private static function crop($image, int $x, int $y, int $width = 140, int $height = 30){// 创建裁剪后的图像资源$config = ['x' => $x,'y' => $y,'width' => $width,'height' => $height,];// 输出图片
// $textRegionImage = imagecrop($image, $config);
// header('Content-Type: image/jpeg');
// imagejpeg($textRegionImage);
// dd($textRegionImage);return imagecrop($image, $config);}/*** 获取文字颜色* @param $image* @param int $imageWidth* @param int $imageHeight* @return mixed*/public function getTextColors($image, int $imageWidth = 140, int $imageHeight = 30){// 调整对比度(重要)imagefilter($image, IMG_FILTER_CONTRAST, -50);// 假设图像中文字区域的左上角坐标为(100, 100),宽度为200,高度为50$textRegionX = 0;$textRegionY = 0;$textRegionWidth = $imageWidth;$textRegionHeight = $imageHeight;// 数组用于存储颜色及其数量$colors = array();// 循环遍历文字区域内的像素for ($x = $textRegionX; $x < $textRegionX + $textRegionWidth; $x++) {for ($y = $textRegionY; $y < $textRegionY + $textRegionHeight; $y++) {// 获取像素的颜色$color = @imagecolorat($image, $x, $y);// 将颜色转换为RGB值$rgb = imagecolorsforindex($image, $color);// 将颜色添加到数组中$colors[$color] = isset($colors[$color]) ? $colors[$color] + 1 : 1;}}// 根据颜色数量排序数组arsort($colors);// 获取前两种颜色$topColors = array_slice($colors, 0, 2, true);$colorArr = [];// 输出前两种颜色foreach ($topColors as $color => $count) {$rgb = imagecolorsforindex($image, $color);array_push($colorArr, "RGB({$rgb['red']},{$rgb['green']},{$rgb['blue']})");}return $colorArr[1];}/*** 调整RGB颜色的对比度* @param $color // rgb()* @param $contrast // 对比度 0 ~ 100* @return string*/public function adjustContrast($color, $contrast): string{// 将对比度限制在0到100之间$contrast = max(0, min(100, $contrast));// 将对比度转换为0到1之间的值$contrast = $contrast / 100;// 解析颜色值$color = str_replace('rgb(', '', $color);$color = str_replace(')', '', $color);$color = explode(',', $color);$r = intval($color[0]);$g = intval($color[1]);$b = intval($color[2]);// 将RGB值转换为0到1之间的范围$r /= 255;$g /= 255;$b /= 255;// 调整亮度和饱和度$brightness = (2 * $contrast) - 1;$saturation = $contrast;// 计算新的RGB值$r = $r + $brightness;$g = $g + $brightness;$b = $b + $brightness;if ($r > 1) {$r = 1;}if ($g > 1) {$g = 1;}if ($b > 1) {$b = 1;}// 调整饱和度$r = $r * $saturation;$g = $g * $saturation;$b = $b * $saturation;// 将RGB值转换回0到255的范围$r = round($r * 255);$g = round($g * 255);$b = round($b * 255);// 将RGB值合并为新的颜色$newColor = ($r << 16) | ($g << 8) | $b;return dechex($newColor);}/*** 获取稀有度*/public function getRarity($rgb){$colors = [['color' => '灰色','rarity' => '粗糙','min' => [90, 90, 90],'max' => [220, 220, 220]],['color' => '白色','rarity' => '普通','min' => [245, 245, 245],'max' => [255, 255, 255]],['color' => '绿色','rarity' => '优秀','min' => [0, 90, 0],'max' => [185, 255, 165]],['color' => '蓝色','rarity' => '稀有','min' => [0, 0, 128],'max' => [0, 255, 255]],['color' => '紫色','rarity' => '史诗','min' => [128, 0, 128],'max' => [255, 128, 255]],['color' => '橙色','rarity' => '传说','min' => [220, 128, 0],'max' => [255, 200, 128]],['color' => '黄色','rarity' => '暗金','min' => [220, 128, 128],'max' => [255, 255, 200]]];$rgbArr = $this->parseRGB($rgb);return $this->findMatchingColor($rgbArr, $colors);}/*** 判断颜色范围* @param $rgb* @param $colors* @return int|string|null*/public function findMatchingColor($rgb, $colors){foreach ($colors as $range) {$minR = $range['min'][0];$maxR = $range['max'][0];$minG = $range['min'][1];$maxG = $range['max'][1];$minB = $range['min'][2];$maxB = $range['max'][2];if ($rgb[0] >= $minR && $rgb[0] <= $maxR && $rgb[1] >= $minG && $rgb[1] <= $maxG && $rgb[2] >= $minB && $rgb[2] <= $maxB) {return $range;}}return null;}/*** 解析RGB并转换为数组* @param $rgbString* @return array*/public function parseRGB($rgbString): array{// 去除 RGB() 中的空格和括号$rgbString = str_ireplace(['RGB', '(', ')'], '', $rgbString);// 分割 RGB 值$rgbValues = explode(',', $rgbString);// 移除空格并转换为整数return array_map('intval', $rgbValues);}}