PIL
JavaScript
Eksempler >Bildegalleri

Bildegalleri

Hva
galleri
Skjermbiled bildegalleri
Et enkelt bildegalleri

Utgangspunktet er at vi har en katalog med bilder av varierende størrelse. Vi antar for enkelhets skyld at det er JPG-bilder. Vi skal lage en halvautomatikk som lar oss vise et utdrag av bildene i et enkelt galleri, med thumbnails.

Vi ønsker følgende funksjonalitet:

  • Vi skal se en full versjon av den thumbnailen vi klikker på
  • Vi skal kunne vandre framover og bakover
  • Vi skal kunne ha et automatisk "slideshow"

Vi skal lage løsningen på følgende måte:

  1. Vi lager en XML-fil som inneholder en kopling mellom bildenavn, dato når bildet er tatt(hvis det er et fotografi) og en kort beskrivelse, data.xml
  2. Vi lager en master for en framvisningsside, master.html
  3. Vi lager en Pythonmodul, makegalleri.py, som leser data.xml, master.html og produserer index.html som er den siden som skal vise fram galleriet.
  4. Vi skriver en javascript-fil, galleri.js, som inkluderes i index.html og tar seg av dynamikken på framvisningssiden,
  5. Vi skriver css-fil, galleri.css, som justerer layouten for oss.

Datafil

<?xml version="1.0" encoding="utf-8"?>
<bilder>
    <front>
    <![CDATA[
       <h1>Noen bilder</h1>
       <p>Her finner du  litt diverse bilder
       </p>
    ]]>
    </front>
    <bilde>
        <imagename>bilde1</imagename>
        <dato>2007-03-30</dato>
        <text>Pussig fyr</text>
    </bilde>
        ...
</bilder>

Master for indexfil

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
    <link href="galleri.css" rel="STYLESHEET" />
    <title>Noen bilder</title>
    <script type="text/javascript" src="galleri.js"> </script>
</head>
<body onload="init()">
  <!-- navigator -->
  <div  class="printhide" style="position:absolute;left:17px;top:7px">
      <span class="mybutton" onclick="previous()">&lt;</span>
      <span class="mybutton" id="autobutton" onclick="toggle()">&gt;&gt;</span>
      <span class="mybutton"  onclick="next()">&gt;</span>
  </div>
<div style="float:left">
  <div <!-- STYLE FROM PYCODE --> id="hilitedimg">
  </div>
</div>
<div id="content" class="printhide">
            <!-- CONTENT FROM PYCODE -->
</div>
<div style="clear:left;text-align:center">
    <hr/>
    <p>
        En enkel demonstrasjon. 
        Skaler vinduet så ser du at 
        de små bildene flyter. 
        Avspillingskontrollen burde kanskje flyttes ?
    </p>
    <p>
        <a href="javascript:history.back()">Tilbake</a>
    </p>
</div>
</body>
</html>

Vi har satt inn to kommentarer som skal erstattes med materiale som produseres i Pythonmodulen.

Pythonmodul

Merk at modulen bruker Python Imaging Library (PIL) til å skalere ned bildet til en akseptabel størrelse og til å lage thumbnails.

import xml.dom.minidom
import Image
import os
"""
See: http://www.ia.hiof.no/~borres/ml/galleri/p-galleri.html
"""

thumbFragment="""
<span>
<a href="javascript:hilite('%s')" title="Vis dette">
<img alt="?" src="images/%s" />
</a>
<div style="display:none" id="thumb%s">
  <div><img src="images/%s.jpg" alt="-"/></div>
  <div ><!-- datoen -->
     %s
  </div>
  <div><!-- teksten -->
    %s
  </div>
</div>
</span>
"""
#------------------------
# Read / write text files
def getTextFile(filename):
    try:
        file=open(filename,'r')
        res=file.read()
        file.close()
        return res
    except:
        print 'Trouble reading: '+filename
        return None
def storeTextFile(filename,txt):
    try:
        file=open(filename,'w')
        file.write(txt)
        file.close()
    except:
        print 'Trouble writing to: '+filename
      
#----------------------------------------------
# extract text from a node
def getText(nodelist):
    rc = ''
    for node in nodelist:
        if node.nodeType == node.TEXT_NODE or \
           node.nodeType == node.CDATA_SECTION_NODE:
            t=node.data.encode('ISO-8859-1')
            rc += t
    return rc
#----------------------------------------------
# produce a thumbnail
def makeThumb(infile,outfile):
    global maxWidth
    global maxHeight
    im = Image.open(infile)
    w=im.size[0]
    if w > maxWidth:
        maxWidth=w
    h=im.size[1]
    if h > maxHeight:
        maxHeight=h
    tsize=T_SIZE,T_SIZE
    if w > h:
        tsize= int(round(1.0*w/h*T_SIZE)),int(round(1.0*w/h*T_SIZE))
    im.thumbnail(tsize,Image.ANTIALIAS)
    im.save(outfile,"JPEG")
#-----------------------------------------------
# resize an image, down to max height and width
def resizeImage(imfile,maxW,maxH):
    im = Image.open(imfile)
    w=im.size[0]
    h=im.size[1]
    if w <= maxW and h <= maxH:
        return
    if w > maxW:
        h=int(round((1.0*h/w)*maxW))
        w=maxW
    if h > maxH:
        w=int(round((1.0*w/h)*maxH))
        h=maxH
    isize=w,h
    im=im.resize(isize,Image.ANTIALIAS)
    im.save(imfile,"JPEG")
    
#----------------------------------------------
# build DOM tree from XML-file
def buildDom(filename):
    T=getTextFile(filename)
    if T== None:
        return None
    try:
        return xml.dom.minidom.parseString(T)
    except:
        print 'Error building dom '
        return None
#----------------------------------------------
# Find all image elements and populate
# a spanFragment list
def buildPage(dom,catalog):
    global masterPage
    res=''
    # pick up frontpage
    front=''
    try:
        front=getText(dom.getElementsByTagName('front')[0].childNodes)
    except:
        front='<p>Bilder</p>'
    res="""
    <div style="display:none" id="thumb0">
    %s
    </div>
    """%front
    # pick up imagedescriptions
    bildeliste=dom.getElementsByTagName('bilde')
    ix=0
    for bilde in bildeliste:
        ix+=1
        # pick up imagename (106_0629), dato(2006-04-14) 
        # and txt(dette er en tekst)
        try:
            imx=bilde.getElementsByTagName('imagename')[0]
            imagename=getText(imx.childNodes)
            if imagename.endswith('.jpg'):
                imagename=imagename.replace('.jpg','')
            dato=getText(bilde.getElementsByTagName('dato')[0].childNodes)
            txt=getText(bilde.getElementsByTagName('text')[0].childNodes)
            imagefile=catalog+'images\\'+imagename+'.jpg'
            thumbfile=catalog+'images\\t_'+imagename+'.jpg'
            resizeImage(imagefile,I_WIDTH,I_HEIGTH)
            makeThumb(imagefile,thumbfile)
            res+='\n'+thumbFragment%\
            (str(ix),'t_'+imagename+'.jpg',str(ix),imagename,dato,txt)
        except:
            print 'something went wrong,bilde nr: '+str(ix)
    style='style="text-align:center;width:%spx;height:%spx"'%\
          (str(maxWidth+5),str(maxHeight+40))
    masterPage=masterPage.replace('<!-- STYLE FROM PYCODE -->',style)
    masterPage=masterPage.replace('<!-- CONTENT FROM PYCODE -->',res)
    return masterPage
#-------------
catalog='f:\\html\\ml\\galleri\\'
#---------------------------------------------
# max size for images to show
I_WIDTH=700
I_HEIGTH=500
# will be set as max image dimensions found
maxWidth=20
maxHeight=20
# max heigth for thumbnail
T_SIZE=50
masterPage=getTextFile(catalog+'master.html')
if masterPage==None:
    exit(0)
dom=buildDom(catalog+'data.xml')
if dom != None:
    res=buildPage(dom,catalog)
    try:
        outfile=open(catalog+'index.html','w')
        outfile.write(res)
        outfile.close()
    except:
        print 'Error writing file ',filename

Javascript

var currentNr=0;
var maxNr=1;
var stopped=true;

function init()
{
  var nr=0;
  while (document.getElementById('thumb'+nr))
   nr+=1
  maxNr=nr-1;
  hilite('0');
}

function hilite(nr)
{
  var content=document.getElementById('thumb'+nr).innerHTML;
  document.getElementById('hilitedimg').innerHTML=
    '<div>'+content+'</div>';
  currentNr=parseInt(nr);
}

function previous()
{
    if(currentNr==0)
      hilite(maxNr);
    else
      hilite(currentNr-1);
}

function next()
{
  if(currentNr==maxNr)
    hilite(0);
  else
    hilite(currentNr+1);
}

function toggle()
{
  if(stopped)
  {
    stopped=false;
    setTimeout("show()",3000);
    document.getElementById('autobutton').innerHTML=
      '&nbsp;||&nbsp;';
  }
  else
  {
    stopped=true;
    document.getElementById('autobutton').innerHTML=
      '&nbsp;&gt;&gt;&nbsp;';
  }
}

function show()
{
  if (!stopped)
  {
    next();
    setTimeout("show()",3000);
  }
}

Stilsett

@media screen
    {
        body{
                color: black;
                font-family:"Verdana","Geneva","Arial","Times",sans-serif;
                font-size:13px;
                margin:5px;
                padding:0px;
        }
        .text{font-size:14px}
        .dato{color:gray}
        .mybutton{cursor:pointer;color:black;
                  background-color:#EED9B0;
                  border-style:solid;
                  border-width:thin;
                  padding:5px;
                  font-weight:bold;
                  margin-right:2px}
        h2{background-color:#EED9B0;}
    }
    @media print
    {
        .printhide{display:none;font-size:16px;text-align:center}
    }
Du kan teste løsningen her http://www.it.hiof.no/~borres/dw/galleri/index.html
Referanser
1
Python Imaging Library pythonware.com www.pythonware.com/products/pil/index.htm 14-03-2010

Et komplett eksempel: sample.zip

Vedlikehold

B. Stenseth, juli 2007

( Velkommen ) Eksempler >Bildegalleri ( Slideshow )