From 064c7fcd8534e745d03e78b44866a1c12d3f7c94 Mon Sep 17 00:00:00 2001 From: Rene Jochum Date: Wed, 27 Jul 2011 06:27:31 +0200 Subject: [PATCH] Add some more improvements to the map tool. --- tools/map/CMakeLists.txt | 47 ++++++--- tools/map/make_win32.sh | 21 ++++ tools/map/map2lnd.cpp | 7 +- tools/map/map2png.cpp | 115 +++++++++----------- tools/map/map2preview.cpp | 22 +--- tools/map/mapload.cpp | 8 +- tools/map/pngsave.cpp | 214 +++++++++++++++++++++----------------- tools/map/wzconfig.h | 6 +- 8 files changed, 233 insertions(+), 207 deletions(-) create mode 100755 tools/map/make_win32.sh diff --git a/tools/map/CMakeLists.txt b/tools/map/CMakeLists.txt index 7a6b2e2d8..44d395442 100644 --- a/tools/map/CMakeLists.txt +++ b/tools/map/CMakeLists.txt @@ -9,15 +9,28 @@ if (NOT CMAKE_BUILD_TYPE) FORCE) endif () -find_package(PhysFS 2 REQUIRED) +# For Static builds +IF(LIBTYPE STREQUAL "STATIC") + ADD_DEFINITIONS("-DQT_STATIC") + ADD_DEFINITIONS("-DQT_NODLL") + SET(CMAKE_EXE_LINKER_FLAGS -static) + SET(QT_IS_STATIC 1) + SET(QT_CONFIG "static") -find_package(PNG REQUIRED) + find_package(ZLIB REQUIRED) + find_package(JPEG REQUIRED) + find_package(TIFF REQUIRED) + + SET(QT_DEPS ${JPEG_LIBRARY} ${TIFF_LIBRARY} "mng" "lcms") +endif() -set(QT_USE_IMPORTED_TARGETS TRUE) find_package(Qt4 REQUIRED) include(${QT_USE_FILE}) add_definitions(${QT_DEFINITIONS}) +find_package(PNG 1.5 REQUIRED) +find_package(PhysFS 2 REQUIRED) + # Ugly OS-X Fix, should find a better way. IF(${CMAKE_SYSTEM_NAME} MATCHES "^Darwin") SET(QT_QTCORE_LIBRARY "-framework QtCore") @@ -61,35 +74,35 @@ set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}/bin") INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR} "${CMAKE_SOURCE_DIR}/../.." ${PNG_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR} ${QT_INCLUDES} ${PHYSFS_INCLUDE_DIR}) -set(MAPTOOLS_LIBS ${PNG_LIBRARIES} ${PHYSFS_LIBRARY} ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY}) +set(MAPTOOLS_LIBS ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} ${PHYSFS_LIBRARY} ${QT_LIBRARIES} ${QT_DEPS}) # map2lnd -# ADD_EXECUTABLE(map2lnd -# map2lnd.cpp -# mapload.cpp) -# TARGET_LINK_LIBRARIES(map2lnd ${MAPTOOLS_LIBS}) +ADD_EXECUTABLE(map2lnd + map2lnd.cpp + maplib.cpp + mapload.cpp) +TARGET_LINK_LIBRARIES(map2lnd ${MAPTOOLS_LIBS}) # map2png -# ADD_EXECUTABLE(map2png -# map2png.cpp -# mapload.cpp -# pngsave.cpp) -# TARGET_LINK_LIBRARIES(map2png ${MAPTOOLS_LIBS}) +ADD_EXECUTABLE(map2png + map2png.cpp + maplib.cpp + mapload.cpp + pngsave.cpp) +TARGET_LINK_LIBRARIES(map2png ${MAPTOOLS_LIBS}) # map2preview ADD_EXECUTABLE(map2preview map2preview.cpp maplib.cpp mapload.cpp - pngsave.cpp wzconfig.cpp) TARGET_LINK_LIBRARIES(map2preview ${MAPTOOLS_LIBS}) -# map2png +# mapconv ADD_EXECUTABLE(mapconv mapconv.cpp maplib.cpp - mapload.cpp - pngsave.cpp) + mapload.cpp) TARGET_LINK_LIBRARIES(mapconv ${MAPTOOLS_LIBS}) diff --git a/tools/map/make_win32.sh b/tools/map/make_win32.sh new file mode 100755 index 000000000..b11a4ac6d --- /dev/null +++ b/tools/map/make_win32.sh @@ -0,0 +1,21 @@ +#!/bin/sh +OLDPATH="$(pwd)" +MYPATH="$(cd -P -- "$(dirname -- "$0")" && pwd -P)" +MINGW_ENV="/opt/mingw" + +# cd "${MYPATH}/../.." +# make clean +# ./autogen.sh +# ./configure --host=i686-pc-mingw32 --enable-static PKG_CONFIG=i686-pc-mingw32-pkg-config \ +# CC_FOR_BUILD="gcc" CXX_FOR_BUILD="g++" \ +# CFLAGS="-pipe -m32 -march=i686 -O2 -g -gstabs -g3" \ +# CXXFLAGS="-pipe -m32 -march=i686 -O2 -g -gstabs -g3 -fno-exceptions" \ +# --with-installer-version="2.46.0.0" --disable-debug + +cd ${MYPATH} +cmake . -B$PWD/build -DCMAKE_BUILD_TYPE=Debug3 \ + -DCMAKE_TOOLCHAIN_FILE=${MINGW_ENV}/usr/i686-pc-mingw32/share/cmake/mingw-cross-env-conf.cmake \ + -DLIBTYPE=STATIC + +make -C$PWD/build -j4 VERBOSE=1 all +cd ${OLDPATH} diff --git a/tools/map/map2lnd.cpp b/tools/map/map2lnd.cpp index 6b0984c91..68e6835f0 100644 --- a/tools/map/map2lnd.cpp +++ b/tools/map/map2lnd.cpp @@ -5,10 +5,9 @@ // gcc -o ~/bin/map2lnd map2lnd.c mapload.c -I. -lphysfs -g -I../../lib/framework -Wall -#include -#include -#include -#include +// Tool framework +#include "maplib.h" + #include "mapload.h" #define GRDLANDVERSION 4 diff --git a/tools/map/map2png.cpp b/tools/map/map2png.cpp index b12e04a55..0aa4a8ef9 100644 --- a/tools/map/map2png.cpp +++ b/tools/map/map2png.cpp @@ -1,26 +1,13 @@ -#include -#include -#include -#include - -// Physfs -#include - -// framework -#include "physfs_ext.h" -#include "wzglobal.h" - +// tool "framework" #include "maplib.h" #include "pngsave.h" #include "mapload.h" int main(int argc, char **argv) { - char filename[PATH_MAX] = { '\0' }; - char pngfile[PATH_MAX] = { '\0' }; - char *p_filename = filename; - char *delim; - int namelength; + char *filename, *p_filename; + char *base, tmpFile[PATH_MAX]; + GAMEMAP *map; if (argc != 2) @@ -29,62 +16,54 @@ int main(int argc, char **argv) return -1; } - PHYSFS_init(argv[0]); - PHYSFS_addToSearchPath(".", 1); - - strcat(p_filename, "multiplay/maps/"); - p_filename += strlen("multiplay/maps/"); - - delim = strrchr(argv[1], PHYSFS_getDirSeparator()[0]); - if (delim) - { - delim++; - strcpy(p_filename, delim); - - namelength = strlen(filename); - if (namelength >= 3 && strcmp(&filename[namelength-3], ".wz")==0) - { - // remove ".wz" from end - filename[namelength-3] = '\0'; - } - strcpy(pngfile, delim); - strcat(pngfile, ".png"); - PHYSFS_addToSearchPath(argv[0], 1); - } - else - { - strcpy(pngfile, argv[1]); - namelength = strlen(pngfile); - if (namelength >= 3 && strcmp(&pngfile[namelength-3], ".wz")==0) - { - // remove ".wz" from end - pngfile[namelength-3] = '\0'; - } - - strcpy(p_filename, pngfile); - strcat(pngfile, ".png"); - } + physfs_init(argv[0]); + filename = physfs_addmappath(argv[1]); + p_filename = strrchr(filename, '/'); + if (p_filename) + { + p_filename++; + base = strdup(p_filename); + } + else + { + base = strdup(filename); + } + if (!PHYSFS_exists(base)) + { + PHYSFS_mkdir(base); + } map = mapLoad(filename); - if (map) + free(filename); + + if (!map) { - uint x, y; - uint8_t *pixels = (uint8_t *)malloc(map->width * map->height); + return EXIT_FAILURE; + } + + uint x, y; + uint8_t *pixels = (uint8_t *)malloc(map->width * map->height); - for (x = 0; x < map->width; x++) - { - for (y = 0; y < map->height; y++) - { - MAPTILE *psTile = mapTile(map, x, y); - int pixpos = y * map->width + x; + for (x = 0; x < map->width; x++) + { + for (y = 0; y < map->height; y++) + { + MAPTILE *psTile = mapTile(map, x, y); + int pixpos = y * map->width + x; - pixels[pixpos++] = psTile->height; - } - } - savePngI8(pngfile, pixels, map->width * 4, map->height * 4); - free(pixels); - } - mapFree(map); + pixels[pixpos++] = psTile->height; + } + } + + strcpy(tmpFile, base); + strcat(tmpFile, "/height.png"); + + savePngI8(tmpFile, pixels, map->width, map->height); + free(pixels); + + mapFree(map); + + physfs_shutdown(); return 0; } diff --git a/tools/map/map2preview.cpp b/tools/map/map2preview.cpp index 86385495b..663a5617e 100644 --- a/tools/map/map2preview.cpp +++ b/tools/map/map2preview.cpp @@ -1,13 +1,3 @@ -/* -g++ -Wall -I. -DQT_SHARED -I/usr/include/qt4 -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui \ - -o map2preview map2preview.cpp mapload.c pngsave.c wzconfig.cpp \ - -lz -lphysfs -lpng -I../../lib/framework -L/usr/local/lib -lQtCore -lQtGui - -*/ - -// Mingw -// i686-pc-mingw32-g++ -O0 -g --static -o map2preview.exe map2preview.cpp mapload.c pngsave.c -I. -I../../lib/framework -L/opt/mingw/usr/i686-pc-mingw32/lib -lpng15 -lz -lphysfs -lshfolder -lshlwapi -lpsapi -lshell32 -lws2_32 -liphlpapi -Wall - // tool "framework" #include "maplib.h" @@ -203,10 +193,6 @@ int main(int argc, char **argv) { base = strdup(filename); } - if (!PHYSFS_exists(base)) - { - PHYSFS_mkdir(base); - } map = mapLoad(filename); free(filename); @@ -277,16 +263,18 @@ int main(int argc, char **argv) } else { - debug(LOG_ERROR, "Cannot add structure data, please convert base data first.\nUse mapconf for that."); + debug(LOG_ERROR, "Cannot add structure data, please convert base data first.\nUse \"mapconv %s\" for that.", argv[1]); } strcpy(tmpFile, base); - strcat(tmpFile, "/preview.png"); + strcat(tmpFile, ".png"); QImage image(imageData, mapWidth, mapHeight, QImage::Format_RGB888); image.scaled(previewWidth, previewHeight, Qt::KeepAspectRatio).save(tmpFile, "PNG"); // savePng(tmpFile, imageData, previewWidth, previewHeight); - + + free(imageData); + mapFree(map); physfs_shutdown(); diff --git a/tools/map/mapload.cpp b/tools/map/mapload.cpp index ee69d1891..47c0e392b 100644 --- a/tools/map/mapload.cpp +++ b/tools/map/mapload.cpp @@ -34,7 +34,7 @@ GAMEMAP *mapLoad(char *filename) bool littleEndian = true; PHYSFS_file *fp = NULL; bool counted[MAX_PLAYERS]; - uint16_t *pType; + uint16_t pType; // this cries out for a class based design #define readU8(v) ( littleEndian ? PHYSFS_readULE8(fp, v) : PHYSFS_readUBE8(fp, v) ) @@ -291,15 +291,15 @@ featfailure: for (i = 0; i < map->numTerrainTypes; i++) { - readU16(pType); + readU16(&pType); - if (*pType > TER_MAX) + if (pType > TER_MAX) { debug(LOG_ERROR, "loadTerrainTypeMap: terrain type out of range"); goto terrainfailure; } - terrainTypes[i] = (uint8_t)*pType; + terrainTypes[i] = (uint8_t)pType; } if (terrainTypes[0] == 1 && terrainTypes[1] == 0 && terrainTypes[2] == 2) diff --git a/tools/map/pngsave.cpp b/tools/map/pngsave.cpp index f2ad08d46..4913cc86a 100644 --- a/tools/map/pngsave.cpp +++ b/tools/map/pngsave.cpp @@ -1,106 +1,132 @@ -#include -#include -#include -#include +// Framework +#include "maplib.h" #include #include "pngsave.h" -#define debug(x, ...) printf(__VA_ARGS__); printf("\n"); -/************************************************************************** - Save given buffer type to file. -**************************************************************************/ -bool savePngInternal(const char *filename, unsigned char *pixels, int w, int h, int bitdepth, int color_type) +static inline void PNGWriteCleanup(png_infop *info_ptr, png_structp *png_ptr, FILE* fileHandle) { - png_structp pngp; - png_infop infop; - int y; - FILE *fp; - png_bytep *row_pointers; - int const bytes = bitdepth / 8; - - if (filename == NULL || *filename == '\0' || pixels == NULL) - { - return false; - } - if (!(fp = fopen(filename, "wb"))) - { - debug(LOG_ERROR, "%s won't open for writing!", filename); - return false; - } - pngp = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!pngp) - { - debug(LOG_ERROR, "fgl_save_pixmap: Failed to create PNG write struct"); - fclose(fp); - return false; - } - - infop = png_create_info_struct(pngp); - if (!infop) - { - debug(LOG_ERROR, "fgl_save_pixmap: Failed to create PNG info struct"); - fclose(fp); - png_destroy_write_struct(&pngp, NULL); - return false; - } - - if (setjmp(png_jmpbuf(pngp))) - { - debug(LOG_ERROR, "fgl_save_pixmap: Failed to initialize IO during PNG save"); - fclose(fp); - png_destroy_write_struct(&pngp, NULL); - return false; - } - png_init_io(pngp, fp); - - /* write header */ - if (setjmp(png_jmpbuf(pngp))) - { - debug(LOG_ERROR, "fgl_save_pixmap: Failed to write PNG header"); - fclose(fp); - png_destroy_write_struct(&pngp, NULL); - return false; - } - png_set_IHDR(pngp, infop, w, h, bitdepth, color_type, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, - PNG_FILTER_TYPE_BASE); - png_write_info(pngp, infop); - - /* Create pointers to each row of the data, as libpng wants it */ - row_pointers = (png_byte **)malloc(sizeof(png_bytep) * h); - for (y = 0; y < h; y++) - { - row_pointers[y] = pixels + (y * w * bytes); - } - - if (setjmp(png_jmpbuf(pngp))) - { - debug(LOG_ERROR, "fgl_save_pixmap: Failed to write PNG body"); - fclose(fp); - png_destroy_write_struct(&pngp, NULL); - return false; - } - png_write_image(pngp, row_pointers); - - if (setjmp(png_jmpbuf(pngp))) - { - debug(LOG_ERROR, "fgl_save_pixmap: Failed to finalize PNG"); - fclose(fp); - png_destroy_write_struct(&pngp, NULL); - return false; - } - png_write_end(pngp, NULL); - - free(row_pointers); - fclose(fp); - png_destroy_write_struct(&pngp, NULL); - - return true; + if (*info_ptr != NULL) + png_destroy_info_struct(*png_ptr, info_ptr); + if (*png_ptr != NULL) + png_destroy_write_struct(png_ptr, NULL); + if (fileHandle != NULL) + fclose(fileHandle); } +static bool savePngInternal(const char *fileName, unsigned char *pixels, int w, int h, int bitdepth, int color_type) +{ + unsigned char** scanlines = NULL; + png_infop info_ptr = NULL; + png_structp png_ptr = NULL; + FILE *fp; + + if (fileName == NULL || *fileName == '\0' || pixels == NULL) + { + return false; + } + if (!(fp = fopen(fileName, "wb"))) + { + debug(LOG_ERROR, "%s won't open for writing!", fileName); + return false; + } + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) + { + debug(LOG_ERROR, "savePng: Unable to create png struct\n"); + PNGWriteCleanup(&info_ptr, &png_ptr, fp); + return false; + } + + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + { + debug(LOG_ERROR, "savePng: Unable to create png info struct\n"); + PNGWriteCleanup(&info_ptr, &png_ptr, fp); + return false; + } + + // If libpng encounters an error, it will jump into this if-branch + if (setjmp(png_jmpbuf(png_ptr))) + { + debug(LOG_ERROR, "savePng: Error encoding PNG data\n"); + PNGWriteCleanup(&info_ptr, &png_ptr, fp); + return false; + } + else + { + unsigned int channelsPerPixel = 3; + unsigned int currentRow, row_stride; + + if (color_type == PNG_COLOR_TYPE_GRAY) + { + channelsPerPixel = 1; + } + row_stride = w * channelsPerPixel * bitdepth / 8; + + scanlines = (unsigned char **)malloc(sizeof(unsigned char *) * h); + if (scanlines == NULL) + { + debug(LOG_ERROR, "pie_PNGSaveFile: Couldn't allocate memory\n"); + PNGWriteCleanup(&info_ptr, &png_ptr, fp); + return false; + } + + png_init_io(png_ptr, fp); + + //png_set_write_fn(png_ptr, fp, wzpng_write_data, wzpng_flush_data); + + // Set the compression level of ZLIB + // Right now we stick with the default, since that one is the + // fastest which still produces acceptable filesizes. + // The highest compression level hardly produces smaller files than default. + // + // Below are some benchmarks done while taking screenshots at 1280x1024 + // Z_NO_COMPRESSION: + // black (except for GUI): 398 msec + // 381, 391, 404, 360 msec + // + // Z_BEST_SPEED: + // black (except for GUI): 325 msec + // 611, 406, 461, 608 msec + // + // Z_DEFAULT_COMPRESSION: + // black (except for GUI): 374 msec + // 1154, 1121, 627, 790 msec + // + // Z_BEST_COMPRESSION: + // black (except for GUI): 439 msec + // 1600, 1078, 1613, 1700 msec + + // Not calling this function is equal to using the default + // so to spare some CPU cycles we comment this out. + // png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION); + png_set_IHDR(png_ptr, info_ptr, w, h, bitdepth, + color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + png_write_info(png_ptr, info_ptr); + + // Create an array of scanlines + for (currentRow = 0; currentRow < h; ++currentRow) + { + // We're filling the scanline from the bottom up here, + // otherwise we'd have a vertically mirrored image. + scanlines[currentRow] = pixels + row_stride * (h - currentRow - 1); + } + + png_write_image(png_ptr, (png_bytepp)scanlines); + + png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); + png_write_end(png_ptr, NULL); + } + + free(scanlines); + PNGWriteCleanup(&info_ptr, &png_ptr, fp); + + return true; +} /************************************************************************** Save an RGBA8888 image buffer to a PNG file. diff --git a/tools/map/wzconfig.h b/tools/map/wzconfig.h index 9476cd4b6..1b1753714 100644 --- a/tools/map/wzconfig.h +++ b/tools/map/wzconfig.h @@ -1,9 +1,9 @@ #ifndef TOOLS_MAP_WZCONFIG_H #define TOOLS_MAP_WZCONFIG_H -#include -#include -#include +#include +#include +#include struct Rotation; struct Vector3i;