Re: Printing Matplotlib (MPL) Graphs in PIL?

Kevin Cazabon <[email protected]>
Newsgroups gmane.comp.python.image
Message-ID <[email protected]>
Here's a module that will print any PIL image for you... it's been a long time since I've modified it or tested it, but it should work on Windows systems at least.  It was based on some code from someone else (I think I referenced them in the code), but cleaned up and expanded.  There's some sample usages at the bottom I believe too.

ImagePrintWin.py is what you want... I've included some random test files too.  Good luck!


It also includes a Tkinter class for a "Print" dialog, including print preview.




(I'll gladly append more open licensing if anyone wants it, or if Fred is willing to add yet another hack of mine to the standard Library... sorry this one isn't so clean)

Kevin.


On 17 Jan 2010, at 11:16, Wayne Watson wrote:

> I've used MPL a bit, and am wondering if there's a facility in PIL for sending graphic images to a printer, or putting them in some format like png? I don't necessarily want the graphics to appear in a window, but would like to print them directly once they are ready. Can one put in a page feed, so that images don't all fall on the same page or cut across pages?
> 
> I asked about this in the MPL list and didn't get a single reply, so I guess there's nothing in MPL that will do it.
> 
> 
> -- 
>           Wayne Watson (Watson Adventures, Prop., Nevada City, CA)
> 
>             (121.015 Deg. W, 39.262 Deg. N) GMT-8 hr std. time)
>              Obz Site:  39° 15' 7" N, 121° 2' 32" W, 2700 feet
> 
>           "I was thinking about how people seem to read the Bible
>            a whole lot more as they get older; then it dawned on
>            me . . they're cramming for their final exam."
>                                    -- George Carlin
> 
>                    Web Page: <www.speckledwithstars.net/>
> 
> 
> _______________________________________________
> Image-SIG maillist  -  [email protected]
> http://mail.python.org/mailman/listinfo/image-sig

_______________________________________________
Image-SIG maillist  -  [email protected]
http://mail.python.org/mailman/listinfo/image-sig
ImagePrintWin.py (text/x-python-script, 100.4 KB) - not displayed
printdemo.py (text/x-python-script, 7.4 KB)
# Demo of printing an image (requires PIL)
# by Roger Burnham ([email protected])

import win32ui
import win32con
import afxres
import Image
import ImageWin
import copy
import string
from pywin.mfc import docview
from pywin.mfc import dialog


PRINTDLGORD = 1538
IDC_PRINT_MAG_EDIT = 1010


class PrintView(docview.ScrollView):
    def __init__(self,  doc):
        docview.ScrollView.__init__(self, doc)
        self.doc = doc
        self.image = self.pilDisplay = None
        dlg = win32ui.CreateFileDialog(1, None, None,
                                       (win32con.OFN_FILEMUSTEXIST|
                                        win32con.OFN_EXPLORER),
                                       'Image File (*.bmp)|*.bmp||')
        dlg.SetOFNTitle('Image to Print')
        if dlg.DoModal() == win32con.IDOK:
            image = dlg.GetPathNames()[0]
        else:
            return
        image = Image.open(image)
        self.image = image.convert('RGB')
        self.image.filename = image.filename
                
    def OnInitialUpdate(self):
        self._obj_.OnInitialUpdate()
        if self.image is None:
            return
        self.pilDisplay = ImageWin.Dib(self.image.mode, self.image.size)
        self.pilDisplay.paste(self.image)
        self.SetScrollSizes(win32con.MM_TEXT, self.image.size)
        self.ResizeParentToFit(0)
        self.HookCommand(self.OnFilePrint, afxres.ID_FILE_PRINT)
        self.HookCommand(self.OnFilePrintPreview, win32ui.ID_FILE_PRINT_PREVIEW)
        
    def OnAttachedObjectDeath(self):
        docview.ScrollView.OnAttachedObjectDeath(self)

    def OnDraw(self, dc):
        if self.pilDisplay is not None:
            self.pilDisplay.expose(dc.GetHandleOutput())
        
    def OnFilePrintPreview(self, *arg):
        self._obj_.OnFilePrintPreview()

    def OnFilePrint(self, *arg):
        self._obj_.OnFilePrint()

    def OnPreparePrinting(self, pInfo):
        flags = (win32ui.PD_USEDEVMODECOPIES|
                 win32ui.PD_PAGENUMS|
                 win32ui.PD_NOPAGENUMS|
                 win32ui.PD_NOSELECTION)
        self.prtDlg = ImagePrintDialog(pInfo, PRINTDLGORD, flags)
        pInfo.SetPrintDialog(self.prtDlg)
        self._continuePrinting = 1
        self.noteLines = []
        self.printTop = 0
        return self.DoPreparePrinting(pInfo)

    def OnBeginPrinting(self, dc, pInfo):
        mag = self.prtDlg['mag']
        dc.SetMapMode(win32con.MM_ANISOTROPIC);
        dc.SetWindowOrg((0, 0))
        dc.SetWindowExt((1, 1))
        dc.SetViewportOrg((0, 0))
        dc.SetViewportExt((mag, mag))
        pInfo.SetFromPage(1)
        pInfo.SetToPage(100)

    def OnPrepareDC(self, dc, pInfo):
        if dc.IsPrinting():
            mag = self.prtDlg['mag']
            dc.SetMapMode(win32con.MM_ANISOTROPIC);
            dc.SetWindowOrg((0, 0))
            dc.SetWindowExt((1, 1))
            dc.SetViewportOrg((0, 0))
            dc.SetViewportExt((mag, mag))
            pInfo.SetContinuePrinting(self._continuePrinting)

    def OnPrint(self, dc, pInfo):
        page = pInfo.GetCurPage()

        metrics = dc.GetTextMetrics()
        cxChar = metrics['tmAveCharWidth']
        cyChar = metrics['tmHeight']
        left, top, right, bottom = pInfo.GetDraw()

        rect = self.ScreenToClient(self.GetWindowRect())
        height = (rect[3]-rect[1])

        if page == 1:
            if self.image.filename is not None:
                dc.TextOut(0, 2*cyChar, '%s - Page %d'
                           % (self.image.filename, page))
            top = top + (7*cyChar)/2
            dc.MoveTo(left, top)
            dc.LineTo(right, top)
            top = top + cyChar
            pInfo.SetDraw((left, top, right, bottom))
            left, top, right, bottom = pInfo.GetDraw()
            dc.SetWindowOrg((left, -top))

            self.OnDraw(dc)
            dc.SetTextAlign(win32con.TA_LEFT|win32con.TA_BOTTOM)

            self.printTop = top+height+cyChar
            dc.SetWindowOrg((left, -self.printTop))
            dc.MoveTo(left, 0)
            dc.LineTo(right, 0)

            self.noteLines.append(self.doc.GetTitle())

            keys = self.image.info.keys()
            keys.sort()
            maxKey = 0
            for key in keys:
                maxKey = max(maxKey, len(key))
            for key in keys:
                val = self.image.info[key]
                if type(val) != type(''):
                    val = `val`
                self.noteLines.append('%*s : %s' % (maxKey, key, val))

            left, top, right, bottom = pInfo.GetDraw()
            self.noteLines.append('Notes:')
            for line in string.split(self.prtDlg['notes'], '\n'):
                if line:
                    txtLine = None
                    for word in string.split(line):
                        if txtLine is None:
                            tstLine = txtLine = '   ' + word
                        else:
                            tstLine = txtLine + ' ' + word
                        w,h = dc.GetTextExtent(tstLine)
                        if w <= right:
                            txtLine = tstLine
                        else:
                            self.noteLines.append(txtLine)
                            txtLine = '   ' + word
                    self.noteLines.append(txtLine)

        lines = copy.copy(self.noteLines)

        if page > 1:
            if self.image.filename is not None:
                dc.TextOut(0, 2*cyChar, '%s - Page %d'
                           % (self.image.filename, page))
            self.printTop = self.printTop + (7*cyChar)/2
            dc.MoveTo(left, self.printTop)
            dc.LineTo(right, self.printTop)
        else:
            self.printTop = self.printTop + cyChar/2
        dc.SetWindowOrg((left, -self.printTop))

        for line in lines:
            self.printTop = self.printTop + cyChar
            if self.printTop >= bottom:
                break
            dc.SetWindowOrg((left, -self.printTop))
            dc.TextOut(0, 0, line)
            self.noteLines.remove(line)

        self._continuePrinting = (len(self.noteLines) > 0)
        if self._continuePrinting:
            self.printTop = 0

    def OnEndPrinting(self, dc, pInfo):
        del self.prtDlg
        return self._obj_.OnEndPrinting(dc, pInfo)

	
class ImagePrintDialog(dialog.PrintDialog):
    def __init__(self, pInfo, dlgID, flags=win32ui.PD_USEDEVMODECOPIES):
        dialog.PrintDialog.__init__(self, pInfo, dlgID, flags=flags)
        self['mag'] = 3
        self['notes'] = '''
line 1 of some notes.
line 2 of more notes.
'''

    def OnInitDialog(self):
        rc = dialog.PrintDialog.OnInitDialog(self)
        self.magCtl = self.GetDlgItem(IDC_PRINT_MAG_EDIT)
        self.magCtl.SetWindowText(`self['mag']`)
        return rc
    
    def OnOK(self):
        dialog.PrintDialog.OnOK(self)
        try:
            self['mag'] = string.atoi(self.magCtl.GetWindowText())
        except:
            pass


def Printdemo():
    template = docview.DocTemplate(win32ui.IDR_PYTHONTYPE,
                                   None, None, PrintView)
    doc = template.OpenDocumentFile(None)
    doc.SetTitle ('Print Demo')
    PrintView(doc)
    template.close()


if __name__=='__main__':
    import demoutils
    if demoutils.NeedGoodGUI():
        Printdemo()
PrinterTesting.py (text/x-python-script, 1.6 KB)
import win32ui
import win32gui
import win32con
import win32print
from PIL import Image, ImageWin

#
# Constants for GetDeviceCaps 
HORZSIZE = 4		
VERTSIZE = 6		
HORZRES = 8		#Total device units horiz in page size
VERTRES = 10		#Total device units vert in page size

ASPECTX = 40
ASPECTY = 42
ASPECTXY = 44

PHYSICALWIDTH = 110	#
PHYSICALHEIGHT = 111
PHYSICALOFFSETX = 112
PHYSICALOFFSETY = 113

LOGPIXELSX = 88		#Device units per inch
LOGPIXELSY = 90		#Device units per inch

#
# Find the printer resolution to scale to
#
hDC = win32ui.CreateDC ()
hDC.CreatePrinterDC ("QMS-PS 2000 v52.4") # can optionally put a printer name in here

print "HORZSIZE:\t%s" %hDC.GetDeviceCaps (HORZSIZE)
print "VERTSIZE:\t%s" %hDC.GetDeviceCaps (VERTSIZE)
print "HORZRES:\t%s" %hDC.GetDeviceCaps (HORZRES)
print "VERTRES:\t%s" %hDC.GetDeviceCaps (VERTRES)
print "PHYSICALWIDTH:\t%s" %hDC.GetDeviceCaps (PHYSICALWIDTH)
print "PHYSICALHEIGHT:\t%s" %hDC.GetDeviceCaps (PHYSICALHEIGHT)
print "PHYSICALOFFSETX:\t%s" %hDC.GetDeviceCaps (PHYSICALOFFSETX)
print "PHYSICALOFFSETY:\t%s" %hDC.GetDeviceCaps (PHYSICALOFFSETY)
print "LOGPIXELSX:\t%s" %hDC.GetDeviceCaps (LOGPIXELSX)
print "LOGPIXELSY:\t%s" %hDC.GetDeviceCaps (LOGPIXELSY)
print "ASPECTX:\t%s" %hDC.GetDeviceCaps (ASPECTX)
print "ASPECTY:\t%s" %hDC.GetDeviceCaps (ASPECTY)
print "ASPECTXY:\t%s" %hDC.GetDeviceCaps (ASPECTXY)

print win32print.EnumPrinters(2)
#((8388608, 'QMS-PS 2000 v52.4,QMS-PS 2000 v52.4,', 'QMS-PS 2000 v52.4', ''), (8388608, 'Lexmark,Lexmark Z25-Z35,', 'Lexmark', ''))

#[x][2] is printer name
printTest.py (text/x-python-script, 1.1 KB)
    
import ImageWin
import win32print
import win32ui
import Image
    
def printIm(img):
    img.load()
    dib=ImageWin.Dib('RGB',img.size)
    dib.paste(img,None)
    
    # get the default printer
    pname = win32print.GetDefaultPrinter()
    
    # get DC
    try:
        hnum=win32print.OpenPrinter(pname)
    except:
        print 'failure OpenPrinter'

    try:
        win32print.StartDocPrinter(hnum,1,('Test',None,None))
    except:
        print 'failure startdocprint'
        
    #win32print.WritePrinter(hnum,'This is a test\n')
    
    try:
        dc=win32ui.CreateDCFromHandle(hnum)
    except:
        print 'failure getting DC'
        return
    
    # output to DC
    hdc=dc.GetHandleAttrib()
    
    dib.draw(hdc, (0, 0) + img.size)
    #dib.expose(hdc) 

    win32print.WritePrinter(hnum, dib)

    # close DC
    del dc
    win32print.EndDocPrinter(hnum)
    win32print.ClosePrinter(hnum)
    del dib
    del img
    print "Successfully printed"

if __name__ == "__main__":
    im = Image.open("c:\\temp\\test.jpg")
    printIm(im)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.