exploder_utils.cpp

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

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs