2010-02-09 13 views
9

Ho riscontrato un problema che non riesco a capire con PIL e reportlab. In particolare, mi piacerebbe usare drawImage su una tela in reportlab usando un oggetto immagine PIL.Report Library e immagini della libreria di imaging Python da problemi di memoria

In passato ho inserito le immagini nei documenti di reportlab dal web utilizzando i dati grezzi, StringIO e la classe ImageReader di reportlab. Sfortunatamente, ImageReader prende un nome di file o un buffer di file come oggetto.

L'obiettivo finale è quello di poter inserire i codici QR (che sono oggetti PIL) nei PDF di reportlab. Una cosa che funziona è la seguente:

size, qrcode = PyQrcodec.encode('http://www.google.com') 
    qrcode.save("img.jpeg") 
    self.pdf.drawImage(ImageReader("img.jpeg"), 25, 25, width=125, height=125) 
    self.pdf.showPage() 

Ciò consente di risparmiare l'immagine e poi lo legge in pdf. Ovviamente farlo in questo modo non ha senso.

I miei sforzi sono aggravati dalla storia di sviluppo relativamente lunga di reportlab che rende la ricerca delle risposte rilevanti per l'ultima versione (2.4).

Grazie per l'aiuto.

(A proposito, sto usando 1.1.6 PIL)

risposta

4

Anche se sembra che dovrebbe funzionare, in realtà non lo è. Finalmente sono stato in grado di rintracciare il problema, ed era nella funzione _isPILImage(). Il problema è che "Image.Image" è in realtà "da PIL import Image" mentre il mio oggetto è in realtà solo da Image. Avrei pensato che fossero uguali, ma in ogni caso l'istanza non li valuta come la stessa cosa. La mia soluzione trucco era quello di cambiare _isPILImage (fileName): ... per

519 def _isPILImage(im): 
520  import Image as PIL_Image 
521  try: 
522   return isinstance(im,Image.Image) or isinstance(im, PIL_Image.Image) 
523  except ImportError: 
524   return 0 

che risolve il mio errore. Dal momento che mi hai indirizzato nella giusta direzione, inizialmente ho provato a postare questo commento come un commento, quindi accetto la tua risposta, ma non consente un numero sufficiente di caratteri.

Grazie per l'input! Se riesci a pensare ad un modo più elegante per risolvere questo problema ... (ho provato a racchiudere l'oggetto Image.Image in un oggetto PIL Image) fammi sapere!

+1

A proposito, la funzione precedente è in lib/utils.py in reportlab. – philipk

+3

+1 buona presa. L'installatore PIL che mette i moduli PIL in una cartella PIL fuori dal percorso del sito è una decisione discutibile, ma ReportLab sta commettendo un errore peggiore facendo affidamento su di esso. Dovrebbe essere solo l'importazione dell'immagine. Ho risolto il problema ricorrendo alle patch per le scimmie dall'esterno: importate me stesso l'immagine e dicendo "reportlab.lib.utils.Image = Image'. – bobince

+0

@bobince ha l'idea giusta qui. ReportLab fa alcune ipotesi davvero pessime circa la localizzazione del PIL, ma è più pulito da applicare dopo l'importazione con 'reportlab.lib.utils.Image = Image' piuttosto che per giocare con il codice di ReportLab e complicare la distribuzione. – dkamins

2

Guardando la fonte per ReportLab 2.4, sembra che ImageReader accetterà un oggetto Immagine PIL come "nome del file".


def _isPILImage(im): 
    try: 
     return isinstance(im,Image.Image) 
    except ImportError: 
     return 0 

class ImageReader(object): 
    "Wraps up either PIL or Java to get data from bitmaps" 
    _cache={} 
    def __init__(self, fileName): 
     if isinstance(fileName,ImageReader): 
      self.__dict__ = fileName.__dict__ #borgize 
      return 
     #start wih lots of null private fields, to be populated by 
     #the relevant engine. 
     self.fileName = fileName 
     self._image = None 
     self._width = None 
     self._height = None 
     self._transparent = None 
     self._data = None 
     if _isPILImage(fileName): 
      self._image = fileName 
      self.fp = getattr(fileName,'fp',None) 
      try: 
       self.fileName = self._image.fileName 
      except AttributeError: 
       self.fileName = 'PILIMAGE_%d' % id(self) 
+0

Così 'self.pdf.drawImage (ImageReader (QRCode), 25, 25, width = 125, height = 125) 'dovrebbe funzionare, assumendo che il resto degli argomenti a' drawImage' siano appropriati. – MattH

0

weired la documentazione afferma che drawImage e drawInlineImage funzionano allo stesso modo, ma funziona con drawInlineImage fuori dalla scatola, e non funzionano in drawImage

Problemi correlati