degate  0.1.2
ImageHelper.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 __IMAGEHELPER_H__
00023 #define __IMAGEHELPER_H__
00024 
00025 #include <ImageReaderFactory.h>
00026 #include <ImageReaderBase.h>
00027 #include <ImageWriterBase.h>
00028 #include <TIFFWriter.h>
00029 #include <PixelPolicies.h>
00030 #include <StoragePolicies.h>
00031 #include <Image.h>
00032 
00033 #include <set>
00034 #include <boost/foreach.hpp>
00035 
00036 namespace degate {
00037 
00038 
00039   /**
00040    * Load an image in a common image format, such as tiff.
00041    * @exception InvalidPathException Thrown if, path does not exists.
00042    * @exception DegateRuntimeException This exception is thrown, if there is
00043    *   no matching image importer or if the import failed.
00044    */
00045 
00046   template<typename ImageType>
00047   std::shared_ptr<ImageType> load_image(std::string const& path) {
00048     if(!file_exists(path)) {
00049       boost::format fmter("Error in load_image(): file %1% does not exist.");
00050       fmter % path;
00051       throw InvalidPathException(fmter.str());
00052     }
00053     else {
00054       boost::format fmter("Error in load_image(): The image file %1% cannot be loaded.");
00055       fmter % path;
00056 
00057       // get a reader
00058       ImageReaderFactory<ImageType> ir_factory;
00059       std::shared_ptr<ImageReaderBase<ImageType> > reader = ir_factory.get_reader(path);
00060 
00061       if(reader->read() == false) {
00062         throw DegateRuntimeException(fmter.str());
00063       }
00064       else {
00065 
00066         debug(TM, "reading image file: %s", path.c_str());
00067 
00068         // create an empty image
00069         std::shared_ptr<ImageType> img(new ImageType(reader->get_width(),
00070                                                           reader->get_height()));
00071         if(reader->get_image(img) == true)
00072           return img;
00073         else
00074           throw DegateRuntimeException(fmter.str());
00075       }
00076     }
00077   }
00078 
00079   /**
00080    * Load an image in a common image format, such as tiff, into an existing degate image.
00081    * @exception InvalidPointerException This exception is thrown, if parameter \p img represents an invalid pointer.
00082    */
00083 
00084   template<typename ImageType>
00085   void load_image(std::string const& path, std::shared_ptr<ImageType> img) {
00086 
00087     if(img == NULL) throw InvalidPointerException("invalid image pointer");
00088     std::shared_ptr<ImageType> i = load_image<ImageType>(path);
00089     copy_image<ImageType, ImageType>(img, i);
00090   }
00091 
00092 
00093   /**
00094    * Store an image in a common file format.
00095    * Only the tiff file format is supported.
00096    * @todo We should use a factory for writer objects.
00097    * @exception DegateRuntimeException This exception is thrown, if the writer failed to save the image.
00098    * @exception InvalidPointerException This exception is thrown, if parameter \p img represents an invalid pointer.
00099    */
00100 
00101   template<typename ImageType>
00102   void save_image(std::string const& path, std::shared_ptr<ImageType> img) {
00103 
00104     if(img == NULL) throw InvalidPointerException("invalid image pointer");
00105     TIFFWriter<ImageType> tiff_writer(img->get_width(),
00106                                       img->get_height(), path);
00107     if(tiff_writer.write_image(img) != true) {
00108       boost::format fmter("Error in save_image(): Cannot write file %1%.");
00109       fmter % path;
00110       throw DegateRuntimeException(fmter.str());
00111     }
00112   }
00113 
00114   /**
00115    * Save a part of an image.
00116    * @exception InvalidPointerException This exception is thrown, if parameter \p img represents an invalid pointer.
00117    */
00118   template<typename ImageType>
00119   void save_part_of_image(std::string const& path,
00120                           std::shared_ptr<ImageType> img,
00121                           BoundingBox const& bounding_box) {
00122 
00123     if(img == NULL) throw InvalidPointerException("invalid image pointer");
00124     std::shared_ptr<ImageType> part(new ImageType(bounding_box.get_width(),
00125                                                        bounding_box.get_height()));
00126 
00127     extract_partial_image(part, img, bounding_box);
00128     save_image(path, part);
00129   }
00130 
00131   /**
00132    * Normalize a single channel image and store it in a common file format.
00133    * Only the tiff file format is supported.
00134    * @exception InvalidPointerException This exception is thrown, if parameter \p img represents an invalid pointer.
00135    */
00136 
00137   template<typename ImageType>
00138   void save_normalized_image(std::string const& path, std::shared_ptr<ImageType> img) {
00139 
00140     if(img == NULL) throw InvalidPointerException("invalid image pointer");
00141     std::shared_ptr<ImageType> normalized_img(new ImageType(img->get_width(),
00142                                                                  img->get_height()));
00143 
00144     normalize<ImageType, ImageType>(normalized_img, img, 0, 255);
00145 
00146     save_image<ImageType>(path, normalized_img);
00147   }
00148 
00149 
00150   /**
00151    * Merge a set of images by averaging them.
00152    * @exception DegateRuntimeException This exception is thrown, if images differ in size.
00153    * @return If image collection \p images contains elements, this function returns a
00154    *   valid merged image. If the collection is empty, a NULL pointer is returned.
00155    */
00156   template<typename ImageType>
00157   std::shared_ptr<ImageType> merge_images(std::list<std::shared_ptr<ImageType> > const & images) {
00158 
00159     std::shared_ptr<ImageType> new_img;
00160     if(images.empty()) return new_img;
00161 
00162     const std::shared_ptr<ImageType> img = images.front();
00163 
00164     unsigned int w = img->get_width(), h = img->get_height();
00165     std::vector<double> i_tmp(4 * w * h);
00166 
00167     BOOST_FOREACH(const std::shared_ptr<ImageType> i, images) {
00168 
00169       // verify that all images have the same dimensions
00170       if(w != i->get_width() || h != i->get_height()) 
00171         throw DegateRuntimeException("merge_images() failed, because images differ in size.");
00172 
00173       for(unsigned int y = 0; y < h; y++)
00174       for(unsigned int x = 0; x < w; x++) {
00175         color_t pix = i->template get_pixel_as<color_t>(x, y);
00176         unsigned int offs = 4 * (y * w + x);
00177         i_tmp[offs] += MASK_R(pix);
00178         i_tmp[offs+1] += MASK_G(pix);
00179         i_tmp[offs+2] += MASK_B(pix);
00180         i_tmp[offs+3] += MASK_A(pix);
00181       }
00182     }
00183 
00184     const double elems = images.size();
00185 
00186     new_img = std::shared_ptr<ImageType>(new GateTemplateImage(w, h));
00187     assert(new_img != NULL);
00188 
00189     for(unsigned int y = 0; y < h; y++)
00190       for(unsigned int x = 0; x < w; x++) {
00191         unsigned int offs = 4 * (y * w + x);
00192         color_t pix = MERGE_CHANNELS(lround(i_tmp[offs] / elems),
00193                                      lround(i_tmp[offs+1] / elems),
00194                                      lround(i_tmp[offs+2] / elems),
00195                                      lround(i_tmp[offs+3] / elems));
00196         new_img->set_pixel(x, y, pix);
00197       }
00198 
00199     return new_img;
00200   }
00201 
00202 
00203 }
00204 
00205 #endif