private function _loadLBM($file) { $lbm = fopen($file, "rb"); if (!$lbm) { return false; } fseek($lbm, 0, SEEK_END); $size = ftell($lbm); fseek($lbm, 0, SEEK_SET); $form = file_helpers::freadstring($lbm, 4, false); if ($form != "FORM") { return $this->_error("not a LBM file"); } $length = file_helpers::freadint($lbm); $pbm = file_helpers::freadstring($lbm, 4, false); if ($pbm != "PBM ") { return $this->_error("not a LBM file with PBM structure"); } while (!feof($lbm) && ftell($lbm) < $size) { $chunk = file_helpers::freadstring($lbm, 4, false); // Länge einlesen $length = file_helpers::freadbint($lbm); #echo $chunk." = ".$length."<br>\n"; // Bei ungerader Zahl aufrunden if ($length & 1) { ++$length; } switch ($chunk) { case "BMHD": // Breite & Höhe einlesen $this->image['header']['width'] = file_helpers::freadbshort($lbm); $this->image['header']['height'] = file_helpers::freadbshort($lbm); // Unbekannte Daten ( 4 Byte ) berspringen fseek($lbm, 4, SEEK_CUR); // Farbtiefe einlesen $this->image['header']['depth'] = file_helpers::freadshort($lbm); // Nur 256 Farben und nicht mehr! if ($this->image['header']['depth'] != 8) { $this->_error("Invalid File: LBM with 8bit colors are supported only"); return false; } // Kompressionflag lesen $this->image['header']['compression'] = file_helpers::freadshort($lbm); if ($this->image['header']['compression'] != 1) { $this->_error("Invalid File: LBM has unknown compression flag: " . $this->image['header']['compression']); return false; } $length -= 12; // Rest überspringen fseek($lbm, $length, SEEK_CUR); break; case "BODY": switch ($this->image['header']['compression']) { case 0: // uncompressed return false; case 1: $pos = 0; // Solange einlesen, bis Block zuende bzw. Datei zuende ist while ($length >= 0 && !feof($lbm) && ftell($lbm) < $size) { // Typ lesen $ctype = file_helpers::freadchar($lbm); --$length; if ($length == 0) { continue; } if ($ctype < 128) { for ($i = 0; $i <= $ctype; ++$i) { $this->image['body'][$pos] = file_helpers::freadchar($lbm); --$length; ++$pos; } } else { $count = 0xff - $ctype + 1; $color = file_helpers::freadchar($lbm); --$length; for ($i = 0; $i <= $count; ++$i) { $this->image['body'][$pos] = $color; ++$pos; } } } if ($pos < $this->image['header']['width'] * $this->image['header']['height']) { $this->_error("ooops? {$pos} " . $this->image['header']['width'] * $this->image['header']['height']); return false; } break; } break; case "CMAP": if ($length != 256 * 3) { $this->_error("Invalid Chunk: {$chunk} with length {$length} does not have 256 rgb values"); return false; } $this->palette->set_256rgb(s2pal::read_256rgb($lbm)); break; case "DPPS": // known but unused // known but unused case "CRNG": case "TINY": fseek($lbm, $length, SEEK_CUR); break; default: $this->_error("Unknown Chunk: {$chunk} with length {$length}"); // Rest überspringen fseek($lbm, $length, SEEK_CUR); break; } } fclose($lbm); return true; }
private function _generate() { $files = array(0 => array("PAL5.BBM", "GOU5.DAT", "TEX5.LBM"), 1 => array("PAL6.BBM", "GOU6.DAT", "TEX6.LBM"), 2 => array("PAL7.BBM", "GOU7.DAT", "TEX7.LBM")); if (!$this->_load()) { return $this->error("failed to load map"); } $s2pal = new s2pal(__DIR__ . "/S2/GFX/PALETTE/" . $files[$this->header['type']][0]); $s2gou = new s2gou(__DIR__ . "/S2/DATA/TEXTURES/" . $files[$this->header['type']][1]); $s2lbm = new s2lbm(__DIR__ . "/S2/GFX/TEXTURES/" . $files[$this->header['type']][2]); $size = 12; //6; $img = imagecreatetruecolor($this->header['width'] * $size, $this->header['height'] * $size); imagecolortransparent($img, $s2pal->apply($img, $s2pal->transparent())); for ($x = 0; $x < $this->header['width']; $x++) { for ($y = 0; $y < $this->header['height']; $y++) { $color = 0xfe; $landscape_obj = $this->blocks['objects'][$y * $this->header['width'] + $x]; // wald? if ($landscape_obj >= 0xc4 && $landscape_obj <= 0xc6) { $color = $landscape_obj - 0x9b; } else { $terrain2 = $this->blocks['terrain2'][$y * $this->header['width'] + $x]; if ($terrain2 > 0x40) { // hafen? $terrain2 -= 0x40; } $cx = -1; $cy = -1; $color = array(); switch ($terrain2) { // first row case 2: $cx = 16; $cy = 0; break; case 4: case 7: $cx = 64; $cy = 0; break; case 3: $cx = 112; $cy = 0; break; case 15: $cx = 160; $cy = 0; break; // 2nd row // 2nd row case 1: $cx = 16; $cy = 48; break; case 11: $cx = 64; $cy = 48; break; case 12: $cx = 112; $cy = 48; break; case 13: $cx = 160; $cy = 48; break; // 3rd row // 3rd row case 0: $cx = 16; $cy = 96; break; case 8: $cx = 64; $cy = 96; break; case 9: $cx = 112; $cy = 96; break; case 10: $cx = 160; $cy = 96; break; // 4th row // 4th row case 14: $color = array(236, 167, 233); break; case 18: $cx = 64; $cy = 144; break; case 16: $color = array(57, 248, 248); break; // water // water case 5: $color = array(61, 42, 240); break; case 6: $color = array(61, 42, 240); break; case 19: $color = array(61, 42, 240); break; // single pixel texture // single pixel texture case 17: $cx = 0; $cy = 254; break; // unknown bottom 3 // unknown bottom 3 case 20: $color = array(57, 248, 248); break; case 21: $color = array(57, 248, 248); break; case 22: $color = array(57, 248, 248); break; } if ($cx != -1 && $cy != -1) { $color = $s2lbm->color($cx, $cy); //trigger_error("($cx, $cy) => $color"); } else { // hardcoded $color = $color[$this->header['type']]; } } $shadow = 0x40; if ($terrain2 != 0x5 && $terrain2 != 0x10) { $shadow = $this->blocks['shadow'][$y * $this->header['width'] + $x]; } $color = $s2pal->apply($img, $s2gou->apply($s2pal, $color, $shadow)); imagefilledrectangle($img, $x * $size, $y * $size, $x * $size + $size, $y * $size + $size, $color); } } $text = $this->header['name'] . " von " . $this->header['author']; $text .= "\n"; $text .= "(" . $this->header['width'] . "x" . $this->header['height'] . ", " . $this->header['players'] . " players)"; $size = 12; $box = imagettfbbox($size, 0, __DIR__ . "/s2map.ttf", $text); imagefilledrectangle($img, 2, 2, 6 + $box[2], 8 + $size * 1.45 * 2, imagecolorallocate($img, 0xff, 0xff, 0xff)); imagettftext($img, $size, 0, 4, 18, imagecolorallocate($img, 0x0, 0x0, 0x0), __DIR__ . "/s2map.ttf", $text); $temp_file = tempnam(sys_get_temp_dir(), 's2map'); // create image file imagepng($img, $temp_file); imagedestroy($img); $img = fopen($temp_file, "rb"); $img_data = fread($img, filesize($temp_file)); fclose($img); unlink($temp_file); $map = fopen($this->file, "rb"); $map_data = fread($map, filesize($this->file)); fclose($map); $last_changed = filemtime($this->file); if (!$this->sql->query_exec("REPLACE INTO `s2map` (`hash`, `name`, `author`, `players`, `type`, `width`, `height`, `map`, `preview`, `last_changed`)\n\t\t VALUES (\n\t\t '" . $this->sql->escape($this->hash) . "',\n\t\t '" . $this->sql->escape($this->header['name']) . "',\n\t\t '" . $this->sql->escape($this->header['author']) . "',\n\t\t '" . $this->sql->escape($this->header['players']) . "',\n\t\t '" . $this->sql->escape($this->header['type']) . "',\n\t\t '" . $this->sql->escape($this->header['width']) . "',\n\t\t '" . $this->sql->escape($this->header['height']) . "',\n\t\t '" . $this->sql->escape($map_data) . "',\n\t\t '" . $this->sql->escape($img_data) . "',\n\t\t '" . $this->sql->escape($last_changed) . "')")) { return 0; } return $this->sql->query_one("SELECT preview FROM `s2map` WHERE `hash` = '" . $this->sql->escape($this->hash) . "'"); }