Download raw (6.2 KB)
#!/usr/bin/env python # Copyright (C) 2011: Simeon Voelkel <simeon_voelkel@arcor.de> # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. The name of the author may not be used to endorse or promote # products derived from this software without specific prior written # permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import Image import sys from optparse import OptionParser #import optparse epsprolog_text="""%%Creator: duotoner.py %%LanguageLevel: 3 %%DocumentProcessColors: Black """ HKS43K_text="""%%DocumentCustomColors: %%+ (HKS 43 K) %%CMYKCustomColor: %%+ 0.94902 0.8 0 0 (HKS 43 K) """ HKS15K_text="""%%DocumentCustomColors: %%+ (HKS 15 K) %%CMYKCustomColor: %%+ 0.05 1.0 0.8 0 (HKS 15 K) """ PANTONE_2735_U_text="""%%DocumentCustomColors: %%+ (PANTONE 2735 U) %%CMYKCustomColor: %%+ 0.72 1.0 0 0.43 (PANTONE 2735 U) """ PANTONE_2735_U_colorspace=""" [ /DeviceN [ (PANTONE 2735 U) /Black ] /DeviceCMYK { exch dup 0.72 mul exch dup 1.0 mul exch dup 0.0 mul exch 0.43 mul 5 -1 roll add } ] setcolorspace """ HKS43K_colorspace=""" [ /DeviceN [ (HKS 43 K) /Black ] /DeviceCMYK { exch dup 0.94902 mul exch dup 0.8 mul exch dup 0.0 mul exch 0.0 mul 5 -1 roll add } ] setcolorspace """ HKS15K_colorspace=""" [ /DeviceN [ (HKS 15 K) /Black ] /DeviceCMYK { exch dup 0.05 mul exch dup 1.0 mul exch dup 0.8 mul exch 0.0 mul 5 -1 roll add } ] setcolorspace """ def epsprolog(ofile, width, height): ofile.write( '%!PS-Adobe-3.0 EPSF-3.0\n' ) # one point (1/72 inch, unit of coord.sys) contains 25/6 dots at 300 dpi: ofile.write( '%%BoundingBox: 0 0 {0:f} {1:f}\n'.format((width*6)/25+1, ((height+1)*6)/25+1) ) ofile.write( '%%HiResBoundingBox: 0 0 {0:f} {1:f}\n'.format((width*6.0)/25.0, ((height+1)*6.0)/25.0) ) ofile.write( epsprolog_text ) ofile.write( PANTONE_2735_U_text ) ofile.write( '%%EndComments\n' ) ofile.write( PANTONE_2735_U_colorspace ) ofile.write( '0 0 translate\n' ) ofile.write( '{0:f} {1:f} scale\n'.format((width*6.0)/25.0, (height*6.0)/25.0) ) ofile.write( '<<\n' ) ofile.write( ' /ImageType 1\n' ) ofile.write( ' /Width {0:d}\n'.format(width) ) ofile.write( ' /Height {0:d}\n'.format(height) ) ofile.write( ' /BitsPerComponent 8\n' ) ofile.write( ' /Decode [ 1 0 1 0 ]\n' ) ofile.write( ' /ImageMatrix [ {0:d} 0 0 -{1:d} 0 {1:d} ]\n'.format(width,height) ) ofile.write( ' /DataSource currentfile /ASCIIHexDecode filter \n' ) ofile.write( '>>\n' ) ofile.write( 'image\n' ) def heximageoutput(ofile,bpixel,spixel,width,height): for y in range(height) : linelength = 16; for x in range(width) : ofile.write( '{0:02X}'.format(spixel[x,y]) ) ofile.write( '{0:02X}'.format(bpixel[x,y]) ) linelength -= 1; if linelength == 0 : ofile.write( '\n' ) linelength = 16 ofile.write( '\n>\n' ) def epsepilog(ofile): ofile.write( '\n' ) ofile.write( 'showpage\n' ) ofile.write( '%%EOF\n' ) def do_duotone(grayimage, spotimage, epsout): imblack = Image.open(grayimage) imspot = Image.open(spotimage) bpixel = imblack.load() spixel = imspot.load() bwidth = imblack.size[0] swidth = imspot.size[0] bheight = imblack.size[1] sheight = imspot.size[1] bmode = imblack.mode smode = imspot.mode if bmode != 'L' : print('Grayscale(L) image required, but received {0:s} for black ink'.format(bmode)) exit (-1) if smode != 'L' : print('Grayscale(L) image required, but received {0:s} for spot color'.format(smode)) exit (-2) if bwidth != swidth or bheight != sheight : print('Image dimensions do not match!: Black: {0:d}x{1:d} vs. Spot: {2:d}x{3:d}'.format(bwidth,bheight,swidth,sheight)) exit (-3) print('Image dimensions are: Black: {0:d}x{1:d} vs. Spot: {2:d}x{3:d}'.format(bwidth,bheight,swidth,sheight)) ofile = open(epsout, 'wb') epsprolog(ofile,bwidth,bheight) heximageoutput(ofile,bpixel,spixel,bwidth,bheight) epsepilog(ofile) def process_args(): parser = OptionParser() parser.add_option("-b", "--black", action="store", type="string", dest="grayinfilename", default="/dev/stdin", help="image for black ink") parser.add_option("-s", "--spot", action="store", type="string", dest="spotinfilename", default="/dev/stdin", help="image for spot color") parser.add_option("-o", "--output", action="store", type="string", dest="epsoutfilename", default="/dev/stdout", help="epsfile for output") (options, args) = parser.parse_args() do_duotone(options.grayinfilename, options.spotinfilename, options.epsoutfilename) if __name__ == "__main__": process_args()