首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用Python和PIL创建标题模因

使用Python和PIL创建标题模因
EN

Stack Overflow用户
提问于 2020-08-20 05:12:28
回答 1查看 647关注 0票数 0

我想用Python3来拍摄一张图片,并把它变成一个模因。

我会拍一个像左边的图片,然后把它变成右边的图像。

我想要这段文字

  • 以白色为黑色轮廓
  • 居中
  • 如果文本对图像太宽,则拆分为多行。
  • 能够在字母之间加上间隔
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-08-20 05:12:28

这是一个Github回购,它有下面的解决方案,一个字体文件和一个用来测试它的图像。

在下面的解决方案中,您可以通过更改存储在Meme类属性中的值来定制文本。

你可能需要注意

  • 字母之间的空格(LetSpacing)
  • 黑色文本大纲(Stroke_width)的厚度
  • 字体大小(FontBase)
  • 结果图像的宽度(BaseWidth)
代码语言:javascript
运行
复制
from PIL import Image, ImageDraw, ImageFont
import textwrap

class Meme:

    basewidth = 1200            #Width to make the meme
    fontBase = 100              #Font size
    letSpacing = 9              #Space between letters
    fill = (255, 255, 255)      #TextColor
    stroke_fill = (0,0,0)       #Color of the text outline
    lineSpacing = 10            #Space between lines
    stroke_width=9              #How thick the outline of the text is
    fontfile = './impact.ttf'

    def __init__(self, caption, image):
        self.img = self.createImage(image)
        self.d = ImageDraw.Draw(self.img)

        self.splitCaption = textwrap.wrap(caption, width=20)  # The text can be wider than the img. If thats the case split the text into multiple lines
        self.splitCaption.reverse()                           # Draw the lines of text from the bottom up

        fontSize = self.fontBase+10 if len(self.splitCaption) <= 1 else self.fontBase   #If there is only one line, make the text a bit larger
        self.font = ImageFont.truetype(font=self.fontfile, size=fontSize)
        # self.shadowFont = ImageFont.truetype(font='./impact.ttf', size=fontSize+10)

    def draw(self):
        '''
        Draws text onto this objects img object
        :return: A pillow image object with text drawn onto the image
        '''
        (iw, ih) = self.img.size
        (_, th) = self.d.textsize(self.splitCaption[0], font=self.font) #Height of the text
        y = (ih - (ih / 10)) - (th / 2) #The starting y position to draw the last line of text. Text in drawn from the bottom line up

        for cap in self.splitCaption:   #For each line of text
            (tw, _) = self.d.textsize(cap, font=self.font)  # Getting the position of the text
            x = ((iw - tw) - (len(cap) * self.letSpacing))/2  # Center the text and account for the spacing between letters

            self.drawLine(x=x, y=y, caption=cap)
            y = y - th - self.lineSpacing  # Next block of text is higher up

        wpercent = ((self.basewidth/2) / float(self.img.size[0]))
        hsize = int((float(self.img.size[1]) * float(wpercent)))
        return self.img.resize((int(self.basewidth/2), hsize))

    def createImage(self, image):
        '''
        Resizes the image to a resonable standard size
        :param image: Path to an image file
        :return: A pil image object
        '''
        img = Image.open(image)
        wpercent = (self.basewidth / float(img.size[0]))
        hsize = int((float(img.size[1]) * float(wpercent)))
        return img.resize((self.basewidth, hsize))

    def drawLine(self, x, y, caption):
        '''
        The text gets split into multiple lines if it is wider than the image. This function draws a single line
        :param x: The starting x coordinate of the text
        :param y: The starting y coordinate of the text
        :param caption: The text to write on the image
        :return: None
        '''
        for idx in range(0, len(caption)):  #For each letter in the line of text
            char = caption[idx]
            w, h = self.font.getsize(char)  #width and height of the letter
            self.d.text(
                (x, y),
                char,
                fill=self.fill,
                stroke_width=self.stroke_width,
                font=self.font,
                stroke_fill=self.stroke_fill
            )  # Drawing the text character by character. This way spacing can be added between letters
            x += w + self.letSpacing #The next character must be drawn at an x position more to the right



caption = "Now I Have a Caption"
image = './my_image.jpg'
outputImage = './my_captioned_image.jpg'

meme = Meme(caption, image)
img = meme.draw()
if img.mode in ("RGBA", "P"):   #Without this the code can break sometimes
    img = img.convert("RGB")
img.save(outputImage, optimize=True, quality=80)    #Save with some image optimization
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63498671

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档