summaryrefslogtreecommitdiffstats
path: root/gis/qmapshack/rgb2pct.patch
diff options
context:
space:
mode:
Diffstat (limited to 'gis/qmapshack/rgb2pct.patch')
-rw-r--r--gis/qmapshack/rgb2pct.patch971
1 files changed, 971 insertions, 0 deletions
diff --git a/gis/qmapshack/rgb2pct.patch b/gis/qmapshack/rgb2pct.patch
new file mode 100644
index 0000000000..92c5df8776
--- /dev/null
+++ b/gis/qmapshack/rgb2pct.patch
@@ -0,0 +1,971 @@
+From 763cfc149566325cce9e4690cb7b5f986048f86a Mon Sep 17 00:00:00 2001
+From: Oliver Eichler <oliver.eichler@dspsolutions.de>
+Date: Thu, 12 Sep 2019 20:32:06 +0200
+Subject: [PATCH] [QMS-3] Add qmt_rgb2pct from former sub-repo
+
+---
+ src/qmt_rgb2pct/CApp.cpp | 280 +++++++++++++++++++++++
+ src/qmt_rgb2pct/CApp.h | 55 +++++
+ src/qmt_rgb2pct/CMakeLists.txt | 117 ++++++++++
+ src/qmt_rgb2pct/README.md | 5 +
+ src/qmt_rgb2pct/locale/qmt_rgb2pct.ts | 126 ++++++++++
+ src/qmt_rgb2pct/locale/qmt_rgb2pct_de.ts | 127 ++++++++++
+ src/qmt_rgb2pct/main.cpp | 155 +++++++++++++
+ src/qmt_rgb2pct/version.h | 33 +++
+ 8 files changed, 898 insertions(+)
+ create mode 100644 src/qmt_rgb2pct/CApp.cpp
+ create mode 100644 src/qmt_rgb2pct/CApp.h
+ create mode 100644 src/qmt_rgb2pct/CMakeLists.txt
+ create mode 100644 src/qmt_rgb2pct/README.md
+ create mode 100644 src/qmt_rgb2pct/locale/qmt_rgb2pct.ts
+ create mode 100644 src/qmt_rgb2pct/locale/qmt_rgb2pct_de.ts
+ create mode 100644 src/qmt_rgb2pct/main.cpp
+ create mode 100644 src/qmt_rgb2pct/version.h
+
+diff --git a/src/qmt_rgb2pct/CApp.cpp b/src/qmt_rgb2pct/CApp.cpp
+new file mode 100644
+index 00000000..993ed759
+--- /dev/null
++++ b/src/qmt_rgb2pct/CApp.cpp
+@@ -0,0 +1,280 @@
++/**********************************************************************************************
++ Copyright (C) 2018 Oliver Eichler oliver.eichler@gmx.de
++
++ This program is free software: you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation, either version 3 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program. If not, see <http://www.gnu.org/licenses/>.
++
++**********************************************************************************************/
++
++#include "CApp.h"
++
++#include <gdal_alg.h>
++#include <gdal_priv.h>
++#include <iostream>
++
++const GDALColorEntry CApp::noColor = {255,255,255,0};
++
++void printStdoutQString(const QString& str)
++{
++ QByteArray array = str.toUtf8();
++ printf("%s", array.data());
++ printf("\n");
++}
++
++void printStderrQString(const QString& str)
++{
++ QByteArray array = str.toUtf8();
++ fprintf(stderr, "%s", array.data());
++ fprintf(stderr, "\n");
++}
++
++
++
++CApp::CApp(qint32 ncolors, const QString& pctFilename, const QString &sctFilename, const QString &srcFilename, const QString &tarFilename)
++ : ncolors(ncolors)
++ , pctFilename(pctFilename)
++ , sctFilename(sctFilename)
++ , srcFilename(srcFilename)
++ , tarFilename(tarFilename)
++{
++ GDALAllRegister();
++}
++
++qint32 CApp::exec()
++{
++ qint32 res = 0;
++ GDALColorTable * ct = nullptr;
++ GDALDataset * dsSrc = nullptr;
++ try
++ {
++ dsSrc = (GDALDataset*)GDALOpenShared(srcFilename.toUtf8(),GA_ReadOnly);
++ if(dsSrc == nullptr)
++ {
++ throw tr("Failed to open source file.");
++ }
++
++ if(dsSrc->GetRasterCount() < 3 || dsSrc->GetRasterCount() > 4)
++ {
++ throw tr("Raster band count of source file must be either 3 or 4.");
++ }
++
++ if(QFile(tarFilename).exists())
++ {
++ QFile::remove(tarFilename);
++ }
++
++ ct = createColorTable(ncolors, pctFilename, dsSrc);
++ saveColorTable(ct, sctFilename);
++ ditherMap(dsSrc, tarFilename, ct);
++ }
++ catch(const QString& msg)
++ {
++ printStderrQString(msg);
++ res = -1;
++ }
++
++
++ GDALClose(dsSrc);
++ delete ct;
++ return res;
++}
++
++GDALColorTable * CApp::createColorTable(qint32 ncolors, const QString& pctFilename, GDALDataset * dataset)
++{
++ GDALColorTable * ct = nullptr;
++ try
++ {
++ if(pctFilename.isEmpty())
++ {
++ ct = (GDALColorTable*)GDALCreateColorTable(GPI_RGB);
++
++ printStdoutQString(tr("Calculate optimal color table from source file"));
++
++ int ok = GDALComputeMedianCutPCT(dataset->GetRasterBand(1),
++ dataset->GetRasterBand(2),
++ dataset->GetRasterBand(3),
++ nullptr,
++ ncolors,
++ ct,
++ GDALTermProgress,
++ 0
++ );
++
++ if(ok != CE_None)
++ {
++ throw tr("Failed to create color table.");
++ }
++ }
++ else
++ {
++ GDALDataset * dsPct = (GDALDataset*)GDALOpenShared(pctFilename.toUtf8(),GA_ReadOnly);
++ if(dsPct == nullptr)
++ {
++ throw tr("Failed to open file with palette.");
++ }
++
++ GDALRasterBand * band = (GDALRasterBand*)dsPct->GetRasterBand(1);
++
++ if((dsPct->GetRasterCount() != 1) || (band->GetColorInterpretation() != GCI_PaletteIndex))
++ {
++ GDALClose(dsPct);
++ throw tr("Palette file does not have a single band with a color table");
++ }
++
++ int ok = 0;
++ band->GetNoDataValue(&ok);
++
++ if(ok || band->GetColorTable()->GetColorEntryCount() > 255)
++ {
++ GDALClose(dsPct);
++ throw tr("The color table must not contain a \"no data\" value and it's size must not exceed 255 colors.");
++ }
++
++ ct = dsPct->GetRasterBand(1)->GetColorTable()->Clone();
++ }
++ }
++ catch(const QString& msg)
++ {
++ delete ct;
++ throw msg;
++ }
++ return ct;
++}
++
++void CApp::saveColorTable(GDALColorTable * ct, QString& sctFilename)
++{
++ if(sctFilename.isEmpty())
++ {
++ return;
++ }
++
++ if(!sctFilename.endsWith(".vrt"))
++ {
++ sctFilename += ".vrt";
++ }
++
++ QByteArray buf = sctFilename.toUtf8();
++ printStdoutQString(tr("Save color table to: %1").arg(buf.data()));
++
++ GDALDriverManager * drvman = GetGDALDriverManager();
++ GDALDriver * driver = drvman->GetDriverByName("VRT");
++ GDALDataset * dataset = driver->Create(sctFilename.toUtf8(), 1, 1, 1, GDT_Byte, {});
++
++ dataset->GetRasterBand(1)->SetColorInterpretation(GCI_PaletteIndex);
++ dataset->GetRasterBand(1)->SetColorTable(ct);
++
++ dataset->FlushCache();
++ GDALClose(dataset);
++}
++
++void CApp::ditherMap(GDALDataset * dsSrc, const QString& tarFilename, GDALColorTable *ct)
++{
++ if(tarFilename.isEmpty())
++ {
++ return;
++ }
++
++ qint32 xsize = dsSrc->GetRasterBand(1)->GetXSize();
++ qint32 ysize = dsSrc->GetRasterBand(1)->GetYSize();
++
++ GDALDriverManager * drvman = nullptr;
++ GDALDriver * driver = nullptr;
++ GDALDataset * dataset = nullptr;
++
++ try
++ {
++ const char * cargs[] = {"TILED=YES","COMPRESS=LZW", 0};
++ drvman = GetGDALDriverManager();
++ driver = drvman->GetDriverByName("GTiff");
++ dataset = driver->Create(tarFilename.toUtf8(), xsize, ysize, 1, GDT_Byte, (char**)cargs);
++
++ if(dataset == nullptr)
++ {
++ throw tr("Failed to create target file.");
++ }
++
++ dataset->GetRasterBand(1)->SetColorTable(ct);
++ dataset->GetRasterBand(1)->SetNoDataValue(ct->GetColorEntryCount());
++ dataset->SetProjection(dsSrc->GetProjectionRef());
++
++ double adfGeoTransform[6] = {0};
++ dsSrc->GetGeoTransform(adfGeoTransform);
++ dataset->SetGeoTransform(adfGeoTransform);
++
++ printStdoutQString(tr("Dither source file to target file"));
++ int res = GDALDitherRGB2PCT(dsSrc->GetRasterBand(1),
++ dsSrc->GetRasterBand(2),
++ dsSrc->GetRasterBand(3),
++ dataset->GetRasterBand(1),
++ ct,
++ GDALTermProgress,
++ 0
++ );
++ if(res != CE_None)
++ {
++ throw tr("Failed to dither file.");
++ }
++
++ if(dsSrc->GetRasterCount() == 3)
++ {
++ return;
++ }
++
++ GDALRasterBand * alpha = dsSrc->GetRasterBand(4);
++ GDALRasterBand * band = dataset->GetRasterBand(1);
++
++ QByteArray buffer1(xsize, 0);
++ QByteArray buffer2(xsize, 0);
++
++ quint8 nodata = band->GetNoDataValue();
++ printStdoutQString(tr("Apply alpha channel as no data value to target file"));
++ for(int y = 0; y < ysize; y++)
++ {
++ GDALTermProgress(double(xsize * y)/(xsize*ysize),0,0);
++ res = alpha->RasterIO(GF_Read, 0, y, xsize, 1, buffer1.data(), xsize, 1, GDT_Byte, 0, 0);
++ if(res != CE_None)
++ {
++ throw tr("Failed to read from alpha channel.");
++ }
++
++ res = band->RasterIO(GF_Read, 0, y, xsize, 1, buffer2.data(), xsize, 1, GDT_Byte, 0, 0);
++ if(res != CE_None)
++ {
++ throw tr("Failed to read from target file.");
++ }
++
++ for(int x = 0; x < xsize; x++)
++ {
++ if(buffer1[x] != char(0xFF))
++ {
++ buffer2[x] = nodata;
++ }
++ }
++
++ res = band->RasterIO(GF_Write, 0, y, xsize, 1, buffer2.data(), xsize, 1, GDT_Byte, 0, 0);
++ if(res != CE_None)
++ {
++ throw tr("Failed to write to target file.");
++ }
++ }
++ GDALTermProgress(1.0,0,0);
++ }
++ catch(const QString& msg)
++ {
++ GDALClose(dataset);
++ throw msg;
++ }
++
++ dataset->FlushCache();
++ GDALClose(dataset);
++}
+diff --git a/src/qmt_rgb2pct/CApp.h b/src/qmt_rgb2pct/CApp.h
+new file mode 100644
+index 00000000..e2e0f7ca
+--- /dev/null
++++ b/src/qmt_rgb2pct/CApp.h
+@@ -0,0 +1,55 @@
++/**********************************************************************************************
++ Copyright (C) 2018 Oliver Eichler oliver.eichler@gmx.de
++
++ This program is free software: you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation, either version 3 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program. If not, see <http://www.gnu.org/licenses/>.
++
++**********************************************************************************************/
++
++#ifndef CAPP_H
++#define CAPP_H
++
++#include <QtCore>
++#include <gdal.h>
++
++class GDALColorTable;
++class GDALDataset;
++
++class CApp
++{
++ Q_DECLARE_TR_FUNCTIONS(CApp)
++public:
++ CApp(qint32 ncolors, const QString& pctFilename, const QString& sctFilename, const QString& srcFilename, const QString& tarFilename);
++ virtual ~CApp() = default;
++
++ qint32 exec();
++
++private:
++ static GDALColorTable * createColorTable(qint32 ncolors, const QString& pctFilename, GDALDataset *dataset);
++ static void saveColorTable(GDALColorTable *ct, QString &sctFilename);
++ static void ditherMap(GDALDataset * dsSrc, const QString& tarFilename, GDALColorTable *ct);
++
++ qint32 ncolors = 0;
++ QString pctFilename;
++ QString sctFilename;
++ QString srcFilename;
++ QString tarFilename;
++
++ static const GDALColorEntry noColor;
++};
++
++void printStdoutQString(const QString& str);
++void printStderrQString(const QString& str);
++
++#endif //CAPP_H
++
+diff --git a/src/qmt_rgb2pct/CMakeLists.txt b/src/qmt_rgb2pct/CMakeLists.txt
+new file mode 100644
+index 00000000..c763595e
+--- /dev/null
++++ b/src/qmt_rgb2pct/CMakeLists.txt
+@@ -0,0 +1,117 @@
++# Prevent custom commands/targets outputs to be deleted by make clean
++# We need this to prevent .ts files from being deleted with make clean, when
++# UPDATE_TRANSLATIONS=ON
++# WARNING: Only works with Makefile generator.
++set_directory_properties(PROPERTIES CLEAN_NO_CUSTOM TRUE)
++# Find includes in corresponding build directories
++set(CMAKE_INCLUDE_CURRENT_DIR ON)
++# Instruct CMake to run moc automatically when needed.
++set(CMAKE_AUTOMOC ON)
++
++###############################################################################################
++# Setup application name and version tags
++###############################################################################################
++
++set(APPLICATION_NAME qmt_rgb2pct)
++set(RGB2PCT_VERSION_MAJOR 1)
++set(RGB2PCT_VERSION_MINOR 0)
++set(RGB2PCT_VERSION_PATCH 0)
++
++add_definitions(
++ -DVER_MAJOR=${RGB2PCT_VERSION_MAJOR}
++ -DVER_MINOR=${RGB2PCT_VERSION_MINOR}
++ -DVER_STEP=${RGB2PCT_VERSION_PATCH}
++ -DVER_TWEAK=${VERSION_SUFFIX}
++ -DAPPLICATION_NAME=${APPLICATION_NAME}
++)
++
++###############################################################################################
++# All source files needed to compile
++###############################################################################################
++set( SRCS
++ main.cpp
++ CApp.cpp
++)
++
++set( HDRS
++ version.h
++ CApp.h
++)
++
++set( UIS
++)
++
++set( RCS
++)
++
++###############################################################################################
++# Some Qt magic
++###############################################################################################
++
++qt5_wrap_ui(UI_HDRS ${UIS})
++qt5_add_resources(RC_SRCS ${RCS})
++
++###############################################################################################
++# Translation related stuff
++###############################################################################################
++translate_ts(${APPLICATION_NAME}_QM_FILES
++ UPDATE_TRANSLATIONS ${UPDATE_TRANSLATIONS}
++ UPDATE_OPTIONS "-I${CMAKE_CURRENT_SOURCE_DIR}" ${KEEP_OLD_TRANSLATIONS}
++ SOURCES ${SRCS} ${HDRS} ${UIS}
++ TEMPLATE ${APPLICATION_NAME}
++ TRANSLATION_DIR "locale"
++)
++
++###############################################################################################
++# Build source file and include paths lists
++###############################################################################################
++set(MAININP
++ ${SRCS}
++ ${HDRS}
++ ${UI_HDRS}
++ ${RC_SRCS}
++ ${${APPLICATION_NAME}_QM_FILES}
++ ${${APPLICATION_NAME}_DESKTOP_FILES}
++)
++
++include_directories(
++ SYSTEM # this prevents warnings from non-QMS headers
++ ${CMAKE_BINARY_DIR}
++ ${GDAL_INCLUDE_DIRS}
++ ${PROJ4_INCLUDE_DIRS}
++)
++
++if(APPLE)
++ INCLUDE_DIRECTORIES(/System/Library/Frameworks/Foundation.framework)
++ INCLUDE_DIRECTORIES(/System/Library/Frameworks/DiskArbitration.framework)
++endif(APPLE)
++
++
++###############################################################################################
++# Build the executable and define necessary libraries.
++###############################################################################################
++add_executable(${APPLICATION_NAME} WIN32 ${MAININP})
++
++target_link_libraries(${APPLICATION_NAME}
++ Qt5::Core
++ ${GDAL_LIBRARIES}
++ ${PROJ4_LIBRARIES}
++)
++
++if(APPLE)
++ target_link_libraries(${APPLICATION_NAME}
++ ${Foundation_LIBRARY}
++ ${DiskArbitration_LIBRARY}
++ )
++endif(APPLE)
++
++
++###############################################################################################
++# Install target related stuff
++###############################################################################################
++install(TARGETS ${APPLICATION_NAME} DESTINATION ${BIN_INSTALL_DIR})
++
++if (UNIX AND NOT WIN32 AND NOT APPLE)
++ install(FILES ${${APPLICATION_NAME}_QM_FILES} DESTINATION ${DATA_INSTALL_PREFIX}/${APPLICATION_NAME}/translations)
++ install(FILES ${${APPLICATION_NAME}_DESKTOP_FILES} DESTINATION ${XDG_APPS_DIR})
++endif (UNIX AND NOT WIN32 AND NOT APPLE)
+diff --git a/src/qmt_rgb2pct/README.md b/src/qmt_rgb2pct/README.md
+new file mode 100644
+index 00000000..21e6c750
+--- /dev/null
++++ b/src/qmt_rgb2pct/README.md
+@@ -0,0 +1,5 @@
++This is a sub-project of QMapShack and it's not supposed to compile on it's own. Please refere to
++
++https://bitbucket.org/maproom/qmapshack/overview
++
++to check out and compile this project.
+\ No newline at end of file
+diff --git a/src/qmt_rgb2pct/locale/qmt_rgb2pct.ts b/src/qmt_rgb2pct/locale/qmt_rgb2pct.ts
+new file mode 100644
+index 00000000..02904577
+--- /dev/null
++++ b/src/qmt_rgb2pct/locale/qmt_rgb2pct.ts
+@@ -0,0 +1,126 @@
++<?xml version="1.0" encoding="utf-8"?>
++<!DOCTYPE TS>
++<TS version="2.1">
++<context>
++ <name>CApp</name>
++ <message>
++ <location filename="../CApp.cpp" line="63"/>
++ <source>Failed to open source file.</source>
++ <translation type="unfinished"></translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="68"/>
++ <source>Raster band count of source file must be either 3 or 4.</source>
++ <translation type="unfinished"></translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="101"/>
++ <source>Calculate optimal color table from source file</source>
++ <translation type="unfinished"></translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="115"/>
++ <source>Failed to create color table.</source>
++ <translation type="unfinished"></translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="123"/>
++ <source>Failed to open file with palette.</source>
++ <translation type="unfinished"></translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="131"/>
++ <source>Palette file does not have a single band with a color table</source>
++ <translation type="unfinished"></translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="140"/>
++ <source>The color table must not contain a &quot;no data&quot; value and it&apos;s size must not exceed 255 colors.</source>
++ <translation type="unfinished"></translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="167"/>
++ <source>Save color table to: %1</source>
++ <translation type="unfinished"></translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="203"/>
++ <source>Failed to create target file.</source>
++ <translation type="unfinished"></translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="214"/>
++ <source>Dither source file to target file</source>
++ <translation type="unfinished"></translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="225"/>
++ <source>Failed to dither file.</source>
++ <translation type="unfinished"></translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="240"/>
++ <source>Apply alpha channel as no data value to target file</source>
++ <translation type="unfinished"></translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="247"/>
++ <source>Failed to read from alpha channel.</source>
++ <translation type="unfinished"></translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="253"/>
++ <source>Failed to read from target file.</source>
++ <translation type="unfinished"></translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="267"/>
++ <source>Failed to write to target file.</source>
++ <translation type="unfinished"></translation>
++ </message>
++</context>
++<context>
++ <name>main</name>
++ <message>
++ <location filename="../main.cpp" line="96"/>
++ <source>
++Convert a map file with RGBA color coding to a color palette coding.</source>
++ <translation type="unfinished"></translation>
++ </message>
++ <message>
++ <location filename="../main.cpp" line="99"/>
++ <source>Source file.</source>
++ <translation type="unfinished"></translation>
++ </message>
++ <message>
++ <location filename="../main.cpp" line="100"/>
++ <source>Target file.</source>
++ <translation type="unfinished"></translation>
++ </message>
++ <message>
++ <location filename="../main.cpp" line="104"/>
++ <source>Number of colors. (default: 255)</source>
++ <translation type="unfinished"></translation>
++ </message>
++ <message>
++ <location filename="../main.cpp" line="107"/>
++ <source>Input palette file for color table (*.vrt)</source>
++ <translation type="unfinished"></translation>
++ </message>
++ <message>
++ <location filename="../main.cpp" line="110"/>
++ <source>Save color table to palette file (*.vrt)</source>
++ <translation type="unfinished"></translation>
++ </message>
++ <message>
++ <location filename="../main.cpp" line="120"/>
++ <source>There must be a source and destination file.</source>
++ <translation type="unfinished"></translation>
++ </message>
++ <message>
++ <location filename="../main.cpp" line="143"/>
++ <source>--ncolors must be an integer value less than 256</source>
++ <translation type="unfinished"></translation>
++ </message>
++</context>
++</TS>
+diff --git a/src/qmt_rgb2pct/locale/qmt_rgb2pct_de.ts b/src/qmt_rgb2pct/locale/qmt_rgb2pct_de.ts
+new file mode 100644
+index 00000000..9622b8d9
+--- /dev/null
++++ b/src/qmt_rgb2pct/locale/qmt_rgb2pct_de.ts
+@@ -0,0 +1,127 @@
++<?xml version="1.0" encoding="utf-8"?>
++<!DOCTYPE TS>
++<TS version="2.1" language="de_DE">
++<context>
++ <name>CApp</name>
++ <message>
++ <location filename="../CApp.cpp" line="63"/>
++ <source>Failed to open source file.</source>
++ <translation>Konnte Quelldatei nicht öffnen.</translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="68"/>
++ <source>Raster band count of source file must be either 3 or 4.</source>
++ <translation>Die Anzahl der Rasterbänder muss entweder 3 oder 4 sein.</translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="101"/>
++ <source>Calculate optimal color table from source file</source>
++ <translation>Berechne die optimale Farbtabelle für die Quelldatei</translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="115"/>
++ <source>Failed to create color table.</source>
++ <translation>Konnte die Farbtabelle nicht erstellen.</translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="123"/>
++ <source>Failed to open file with palette.</source>
++ <translation>Konnte die Datei mit der Palette nicht öffnen.</translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="131"/>
++ <source>Palette file does not have a single band with a color table</source>
++ <translation>Die Datei mit der Palette hat kein einzelnes Band mit einer Farbtabelle</translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="140"/>
++ <source>The color table must not contain a &quot;no data&quot; value and it&apos;s size must not exceed 255 colors.</source>
++ <translation>Die Farbtabelle darf keinen Eintrag für &quot;no data&quot; haben und ihre Größe darf nicht 255 Farben überschreiten.</translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="167"/>
++ <source>Save color table to: %1</source>
++ <translation>Speichere Farbtabelle in: %1</translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="203"/>
++ <source>Failed to create target file.</source>
++ <translation>Konnte Zieldatei nicht erstellen.</translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="214"/>
++ <source>Dither source file to target file</source>
++ <translation>Wandle Quelldatei in Zieldatei um</translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="225"/>
++ <source>Failed to dither file.</source>
++ <translation>Konnte die Datei nicht umwandeln.</translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="240"/>
++ <source>Apply alpha channel as no data value to target file</source>
++ <translation>Wandle für die Zieldatei den Alphakanal in &quot;no data&quot; Werte um </translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="247"/>
++ <source>Failed to read from alpha channel.</source>
++ <translation>Konnte den Alphakanal nicht lesen.</translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="253"/>
++ <source>Failed to read from target file.</source>
++ <translation>Konnte die Zieldatei nicht lesen.</translation>
++ </message>
++ <message>
++ <location filename="../CApp.cpp" line="267"/>
++ <source>Failed to write to target file.</source>
++ <translation>Konnte die Zieldatei nicht schreiben.</translation>
++ </message>
++</context>
++<context>
++ <name>main</name>
++ <message>
++ <location filename="../main.cpp" line="96"/>
++ <source>
++Convert a map file with RGBA color coding to a color palette coding.</source>
++ <translation>
++Konvertiert eine Kartendatei mit RGBA Farbschema in eine Kartendatei mit Farbtabelle.</translation>
++ </message>
++ <message>
++ <location filename="../main.cpp" line="99"/>
++ <source>Source file.</source>
++ <translation>Quelldatei.</translation>
++ </message>
++ <message>
++ <location filename="../main.cpp" line="100"/>
++ <source>Target file.</source>
++ <translation>Zieldatei.</translation>
++ </message>
++ <message>
++ <location filename="../main.cpp" line="104"/>
++ <source>Number of colors. (default: 255)</source>
++ <translation>Anzahl an Farben (Vorgabe: 255)</translation>
++ </message>
++ <message>
++ <location filename="../main.cpp" line="107"/>
++ <source>Input palette file for color table (*.vrt)</source>
++ <translation>Datei mit Palette als Vorgabe für die Farbtabelle (*.vrt) </translation>
++ </message>
++ <message>
++ <location filename="../main.cpp" line="110"/>
++ <source>Save color table to palette file (*.vrt)</source>
++ <translation>Farbtabelle in Datei mit Palette sichern (*.vrt)</translation>
++ </message>
++ <message>
++ <location filename="../main.cpp" line="120"/>
++ <source>There must be a source and destination file.</source>
++ <translation>Es muss eine Quell- und eine Zieldatei angegeben werden.</translation>
++ </message>
++ <message>
++ <location filename="../main.cpp" line="143"/>
++ <source>--ncolors must be an integer value less than 256</source>
++ <translation>--ncolors muss eine ganze Zahl kleiner 256 sein</translation>
++ </message>
++</context>
++</TS>
+diff --git a/src/qmt_rgb2pct/main.cpp b/src/qmt_rgb2pct/main.cpp
+new file mode 100644
+index 00000000..4ff9a9ae
+--- /dev/null
++++ b/src/qmt_rgb2pct/main.cpp
+@@ -0,0 +1,155 @@
++/**********************************************************************************************
++ Copyright (C) 2018 Oliver Eichler oliver.eichler@gmx.de
++
++ This program is free software: you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation, either version 3 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program. If not, see <http://www.gnu.org/licenses/>.
++
++**********************************************************************************************/
++
++#include "CApp.h"
++#include "version.h"
++#include <QtCore>
++
++#ifdef Q_OS_MACOS
++static QDir getApplicationDir(QString subdir)
++{
++ QDir appDir(QCoreApplication::applicationDirPath());
++ appDir.cdUp();
++ appDir.cd(subdir);
++ return appDir;
++}
++#endif
++static void prepareTranslator(QString translationPath, QString translationPrefix)
++{
++ QString locale = QLocale::system().name();
++ QDir dir(translationPath);
++ if(!QFile::exists(dir.absoluteFilePath(translationPrefix + locale)))
++ {
++ locale = locale.left(2);
++ }
++
++ QCoreApplication* app = (QCoreApplication*) QCoreApplication::instance();
++ QTranslator *qtTranslator = new QTranslator(app);
++
++ if (qtTranslator->load(translationPrefix + locale, translationPath))
++ {
++ app->installTranslator(qtTranslator);
++ }
++}
++
++static void loadTranslations()
++{
++#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(__FreeBSD_kernel__) || defined(__GNU__) || defined(Q_OS_CYGWIN)
++ QString resourceDir = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
++ QString translationPath = QCoreApplication::applicationDirPath();
++ translationPath.replace(QRegExp("bin$"), "share/" APP_STR "/translations");
++ prepareTranslator(resourceDir, "qt_");
++ prepareTranslator(translationPath, APP_STR "_");
++#endif
++
++#ifdef Q_OS_OSX
++ // os x
++ static QString relTranslationDir = "Resources/translations"; // app
++ QString translationPath = getApplicationDir(relTranslationDir).absolutePath();
++ prepareTranslator(translationPath, "qt_");
++ prepareTranslator(translationPath, APP_STR "_");
++#endif
++
++#ifdef Q_OS_WIN
++ QString apppath = QCoreApplication::applicationDirPath();
++ apppath = apppath.replace("/", "\\");
++ QString appResourceDir = QString("%1\\translations").arg(apppath).toUtf8();
++ prepareTranslator(appResourceDir, "qtbase_");
++ prepareTranslator(appResourceDir, APP_STR "_");
++#endif
++
++}
++
++int main(int argc, char ** argv)
++{
++ QCoreApplication app(argc, argv);
++ QCoreApplication::setApplicationName(APP_STR);
++ QCoreApplication::setApplicationVersion(VER_STR);
++ if(QString(VER_SUFFIX).isEmpty())
++ {
++ QCoreApplication::setApplicationVersion(VER_STR);
++ }
++ else
++ {
++ QCoreApplication::setApplicationVersion(VER_STR "." VER_SUFFIX);
++ }
++
++
++ loadTranslations();
++
++ QCommandLineParser parser;
++ parser.setApplicationDescription(QCoreApplication::translate("main", "\nConvert a map file with RGBA color coding to a color palette coding."));
++ parser.addHelpOption();
++ parser.addVersionOption();
++ parser.addPositionalArgument("source", QCoreApplication::translate("main", "Source file."));
++ parser.addPositionalArgument("target", QCoreApplication::translate("main", "Target file."));
++
++ parser.addOptions({
++ {
++ {"n","ncolors"}, QCoreApplication::translate("main", "Number of colors. (default: 255)"), "number", "255"
++ },
++ {
++ {"p","pct"}, QCoreApplication::translate("main", "Input palette file for color table (*.vrt)"), "filename", ""
++ },
++ {
++ {"s","sct"}, QCoreApplication::translate("main", "Save color table to palette file (*.vrt)"), "filename", ""
++ },
++ });
++
++ // Process the actual command line arguments given by the user
++ parser.process(app);
++
++ if(parser.positionalArguments().count() == 1 && parser.value("sct").isEmpty())
++ {
++ printStderrQString("");
++ printStderrQString(QCoreApplication::translate("main","There must be a source and destination file."));
++ printStderrQString("");
++ parser.showHelp(-1);
++ }
++
++ if(parser.positionalArguments().isEmpty())
++ {
++ parser.showHelp(-1);
++ }
++
++ QString srcFilename = parser.positionalArguments()[0];
++ QString tarFilename;
++ if(parser.positionalArguments().count() > 1)
++ {
++ tarFilename = parser.positionalArguments()[1];
++ }
++
++
++ bool ok = false;
++ const qint32 ncolors = parser.value("ncolors").toInt(&ok);
++ if(!ok || ncolors > 255)
++ {
++ printStderrQString("");
++ printStderrQString(QCoreApplication::translate("main","--ncolors must be an integer value less than 256"));
++ printStderrQString("");
++ parser.showHelp(-1);
++ }
++
++ QString pctFilename = parser.value("pct");
++ QString sctFilename = parser.value("sct");
++
++ CApp theApp(ncolors, pctFilename, sctFilename, srcFilename, tarFilename);
++ return theApp.exec();
++}
++
++
+diff --git a/src/qmt_rgb2pct/version.h b/src/qmt_rgb2pct/version.h
+new file mode 100644
+index 00000000..60f94f71
+--- /dev/null
++++ b/src/qmt_rgb2pct/version.h
+@@ -0,0 +1,33 @@
++/**********************************************************************************************
++ Copyright (C) 2017 Oliver Eichler oliver.eichler@gmx.de
++
++ This program is free software: you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation, either version 3 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program. If not, see <http://www.gnu.org/licenses/>.
++
++**********************************************************************************************/
++
++#ifndef VERSION_H
++#define VERSION_H
++
++#ifndef _MKSTR_1
++#define _MKSTR_1(x) #x
++#define _MKSTR(x) _MKSTR_1(x)
++#endif
++
++#define VER_STR _MKSTR(VER_MAJOR) "." _MKSTR (VER_MINOR) "." _MKSTR (VER_STEP)
++#define VER_SUFFIX _MKSTR(VER_TWEAK)
++#define APP_STR _MKSTR(APPLICATION_NAME)
++#define WHAT_STR _MKSTR(APPLICATION_NAME) ", Version " VER_STR
++
++#endif //VERSION_H
++