我曾经经营过一家丝网印刷工作室(那是一间很小的),虽然我从未真正做过分色印刷,但我对这些原理相当熟悉。这就是我的处理方式:
- 将图像拆分为 C、M、Y、K。
- 将每个分离的图像分别旋转 0、15、30 和 45 度。
- 取每个图像的半色调(点大小将与强度成正比)。
- 旋转每个半色调图像。
现在你有你的颜色分离的图像。正如您所提到的,旋转步骤减少了点对齐问题(这会使一切变得混乱),并且诸如莫尔图案效果之类的事情将被合理地最小化。
这应该很容易使用PIL进行编码。
更新 2:
我写了一些快速代码来为你做这件事,它还包括一个GCR
函数(如下所述):
import Image, ImageDraw, ImageStat
def gcr(im, percentage):
'''basic "Gray Component Replacement" function. Returns a CMYK image with
percentage gray component removed from the CMY channels and put in the
K channel, ie. for percentage=100, (41, 100, 255, 0) >> (0, 59, 214, 41)'''
cmyk_im = im.convert('CMYK')
if not percentage:
return cmyk_im
cmyk_im = cmyk_im.split()
cmyk = []
for i in xrange(4):
cmyk.append(cmyk_im[i].load())
for x in xrange(im.size[0]):
for y in xrange(im.size[1]):
gray = min(cmyk[0][x,y], cmyk[1][x,y], cmyk[2][x,y]) * percentage / 100
for i in xrange(3):
cmyk[i][x,y] = cmyk[i][x,y] - gray
cmyk[3][x,y] = gray
return Image.merge('CMYK', cmyk_im)
def halftone(im, cmyk, sample, scale):
'''Returns list of half-tone images for cmyk image. sample (pixels),
determines the sample box size from the original image. The maximum
output dot diameter is given by sample * scale (which is also the number
of possible dot sizes). So sample=1 will presevere the original image
resolution, but scale must be >1 to allow variation in dot size.'''
cmyk = cmyk.split()
dots = []
angle = 0
for channel in cmyk:
channel = channel.rotate(angle, expand=1)
size = channel.size[0]*scale, channel.size[1]*scale
half_tone = Image.new('L', size)
draw = ImageDraw.Draw(half_tone)
for x in xrange(0, channel.size[0], sample):
for y in xrange(0, channel.size[1], sample):
box = channel.crop((x, y, x + sample, y + sample))
stat = ImageStat.Stat(box)
diameter = (stat.mean[0] / 255)**0.5
edge = 0.5*(1-diameter)
x_pos, y_pos = (x+edge)*scale, (y+edge)*scale
box_edge = sample*diameter*scale
draw.ellipse((x_pos, y_pos, x_pos + box_edge, y_pos + box_edge), fill=255)
half_tone = half_tone.rotate(-angle, expand=1)
width_half, height_half = half_tone.size
xx=(width_half-im.size[0]*scale) / 2
yy=(height_half-im.size[1]*scale) / 2
half_tone = half_tone.crop((xx, yy, xx + im.size[0]*scale, yy + im.size[1]*scale))
dots.append(half_tone)
angle += 15
return dots
im = Image.open("1_tree.jpg")
cmyk = gcr(im, 0)
dots = halftone(im, cmyk, 10, 1)
im.show()
new = Image.merge('CMYK', dots)
new.show()
这将变成这样:
![在此处输入图像描述](https://i.stack.imgur.com/2ee5J.jpg)
进入这个(模糊你的眼睛并远离显示器):
![在此处输入图像描述](https://i.stack.imgur.com/N7CiK.jpg)
请注意,图像采样可以逐像素进行(从而在最终图像中保留原始图像的分辨率)。通过设置来做到这一点sample=1
,在这种情况下,您需要设置scale
一个更大的数字,以便有许多可能的点大小。这也将导致更大的输出图像大小(原始图像大小 * 比例 ** 2,所以要小心!)。
默认情况下,当您转换RGB
为通道CMYK
时K
(黑色通道)为空。是否需要K
通道取决于您的打印过程。您可能想要它的原因可能有多种:获得比重叠更好的黑色CMY
、节省墨水、缩短干燥时间、减少墨水渗色等。总之我还写了一点灰色组件替换功能GCR
,因此您可以设置K
您想要替换重叠的频道百分比CMY
(我在代码注释中进一步解释了这一点)。
这里有几个例子来说明。处理letter F
来自图像的sample=1
和scale=8
,因此分辨率相当高。
4CMYK
个通道,带有percentage=0
,因此为空K
通道:
![在此处输入图像描述](https://i.stack.imgur.com/kuQre.jpg)
![在此处输入图像描述](https://i.stack.imgur.com/xeUpM.jpg)
![在此处输入图像描述](https://i.stack.imgur.com/8xCS6.jpg)
![在此处输入图像描述](https://i.stack.imgur.com/XfK3a.jpg)
结合产生:
![在此处输入图像描述](https://i.stack.imgur.com/VXb5U.jpg)
CMYK
通道,有percentage=100
,所以K
使用通道。您可以看到青色通道被完全抑制,品红色和黄色通道使用的墨水少得多,在图像底部的黑色带中:
![在此处输入图像描述](https://i.stack.imgur.com/jlC3D.jpg)
![在此处输入图像描述](https://i.stack.imgur.com/fnG6g.jpg)
![在此处输入图像描述](https://i.stack.imgur.com/XgYlt.jpg)
![在此处输入图像描述](https://i.stack.imgur.com/DQj4O.jpg)
![在此处输入图像描述](https://i.stack.imgur.com/tSK9C.jpg)