10ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Ceres Solver - A fast non-linear least squares minimizer
20ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Copyright 2012 Google Inc. All rights reserved.
30ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// http://code.google.com/p/ceres-solver/
40ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
50ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Redistribution and use in source and binary forms, with or without
60ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// modification, are permitted provided that the following conditions are met:
70ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
80ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// * Redistributions of source code must retain the above copyright notice,
90ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//   this list of conditions and the following disclaimer.
100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// * Redistributions in binary form must reproduce the above copyright notice,
110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//   this list of conditions and the following disclaimer in the documentation
120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//   and/or other materials provided with the distribution.
130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// * Neither the name of Google Inc. nor the names of its contributors may be
140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//   used to endorse or promote products derived from this software without
150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//   specific prior written permission.
160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
200ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
210ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
220ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
230ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
240ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
250ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
260ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
270ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// POSSIBILITY OF SUCH DAMAGE.
280ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
290ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Author: strandmark@google.com (Petter Strandmark)
300ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
310ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Simple class for accessing PGM images.
320ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
330ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#ifndef CERES_EXAMPLES_PGM_IMAGE_H_
340ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#define CERES_EXAMPLES_PGM_IMAGE_H_
350ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
360ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include <algorithm>
370ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include <cstring>
380ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include <fstream>
390ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include <iostream>
400ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include <sstream>
410ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include <string>
420ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include <vector>
430ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
440ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "glog/logging.h"
450ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
460ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongnamespace ceres {
470ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongnamespace examples {
480ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
490ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate<typename Real>
500ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongclass PGMImage {
510ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong public:
520ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Create an empty image
530ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  PGMImage(int width, int height);
540ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Load an image from file
550ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  explicit PGMImage(std::string filename);
560ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Sets an image to a constant
570ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  void Set(double constant);
580ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
590ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Reading dimensions
600ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  int width() const;
610ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  int height() const;
620ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  int NumPixels() const;
630ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
640ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Get individual pixels
650ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  Real* MutablePixel(int x, int y);
660ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  Real  Pixel(int x, int y) const;
670ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  Real* MutablePixelFromLinearIndex(int index);
680ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  Real  PixelFromLinearIndex(int index) const;
690ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  int LinearIndex(int x, int y) const;
700ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
710ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Adds an image to another
720ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  void operator+=(const PGMImage& image);
730ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Adds a constant to an image
740ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  void operator+=(Real a);
750ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Multiplies an image by a constant
760ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  void operator*=(Real a);
770ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
780ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // File access
790ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  bool WriteToFile(std::string filename) const;
800ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  bool ReadFromFile(std::string filename);
810ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
820ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Accessing the image data directly
830ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  bool SetData(const std::vector<Real>& new_data);
840ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  const std::vector<Real>& data() const;
850ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
860ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong protected:
870ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  int height_, width_;
880ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  std::vector<Real> data_;
890ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong};
900ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
910ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// --- IMPLEMENTATION
920ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
930ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate<typename Real>
940ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongPGMImage<Real>::PGMImage(int width, int height)
950ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  : height_(height), width_(width), data_(width*height, 0.0) {
960ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
970ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
980ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate<typename Real>
990ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongPGMImage<Real>::PGMImage(std::string filename) {
1000ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  if (!ReadFromFile(filename)) {
1010ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    height_ = 0;
1020ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    width_  = 0;
1030ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
1040ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1050ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1060ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate<typename Real>
1070ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongvoid PGMImage<Real>::Set(double constant) {
1080ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  for (int i = 0; i < data_.size(); ++i) {
1090ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    data_[i] = constant;
1100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
1110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate<typename Real>
1140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongint PGMImage<Real>::width() const {
1150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  return width_;
1160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate<typename Real>
1190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongint PGMImage<Real>::height() const {
1200ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  return height_;
1210ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1220ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1230ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate<typename Real>
1240ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongint PGMImage<Real>::NumPixels() const {
1250ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  return width_ * height_;
1260ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1270ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1280ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate<typename Real>
1290ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongReal* PGMImage<Real>::MutablePixel(int x, int y) {
1300ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  return MutablePixelFromLinearIndex(LinearIndex(x, y));
1310ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1320ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1330ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate<typename Real>
1340ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongReal PGMImage<Real>::Pixel(int x, int y) const {
1350ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  return PixelFromLinearIndex(LinearIndex(x, y));
1360ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1370ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1380ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate<typename Real>
1390ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongReal* PGMImage<Real>::MutablePixelFromLinearIndex(int index) {
1400ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  CHECK(index >= 0);
1410ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  CHECK(index < width_ * height_);
1420ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  CHECK(index < data_.size());
1430ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  return &data_[index];
1440ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1450ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1460ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate<typename Real>
1470ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongReal  PGMImage<Real>::PixelFromLinearIndex(int index) const {
1480ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  CHECK(index >= 0);
1490ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  CHECK(index < width_ * height_);
1500ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  CHECK(index < data_.size());
1510ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  return data_[index];
1520ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1530ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1540ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate<typename Real>
1550ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongint PGMImage<Real>::LinearIndex(int x, int y) const {
1560ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  return x + width_*y;
1570ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1580ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1590ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Adds an image to another
1600ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate<typename Real>
1610ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongvoid PGMImage<Real>::operator+= (const PGMImage<Real>& image) {
1620ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  CHECK(data_.size() == image.data_.size());
1630ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  for (int i = 0; i < data_.size(); ++i) {
1640ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    data_[i] += image.data_[i];
1650ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
1660ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1670ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1680ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Adds a constant to an image
1690ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate<typename Real>
1700ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongvoid PGMImage<Real>::operator+= (Real a) {
1710ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  for (int i = 0; i < data_.size(); ++i) {
1720ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    data_[i] += a;
1730ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
1740ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1750ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1760ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Multiplies an image by a constant
1770ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate<typename Real>
1780ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongvoid PGMImage<Real>::operator*= (Real a) {
1790ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  for (int i = 0; i < data_.size(); ++i) {
1800ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    data_[i] *= a;
1810ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
1820ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1830ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1840ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate<typename Real>
1850ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongbool PGMImage<Real>::WriteToFile(std::string filename) const {
1860ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  std::ofstream outputfile(filename.c_str());
1870ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  outputfile << "P2" << std::endl;
1880ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  outputfile << "# PGM format" << std::endl;
1890ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  outputfile << " # <width> <height> <levels> " << std::endl;
1900ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  outputfile << " # <data> ... " << std::endl;
1910ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  outputfile << width_ << ' ' << height_ << " 255 " << std::endl;
1920ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1930ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Write data
1940ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  int num_pixels = width_*height_;
1950ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  for (int i = 0; i < num_pixels; ++i) {
1960ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // Convert to integer by rounding when writing file
1970ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    outputfile << static_cast<int>(data_[i] + 0.5) << ' ';
1980ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
1990ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
20079397c21138f54fcff6ec067b44b847f1f7e0e98Carlos Hernandez  return bool(outputfile);  // Returns true/false
2010ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
2020ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2030ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongnamespace  {
2040ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2050ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Helper function to read data from a text file, ignoring "#" comments.
2060ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate<typename T>
2070ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongbool GetIgnoreComment(std::istream* in, T& t) {
2080ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  std::string word;
2090ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  bool ok;
2100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  do {
2110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    ok = true;
2120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    (*in) >> word;
2130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    if (word.length() > 0 && word[0] == '#') {
2140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      // Comment; read the whole line
2150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      ok = false;
2160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      std::getline(*in, word);
2170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
2180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  } while (!ok);
2190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2200ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Convert the string
2210ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  std::stringstream sin(word);
2220ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  sin >> t;
2230ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2240ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Check for success
2250ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  if (!in || !sin) {
2260ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    return false;
2270ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
2280ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  return true;
2290ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
2300ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}  // namespace
2310ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2320ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate<typename Real>
2330ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongbool PGMImage<Real>::ReadFromFile(std::string filename) {
2340ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  std::ifstream inputfile(filename.c_str());
2350ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2360ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // File must start with "P2"
2370ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  char ch1, ch2;
2380ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  inputfile >> ch1 >> ch2;
2390ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  if (!inputfile || ch1 != 'P' || (ch2 != '2' && ch2 != '5')) {
2400ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    return false;
2410ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
2420ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2430ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Read the image header
2440ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  int two_fifty_five;
2450ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  if (!GetIgnoreComment(&inputfile, width_)  ||
2460ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      !GetIgnoreComment(&inputfile, height_) ||
2470ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      !GetIgnoreComment(&inputfile, two_fifty_five) ) {
2480ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    return false;
2490ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
2500ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Assert that the number of grey levels is 255.
2510ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  if (two_fifty_five != 255) {
2520ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    return false;
2530ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
2540ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2550ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Now read the data
2560ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  int num_pixels = width_*height_;
2570ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  data_.resize(num_pixels);
2580ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  if (ch2 == '2') {
2590ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // Ascii file
2600ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    for (int i = 0; i < num_pixels; ++i) {
2610ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      int pixel_data;
2620ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      bool res = GetIgnoreComment(&inputfile, pixel_data);
2630ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      if (!res) {
2640ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong        return false;
2650ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      }
2660ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      data_[i] = pixel_data;
2670ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
2680ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // There cannot be anything else in the file (except comments). Try reading
2690ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // another number and return failure if that succeeded.
2700ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    int temp;
2710ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    bool res = GetIgnoreComment(&inputfile, temp);
2720ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    if (res) {
2730ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      return false;
2740ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
2750ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  } else {
2760ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // Read the line feed character
2770ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    if (inputfile.get() != '\n') {
2780ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      return false;
2790ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
2800ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // Binary file
2810ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // TODO(strandmark): Will not work on Windows (linebreak conversion).
2820ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    for (int i = 0; i < num_pixels; ++i) {
2830ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      unsigned char pixel_data = inputfile.get();
2840ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      if (!inputfile) {
2850ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong        return false;
2860ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      }
2870ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      data_[i] = pixel_data;
2880ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
2890ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // There cannot be anything else in the file. Try reading another byte
2900ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // and return failure if that succeeded.
2910ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    inputfile.get();
2920ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    if (inputfile) {
2930ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      return false;
2940ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
2950ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
2960ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2970ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  return true;
2980ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
2990ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
3000ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate<typename Real>
3010ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongbool PGMImage<Real>::SetData(const std::vector<Real>& new_data) {
3020ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // This function cannot change the dimensions
3030ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  if (new_data.size() != data_.size()) {
3040ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    return false;
3050ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
3060ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  std::copy(new_data.begin(), new_data.end(), data_.begin());
3070ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  return true;
3080ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
3090ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
3100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate<typename Real>
3110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongconst std::vector<Real>& PGMImage<Real>::data() const {
3120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  return data_;
3130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
3140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
3150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}  // namespace examples
3160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}  // namespace ceres
3170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
3180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
3190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#endif  // CERES_EXAMPLES_PGM_IMAGE_H_
320