Shr*_*rey 2 python python-imaging-library python-3.x
我想用PIL画一个虚线矩形。
我知道我可以绘制 4 条不同的虚线,使其看起来像一个矩形:
for x in range(0, Width_of_image, 5):
d.line([(x, 30), (x + 2, 30)],fill ="black", width =2)
Run Code Online (Sandbox Code Playgroud)
但是有没有办法使用 绘制一个矩形draw.rectangle,即不绘制 4 条不同的线?
正如其他用户所说,PIL 库(特别是PIL.ImageDraw.ImageDraw)不提供绘制虚线的功能。我查看了有关 PIL 中虚线的 StackOverflow 问题(以及其他地方),但我还没有找到在 PIL 中绘制虚线的令人满意的方法。我找到的答案都没有以预期的方式绘制虚线(其他Python库提供虚线的方式,例如使用Tkinter canvas)。
所以我编写了一个类DashedImageDraw(它扩展了PIL.ImageDraw.ImageDraw),它具有绘制虚线和虚线矩形的功能。以下是代码和如何使用它的示例:
from PIL import Image, ImageDraw\nimport math\n\n\nclass DashedImageDraw(ImageDraw.ImageDraw):\n\n def thick_line(self, xy, direction, fill=None, width=0):\n #xy \xe2\x80\x93 Sequence of 2-tuples like [(x, y), (x, y), ...]\n #direction \xe2\x80\x93 Sequence of 2-tuples like [(x, y), (x, y), ...]\n if xy[0] != xy[1]:\n self.line(xy, fill = fill, width = width)\n else:\n x1, y1 = xy[0] \n dx1, dy1 = direction[0]\n dx2, dy2 = direction[1]\n if dy2 - dy1 < 0:\n x1 -= 1\n if dx2 - dx1 < 0:\n y1 -= 1\n if dy2 - dy1 != 0:\n if dx2 - dx1 != 0:\n k = - (dx2 - dx1)/(dy2 - dy1)\n a = 1/math.sqrt(1 + k**2)\n b = (width*a - 1) /2\n else:\n k = 0\n b = (width - 1)/2\n x3 = x1 - math.floor(b)\n y3 = y1 - int(k*b)\n x4 = x1 + math.ceil(b)\n y4 = y1 + int(k*b)\n else:\n x3 = x1\n y3 = y1 - math.floor((width - 1)/2)\n x4 = x1\n y4 = y1 + math.ceil((width - 1)/2)\n self.line([(x3, y3), (x4, y4)], fill = fill, width = 1)\n return \n \n def dashed_line(self, xy, dash=(2,2), fill=None, width=0):\n #xy \xe2\x80\x93 Sequence of 2-tuples like [(x, y), (x, y), ...]\n for i in range(len(xy) - 1):\n x1, y1 = xy[i]\n x2, y2 = xy[i + 1]\n x_length = x2 - x1\n y_length = y2 - y1\n length = math.sqrt(x_length**2 + y_length**2)\n dash_enabled = True\n postion = 0\n while postion <= length:\n for dash_step in dash:\n if postion > length:\n break\n if dash_enabled:\n start = postion/length\n end = min((postion + dash_step - 1) / length, 1)\n self.thick_line([(round(x1 + start*x_length),\n round(y1 + start*y_length)),\n (round(x1 + end*x_length),\n round(y1 + end*y_length))],\n xy, fill, width)\n dash_enabled = not dash_enabled\n postion += dash_step\n return\n\n def dashed_rectangle(self, xy, dash=(2,2), outline=None, width=0):\n #xy - Sequence of [(x1, y1), (x2, y2)] where (x1, y1) is top left corner and (x2, y2) is bottom right corner\n x1, y1 = xy[0]\n x2, y2 = xy[1]\n halfwidth1 = math.floor((width - 1)/2)\n halfwidth2 = math.ceil((width - 1)/2)\n min_dash_gap = min(dash[1::2])\n end_change1 = halfwidth1 + min_dash_gap + 1\n end_change2 = halfwidth2 + min_dash_gap + 1\n odd_width_change = (width - 1)%2 \n self.dashed_line([(x1 - halfwidth1, y1), (x2 - end_change1, y1)],\n dash, outline, width) \n self.dashed_line([(x2, y1 - halfwidth1), (x2, y2 - end_change1)],\n dash, outline, width)\n self.dashed_line([(x2 + halfwidth2, y2 + odd_width_change),\n (x1 + end_change2, y2 + odd_width_change)],\n dash, outline, width)\n self.dashed_line([(x1 + odd_width_change, y2 + halfwidth2),\n (x1 + odd_width_change, y1 + end_change2)],\n dash, outline, width)\n return\n \n\n\nimage = Image.new(\'RGB\', (300, 200), (255, 255, 255))\nd = DashedImageDraw(image)\n\nd.dashed_rectangle([(20, 20), (280, 180)],\n dash = (5, 3), outline = \'black\', width = 2)\n\nimage.save("image.png", "PNG")\nRun Code Online (Sandbox Code Playgroud)\n这条线绘制了矩形:
\nd.dashed_rectangle([(20, 20), (280, 180)], dash = (5, 3), outline = \'black\', width = 2)\nRun Code Online (Sandbox Code Playgroud)\n(20, 20)是左上角,(280, 180)是右下角,outline是线条的颜色,width是线条的宽度,dash 是表示虚线图案的元组。例如:
dash = (5, 3) 将画线:
\n----- ----- ----- ----- ----- -----
dash = (4, 2, 3, 1) 将画线:
\n---- --- ---- --- ---- --- ---- --- ----
这是上面代码生成的虚线矩形的图像:
\n\n| 归档时间: |
|
| 查看次数: |
4998 次 |
| 最近记录: |