精华内容
下载资源
问答
  • 2020-12-04 23:01:12

    前段时间换工作,在BOSS直聘上看到一个有意思的功能,上传docx格式的简历,能够以图片的形式在线预览,并且图片还添加了水印,笔者对此比较感兴趣,就摸索着实现方法。网上逛了一圈,对于docx直接转图片这种转换没有什么有效的信息,不过结合获取的信息,笔者倒是想了一个曲线救国的法子,docx->pdf, pdf->image,通过两步可以最终实现该转换。

    一、环境准备

    首先进行环境准备工作,把需要用到的工具都安装配置好:

    1、安装pandoc

    Pandoc是由John MacFarlane开发的标记语言转换工具,可实现不同标记语言间的格式转换,堪称该领域中的“瑞士军刀”。该工具使用Haskell语言编写,以命令行形式实现与用户的交互,可支持多种操作系统。简而言之,pandoc就是一款转换工具,可以把格式A的文档转换为格式B的文档,就本文的目标来讲,主要用它实现了docx->pdf的转换。

    根据系统类别选择对应的安装包,安装完成后将其安装目录添加到系统路径中,windows版本的安装完成后会自动添加,不用额外设置。

    2、安装miktex

    MikTex是一款基于Tex的排版引擎。TeX 在不同的硬件和操作系统上有不同的实现版本。这就像C语言,在不同的操作系统中有不同的编译系统,例如Linux 下的gcc,Windows 下的Visual C++ 等。有时,一种操作系统里也会有好几种的TeX系统。目前常见的Unix/Linux 下的TeX系统是Texlive,Windows 下则有MiKTeX和fpTeX。CTeX指的是CTeX中文套装的简称,是把MiKTeX和一些常用的相关工具,如GSview,WinEdt 等包装在一起制作的一个简易安装程序,并对其中的中文支持部分进行了配置,使得安装后马上就可以使用中文。

    该排版工具是docx->pdf转换时不可获取的,否则无法实现转换。

    下载地址:https://miktex.org/   根据系统类别选择合适的版本,安装完成后将安装目录添加到系统路径。

    3、安装poppler

    代码实现中引用了一个开源库pdf2image,而这个库又引用了poppler,所以需要安装该环境。Poppler是一个基于xpdf-3.0的用于操作pdf的库,其中poppler-utils是建立在Poppler的库API上的工具集合,用于管理PDF和提取内容,主要工具如下:

    pdfdetach – 从PDF中提取嵌入式文档;

    pdffonts – 列出PDF中使用的字体;

    pdfimages – 从PDF中以原始分辨率提取所有嵌入式图像;

    pdfinfo – 列出PDF的所有信息;

    pdfseparate – 从PDF中提取单个页面;

    pdftocairo – 使用cairo将单页从PDF转换为矢量或位图格式;

    pdftohtml – 将PDF转换为HTML格式的保留格式;

    pdftoppm – 将PDF页面转换为位图;

    pdftops – 将PDF转换为可打印的PS格式;

    pdftotext – 从PDF中提取所有文本;

    pdfunite – 合并几个PDF。

    pdf2image使用了pdftoppm和pdfinfo这两个工具,用来将pdf转换为图片和获取pdf的文档页数,代码稍后会列出。

    下载地址:https://github.com/Belval/pdf2image  根据系统类别选择对应的版本,安装完成后将安装目录下的bin目录添加到系统路径。

    4、字体下载

    用来生成水印时使用,笔者下载的是SimSun宋体,下载地址:https://www.fontke.com/font/10132367/download/,也可以下载其他字体,看个人选择。

    完成上边四步环境就配置好了,笔者的电脑是Windows10,当然以上工具同样支持linux和mac环境,每个工具的官档都标注了支持的系统版本。环境配置好后接下来就是coding环节了,通过程序来实现转换过程的自动化调用,笔者会列出代码的目录结构,并依次说明其用途。

    二、代码实现

    关于实现这部分,笔者使用的开发语言是python36,以下为目录结构:

    1、font目录

    该目录存放的是下载好的字体文件,供代码中引用。

    2、pdf目录

    该目录存放转换之后的pdf文件。

    3、target目录

    该目录存放最终转换后的图片,图片为以时间戳命名的png图片,格式可以指定。

    4、config.py

    配置文件,存放了目录、图片大小、水印等配置,代码如下:

    Python

    import os

    # 根目录

    BASE_DIR = os.path.dirname(__file__)

    # pdf默认输出路径

    DEFAULT_OUTPUT_DIR = os.path.join(BASE_DIR, 'pdf')

    # 最终生成的图片存放在此目录

    TARGET_DIR = os.path.join(BASE_DIR, 'target')

    # 水印字体

    FONT_FILE = os.path.join(BASE_DIR, "font/simsun.ttf")

    # 单张图片的宽高,PIL支持图片的最大宽度1700

    IMAGE_WIDTH = 1700

    IMAGE_HEIGHT = 2200

    # 水印位置-left和top

    WATERMARK_LEFT = 0

    WATERMARK_TOP = 1800

    # 水印图片背景色-白色透明,最后一位表示透明度0~255,0为透明

    BACKGROUND_COLOR = (255, 255, 255, 0)

    #水印字体颜色-红色 60透明度

    FONT_COLOR = (255, 0, 0, 60)

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    importos

    # 根目录

    BASE_DIR=os.path.dirname(__file__)

    # pdf默认输出路径

    DEFAULT_OUTPUT_DIR=os.path.join(BASE_DIR,'pdf')

    # 最终生成的图片存放在此目录

    TARGET_DIR=os.path.join(BASE_DIR,'target')

    # 水印字体

    FONT_FILE=os.path.join(BASE_DIR,"font/simsun.ttf")

    # 单张图片的宽高,PIL支持图片的最大宽度1700

    IMAGE_WIDTH=1700

    IMAGE_HEIGHT=2200

    # 水印位置-left和top

    WATERMARK_LEFT=0

    WATERMARK_TOP=1800

    # 水印图片背景色-白色透明,最后一位表示透明度0~255,0为透明

    BACKGROUND_COLOR=(255,255,255,0)

    #水印字体颜色-红色 60透明度

    FONT_COLOR=(255,0,0,60)

    5、doc2pdf.py

    该模块封装了pandoc命令行工具的调用,实现了docx文档到pdf的转换过程

    Python

    import os

    import uuid

    from subprocess import Popen, PIPE

    def _load_doc(doc):

    doc = str(doc)

    if not os.path.exists(doc):

    raise FileNotFoundError("file {} not found".format(doc))

    _, doc_name = os.path.split(doc)

    if not doc_name.endswith('.docx'):

    raise TypeError("Only support word doc with suffix '.docx'")

    return doc

    def _build_command(doc_path, output_dir, pdf_name=None, pdf_engine=None):

    args = ['pandoc', '--pdf-engine=xelatex']

    # args = ['pandoc', '--pdf-engine=lualatex']

    if pdf_engine is not None:

    # MikTex包含了两种pandoc支持的Tex

    if pdf_engine not in ("xelatex", "lualatex"):

    raise ValueError("not supported pdf-engine: {}".format(pdf_engine))

    else:

    args[1] = '--pdf-engine={}'.format(pdf_engine)

    if pdf_name is None:

    pdf_name = str(uuid.uuid4()) + '.pdf'

    if not os.path.isdir(output_dir):

    raise NotADirectoryError("{} is not a existed directory".format(output_dir))

    pdf_path = os.path.join(output_dir, pdf_name)

    args.append('-o')

    args.append(pdf_path)

    args.append(doc_path)

    # 设置字体避免中文乱码无法输出问题,SimSun是宋体, MicrosoftYaHei是微软雅黑

    args.append('-V')

    args.append('mainfont="MicrosoftYaHei"')

    # args.append('-V')

    # args.append('margin-left=0in')

    return args, pdf_path

    def doc2pdf(source, pdf_path):

    doc_path = _load_doc(source)

    cmd, output_pdf = _build_command(doc_path, pdf_path)

    # run cmd

    print("doc to pdf, converting...")

    Popen(cmd, stderr=PIPE, stdout=PIPE).communicate()

    print("job done!")

    return output_pdf

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    importos

    importuuid

    fromsubprocessimportPopen,PIPE

    def_load_doc(doc):

    doc=str(doc)

    ifnotos.path.exists(doc):

    raiseFileNotFoundError("file {} not found".format(doc))

    _,doc_name=os.path.split(doc)

    ifnotdoc_name.endswith('.docx'):

    raiseTypeError("Only support word doc with suffix '.docx'")

    returndoc

    def_build_command(doc_path,output_dir,pdf_name=None,pdf_engine=None):

    args=['pandoc','--pdf-engine=xelatex']

    # args = ['pandoc', '--pdf-engine=lualatex']

    ifpdf_engineisnotNone:

    # MikTex包含了两种pandoc支持的Tex

    ifpdf_enginenotin("xelatex","lualatex"):

    raiseValueError("not supported pdf-engine: {}".format(pdf_engine))

    else:

    args[1]='--pdf-engine={}'.format(pdf_engine)

    ifpdf_nameisNone:

    pdf_name=str(uuid.uuid4())+'.pdf'

    ifnotos.path.isdir(output_dir):

    raiseNotADirectoryError("{} is not a existed directory".format(output_dir))

    pdf_path=os.path.join(output_dir,pdf_name)

    args.append('-o')

    args.append(pdf_path)

    args.append(doc_path)

    # 设置字体避免中文乱码无法输出问题,SimSun是宋体, MicrosoftYaHei是微软雅黑

    args.append('-V')

    args.append('mainfont="MicrosoftYaHei"')

    # args.append('-V')

    # args.append('margin-left=0in')

    returnargs,pdf_path

    defdoc2pdf(source,pdf_path):

    doc_path=_load_doc(source)

    cmd,output_pdf=_build_command(doc_path,pdf_path)

    # run cmd

    print("doc to pdf, converting...")

    Popen(cmd,stderr=PIPE,stdout=PIPE).communicate()

    print("job done!")

    returnoutput_pdf

    6、pdf2image.py

    一个开源的python库,只包含了一个文件,笔者直接复制过来使用的。主要封装了poppler的命令行调用,实现pdf到图片的转换。

    Python

    """

    pdf2image is a light wrapper for the poppler-utils tools that can convert your

    PDFs into Pillow images.

    """

    import os

    import re

    import tempfile

    import uuid

    from io import BytesIO

    from subprocess import Popen, PIPE

    from PIL import Image

    def convert_from_path(pdf_path, dpi=200, output_folder=None, first_page=None, last_page=None, fmt='ppm', thread_count=1, userpw=None):

    """

    Description: Convert PDF to Image will throw whenever one of the condition is reached

    Parameters:

    pdf_path -> Path to the PDF that you want to convert

    dpi -> Image quality in DPI (default 200)

    output_folder -> Write the resulting images to a folder (instead of directly in memory)

    first_page -> First page to process

    last_page -> Last page to process before stopping

    fmt -> Output image format

    thread_count -> How many threads we are allowed to spawn for processing

    userpw -> PDF's password

    """

    page_count = __page_count(pdf_path, userpw)

    if thread_count < 1:

    thread_count = 1

    if first_page is None:

    first_page = 1

    if last_page is None or last_page > page_count:

    last_page = page_count

    # Recalculate page count based on first and last page

    page_count = last_page - first_page + 1

    if thread_count > page_count:

    thread_count = page_count

    reminder = page_count % thread_count

    current_page = first_page

    processes = []

    for _ in range(thread_count):

    # A unique identifier for our files if the directory is not empty

    uid = str(uuid.uuid4())

    # Get the number of pages the thread will be processing

    thread_page_count = page_count // thread_count + int(reminder > 0)

    # Build the command accordingly

    args, parse_buffer_func = __build_command(['pdftoppm', '-r', str(dpi), pdf_path], output_folder, current_page, current_page + thread_page_count - 1, fmt, uid, userpw)

    # Update page values

    current_page = current_page + thread_page_count

    reminder -= int(reminder > 0)

    # Spawn the process and save its uuid

    processes.append((uid, Popen(args, stdout=PIPE, stderr=PIPE)))

    images = []

    for uid, proc in processes:

    data, _ = proc.communicate()

    if output_folder is not None:

    images += __load_from_output_folder(output_folder, uid)

    else:

    images += parse_buffer_func(data)

    return images

    def convert_from_bytes(pdf_file, dpi=200, output_folder=None, first_page=None, last_page=None, fmt='ppm', thread_count=1, userpw=None):

    """

    Description: Convert PDF to Image will throw whenever one of the condition is reached

    Parameters:

    pdf_file -> Bytes representing the PDF file

    dpi -> Image quality in DPI

    output_folder -> Write the resulting images to a folder (instead of directly in memory)

    first_page -> First page to process

    last_page -> Last page to process before stopping

    fmt -> Output image format

    thread_count -> How many threads we are allowed to spawn for processing

    userpw -> PDF's password

    """

    with tempfile.NamedTemporaryFile('wb') as f:

    f.write(pdf_file)

    f.flush()

    return convert_from_path(f.name, dpi=dpi, output_folder=output_folder, first_page=first_page, last_page=last_page, fmt=fmt, thread_count=thread_count, userpw=userpw)

    def pdf_page_count(pdf, password=None):

    return __page_count(pdf, password)

    def __build_command(args, output_folder, first_page, last_page, fmt, uid, userpw):

    if first_page is not None:

    args.extend(['-f', str(first_page)])

    if last_page is not None:

    args.extend(['-l', str(last_page)])

    parsed_format, parse_buffer_func = __parse_format(fmt)

    if parsed_format != 'ppm':

    args.append('-' + parsed_format)

    if output_folder is not None:

    args.append(os.path.join(output_folder, uid))

    if userpw is not None:

    args.extend(['-upw', userpw])

    return args, parse_buffer_func

    def __parse_format(fmt):

    if fmt[0] == '.':

    fmt = fmt[1:]

    if fmt == 'jpeg' or fmt == 'jpg':

    return 'jpeg', __parse_buffer_to_jpeg

    if fmt == 'png':

    return 'png', __parse_buffer_to_png

    # Unable to parse the format so we'll use the default

    return 'ppm', __parse_buffer_to_ppm

    def __parse_buffer_to_ppm(data):

    images = []

    index = 0

    while index < len(data):

    code, size, rgb = tuple(data[index:index + 40].split(b'\n')[0:3])

    size_x, size_y = tuple(size.split(b' '))

    file_size = len(code) + len(size) + len(rgb) + 3 + int(size_x) * int(size_y) * 3

    images.append(Image.open(BytesIO(data[index:index + file_size])))

    index += file_size

    return images

    def __parse_buffer_to_jpeg(data):

    return [

    Image.open(BytesIO(image_data + b'\xff\xd9'))

    for image_data in data.split(b'\xff\xd9')[:-1] # Last element is obviously empty

    ]

    def __parse_buffer_to_png(data):

    images = []

    index = 0

    while index < len(data):

    file_size = data[index:].index(b'IEND') + 8 # 4 bytes for IEND + 4 bytes for CRC

    images.append(Image.open(BytesIO(data[index:index+file_size])))

    index += file_size

    return images

    def __page_count(pdf_path, userpw=None):

    try:

    if userpw is not None:

    proc = Popen(["pdfinfo", pdf_path, '-upw', userpw], stdout=PIPE, stderr=PIPE)

    else:

    proc = Popen(["pdfinfo", pdf_path], stdout=PIPE, stderr=PIPE)

    out, err = proc.communicate()

    except:

    raise Exception('Unable to get page count. Is poppler installed and in PATH?')

    try:

    # This will throw if we are unable to get page count

    return int(re.search(r'Pages:\s+(\d+)', out.decode("utf8", "ignore")).group(1))

    except:

    raise Exception('Unable to get page count. %s' % err.decode("utf8", "ignore"))

    def __load_from_output_folder(output_folder, uid):

    return [Image.open(os.path.join(output_folder, f)) for f in sorted(os.listdir(output_folder)) if uid in f]

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    69

    70

    71

    72

    73

    74

    75

    76

    77

    78

    79

    80

    81

    82

    83

    84

    85

    86

    87

    88

    89

    90

    91

    92

    93

    94

    95

    96

    97

    98

    99

    100

    101

    102

    103

    104

    105

    106

    107

    108

    109

    110

    111

    112

    113

    114

    115

    116

    117

    118

    119

    120

    121

    122

    123

    124

    125

    126

    127

    128

    129

    130

    131

    132

    133

    134

    135

    136

    137

    138

    139

    140

    141

    142

    143

    144

    145

    146

    147

    148

    149

    150

    151

    152

    153

    154

    155

    156

    157

    158

    159

    160

    161

    162

    163

    164

    165

    166

    167

    168

    169

    170

    171

    172

    173

    174

    175

    176

    """

    pdf2image is a light wrapper for the poppler-utils tools that can convert your

    PDFs into Pillow images.

    """

    importos

    importre

    importtempfile

    importuuid

    fromioimportBytesIO

    fromsubprocessimportPopen,PIPE

    fromPILimportImage

    defconvert_from_path(pdf_path,dpi=200,output_folder=None,first_page=None,last_page=None,fmt='ppm',thread_count=1,userpw=None):

    """

    Description: Convert PDF to Image will throw whenever one of the condition is reached

    Parameters:

    pdf_path -> Path to the PDF that you want to convert

    dpi -> Image quality in DPI (default 200)

    output_folder -> Write the resulting images to a folder (instead of directly in memory)

    first_page -> First page to process

    last_page -> Last page to process before stopping

    fmt -> Output image format

    thread_count -> How many threads we are allowed to spawn for processing

    userpw -> PDF's password

    """

    page_count=__page_count(pdf_path,userpw)

    ifthread_count<1:

    thread_count=1

    iffirst_pageisNone:

    first_page=1

    iflast_pageisNoneorlast_page>page_count:

    last_page=page_count

    # Recalculate page count based on first and last page

    page_count=last_page-first_page+1

    ifthread_count>page_count:

    thread_count=page_count

    reminder=page_count%thread_count

    current_page=first_page

    processes=[]

    for_inrange(thread_count):

    # A unique identifier for our files if the directory is not empty

    uid=str(uuid.uuid4())

    # Get the number of pages the thread will be processing

    thread_page_count=page_count//thread_count+int(reminder>0)

    # Build the command accordingly

    args,parse_buffer_func=__build_command(['pdftoppm','-r',str(dpi),pdf_path],output_folder,current_page,current_page+thread_page_count-1,fmt,uid,userpw)

    # Update page values

    current_page=current_page+thread_page_count

    reminder-=int(reminder>0)

    # Spawn the process and save its uuid

    processes.append((uid,Popen(args,stdout=PIPE,stderr=PIPE)))

    images=[]

    foruid,procinprocesses:

    data,_=proc.communicate()

    ifoutput_folderisnotNone:

    images+=__load_from_output_folder(output_folder,uid)

    else:

    images+=parse_buffer_func(data)

    returnimages

    defconvert_from_bytes(pdf_file,dpi=200,output_folder=None,first_page=None,last_page=None,fmt='ppm',thread_count=1,userpw=None):

    """

    Description: Convert PDF to Image will throw whenever one of the condition is reached

    Parameters:

    pdf_file -> Bytes representing the PDF file

    dpi -> Image quality in DPI

    output_folder -> Write the resulting images to a folder (instead of directly in memory)

    first_page -> First page to process

    last_page -> Last page to process before stopping

    fmt -> Output image format

    thread_count -> How many threads we are allowed to spawn for processing

    userpw -> PDF's password

    """

    withtempfile.NamedTemporaryFile('wb')asf:

    f.write(pdf_file)

    f.flush()

    returnconvert_from_path(f.name,dpi=dpi,output_folder=output_folder,first_page=first_page,last_page=last_page,fmt=fmt,thread_count=thread_count,userpw=userpw)

    defpdf_page_count(pdf,password=None):

    return__page_count(pdf,password)

    def__build_command(args,output_folder,first_page,last_page,fmt,uid,userpw):

    iffirst_pageisnotNone:

    args.extend(['-f',str(first_page)])

    iflast_pageisnotNone:

    args.extend(['-l',str(last_page)])

    parsed_format,parse_buffer_func=__parse_format(fmt)

    ifparsed_format!='ppm':

    args.append('-'+parsed_format)

    ifoutput_folderisnotNone:

    args.append(os.path.join(output_folder,uid))

    ifuserpwisnotNone:

    args.extend(['-upw',userpw])

    returnargs,parse_buffer_func

    def__parse_format(fmt):

    iffmt[0]=='.':

    fmt=fmt[1:]

    iffmt=='jpeg'orfmt=='jpg':

    return'jpeg',__parse_buffer_to_jpeg

    iffmt=='png':

    return'png',__parse_buffer_to_png

    # Unable to parse the format so we'll use the default

    return'ppm',__parse_buffer_to_ppm

    def__parse_buffer_to_ppm(data):

    images=[]

    index=0

    whileindex

    code,size,rgb=tuple(data[index:index+40].split(b'\n')[0:3])

    size_x,size_y=tuple(size.split(b' '))

    file_size=len(code)+len(size)+len(rgb)+3+int(size_x)*int(size_y)*3

    images.append(Image.open(BytesIO(data[index:index+file_size])))

    index+=file_size

    returnimages

    def__parse_buffer_to_jpeg(data):

    return[

    Image.open(BytesIO(image_data+b'\xff\xd9'))

    forimage_dataindata.split(b'\xff\xd9')[:-1]# Last element is obviously empty

    ]

    def__parse_buffer_to_png(data):

    images=[]

    index=0

    whileindex

    file_size=data[index:].index(b'IEND')+8# 4 bytes for IEND + 4 bytes for CRC

    images.append(Image.open(BytesIO(data[index:index+file_size])))

    index+=file_size

    returnimages

    def__page_count(pdf_path,userpw=None):

    try:

    ifuserpwisnotNone:

    proc=Popen(["pdfinfo",pdf_path,'-upw',userpw],stdout=PIPE,stderr=PIPE)

    else:

    proc=Popen(["pdfinfo",pdf_path],stdout=PIPE,stderr=PIPE)

    out,err=proc.communicate()

    except:

    raiseException('Unable to get page count. Is poppler installed and in PATH?')

    try:

    # This will throw if we are unable to get page count

    returnint(re.search(r'Pages:\s+(\d+)',out.decode("utf8","ignore")).group(1))

    except:

    raiseException('Unable to get page count. %s'%err.decode("utf8","ignore"))

    def__load_from_output_folder(output_folder,uid):

    return[Image.open(os.path.join(output_folder,f))forfinsorted(os.listdir(output_folder))ifuidinf]

    7、main.py

    入口主程序,传入doc文档,得到png图片^_^

    Python

    import os

    import time

    from PIL import Image

    from PIL import ImageFont

    from PIL import ImageDraw

    from config import *

    from pdf2image import convert_from_path, pdf_page_count

    from doc2pdf import doc2pdf

    def doc2image(doc, fmt='png', output_dir=None, watermark=None, fpage=None, lpage=None):

    if output_dir is None:

    output_dir = TARGET_DIR

    target_name = os.path.join(output_dir, "{}.{}".format(int(time.time()), fmt))

    temp_pdf = doc2pdf(doc, pdf_path=DEFAULT_OUTPUT_DIR)

    if fpage is None:

    fpage = 1

    if lpage is not None:

    page_count = lpage - fpage + 1

    else:

    page_count = pdf_page_count(temp_pdf)

    print("pdf to image, converting...")

    to_image = _convert_pdf_to_image(temp_pdf, page_count, fmt, fpage, lpage)

    if watermark is not None:

    watermark_image = _make_watermark_image(to_image.size, watermark, page_count)

    # 合并内容图片和水印图片

    out = Image.alpha_composite(to_image, watermark_image)

    # out.show()

    # 转换为RGB模式才可保存为图片

    out.convert("RGB").save(target_name)

    else:

    to_image.save(target_name)

    print("job done!")

    def _convert_pdf_to_image(pdf, page_count, fmt, f, l, save=False):

    '''

    params:

    pdf: 待转换的pdf文件路径

    page_count: 要转换的页数

    fmt: 转换的图片格式

    f: 要转换的开始页数

    l: 结束页数

    save: 是否保留pdf文件,默认不保留

    '''

    # 根据页数转换为相应数量的图片

    image_list = convert_from_path(pdf, fmt=fmt, first_page=f, last_page=l)

    target_name = os.path.join(TARGET_DIR, "{}.{}".format(int(time.time()), fmt))

    to_image = Image.new('RGBA', (IMAGE_WIDTH, page_count * IMAGE_HEIGHT))

    for i, image in enumerate(image_list):

    # 计算高度,拼合单张图片到一整张图片上

    loc = (0, i * IMAGE_HEIGHT)

    to_image.paste(image, loc)

    if not save:

    try:

    os.remove(pdf)

    except Exception as e:

    print("fail to remove pdf, please check and remove it manually")

    return to_image

    def _make_watermark_image(image_size, watermark, count=1):

    '''

    生成水印图片

    params:

    image_size: 水印图片大小,与底板图片大小一致

    watermark: 水印文本

    count: 水印数量, 与内容页数保持一致

    '''

    fnt = ImageFont.truetype(font=FONT_FILE, size=80)

    watermark_image = Image.new('RGBA', image_size, color=BACKGROUND_COLOR)

    draw = ImageDraw.Draw(watermark_image)

    for i in range(1, count+1):

    draw.multiline_text((WATERMARK_LEFT, WATERMARK_TOP * i), watermark, font=fnt, fill=FONT_COLOR)

    return watermark_image

    if __name__ == '__main__':

    txt = "玩点coding https://vdcoding.com"

    doc = "resume.docx"

    doc2image(doc, watermark=txt)

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    69

    70

    71

    72

    73

    74

    75

    76

    77

    78

    79

    80

    81

    82

    83

    importos

    importtime

    fromPILimportImage

    fromPILimportImageFont

    fromPILimportImageDraw

    fromconfigimport*

    frompdf2imageimportconvert_from_path,pdf_page_count

    fromdoc2pdfimportdoc2pdf

    defdoc2image(doc,fmt='png',output_dir=None,watermark=None,fpage=None,lpage=None):

    ifoutput_dirisNone:

    output_dir=TARGET_DIR

    target_name=os.path.join(output_dir,"{}.{}".format(int(time.time()),fmt))

    temp_pdf=doc2pdf(doc,pdf_path=DEFAULT_OUTPUT_DIR)

    iffpageisNone:

    fpage=1

    iflpageisnotNone:

    page_count=lpage-fpage+1

    else:

    page_count=pdf_page_count(temp_pdf)

    print("pdf to image, converting...")

    to_image=_convert_pdf_to_image(temp_pdf,page_count,fmt,fpage,lpage)

    ifwatermarkisnotNone:

    watermark_image=_make_watermark_image(to_image.size,watermark,page_count)

    # 合并内容图片和水印图片

    out=Image.alpha_composite(to_image,watermark_image)

    # out.show()

    # 转换为RGB模式才可保存为图片

    out.convert("RGB").save(target_name)

    else:

    to_image.save(target_name)

    print("job done!")

    def_convert_pdf_to_image(pdf,page_count,fmt,f,l,save=False):

    '''

    params:

    pdf: 待转换的pdf文件路径

    page_count: 要转换的页数

    fmt: 转换的图片格式

    f: 要转换的开始页数

    l: 结束页数

    save: 是否保留pdf文件,默认不保留

    '''

    # 根据页数转换为相应数量的图片

    image_list=convert_from_path(pdf,fmt=fmt,first_page=f,last_page=l)

    target_name=os.path.join(TARGET_DIR,"{}.{}".format(int(time.time()),fmt))

    to_image=Image.new('RGBA',(IMAGE_WIDTH,page_count*IMAGE_HEIGHT))

    fori,imageinenumerate(image_list):

    # 计算高度,拼合单张图片到一整张图片上

    loc=(0,i*IMAGE_HEIGHT)

    to_image.paste(image,loc)

    ifnotsave:

    try:

    os.remove(pdf)

    exceptExceptionase:

    print("fail to remove pdf, please check and remove it manually")

    returnto_image

    def_make_watermark_image(image_size,watermark,count=1):

    '''

    生成水印图片

    params:

    image_size: 水印图片大小,与底板图片大小一致

    watermark: 水印文本

    count: 水印数量, 与内容页数保持一致

    '''

    fnt=ImageFont.truetype(font=FONT_FILE,size=80)

    watermark_image=Image.new('RGBA',image_size,color=BACKGROUND_COLOR)

    draw=ImageDraw.Draw(watermark_image)

    foriinrange(1,count+1):

    draw.multiline_text((WATERMARK_LEFT,WATERMARK_TOP*i),watermark,font=fnt,fill=FONT_COLOR)

    returnwatermark_image

    if__name__=='__main__':

    txt="玩点coding https://vdcoding.com"

    doc="resume.docx"

    doc2image(doc,watermark=txt)

    三、待完善的地方

    笔者从网上下载了份docx格式的简历模板,通过上边的程序转换后得到的图片如下:

    从图中可以看到个人信息部分的样式跑偏了,这部分是在docx->pdf过程中的排版引擎决定的,所以想要获得完美的图片,先要好好研究下排版引擎的使用,排版引擎可以加载多种扩展包,用来支持不同的排版格式。笔者只是兴趣使然,在短时间内实现了docx到图片的转换,没有深入研究排版引擎部分。关于这种转换笔者能力有限,只能以这种繁琐的方式实现,不过笔者倒是很好奇BOSS直聘是如何实现的,如果有机会真心希望交流一下。

    更多相关内容
  • 1、poi版本3.13 2、可进行表格替换。复制、图片导出 3、可直接运行
  • 本代码实现使用Java程序读取word文档成网页,将word文档按原样在网页输出。项目编码UTF-8,文件编码也是utf8,再不要说乱码这种骚话了,选择utf8加载项目就不会乱码
  • simulink选用示波器直接输出图像更直观简单易操作易修改 2. 全网simulink示波器输出图像版本低方法老旧已经不能实现 3. simulink选用示波器直接输出图像如何保证清晰度 4. simulink选用示波器直接输出图像如何...
  • 1、Word转换Pdf,程序很多,但转换后的Pdf,还可以复制,虽可以加密禁止复制,但市场上太多的Pdf,还可以把Pdf转换Word等其他格式,很容易被别人利用和剽窃,如何彻底的自己的Word文档,可以被人浏览,查看,而不被...
  • 解决WORD输出Html图片Jpg变模糊的问题

    千次阅读 2019-11-10 11:06:32
    最近用WORD输出HTML时碰到个小问题,就是输出的图片会变得有点模糊。比如这个文档页面: 将它另存筛选过的HTML: 警告直接忽略: 然后用浏览器打开,会发现两个图的质量都有下降,有变模糊的感觉(区别不...

    最近用WORD输出HTML时碰到个小问题,就是输出的图片会变得有点模糊。比如这个文档页面:

    将它另存为筛选过的HTML:

    警告直接忽略:

    然后用浏览器打开,会发现两个图的质量都有下降,有变模糊的感觉(区别不明显,但确实有区别):

    右键在新标签页打开图片,会发现用的是JPG格式:

    打开文件目录看看,确实全是JPG:

    JPG是有损压缩,自然质量会下降了。

    不过WORD其实是有PNG格式的,如果另存时,不选择“筛选过的网页”,而是直接选择“网页”:

    出来的结果——,不好意思,也是糊的:

    还是用了JPG,但我打开文件夹发现,它其实把PNG也存了:

    虽然存了PNG,但它就是不用,为什么呢?

    研究了半天,后来发现,其实WORD在输出HTML里,有个使用PNG的选项,在那个WEB选项里:

     

    就是那个“允许将PNG作为图形格式”了,默认是没勾上的,我们勾上试试:

    勾上后上面的IE4会变成IE6,估计是IE4不支持PNG吧,无所谓,反正现在也没有人用IE4了。

    保存打开一看,第一个图是变成PNG了,但第二个图还是JPG:

    这又是为什么呢?经过一番试验,原来,只有百分百大小显示的原图才会以PNG输出。这个难不倒我,写段脚本把全部图重置一次就好了。于是录了个宏,发现重置是reset方法,上网查了下相关遍历shape的脚本,然后开干。

    在WORD中打开文档,按Alt+F11进入VB界面,右键插入用户窗体:

    放一个大按钮上去:

    双击按钮,输入以下脚本(我的图片是嵌入型的,所以我只遍历InlineShapes):

    Private Sub CommandButton1_Click()
    
        For Each iShape In ActiveDocument.InlineShapes
            iShape.Reset
        Next iShape
    
    End Sub
    

    运行看看效果:

    很奇怪,图片大小确实有变化,但并没有如我想像的复位,而是变成了另一种拉伸状态。多点几次,它还会继续变,反正,就是不复位。

    继续折腾,经过一番试验,我发现,只要在复位前,把大小先改一下,比如改成3x3cm,再复位就能成功。最终脚本修改如下:

    Private Sub CommandButton1_Click()
    
        For Each iShape In ActiveDocument.InlineShapes
            iShape.Height = 3 * 28.35
            iShape.Width = 3 * 28.35
            iShape.Reset
        Next iShape
    
    End Sub
    

    效果如下:

    看上去挺好,这时再输出HTML:

    满怀希望打开一看,我靠,它居然全是JPG:

    怎么不按套路出牌呢?人与人之间的信任呢?

    继续折腾吧。经过一番研究,最终发现,将DOC转存为DOCX,再执行重置脚本,再转存HTML设置PNG格式,出来的就是PNG了:

    我也不知道为什么会这样,反正,现实就是这么残酷,也许,是要逼你们升级DOCX吧:

    总算达到目的了。总结就3点:

    1.先保存为DOCX格式

    2.写VB脚本,遍历所有图片,先缩小再复位

    3.转存HTML时,在WEB选项里设置PNG格式

    注意:我只对自己的电脑负责,其他人机器上是否行得通我没验证过的,照此操作出不来结果不要怪我哈。

    展开全文
  • mongodb的应用之用python...文档存储一般用类似json的格式存储,存储的内容是文档型的。这样也就有机会对某些字段建立索引,实现关系数据库的某些功能。 MongoDB 旨在WEB应用提供可扩展的高性能数据存储解决方案。
  • 本资源一个无需office环境,使用开源库NPOI操作word、excel的样例程序,使用C#语言。内含NPOI库,可直接运行。在vs2019中测试通过。 程序实现的功能:  读取excel表格中的数据,  将数据转换成datatable,  ...
  • 该软件可将指定文件夹及子文件夹下所有的Word文件(支持.doc和.docx格式)全部转换成PDF或者图片(png、jpg或者tiff格式),生成的PDF或者图片文件保存在“输出文件”文件夹中。详见...
  • 概要:「我的ABC软件工具箱」提供了强大的图片转为文档的功能,支持将图片转为 Word 、Excel 、PPT 、PDF 等格式,且支持 jpg、jpeg、png、gif、bmp、tif、svg、ico、icns、webp 等常见的图片格式。转换效率高,操作...

    概要:「我的ABC软件工具箱」提供了强大的图片转为文档的功能,支持将图片转为 Word 、Excel 、PPT 、PDF 等格式,且支持 jpg、jpeg、png、gif、bmp、tif、svg、ico、icns、webp 等常见的图片格式。转换效率高,操作流程简单!

    在之前的文章中,我们介绍过将 Word 、Excel 、PPT 、PDF 等格式的文档转为图片,也介绍过将一种格式的图片转为另一种格式的图片。今天给大家介绍使用办公软件「我的ABC软件工具箱」批量将图片格式转为Word 、Excel 、PPT 、PDF 等格式。

    打开「我的ABC软件工具箱」,左侧面板选择【格式转换】,右侧就能看到【图片转换为文档】的按钮!

    点击菜单按钮,会进入到选择图片的页面。

    注意界面上的提示:此功能只是转换文件的格式,并不是图片文字识别!

    在这个页面我们可以单击添加文件按钮,选择需要进行批量转换为文档的图片,可以同时选择 jpg、jpeg、png、gif、bmp、tif、svg、ico、icns、webp 等多种格式!

    这里分别选择了 jpg、png、bmp类型的图片,确认无误后我们就可以点击下一步,进入到选项设置的页面。

    在这个页面,我们可选择一个需要转换的目标格式。确认无误后我们就可以点击下一步,进入到设置输出目录的页面。

    在这个页面,我们可以设置文件存储的位置。设置好并确认无误后,继续点击下一步,「我的ABC软件工具箱」就开始进行图片转为 Word 文档了。

    一会儿的功夫,批量图片转为文档的操作就完成了。需要注意的是,这里是每一张图片都会被转为一个独立的文档!有没有觉得整个操作特别简单呢?

    展开全文
  • Word转JPG转换器拥有输出图片大小设置的功能,您可以轻松的通过设置DPI数值(例如200,300,500)来获得您想要的图片尺寸。除了Doc和Docx格式Word转JPG转换器也支持将富文本RTF格式,HTML和HTM网页格式,以及开放...
  • php导出生成word的方法

    2020-12-19 02:22:39
    (3)点击下载后,(如果是图片的话,在保存为word时要使用绝对路径,这样才可以在保存的word中正常显示) (4)关闭缓存输出 Word_con.php 预览要导出的html文件 <?php if(@$_GET[id]!='') { include('word_...
  • 该软件可将指定文件夹下所有的Word文件(支持.doc和.docx格式)全部转换成PDF或者图片(png、jpg或者bmp等格式),生成的PDF或者图片文件保存在“输出文件”文件夹中。详见文章...
  • 所需软件:inkscape 写论文需要在论文里插入无损的图片,之前试过直接插入pdf,效果...解决方法就是用svg文件在inkscape中导出emf文件,这样图片颜色就不会变,而且插入word导出pdf后不会糊。 其实长这样子 ...

    所需软件:inkscape


    写论文需要在论文里插入无损的图片,之前试过直接插入pdf,效果很差,直接插入过svg,在word上是无论放多大都是清晰的,但是导出为pdf后文档里就超级糊。

    解决方法就是在inkscape中导出为emf文件,插入word导出为pdf后不会糊。

    导入文件后,左上角菜单栏里的文件中点击另存为
    在这里插入图片描述
    选择生成emf文件
    在这里插入图片描述
    点击OK就可以生成
    在这里插入图片描述
    然后插入word中可以看到放大依然很清晰(刚刚那张图本来就是糊的,放大还是糊的,所以用了另一张)
    在这里插入图片描述
    导出为pdf依旧很清晰。

    建议是从pdf或者svg转成emf,这样文件不会很大,如果png转emf文件会比上述转换要大很多。

    但是有一个问题是inkscape把颜色比较淡的图的pdf转换成emf时会改变颜色,好像是因为CMYK的原因,但是没找到入口修改,所以对于这种图片,我导出svg之后会用Visio打开再转成emf文件,不过导出pdf后还是有点糊的,凑合用用吧。
    在这里插入图片描述
    其实长这样子
    在这里插入图片描述


    恭喜梁部长竞标成功嘻嘻
    在这里插入图片描述

    展开全文
  • MATLAB图形输出word

    千次阅读 2021-04-18 16:22:13
    强大的计算功能与图形功能相结合MATLAB在科学技术和教学方面的应用提供了更加广阔的天地。下面着重介绍二维图形的画法,对三维图形只作简单叙述。5.1二维图形的绘制5.1.1基本形式二维图形的绘制是MATLAB语言图形...
  • 有时候我们需要将每一页的Word文档变成图片形式的文件进行保存和传输,以防止其他人修改文档的内容,比如我们在进行项目申报、报表申报时,就必须要提交图片格式的文件,这时候则必须将编辑好的Word文档转为图片。...
  • 1、 Word转换Pdf,程序很多,但转换后的Pdf,还可以复制,虽可以加密禁止复制,但市场上太多的Pdf,还可以把Pdf转换Word等其他格式,很容易被别人利用和剽窃,如何彻底的自己的Word文档,可以被人浏览,查看,而不...
  • 工作或生活中,有时需要把word转成图片文件(如 jpg格式),可以试一试以下几种方法。1、截屏具体方法参见《截图工具大比拼,哪一款是你的最爱?》,另有大神指出,sogou拼音输入法也可以截屏。2、Word导入具体分三步...
  • C#输出Word文档

    2013-12-23 09:25:19
    C#按指定格式输出Word表格文档,新建word,插入文字、图片、图表等
  • VB源码,字符处理,仿Word VB仿Word文字编辑程序,相对于Word,本程序实现的功能还不算太多,但是比记事本更高级一些,它可以编辑文字格式,比如设置字体、颜色,对齐方式,统计文字数量等,另外可以插入图片和表格...
  • WORD文档填写器是按照WORD文档书签所指定的数据库数据(及图片)按格式填写到WORD文档中的程序体。可在线编辑,提取指定位置文档数据,并防篡改等。主要用于各种信息管理系统中报表或格式文档的自动制作及生成。 可...
  • php如何把word图片

    千次阅读 2021-03-23 21:01:52
    php把word图片的方法:首先给服务器安装...linux,centos,php,word图片方法(无格式错乱,乱码等问题)刚开始的时候是客户的活儿,真的是没有想到,被这样一个方法给卡住了,真是醉了,经过漫长的一周,终于搞...
  • 如何精确控制Origin输出Word图片格式 及简便绘制相同格式的图片 相比于Excel图形的粗糙、Matlab的专业,Origin兼得了图形美观和易于操作的优点。关于Origin本身的设置帖子很多了,但是如何精确控制Origin输出...
  • 最近在写项目中遇到一个问题,是需要将一个word转为图片 展示到前端,在网上搜索好久,苦得一法,简单 高效的转化图片。 1.首先下载aspose-words-15.8.0-jdk16.jar包 在我的网盘里 我已无私贡献 链接:...
  • 具体需求是这样的,源文件有大量,需要将源文件内容格式和样式按指定的目标文件格式样式输出,如果用java实现的话,用什么方法和工具实现比较好呢?源文件图![图片说明]...
  • 可以将word文档格式转换成pdf格式,只需打开word文档,文件菜单选择pdf输出
  • 输出也是流而不是文件,不依赖于任何输出工具。此模块应适用于支持Node.js 0.10或更高版本的任何环境,包括Linux,OSX和Windows。 2, textract 文本提取节点模块。 3, pdf2json 是一个节点。js模块解析和转换PDF从二...
  • 本软件可将指定文件夹(包含其子文件夹)下所有的Word文件(支持.doc和.docx格式)全部转换成PDF(图片清晰),生成的PDF保存在“输出文件”文件夹中......详见...
  • import matplotlib.pyplot as plt x=[1,2,3,4,5] y=[2.4,8.2,9.3,1.3,2.0] plt.scatter(x,y) plt.savefig(fname="name.svg",format="svg") plt.show()
  • 如何把用Word文档转换成PNG图片

    千次阅读 2022-02-20 21:14:59
    一、把word转成pdf文档: 1. 打开word,选择 File >...2. 将 word 文件另存pdf,并勾选: 二、把pdf转换成png图片: 1. 用Photoshop打开pdf文件,并进行设置: 2. 把pdf另存png。 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 36,844
精华内容 14,737
关键字:

word输出为图片格式