我正在开发一个项目,需要我在图像周围创建一条剪切线,但在任何 RIP 程序(例如 Versaworks 或 Flexi)上将其注册为实际剪切线时遇到困难。
我尝试了很多不同的方法python 库可以帮助解决这个问题,但我无法让它工作。我希望它像我们在 Illustrator 中所做的那样,创建一条名为 CutContour 的剪切线作为专色,但由于某种原因,它没有在导出时注册。
我尝试过枕头、元素树、inkscape、scribus,但没有效果.
import subprocess
import os
import xml.etree.ElementTree as ET
import cv2
import numpy as np
from PIL import Image
def convert_png_to_svg(input_image_path, output_svg_path):
try:
subprocess.run(['C:\\Program Files\\Inkscape\\bin\\inkscape.exe', input_image_path, '--export-type=svg', '--export-filename', output_svg_path], check=True)
if os.path.exists(output_svg_path):
print(f"SVG file created: {os.path.abspath(output_svg_path)}")
else:
print(f"Error: SVG file was not created: {output_svg_path}")
except subprocess.CalledProcessError as e:
print(f"Error running Inkscape: {e}")
except FileNotFoundError:
print("Inkscape not found. Make sure it's installed at the specified path.")
def remove_small_objects(mask, min_size):
num_labels, labels, stats, _ = cv2.connectedComponentsWithStats(mask, connectivity=8)
for i in range(1, num_labels):
if stats[i, cv2.CC_STAT_AREA] < min_size:
mask[labels == i] = 0
return mask
def add_contour_to_svg(input_image_path, svg_path, output_svg_path, border_size, padding):
# Open the original image
img = Image.open(input_image_path).convert("RGBA")
# Add initial padding to the original image
padded_size = (img.width + 2 * padding, img.height + 2 * padding)
padded_img = Image.new("RGBA", padded_size, (0, 0, 0, 0))
padded_img.paste(img, (padding, padding))
# Convert to numpy array
img_np = np.array(padded_img)
# Create an alpha mask
alpha = img_np[:, :, 3]
# Create a binary mask
mask = (alpha > 0).astype(np.uint8) * 255
# Remove small objects (smaller than 1px)
mask = remove_small_objects(mask, 1)
# Find contours using OpenCV
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Find the outer contour
outer_contour = max(contours, key=cv2.contourArea)
# Create a new mask for the border
border_mask = np.zeros_like(mask)
# Draw the contour on the border mask with a thicker stroke
cv2.drawContours(border_mask, [outer_contour], -1, 255, border_size)
# Find the contours of the border mask
border_contours, _ = cv2.findContours(border_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
border_contour = max(border_contours, key=cv2.contourArea)
# Parse the SVG
tree = ET.parse(svg_path)
root = tree.getroot()
ns = {'svg': 'http://www.w3.org/2000/svg'}
# Create a new layer for the cut path
layer = ET.SubElement(root, 'g', {
'id': 'cut_layer',
'inkscape:groupmode': 'layer',
'inkscape:label': 'CutContour'
})
# Create the cut path
path_data = 'M ' + ' '.join(f'{px},{py}' for px, py in [point[0] for point in border_contour]) + ' Z'
ET.SubElement(layer, 'path', {
'd': path_data,
'fill': 'none',
'stroke': '#EC008C',
'stroke-width': str(border_size)
})
# Save the modified SVG
tree.write(output_svg_path)
print(f"Modified SVG with contour saved as: {output_svg_path}")
def export_svg_to_pdf(svg_path, output_pdf_path):
try:
subprocess.run(['C:\\Program Files\\Inkscape\\bin\\inkscape.exe', svg_path, '--export-type=pdf', '--export-filename', output_pdf_path], check=True)
if os.path.exists(output_pdf_path):
print(f"PDF file created: {os.path.abspath(output_pdf_path)}")
else:
print(f"Error: PDF file was not created: {output_pdf_path}")
except subprocess.CalledProcessError as e:
print(f"Error running Inkscape: {e}")
except FileNotFoundError:
print("Inkscape not found. Make sure it's installed at the specified path.")
# Input image path
input_image_path = '2.png'
# Output SVG paths
output_svg_path = '2_converted.svg'
modified_svg_path = '2_with_cut.svg'
# Output PDF path
output_pdf_path = '2_final.pdf'
# Border size (pixels)
border_size = 1
# Padding size (pixels)
padding = 10
# Step 1: Convert PNG to SVG using Inkscape
convert_png_to_svg(input_image_path, output_svg_path)
# Step 2: Add cut path and spot color to the SVG
add_contour_to_svg(input_image_path, output_svg_path, modified_svg_path, border_size, padding)
# Step 3: Export the modified SVG to PDF using Inkscape
export_svg_to_pdf(modified_svg_path, output_pdf_path)
已修复 - 此代码将为在 Flexi 和 Versaworks 中注册的任何文件添加填充边框和剪切线。目前,您的项目目录中需要有一个名为 2.png 的文件,但您可以轻松地在此基础上进行构建。
import numpy as np
from PIL import Image, ImageDraw, ImageFilter
import cv2
import os
from reportlab.pdfgen import canvas
from reportlab.lib.colors import PCMYKColorSep
from reportlab.lib.utils import ImageReader
def remove_small_objects(mask, min_size):
num_labels, labels, stats, _ = cv2.connectedComponentsWithStats(mask, connectivity=8)
for i in range(1, num_labels):
if stats[i, cv2.CC_STAT_AREA] < min_size:
mask[labels == i] = 0
return mask
def create_image_with_border(input_image_path, border_size, corner_radius):
# Open the original image
img = Image.open(input_image_path).convert("RGBA")
# Convert to numpy array
img_np = np.array(img)
# Remove pixels with opacity lower than 60%
img_np[img_np[:, :, 3] < 153] = [0, 0, 0, 0]
# Create an alpha mask
alpha = img_np[:, :, 3]
# Create a binary mask
mask = (alpha > 0).astype(np.uint8) * 255
# Remove small objects (smaller than 2px)
mask = remove_small_objects(mask, 2)
# Convert mask to PIL Image
mask_img = Image.fromarray(mask)
# Calculate new size with padding
padding = max(border_size * 3, corner_radius * 2)
new_size = (img_np.shape[1] + padding * 2, img_np.shape[0] + padding * 2)
# Create a new image with extra space for the border
img_with_border = Image.new('RGBA', new_size, (0, 0, 0, 0))
# Create a mask for the contour
contour_mask = Image.new('L', new_size, 0)
paste_position = (padding, padding)
contour_mask.paste(mask_img, paste_position)
# Apply corner rounding
contour_mask = contour_mask.filter(ImageFilter.GaussianBlur(radius=corner_radius / 2))
contour_mask = contour_mask.point(lambda x: 255 if x > 128 else 0)
# Create the contour border
contour_border = contour_mask.filter(ImageFilter.GaussianBlur(radius=border_size / 2))
contour_border = contour_border.point(lambda x: 255 if x > 0 else 0)
# Create a white layer for the border
white_layer = Image.new('RGBA', new_size, (255, 255, 255, 255))
# Paste the white border behind the image
img_with_border.paste(white_layer, (0, 0), contour_border)
# Paste the original image on top
img_with_border.paste(Image.fromarray(img_np), paste_position, Image.fromarray(mask))
return img_with_border
def create_contour(image):
# Convert image to numpy array
img_np = np.array(image)
# Create a binary mask
mask = (img_np[:, :, 3] > 0).astype(np.uint8) * 255
# Find contours
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Find the outer contour
outer_contour = max(contours, key=cv2.contourArea)
return outer_contour
def create_pdf_with_spot_color(image, contour, pdf_path, cutline_offset):
# Get image dimensions
img_width, img_height = image.size
# Create a new PDF canvas
c = canvas.Canvas(pdf_path, pagesize=(img_width + 2 * cutline_offset, img_height + 2 * cutline_offset))
# Define the spot color for the cut contour
cut_contour_spot = PCMYKColorSep(0.0, 100.0, 91.0, 0.0, spotName='CutContour', density=100)
# Draw the image
c.drawImage(ImageReader(image), cutline_offset, cutline_offset, img_width, img_height, mask='auto')
# Set the spot color
c.setStrokeColor(cut_contour_spot)
# Draw the contour path
c.setLineWidth(1)
path = c.beginPath()
# Start the path with a move to command
path.moveTo(contour[0][0][0] + cutline_offset,
(img_height + 2 * cutline_offset) - (contour[0][0][1] + cutline_offset))
# Draw the contour path
for point in contour[1:]:
px, py = point[0]
path.lineTo(px + cutline_offset,
(img_height + 2 * cutline_offset) - (py + cutline_offset)) # Adjust for coordinate system
path.close()
c.drawPath(path)
# Save the PDF
c.save()
print(f"PDF with spot color cut contour created: {pdf_path}")
# Input image path
input_image_path = '2.png'
# Output PDF path
output_pdf_path = 'cut_contour_spot_color.pdf'
# Border size (pixels)
border_size = 12
# Corner radius (pixels)
corner_radius = 7
# Cutline offset (distance from border to cutline)
cutline_offset = 1
# Create image with rounded contour padding border
img_with_border = create_image_with_border(input_image_path, border_size, corner_radius)
# Create contour from image with border
contour = create_contour(img_with_border)
# Create the PDF with the spot color cut contour
create_pdf_with_spot_color(img_with_border, contour, output_pdf_path, cutline_offset)
print(f"PDF created: {os.path.abspath(output_pdf_path)}")
以下是如何使用 Python 在 PDF 中创建注册为专色的剪切线的解决方法:
1. 图像处理和轮廓检测
- 使用 Pillow 或 OpenCV 加载的图像: 这些库非常适合图像处理任务。
- 创建蒙版: 为的图像创建一个蒙版以隔离要创建剪切线的区域。可以根据颜色阈值、alpha 透明度或任何其他相关的标准来实现这一点。
-
查找轮廓:
使用 OpenCV 的
cv2.findContours
函数检测蒙版图像中的轮廓。选择代表所需剪切线的适当轮廓(例如,外部轮廓)。
2. 生成 SVG 并使用专色
-
安装 svgwrite:
我们将使用
svgwrite
库生成 SVG 文件。可以使用pip install svgwrite
安装它。 -
创建 SVG:
- 创建一个新的 SVG 文档。
-
为的图像添加一个
<image>
元素。 -
创建一个新的
<path>
元素以表示剪切线。-
将
<path>
元素的d
属性设置为步骤 1 中提取的轮廓坐标。 -
将
<path>
元素的stroke
属性设置为的专色。可以使用专色名称(如果的 RIP 软件支持)或 CMYK 值。例如,对于“CutContour”,可以使用stroke="CutContour"
。
-
将
- 保存 SVG 文件。
3. 将 SVG 转换为 PDF(使用 Inkscape)
- 安装 Inkscape: 确保的系统上安装了 Inkscape。
-
使用
subprocess
模块从 Python 运行 Inkscape 命令行:-
使用
inkscape --export-type=pdf your_file.svg
命令将 SVG 文件转换为 PDF。
-
使用
代码示例:
import cv2
import numpy as np
from PIL import Image
import svgwrite
import subprocess
# 1. 图像处理和轮廓检测
image = cv2.imread("your_image.png", cv2.IMREAD_UNCHANGED)
# 创建蒙版(根据需要调整此步骤)
mask = image[:, :, 3] > 128
# 查找轮廓
contours, hierarchy = cv2.findContours(mask.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cut_contour = contours[0] # 假设想要外部轮廓
# 2. 生成 SVG 并使用专色
dwg = svgwrite.Drawing("output.svg", profile='tiny')
dwg.add(dwg.image("your_image.png", size=(image.shape[1], image.shape[0])))
path = dwg.path(d=f"M {' '.join(f'{p[0][0]},{p[0][1]}' for p in cut_contour)} Z",
fill="none", stroke="CutContour", stroke_width="1") # 使用 CutContour 专色
dwg.add(path)
dwg.save()
# 3. 将 SVG 转换为 PDF(使用 Inkscape)
subprocess.run(["inkscape", "--export-type=pdf", "output.svg"])
重要说明:
- 此解决方法假设的 RIP 软件支持“CutContour”专色或可以指定其 CMYK 等效值。
- 调整图像处理步骤以适合特定图像和所需剪切线的需要。
- 可能需要调整 Inkscape 命令中的路径和文件名以匹配的系统设置。
此方法结合了不同的库和工具来实现想要的结果。请记住,在不同的 RIP 软件中,对专色和剪切线支持的实现可能会有所不同,因此可能需要进行一些实验和调整才能使其与的特定设置完美配合。
标签:python,svg From: 78818116