2016-11-16 132 views
1

wxPython的圖片我有一個產生數,只有在不同的目錄名稱相同地塊的數據項目。查看這些圖可以幫助我們看看數據是否有什麼奇怪的現象,但嘗試逐個打開它們或者將它們全部複製到一個目錄,重新命名它們,然後打開我的標準圖像觀衆。佔用大量內存

瞭解一些wxPython的GUI編程我決定掀起一個應用程序,將採取在目錄中這些圖像的列表,我可以在幻燈片放映他們提供一些箭頭按鈕。那麼我可以添加到這個列表隨着越來越多的地塊進來。

我得到了應用程序正常運行,但現在當我在周圍23〜3 MB的圖像加載我我的程序內存佔用率達到近10 GB。

的代碼如下,但總之我才顯示裝載它們全部爲wxPython的形象,這就是記憶攀登哪裏。通過堆棧在圖像之間切換看起來並不會讓內存進一步攀升。我認爲這可能是我堅持不再需要的資源,但是這種用法似乎與圖像的大小和數量不成比例。

是有人能夠在我的方法來指出一個缺陷?

```

class Slide(wx.Frame): 

    def __init__(self): 
     wx.Frame.__init__(self, None, -1, "Slide Show") 

     self.display = wx.GetDisplaySize() 

     self.image_list = None 
     self.current = None # holds currently displayed bitmap 
     # stacks that hold the bitmaps 
     self.future = [] 
     self.past = [] 


     self.left = wx.BitmapButton(self, id=101, size=(100,-1), bitmap=wx.ArtProvider.GetBitmap(wx.ART_GO_BACK)) 
     self.left.Enable(False) 
     self.right = wx.BitmapButton(self, id=102, size=(100,-1), bitmap=wx.ArtProvider.GetBitmap(wx.ART_GO_FORWARD)) 
     self.right.Enable(False) 
     self.open = wx.BitmapButton(self, id=103, size=(100,-1), bitmap=wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN)) 

     # Testing code 
     #png = wx.Image("set001_fit_001_1.png", wx.BITMAP_TYPE_ANY).ConvertToBitmap() 
     #image = wx.ImageFromBitmap(png) 
     #image = image.Scale(self.display[0]/1.4, self.display[1]/1.4, wx.IMAGE_QUALITY_HIGH) 
     #png = wx.BitmapFromImage(image) 

     # make empty image slot 
     self.img = wx.StaticBitmap(self, -1, size=(self.display[0]/1.4, self.display[1]/1.4)) 


     ## Main sizers 
     self.vertSizer = wx.BoxSizer(wx.VERTICAL) 

     # sub sizers 
     self.buttonSizer = wx.BoxSizer(wx.HORIZONTAL) 

     # place buttons together 
     self.buttonSizer.Add(self.left, flag=wx.ALIGN_CENTER) 
     als.AddLinearSpacer(self.buttonSizer, 15) 
     self.buttonSizer.Add(self.right, flag=wx.ALIGN_CENTER) 

     # place arrows and open together 
     self.vertSizer.Add(self.img, flag=wx.ALIGN_CENTER) 
     self.vertSizer.Add(self.open, flag=wx.ALIGN_CENTER) 
     als.AddLinearSpacer(self.vertSizer, 15) 
     self.vertSizer.Add(self.buttonSizer, flag=wx.ALIGN_CENTER) 
     als.AddLinearSpacer(self.vertSizer, 15) 

     self.Bind(wx.EVT_BUTTON, self.onOpen, id=103) 
     self.Bind(wx.EVT_BUTTON, self.onLeft, id=101) 
     self.Bind(wx.EVT_BUTTON, self.onRight, id=102) 

     self.SetSizer(self.vertSizer) 
     self.vertSizer.Fit(self) 

    def onOpen(self, evt): 
     print("Opening") 
     openFileDialog = wx.FileDialog(self, "Open Image List", "", "", "List (*.ls)|*.ls", wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) 
     if openFileDialog.ShowModal() == wx.ID_CANCEL: 
      return 

     fileName = str(openFileDialog.GetPath()) 
     print(fileName) 

     # put image list in a python list 
     image_list = [] 
     f = open(fileName, 'r') 
     for line in f: 
      image_list.append(line.rstrip()) 
     f.close() 

     print(image_list) 
     # convert every image to wx Image 
     png_list = [] 
     for image in image_list: 
      png = wx.Image(image, wx.BITMAP_TYPE_ANY) 
      png_list.append(png) 

     # store pngs 
     print(image_list[::-1]) 
     png_list = png_list[::-1] 
     for png in png_list[:-1]: 
      self.future.append(png) 

     # display first png 
     self.current = png_list[-1] # put into current buffer 
     png = self.current.Scale(self.display[0]/1.4, self.display[1]/1.4, wx.IMAGE_QUALITY_HIGH) 
     png = wx.BitmapFromImage(png) 
     self.img.SetBitmap(png) 

     self.Refresh() 
     self.right.Enable(True) 

    def onLeft(self, evt): 
     # put current image into future stack and grab a new current image from past stack 
     self.future.append(self.current) 
     self.current = self.past.pop() 

     png = self.current.Scale(self.display[0]/1.4, self.display[1]/1.4, wx.IMAGE_QUALITY_HIGH) 
     png = wx.BitmapFromImage(png) 
     self.img.SetBitmap(png) 
     self.Refresh() 
     if len(self.past) <= 0: 
      self.left.Enable(False) 

     self.right.Enable(True) 

    def onRight(self, evt): 
     # put current image into past stack and load in a new image from future stack 
     self.past.append(self.current) 
     self.current = self.future.pop() 

     png = self.current.Scale(self.display[0]/1.4, self.display[1]/1.4, wx.IMAGE_QUALITY_HIGH) 
     png = wx.BitmapFromImage(png) 
     self.img.SetBitmap(png) 
     self.Refresh() 

     if len(self.future) <= 0: 
      self.right.Enable(False) 
     self.left.Enable(True) 

```

+2

圖像文件使用壓縮,但程序必須保持它未壓縮。 – furas

+0

謝謝!這有助於我獲得更多搜索條件。我不知道這是這種情況,所以我要麼在內存中變得更復雜一些,要麼在需要的基礎上顯示它們。後來唯一的問題是我正在通過sshfs讀取圖像,這並不是最快的。再次感謝。 – Tristan

回答

2

加載它們需要很可能會減少內存使用的最佳方法。或者也許將當前,下一個和前一個圖像保存在內存中以幫助加快視圖之間的切換。或者可以使用緩存實現在內存中保留最近查看的圖像(加上序列中的下一個)。然後你可以撥動N的大小來看看哪些效果很好,並且是內存和速度之間的合理折衷。

另一個可能的改進是在每次需要顯示它的時候不會縮放圖像,只是它的規模,一旦在讀取和保存一個內存(或緩存)它。你也可以嘗試將它們預轉換爲wx.Bitmaps,因爲圖像到位圖轉換不是一個簡單的操作。

+0

隨着我的圖像有時通過SSHFS,將需要一個解決方案,在顯示之前只加載一些。我也在想我可以通過提取RGB數據來將它們壓縮在內存中,但這可能會很複雜。我也可以撥弄我的地塊的dpi和大小。至於你說我在顯示之前所做的操作,我確實嘗試了最初縮放和轉換位圖,但是圖像不會以我想要的比例顯示,所以我的快速解決方案就是您看到的代碼。 – Tristan