tools/exploder_utils.cpp

Go to the documentation of this file.
00001 /* $Id: exploder_utils.cpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
00002 /*
00003    Copyright (C) 2004 - 2012 by Philippe Plantier <ayin@anathas.org>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 #include "exploder_utils.hpp"
00017 #include "game_config.hpp"
00018 #include "serialization/string_utils.hpp"
00019 #include <png.h>
00020 #include <zlib.h>
00021 
00022 exploder_point::exploder_point(const std::string &s)
00023     : x(0)
00024     , y(0)
00025 {
00026     std::vector<std::string> items = utils::split(s);
00027     if(items.size() == 2) {
00028         x = atoi(items[0].c_str());
00029         y = atoi(items[1].c_str());
00030     }
00031 }
00032 
00033 exploder_rect::exploder_rect(const std::string &s)
00034     : x(0)
00035     , y(0)
00036     , w(0)
00037     , h(0)
00038 {
00039     std::vector<std::string> items = utils::split(s);
00040     if(items.size() == 4) {
00041         x = atoi(items[0].c_str());
00042         y = atoi(items[1].c_str());
00043         w = atoi(items[2].c_str());
00044         h = atoi(items[3].c_str());
00045     }
00046 }
00047 
00048 std::string get_mask_dir()
00049 {
00050     // return ".";
00051     return game_config::path + "/images/tools/exploder";
00052 }
00053 
00054 std::string get_exploder_dir()
00055 {
00056     return game_config::path + "/data/tools/exploder";
00057 }
00058 
00059 //on pixels where mask is not white, overwrite dest with src. Mask and dest are
00060 //translated to the position (x,y) on dest.
00061 //All surfaces are supposed to be neutral surfaces, mask and src are supposed
00062 //to be of identical size.
00063 void masked_overwrite_surface(surface dest, surface src, surface mask, int x, int y)
00064 {
00065     surface_lock dest_lock(dest);
00066     surface_lock src_lock(src);
00067     surface_lock mask_lock(mask);
00068 
00069     Uint32* dest_beg = dest_lock.pixels();
00070     Uint32* src_beg = src_lock.pixels();
00071     Uint32* mask_beg = mask_lock.pixels();
00072 
00073     size_t small_shift_before;
00074     size_t small_shift_after;
00075     size_t dest_shift;
00076     size_t src_width = src->w;
00077     size_t src_height = src->h;
00078 
00079     if(x < 0) {
00080         small_shift_before = -x;
00081         if (src_width < small_shift_before)
00082             return;
00083         src_width -= small_shift_before;
00084         x = 0;
00085     } else {
00086         small_shift_before = 0;
00087     }
00088 
00089     if(x + src_width <= unsigned(dest->w)) {
00090         small_shift_after = 0;
00091     } else {
00092         small_shift_after = src_width - (dest->w - x);
00093         src_width = dest->w - x;
00094     }
00095 
00096     if(y >= 0) {
00097         dest_beg += dest->w * y + x;
00098     } else {
00099         src_beg += (-y) * src->w;
00100         mask_beg += (-y) * mask->w;
00101         dest_beg += x;
00102         if (src_height < static_cast<size_t>(-y))
00103             return;
00104         src_height += y;
00105         y = 0;
00106     }
00107 
00108     if(y + src_height > unsigned(dest->h)) {
00109         src_height = dest->h - y;
00110     }
00111 
00112     dest_shift = dest->w - src_width;
00113 
00114     for(size_t j = 0; j < src_height; ++j) {
00115         src_beg += small_shift_before;
00116         mask_beg += small_shift_before;
00117 
00118         for(size_t i = 0; i < src_width; ++i) {
00119             //Assuming here alpha mask is 0xff000000
00120             if((*mask_beg & 0x00ffffff) != 0x00ffffff) {
00121                 *dest_beg = *src_beg;
00122             }
00123             ++dest_beg;
00124             ++src_beg;
00125             ++mask_beg;
00126         }
00127 
00128         src_beg += small_shift_after;
00129         mask_beg += small_shift_after;
00130         dest_beg += dest_shift;
00131     }
00132 }
00133 
00134 
00135 //returns true if the image is empty. the surface surf is considered to be a
00136 //neutral surface.
00137 bool image_empty(surface surf)
00138 {
00139     //an image is considered empty if
00140     // * all its pixels have 0 alpha, OR
00141     // * all of its pixels have the same color (and the same alpha)
00142 
00143     surface_lock lock(surf);
00144 
00145     Uint32* beg = lock.pixels();
00146     Uint32* end = beg + surf->w*surf->h;
00147 
00148     Uint32 color = *beg;
00149 
00150     while(beg != end) {
00151         if((*beg & 0xff000000) != 0 && (*beg != color))
00152             return false;
00153 
00154         ++beg;
00155     }
00156     return true;
00157 }
00158 
00159 
00160 namespace {
00161     struct rgba {
00162         Uint8 r;
00163         Uint8 g;
00164         Uint8 b;
00165         Uint8 a;
00166     };
00167 }
00168 
00169 //saves the given SDL structure into a given filename.
00170 void save_image(surface surf, const std::string &filename)
00171 {
00172     //opens the actual file
00173     const util::scoped_FILE file(fopen(filename.c_str(),"wb"));
00174 
00175     //initializes PNG write structures
00176     //TODO: review whether providing NULL error handlers is something
00177     //sensible
00178     png_struct* png_ptr = png_create_write_struct
00179         (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00180     if(!png_ptr)
00181         throw exploder_failure("Unable to initialize the png write structure");
00182 
00183     png_info* info_ptr = png_create_info_struct(png_ptr);
00184     if(!info_ptr) {
00185         png_destroy_write_struct(&png_ptr, NULL);
00186         throw exploder_failure("Unable to initialize the png info structure");
00187     }
00188 
00189     //instructs the PNG library to use the open file
00190     png_init_io(png_ptr, file);
00191 
00192     //sets compression level to the maximum
00193     png_set_compression_level(png_ptr,
00194             Z_BEST_COMPRESSION);
00195 
00196     //configures the header
00197     png_set_IHDR(png_ptr, info_ptr, surf->w, surf->h,
00198             8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
00199             PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
00200 
00201     //puts the actual image data in the row_pointers array
00202     png_byte **row_pointers = new png_byte *[surf->h];
00203     surface_lock lock(surf);
00204 
00205     //converts the data to the RGBA format. We cannot pass SDL data
00206     //directly to the png lib, even if we know its pixel format, because of
00207     //endianness problems.
00208     util::scoped_array<rgba> rgba_data(new rgba[surf->w * surf->h]);
00209 
00210     Uint32 *surf_data = lock.pixels();
00211     int pos = 0;
00212     for(int y = 0; y < surf->h; ++y) {
00213         row_pointers[y] = reinterpret_cast<png_byte*>(rgba_data + pos);
00214         for(int x = 0; x < surf->w; ++x) {
00215             Uint8 red, green, blue, alpha;
00216             SDL_GetRGBA(*surf_data, surf->format, &red, &green, &blue, &alpha);
00217             rgba_data[pos].r = red;
00218             rgba_data[pos].g = green;
00219             rgba_data[pos].b = blue;
00220             rgba_data[pos].a = alpha;
00221             pos++;
00222             surf_data++;
00223         }
00224     }
00225     png_set_rows(png_ptr, info_ptr, row_pointers);
00226 
00227     //writes the actual image data
00228     png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
00229 
00230     //cleans everything
00231     png_write_end(png_ptr, info_ptr);
00232     png_destroy_write_struct(&png_ptr, &info_ptr);
00233     delete [] row_pointers;
00234 }
00235 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Thu May 24 2012 01:02:54 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs