Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "exploder_cutter.hpp"
00017 #include "filesystem.hpp"
00018 #include "foreach.hpp"
00019 #include "serialization/parser.hpp"
00020 #include "serialization/preprocessor.hpp"
00021 #include "serialization/string_utils.hpp"
00022 #include "SDL_image.h"
00023
00024 #include <iostream>
00025
00026 cutter::cutter()
00027 : masks_()
00028 , verbose_(false)
00029 {
00030 }
00031
00032 const config cutter::load_config(const std::string &filename)
00033 {
00034 const std::string conf_string = find_configuration(filename);
00035
00036 config res;
00037
00038 try {
00039 scoped_istream stream = preprocess_file(conf_string);
00040 read(res, *stream);
00041 } catch(config::error& err) {
00042 throw exploder_failure("Unable to load the configuration for the file " + filename + ": "+ err.message);
00043 }
00044
00045 return res;
00046 }
00047
00048
00049 void cutter::load_masks(const config& conf)
00050 {
00051 foreach (const config &m, conf.child_range("mask"))
00052 {
00053 const std::string name = m["name"];
00054 const std::string image = get_mask_dir() + "/" + std::string(m["image"]);
00055
00056 if(verbose_) {
00057 std::cerr << "Adding mask " << name << "\n";
00058 }
00059
00060 if(image.empty())
00061 throw exploder_failure("Missing image for mask " + name);
00062
00063 const exploder_point shift(m["shift"]);
00064 const exploder_rect cut(m["cut"]);
00065
00066 if(masks_.find(name) != masks_.end() && masks_[name].filename != image) {
00067 throw exploder_failure("Mask " + name +
00068 " correspond to two different files: " +
00069 name + " and " +
00070 masks_.find(name)->second.filename);
00071 }
00072
00073 if(masks_.find(name) == masks_.end()) {
00074 mask& cur_mask = masks_[name];
00075
00076 cur_mask.name = name;
00077 cur_mask.shift = shift;
00078 cur_mask.cut = cut;
00079 cur_mask.filename = image;
00080 surface tmp(IMG_Load(image.c_str()));
00081 if(tmp == NULL)
00082 throw exploder_failure("Unable to load mask image " + image);
00083
00084 cur_mask.image = surface(make_neutral_surface(tmp));
00085 }
00086
00087 if(masks_[name].image == NULL)
00088 throw exploder_failure("Unable to load mask image " + image);
00089 }
00090 }
00091
00092
00093 cutter::surface_map cutter::cut_surface(surface surf, const config& conf)
00094 {
00095 surface_map res;
00096
00097 foreach (const config &part, conf.child_range("part")) {
00098 add_sub_image(surf, res, &part);
00099 }
00100
00101 return res;
00102 }
00103
00104
00105 std::string cutter::find_configuration(const std::string &file)
00106 {
00107
00108 const std::string fname = file_name(file);
00109 const std::string::size_type dotpos = fname.rfind('.');
00110
00111 std::string basename;
00112 if(dotpos == std::string::npos) {
00113 basename = fname;
00114 } else {
00115 basename = fname.substr(0, dotpos);
00116 }
00117
00118 return get_exploder_dir() + "/" + basename + ".cfg";
00119 }
00120
00121
00122 void cutter::add_sub_image(const surface &surf, surface_map &map, const config* config)
00123 {
00124 const std::string name = (*config)["name"];
00125 if(name.empty())
00126 throw exploder_failure("Un-named sub-image");
00127
00128 if(masks_.find(name) == masks_.end())
00129 throw exploder_failure("Unable to find mask corresponding to " + name);
00130
00131 const cutter::mask& mask = masks_[name];
00132
00133 std::vector<std::string> pos = utils::split((*config)["pos"]);
00134 if(pos.size() != 2)
00135 throw exploder_failure("Invalid position " + (*config)["pos"].str());
00136
00137 int x = atoi(pos[0].c_str());
00138 int y = atoi(pos[1].c_str());
00139
00140 const SDL_Rect cut = create_rect(x - mask.shift.x
00141 , y - mask.shift.y
00142 , mask.image->w
00143 , mask.image->h);
00144
00145 typedef std::pair<std::string, positioned_surface> sme;
00146
00147 positioned_surface ps;
00148 ps.image = surface(::cut_surface(surf, cut));
00149 if(ps.image == NULL)
00150 throw exploder_failure("Unable to cut surface!");
00151 ps.name = name;
00152 ps.mask = mask;
00153 ps.pos.x = x - mask.shift.x;
00154 ps.pos.y = y - mask.shift.y;
00155 map.insert(sme(name, ps));
00156
00157 if(verbose_) {
00158 std::cerr << "Extracting sub-image " << name << ", position (" << x << ", " << y << ")\n";
00159 }
00160 }
00161
00162 void cutter::set_verbose(bool value)
00163 {
00164 verbose_ = value;
00165 }
00166