Bearbeiten von „FreewarWiki:Bot/Skripts/makemap.php

Zur Navigation springen Zur Suche springen

Achtung

Du bearbeitest diese Seite unangemeldet. Wenn du deine Änderung speicherst, wird deine aktuelle IP-Adresse in der Versionsgeschichte aufgezeichnet und ist damit öffentlich einsehbar. Um effektiver mitarbeiten zu können und deine IP-Adresse zu verbergen, melde dich doch bitte an.

Speichere bitte keine Textversuche ab. Nutze stattdessen die Spielwiese, um dich im Umgang mit der Textverarbeitung im Wiki vertraut zu machen.

Die Bearbeitung kann rückgängig gemacht werden. Bitte prüfe den Vergleich unten, um sicherzustellen, dass du dies tun möchtest, und veröffentliche dann unten deine Änderungen, um die Bearbeitung rückgängig zu machen.

Aktuelle Version Dein Text
Zeile 1: Zeile 1:
{{Scriptquelltextverwendung}}
{{Scriptquelltextverwendung}}
Letzte Änderungen:
* Umstellung auf "getopt" (Angabe von Optionen auf der Befehlszeile). Neue Features "Atlas" und "Einzelkarten", damit auch Erstellung von Dungeon-Karten. Damit kann man jetzt weitgehend automatisch sowas machen wie http://www.remote-island.org/101912/atlas.pdf (Quelltext: http://www.remote-island.org/101912/atlas.odt) --[[Benutzer:Count Ypsilon|Count Ypsilon]] ([[Benutzer Diskussion:Count Ypsilon|Diskussion]]) 23:24, 17. Feb. 2019 (CET)
<pre>
<pre>
<?php
<?php
header('Content-Type: text/plain; charset=utf-8;');
header('Content-Type: text/plain; charset=utf-8;');


const BERGFELD = 'http://welt1.freewar.de/freewar/images/map/std.jpg';
// Bergfeld url
const ATLAS_TEMPLATE = 'atlas-vorlage.odt';
define("BERGFELD", 'http://welt1.freewar.de/freewar/images/map/std.jpg');
const GESAMTKARTE_LORU = array(2, 2, 170, 400);
const MAPLIST = 'maplist.txt';
const MAPCACHE = './map_cache';


/* ----------------------------------------------------------------------------
$host  = 'http://www.fwwiki.de';
* Der Freewar-Kartengenerator
$prefix = 'Karte';                // Wiki-Namespace
*
*
*/


function show_help() {
// pfad zu maplist.txt
    echo <<<EOF
$maplist = 'maplist.txt';


Befehlszeilenoptionen:
// Pfad zur Ausgabedatei
$mapfile = './Gesamtkarte (automatisch generiert).jpg';


--mode          "gesamt": erzeugt eine Gesamtkarte für die Oberfläche
// pfad zu map_cache
                "einzel": erzeugt einzelne Karten für jedes Gebiet
$map_cache = './map_cache';
                "atlas": erzeugt ein Atlas-Dokument (OpenOffice/Libre-
                Office-Format); benötigt dafür eine Vorlage
--dungeons      auch Dungeons mit ausgeben
--grid          alle X Zeilen/Spalten eine Linie
--cellspacing    Pixel Abstand zwischen Feldern
--gridlabels    Gitternetz mit Koordinaten beschriften
--rotatelabels  Koordinaten an X-Achse rotieren
--gebietlabel    Gebiete beschriften (bei Einzel/Atlas)
--labelfont      TTF-Datei für Beschriftungen
--lighten        nichtbetretbare/gebietsfremde Felder aufhellen
--output        Name der Ausgabedatei/des Ausgabeverzeichnisses
--bgcolor        Bildhintergrund in Hex
--verbose        mehr Meldungen anzeigen


Bei Modus "Atlas" zusätzlich
# Bereich angeben. Alles ausserhalb wird ignoriert. Die Karte wird aber
--dpi            Auflösung für die Bildausgabe (Default 140, größere Auflösung
# immer nur so gross, wie tatsaechlich Felder da sind, nicht so gross,
                bringt kleinere Bilder)
# wie man hier angibt.
--pagewidth      druckbare Seitenbreite in cm
# (nicht mit 1,1 starten, sonst kriegt man den Dummyplace mit)
--pageheight    druckbare Seitenhöhe in cm
$min_x = 2;
$min_y = 2;
$max_x = 170; # oestlicher Rand, damit Itolos und Belpharia-Inseln draussen bleiben
$max_y = 400;
# Hintergrundfarbe fuer Karte
$bgcolor = "ffffff";


# auf z.b. 5 setzen, wenn felder mit luecken gewuenscht
$cellspacing = 0;
# auf 1 setzen, wenn alle 5 zeilen/spalten linie gewuenscht
$draw_grid = 1;


EOF;
// ab hier nichts ändern ohne Kenntnisse über Funktionsweise des Skripts
}
function get_templates($template, $wiki_text) {
 
    $pattern = '/\{\{(Vorlage:)?' . preg_quote($template, '/') . '/';
 
// --- Einlesen der Befehlszeile ----------------------------------------------


$longopts = array(
    $templates = preg_split($pattern, $wiki_text);
    "mode:",           // gesamt (Default), einzel oder atlas
    "dungeons",        // sollen Dungeons mit ausgegeben werden?
    "verbose",        // soll das Programm geschwätzig sein?
    "lighten",        // sollen gebietsfremde Felde aufgehellt werden?
    "bgcolor:",        // Kartenhintergrund in Web-Notation (Default weiss)
    "grid:",          // Gitternetz-Abstand (Default keins)
    "help",            // Hilfe anzeigen
    "gridlabels",      // soll das Gitternetz beschriftet sein? (Default nein)
    "gebietlabel",    // soll die Gebietskarte ein Label haben? (Default nein)
    "labelfont:",      // TTF-Datei für die Beschriftungen
    "rotatelabels",    // soll X-Achesen-Label 90° rotiert sein? (Default nein)
    "cellspacing:",    // Feld-Abstand (Default 0)
    "dpi:",            // dpi für Bilder im Atlas (Default 140)
    "pagewidth:",      // druckbare Seitenbreite (cm, Papier-Rand) im Atlas
    "pageheight:",    // druckbare Seitenhöhe (cm, Papier-Rand) im Atlas
    "output:",        // Ausgabedatei oder -Verzeichnis
);


$o = getopt(NULL, $longopts, $optind);
    return array_slice($templates, 1);
 
$o['verbose'] = array_key_exists('verbose', $o);
 
if (array_key_exists('help', $o)) {
    show_help();
    exit;
}
}


if (!array_key_exists('mode', $o)) {
// cacht mapfile
    $o['mode'] = 'gesamt';
function cache_mapfile($url, $map_cache) {
    echo "Betriebsmodus \"Gesamtkarte\" automatisch gewählt. Programm mit --help\n";
     $cache_file = "$map_cache/" . md5($url);
    echo "aufrufen für weitere Funktionen\n";
     if (!file_exists($cache_file)) {
}
         file_put_contents($cache_file, file_get_contents($url));
 
if ($o['mode'] != 'gesamt' && $o['mode'] != 'atlas' && $o['mode'] != 'einzel') {
    echo "mode muss entweder 'atlas', 'einzel' oder 'gesamt' sein\n";
    show_help();
    exit;
}
 
if (!array_key_exists('bgcolor', $o)) {
    $o['bgcolor'] = 'ffffff';
}
 
if (!preg_match('/^[a-f0-9]{6}$/i', $o['bgcolor'])) {
    echo "bgcolor muss eine 6stellige Hexadezimalzahl sein, z.B. fafefa - nicht '".$o['bgcolor']."'\n";
    show_help();
    exit;
}
 
if (!array_key_exists('grid', $o)) {
    $o['grid'] = 0;
}
 
if (!preg_match('/^\d\d?$/', $o['grid'])) {
     echo "grid muss zwischen 0 und 99 liegen\n";
    show_help();
    exit;
}
 
$o['gridlabels'] = array_key_exists('gridlabels', $o);
if ($o['gridlabels'] && !$o['grid']) {
    echo "gridlabels kann nur zusammen mit grid verwendet werden\n";
    show_help();
    exit;
}
 
$o['rotatelabels'] = array_key_exists('rotatelabels', $o);
if ($o['rotatelabels'] && !$o['gridlabels']) {
    echo "rotatelabels kann nur zusammen mit gridlabels verwendet werden\n";
    show_help();
    exit;
}
 
$o['dungeons'] = array_key_exists('dungeons', $o);
 
$o['gebietlabel'] = array_key_exists('gebietlabel', $o);
if ($o['gebietlabel'] && $o['mode'] == 'gesamt') {
    echo "--gebietlabel geht nur bei --mode atlas oder --mode einzel\n";
    show_help();
    exit;
}
 
$o['lighten'] = array_key_exists('lighten', $o);
if ($o['lighten'] && $o['mode'] == 'gesamt') {
    echo "--lighten geht nur bei --mode atlas oder --mode einzel\n";
    show_help();
    exit;
}
 
if (!array_key_exists('cellspacing', $o)) $o['cellspacing'] = 0;
if (!preg_match('/^\d\d?$/', $o['cellspacing'])) {
    echo "cellspacing muss zwischen 0 und 99 liegen\n";
    show_help();
    exit;
}
 
if ($o['mode'] == 'atlas') {
 
    if (!array_key_exists('dpi', $o)) {
        $o['dpi'] = 140;
    }
 
    if (!preg_match('/^\d\d\d?$/', $o['dpi'])) {
        echo "dpi muss zwischen 10 und 999 liegen\n";
        show_help();
        exit;
    }
 
    if (!array_key_exists('pagewidth', $o)) $o['pagewidth'] = 12.85;
    $o['pagewidth'] = strtr($o['pagewidth'], ",", ".");
 
    if (!array_key_exists('pageheight', $o)) $o['pageheight'] = 19;
    $o['pageheight'] = strtr($o['pageheight'], ",", ".");
 
     if (!preg_match('/^\d\d?(\.\d+)?$/', $o['pageheight'])) {
         echo "pageheight muss zwischen 0 und 99.9 liegen\n";
        show_help();
        exit;
    }
 
    if (!preg_match('/^\d\d?(\.\d+)?$/', $o['pagewidth'])) {
        echo "pagewidth muss zwischen 0 und 99.9 liegen\n";
        show_help();
        exit;
    }
 
} else {
    if (array_key_exists('dpi', $o) ||
        array_key_exists('pageheight', $o) ||
        array_key_exists('pagewidth', $o)) {
        echo "--dpi, --pageheight, --pagewidth gehen nur mit --mode atlas\n";
        show_help();
        exit;
     }
     }
   
    return $cache_file;
}
}


if (!array_key_exists("labelfont", $o)) {
$parser_function = 'parse_card_article';              // Parser Funktion des Skripts
    $o['labelfont'] = '/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf';
$api_url        = "$host/api.php?format=json";
}


if ($o['gebietlabel'] || $o['gridlabels']) {
// trennzeichen für positionsschlüssel
    if (!file_exists($o['labelfont'])) {
$pos_delimiter = '|';
        echo "Datei ".$o['labelfont']." (--labelfont) nicht gefunden\n";
        show_help();
        exit;
    }
}


if (!array_key_exists("output", $o)) {
    $o['output'] = './karten';
    if ($o['mode'] == 'atlas') $o['output'] = './atlas.odt';
    if ($o['mode'] == 'gesamt' && !$o['dungeons']) $o['output'] = './Gesamtkarte (automatisch generiert).jpg';
}


if ($optind < $argc) {
// Rahmen
    echo "Ungültige Befehlszeilenoption\n";
$min_x_found = $max_x;
    show_help();
$min_y_found = $max_y;
    exit;
$max_x_found = $min_x;
}
$max_y_found = $min_y;
// zusätzliche Felder, die nicht von Feld-Artikeln erfasst werden
$additional_fields = [];


// --- Einlesen der Befehlszeile beendet --------------------------------------
// Bergfeld cachen
cache_mapfile(BERGFELD, $map_cache);


if ($o['mode'] == 'atlas') {
// Karten holen
$api_query_url = "$api_url&action=query&list=categorymembers".
                        "&cmtitle=Kategorie:Karten&cmtype=page".
                        "&cmprop=ids|sortkeyprefix|title&cmlimit=50";
$api_query_url_continue = $api_query_url;


    // Atlas benötigt eine vorbereitete OpenOffice-Datei
// pageids der karten
    if (!file_exists(ATLAS_TEMPLATE)) {
$map_pageids = [];
        echo "Datei ".ATLAS_TEMPLATE." wird für --mode atlas benötigt, fehlt aber.\n";
        echo "Entweder eine leere OpenOffice-Datei erzeugen, die irgendwo den Text\n";
        echo "ADD CONTENT HERE enthält, oder herunterladen von\n";
        echo "http://www.remote-island.org/101912/atlas-vorlage.odt";
        exit;
    }


    if ($o['verbose']) echo ATLAS_TEMPLATE.' nach '.$o['output']." kopieren...\n";
// kategorieeinträge durchlaufen
     copy(ATLAS_TEMPLATE, $o['output']);
while (true)
 
     $json = json_decode(file_get_contents($api_query_url_continue), true);
     $zipfile = new ZipArchive;
   
     $res = $zipfile->open($o['output']);
     // pageids hinzufügen
    if (!$res) {
     $map_pageids = array_merge($map_pageids, array_filter(array_map(function ($row) {
         echo "Fehler beim Öffnen der Datei ".$o['output']."!\n";
         // keine ! kategorieeinträge
         exit;
         return ($row['sortkeyprefix'][0] == '!') ? null : $row['pageid'];
    }
     }, $json['query']['categorymembers'])));
} else if ($o['mode'] != 'gesamt' || $o['dungeons']) {
   
     mkdir($o['output'], 0777, TRUE);
    // continue url
     if (!is_dir($o['output'])) {
     if (isset($json['continue'])) {
         echo "'".$o['output']."' ist kein Verzeichnis bzw. kann nicht angelegt werden!\n";
         $api_query_url_continue = "$api_query_url&cmcontinue={$json['continue']['cmcontinue']}";
         exit;
    } else {
         break;
     }
     }
}
}


$count = 10000;
// karten durchlaufen
$rvlimit = 10;


 
foreach (array_chunk($map_pageids, $rvlimit) as $pageids) {
// ab hier nichts ändern ohne Kenntnisse über Funktionsweise des Skripts
    $api_query_url = "$api_url&action=query&prop=revisions".
 
                        "&rvprop=content&pageids=". implode("|", $pageids);
// cacht mapfile
    $json = json_decode(file_get_contents($api_query_url), true);
function cache_mapfile($url) {
   
    $cache_file = MAPCACHE . "/". md5($url);
    foreach ($json['query']['pages'] as $pageid => $prop) {
    if (!file_exists($cache_file)) {
        $raw = $prop['revisions'][0]['*'];
         file_put_contents($cache_file, file_get_contents($url));
       
        // unbetretbare und rahmenfelder erfassen, durchlaufen und an maplist format anpassen
        $additional_fields = array_merge($additional_fields, array_map(function ($template_text) {
            preg_match("/([0-9\-]+)\|([0-9\-]+)(\|([^}\|]+))?/", $template_text, $values);
           
            if (!isset($values[1])) {
                return [];
            }
           
            return [
                // array keys entsprechend format in maplist.txt
                2 => $values[1],
                3 => $values[2],
                5 => isset($values[3]) ? $values[4] : BERGFELD
            ];
         }, array_merge(get_templates("Karte/Unbetretbar", $raw), get_templates("Karte/Rahmenfeld", $raw))));
     }
     }
   
    return $cache_file;
}
}


// trennzeichen für positionsschlüssel
// zusätzliche Felder geholt
$pos_delimiter = '|';
// eigentliche maplist holen und mit zusätzlichen zusammenführen
 
$field_rows = array_merge(array_map(function ($line) {
// Bergfeld cachen
     return str_getcsv($line, ";");
cache_mapfile(BERGFELD);
}, explode("\n", file_get_contents($maplist))), $additional_fields);
 
// maplist holen
if ($o['verbose']) echo "Felder aus ".MAPLIST." holen und Bilder laden...\n";
 
$handle = fopen(MAPLIST, "r");
if (!$handle) {
     echo "Kann Feldliste aus ".MAPLIST." nicht laden\n";
    exit;
}
$field_rows = array();
while ($data = fgetcsv($handle, 1000, ";")) {
  array_push($field_rows, $data);
}
fclose($handle);


// felder in `position` => `url` format überführen
// felder in `position` => `url` format überführen
$fields = [];
$fields = [];
foreach ($field_rows as $field) {
foreach ($field_rows as $field) {
     $x = array_key_exists(2, $field) ? $field[2] : NULL;
     # Koordinaten-Check
    $y = array_key_exists(3, $field) ? $field[3] : NULL;
    if ($field[2] < $min_x || $field[2] > $max_x || $field[3] < $min_y || $field[3] > $max_y) {
    $g = array_key_exists(0, $field) ? $field[0] : NULL;
         continue;
    $b = array_key_exists(1, $field) ? $field[1] : NULL;
    }
 
    if ($field[2] < $min_x_found) {
    if ($o["mode"] == "gesamt") {
        $min_x_found = $field[2] ;
 
    }
         // Für die Gesamtkarte werden die Felder des Kontinents als ein Gebiet
    if ($field[3] < $min_y_found) {
        // behandelt
         $min_y_found = $field[3];
        if ($x>GESAMTKARTE_LORU[0] && $y>GESAMTKARTE_LORU[1] &&
            $x<GESAMTKARTE_LORU[2] && $y<GESAMTKARTE_LORU[3]) {
            $g="Oberfläche";
        } else {
            // Dungeons (und Außenbereiche des Kontinents wie Narubia)
            // nur, wenn --dungeons gesetzt ist
            if (!$o['dungeons']) continue;
        }
 
    } else {
 
         // Für Einzelkarten und Atlas kann man mit $dungeons steuern,
        // ob auch Dungeons ausgegeben werden sollen
        if (!$o['dungeons'] && $x<2) continue;
     }
     }
 
     if ($field[2] > $max_x_found) {
     $lim = &$gebiet_limits[$g];
         $max_x_found = $field[2] ;
    if (!$lim) {
         $lim["minx"] = 99999;
        $lim["miny"] = 99999;
        $lim["maxx"] = -99999;
        $lim["maxy"] = -99999;
     }
     }
 
     if ($field[3] > $max_y_found) {
    // Hier wird die Größe jedes Gebiets ermittelt; dazu berücksichtigen
         $max_y_found = $field[3];
    // wir aber nur die begehbaren Teile, sonst haben Karten wie z.B.
    // Düsterfrostinsel einen unnötig großen Platzbedarf. TODO, dies
     // konfigurierbar machen
    if ($b) {
        if ($x < $lim["minx"]) $lim["minx"] = $x;
        if ($y < $lim["miny"]) $lim["miny"] = $y;
         if ($x > $lim["maxx"]) $lim["maxx"] = $x;
        if ($y > $lim["maxy"]) $lim["maxy"] = $y;
     }
     }
          
          
     // und gleich bilddatein holen
     // und gleich bilddatein holen
     $cache_file = cache_mapfile(array_key_exists(5, $field) ? $field[5] : NULL);
     $cache_file = cache_mapfile($field[5], $map_cache);
      
      
     // kein Feldtitel oder `Feldtitel Pensal (brennend)`
     // kein Feldtitel oder `Feldtitel Pensal (brennend)`
     if (!isset($g) || strpos($g, ' (brennend)') === false) {
     if (!isset($field[1]) || strpos($field[1], ' (brennend)') === false) {
         $fields["{$x}$pos_delimiter{$y}"] = [
         $fields["{$field[2]}$pos_delimiter{$field[3]}"] = [
             'x' => $x,
             'x' => $field[2],
             'y' => $y,
             'y' => $field[3],
            'g' => $g,
            'begehbar' => $b,
             'file' => $cache_file
             'file' => $cache_file
         ];   
         ];   
Zeile 353: Zeile 181:
                     'x' => $field['x'] + $diff_x,
                     'x' => $field['x'] + $diff_x,
                     'y' => $field['y'] + $diff_y,
                     'y' => $field['y'] + $diff_y,
                     'file' => MAPCACHE . '/' . md5(BERGFELD)
                     'file' => "$map_cache/" . md5(BERGFELD)
                 ];
                 ];
             }
             }
Zeile 362: Zeile 190:
# Groesse eines Kartenfelds feststellen
# Groesse eines Kartenfelds feststellen
list($tilewidth, $tileheight) = getimagesize($cache_file);
list($tilewidth, $tileheight) = getimagesize($cache_file);
if ($o['verbose']) echo "tile size: $tilewidth x $tileheight\n";
echo "tile size: $tilewidth x $tileheight\n";
 
// ein weisses Kartenfeld herstellen
if ($o['lighten']) {
    $aufheller = imagecreatetruecolor($tilewidth, $tileheight);
    $farbe = imagecolorallocate($aufheller, 255, 255, 255);
    imagefilledrectangle($aufheller, 0, 0, $tilewidth, $tileheight, $farbe);
}
 
if ($o["mode"] == 'atlas')
{
  file_put_contents("odt/content.xml", file_get_contents("head.xml"));
  $dungeons = "";
  $oberflaeche = "";
}
 
foreach($gebiet_limits as $gebiet => $limits) {
 
    // Bereich ermitteln
 
    $max_x_found = $limits['maxx'] + 1;
    $max_y_found = $limits['maxy'] + 1;
    $min_x_found = $limits['minx'] - 1;
    $min_y_found = $limits['miny'] - 1;
 
    // Leeres Kartenbild erstellen
 
    $mapwidth = ($max_x_found - $min_x_found + ($o['grid'] ? 3 : 1)) * $tilewidth +
                ($max_x_found - $min_x_found + 2) * $o['cellspacing'];
    $mapheight = ($max_y_found - $min_y_found + ($o['grid'] ? 3 : 1)) * $tileheight +
                ($max_y_found - $min_y_found + 2) * $o['cellspacing'];
 
    if ($o['verbose']) {
        echo "Karte für '$gebiet': x_min: $min_x_found; x_max: $max_x_found; y_min: $min_y_found; y_max: $max_y_found; ";
        echo "Bildgröße: $mapwidth x $mapheight\n";
    }
 
    $mapimage = imagecreatetruecolor($mapwidth, $mapheight);
    if (!$mapimage) {
        echo "Fehler bei der Erstellung des Kartenbilds für '$gebiet'\n";
        continue;
    }
 
    // Hintergrundfarbe setzen
 
    $bgarray = sscanf($o['bgcolor'], "%02X%02X%02X");
    $bgindex = imagecolorallocate($mapimage, $bgarray[0], $bgarray[1], $bgarray[2]);
    imagefill($mapimage, 0, 0, $bgindex);
 
    // Gitternetz einzeichnen und ggf. beschriften
 
    if ($o['grid']) {
        for ($x = $min_x_found; $x <= $max_x_found; $x++) {
            if ($x%$o['grid'] == 0) {
                $mpx = ($x - $min_x_found + 1) * ($tilewidth + $o['cellspacing']) + $o['cellspacing'] + $tilewidth/2;
                imageline($mapimage, $mpx, $o['rotatelabels'] ? 0 : 40, $mpx, $o['rotatelabels'] ? $mapheight : $mapheight - 40, 0);
                if (!$o['gridlabels']) continue;
                $t = $x;
                if (strlen($t) > 4) $t=substr($t,0,2)."\n".substr($t,3);
 
                // X-Achsen-Labels können entweder gerade stehen oder
                // entlang der Achse (rotatelabels)
                if ($o['rotatelabels']) {
                    imagettftext($mapimage, 11, 270, $mpx + 3, 5, 0, $o['labelfont'], $t);
                    $ar = imagettfbbox (11, 270, $o['labelfont'], $t);
                    imagettftext($mapimage, 11, 270, $mpx + 3, $mapheight - $ar[3] - 5, 0, $o['labelfont'], $t);
                } else {
                    $ar = imagettfbbox (11, 0, $o['labelfont'], $t);
                    imagettftext($mapimage, 11, 0, $mpx + 3 - $ar[4]/2, 22 - $ar[5], 0, $o['labelfont'], $t);
                    imagettftext($mapimage, 11, 0, $mpx + 3 - $ar[4]/2, $mapheight + $ar[5] - 10, 0, $o['labelfont'], $t);
                }
            }
        }
        for ($y = $min_y_found; $y <= $max_y_found; $y++) {
            if ($y%$o['grid'] == 0) {
                $mpy = ($y - $min_y_found + 1) * ($tileheight + $o['cellspacing']) + $o['cellspacing'] + $tileheight/2;
                imageline($mapimage, 0, $mpy, $mapwidth, $mpy, 0);
                if (!$o['gridlabels']) continue;
                $t = $y;
                if (strlen($t) > 4) $t=substr($t,0,2)."\n".substr($t,3);
                imagettftext($mapimage, 11, 0, 5, $mpy - 2, 0, $o['labelfont'], $t);
                $ar = imagettfbbox (11, 0, $o['labelfont'], $t);
                imagettftext($mapimage, 11, 0, $mapwidth - 5 - $ar[4], $mpy - 2, 0, $o['labelfont'], $t);
            }
        }
    }
 
    // Label für Gebiet einzeichnen; schwarze Box, darin weisse Box,
    // darin Text
 
    if ($o['gebietlabel']) {
        $ar = imagettfbbox (16, 0, $o['labelfont'], $gebiet);
        // FIXME die Zahlen hier sind etwas magisch durch Ausprobieren
        // gewählt
        imagefilledrectangle($mapimage, $mapwidth - $ar[4] - 55,
            $mapheight + $ar[7] - 26, $mapwidth-51, $mapheight-21, 0);
        imagefilledrectangle($mapimage, $mapwidth - $ar[4] - 54,
            $mapheight + $ar[7] - 25, $mapwidth-52, $mapheight-22, $bgindex);
        imagettftext($mapimage, 16, 0, $mapwidth - $ar[4] - 52,
            $mapheight + $ar[7] - 7, 0, $o['labelfont'], $gebiet);
    }
 
    // Feldbilder an die richtige Stelle im Gebiet einzeichnen.
    // Diese Schleife geht alle Felder durch, die im Rechteck liegen, das
    // das Gebiet umgibt.
    foreach ($fields as $key => $data) {


        // weiter, wenn das Feld ausserhalb ist
# Leeres Kartenbild erstellen
        if ($data['x'] < $min_x_found) continue;
$mapwidth = ($max_x_found - $min_x_found + 3) * $tilewidth +
        if ($data['x'] > $max_x_found) continue;
            ($max_x_found - $min_x_found + 2) * $cellspacing;
        if ($data['y'] < $min_y_found) continue;
$mapheight = ($max_y_found - $min_y_found + 3) * $tileheight +
        if ($data['y'] > $max_y_found) continue;
            ($max_y_found - $min_y_found + 2) * $cellspacing;
$mapimage = imagecreatetruecolor($mapwidth, $mapheight);
echo "x_min: $min_x_found; x_max: $max_x_found; y_min: $min_y_found; y_max: $max_y_found;";
echo "map size: $mapwidth x $mapheight\n";


        // Feld kopieren
// hintergrundfarbe
        $offset = ($o['grid']) ? 1 : 0;
imagefill($mapimage, 0, 0, imagecolorallocate($mapimage, hexdec(substr($bgcolor, 0, 2)),  
        imagecopy($mapimage,  
                                                        hexdec(substr($bgcolor, 2, 2)),  
            imagecreatefromjpeg($data['file']),  
                                                        hexdec(substr($bgcolor, 4, 2))));
            ($data['x'] - $min_x_found + $offset) *
                ($tilewidth + $o['cellspacing']) + $o['cellspacing'],  
            ($data['y'] - $min_y_found + $offset) *
                ($tileheight + $o['cellspacing']) + $o['cellspacing'],  
            0, 0,
            $tilewidth, $tileheight);


        // Feld aufhellen, wenn es nicht zum Gebiet gehört
// Gitter malen, wenn angefordert
        if ($o['lighten'] && (!array_key_exists('begehbar', $data) || !$data['begehbar'] || $gebiet != $data['g'])) {
if ($draw_grid) {
            imagecopymerge($mapimage,
    for ($x = $min_x_found; $x <= $max_x_found; $x++) {
                $aufheller,
        if ($x%5 == 0) {
                ($data['x'] - $min_x_found + $offset) *  
            $mpx = ($x - $min_x_found + 1) * ($tilewidth + $cellspacing) + $cellspacing + $tilewidth/2;
                    ($tilewidth + $o['cellspacing']) + $o['cellspacing'],
            imageline($mapimage, $mpx, 0, $mpx, $mapheight, 0);
                ($data['y'] - $min_y_found + $offset) *
                    ($tileheight + $o['cellspacing']) + $o['cellspacing'],
                0, 0,
                $tilewidth, $tileheight,
                50);
         }
         }
     }
     }
 
     for ($y = $min_y_found; $y <= $max_y_found; $y++) {
    // Ausgabe des Bildes für ein Gebiet. Im Gesamtkartenmodus gibt es nur
         if ($y%5 == 0) {
    // ein Gebiet, also auch nur eine Ausgabe; in den anderen Modi passiert
             $mpy = ($y - $min_y_found + 1) * ($tileheight + $cellspacing) + $cellspacing + $tileheight/2;
    // das hier öfter.
             imageline($mapimage, 0, $mpy, $mapwidth, $mpy, 0);
 
     if ($o["mode"] == 'atlas') {
 
        // Für die Atlas-Ausgabe werden Bilder, die nicht auf die Seite
        // passen, eventuell gedreht oder zweigeteilt oder beides. Mehr
        // ist aber nicht drin - wenn das Bild auch gedreht und zweigeteilt
        // nicht passt, fliegt es raus.
 
        $px_per_cm = $o['dpi'] / 2.54;
 
        // Bildgröße in cm
        $w = $mapwidth / $px_per_cm;
        $h = $mapheight / $px_per_cm;
 
        // Bild-Pixel-Spalte, an der wir durchschneiden, wenn nötig
        // (wird gerundet auf ganze Felder, damit wir nicht mitten in
        // einem Feld schneiden)
        $cutoff = floor($o['pagewidth'] * $px_per_cm / ($tilewidth + $o['cellspacing']))
          * ($tilewidth + $o['cellspacing']) - $o['cellspacing']/2 + 2;
 
        // Leeres Array initialisieren; eventuell haben wir mehr als
        // ein Ausgabebild
        $images = array();
 
         if ($w <= $o['pagewidth'] && $h <= $o['pageheight']) {
 
             // alles super, Bild passt auf Seite
            array_push($images, $mapimage);
 
        } elseif ($h <= $o['pagewidth'] && $w <= $o['pageheight']) {
 
            // Bild passt, wenn wir es drehen
            array_push($images, imagerotate($mapimage, 90, $bgindex));
            imagedestroy($mapimage);
 
        } elseif ($w <= 2* $o['pagewidth'] && $h <= $o['pageheight']) {
 
            // Bild passt, wenn wir es durchschneiden - also schneiden
            // und zwei Teile in Ausgabe-Array stecken
            // TODO: Formel 2*pagewidth nicht ganz korrekt, da cutoff
            // bedeutet, dass wir die Seite nicht 100% ausnutzen
            array_push($images, imagecrop($mapimage,
                [ 'x' => 0, 'y' => 0, 'height' => $mapheight, 'width' => $cutoff ]));
            array_push($images, imagecrop($mapimage,
                [ 'x' => $cutoff, 'y' => 0, 'height' => $mapheight,
                    'width' => $mapwidth - $cutoff]));
            imagedestroy($mapimage);
 
        } elseif ($w <= $o['pageheight'] && $h <= 2 * $o['pagewidth']) {
 
            // Bild passt rotiert und geschnitten
            $m = imagerotate($mapimage, 90, $bgindex);
             imagedestroy($mapimage);
            $mapimage = $m;
            $temp = $w; $w = $h; $h = $temp;
            array_push($images, imagecrop($m, [ 'x' => 0, 'y' => 0,
                'height' => $mapwidth, 'width' => $cutoff ]));
            array_push($images, imagecrop($m, [ 'x' => $cutoff, 'y' => 0,  
                'height' => $mapwidth, 'width' => $mapheight - $cutoff]));
            imagedestroy($m);
 
        } else {
 
            echo "Bild für '$gebiet' zu groß. Wähle höhere DPI oder größeres Papier\n";
 
        }
 
        // Wir führen zwei Ausgabedokumente, eins mit den oberirdischen
        // Gebieten und eins mit den Dungeons:
        if ($min_x_found < 0) {
            $xml = & $dungeons;
        } else {
            $xml = & $oberflaeche;
         }
         }
        // OpenOffice-XML an das passende Dokument anfügen
        $xml .= '<text:h text:style-name="Heading_20_2" text:outline-level="2">'.
            $gebiet."</text:h>";
        foreach ($images as $image) {
            $count++;
            // TODO: Dieser Dateiname muss eigentlich eine Prüfsumme des Inhalts
            // sein. Ist er es nicht, meldet LibreOffice immer ein "defektes
            // Dokument", bietet aber eine Reparatur an.
            ob_start();
            imagepng($image);
            $imagestring = ob_get_clean();
            $imagename = sprintf("Pictures/10000000%08X%08XDEADBEEF%08X.png",
                imagesx($image), imagesy($image), $count);
            $zipfile->addFromString($imagename, $imagestring);
            $h = imagesy($image) / $px_per_cm;
            $w = imagesx($image) / $px_per_cm;
            $xml .= <<<EOF
          <text:p text:style-name="P1">
            <draw:frame draw:style-name="fr1" draw:name="Image$count" text:anchor-type="as-char" svg:width="${w}cm" svg:height="${h}cm" draw:z-index="0">
              <draw:image xlink:href="$imagename" xlink:type="simple" xlink:show="embed" xlink:actuate="onLoad" loext:mime-type="image/png"/>
            </draw:frame>
          </text:p>
EOF;
            imagedestroy($image);
        }
    } elseif ($o['mode'] == 'einzel' || ($o['mode'] == 'gesamt' && $o['dungeons'])) {
        // Bei Einzelbildausgabe einfach PNG schreiben
        imagepng($mapimage, $o['output']."/".$gebiet.".png");
        imagedestroy($mapimage);
    } else {
        // Bei Gesamtbild traditionell JPG
        // TODO was wenn ein .png als Ausgabename gewählt wurde?
        imagejpeg($mapimage, $o['output']);
        imagedestroy($mapimage);
     }
     }
}
}
if ($o["mode"] == 'atlas')
 
{
// Felder einzeichnen
    $old_contents = $zipfile->getFromName('content.xml');
foreach ($fields as $key => $data) {
    if (!$old_contents) {
     // bild in map einfügen
        echo ATLAS_TEMPLATE." enthält keine Datei content.xml - kein .odt-Dokument?\n";
     imagecopy($mapimage,
     }
              imagecreatefromjpeg($data['file']),  
     if (!preg_match('/(.*)<text:p[^<]*<text:span[^<]*ADD_CONTENT_HERE[^<]*<\/text:span>[^<]*<\/text:p>(.*)/', $old_contents, $matches)) {
              ($data['x'] - $min_x_found + 1) * ($tilewidth + $cellspacing) + $cellspacing,
        if (!preg_match('/(.*)<text:p[^<]*ADD CONTENT HERE[^<]*<\/text:p>(.*)/', $old_contents, $matches)) {
              ($data['y'] - $min_y_found + 1) * ($tileheight + $cellspacing) + $cellspacing,
            echo "Die contents.xml im Atlas-Template entspricht nicht der erwarteten Form.\n";
              0, 0,
            echo $old_contents;
              $tilewidth, $tileheight);
            exit;
        }
    }
    $contents = $matches[1] . $oberflaeche . $dungeons . $matches[2];
    $zipfile->addFromString('content.xml', $contents);
    $zipfile->close();
    echo "Atlas erstellt. Die fertige Datei muss nun im OpenOffice/LibreOffice\n";
    echo "geöffnet und \"repariert\" werden.\n";
}
}


// ausgabe
imagejpeg($mapimage, $mapfile);
imagedestroy($mapimage);
</pre>
</pre>

Bitte beachte, dass alle Beiträge zu FreewarWiki von anderen Mitwirkenden bearbeitet, geändert oder gelöscht werden können. Reiche hier keine Texte ein, falls du nicht willst, dass diese ohne Einschränkung geändert werden können.

Du bestätigst hiermit auch, dass du diese Texte selbst geschrieben hast oder diese von einer gemeinfreien Quelle kopiert hast (weitere Einzelheiten unter FreewarWiki:Urheberrechte). ÜBERTRAGE OHNE GENEHMIGUNG KEINE URHEBERRECHTLICH GESCHÜTZTEN INHALTE!

Bitte beantworte die folgende Frage, um diese Seite speichern zu können (weitere Informationen):

Abbrechen Bearbeitungshilfe (wird in einem neuen Fenster geöffnet)

Die folgende Vorlage wird auf dieser Seite verwendet: