示例#1
0
文件: figure.py 项目: Cgadal/beampy
    def render(self):
        """
            function to render figures
        """

        # Svg // pdf render
        if self.ext in ('svg', 'pdf', 'eps', 'matplotlib'):
            #Convert pdf to svg
            if self.ext == 'pdf':
                figurein = convert_pdf_to_svg(self.content)
            elif self.ext == 'eps':
                figurein = convert_eps_to_svg(self.content)

            #Convert matplotlib figure to svg
            elif self.ext == 'matplotlib':

                #Store mpl svg to a stringIO object
                with StringIO() as tmpf:
                    self.content.savefig(tmpf,
                                         bbox_inches='tight',
                                         format='svg')
                    tmpf.seek(0)  #go to the biginig of the file

                    #store tmpf content as string in figurein variable
                    figurein = tmpf.read().encode('utf-8')

            #General case for svg format
            else:
                #Check if a filename is given for a svg file or directly read the content value
                if os.path.isfile(self.content):
                    with open(self.content, 'r') as f:
                        figurein = f.read()

                else:
                    figurein = self.content

            #test if we need to optimise the svg
            if document._optimize_svg:
                figurein = optimize_svg(figurein)

            soup = BeautifulSoup(figurein, 'xml')

            #Change id in svg defs to use the global id system
            soup = make_global_svg_defs(soup)

            #Optimize the size of embeded svg images !
            if document._resize_raster:
                imgs = soup.findAll('image')
                if imgs:
                    for img in imgs:

                        #True width and height of embed svg image
                        width, height = int(float(img['width'])), int(
                            float(img['height']))
                        img_ratio = height / float(width)
                        b64content = img['xlink:href']

                        try:
                            in_img = BytesIO(
                                base64.b64decode(
                                    b64content.split(';base64,')[1]))
                            tmp_img = Image.open(in_img)
                            #print(tmp_img)
                            out_img = resize_raster_image(
                                tmp_img,
                                max_width=self.positionner.width.value)
                            out_b64 = base64.b64encode(
                                out_img.read()).decode('utf8')

                            #replace the resized image into the svg
                            img['xlink:href'] = 'data:image/%s;base64, %s' % (
                                tmp_img.format.lower(), out_b64)
                        except:
                            print('Unable to reduce the image size')
                            pass

            svgtag = soup.find('svg')

            svg_viewbox = svgtag.get("viewBox")

            tmph = svgtag.get("height")
            tmpw = svgtag.get("width")
            if tmph is None or tmpw is None:
                with tempfile.NamedTemporaryFile(mode='w',
                                                 prefix='beampytmp',
                                                 suffix='.svg') as f:
                    try:
                        f.write(figurein)
                    except Exception as e:
                        #python 2
                        f.write(figurein.encode('utf8'))

                    # force to write file content to disk
                    f.file.flush()

                    # get svg size using inkscape
                    tmph = getsvgheight(f.name)
                    tmpw = getsvgwidth(f.name)

            svgheight = convert_unit(tmph)
            svgwidth = convert_unit(tmpw)

            if svg_viewbox is not None:
                svgheight = svg_viewbox.split(' ')[3]
                svgwidth = svg_viewbox.split(' ')[2]

            # BS4 get the svg tag content without <svg> and </svg>
            tmpfig = svgtag.renderContents().decode('utf8')

            # Scale the figure according to the given width
            if self.width.value is not None and self.height.value is None:
                # SCALE OK need to keep the original viewBox !!!
                scale = (self.positionner.width / float(svgwidth)).value
                figure_height = float(svgheight) * scale
                figure_width = self.positionner.width.value

            # Scale the figure according to the given height
            if self.height.value is not None and self.width.value is None:
                figure_height = self.positionner.height.value
                scale = (self.positionner.height / float(svgheight)).value
                figure_width = float(svgwidth) * scale

            # Dont scale the figure let the user fix the width height
            if self.height.value is not None and self.width.value is not None:
                output = tmpfig
                figure_height = self.positionner.height.value
                figure_width = self.positionner.width.value
            else:
                # Apply the scaling to the figure
                tmphead = '\n<g transform="scale(%0.5f)">' % (scale)
                output = tmphead + tmpfig + '</g>\n'

            #Update the final svg size
            self.update_size(figure_width, figure_height)
            #Add the final svg output of the figure
            self.svgout = output

        #Bokeh images
        if self.ext == 'bokeh':

            # Change the sizing mode (need scale_both) to adapt size of the figure
            self.content.sizing_mode = 'scale_both'
            # Run the bokeh components function to separate figure html div and js script
            figscript, figdiv = components(self.content, wrap_script=False)

            # Transform figscript to givea function name load_bokehjs
            tmp = figscript.splitlines()
            goodscript = '\n'.join(['["load_bokeh"] = function() {'] +
                                   tmp[1:-1] + ['};\n'])

            #Add the htmldiv to htmlout
            self.htmlout = "<div id='bk_resizer' width='{width}px' height='{height}px' style='width: {width}px; height: {height}px; transform-origin: left top 0px;'> {html} </div>"
            self.htmlout = self.htmlout.format(width=self.positionner.width,
                                               height=self.positionner.height,
                                               html=figdiv)

            #Add the script to scriptout
            self.jsout = goodscript

        #For the other format
        if self.ext in ('png', 'jpeg', 'gif'):
            #Open image with PIL to compute size
            tmp_img = Image.open(self.content)
            _, _, tmpwidth, tmpheight = tmp_img.getbbox()

            # Scale the figure according to the given width
            if self.width.value is not None and self.height.value is None:
                # SCALE OK need to keep the original viewBox !!!
                scale = (self.positionner.width / float(tmpwidth)).value
                figure_height = float(tmpheight) * scale
                figure_width = self.positionner.width.value

            # Scale the figure according to the given height
            if self.height.value is not None and self.width.value is None:
                figure_height = self.positionner.height.value
                scale = (self.positionner.height / float(tmpheight)).value
                figure_width = float(tmpwidth) * scale

            # Dont scale the figure let the user fix the width height
            if self.height.value is not None and self.width.value is not None:
                figure_height = self.positionner.height.value
                figure_width = self.positionner.width.value

            if document._resize_raster:
                #Rescale figure to the good size (to improve size and display speed)
                if self.ext == 'gif':
                    print('Gif are not resized, the original size is taken!')
                    with open(self.content, "rb") as f:
                        figurein = base64.b64encode(f.read()).decode('utf8')

                else:
                    out_img = resize_raster_image(tmp_img,
                                                  max_width=figure_width)
                    figurein = base64.b64encode(out_img.read()).decode('utf8')
                    out_img.close()
            else:
                with open(self.content, "rb") as f:
                    figurein = base64.b64encode(f.read()).decode('utf8')

            tmp_img.close()

            if self.ext == 'png':
                output = '<image x="0" y="0" width="%s" height="%s" xlink:href="data:image/png;base64, %s" />' % (
                    figure_width, figure_height, figurein)

            if self.ext == 'jpeg':
                output = '<image x="0" y="0" width="%s" height="%s" xlink:href="data:image/jpg;base64, %s" />' % (
                    figure_width, figure_height, figurein)

            if self.ext == 'gif':
                output = '<image x="0" y="0" width="%s" height="%s" xlink:href="data:image/gif;base64, %s" />' % (
                    figure_width, figure_height, figurein)

            # Update the final size of the figure
            self.update_size(figure_width, figure_height)
            # Add the final svg to svgout
            self.svgout = output

        #print self.width, self.height
        #Update the rendered state of the module
        self.rendered = True
示例#2
0
文件: figure.py 项目: hchauvet/beampy
    def render(self):
        """
            function to render figures
        """


        #Svg // pdf render
        if self.ext in ('svg', 'pdf') :
            #Convert pdf to svg
            if self.ext == 'pdf' :
                figurein = convert_pdf_to_svg( self.content )
            else:
                #Check if a filename is given for a svg file or directly read the content value
                if os.path.isfile(self.content):
                    with open(self.content) as f:
                        figurein = f.read()
                else:
                    figurein = self.content

            #test if we need to optimise the svg
            if document._optimize_svg:
                figurein = optimize_svg(figurein)

            soup = BeautifulSoup(figurein, 'xml')

            #Change id in svg defs to use the global id system
            soup = make_global_svg_defs(soup)

            #Optimize the size of embeded svg images !
            if document._resize_raster:
                imgs = soup.findAll('image')
                if imgs:
                    for img in imgs:

                        #True width and height of embed svg image
                        width, height = int( float(img['width']) ) , int( float(img['height']) )
                        img_ratio = height/float(width)
                        b64content = img['xlink:href']

                        try:
                            in_img =  BytesIO( base64.b64decode(b64content.split(';base64,')[1]) )
                            tmp_img = Image.open(in_img)
                            #print(tmp_img)
                            out_img = resize_raster_image( tmp_img )
                            out_b64 = base64.b64encode( out_img.read() )

                            #replace the resized image into the svg
                            img['xlink:href'] = 'data:image/%s;base64, %s'%(tmp_img.format.lower(), out_b64)
                        except:
                            print('Unable to reduce the image size')
                            pass

            svgtag = soup.find('svg')

            svg_viewbox = svgtag.get("viewBox")

            tmph = svgtag.get("height")
            tmpw = svgtag.get("width")
            if tmph == None or tmpw == None:
                fmpf, tmpname = tempfile.mkstemp(prefix="beampytmp")
                with open( tmpname+'.svg', 'w' ) as f:
                    f.write(figurein)
                    #print figurein
                tmph = getsvgheight( tmpname+'.svg' )
                tmpw = getsvgwidth( tmpname+'.svg' )
                #print tmpw, tmph
                os.remove(tmpname+'.svg')


            svgheight = convert_unit( tmph )
            svgwidth = convert_unit( tmpw )

            if svg_viewbox != None:
                svgheight = svg_viewbox.split(' ')[3]
                svgwidth = svg_viewbox.split(' ')[2]

            #SCALE OK need to keep the original viewBox !!!
            scale_x = self.positionner.width/float(svgwidth)
            #print svgwidth, svgheight, scale_x
            #scale_y = float(convert_unit(args['height']))/float(svgheight)
            good_scale = scale_x

            #BS4 get the svg tag content without <svg> and </svg>
            tmpfig = svgtag.renderContents()

            #Add the correct first line and last
            tmphead = '\n<g transform="scale(%0.5f)">'%(good_scale)
            output = tmphead + tmpfig + '</g>\n'

            figure_height = float(svgheight)*good_scale
            figure_width = self.width

            #Update the final svg size
            self.update_size(figure_width, figure_height)
            #Add the final svg output of the figure
            self.svgout = output

        #Bokeh images
        if self.ext == 'bokeh':

            #Run the bokeh components function to separate figure html div and js script
            figscript, figdiv = components(self.content, wrap_script=False)

            #Transform figscript to givea function name load_bokehjs
            tmp = figscript.splitlines()
            goodscript = '\n'.join( ['["load_bokeh"] = function() {'] + tmp[1:-1] + ['};\n'] )

            #Add the htmldiv to htmlout
            self.htmlout = figdiv
            #Add the script to scriptout
            self.jsout = goodscript

        #For the other format
        if self.ext in ('png', 'jpeg'):
            #Open image with PIL to compute size
            tmp_img = Image.open(self.content)
            _,_,tmpwidth,tmpheight = tmp_img.getbbox()
            scale_x = self.positionner.width/float(tmpwidth)
            figure_height = float(tmpheight) * scale_x
            figure_width = self.positionner.width

            if document._resize_raster:
                #Rescale figure to the good size (to improve size and display speed)
                out_img = resize_raster_image(tmp_img)
                figurein = base64.b64encode(out_img.read())
                out_img.close()
            else:
                with open( self.content, "r") as f:
                    figurein = base64.b64encode(f.read())

            tmp_img.close()

            if self.ext == 'png':
                output = '<image x="0" y="0" width="%s" height="%s" xlink:href="data:image/png;base64, %s" />'%(figure_width, figure_height, figurein)

            if self.ext == 'jpeg':
                output = '<image x="0" y="0" width="%s" height="%s" xlink:href="data:image/jpg;base64, %s" />'%(figure_width, figure_height, figurein)

            #Update the final size of the figure
            self.update_size(figure_width, figure_height)
            #Add the final svg to svgout
            self.svgout = output

        #print self.width, self.height
        #Update the rendered state of the module
        self.rendered = True
示例#3
0
def render_figure( ct ):

    """
        function to render figures
    """

    #read args in the dict
    args = ct['args']

    #Svg // pdf render
    if args['ext'] in ('svg', 'pdf') :

        #Convert pdf to svg
        if args['ext'] == 'pdf' :
            figurein = convert_pdf_to_svg( args['filename'] )
        else:
            #Check if a filename is given for a svg file or directly read the content value
            if 'filename' in args:
                with open(args['filename']) as f:
                    figurein = f.read()
            else:
                figurein = ct['content']

        #test if we need to optimise the svg
        if document._optimize_svg:
            figurein = optimize_svg(figurein)

        soup = BeautifulSoup(figurein, 'xml')

        #Change id in svg defs to use the global id system
        soup = make_global_svg_defs(soup)

        #Optimize the size of embeded svg images !
        if document._resize_raster:
            imgs = soup.findAll('image')
            if imgs:
                for img in imgs:
                    #True width and height of embed svg image
                    width, height = int( float(img['width']) ) , int( float(img['height']) )
                    img_ratio = height/float(width)
                    b64content = img['xlink:href']

                    try:
                        in_img =  BytesIO( base64.b64decode(b64content.split(';base64,')[1]) )
                        tmp_img = Image.open(in_img)
                        #print(tmp_img)
                        out_img = resize_raster_image( tmp_img )
                        out_b64 = base64.b64encode( out_img.read() )

                        #replace the resized image into the svg
                        img['xlink:href'] = 'data:image/%s;base64, %s'%(tmp_img.format.lower(), out_b64)
                    except:
                        print('Unable to reduce the image size')
                        pass

        svgtag = soup.find('svg')

        svg_viewbox = svgtag.get("viewBox")

        tmph = svgtag.get("height")
        tmpw = svgtag.get("width")
        if tmph == None or tmpw == None:
            fmpf, tmpname = tempfile.mkstemp(prefix="beampytmp")
            with open( tmpname+'.svg', 'w' ) as f:
                f.write(figurein)
                #print figurein
            tmph = getsvgheight( tmpname+'.svg' )
            tmpw = getsvgwidth( tmpname+'.svg' )
            #print tmpw, tmph
            os.remove(tmpname+'.svg')


        svgheight = convert_unit( tmph )
        svgwidth = convert_unit( tmpw )

        if svg_viewbox != None:
            svgheight = svg_viewbox.split(' ')[3]
            svgwidth = svg_viewbox.split(' ')[2]

        #SCALE OK need to keep the original viewBox !!!
        scale_x = ct['positionner'].width/float(svgwidth)
        #print svgwidth, svgheight, scale_x
        #scale_y = float(convert_unit(args['height']))/float(svgheight)
        good_scale = scale_x

        #BS4 get the svg tag content without <svg> and </svg>
        tmpfig = svgtag.renderContents()

        #print tmpfig[:100]

        #Add the correct first line and last
        #tmphead = '<g  transform="matrix(%s,0,0,%s,%s,%s)" viewBox="%s">'%(str(good_scale), str(good_scale), convert_unit(args['x']), convert_unit(args['y']), svg_viewbox))
        tmphead = '\n<g transform="scale(%0.5f)">'%(good_scale)
        output = tmphead + tmpfig + '</g>\n'

        figure_height = float(svgheight)*good_scale
        figure_width = ct['positionner'].width

    #Bokeh images
    if args['ext'] == 'bokeh':
        figurein = ct['content']
        figure_height = ct['positionner'].height
        figure_width =  ct['positionner'].width
        output = """%s"""%figurein


    #For the other format
    if args['ext'] in ['png', 'jpeg']:
        #Open image with PIL to compute size
        tmp_img = Image.open(args['filename'])
        _,_,tmpwidth,tmpheight = tmp_img.getbbox()
        scale_x = ct['positionner'].width/float(tmpwidth)
        figure_height = float(tmpheight) * scale_x
        figure_width = ct['positionner'].width

        if document._resize_raster:
            #Rescale figure to the good size (to improve size and display speed)
            out_img = resize_raster_image(tmp_img)
            figurein = base64.b64encode(out_img.read())
            out_img.close()
        else:
            with open( args['filename'], "r") as f:
                figurein = base64.b64encode(f.read())

        tmp_img.close()

    if args['ext'] == 'png':
        output = '<image x="0" y="0" width="%s" height="%s" xlink:href="data:image/png;base64, %s" />'%(figure_width, figure_height, figurein)

    if args['ext'] == 'jpeg':
        output = '<image x="0" y="0" width="%s" height="%s" xlink:href="data:image/jpg;base64, %s" />'%(figure_width, figure_height, figurein)

    ct['positionner'].update_size(figure_width, figure_height)

    return output
示例#4
0
    def render(self):
        """
            function to render figures
        """


        #Svg // pdf render
        if self.ext in ('svg', 'pdf', 'matplotlib') :
            #Convert pdf to svg
            if self.ext == 'pdf' :
                figurein = convert_pdf_to_svg( self.content )

            #Convert matplotlib figure to svg
            elif self.ext == 'matplotlib':

                #Store mpl svg to a stringIO object
                with StringIO() as tmpf:
                    self.content.savefig(tmpf, bbox_inches='tight', format='svg')
                    tmpf.seek(0) #go to the biginig of the file

                    #store tmpf content as string in figurein variable
                    figurein = tmpf.read().encode('utf-8')

            #General case for svg format
            else:
                #Check if a filename is given for a svg file or directly read the content value
                if os.path.isfile(self.content):
                    with open(self.content) as f:
                        figurein = f.read()
                else:
                    figurein = self.content

            #test if we need to optimise the svg
            if document._optimize_svg:
                figurein = optimize_svg(figurein)

            soup = BeautifulSoup(figurein, 'xml')

            #Change id in svg defs to use the global id system
            soup = make_global_svg_defs(soup)

            #Optimize the size of embeded svg images !
            if document._resize_raster:
                imgs = soup.findAll('image')
                if imgs:
                    for img in imgs:

                        #True width and height of embed svg image
                        width, height = int( float(img['width']) ) , int( float(img['height']) )
                        img_ratio = height/float(width)
                        b64content = img['xlink:href']

                        try:
                            in_img =  BytesIO( base64.b64decode(b64content.split(';base64,')[1]) )
                            tmp_img = Image.open(in_img)
                            #print(tmp_img)
                            out_img = resize_raster_image( tmp_img )
                            out_b64 = base64.b64encode( out_img.read() )

                            #replace the resized image into the svg
                            img['xlink:href'] = 'data:image/%s;base64, %s'%(tmp_img.format.lower(), out_b64)
                        except:
                            print('Unable to reduce the image size')
                            pass

            svgtag = soup.find('svg')

            svg_viewbox = svgtag.get("viewBox")

            tmph = svgtag.get("height")
            tmpw = svgtag.get("width")
            if tmph == None or tmpw == None:
                fmpf, tmpname = tempfile.mkstemp(prefix="beampytmp")
                with open( tmpname+'.svg', 'w' ) as f:
                    f.write(figurein)
                    #print figurein
                tmph = getsvgheight( tmpname+'.svg' )
                tmpw = getsvgwidth( tmpname+'.svg' )
                #print tmpw, tmph
                os.remove(tmpname+'.svg')


            svgheight = convert_unit( tmph )
            svgwidth = convert_unit( tmpw )

            if svg_viewbox != None:
                svgheight = svg_viewbox.split(' ')[3]
                svgwidth = svg_viewbox.split(' ')[2]

            #SCALE OK need to keep the original viewBox !!!
            scale_x = self.positionner.width/float(svgwidth)
            #print svgwidth, svgheight, scale_x
            #scale_y = float(convert_unit(args['height']))/float(svgheight)
            good_scale = scale_x

            #BS4 get the svg tag content without <svg> and </svg>
            tmpfig = svgtag.renderContents()

            #Add the correct first line and last
            tmphead = '\n<g transform="scale(%0.5f)">'%(good_scale)
            output = tmphead + tmpfig + '</g>\n'

            figure_height = float(svgheight)*good_scale
            figure_width = self.width

            #Update the final svg size
            self.update_size(figure_width, figure_height)
            #Add the final svg output of the figure
            self.svgout = output

        #Bokeh images
        if self.ext == 'bokeh':

            # Run the bokeh components function to separate figure html div and js script
            figscript, figdiv = components(self.content, wrap_script=False)

            # Transform figscript to givea function name load_bokehjs
            tmp = figscript.splitlines()
            goodscript = '\n'.join( ['["load_bokeh"] = function() {'] + tmp[1:-1] + ['};\n'] )

            #Add the htmldiv to htmlout
            self.htmlout = figdiv
            #Add the script to scriptout
            self.jsout = goodscript

        #For the other format
        if self.ext in ('png', 'jpeg'):
            #Open image with PIL to compute size
            tmp_img = Image.open(self.content)
            _,_,tmpwidth,tmpheight = tmp_img.getbbox()
            scale_x = self.positionner.width/float(tmpwidth)
            figure_height = float(tmpheight) * scale_x
            figure_width = self.positionner.width

            if document._resize_raster:
                #Rescale figure to the good size (to improve size and display speed)
                out_img = resize_raster_image(tmp_img)
                figurein = base64.b64encode(out_img.read())
                out_img.close()
            else:
                with open( self.content, "r") as f:
                    figurein = base64.b64encode(f.read())

            tmp_img.close()

            if self.ext == 'png':
                output = '<image x="0" y="0" width="%s" height="%s" xlink:href="data:image/png;base64, %s" />'%(figure_width, figure_height, figurein)

            if self.ext == 'jpeg':
                output = '<image x="0" y="0" width="%s" height="%s" xlink:href="data:image/jpg;base64, %s" />'%(figure_width, figure_height, figurein)

            #Update the final size of the figure
            self.update_size(figure_width, figure_height)
            #Add the final svg to svgout
            self.svgout = output

        #print self.width, self.height
        #Update the rendered state of the module
        self.rendered = True
示例#5
0
def figure(filename,x='center',y='auto', width=None, height=None, ext=None):
    """
        Add figure to current slide
        Accepted format: [svg, png, jpeg, bokeh figure]

        - x['center']: x coordinate of the image
                       'center': center image relative to document._width
                       '+1cm": place image relative to previous element

        - y['auto']: y coordinate of the image
                     'auto': distribute all slide element on document._height
                     'center': center image relative to document._height (ignore other slide elements)
                     '+3cm': place image relative to previous element

        - width[None]: Image width, if None: width = document._width

        - height[None]: Image heigt

        - ext[None]: Image format, if None, format is guessed from filename.

    """
    #Check if the given filename is a string
    if type(filename) == type(''):
        #Check extension
        if ext == None:
            if '.svg' in filename.lower():
                ext = 'svg'

            if '.png' in filename.lower():
                ext = 'png'

            if ( '.jpeg' in filename.lower() ) or ( '.jpg' in filename.lower() ):
                ext = 'jpeg'
            
            if '.pdf' in filename.lower():
                ext = 'pdf'
            
    else:
        if "bokeh" in str(type(filename)):
            ext = 'bokeh'

    ######################################


    if ext == None:
        print("figure format can't be guessed from file name")

    #Bokeh image
    elif ext == 'bokeh':
        #print('I got a bokeh figure')
        figscript, figdiv = components(filename, wrap_script=False)

        #Todo get width and height from a bokeh figure
        if width == None:
            width = '%ipx'%filename.plot_width
        if height == None:
            height = '%ipx'%filename.plot_height

        #Transform figscript to givea function name load_bokehjs
        tmp = figscript.splitlines()
        goodscript = '\n'.join( ['["load_bokeh"] = function() {'] + tmp[1:-1] + ['};\n'] )
        args = {"x":str(x), "y": str(y) , "width": str(width), "height": str(height),
                "ext": ext,  'script':goodscript}

        figout = {'type': 'html', 'content': figdiv, 'args': args,
                  'render': render_figure}

        document._contents[gcs()]['contents'] += [ figout ]


    #Other filetype images
    else:

        if width == None:
            width = str(document._width)
        else:
            width = str(width)
            
        if height != None:
            height = str(height)

        args = {"x":str(x), "y": str(y) , "width": width, "height": height,
                "ext": ext, 'filename':filename }
        if ext == 'pdf' :
            figdata = convert_pdf_to_svg( filename )

        else :
            with open(filename,"r") as f:
                figdata = f.read()
			#If it's png/jpeg figure we need to encode them to base64
     
            if ext in ( 'png', 'jpeg' ):
                figdata = base64.encodestring(figdata)
			
        figout = {'type': 'figure', 'content': figdata, 'args': args,
                  "render": render_figure}

        document._contents[gcs()]['contents'] += [ figout ]