summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYohann Ferreira <yohann_dot_ferreira_at_orange_dot_fr>2010-05-22 15:57:21 +0200
committerYohann Ferreira <yohann_dot_ferreira_at_orange_dot_fr>2010-05-27 02:21:40 +0200
commitad34e7cf98b7a4d7096b66c743e4a087d9b432dd (patch)
treedb3cee9dff3847c9f424c9fa8761e9f1e27d19d2
parent5497d10b008bfed6b1aee8aac23fe640faebf1ad (diff)
downloadmana-ad34e7cf98b7a4d7096b66c743e4a087d9b432dd.tar.gz
mana-ad34e7cf98b7a4d7096b66c743e4a087d9b432dd.tar.bz2
mana-ad34e7cf98b7a4d7096b66c743e4a087d9b432dd.tar.xz
mana-ad34e7cf98b7a4d7096b66c743e4a087d9b432dd.zip
Basically rewrote a big part of the dyecmd tool.
The tool should be fine now, but some testing on mac would be appreciated. Mainly removed all the program exits using exception, try catch, etc... I found them rather irrelevant, creating memleaks, while not returning information about the error in some case. Reviewed-by: Jaxad0127
-rwxr-xr-x[-rw-r--r--]tools/dyecmd/src/dye.cpp96
-rwxr-xr-x[-rw-r--r--]tools/dyecmd/src/dye.h19
-rwxr-xr-x[-rw-r--r--]tools/dyecmd/src/dyecmd.cpp120
-rwxr-xr-x[-rw-r--r--]tools/dyecmd/src/imagewriter.cpp24
-rwxr-xr-x[-rw-r--r--]tools/dyecmd/src/imagewriter.h0
5 files changed, 144 insertions, 115 deletions
diff --git a/tools/dyecmd/src/dye.cpp b/tools/dyecmd/src/dye.cpp
index 76b759cc..77da2ebb 100644..100755
--- a/tools/dyecmd/src/dye.cpp
+++ b/tools/dyecmd/src/dye.cpp
@@ -21,16 +21,20 @@
#include <algorithm>
#include <sstream>
+#include <iostream>
#include "dye.h"
Palette::Palette(const std::string &description)
{
+ mLoaded = false;
int size = description.length();
if (size == 0) return;
if (description[0] != '#')
{
- throw;
+ std::cout << "Missing # in the palette description "
+ << "in the third parameter." << std::endl;
+ return;
}
int pos = 1;
@@ -42,25 +46,41 @@ Palette::Palette(const std::string &description)
{
char c = description[pos + i];
int n;
- if ('0' <= c && c <= '9') n = c - '0';
- else if ('A' <= c && c <= 'F') n = c - 'A' + 10;
- else if ('a' <= c && c <= 'f') n = c - 'a' + 10;
+ if ('0' <= c && c <= '9')
+ n = c - '0';
+ else if ('A' <= c && c <= 'F')
+ n = c - 'A' + 10;
+ else if ('a' <= c && c <= 'f')
+ n = c - 'a' + 10;
else
- throw;
+ {
+ std::cout << "invalid Hexadecimal description: "
+ << description << std::endl;
+ return;
+ }
v = (v << 4) | n;
}
Color c = { { v >> 16, v >> 8, v } };
mColors.push_back(c);
pos += 6;
- if (pos == size) return;
- if (description[pos] != ',') break;
+ if (pos == size)
+ {
+ mLoaded = true;
+ return;
+ }
+ if (description[pos] != ',')
+ break;
+
++pos;
}
+
+ mLoaded = true;
}
void Palette::getColor(int intensity, int color[3]) const
{
+ // Return implicit black
if (intensity == 0)
{
color[0] = 0;
@@ -107,6 +127,7 @@ void Palette::getColor(int intensity, int color[3]) const
Dye::Dye(const std::string &description)
{
+ mLoaded = false;
for (int i = 0; i < 7; ++i)
mPalettes[i] = 0;
@@ -121,7 +142,9 @@ Dye::Dye(const std::string &description)
next_pos = length;
if (next_pos <= pos + 3 || description[pos + 1] != ':')
{
- throw;
+ std::cout << "Dyeing: Missing ':' in channel description."
+ << std::endl;
+ return;
}
int i = 0;
switch (description[pos])
@@ -134,12 +157,21 @@ Dye::Dye(const std::string &description)
case 'C': i = 5; break;
case 'W': i = 6; break;
default:
- throw;
+ std::cout << "Dyeing: Invalid channel. Not in [R,G,Y,B,M,C,W]"
+ << std::endl;
+ return;
}
- mPalettes[i] = new Palette(description.substr(pos + 2, next_pos - pos - 2));
+ mPalettes[i] = new Palette(
+ description.substr(pos + 2, next_pos - pos - 2));
+
+ if (!mPalettes[i]->loaded())
+ return;
+
++next_pos;
}
while (next_pos < length);
+
+ mLoaded = true;
}
Dye::~Dye()
@@ -168,47 +200,3 @@ void Dye::update(int color[3]) const
if (mPalettes[i - 1])
mPalettes[i - 1]->getColor(cmax, color);
}
-
-void Dye::instantiate(std::string &target, const std::string &palettes)
-{
- std::string::size_type next_pos = target.find('|');
- if (next_pos == std::string::npos || palettes.empty()) return;
- ++next_pos;
-
- std::ostringstream s;
- s << target.substr(0, next_pos);
- std::string::size_type last_pos = target.length(), pal_pos = 0;
- do
- {
- std::string::size_type pos = next_pos;
- next_pos = target.find(';', pos);
- if (next_pos == std::string::npos) next_pos = last_pos;
- if (next_pos == pos + 1 && pal_pos != std::string::npos)
- {
- std::string::size_type pal_next_pos = palettes.find(';', pal_pos);
- s << target[pos] << ':';
- if (pal_next_pos == std::string::npos)
- {
- s << palettes.substr(pal_pos);
- s << target.substr(next_pos);
- pal_pos = std::string::npos;
- break;
- }
- s << palettes.substr(pal_pos, pal_next_pos - pal_pos);
- pal_pos = pal_next_pos + 1;
- }
- else if (next_pos > pos + 2)
- {
- s << target.substr(pos, next_pos - pos);
- }
- else
- {
- throw;
- }
- s << target[next_pos];
- ++next_pos;
- }
- while (next_pos < last_pos);
-
- target = s.str();
-}
diff --git a/tools/dyecmd/src/dye.h b/tools/dyecmd/src/dye.h
index 5a8fe1b5..922f3370 100644..100755
--- a/tools/dyecmd/src/dye.h
+++ b/tools/dyecmd/src/dye.h
@@ -45,11 +45,19 @@ class Palette
*/
void getColor(int intensity, int color[3]) const;
+ /**
+ * Tells if the palette was successfully loaded.
+ */
+ bool loaded() const
+ { return mLoaded; }
+
private:
struct Color { unsigned char value[3]; };
std::vector< Color > mColors;
+
+ bool mLoaded;
};
/**
@@ -73,15 +81,15 @@ class Dye
~Dye();
/**
- * Modifies a pixel color.
+ * Tells if the dye description was successfully loaded.
*/
- void update(int color[3]) const;
+ bool loaded() const
+ { return mLoaded; }
/**
- * Fills the blank in a dye placeholder with some palette names.
+ * Modifies a pixel color.
*/
- static void instantiate(std::string &target,
- const std::string &palettes);
+ void update(int color[3]) const;
private:
@@ -91,6 +99,7 @@ class Dye
* Red, Green, Yellow, Blue, Magenta, White (or rather gray).
*/
Palette *mPalettes[7];
+ bool mLoaded;
};
#endif
diff --git a/tools/dyecmd/src/dyecmd.cpp b/tools/dyecmd/src/dyecmd.cpp
index 3ae963b7..5e06e500 100644..100755
--- a/tools/dyecmd/src/dyecmd.cpp
+++ b/tools/dyecmd/src/dyecmd.cpp
@@ -29,11 +29,14 @@
using namespace std;
// return values
-#define RETURN_OK 1
-#define INVALID_PARAMETER_LIST 100
-#define INVALID_INPUT_IMAGE 101
-#define INVALID_OUTPUT_IMAGE 102
-#define INVALID_DYE_PARAMETER 105
+enum ReturnValues
+{
+ RETURN_OK = 0,
+ INVALID_PARAMETER_LIST = 100,
+ INVALID_INPUT_IMAGE = 101,
+ INVALID_OUTPUT_IMAGE = 102,
+ INVALID_DYE_PARAMETER = 105
+};
SDL_Surface* recolor(SDL_Surface* tmpImage, Dye* dye)
{
@@ -49,18 +52,20 @@ SDL_Surface* recolor(SDL_Surface* tmpImage, Dye* dye)
rgba.alpha = 255;
SDL_Surface *surf = SDL_ConvertSurface(tmpImage, &rgba, SDL_SWSURFACE);
- //SDL_FreeSurface(tmpImage);
+ //SDL_FreeSurface(tmpImage); <-- We'll free the surface later.
Uint32 *pixels = static_cast< Uint32 * >(surf->pixels);
for (Uint32 *p_end = pixels + surf->w * surf->h; pixels != p_end; ++pixels)
{
- int alpha = *pixels & 255;
+ int alpha = (*pixels >> rgba.Ashift) & 255;
if (!alpha) continue;
int v[3];
+
v[0] = (*pixels >> rgba.Rshift) & 255;
v[1] = (*pixels >> rgba.Gshift) & 255;
v[2] = (*pixels >> rgba.Bshift) & 255;
dye->update(v);
+
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
*pixels = (v[0] << 24) | (v[1] << 16) | (v[2] << 8) | alpha;
#else
@@ -71,53 +76,80 @@ SDL_Surface* recolor(SDL_Surface* tmpImage, Dye* dye)
return surf;
}
+void printHelp()
+{
+ cout << endl
+ << "This tool is used to dye item graphics used by the Mana client "
+ << "according to the specification described here: "
+ << endl << "http://doc.manasource.org/image_dyeing_system"
+ << endl << endl <<
+ "The tool expects 3 parameters:" << endl
+ << "dyecmd <source_image> <target_image> <dye_string>" << endl
+ << "e.g.:" << endl
+ << "dyecmd \"armor-legs-shorts.png\" "
+ <<"\"armor-legs-shorts2.png\" \"W:#222255,6666ff\"" << std::endl;
+}
+
int main(int argc, char* argv[])
{
Dye* dye = NULL;
- SDL_Surface* source = NULL;
+ SDL_Surface* source = NULL, *target = NULL;
+ ReturnValues returnValue = RETURN_OK;
- // not enough or to many parameters
- if (argc != 4)
+ if (argc > 1 && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")))
{
- cout << INVALID_PARAMETER_LIST << " - INVALID_PARAMETER_LIST";
- exit(INVALID_PARAMETER_LIST);
+ printHelp();
}
-
- try
+ // not enough or to many parameters
+ else if (argc != 4)
{
- dye = new Dye(argv[3]);
+ cout << INVALID_PARAMETER_LIST << " - INVALID_PARAMETER_LIST";
+ printHelp();
+ returnValue = INVALID_PARAMETER_LIST;
}
- catch (exception &e)
+ else
{
- cout << INVALID_DYE_PARAMETER << " - INVALID_DYE_PARAMETER";
- exit(INVALID_DYE_PARAMETER);
- }
+ // Start dyeing process.
+ string inputFile = argv[1];
+ string outputFile = argv[2];
+ string dyeDescription = argv[3];
- try
- {
- source = IMG_Load(argv[1]);
- if (!source)
+ dye = new Dye(dyeDescription);
+ if (!dye->loaded())
{
- throw;
+ cout << INVALID_DYE_PARAMETER << " - INVALID_DYE_PARAMETER";
+ printHelp();
+ returnValue = INVALID_DYE_PARAMETER;
}
- }
- catch (exception &e)
- {
- cout << INVALID_INPUT_IMAGE << " - INVALID_INPUT_IMAGE";
- exit(INVALID_INPUT_IMAGE);
- }
-
- SDL_Surface* target = recolor(source, dye);
-
- if (!ImageWriter::writePNG(target, argv[2]))
- {
- cout << INVALID_OUTPUT_IMAGE << " - INVALID_OUTPUT_IMAGE";
- exit(INVALID_OUTPUT_IMAGE);
- }
-
- SDL_FreeSurface(source);
- SDL_FreeSurface(target);
- delete dye;
-
- return 0;
+ else
+ {
+ source = IMG_Load(inputFile.c_str());
+ if (!source)
+ {
+ cout << INVALID_INPUT_IMAGE << " - INVALID_INPUT_IMAGE";
+ printHelp();
+ returnValue = INVALID_INPUT_IMAGE;
+ }
+ else
+ {
+ target = recolor(source, dye);
+
+ if (!ImageWriter::writePNG(target, outputFile))
+ {
+ cout << INVALID_OUTPUT_IMAGE << " - INVALID_OUTPUT_IMAGE";
+ printHelp();
+ returnValue = INVALID_OUTPUT_IMAGE;
+ }
+ } // Valid source image file
+ } // Valid dye parameter
+ } // Parameters ok
+
+ if (source)
+ SDL_FreeSurface(source);
+ if (target)
+ SDL_FreeSurface(target);
+ if (dye)
+ delete dye;
+
+ return returnValue;
}
diff --git a/tools/dyecmd/src/imagewriter.cpp b/tools/dyecmd/src/imagewriter.cpp
index 669b3567..d237abbf 100644..100755
--- a/tools/dyecmd/src/imagewriter.cpp
+++ b/tools/dyecmd/src/imagewriter.cpp
@@ -22,6 +22,7 @@
#include "imagewriter.h"
#include <png.h>
+#include <iostream>
#include <string>
#include <SDL/SDL.h>
@@ -32,8 +33,8 @@ bool ImageWriter::writePNG(SDL_Surface *surface,
FILE *fp = fopen(filename.c_str(), "wb");
if (!fp)
{
- // todo
- // logger->log("could not open file %s for writing", filename.c_str());
+ std::cout << "PNG writer: Could not open file for writing: "
+ << filename << std::endl;
return false;
}
@@ -49,8 +50,8 @@ bool ImageWriter::writePNG(SDL_Surface *surface,
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
if (!png_ptr)
{
- // todo
- // logger->log("Had trouble creating png_structp");
+ std::cout << "PNG writer: Had trouble creating png_structp"
+ << std::endl;
return false;
}
@@ -58,16 +59,15 @@ bool ImageWriter::writePNG(SDL_Surface *surface,
if (!info_ptr)
{
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
- // todo
- // logger->log("Could not create png_info");
+ std::cout << "PNG writer: Could not create png_info" << std::endl;
return false;
}
if (setjmp(png_jmpbuf(png_ptr)))
{
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
- // todo
- // logger->log("problem writing to %s", filename.c_str());
+ std::cout << "PNG writer: problem writing to : "
+ << filename << std::endl;
return false;
}
@@ -86,8 +86,9 @@ bool ImageWriter::writePNG(SDL_Surface *surface,
row_pointers = new png_bytep[surface->h];
if (!row_pointers)
{
- // todo
- // logger->log("Had trouble converting surface to row pointers");
+ std::cout
+ << "PNG writer: Had trouble converting surface to row pointers"
+ << std::endl;
return false;
}
@@ -105,9 +106,8 @@ bool ImageWriter::writePNG(SDL_Surface *surface,
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
- if (SDL_MUSTLOCK(surface)) {
+ if (SDL_MUSTLOCK(surface))
SDL_UnlockSurface(surface);
- }
return true;
}
diff --git a/tools/dyecmd/src/imagewriter.h b/tools/dyecmd/src/imagewriter.h
index a8bcdf57..a8bcdf57 100644..100755
--- a/tools/dyecmd/src/imagewriter.h
+++ b/tools/dyecmd/src/imagewriter.h