degate  0.1.2
ScalingManager.h
Go to the documentation of this file.
00001 /* -*-c++-*-
00002 
00003  This file is part of the IC reverse engineering tool degate.
00004 
00005  Copyright 2008, 2009, 2010 by Martin Schobert
00006 
00007  Degate is free software: you can redistribute it and/or modify
00008  it under the terms of the GNU General Public License as published by
00009  the Free Software Foundation, either version 3 of the License, or
00010  any later version.
00011 
00012  Degate is distributed in the hope that it will be useful,
00013  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  GNU General Public License for more details.
00016 
00017  You should have received a copy of the GNU General Public License
00018  along with degate. If not, see <http://www.gnu.org/licenses/>.
00019 
00020 */
00021 
00022 #ifndef __SCALINGMANAGER_H__
00023 #define __SCALINGMANAGER_H__
00024 
00025 #include "Image.h"
00026 
00027 #include <map>
00028 #include <assert.h>
00029 #include <algorithm>
00030 
00031 namespace degate {
00032 
00033   /**
00034    * The ScalingManager creates prescaled images for a master image.
00035    * You can use the ScalingManager only for images of type TileImage.
00036    * If you want to scale images for yourself, please check out method
00037    * scale_down().
00038    *
00039    * @see ImageManipulation::scale_down()
00040    */
00041   template<class ImageType>
00042   class ScalingManager {
00043 
00044   public:
00045 
00046     typedef std::pair<double, std::shared_ptr<ImageType> > image_map_element;
00047     typedef std::map<double, /* scaling */
00048                      std::shared_ptr<ImageType> > image_map;
00049 
00050   private:
00051     std::string base_directory;
00052 
00053     image_map images;
00054 
00055     unsigned int min_size;
00056 
00057   private:
00058 
00059     unsigned long get_nearest_power_of_two(unsigned int value) {
00060       unsigned int i = 1;
00061 
00062       if (value == 0) return 1;
00063       for (;;) {
00064         if (value == 1) return i;
00065         else if (value == 3) return i*4;
00066         value >>= 1;
00067         i *= 2;
00068       }
00069     }
00070 
00071 
00072   public:
00073 
00074     typedef std::list<double> zoom_step_list;
00075 
00076     /**
00077      * Create a new ScalingManager object for an image.
00078      * @param img The background image.
00079      * @param base_directory A directory where all files can be stored. You
00080      *  can use the directory of the master image for that. Make
00081      *  sure that the directory exist. if you compile libdegate
00082      *  with DEBUG=1 the existence is assert()ed.
00083      * @param min_size Create down scalings until the edge length
00084      *  is becomes less than \p min_size.
00085      */
00086     ScalingManager(std::shared_ptr<ImageType> img,
00087                    std::string const& base_directory,
00088                    int min_size = 1024) {
00089 
00090       assert(img != NULL);
00091       this->base_directory = base_directory;
00092       images[1] = img;
00093       this->min_size = min_size;
00094 
00095       assert(file_exists(base_directory));
00096     }
00097 
00098     /**
00099      * Destroy a scaling manager. This will destroy images anf their files
00100      * and directories if the imag is not persistent.
00101      */
00102     ~ScalingManager() {}
00103 
00104     /**
00105      * Get a list of available zoom steps.
00106      * @return Returns a std::list<double> with the zoom steps. A value larger
00107      *    than 1 indicates a downscaled version. The non scaled version with
00108      *    scale factor 1.0 is stored in the list, too.
00109      */
00110     const zoom_step_list get_zoom_steps() const {
00111       zoom_step_list steps;
00112 
00113       for(typename image_map::const_iterator iter = images.begin();
00114           iter != images.end(); ++iter)
00115         steps.push_back((*iter).first);
00116 
00117       steps.sort();
00118       return steps;
00119     }
00120 
00121     /**
00122      * Create the scaled images.
00123      * Created prescaled images that have the same peristence state as the
00124      * master image. The files are written into the directory, where the
00125      * master image is stored.
00126      * @throw InvalidPathException This exception is thrown, if the
00127      *   \p directory (ctor param) doesn't exists.
00128      * @todo If the image was already scaled, do not do it again. Maybe we need a force option.
00129      */
00130     void create_scalings() {
00131       if(!(file_exists(base_directory) && is_directory(base_directory)))
00132         throw InvalidPathException("The directory for prescaled images must exist. but it is not there.");
00133 
00134       std::shared_ptr<ImageType> last_img = images[1];
00135       unsigned int w = last_img->get_width();
00136       unsigned int h = last_img->get_height();
00137 
00138       for(int i = 2; ((h > min_size) || (w > min_size)) &&
00139             (i < (1<<24));  // max 24 scaling levels
00140           i*=2) {
00141 
00142         w >>= 1;
00143         h >>= 1;
00144 
00145         // create a new image
00146         char dir_name[PATH_MAX];
00147         snprintf(dir_name, sizeof(dir_name), "scaling_%d.dimg", i);
00148         std::string dir_path = join_pathes(images[1]->get_directory(), std::string(dir_name));
00149 
00150         debug(TM, "create scaled image in %s for scaling factor %d?", dir_path.c_str(), i);
00151         if(!file_exists(dir_path)) {
00152           debug(TM, "yes");
00153           create_directory(dir_path);
00154 
00155           std::shared_ptr<ImageType> new_img(new ImageType(w, h, dir_path,
00156                                                                 images[1]->is_persistent()));
00157 
00158           scale_down_by_2<ImageType, ImageType>(new_img, last_img);
00159           last_img = new_img;
00160         }
00161         else {
00162           debug(TM, "no");
00163           std::shared_ptr<ImageType> new_img(new ImageType(w, h, dir_path,
00164                                                                 images[1]->is_persistent()));
00165 
00166           last_img = new_img;
00167         }
00168         images[i] = last_img;
00169       }
00170     }
00171 
00172     /**
00173      * Get the image with the nearest scaling value to the requested scaling.
00174      * @return Returns a std::pair<double, shared_ptr> with the scaling
00175      *    factor and a shared pointer to the image.
00176      */
00177     image_map_element get_image(double request_scaling) {
00178       unsigned int factor;
00179       if(request_scaling > 1) {
00180         factor = std::min(get_nearest_power_of_two(lrint(request_scaling)),
00181                           (unsigned long)lrint(images.rbegin()->first));
00182         typename image_map::iterator found = images.find(factor);
00183         assert(found != images.end());
00184         //debug(TM, "requested scaling is %f. nearest scaling is %d. found image with scaling %f", request_scaling, factor, found->first);
00185         return *found;
00186       }
00187 
00188       //debug(TM, "return normal image");
00189       return image_map_element(1, images[1]);
00190     }
00191 
00192   };
00193 
00194   /**
00195    * A typedef for scaling managers that handle background images.
00196    */
00197   typedef std::shared_ptr<ScalingManager<BackgroundImage> > ScalingManager_shptr;
00198 }
00199 
00200 #endif