Frickelblog

5. Oktober 2009

Bücher des PC-Spiels MYST werden verfilmt

Gespeichert unter: Spiele — frickelblog @ 18:54
Tags: , , , ,

Gerade vorhin auf der Website von Cyan (der Entwicklerfirma von Myst) gelesen habe, soll das bekannte Point&Click-Adventure Myst verfilmt werden / bzw. die Bücher davon.

Das PC-Game selbst spielt in einer teils surrealen Welt, in der Rätsel zu lösen sind. Die Rätsel sind dabei nicht immer einfach, aber gerade das macht es doch sehr spannend. Während Myst 1 grafisch noch recht spärlich ist (nun ja, das Spiel ist von 1993), wird die Grafik von Teil zu Teil besser und war in „Myst V End of Ages“ (2005) wirklich sehr schön anzusehen. Insbesondere das Feature der veränderlichen Schärfentiefe, die von der Position des Mauszeigers definiert wird, war sehr interessant! Der Schwierigkeitsgrad der Spiele ist nie ganz trivial – am schwierigsten empfand ich Riven (Myst 2), da es sich doch über ein relativ großes Areal erstreckt.

Die durchwegs sehr angenehm zu betrachtende Grafik wird übrigens dadurch erreicht, dass die Umgebung vorgerendert ist. Im Spiel selber klickt man sich von Position zu Position (daher, Point and Click). An einer Position kann man sich dann in aller Seelenruhe in nahezu 720° umsehen, die Landschaft betrachten und sich über die Rätsel hermachen. Weitere Infos zu Myst, kann man bei Wikipedia nachlesen. Mittlerweile sind auch alle Teile für ein paar Euro zu haben. Die Masterpice Edition  „Myst 1-5″ kostet auch nur knapp über 30€.

Okay – soviel zum PC-Spiel. Nachdem ich die Spiele durch hatte, habe ich bemerkt, dass es zu den Spelen ja auch 3 Bücher gibt:  Das Buch Atrus, Das Buch Ti’ana, Das Buch der D’ni (auch als Trilogie zu haben). Die Bücher erklären sehr viel zur Hintergrundgeschichte. Wie es zu den Büchern kam, die Welten verbinden/erschaffen und was mit der Zivilisation der D’ni geschah.

Und genau um diese Bücher scheint es zu gehen.  So wie hier zu lesen und in dem Conceptual Trailer zu sehen ist, werden die Bücher verfilmt. Was mich etwas stutzig macht, ist dass die Nachricht von 2004 ist. Das aktuellste BlogPost ist aber vom 11. Sept. 2009. Das Projekt scheint also zwar noch nicht tot zu sein – aber auch noch weit von der Fertigstellung :-( Bleibt vielleicht noch mal Zeit, Myst doch nochmal durch zu spielen. Mal sehen, ob ich diesmal alle Rätsel komplett ohne Lösungshilfen schaffe (ja ich geb’s zu – manche waren mir echt zu hoch).

Was ich sehr erstaunlich fand: Myst 1 war mit über 9 Millionen Kopien das damals am meisten verkaufte Computerspiel der Welt. – Und nur eine Person in meinem Umfeld kannte lediglich Riven (Myst 2). So kam ich erst relativ spät auf die Serie.

15. September 2009

Downloading / Exporting Data from OpenStreetMap

Gespeichert unter: Allgemeines — frickelblog @ 21:47
Tags: ,

A short time ago I wanted to extract and process certain street map data from certain areas. OpenStreetMap seemd to provide excellent data. But how could I dwonload/export the data.

The first choice was the web-api. The problem with the API is, that you can’t export map tiles of arbitrary size. A possibility would have been be to download several tiles which are aligned next to each other and join them afterwards.

But when  I attended the 5th Wikipedia Fotoworkshop last weekend, I met a guy from OpenStreetMap who gave me the hint to the planetfile! Quite obvious – too strange I didn’t find it before. And as I didn’t need the complete worldfile (which would be rather big) I just downloaded a small subset (part of Germany only).

10. September 2009

Adresse Bahncard Service / Bahn Card kündigen

Gespeichert unter: Sonstiges — frickelblog @ 21:08
Tags: , ,

Nachdem ich meine BahnCard kündigen will, benötige ich logischerweise die Kontaktadresse des BahnCard Abocenters. Kein Problem, Google nach „Bahncard Bahncardservice kündigen“ … ohje, da kommen ja lauter angsteinflößende Seiten über wirre Bahngeschichten *hilfe*.

Also Bahn.de angesurft.
Uff was will ich, Kontakt eigentlich, also „Kontakt“ angeklickt.
Oha – da ist viel.  “ Rund um die Bahncard“ klingt doch gut. Am besten klingt der erste Punkt „BahnCard„.
„Wohin wende ich mich bei Rückfragen oder sonstigen Anliegen wie Kündigungen?“ Genau! Und da steht dann auch:
„[...] BahnCard-Service unter 01805/340035 (14 ct/Min. aus dem Festnetz [je nach Anbieter ..]) oder Faxnummer: 01805 121998. [...] Montag bis Freitag von 7.00 bis 21.00 Uhr [...].
Per Post [...]:  BahnCard-Service, 60643 Frankfurt am Main“

Na, war doch gar nicht so schwer. Mal sehen, ob das mit der Kündigung auch  so reibungslos klappt.

27. August 2009

New Generics-Sytnax in Java7

Gespeichert unter: Java — frickelblog @ 19:41
Tags: , , ,

Just read in this blogpost, that there will be a new type of Generics-Syntax allowed in Java7, called the Diamond-Syntax:
Map<Integer, List<String>> map = new HashMap<>();
If you’ve ever been annoyed by unreadable long Generics-declarations (like me), you’ll like the new feature.

24. August 2009

improved ButtonUI

Gespeichert unter: Java — frickelblog @ 19:31
Tags: , , ,

In the JavaGraphics Blog there are some very nice examples of how Java Buttons can be made nicely. The code is also available. So it’ a nice starting point for learning how to make own UIs! Features include:

  • cross-platform.
  • pure Java
  • Resizable
  • Vertical segments
  • Java 1.4 compatible

See the BlogPost here.

21. August 2009

Java Library for reading & writing EXIF, XMP and IPTC in JPEGs

Gespeichert unter: Java — frickelblog @ 22:23
Tags: , , , , , , ,

Finally it seems that I’ve found a pure Java Library that can read and write XMP Data to and from JPEGs!

In the past time I’ve been googling for such a library repeatedly. There are quite some libraries for just reading EXIF or IPTC data. Amongst others are Drew Noakes’ library and Imagero. As I am on the verge of adding more metadata functionality to my self-made image database I had 2 issues:

  1. A decision of how to store labels and descriptions to images: a database only without touching the images or IPTC, XMP within images (with cached information to a database). Finally I decided that I wanted to use XMP(or IPTC so that the information is kept close to the image.
  2. A library for this!

What I’ve found so far (incomplete listing as I came across QUITE some libs for reading data):

Imagero and Drew Noakes: Until now I was using Drew Noakes library for reding EXIF data – which was absolutely okay but couldn’t write any data :-( Imagero supports writing of IPTC and XMP (from what I’ve read) and is even free for non-commercial usage. But it’s not true open source and you need to request a licence every year (which works w/out problems!). Judging the work Andrey Kusnetsov (maintainer of Imagero) is putting into it I think, that’s quite acceptable.

Adobe XMP SDK: Adobe – as the inventor of XMP – has released an SDK for reading/writing XMP. Most of the SDK is written in C, the SDK Core is also available in Java (great!) but the functionality to get and write the XMP to and from files .. is not available as Java. Quite annoying.

Apache Sanselan: When searching for Apache Sanselan you most likely end up at the incubator-site which says that the project is in the stat of migrating into apache – the mailinglist also doesn’t work. The simple reason: Sanselan is already a part of Apache Commons. So, this new link is the place to go. The most interesting thing of Sanselan is the format support:

  • JPEG IPTC support: read (yes), write (soon), Can read IPTC data from exsiting JPEG/JFIF files WITHOUT modifying image data.
  • JPEG EXIF: read (yes), write (yes), Can read and write EXIF data to and from exsiting JPEG/JFIF files WITHOUT modifying image data.
  • XMP: read (yes), write (yes), Can read XMP XML (as as String) from [...] JPEG [...]. Can remove, insert and update XMP XML into existing JPEG files.

14. August 2009

How to display images with rounded Corners / Borders

Gespeichert unter: Java, Java2D, Swing — frickelblog @ 18:00
Tags: , , , , , ,

Bilder in Java darzustellen ist keine große Kunst, dazu gibt es auch ein Tutorial von Sun. Etwas schöner wären aber abgerundete Ecken. Und noch schöner wäre es, wenn wir einfach eine kleine Componente hätten die das alles selber macht, die wiederverwendbar wäre und die im GUI-Editor einfach zu bedienen wäre. Gesagt getan.

Die Anforderung ist also eine Gui Componente, die im Gui Editor (NetBeans in meinem Falle) wiederverwendbar ist (also ein JavaBean), der man ein Bild übergeben kann und bei der die Ecken abgerundet sind. Wenn möglich, wollen wir sogar noch einen Rahmen setzen können. Ein kurzer Blick auf die Seite „Painting in AWT and Swing“ zeigt, dass wir paintComponent() überschreiben sollten. Die Componente soll sich der Einfachheit halber der Größe des Bildes automatisch anpassen.

Die fertige Klasse sieht dann so aus:

public class ThumbPanel extends JPanel {

    protected BufferedImage image = null;
    public static final String PROP_IMAGE = "image";
    protected int roundness = 10;
    public static final String PROP_ROUNDNESS = "roundness";

    public ThumbPanel() {
        init();
    }

    private void init() {
        setOpaque(false);
    }

    protected void update() {
        if (image != null) {
            setSize(image.getWidth(), image.getHeight());
            setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        if (image == null) {
            return;
        }
        g.setClip(new RoundRectangle2D.Double(0, 0, image.getWidth(), image.getHeight(), roundness, roundness));
        g.drawImage(image, 0, 0, null);
        g.setClip(null);
    }

    public int getRoundness() {
        return roundness;
    }

    public void setRoundness(int roundness) {
        int oldRoundness = this.roundness;
        this.roundness = roundness;
        firePropertyChange(PROP_ROUNDNESS, oldRoundness, roundness);
        update();
    }

    public BufferedImage getImage() {
        return image;
    }

    public void setImage(BufferedImage image) {
        BufferedImage oldImage = this.image;
        this.image = image;
        firePropertyChange(PROP_IMAGE, oldImage, image);
        update();
    }
}

Getter und Setter sind selbsterklärend. Update() passt die Komponente der aktuellen Größe an. Ein Null-Images possiert in meinem Anwendungsfall nicht, wäre aber offenbar kein Problem das anzupassen. PaintComponent() setzt die Clip-Eigenschaft und malt dann das Bild auf die Komponente – fertig! Das ganze sieht dann so aus:

rounded corners ISo weit so gut. Nun will man aber vielleicht noch einen Rahmen (=Border) dazufügen. Standard Borders sehen dabei nicht ganz so praktikabel aus, da sie an den Ecken abgeschnitten werden. Also muss wohl oder übel eine eigene Border her. Schön wäre ein Rahmen, bei dem man Farbe, Dicke und Rundung einstellen kann. Der Versuch, die LineBorder zu extenden war nicht wirklich von Erfolg gekrönt, da man dabei Dicke und Rundung nicht separat einstellen kann.

Also selber malen. Linien mit RoundRectangle2Ds zu zeichnen, wollte nie so wirklich schön werden. Insbesondere sobald die Dicke > 1 Pixel sein sollte. Alternative: Roundrect fill und innen wieder Clip’en.  Nur dumm, dass sich das Clip dann auch auf das Bild übertragen hatte. Also per AlphaComposite das Innere einfach ausschneiden. Damit auch bei mehrfachen repaints, nicht immer ein BufferedImage für den Rahmen erzeugt werden muss, wird das Ergebnis einfach gecached. Die ganze klasse sieht dann so aus:

public class MyRoundBorder implements Border {

    private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
    protected int roundness = 10;
    public static final String PROP_ROUNDNESS = "roundness";
    protected Color color = Color.BLACK;
    public static final String PROP_COLOR = "color";
    protected int thickness = 1;
    public static final String PROP_THICKNESS = "thickness";
    // buffer the created image because recreating a complete image could waste precious time
    protected SoftReference cache = new SoftReference(null);
    protected Rectangle oldR = new Rectangle();
    protected Rectangle oldC = new Rectangle();

    public MyRoundBorder() {
    }

    public MyRoundBorder(int roundness, Color color, int thickness) {
        this.roundness = roundness;
        this.color = color;
        this.thickness = thickness;
    }

    public int getThickness() {
        return thickness;
    }

    public void setThickness(int thickness) {
        int oldThickness = this.thickness;
        this.thickness = thickness;
        propertyChangeSupport.firePropertyChange(PROP_THICKNESS, oldThickness, thickness);
        cache = new SoftReference(null);
    }

    public Color getColor() {
        return color;
    }

    public void setColor(Color color) {
        Color oldColor = this.color;
        this.color = color;
        propertyChangeSupport.firePropertyChange(PROP_COLOR, oldColor, color);
        cache = new SoftReference(null);
    }

    public int getRoundness() {
        return roundness;
    }

    public void setRoundness(int roundness) {
        int oldRoundness = this.roundness;
        this.roundness = roundness;
        propertyChangeSupport.firePropertyChange(PROP_ROUNDNESS, oldRoundness, roundness);
        cache = new SoftReference(null);
    }

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        propertyChangeSupport.addPropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        propertyChangeSupport.removePropertyChangeListener(listener);
    }

    @Override
    public void paintBorder(Component c, Graphics g1, int x, int y, int width, int height) {
        Graphics2D g = (Graphics2D) g1;

        BufferedImage buffered = cache.get();
        Rectangle newR = new Rectangle(x, y, width, height);
        if (buffered == null || !c.getBounds().equals(oldC) || !oldR.equals(newR)) {
            buffered = new BufferedImage(c.getWidth(), c.getHeight(), BufferedImage.TYPE_INT_ARGB);
            Graphics2D tmpg = buffered.createGraphics();
            tmpg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            tmpg.setClip(g1.getClip());
            tmpg.setColor(color);
            // fill area
            tmpg.fillRoundRect(x, y, width, height, roundness, roundness);
            // cut out inner
            tmpg.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OUT));
            tmpg.fillRoundRect(x + thickness, y + thickness, width - (2 * thickness), height - (2 * thickness), roundness, roundness);
            tmpg.dispose();

            cache = new SoftReference(buffered);
            c.getBounds(oldC);
            oldR = newR;
        }
        // draw border upon image
        g.drawImage(buffered, 0, 0, null);
    }

    @Override
    public Insets getBorderInsets(Component c) {
        return new Insets(thickness, thickness, thickness, thickness);
    }

    @Override
    public boolean isBorderOpaque() {
        return true;
    }
}

Die Getter/Setter sind wieder dazu da, eine schöne JavaBean zu bauen, damit die Border auch im GUI Editor einfach zu verwenden ist.

Da normale Borders verwendet werden können, kann natürlich auch eine CompoundBorder verwendet werden – um zum Beispiel anzuzeigen, wenn ein Bild selektiert ist (dann zB mit zusätzlichem weißen Innenrahmen), was dann so aussieht (links einfach, rechts Compond):

CompoundBorder II

30. Juli 2009

Erste Schritte mit JavaX JXMapKit

Gespeichert unter: Java — frickelblog @ 20:06
Tags: , , , , , , ,

Nachdem ich festgestellt habe, dass Nasa WorldWind zum Anzeigen von Kartenpositionen vielleicht doch ein bisschen Overkill ist, habe ich mir JXMapKit des SwingLabs-Projekts angesehen.

Um das Beispiel überhaupt zum Laufen zu bekommen, benötigen wir natürlich die richtigen Libraries. Das wären dann SwingX 1.0 und SwingX-ws. Derzeit wird man mit der Kombination nicht ganz glücklich, da in SwingX 1.0 (mindestens) eine Methode entfernt wurde, die in SwingX-ws benötigt wird. Der zugehörige Bug ist zwar reported, aber natürlich noch nicht in der aktuellsten Version eingebaut (Stand 30.7.2009). Eine gepatchte Version habe ich hier online gestellt: Jar / Quellen.

Wenn die Libraries erst einmal im Classpath liegen ist es im Prinzip ganz einfach (ich erkläre wie immer anhand von NetBeans aufgrund des besseren GUI-Editors):

  1. JFrame-Form erstellen
  2. JXMapKit in den Frame ziehen
  3. die JXMapKit Komponente anklicken und in den Properties den defaultProvider auf OpenStreetMap stellen, andernfalls bekommt man nur Exceptions.
  4. fertig!

Das ganze sollte dann so aussehen:

Screenshot von JXMapKit

Screenshot von JXMapKit

Der Code dazu sieht folgendermaßen aus:

public class MapViewer extends javax.swing.JFrame {
    public MapViewer() {
        initComponents();
    }

    private void initComponents() {
        jXMapKit1 = new org.jdesktop.swingx.JXMapKit();
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        jXMapKit1.setDefaultProvider(org.jdesktop.swingx.JXMapKit.DefaultProviders.OpenStreetMaps);
        getContentPane().add(jXMapKit1, java.awt.BorderLayout.CENTER);
        pack();
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new MapViewer().setVisible(true);
            }
        });
    }
    private org.jdesktop.swingx.JXMapKit jXMapKit1;
}

OpenStreetMap ist ja ganz schön. Aber eine Karte wäre ja auch fein. Das erreicht man, indem eine neue TileFactory erstellt wird. Dazu wird schnell der Konstruktor geändert:

    public MapViewer() {
        initComponents();
        WMSService wms = new WMSService();
        wms.setLayer("BMNG");
        wms.setBaseUrl("http://wms.jpl.nasa.gov/wms.cgi?");
        TileFactory fact = new WMSTileFactory(wms);
        jXMapKit1.setTileFactory(fact);
    }
Screenshot von JXMapKit mit BlueMarble

Screenshot von JXMapKit mit BlueMarble der NASA

Und schon sieht’s so aus:

Beim Starten kann es sein, dass man erst mal nur ein blaues Fenster sieht. Ändert sich leicht, indem man ein paar mal auf den Minus-Button drückt und etwas abwartet, da das Laden der Bilder vom Nasa-Server etwas dauern kann. Bei genauem Hinsehen, wird man im obigen Screenshot auch bemerken, dass der markierte Ausschnitt im rechten unteren Teil nicht mit der tatsächlichen Darstellung übereinstimmt sondern (in dem Fall) einen Ausschnitt anzeigt, der deutlich südlicher liegt (im Fenster sieht man nämlich eigentlich die Nordspitze Schottlands.

Nützliche Links:

erste Schritte mit Nasa World Wind

Gespeichert unter: Java — frickelblog @ 15:19
Tags: , ,

Photos auf einer Karte anzuzeigen kann so schwer nicht sein möchte man meinen. Anbindung an Google Maps oder Google Earth und gut is.

Will man diese Kartenanzeige jetzt noch in ein Java-Programm integrieren, sieht’s schon anders aus. Google Maps wäre kein Problem, wenn denn JWebPane schon fertig wäre. Ist es aber nicht. Also bleiben derzeit nur noch 2 Methoden: Nasa WorldWind einbinden oder JXMapViewer benutzen.

Der erste Test mit Nasa WorldWind ging erheblich schneller als erwartet: Das NetBeansWiki beschreibt die wenigen nötigen Schritte.

  1. Nasa Worldwind Java SDK herunterladen
  2. In Netbeans eine Library mit den Dateien worldwind.jar, jogl.jar und gluegen-rt.jar anlegen
  3. die Library zum Projekt hinzufügen
  4. Ein JFrame-Form erstellen
  5. (optional einige JavaBeans in die Palette des GUI Managers hinzufügen)
  6. WorldWindowGLCanvas in den JFrame ziehen
  7. folgende Imports hinzufügen:
    import gov.nasa.worldwind.*;
    import gov.nasa.worldwind.avlist.AVKey;
  8. und folgenden Code unter den initComponents() Aufruf des Konstruktors:
    Model m = (Model) WorldWind.createConfigurationComponent(AVKey.MODEL_CLASS_NAME);
    worldWindowGLCanvas1.setModel(m);
  9. In den Projekteigenschaften noch folgende JVM-Property setzen: -Djava.library.path=c:\pfad\zum\nasaworldwind\sdk\
  10. fertig!

Die ganze Klasse sieht dann so aus:

import gov.nasa.worldwind.*;
import gov.nasa.worldwind.avlist.AVKey;

public class NWW extends javax.swing.JFrame {

    public NWW() {
        initComponents();
        Model m = (Model) WorldWind.createConfigurationComponent(AVKey.MODEL_CLASS_NAME);
        worldWindowGLCanvas1.setModel(m);
    }

    private void initComponents() {
        worldWindowGLCanvas1 = new gov.nasa.worldwind.awt.WorldWindowGLCanvas();
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Nasa World WInd");
        setMinimumSize(new java.awt.Dimension(640, 480));
        getContentPane().add(worldWindowGLCanvas1, java.awt.BorderLayout.CENTER);
        pack();
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new NWW().setVisible(true);
            }
        });
    }
    private gov.nasa.worldwind.awt.WorldWindowGLCanvas worldWindowGLCanvas1;
}

Nützliche Links:

23. Juli 2009

Deinstallation von Inkscape

Gespeichert unter: Sonstiges — frickelblog @ 20:41
Tags: , , , ,

Da Inkscape 0.46 leider ein bekanntes Problem mit Grafiktabletts hat. Habe ich mir – wie in dem Bugreport geraten – die neue Nightly der 0.47 geladen. Bei der Deinstallation der Version 0.46 beglückte mich Inkscape mit folgender Fehlermeldung:

Uninstall Dialog Inkscape

Ich habe mal „Nein“ gewählt – nicht schlimmes passiert – schein die richtige Wahl gewesen zu sein ;-)

Der erste Test mit dem Nightly Build von Inkscape 0.47 sah übrigens schon mal gut aus: Das Wacom Bamboo scheint zu funktionieren!

Nächste Seite »

Bloggen Sie auf WordPress.com.