瀏覽代碼

给图片添加水印

xyxie 3 月之前
父節點
當前提交
b450630211
共有 2 個文件被更改,包括 192 次插入2 次删除
  1. 16 2
      controllers/report_v2.go
  2. 176 0
      static/watermarker.py

+ 16 - 2
controllers/report_v2.go

@@ -16,6 +16,7 @@ import (
 	"html"
 	"io"
 	"os"
+	"os/exec"
 	"strconv"
 	"strings"
 	"time"
@@ -1956,8 +1957,8 @@ func fixSmartReport() {
 
 	fmt.Println("修复智能研报完成")
 }
-func initPdf() {
-	inFile := "anNNgk3Bbi4LRULwcJgNOPrREYh5.pdf"
+func InitPdf() {
+	inFile := "铝年报:25年成本回落后,开启长周期故事20241204.pdf"
 	f2, err := services.GeneralWaterMarkPdf(inFile, "颜鹏 - 18170239278")
 	//f2, err := services.GeneralWaterMarkPdf(inFile, "上周美国馏分油库存累库95万桶,馏分油表需环比下降(-25.6万桶/日)。本期馏分油产量继续抬升,在供增需减的环比变动下库存持续累库。馏分油供应的增加我们认为可能和进口的油种有关,今年以来美国进口的中重质原油占比不断走高,尤其是5")
 	if err != nil {
@@ -1977,3 +1978,16 @@ func initPdf() {
 
 	_, _ = io.Copy(newPdf, f2)
 }
+
+func AddWaterMarkToImage() {
+	//python3 static/watermarker.py --file 铝年报:25年成本回落后,开启长周期故事20241204.jpg -m 你好我是超长水印我是中国人我爱我的家乡-1244555432 -o newMarked.jpg
+	fileName := "铝年报:25年成本回落后,开启长周期故事20241204.jpg"
+	markStr := "你好我是超长水印我是中国人我爱我的家乡-1244555432"
+	outFileName := "static"
+	font := "static/SimHei.ttf"
+	cmd := exec.Command("python3", "static/watermarker.py", "-f", fileName, "--font-family", font, "-m", markStr, "-o", outFileName)
+	err := cmd.Run()
+	if err != nil {
+		fmt.Println("生成失败,ERR:", err)
+	}
+}

+ 176 - 0
static/watermarker.py

@@ -0,0 +1,176 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import argparse
+import os
+import sys
+import math
+import textwrap
+
+from PIL import Image, ImageFont, ImageDraw, ImageEnhance, ImageChops, ImageOps
+
+
+def add_mark(imagePath, mark, args):
+    '''
+    添加水印,然后保存图片
+    '''
+    im = Image.open(imagePath)
+    im = ImageOps.exif_transpose(im)
+
+    image = mark(im)
+    name = os.path.basename(imagePath)
+    if image:
+        if not os.path.exists(args.out):
+            os.mkdir(args.out)
+
+        new_name = os.path.join(args.out, name)
+        if os.path.splitext(new_name)[1] != '.png':
+            image = image.convert('RGB')
+        image.save(new_name, quality=args.quality)
+
+        print(name + " Success.")
+    else:
+        print(name + " Failed.")
+
+
+def set_opacity(im, opacity):
+    '''
+    设置水印透明度
+    '''
+    assert opacity >= 0 and opacity <= 1
+
+    alpha = im.split()[3]
+    alpha = ImageEnhance.Brightness(alpha).enhance(opacity)
+    im.putalpha(alpha)
+    return im
+
+
+def crop_image(im):
+    '''裁剪图片边缘空白'''
+    bg = Image.new(mode='RGBA', size=im.size)
+    diff = ImageChops.difference(im, bg)
+    del bg
+    bbox = diff.getbbox()
+    if bbox:
+        return im.crop(bbox)
+    return im
+
+
+def gen_mark(args):
+    '''
+    生成mark图片,返回添加水印的函数
+    '''
+    # 字体宽度、高度
+    is_height_crop_float = '.' in args.font_height_crop  # not good but work
+    width = len(args.mark) * args.size
+    if is_height_crop_float:
+        height = round(args.size * float(args.font_height_crop))
+    else:
+        height = int(args.font_height_crop)
+
+    # 创建水印图片(宽度、高度)
+    mark = Image.new(mode='RGBA', size=(width, height))
+
+    # 生成文字
+    draw_table = ImageDraw.Draw(im=mark)
+    draw_table.text(xy=(0, 0),
+                    text=args.mark,
+                    fill=args.color,
+                    font=ImageFont.truetype(args.font_family,
+                                            size=args.size))
+    del draw_table
+
+    # 裁剪空白
+    mark = crop_image(mark)
+
+    # 透明度
+    set_opacity(mark, args.opacity)
+
+    def mark_im(im):
+        ''' 在im图片上添加水印 im为打开的原图'''
+
+        # 计算斜边长度
+        c = int(math.sqrt(im.size[0] * im.size[0] + im.size[1] * im.size[1]))
+
+        # 以斜边长度为宽高创建大图(旋转后大图才足以覆盖原图)
+        mark2 = Image.new(mode='RGBA', size=(c, c))
+
+        # 在大图上生成水印文字,此处mark为上面生成的水印图片
+        y, idx = 0, 0
+        while y < c:
+            # 制造x坐标错位
+            x = -int((mark.size[0] + args.space) * 0.5 * idx)
+            idx = (idx + 1) % 2
+
+            while x < c:
+                # 在该位置粘贴mark水印图片
+                mark2.paste(mark, (x, y))
+                x = x + mark.size[0] + args.space
+            y = y + mark.size[1] + args.space
+
+        # 将大图旋转一定角度
+        mark2 = mark2.rotate(args.angle)
+
+        # 在原图上添加大图水印
+        if im.mode != 'RGBA':
+            im = im.convert('RGBA')
+        im.paste(mark2,  # 大图
+                 (int((im.size[0] - c) / 2), int((im.size[1] - c) / 2)),  # 坐标
+                 mask=mark2.split()[3])
+        del mark2
+        return im
+
+    return mark_im
+
+
+def main():
+    parse = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
+    parse.add_argument("-f", "--file", type=str,
+                       help="image file path or directory")
+    parse.add_argument("-m", "--mark", type=str, help="watermark content")
+    parse.add_argument("-o", "--out", default="./output",
+                       help="image output directory, default is ./output")
+    parse.add_argument("-c", "--color", default="#808080", type=str,
+                       help="text color like '#000000', default is #808080")
+    parse.add_argument("-s", "--space", default=100, type=int,
+                       help="space between watermarks, default is 75")
+    parse.add_argument("-a", "--angle", default=30, type=int,
+                       help="rotate angle of watermarks, default is 30")
+    parse.add_argument("--font-family", default="SimHei.ttf", type=str,
+                       help=textwrap.dedent('''\
+                       font family of text, default is './font/SimHei.ttf'
+                       using font in system just by font file name
+                       for example 'PingFang.ttc', which is default installed on macOS
+                       '''))
+    parse.add_argument("--font-height-crop", default="2.2", type=str,
+                       help=textwrap.dedent('''\
+                       change watermark font height crop
+                       float will be parsed to factor; int will be parsed to value
+                       default is '2.2', meaning 2.2 times font size
+                       this useful with CJK font, because line height may be higher than size
+                       '''))
+    parse.add_argument("--size", default=50, type=int,
+                       help="font size of text, default is 50")
+    parse.add_argument("--opacity", default=0.15, type=float,
+                       help="opacity of watermarks, default is 0.15")
+    parse.add_argument("--quality", default=80, type=int,
+                       help="quality of output images, default is 80")
+
+    args = parse.parse_args()
+
+    if isinstance(args.mark, str) and sys.version_info[0] < 3:
+        args.mark = args.mark.decode("utf-8")
+
+    mark = gen_mark(args)
+
+    if os.path.isdir(args.file):
+        names = os.listdir(args.file)
+        for name in names:
+            image_file = os.path.join(args.file, name)
+            add_mark(image_file, mark, args)
+    else:
+        add_mark(args.file, mark, args)
+
+
+if __name__ == '__main__':
+    main()