/usr/include/shark/Data/Pgm.h is in libshark-dev 3.0.1+ds1-2ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 | //===========================================================================
/*!
*
*
* \brief Importing and exporting PGM images
*
*
*
* \author C. Igel
* \date 2011
*
*
* \par Copyright 1995-2015 Shark Development Team
*
* <BR><HR>
* This file is part of Shark.
* <http://image.diku.dk/shark/>
*
* Shark is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Shark is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Shark. If not, see <http://www.gnu.org/licenses/>.
*
*/
//===========================================================================
#ifndef SHARK_DATA_IMPORT_PGM_H
#define SHARK_DATA_IMPORT_PGM_H
#include <iostream>
#include <exception>
#include <stdio.h>
#include <boost/format.hpp>
#include <boost/filesystem.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <shark/LinAlg/Base.h>
#include <shark/Data/Dataset.h>
namespace shark {
namespace detail {
void importPGM( std::string const& fileName, unsigned char ** ppData, int & sx, int & sy )
{
FILE * fp = fopen(fileName.c_str(), "rb");
if( !fp ) throw SHARKEXCEPTION( "[importPGM] cannot open file: " + fileName);
char format[16];
const int nParamRead0 = fscanf(fp, "%s\n", (char *) &format);
if ( 0 == nParamRead0 ) throw SHARKEXCEPTION( "[importPGM] error reading file: " + fileName );
// Ignore comments
char tmpCharBuf[256];
fpos_t position;
fgetpos (fp, &position);
while ( true ) {
char *s = fgets( tmpCharBuf, 255, fp );
if (!s) throw SHARKEXCEPTION( "[importPGM] error reading file: " + fileName );
const int cnt = strncmp( tmpCharBuf, "#", 1 );
if (0 != cnt) {
fsetpos(fp, &position);
break;
} else {
fgetpos (fp, &position);
}
}
int nGrayValues;
const int nParamRead1 = fscanf( fp, "%d %d\n", &sx, &sy );
const int nParamRead2 = fscanf( fp, "%d\n", &nGrayValues );
if ( (nParamRead1 != 2) || (nParamRead2 != 1) ) {
fclose(fp);
throw SHARKEXCEPTION( "[importPGM] file corrupted or format not recognized in file: " + fileName );
} else {
if ( (0 == strncmp("P5", format, 2)) && ( (255 == nGrayValues) || (256 == nGrayValues) ) ) {
//delete[] *ppData;
*ppData = new unsigned char[sx*sy];
fseek(fp, -sx*sy*sizeof(unsigned char), SEEK_END);
const int readcount = (int)( fread(*ppData, sx*sizeof(unsigned char), sy, fp));
if (sy != readcount) {
fclose(fp);
throw SHARKEXCEPTION( "[importPGM] file corrupted or format not recognized in file: " + fileName );
}
} else {
fclose(fp);
throw SHARKEXCEPTION( "[importPGM] file corrupted or format not recognized in file: " + fileName );
}
}
fclose(fp);
}
/**
* \ingroup shark_globals
*
* @{
*/
/// \brief Writes a PGM file.
///
/// \param fileName File to write to
/// \param pData unsigned char pointer to the data
/// \param sx Width of image
/// \param sy Height of image
void writePGM( std::string const& fileName, unsigned char const* pData, std::size_t sx, std::size_t sy )
{
FILE* fp = fopen(fileName.c_str(), "wb");
if( !fp ) throw SHARKEXCEPTION( "[writePGM] cannot open file: " + fileName);
fprintf(fp, "P5\n");
fprintf(fp, "%d %d\n255\n", (int)sx, (int)sy);
if( 1 != fwrite(pData, sx*sy, 1, fp) ) {
fclose(fp);
throw SHARKEXCEPTION( "[writePGM] can not write data to file: "+ fileName );
}
fclose(fp);
}
} // end namespace detail
/// \brief Import a PGM image from file
///
/// \param fileName The file to read from
/// \param data Linear object for storing image
/// \param sx Width of imported image
/// \param sy Height of imported image
template <class T>
void importPGM( std::string const& fileName, T& data, std::size_t& sx, std::size_t& sy ) {
unsigned char *pData;
unsigned i=0;
int isx;
int isy;
detail::importPGM(fileName, &pData, isx, isy);
sx = std::size_t(isx);
sy = std::size_t(isy);
data.resize(sx*sy);
std::copy(pData, pData + sx*sy, data.begin());
delete [] pData;
}
/// \brief Export a PGM image to file
///
/// \param fileName File to write to
/// \param data Linear object storing image
/// \param sx Width of image
/// \param sy Height of image
/// \param normalize Adjust values to [0,255], default false
template <class T>
void exportPGM(std::string const& fileName, T const& data, std::size_t sx, std::size_t sy, bool normalize = false) {
unsigned i = 0;
unsigned char *pData = new unsigned char[data.size()];
typename T::const_iterator it = data.begin();
if(normalize) {
double lb = *std::min_element(data.begin(),data.end());
double ub = *std::max_element(data.begin(), data.end());
for( it = data.begin() ; it != data.end(); ++it, ++i )
pData[i] = (unsigned char)( (*it - lb) / (ub - lb) * 255 );
} else {
for( it = data.begin() ; it != data.end(); ++it, ++i )
pData[i] = (unsigned char)( *it );
}
detail::writePGM(fileName, pData, sx, sy);
delete [] pData;
}
/// \brief Exports a set of filters as a grid image
///
/// It is assumed that the filters each form a row in the filter-matrix.
/// Moreover, the sizes of the filter images has to be given and it must gold width*height=W.size2().
/// The filters a re printed on a single image as a grid. The grid will be close to square. And the
/// image are separated by a black 1 pixel wide line.
/// The output will be normalized so that all images are on the same scale.
/// \param basename File to write to. ".pgm" is appended to the filename
/// \param filters Matrix storing the filters row by row
/// \param width Width of the filter image
/// \param height Height of th filter image
inline void exportFiltersToPGMGrid(std::string const& basename, RealMatrix const& filters,std::size_t width, std::size_t height) {
SIZE_CHECK(filters.size2() == width*height);
//try to get a square image
std::size_t gridX = std::size_t(std::sqrt(double(filters.size1())));
std::size_t gridY = gridX;
while(gridX*gridY < filters.size1()) ++gridX;
RealMatrix image((height+1)*gridY,(width+1)*gridX,min(filters));
for(std::size_t filter = 0; filter != filters.size1(); ++filter){
//get grid position from filter
std::size_t i = filter/gridX;
std::size_t j = filter%gridX;
std::size_t startY = (height+1)*i;
std::size_t startX = (width+1)*j;
//copy images
noalias(subrange(image,startY,startY+height,startX,startX+width)) = to_matrix(row(filters,filter),height,width);
}
exportPGM(
(basename+".pgm").c_str(),
blas::adapt_vector((height+1)*gridY*(width+1)*gridX,&image(0,0)),
(width+1)*gridX, (height+1)*gridY,
true
);
}
/// \brief Exports a set of filters as a grid image
///
/// It is assumed that the filters each form a row in the filter-matrix.
/// Moreover, the sizes of the filter images has to be given and it must gold width*height=W.size2().
/// The filters a re printed on a single image as a grid. The grid will be close to square. And the
/// image are separated by a black 1 pixel wide line.
/// The output will be normalized so that all images are on the same scale.
/// \param basename File to write to. ".pgm" is appended to the filename
/// \param filters Matrix storing the filters row by row
/// \param width Width of the filter image
/// \param height Height of th filter image
inline void exportFiltersToPGMGrid(std::string const& basename, Data<RealVector> const& filters,std::size_t width, std::size_t height) {
SIZE_CHECK(dataDimension(filters) == width*height);
//try to get a square image
std::size_t numFilters = filters.numberOfElements();
std::size_t gridX = std::size_t(std::sqrt(double(numFilters)));
std::size_t gridY = gridX;
while(gridX*gridY < numFilters) ++gridX;
double minimum = std::numeric_limits<double>::max();
for(std::size_t i = 0; i != filters.numberOfBatches(); ++i){
minimum =std::min(minimum,min(filters.batch(i)));
}
RealMatrix image((height+1)*gridY,(width+1)*gridX,minimum);
for(std::size_t filter = 0; filter != numFilters; ++filter){
//get grid position from filter
std::size_t i = filter/gridX;
std::size_t j = filter%gridX;
std::size_t startY = (height+1)*i;
std::size_t startX = (width+1)*j;
RealVector filterImage =filters.element(filter);
//copy images
noalias(subrange(image,startY,startY+height,startX,startX+width)) = to_matrix(filterImage,height,width);
}
exportPGM(
(basename+".pgm").c_str(),
blas::adapt_vector((height+1)*gridY*(width+1)*gridX,&image(0,0)),
(width+1)*gridX, (height+1)*gridY,
true);
}
/// \brief Stores name and size of image externally
///
struct ImageInformation {
std::size_t x;
std::size_t y;
std::string name;
template<typename Archive>
void serialize(Archive & ar, const unsigned int) {
ar & x;
ar & y;
ar & name;
}
};
/// \brief Import PGM images scanning a directory recursively
///
/// \param p Directory
/// \param container Container storing images
/// \param info Vector storing image informations
template<class T>
void importPGMDir(const std::string &p, T &container, std::vector<ImageInformation> &info)
{
typedef typename T::value_type InputType;
if (boost::filesystem::is_directory(p)) {
for (boost::filesystem::recursive_directory_iterator itr(p); itr!=boost::filesystem::recursive_directory_iterator(); ++itr) {
if (boost::filesystem::is_regular(itr->status())) {
if ((boost::filesystem::extension(itr->path()) == ".PGM") ||
(boost::filesystem::extension(itr->path()) == ".pgm")) {
InputType img;
ImageInformation imgInfo;
importPGM(itr->path().string().c_str(), img, imgInfo.x, imgInfo.y);
imgInfo.name = itr->path().filename().string().c_str();
container.push_back(img);
info.push_back(imgInfo);
}
}
}
} else {
throw( std::invalid_argument( "[importPGMDir] cannot open file" ) );
}
}
/// \brief Import PGM images scanning a directory recursively
///
/// \param p Directory
/// \param set Set storing images
/// \param setInfo Vector storing image informations
template<class T>
void importPGMSet(const std::string &p, Data<T> &set, Data<ImageInformation> &setInfo)
{
std::vector<T> tmp;
std::vector<ImageInformation> tmpInfo;
importPGMDir(p, tmp, tmpInfo);
set = createDataFromRange(tmp);
setInfo = createDataFromRange(tmpInfo);
}
/** @}*/
} // end namespace shark
#endif
|