Exemple #1
0
 def OnAddFiles(self, filenames):
     for file in filenames:
         file_stat = os.stat(file)
         mtime = file_stat.st_mtime
         if self._raw_image:
             targetfilename = self.get_media_name_from_filename(file)
             data = open(file, 'rb').read()
             self.AddToIndex(targetfilename, self.active_section, data,
                             self._data, mtime)
         else:
             # :::TODO:: do i need to handle bci specially here?
             # The proper way to handle custom image types, e.g. BCI and LGBIT,
             # is to add a wx.ImageHandler for it. Unfortunately wx.Image_AddHandler
             # is broken in the current wxPython, so . . .
             fi = self.GetFileInfo(file)
             if fi is not None and fi.format == 'LGBIT':
                 img = conversions.convertfilelgbittobmp(file)
             elif fi and fi.format == '3GPP2':
                 # 3g2 video file, no scaling, just add
                 targetfilename = self.get_media_name_from_filename(file)
                 data = open(file, 'rb').read()
                 self.AddToIndex(targetfilename, self.active_section, data,
                                 self._data, mtime)
                 continue
             else:
                 img = wx.Image(file)
             if not img.Ok():
                 guihelper.MessageDialog(
                     self,
                     "Failed to understand the image in '" + file + "'",
                     "Image not understood",
                     style=wx.OK | wx.ICON_ERROR)
                 continue
             self.OnAddImage(img, file, refresh=False, timestamp=mtime)
     self.OnRefresh()
 def ReplaceContents(self, name, origin, new_file_name):
     """Replace the contents of 'file_name' by the contents of
     'new_file_name' by going through the image converter dialog
     """
     fi=self.GetFileInfo(new_file_name)
     if fi is not None and fi.format=='LGBIT':
         img=conversions.convertfilelgbittobmp(new_file_name)
     else:
         img=wx.Image(new_file_name)
     if not img.Ok():
         dlg=wx.MessageDialog(self, "Failed to understand the image in '"+new_file_name+"'",
                             "Image not understood", style=wx.OK|wx.ICON_ERROR)
         dlg.ShowModal()
         dlg.Destroy()
         return
     dlg=ImagePreviewDialog(self, img, self.mainwindow.phoneprofile, self.active_section)
     if dlg.ShowModal()!=wx.ID_OK:
         dlg.Destroy()
         return
     img=dlg.GetResultImage()
     imgparams=dlg.GetResultParams()
     dlg.Destroy()
     extension={'BMP': 'bmp', 'JPEG': 'jpg', 'PNG': 'png'}[imgparams['format']]
     res=getattr(self, "saveimage_"+imgparams['format'])(img, imgparams)
     if not res:
         dlg=wx.MessageDialog(self, "Failed to convert the image in '"+new_file_name+"'",
                             "Image not converted", style=wx.OK|wx.ICON_ERROR)
         dlg.ShowModal()
         dlg.Destroy()
     self.AddToIndex(name, origin, res, self._data)
Exemple #3
0
    def ReplaceContents(self, name, origin, new_file_name):
        """Replace the contents of 'file_name' by the contents of
        'new_file_name' by going through the image converter dialog
        """
        fi=self.GetFileInfo(new_file_name)
        if fi is not None and fi.format=='LGBIT':
            img=conversions.convertfilelgbittobmp(new_file_name)
        else:
            img=wx.Image(new_file_name)
        if not img.Ok():
            guihelper.MessageDialog(self, "Failed to understand the image in '"+new_file_name+"'",
                                    "Image not understood", style=wx.OK|wx.ICON_ERROR)
            return
        with guihelper.WXDialogWrapper(ImagePreviewDialog(self, img, self.mainwindow.phoneprofile, self.active_section),
                                       True) as (dlg, retcode):
            if retcode==wx.ID_OK:
                img=dlg.GetResultImage()
                imgparams=dlg.GetResultParams()
                # ::TODO:: temporary hack - this should really be an imgparam
                extension={'BMP': 'bmp', 'JPEG': 'jpg', 'PNG': 'png'}[imgparams['format']]

                res=getattr(self, "saveimage_"+imgparams['format'])(img, imgparams)
                if not res:
                    guihelper.MessageDialog(self, "Failed to convert the image in '"+new_file_name+"'",
                                            "Image not converted", style=wx.OK|wx.ICON_ERROR)
                self.AddToIndex(name, origin, res, self._data)
Exemple #4
0
 def OnAddFiles(self, filenames):
     for file in filenames:
         file_stat=os.stat(file)
         mtime=file_stat.st_mtime
         if self._raw_image:
             targetfilename=self.get_media_name_from_filename(file)
             data=open(file, 'rb').read()
             self.AddToIndex(targetfilename, self.active_section, data, self._data, mtime)
         else:
             # :::TODO:: do i need to handle bci specially here?
             # The proper way to handle custom image types, e.g. BCI and LGBIT,
             # is to add a wx.ImageHandler for it. Unfortunately wx.Image_AddHandler
             # is broken in the current wxPython, so . . .
             fi=self.GetFileInfo(file)
             if fi is not None and fi.format=='LGBIT':
                 img=conversions.convertfilelgbittobmp(file)
             elif fi and fi.format=='3GPP2':
                 # 3g2 video file, no scaling, just add
                 targetfilename=self.get_media_name_from_filename(file)
                 data=open(file, 'rb').read()
                 self.AddToIndex(targetfilename, self.active_section, data, self._data, mtime)
                 continue
             else:
                 img=wx.Image(file)
             if not img.Ok():
                 guihelper.MessageDialog(self, "Failed to understand the image in '"+file+"'",
                                         "Image not understood", style=wx.OK|wx.ICON_ERROR)
                 continue
             self.OnAddImage(img,file,refresh=False, timestamp=mtime)
     self.OnRefresh()
 def OnAddFiles(self, filenames):
     for file in filenames:
         if self._raw_image:
             decoded_file=self.decodefilename(file)
             targetfilename=self.getshortenedbasename(decoded_file)
             open(targetfilename, 'wb').write(open(file, 'rb').read())
             self.AddToIndex(str(os.path.basename(targetfilename)).decode(guiwidgets.media_codec),
                             'images')
         else:
             fi=self.GetFileInfo(file)
             if fi is not None and fi.format=='LGBIT':
                 img=conversions.convertfilelgbittobmp(file)
             else:
                 img=wx.Image(file)
             if not img.Ok():
                 dlg=wx.MessageDialog(self, "Failed to understand the image in '"+file+"'",
                                     "Image not understood", style=wx.OK|wx.ICON_ERROR)
                 dlg.ShowModal()
                 continue
             self.OnAddImage(img,file,refresh=False)
     self.OnRefresh()
 def OnAddFiles(self, filenames):
     for file in filenames:
         file_stat=os.stat(file)
         mtime=file_stat.st_mtime
         if self._raw_image:
             targetfilename=self.get_media_name_from_filename(file)
             data=open(file, 'rb').read()
             self.AddToIndex(targetfilename, self.active_section, data, self._data, mtime)
         else:
             fi=self.GetFileInfo(file)
             if fi is not None and fi.format=='LGBIT':
                 img=conversions.convertfilelgbittobmp(file)
             else:
                 img=wx.Image(file)
             if not img.Ok():
                 dlg=wx.MessageDialog(self, "Failed to understand the image in '"+file+"'",
                                     "Image not understood", style=wx.OK|wx.ICON_ERROR)
                 dlg.ShowModal()
                 continue
             self.OnAddImage(img,file,refresh=False, timestamp=mtime)
     self.OnRefresh()
	def OnAddFiles(self, filenames):

        for file in filenames:

            if self._raw_image:

                decoded_file=self.decodefilename(file)

                targetfilename=self.getshortenedbasename(decoded_file)

                open(targetfilename, 'wb').write(open(file, 'rb').read())

                self.AddToIndex(str(os.path.basename(targetfilename)).decode(fileview.media_codec),
                                'images')

            else:

                fi=self.GetFileInfo(file)

                if fi is not None and fi.format=='LGBIT':

                    img=conversions.convertfilelgbittobmp(file)

                else:

                    img=wx.Image(file)

                if not img.Ok():

                    dlg=wx.MessageDialog(self, "Failed to understand the image in '"+file+"'",
                                        "Image not understood", style=wx.OK|wx.ICON_ERROR)

                    dlg.ShowModal()

                    continue

                self.OnAddImage(img,file,refresh=False)

        self.OnRefresh()

	def OnAddImage(self, img, file, refresh=True):

        dlg=ImagePreviewDialog(self, img, file, self.mainwindow.phoneprofile)

        if dlg.ShowModal()!=wx.ID_OK:

            dlg.Destroy()

            return

        img=dlg.GetResultImage()

        imgparams=dlg.GetResultParams()

        origin=dlg.GetResultOrigin()

        extension={'BMP': 'bmp', 'JPEG': 'jpg', 'PNG': 'png'}[imgparams['format']]

        decoded_file=self.decodefilename(file)

        targetfilename=self.getshortenedbasename(decoded_file, extension)

        res=getattr(self, "saveimage_"+imgparams['format'])(
            img,
            targetfilename, imgparams)

        if not res:

            try:    os.remove(targetfilename)

            except: pass

            dlg=wx.MessageDialog(self, "Failed to convert the image in '"+file+"'",
                                "Image not converted", style=wx.OK|wx.ICON_ERROR)

            dlg.ShowModal()

            return

        self.AddToIndex(str(os.path.basename(targetfilename)).decode(fileview.media_codec), origin)

        if refresh:

            self.OnRefresh()

	def saveimage_BMP(self, img, targetfilename, imgparams):

        if img.ComputeHistogram(wx.ImageHistogram())<=236: 

            img.SetOptionInt(wx.IMAGE_OPTION_BMP_FORMAT, wx.BMP_8BPP)

        return img.SaveFile(targetfilename, wx.BITMAP_TYPE_BMP)

	def saveimage_JPEG(self, img, targetfilename, imgparams):

        img.SetOptionInt("quality", 100)        

        return img.SaveFile(targetfilename, wx.BITMAP_TYPE_JPEG)

	def saveimage_PNG(self, img, targetfilename, imgparams):

        return img.SaveFile(targetfilename, wx.BITMAP_TYPE_PNG)

	def populatefs(self, dict):

        self.thedir=self.mainwindow.wallpaperpath

        return self.genericpopulatefs(dict, 'wallpapers', 'wallpaper-index', self.CURRENTFILEVERSION)

	def getfromfs(self, result):

        self.thedir=self.mainwindow.wallpaperpath

        return self.genericgetfromfs(result, None, 'wallpaper-index', self.CURRENTFILEVERSION)

	def versionupgrade(self, dict, version):

        """Upgrade old data format read from disk
        @param dict:  The dict that was read in
        @param version: version number of the data on disk
        """

        if version==0:

            version=1  

        if version==1:

            print "converting to version 2"

            version=2

            d={}

            input=dict.get('wallpaper-index', {})

            for i in input:

                d[i]={'name': input[i]}

            dict['wallpaper-index']=d

        return dict

	def getdata(self,dict,want=fileview.FileView.NONE):

        return self.genericgetdata(dict, want, self.mainwindow.wallpaperpath, 'wallpapers', 'wallpaper-index')

    

class  WallpaperPreview (wx.PyWindow) :
	def __init__(self, parent, image=None, id=1, size=wx.DefaultSize, pos=wx.DefaultPosition, style=0):

        wx.PyWindow.__init__(self, parent, id=id, size=size, pos=pos, style=style|wx.FULL_REPAINT_ON_RESIZE)

        self.bg=wx.Brush(parent.GetBackgroundColour())

        self._bufbmp=None

        wx.EVT_ERASE_BACKGROUND(self, lambda evt: None)

        wx.EVT_PAINT(self, self.OnPaint)

        self.SetImage(image)

	def SetImage(self, name):

        if name is None:

            self.theimage=None

        else:

            self.theimage, _=thewallpapermanager.GetImage(name)

        self.thesizedbitmap=None

        self.Refresh(False)

	def OnPaint(self, _):

        sz=self.GetClientSize()

        if self._bufbmp is None or sz.width>self._bufbmp.GetWidth() or sz.height>self._bufbmp.GetHeight():

            self._bufbmp=wx.EmptyBitmap((sz.width+64)&~8, (sz.height+64)&~8)

        dc=wx.BufferedPaintDC(self, self._bufbmp, style=wx.BUFFER_VIRTUAL_AREA)

        dc.SetBackground(self.bg)

        dc.Clear()

        if self.theimage is None: return

        sfactorw=float(sz.width)/self.theimage.GetWidth()

        sfactorh=float(sz.height)/self.theimage.GetHeight()

        sfactor=min(sfactorw,sfactorh)

        newwidth=int(self.theimage.GetWidth()*sfactor)

        newheight=int(self.theimage.GetHeight()*sfactor)

        if self.thesizedbitmap is None or self.thesizedbitmap.GetWidth()!=newwidth or \
           self.thesizedbitmap.GetHeight()!=newheight:

            self.thesizedbitmap=self.theimage.Scale(newwidth, newheight).ConvertToBitmap()

        dc.DrawBitmap(self.thesizedbitmap, sz.width/2-newwidth/2, sz.height/2-newheight/2, True)


def ScaleImageIntoBitmap(img, usewidth, useheight, bgcolor=None, valign="center"):

    """Scales the image and returns a bitmap
    @param usewidth: the width of the new image
    @param useheight: the height of the new image
    @param bgcolor: the background colour as a string ("ff0000" is red etc).  If this
                    is none then the background is made transparent"""

    if bgcolor is None:

        bitmap=wx.EmptyBitmap(usewidth, useheight, 24) 

    else:

        bitmap=wx.EmptyBitmap(usewidth, useheight)

    mdc=wx.MemoryDC()

    mdc.SelectObject(bitmap)

    sfactorw=usewidth*1.0/img.GetWidth()

    sfactorh=useheight*1.0/img.GetHeight()

    sfactor=min(sfactorw,sfactorh) 

    newwidth=int(img.GetWidth()*sfactor/1.0)

    newheight=int(img.GetHeight()*sfactor/1.0)

    img.Rescale(newwidth, newheight)

    if bgcolor is not None:

        transparent=None

        assert len(bgcolor)==6

        red=int(bgcolor[0:2],16)

        green=int(bgcolor[2:4],16)

        blue=int(bgcolor[4:6],16)

        mdc.SetBackground(wx.TheBrushList.FindOrCreateBrush(wx.Colour(red,green,blue), wx.SOLID))

    else:

        transparent=wx.Colour(*(img.FindFirstUnusedColour()[1:]))

        mdc.SetBackground(wx.TheBrushList.FindOrCreateBrush(transparent, wx.SOLID))

    mdc.Clear()

    mdc.SelectObject(bitmap)

    posx=usewidth-(usewidth+newwidth)/2

    if valign in ("top", "clip"):

        posy=0

    elif valign=="center":

        posy=useheight-(useheight+newheight)/2

    else:

        assert False, "bad valign "+valign

        posy=0

    mdc.DrawBitmap(img.ConvertToBitmap(), posx, posy, True)

    mdc.SelectObject(wx.NullBitmap)

    if transparent is not None:

            mask=wx.Mask(bitmap, transparent)

            bitmap.SetMask(mask)

    if valign=="clip" and newheight!=useheight:

        return bitmap.GetSubBitmap( (0,0,usewidth,newheight) )

    return bitmap

statinfo=common.statinfo

class  BPFSHandler (wx.FileSystemHandler) :
	CACHELOWWATER=80
	    CACHEHIGHWATER=100
	    def __init__(self, wallpapermanager):

        wx.FileSystemHandler.__init__(self)

        self.wpm=wallpapermanager

        self.cache={}

	def _GetCache(self, location, statinfo):

        """Return the cached item, or None
        Note that the location value includes the filename and the parameters such as width/height
        """

        if statinfo is None:

            print "bad location",location

            return None

        return self.cache.get( (location, statinfo), None)

	def _AddCache(self, location, statinfo, value):

        "Add the item to the cache"

        if len(self.cache)>=self.CACHEHIGHWATER:

            print "BPFSHandler cache flush"

            while len(self.cache)>self.CACHELOWWATER:

                del self.cache[random.choice(self.cache.keys())]

        self.cache[(location, statinfo)]=value

	def CanOpen(self, location):

        if location.startswith("/"):

            return False

        proto=self.GetProtocol(location)

        if proto=="bpimage" or proto=="bpuserimage":

            return True

        return False

	def OpenFile(self,filesystem,location):

        try:

            res=self._OpenFile(filesystem,location)

        except:

            res=None

            print "Exception in getting image file - you can't do that!"

            print common.formatexception()

        if res is not None:

            res[0].seek(0)

            args=(wx.InputStream(res[0]),)+res[1:]

            res=wx.FSFile(*args)

        return res

	def _OpenFile(self, filesystem, location):

        proto=self.GetProtocol(location)

        r=self.GetRightLocation(location)

        params=r.split(';')

        r=params[0]

        params=params[1:]

        p={}

        for param in params:

            x=param.find('=')

            key=str(param[:x])

            value=param[x+1:]

            if key=='width' or key=='height':

                p[key]=int(value)

            else:

                p[key]=value

        if proto=="bpimage":

            return self.OpenBPImageFile(location, r, **p)

        elif proto=="bpuserimage":

            return self.OpenBPUserImageFile(location, r, **p)

        return None

	def OpenBPUserImageFile(self, location, name, **kwargs):

        si=self.wpm.GetImageStatInformation(name)

        res=self._GetCache(location, si)

        if res is not None: return res

        file,cons=self.wpm.GetImageConstructionInformation(name)

        if cons == wx.Image:

            res=BPFSImageFile(self, location, file, **kwargs)

        else:

            res=BPFSImageFile(self, location, img=cons(file), **kwargs)

        self._AddCache(location, si, res)

        return res

	def OpenBPImageFile(self, location, name, **kwargs):

        f=guihelper.getresourcefile(name)

        if not os.path.isfile(f):

            print f,"doesn't exist"

            return None

        si=statinfo(f)

        res=self._GetCache(location, si)

        if res is not None: return res

        res=BPFSImageFile(self, location, name=f, **kwargs)

        self._AddCache(location, si, res)

        return res


def BPFSImageFile(fshandler, location, name=None, img=None, width=-1, height=-1, valign="center", bgcolor=None):

    """Handles image files
    If we have to do any conversion on the file then we return PNG
    data.  This used to be a class derived from wx.FSFile, but due to
    various wxPython bugs it instead returns the parameters to make a
    wx.FSFile since a new one has to be made every time.
    """

    if img is None and width<0 and height<0:

        mime=guihelper.getwxmimetype(name)

        if mime not in (None, "image/x-bmp"):

            return (open(name, "rb"), location, mime, "", wx.DateTime_Now())

    if img is None:

        img=wx.Image(name)

    if width>0 and height>0:

        b=ScaleImageIntoBitmap(img, width, height, bgcolor, valign)

    else:

        b=img.ConvertToBitmap()

    f=common.gettempfilename("png")

    if not b.SaveFile(f, wx.BITMAP_TYPE_PNG):

        raise Exception, "Saving to png failed"

    data=open(f, "rb").read()

    os.remove(f)

    return (cStringIO.StringIO(data), location, "image/png", "", wx.DateTime_Now())

class  ImageCropSelect (wx.ScrolledWindow) :
	def __init__(self, parent, image, previewwindow=None, id=1, resultsize=(100,100), size=wx.DefaultSize, pos=wx.DefaultPosition, style=0):

        wx.ScrolledWindow.__init__(self, parent, id=id, size=size, pos=pos, style=style|wx.FULL_REPAINT_ON_RESIZE)

        self.previewwindow=previewwindow

        self.bg=wx.Brush(wx.WHITE)

        self.parentbg=wx.Brush(parent.GetBackgroundColour())

        self._bufbmp=None

        self.anchors=None

        wx.EVT_ERASE_BACKGROUND(self, lambda evt: None)

        wx.EVT_PAINT(self, self.OnPaint)

        self.image=image

        self.origimage=image

        self.setresultsize(resultsize)

        self.cursors=[wx.StockCursor(c) for c in (wx.CURSOR_ARROW, wx.CURSOR_HAND, wx.CURSOR_SIZING, wx.CURSOR_NO_ENTRY)]

        self.clickpoint=None 

        wx.EVT_MOTION(self, self.OnMotion)

        wx.EVT_LEFT_DOWN(self, self.OnLeftDown)

        wx.EVT_LEFT_UP(self, self.OnLeftUp)

	def SetPreviewWindow(self, previewwindow):

        self.previewwindow=previewwindow

	def OnPaint(self, _):

        sz=self.thebmp.GetWidth(), self.thebmp.GetHeight()

        sz2=self.GetClientSize()

        sz=max(sz[0],sz2[0])+32,max(sz[1],sz2[1])+32

        if self._bufbmp is None or self._bufbmp.GetWidth()<sz[0] or self._bufbmp.GetHeight()<sz[1]:

            self._bufbmp=wx.EmptyBitmap((sz[0]+64)&~8, (sz[1]+64)&~8)

        dc=wx.BufferedPaintDC(self, self._bufbmp, style=wx.BUFFER_VIRTUAL_AREA)

        if sz2[0]<sz[0] or sz2[1]<sz[1]:

            dc.SetBackground(self.parentbg)

            dc.Clear()

        dc.DrawBitmap(self.thebmp, 0, 0, False)

        l,t,r,b=self.anchors

        points=(l,t), (r,t), (r,b), (l,b)

        dc.DrawLines( points+(points[0],) )

        for x,y in points:

            dc.DrawRectangle(x-5, y-5, 10, 10)

	OUTSIDE=0
	    INSIDE=1
	    HANDLE_LT=2
	    HANDLE_RT=3
	    HANDLE_RB=4
	    HANDLE_LB=5
	    def _hittest(self, evt):

        l,t,r,b=self.anchors

        within=lambda x,y,l,t,r,b:  l<=x<=r and t<=y<=b

        x,y=self.CalcUnscrolledPosition(evt.GetX(), evt.GetY())

        for i,(ptx,pty) in enumerate(((l,t), (r,t), (r,b), (l,b))):

            if within(x,y,ptx-5, pty-5, ptx+5,pty+5):

                return self.HANDLE_LT+i

        if within(x,y,l,t,r,b):

            return self.INSIDE

        return self.OUTSIDE

	def OnMotion(self, evt):

        if evt.Dragging():

            return self.OnMotionDragging(evt)

        self.UpdateCursor(evt)

	def UpdateCursor(self, evt):

        ht=self._hittest(evt)

        self.SetCursor(self.cursors[min(2,ht)])

	def OnMotionDragging(self, evt):

        if not evt.LeftIsDown() or self.clickpoint is None:

            self.SetCursor(self.cursors[3])

            return

        xx,yy=self.CalcUnscrolledPosition(evt.GetX(), evt.GetY())

        deltax=xx-self.origevtpos[0]

        deltay=yy-self.origevtpos[1]

        if self.clickpoint==self.INSIDE:

            newanchors=self.origanchors[0]+deltax, self.origanchors[1]+deltay, \
                        self.origanchors[2]+deltax, self.origanchors[3]+deltay

            iw=self.dimensions[0]

            ih=self.dimensions[1]

            if newanchors[0]<0:

                newanchors=0,newanchors[1], self.origanchors[2]-self.origanchors[0], newanchors[3]

            if newanchors[1]<0:

                newanchors=newanchors[0], 0, newanchors[2], self.origanchors[3]-self.origanchors[1]

            if newanchors[2]>iw:

                newanchors=iw-(self.origanchors[2]-self.origanchors[0]),newanchors[1],iw, newanchors[3]

            if newanchors[3]>ih:

                newanchors=newanchors[0],ih-(self.origanchors[3]-self.origanchors[1]), newanchors[2],ih

            self.anchors=newanchors

            self.Refresh(False)

            self.updatepreview()

            return

        if self.clickpoint==self.HANDLE_LT:

            aa=0,1,-1,-1

        elif self.clickpoint==self.HANDLE_RT:

            aa=2,1,+1,-1

        elif self.clickpoint==self.HANDLE_RB:

            aa=2,3,+1,+1

        elif self.clickpoint==self.HANDLE_LB:

            aa=0,3,-1,+1

        else:

            assert False, "can't get here"

        na=[self.origanchors[0],self.origanchors[1],self.origanchors[2],self.origanchors[3]]

        na[aa[0]]=na[aa[0]]+deltax

        na[aa[1]]=na[aa[1]]+deltay

        neww=na[2]-na[0]

        newh=na[3]-na[1]

        ar=float(neww)/newh

        if ar<self.aspectratio:

            na[aa[0]]=na[aa[0]]+(self.aspectratio*newh-neww)*aa[2]

        elif ar>self.aspectratio:

            na[aa[1]]=na[aa[1]]+(neww/self.aspectratio-newh)*aa[3]

        if neww<10 or newh<10:

            return

        if na[0]<0:

            xdiff=-na[0]

            ydiff=xdiff/self.aspectratio

            na[0]=0

            na[1]+=ydiff

        if na[1]<0:

            ydiff=-na[1]

            xdiff=ydiff*self.aspectratio

            na[1]=0

            na[0]-=xdiff

        if na[2]>self.dimensions[0]:

            xdiff=na[2]-self.dimensions[0]

            ydiff=xdiff/self.aspectratio

            na[2]=na[2]-xdiff

            na[3]=na[3]-ydiff

        if na[3]>self.dimensions[1]:

            ydiff=na[3]-self.dimensions[1]

            xdiff=ydiff*self.aspectratio

            na[2]=na[2]-xdiff

            na[3]=na[3]-ydiff

        if na[0]<0 or na[1]<0 or na[2]>self.dimensions[0] or na[3]>self.dimensions[1]:

            print "offscreen fixup not written yet"

            return

        self.anchors=na

        self.Refresh(False)

        self.updatepreview()

        return

	def OnLeftDown(self, evt):

        ht=self._hittest(evt)

        if ht==self.OUTSIDE:

            self.SetCursor(self.cursors[3])

            return

        self.clickpoint=ht

        xx,yy=self.CalcUnscrolledPosition(evt.GetX(), evt.GetY())

        self.origevtpos=xx,yy

        self.origanchors=self.anchors

	def OnLeftUp(self, evt):

        self.clickpoint=None

        self.UpdateCursor(evt)

	def setlbcolour(self, colour):

        self.bg=wx.Brush(colour)

        self.remakebitmap()

	def SetZoom(self, factor):

        curzoom=float(self.image.GetWidth())/self.origimage.GetWidth()

        self.anchors=[a*factor/curzoom for a in self.anchors]

        self.image=self.origimage.Scale(self.origimage.GetWidth()*factor, self.origimage.GetHeight()*factor)

        self.setresultsize(self.resultsize)

	def setresultsize(self, (w,h)):

        self.resultsize=w,h

        self.aspectratio=ratio=float(w)/h

        imgratio=float(self.image.GetWidth())/self.image.GetHeight()

        neww=self.image.GetWidth()

        newh=self.image.GetHeight()

        if imgratio<ratio:

            neww*=ratio/imgratio

        elif imgratio>ratio:

            newh*=imgratio/ratio

        neww=max(neww, 50)

        newh=max(newh, 50)

        if self.anchors==None:

            self.anchors=0.1 * neww, 0.1 * newh, 0.9 * neww, 0.9 * newh

        l,t,r,b=self.anchors

        l=min(neww-40, l)

        r=min(neww-10, r)

        if r-l<20: r=40

        t=min(newh-40, t)

        b=min(newh-10, b)

        if b-t<20: b=40

        aratio=float(r-l)/(b-t)

        if aratio<ratio:

            b=t+(r-l)/ratio

        elif aratio>ratio:

            r=l+(b-t)*ratio

        self.anchors=l,t,r,b

        self.dimensions=neww,newh

        self.thebmp=wx.EmptyBitmap(neww, newh)

        self.remakebitmap()

	def remakebitmap(self):

        w,h=self.dimensions

        dc=wx.MemoryDC()

        dc.SelectObject(self.thebmp)

        dc.SetBackground(self.bg)

        dc.Clear()

        dc.DrawBitmap(self.image.ConvertToBitmap(), w/2-self.image.GetWidth()/2, h/2-self.image.GetHeight()/2, True)

        dc.SelectObject(wx.NullBitmap)

        self.imageofthebmp=None

        self.SetVirtualSize( (w, h) )

        self.SetScrollRate(1,1)

        self.updatepreview()

        self.Refresh(False)

	def updatepreview(self):

        if self.previewwindow:

            self.previewwindow.SetUpdated(self.GetPreview)

	def GetPreview(self):

        w,h=self.resultsize

        l,t,r,b=self.anchors

        scale=max(float(w+0.99999)/(r-l), float(h+0.99999)/(b-t))

        if True and scale<1:

            sub=wx.EmptyBitmap(w,h)

            mdcsub=wx.MemoryDC()

            mdcsub.SelectObject(sub)

            mdcsub.SetUserScale(scale, scale)

            mdc=wx.MemoryDC()

            mdc.SelectObject(self.thebmp)

            mdcsub.Blit(0,0,r-l,b-t,mdc,l,t)

            mdc.SelectObject(wx.NullBitmap)

            mdcsub.SelectObject(wx.NullBitmap)

            return sub

        sub=self.thebmp.GetSubBitmap( (l,t,(r-l),(b-t)) )

        sub=sub.ConvertToImage()

        sub.Rescale(w,h)

        return sub.ConvertToBitmap()


class  ImagePreview (wx.PyWindow) :
	def __init__(self, parent):

        wx.PyWindow.__init__(self, parent)

        wx.EVT_ERASE_BACKGROUND(self, lambda evt: None)

        wx.EVT_PAINT(self, self.OnPaint)

        self.bmp=wx.EmptyBitmap(1,1)

        self.updater=None

	def SetUpdated(self, updater):

        self.updater=updater

        self.Refresh(True)

	def OnPaint(self, _):

        if self.updater is not None:

            self.bmp=self.updater()

            self.updater=None

        dc=wx.PaintDC(self)

        dc.DrawBitmap(self.bmp, 0, 0, False)


class  ImagePreviewDialog (wx.Dialog) :
	SCALES=[ (0.25, "1/4"),
             (0.5,  "1/2"),
             (1, "1"),
             (2, "2"),
             (4, "4")]
	    def __init__(self, parent, image, filename, phoneprofile):

        wx.Dialog.__init__(self, parent, -1, "Image Preview", style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.SYSTEM_MENU|wx.MAXIMIZE_BOX|wx.MINIMIZE_BOX)

        self.phoneprofile=phoneprofile

        self.filename=filename

        self.image=image

        vbsouter=wx.BoxSizer(wx.VERTICAL)

        hbs=wx.BoxSizer(wx.HORIZONTAL)

        self.cropselect=ImageCropSelect(self, image)

        vbs=wx.BoxSizer(wx.VERTICAL)

        self.colourselect=wx.lib.colourselect.ColourSelect(self, wx.NewId(), "Background ...", (255,255,255))

        vbs.Add(self.colourselect, 0, wx.ALL|wx.EXPAND, 5)

        wx.lib.colourselect.EVT_COLOURSELECT(self, self.colourselect.GetId(), self.OnBackgroundColour)

        vbs.Add(wx.StaticText(self, -1, "Origin"), 0, wx.ALL, 5)

        self.originbox=wx.ListBox(self, size=(-1, 100))

        vbs.Add(self.originbox, 0, wx.ALL|wx.EXPAND, 5)

        vbs.Add(wx.StaticText(self, -1, "Target"), 0, wx.ALL, 5)

        self.targetbox=wx.ListBox(self, size=(-1,100))

        vbs.Add(self.targetbox, 0, wx.EXPAND|wx.ALL, 5)

        vbs.Add(wx.StaticText(self, -1, "Scale"), 0, wx.ALL, 5)

        for one,(s,_) in enumerate(self.SCALES):

            if s==1: break

        self.slider=wx.Slider(self, -1, one, 0, len(self.SCALES)-1, style=wx.HORIZONTAL|wx.SL_AUTOTICKS)

        wx.EVT_SCROLL(self, self.SetZoom)

        vbs.Add(self.slider, 0, wx.ALL|wx.EXPAND, 5)

        self.zoomlabel=wx.StaticText(self, -1, self.SCALES[one][1])

        vbs.Add(self.zoomlabel, 0, wx.ALL|wx.ALIGN_CENTRE_HORIZONTAL, 5)

        vbs.Add(wx.StaticText(self, -1, "Preview"), 0, wx.ALL, 5)

        self.imagepreview=ImagePreview(self)

        self.cropselect.SetPreviewWindow(self.imagepreview)

        vbs.Add(self.imagepreview, 0, wx.ALL, 5)

        hbs.Add(vbs, 0, wx.ALL, 5)

        hbs.Add(self.cropselect, 1, wx.ALL|wx.EXPAND, 5)

        vbsouter.Add(hbs, 1, wx.EXPAND|wx.ALL, 5)

        vbsouter.Add(wx.StaticLine(self, -1, style=wx.LI_HORIZONTAL), 0, wx.EXPAND|wx.ALL, 5)

        vbsouter.Add(self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.HELP), 0, wx.ALIGN_CENTRE|wx.ALL, 5)

        wx.EVT_LISTBOX(self, self.originbox.GetId(), self.OnOriginSelect)

        wx.EVT_LISTBOX_DCLICK(self, self.originbox.GetId(), self.OnOriginSelect)

        wx.EVT_LISTBOX(self, self.targetbox.GetId(), self.OnTargetSelect)

        wx.EVT_LISTBOX_DCLICK(self, self.targetbox.GetId(), self.OnTargetSelect)

        wx.EVT_BUTTON(self, wx.ID_HELP, lambda _:
                      wx.GetApp().displayhelpid(helpids.ID_DLG_IMAGEPREVIEW))

        self.originbox.Set(phoneprofile.GetImageOrigins().keys())

        self.originbox.SetSelection(0)

        self.OnOriginSelect(None)

        self.SetSizer(vbsouter)

        vbsouter.Fit(self)

        import guiwidgets

        guiwidgets.set_size("wallpaperpreview", self, 80, 1.0)

	def ShowModal(self):

        res=wx.Dialog.ShowModal(self)

        import guiwidgets

        guiwidgets.save_size("wallpaperpreview", self.GetRect())

        return res

	def SetZoom(self, evt):

        self.cropselect.SetZoom(self.SCALES[evt.GetPosition()][0])

        self.zoomlabel.SetLabel(self.SCALES[evt.GetPosition()][1])

        return

	def OnBackgroundColour(self, evt):

        self.cropselect.setlbcolour(evt.GetValue())

	def OnOriginSelect(self, _):

        v=self.originbox.GetStringSelection()

        assert v is not None

        t=self.targetbox.GetStringSelection()

        self.targets=self.phoneprofile.GetTargetsForImageOrigin(v)

        keys=self.targets.keys()

        keys.sort()

        self.targetbox.Set(keys)

        if t in keys:

            self.targetbox.SetSelection(keys.index(t))

        else:

            self.targetbox.SetSelection(0)

        self.OnTargetSelect(None)

	def OnTargetSelect(self, _):

        v=self.targetbox.GetStringSelection()

        print "target is",v

        w,h=self.targets[v]['width'],self.targets[v]['height']

        self.imagepreview.SetSize( (w,h) )

        self.cropselect.setresultsize( (w, h) )

        sz=self.GetSizer()

        if sz is not None:

            sz.Layout()

            self.Refresh(True)

	def GetResultImage(self):

        return self.imagepreview.bmp.ConvertToImage()

	def GetResultParams(self):

        return self.targets[self.targetbox.GetStringSelection()]

	def GetResultOrigin(self):

        return self.originbox.GetStringSelection()


if __name__=='__main__':

    if __debug__:

        def profile(filename, command):

            import hotshot, hotshot.stats, os

            file=os.path.abspath(filename)

            profile=hotshot.Profile(file)

            profile.run(command)

            profile.close()

            del profile

            howmany=100

            stats=hotshot.stats.load(file)

            stats.strip_dirs()

            stats.sort_stats('time', 'calls')

            stats.print_stats(100)

            stats.sort_stats('cum', 'calls')

            stats.print_stats(100)

            stats.sort_stats('calls', 'time')

            stats.print_stats(100)

            sys.exit(0)

    class FakeProfile:

        def GetImageOrigins(self):

            return {"images": {'description': 'General images'},
                    "mms": {'description': 'Multimedia Messages'},
                    "camera": {'description': 'Camera images'}}

        def GetTargetsForImageOrigin(self, origin):

            return {"wallpaper": {'width': 100, 'height': 200, 'description': 'Display as wallpaper'},
                    "photoid": {'width': 100, 'height': 150, 'description': 'Display as photo id'},
                    "outsidelcd": {'width': 90, 'height': 80, 'description': 'Display on outside screen'}}

    def run():

        app=wx.PySimpleApp()

        dlg=ImagePreviewDialog(None, wx.Image("test.jpg"), "foobar.png", FakeProfile())

        dlg.ShowModal()

    if __debug__ and True:

        profile("wp.prof", "run()")

    run()


import fileview

if __name__=='__main__':

    if __debug__:

        def profile(filename, command):

            import hotshot, hotshot.stats, os

            file=os.path.abspath(filename)

            profile=hotshot.Profile(file)

            profile.run(command)

            profile.close()

            del profile

            howmany=100

            stats=hotshot.stats.load(file)

            stats.strip_dirs()

            stats.sort_stats('time', 'calls')

            stats.print_stats(100)

            stats.sort_stats('cum', 'calls')

            stats.print_stats(100)

            stats.sort_stats('calls', 'time')

            stats.print_stats(100)

            sys.exit(0)

    class FakeProfile:

        def GetImageOrigins(self):

            return {"images": {'description': 'General images'},
                    "mms": {'description': 'Multimedia Messages'},
                    "camera": {'description': 'Camera images'}}

        def GetTargetsForImageOrigin(self, origin):

            return {"wallpaper": {'width': 100, 'height': 200, 'description': 'Display as wallpaper'},
                    "photoid": {'width': 100, 'height': 150, 'description': 'Display as photo id'},
                    "outsidelcd": {'width': 90, 'height': 80, 'description': 'Display on outside screen'}}

    def run():

        app=wx.PySimpleApp()

        dlg=ImagePreviewDialog(None, wx.Image("test.jpg"), "foobar.png", FakeProfile())

        dlg.ShowModal()

    if __debug__ and True:

        profile("wp.prof", "run()")

    run()