Example #1
0
    def OnDropFiles(self, x, y, filenames):
        """validate image before passing it on to self.app.loadImage()"""
        path = filenames[0]
	## create RGBEImage to check file type and data
        rgbeImg = RGBEImage(self, self.wxapp._log, ["-i", path])
        rgbeImg.readImageData(path)
        if rgbeImg.error:
            msg = "Error loading image.\nFile: %s\nError: %s" % (path,rgbeImg.error)
            self.wxapp.showError(msg)
        else:
            ## now load for real
            self.wxapp.loadImage(path)
Example #2
0
    def test_doFalsecolor_fail(self, fci_mock):
        log.error = mock.MagicMock()
        fci_mock.return_value = False

        img = RGBEImage(wxparent, log)
        img.error = "some error"
        img.showError = mock.MagicMock()

        result = img.doFalsecolor()
        self.assertFalse(result)
        log.error.assert_called_with("FalsecolorImage.doFalsecolor() == False")
        img.showError.assert_called_with("falsecolor2 error:\nsome error")
Example #3
0
    def loadImage(self, path, args=[]):
        """create instance of falsecolor image from <path>"""
        self._log.info("loadImage(%s)" % path)
        self.reset()

        self.rgbeImg = RGBEImage(self, self._log, ["-i", path])
        self.rgbeImg.readImageData(path)

        if self.rgbeImg.error:
            msg = "Error loading image:\n%s" % self.rgbeImg.error
            self.showError(msg)
            self.rgbeImg = None
            return False
        else:
            self.setPath(path)
            self.saveButton.Enable()
            self._loadImageData()
            self.imagepanel.update(self.rgbeImg)
            return True
Example #4
0
 def test_resize_fail(self):
     img = RGBEImage(wxparent, log)
     img.doPfilt = mock.MagicMock()
     img.doPfilt.return_value = False
     img._analyzeImage = mock.MagicMock()
     img.resize(600, 400)
     msg = "_analyzeImage() was called after failed resize()"
     self.assertFalse(img._analyzeImage.called, msg)
Example #5
0
 def test_resize(self):
     img = RGBEImage(wxparent, log)
     img.doPfilt = mock.MagicMock()
     img.doPfilt.return_value = True
     img._analyzeImage = mock.MagicMock()
     img.resize(600, 400)
     msg = "_analyzeImage() was not called after successful resize()"
     self.assertTrue(img._analyzeImage.called, msg)
Example #6
0
class WxfcFrame(wx.Frame):
    """main wxfalsecolor frame"""
    def __init__(self, parent, wxapp, logger, config):
        wx.Frame.__init__(self,
                          parent,
                          title="wxFalsecolor - Radiance Picture Viewer")

        self._log = logger
        self.parser = WxfcOptionParser(logger=self._log)
        self._config = config
        self.wxapp = wxapp
        self.imagepanel = ImagePanel(self)
        self.rgbeImg = None
        self.img = None
        self.path = ""
        self.filename = ""
        self.loadingCanceled = False

        ## layout and show main window
        self._layout()
        #TODO: self._addMenu()
        self.Size = (800, 600)
        self.Show()

    def process_cmd_line_args(self):
        """check arguments, load and convert image"""
        ## check command line args
        if self.parser.parseOptions(sys.argv[1:]) != True:
            self.showError(self.parser.error)
            return
        ## load image if present
        if self.parser.has_option('picture'):
            self.loadImage(self.parser.get('picture'))
            self.Update()
        if self.parser.has_fc_option() == True:
            self.doFalsecolor()

    def _addFileButtons(self, panel):
        """create top buttons"""
        self.loadButton = wx.Button(panel, wx.ID_ANY, label='open HDR')
        self.loadButton.Bind(wx.EVT_LEFT_DOWN, self.onLoadImage)
        self.panelSizer.Add(self.loadButton,
                            proportion=0,
                            flag=wx.EXPAND | wx.ALL,
                            border=5)

        self.saveButton = wx.Button(panel, wx.ID_ANY, label='save image')
        self.saveButton.Bind(wx.EVT_LEFT_DOWN, self.onSaveImage)
        self.saveButton.Disable()
        self.panelSizer.Add(self.saveButton,
                            proportion=0,
                            flag=wx.EXPAND | wx.LEFT | wx.RIGHT,
                            border=5)

        spacepanel = wx.Panel(panel, wx.ID_ANY, size=(-1, 5))
        self.panelSizer.Add(spacepanel, proportion=0, flag=wx.EXPAND)

    def _addMenu(self):
        """add menu to frame (disabled)"""
        return
        self.menubar = wx.MenuBar()
        self.SetMenuBar(self.menubar)
        self.fileMenu = wx.Menu()
        self.menubar.Append(self.file, '&File')
        self.fileOpen = self.file.Append(wx.ID_ANY, '&Open file')
        self.Bind(wx.EVT_MENU, self.onLoadImage, self.fileOpen)

    def _doButtonLayout(self):
        """create buttons"""
        panel = wx.Panel(self, style=wx.RAISED_BORDER)

        self.panelSizer = wx.BoxSizer(wx.VERTICAL)
        ## 'load' and 'save' buttons
        self._addFileButtons(panel)

        ## foldable controls panel
        self._foldpanel = FoldableControlsPanel(panel, self, wx.ID_ANY)
        self.lablecontrols = self._foldpanel.lablecontrols
        self.fccontrols = self._foldpanel.fccontrols
        self.displaycontrols = self._foldpanel.displaycontrols
        self.panelSizer.Add(self._foldpanel,
                            proportion=1,
                            flag=wx.EXPAND | wx.ALL,
                            border=5)

        ## 'quit' button
        quitbutton = wx.Button(panel, wx.ID_EXIT, label='quit')
        quitbutton.Bind(wx.EVT_LEFT_DOWN, self.onQuit)
        self.panelSizer.Add(quitbutton,
                            proportion=0,
                            flag=wx.EXPAND | wx.ALL | wx.ALIGN_BOTTOM,
                            border=10)
        panel.SetSizer(self.panelSizer)
        return panel

    def check_for_update(self, event=None):
        self.wxapp.check_for_update(event)

    def doFalsecolor(self, args=[]):
        """convert Radiance RGBE image to wx.Bitmap"""
        self._log.debug("doFalsecolor(%s)" % str(args))
        if not args:
            args = self.parser.get_options_as_args()
        if "-nofc" in args or self.imagepanel.doFalsecolor(args[:]) == True:
            self.fccontrols.setFromArgs(args[:])
            self.displaycontrols.reset()
            return True
        else:
            return False

    def doPcond(self, args):
        """apply pcond args to image"""
        if self.imagepanel.doPcond(args) == True:
            self.fccontrols.reset()
            return True
        else:
            return False

    def exit(self, error=None):
        """close logger and exit"""
        if error:
            self._log.error(str(error))
        self._config.save_changes()
        logging.shutdown()
        self.Close()

    def expandControlPanel(self, idx):
        """expand control panel with index idx"""
        self._foldpanel.expand(idx)

    def formatNumber(self, n):
        """use FalsecolorImage formating for consistency"""
        if self.rgbeImg:
            return self.rgbeImg.formatNumber(n)
        else:
            return str(n)

    def getLableText(self):
        """return text of lable text box"""
        return self.lablecontrols.getLableText()

    def getRGBVAt(self, pos):
        """return pixel value at position"""
        if self.rgbeImg:
            return self.rgbeImg.getRGBVAt(pos)
        else:
            return (-1, -1, -1, -1)

    def getRGBVAverage(self, start, end):
        """return average pixel value for rectangle"""
        if self.rgbeImg:
            return self.rgbeImg.getRGBVAverage(start, end)
        else:
            return (-1, -1, -1, -1)

    def _layout(self):
        """main layout of controls and image panel"""
        ## buttons
        panel = self._doButtonLayout()
        ## image - buttons layout
        self.sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.sizer.Add(panel, proportion=0, flag=wx.EXPAND)
        self.sizer.Add(self.imagepanel, proportion=1, flag=wx.EXPAND)
        self.SetSizer(self.sizer)
        ## status bar
        self.statusbar = SplitStatusBar(self)
        self.SetStatusBar(self.statusbar)

    def loadImage(self, path, args=[]):
        """create instance of falsecolor image from <path>"""
        self._log.info("loadImage(%s)" % path)
        self.reset()

        self.rgbeImg = RGBEImage(self, self._log, ["-i", path])
        self.rgbeImg.readImageData(path)

        if self.rgbeImg.error:
            msg = "Error loading image:\n%s" % self.rgbeImg.error
            self.showError(msg)
            self.rgbeImg = None
            return False
        else:
            self.setPath(path)
            self.saveButton.Enable()
            self._loadImageData()
            self.imagepanel.update(self.rgbeImg)
            return True

    def _loadImageData(self):
        """load image data of small images immediately"""
        ## TODO: evaluate image data (exclude fc images)
        max_size = self._config.getint("lables", "max_data_load", 1000000)
        if max_size == 0:
            self._log.info("automatic data loading disabled")
            self.lablecontrols.reset()
            return

        ## compare image resolution against max_size
        x, y = self.rgbeImg.getImageResolution()
        if x * y <= max_size:
            ## call OnShowValues with fake event
            self.lablecontrols.OnShowValues(-1)
        else:
            self.statusbar.SetStatusText("confirm 'load data' or resize image")
            nx, ny = beautyscale(x, y, max_size)
            info = {
                'x': x,
                'y': y,
                'new_x': nx,
                'new_y': ny,
                'backup_name': self.rgbeImg.getBackupName(),
                'do_resize': False
            }
            dlg = ResizeDialog(parent=self, ID=-1, title="foo")
            dlg.setImageInfo(info)

            result = dlg.ShowModal()
            if result == wx.ID_OK:
                if dlg.cb_resize.IsChecked():
                    self.resizeRGBEImage(dlg)
                else:
                    self._log.info("loading original image data")
                self.lablecontrols.OnShowValues(-1)
            else:
                self._log.info("loading of image data cancelled by user")
                self.lablecontrols.reset()
                self.statusbar.SetStatusText("skipping 'load data'.")
            dlg.Destroy()

            #msg = "This is a large image.\nDo you want to load image data now?"
            #dlg = wx.MessageDialog(self, message=msg, caption="Load data?", style=wx.YES_NO|wx.YES_DEFAULT|wx.ICON_QUESTION)
            #if dlg.ShowModal() == wx.ID_YES:
            #else:

    def loadValues(self):
        """load luminance/illuminance data from image"""
        return self.rgbeImg.hasArrayData(self)

    def onImagePanelClick(self):
        """action on click on imagepanel"""
        if self.imagepanel.hasLables():
            self.lablecontrols.loadClearButton.Enable()
        elif self.lablecontrols.loadClearButton.GetLabelText() == "load data":
            self.lablecontrols.loadClearButton.Enable()
        else:
            self.lablecontrols.loadClearButton.Disable()

    def onLoadImage(self, event):
        """load new Radiance RGBE image"""
        filedialog = wx.FileDialog(
            self,
            message='Choose an image to open',
            defaultDir='',
            defaultFile='',
            wildcard=
            'Radiance Image Files (*.hdr,*.pic)|*.hdr;*.pic|all files |*.*',
            style=wx.OPEN)
        if filedialog.ShowModal() == wx.ID_OK:
            path = filedialog.GetPath()
            self.loadImage(path)

    def onQuit(self, event):
        """hasta la vista"""
        self.exit()

    def onSaveImage(self, event):
        """save bmp image to file"""
        dirname, filename = os.path.split(self.path)
        filebase = os.path.splitext(filename)[0]
        #formats = "|".join(["HDR file|*.hdr", WX_IMAGE_WILDCARD, "PIC (old)|*.pic"])
        formats = "|".join(
            ["HDR file|*.hdr", WX_IMAGE_WILDCARD, "PPM file|*.ppm"])
        filedialog = wx.FileDialog(self,
                                   message='save image',
                                   defaultDir=dirname,
                                   defaultFile=filebase + '.hdr',
                                   wildcard=formats,
                                   style=wx.SAVE)
        if filedialog.ShowModal() == wx.ID_OK:
            path = filedialog.GetPath()
            result = self.rgbeImg.saveToFile(path)
            if result != True:
                msg = "Error saving image:\n" + self.rgbeImg.error
                self.showError(msg)
            else:
                self.statusbar.SetStatusText("saved file '%s'" % path)

    def reset(self):
        """reset array to inital (empty) values"""
        self.displaycontrols.reset()
        self.imagepanel.clearLabels()
        self.fccontrols.reset()
        if self.rgbeImg:
            self.imagepanel.update(self.rgbeImg)
            if self.rgbeImg.isIrridiance():
                self.fccontrols.reset("Lux")

    def resizeRGBEImage(self, dlg):
        """create backup copy, resize and save image"""
        w = int(dlg.img_width.GetValue())
        h = int(dlg.img_height.GetValue())
        backup = dlg.img_backup.GetValue()
        self._log.info("resizing image: w=%d, h=%d, backup='%s'" %
                       (w, h, backup))

        if backup != "":
            self.rgbeImg.saveToFile(backup)

        self.rgbeImg.resize(w, h)

        if self.rgbeImg.hasFilepath():
            self.rgbeImg.saveToFile(self.rgbeImg.picture)
            self.rgbeImg.readImageData(self.rgbeImg.picture)

    def setPath(self, path):
        """update frame with new image path"""
        self.path = path
        self.filename = os.path.split(path)[1]
        self.SetTitle("wxFalsecolor - '%s'" % self.filename)

    def showAboutDialog(self, event=None):
        """show dialog with license etc"""
        info = wx.AboutDialogInfo()
        info.Name = "wxfalsecolor"
        info.Version = "%s" % VERSION
        info.Copyright = "(c) 2015 Thomas Bleicher"
        info.Description = "cross-platform GUI frontend for falsecolor"
        info.WebSite = ("http://tbleicher.github.io/wxfalsecolor/",
                        "wxfalsecolor home page")
        info.Developers = ["Thomas Bleicher", "Axel Jacobs"]
        lines = [" ".join(line.split()) for line in LICENSE.split("\n\n")]
        info.License = wordwrap("\n\n".join(lines), 500, wx.ClientDC(self))
        wx.AboutBox(info)

    def showError(self, msg):
        """show dialog with error message"""
        self._log.error(" ".join(msg.split()))
        self.statusbar.SetStatusText(msg)
        dlg = wx.MessageDialog(self,
                               message=msg,
                               caption="Error",
                               style=wx.OK | wx.ICON_ERROR)
        dlg.ShowModal()
        dlg.Destroy()

    def showHeaders(self, event=None):
        """display image headers in popup dialog"""
        if not self.rgbeImg:
            return
        header = self.rgbeImg.getHeader()
        if header == False:
            self.showError("Image header not available!")
            return
        header2 = self.rgbeImg.getDataHeader()
        if header2 and header != header2:
            header += "\n\nmodified:\n"
            header += header2

        ## create new dialog window
        dlg = HeaderDialog(self, header)
        dlg.Show()

    def showPixelValueAt(self, pos):
        """set pixel position of mouse cursor"""
        value = ""
        if self.rgbeImg:
            r, g, b, v = self.rgbeImg.getRGBVAt(pos)
            if r > 0:
                value = "rgb=(%.3f,%.3f,%.3f)" % (r, g, b)
                if v > 0 and self.rgbeImg.isIrridiance():
                    value = "%s  value=%s lux" % (value, self.formatNumber(v))
            self.statusbar.SetStatusText(
                "'%s':   x,y=(%d,%d)   %s" %
                (self.filename, pos[0], pos[1], value))
Example #7
0
 def test_doPcond(self):
     img = RGBEImage(wxparent, log)
     img._doPcommand = mock.MagicMock()
     args = ['a', 2]
     img.doPcond(args)
     img._doPcommand.assert_called_with("pcond", args)
Example #8
0
 def test_doFalsecolor(self, fci_mock):
     fci_mock.return_value = True
     img = RGBEImage(wxparent, log)
     result = img.doFalsecolor()
     self.assertTrue(result)