From 5f4032eca0266da573324789e0c3a9754d9f6a26 Mon Sep 17 00:00:00 2001 From: Joshua Moerman Date: Mon, 18 Apr 2011 16:02:16 +0200 Subject: [PATCH] more styling --- Attractor.cpp | 42 +- Attractor.hpp | 2 +- AttractorKernel.cpp | 44 +- AttractorKernel.hpp | 16 +- Canvas.cpp | 6 +- Canvas.hpp | 44 +- Logger.hpp | 12 +- Projector.cpp | 2 +- defines.hpp | 15 +- kernels/Logistic.cpp | 2 +- kernels/Lorenz3D.cpp | 2 +- kernels/Polynomial.cpp | 12 +- kernels/PolynomialA3D.cpp | 2 +- kernels/Unravel3D.cpp | 6 +- ostream_helpers.h | 4 +- pngwriter/pngwriter.cc | 7719 +++++++++++++++++-------------------- pngwriter/pngwriter.h | 1285 +++--- projectors/Normalizer.cpp | 26 +- projectors/Projection.cpp | 6 +- stfu/stf.cpp | 550 +-- stfu/stf.hpp | 718 ++-- 21 files changed, 5031 insertions(+), 5484 deletions(-) diff --git a/Attractor.cpp b/Attractor.cpp index 8d5187f..d95b9b3 100644 --- a/Attractor.cpp +++ b/Attractor.cpp @@ -21,7 +21,7 @@ Attractor::Attractor(const std::string& filename) : kernel(0), projector(0) { projector = Projector::createProjector(system.getChild(system.getValue("Projector")), system); } -Attractor::~Attractor(){ +Attractor::~Attractor() { delete kernel; } @@ -29,7 +29,7 @@ Attractor::~Attractor(){ // this should probably done in the projector section void Attractor::init_range() { // stabilize attractor - for ( unsigned int i = 0; i < 100000; i++ ) { + for(unsigned int i = 0; i < 100000; i++) { iterate(); } } @@ -41,22 +41,22 @@ bool Attractor::is_chaos() { Single point attractor Lyapunov exponent */ -/* - double sum = 0; - for ( unsigned int i = 0; i < dim; i++ ) { - const double dist = 0; //new_point[i] - point[i]; - sum += dist*dist; - } - if ( sum >= 1.0e7 ) { - // big change => Escaping - return false; - } - if ( sum <= 1.0e-7 ) { - // small change => singularity - return false; - } - return true; -*/ + /* + double sum = 0; + for ( unsigned int i = 0; i < dim; i++ ) { + const double dist = 0; //new_point[i] - point[i]; + sum += dist*dist; + } + if ( sum >= 1.0e7 ) { + // big change => Escaping + return false; + } + if ( sum <= 1.0e-7 ) { + // small change => singularity + return false; + } + return true; + */ return true; } @@ -65,7 +65,7 @@ void Attractor::iterate() { } void Attractor::plot() { - const double * point = kernel->vector(); + const double* point = kernel->vector(); projector->plot(point); } @@ -75,9 +75,9 @@ void Attractor::plot() { */ void Attractor::output() { const unsigned int dimension = kernel->getDimension(); - const double * point = kernel->vector(); + const double* point = kernel->vector(); - for ( unsigned int i = 0; i < dimension; i++ ) { + for(unsigned int i = 0; i < dimension; i++) { LogMoreInfo("%f, ", point[i]); } LogMoreInfo("\n"); diff --git a/Attractor.hpp b/Attractor.hpp index 7b12e67..8264492 100644 --- a/Attractor.hpp +++ b/Attractor.hpp @@ -10,7 +10,7 @@ class AttractorKernel; class Attractor { private: - AttractorKernel * kernel; + AttractorKernel* kernel; public: diff --git a/AttractorKernel.cpp b/AttractorKernel.cpp index bb6d71e..a62caaa 100644 --- a/AttractorKernel.cpp +++ b/AttractorKernel.cpp @@ -15,11 +15,11 @@ #pragma mark memory AttractorKernel::AttractorKernel(const unsigned int dimension, const unsigned int numberOfParameters) : -numberOfParameters(numberOfParameters), dimension(dimension){ + numberOfParameters(numberOfParameters), dimension(dimension) { try { allocate(); - } catch (std::exception& e) { + } catch(std::exception& e) { LogError("Couldn't construct Attractorkernel: %s\n", e.what()); dealloc(); } @@ -30,17 +30,17 @@ numberOfParameters(numberOfParameters), dimension(dimension){ } -AttractorKernel::~AttractorKernel(){ +AttractorKernel::~AttractorKernel() { dealloc(); } -void AttractorKernel::allocate(){ +void AttractorKernel::allocate() { parameters = new double[numberOfParameters]; vectorNew = new double[dimension]; vectorOld = new double[dimension]; } -void AttractorKernel::dealloc(){ +void AttractorKernel::dealloc() { delete[] vectorOld; vectorOld = NULL; delete[] vectorNew; @@ -54,30 +54,30 @@ void AttractorKernel::dealloc(){ // NOTE: inlining these functions (with the keyword inline) improves performance by at most 1% (tested) -double & AttractorKernel::operator[](const unsigned int index){ +double& AttractorKernel::operator[](const unsigned int index) { return parameters[index]; } -double const & AttractorKernel::operator[](const unsigned int index) const{ +double const& AttractorKernel::operator[](const unsigned int index) const { return parameters[index]; } -unsigned int AttractorKernel::getNumberOfParameters() const{ +unsigned int AttractorKernel::getNumberOfParameters() const { return numberOfParameters; } #pragma mark - #pragma mark vector -double const * AttractorKernel::vector() const{ +double const* AttractorKernel::vector() const { return vectorNew; } -double const * AttractorKernel::previousVector() const{ +double const* AttractorKernel::previousVector() const { return vectorOld; } -unsigned int AttractorKernel::getDimension() const{ +unsigned int AttractorKernel::getDimension() const { return dimension; } @@ -90,9 +90,9 @@ unsigned int AttractorKernel::getDimension() const{ #include "kernels/PolynomialA3D.hpp" #include "kernels/Unravel3D.hpp" -AttractorKernel * AttractorKernel::createAttractorKernel(stfu::node& attractor){ +AttractorKernel* AttractorKernel::createAttractorKernel(stfu::node& attractor) { - AttractorKernel * myAttractor = NULL; + AttractorKernel* myAttractor = NULL; // reading basic stuff const std::string attractorType = attractor.getValue("type"); @@ -108,30 +108,30 @@ AttractorKernel * AttractorKernel::createAttractorKernel(stfu::node& attractor){ // depending on type, make the formula object - if ( attractorType == "lorenz" ){ - if ( dimension == 3 ) { + if(attractorType == "lorenz") { + if(dimension == 3) { myAttractor = new Lorenz3D(); } else { LogError("something wrong\n"); exit(37); } - } else if ( attractorType == "polynomial" ) { + } else if(attractorType == "polynomial") { const std::string attractorOrde = attractor.getValue("orde"); const unsigned int orde = atoi(attractorOrde.c_str()); LogMoreInfo(" Orde: %d\n", orde); myAttractor = new Polynomial(dimension, orde); - } else if ( attractorType == "polynomial a" ) { - if ( dimension == 3 ) { + } else if(attractorType == "polynomial a") { + if(dimension == 3) { myAttractor = new PolynomialA3D(); } else { LogError("something wrong\n"); exit(37); } - } else if ( attractorType == "logistic" ) { + } else if(attractorType == "logistic") { myAttractor = new Logistic(dimension); - } else if ( attractorType == "unravel" ) { - if ( dimension == 3 ) { + } else if(attractorType == "unravel") { + if(dimension == 3) { myAttractor = new Unravel3D(); } else { LogError("something wrong\n"); @@ -146,7 +146,7 @@ AttractorKernel * AttractorKernel::createAttractorKernel(stfu::node& attractor){ // read parameters const unsigned int numberOfParameters = myAttractor->getNumberOfParameters(); - for ( unsigned int i = 0; i < numberOfParameters; i++ ) { + for(unsigned int i = 0; i < numberOfParameters; i++) { stfu::node attractorParameters = attractor.getChild("parameters"); (*myAttractor)[i] = atof(attractorParameters.getValue(i).c_str()); LogMoreInfo(" Parameter %d set to %f, ", i, (*myAttractor)[i]); diff --git a/AttractorKernel.hpp b/AttractorKernel.hpp index 886b231..b18a830 100644 --- a/AttractorKernel.hpp +++ b/AttractorKernel.hpp @@ -13,9 +13,9 @@ protected: // biggest type first, this will reduce sizeof(AttractorKernel) // size is now 40 (when the unsigned int are in front, it was 48) - double * parameters; - double * vectorNew; - double * vectorOld; + double* parameters; + double* vectorNew; + double* vectorOld; unsigned int numberOfParameters; unsigned int dimension; @@ -26,23 +26,23 @@ protected: public: // parameters are stored in a array of doubles - double & operator[](const unsigned int index); - double const & operator[](const unsigned int index) const; + double& operator[](const unsigned int index); + double const& operator[](const unsigned int index) const; unsigned int getNumberOfParameters() const; // iterate his formula, implemented by subclasses virtual void operator()() = 0; // getter functions for teh resulta (can't be used as setters) - double const * vector() const; - double const * previousVector() const; + double const* vector() const; + double const* previousVector() const; unsigned int getDimension() const; // dtor, should be virtual for subclasses to be deleted virtual ~AttractorKernel(); // factory function - static AttractorKernel * createAttractorKernel(stfu::node& attractorKernel); + static AttractorKernel* createAttractorKernel(stfu::node& attractorKernel); }; diff --git a/Canvas.cpp b/Canvas.cpp index ed60db7..cf5f742 100644 --- a/Canvas.cpp +++ b/Canvas.cpp @@ -1,3 +1,3 @@ -#include "Canvas.hpp" - -// lol +#include "Canvas.hpp" + +// lol diff --git a/Canvas.hpp b/Canvas.hpp index 1b2c659..ac6d038 100644 --- a/Canvas.hpp +++ b/Canvas.hpp @@ -1,22 +1,22 @@ -#ifndef CANVAS_HPP -#define CANVAS_HPP - - -class Canvas { -protected: - - unsigned int dimension; - Canvas (const unsigned int dimension) : dimension (dimension) {}; - -public: - - unsigned int getDimension() const { return dimension; }; - - virtual ~Canvas() {}; - - virtual void clear() = 0; - virtual void plot (const double * normalizedPosition) = 0; - virtual void output_file (const char * filename) const = 0; -}; - -#endif // CANVAS_HPP +#ifndef CANVAS_HPP +#define CANVAS_HPP + + +class Canvas { +protected: + + unsigned int dimension; + Canvas(const unsigned int dimension) : dimension(dimension) {}; + +public: + + unsigned int getDimension() const { return dimension; }; + + virtual ~Canvas() {}; + + virtual void clear() = 0; + virtual void plot(const double* normalizedPosition) = 0; + virtual void output_file(const char* filename) const = 0; +}; + +#endif // CANVAS_HPP diff --git a/Logger.hpp b/Logger.hpp index a065f48..fcb9777 100644 --- a/Logger.hpp +++ b/Logger.hpp @@ -1,8 +1,8 @@ -#ifndef LOGGER_HPP_INCLUDED -#define LOGGER_HPP_INCLUDED +#ifndef LOGGER_HPP_INCLUDED +#define LOGGER_HPP_INCLUDED #include - + extern int verbose; #define LogDebug(s, ...) \ @@ -17,6 +17,6 @@ extern int verbose; #define LogError(s, ...) \ if ( verbose >= 0 ) { printf("%s, %d: ", __FILE__, __LINE__); printf(s, ##__VA_ARGS__); } - - -#endif // LOGGER_HPP_INCLUDED + + +#endif // LOGGER_HPP_INCLUDED diff --git a/Projector.cpp b/Projector.cpp index 11736b9..8780a6c 100644 --- a/Projector.cpp +++ b/Projector.cpp @@ -18,7 +18,7 @@ Projector::Projector(unsigned int inputDimension, unsigned int outputDimension) std::fill_n(projectedPoint, outputDimension, 0.0); } -Projector::~Projector(){ +Projector::~Projector() { deallocate(); } diff --git a/defines.hpp b/defines.hpp index a7da632..359187b 100644 --- a/defines.hpp +++ b/defines.hpp @@ -1,13 +1,12 @@ - #define DEFAULT_ATTRACTOR_FILE "attractors/testUnravel.stf" #ifdef UNI_BUILD - #warning Building for the RU, are you sure? - #define DEFAULT_WIDTH 8000 - #define DEFAULT_HEIGHT 8000 - #define DEFAULT_ITERATIONS 4200000000 +#warning Building for the RU, are you sure? +#define DEFAULT_WIDTH 8000 +#define DEFAULT_HEIGHT 8000 +#define DEFAULT_ITERATIONS 4200000000 #else - #define DEFAULT_WIDTH 800 - #define DEFAULT_HEIGHT 800 - #define DEFAULT_ITERATIONS 1000000 +#define DEFAULT_WIDTH 800 +#define DEFAULT_HEIGHT 800 +#define DEFAULT_ITERATIONS 1000000 #endif diff --git a/kernels/Logistic.cpp b/kernels/Logistic.cpp index 110dcb2..5e3ab2f 100644 --- a/kernels/Logistic.cpp +++ b/kernels/Logistic.cpp @@ -36,7 +36,7 @@ void Logistic::init() { void Logistic::operator()() { std::swap(vectorNew, vectorOld); - for ( unsigned int i = 0; i < dimension; i++ ) { + for(unsigned int i = 0; i < dimension; i++) { vectorNew[i] = parameters[i]*vectorOld[i]*(1.0 - vectorOld[i]); } } diff --git a/kernels/Lorenz3D.cpp b/kernels/Lorenz3D.cpp index 508845a..1c5031d 100644 --- a/kernels/Lorenz3D.cpp +++ b/kernels/Lorenz3D.cpp @@ -6,7 +6,7 @@ #pragma mark ctors Lorenz3D::Lorenz3D(): - AttractorKernel(3, 4){ + AttractorKernel(3, 4) { init(); } diff --git a/kernels/Polynomial.cpp b/kernels/Polynomial.cpp index bbb8c41..e961a60 100644 --- a/kernels/Polynomial.cpp +++ b/kernels/Polynomial.cpp @@ -12,7 +12,7 @@ unsigned int calculateNumberOfParameters(const unsigned int dimension, const unsigned int orde) { double n_coef = orde + 1; - for (unsigned int i = 2; i <= dimension; i++) { + for(unsigned int i = 2; i <= dimension; i++) { n_coef = n_coef*(orde + i)/(i - 1); } @@ -25,10 +25,10 @@ unsigned int calculateNumberOfParameters(const unsigned int dimension, const uns #pragma mark ctors Polynomial::Polynomial(): - AttractorKernel(3, calculateNumberOfParameters(3, 2)), orde(2){} + AttractorKernel(3, calculateNumberOfParameters(3, 2)), orde(2) {} Polynomial::Polynomial(const unsigned int dimension, const unsigned int orde): - AttractorKernel(dimension, calculateNumberOfParameters(dimension, orde)), orde(orde){} + AttractorKernel(dimension, calculateNumberOfParameters(dimension, orde)), orde(orde) {} #pragma mark - @@ -38,7 +38,7 @@ void Polynomial::operator()() { std::swap(vectorNew, vectorOld); unsigned int m = 0; - for ( unsigned int i = 0; i < dimension; i++ ) { + for(unsigned int i = 0; i < dimension; i++) { vectorNew[i] = parameters[m]; m++; @@ -48,12 +48,12 @@ void Polynomial::operator()() { void Polynomial::recur(unsigned int curr_dimension, unsigned int prev_i, unsigned int n, unsigned int& m, double prev_product) { double product; - for (unsigned int i = prev_i; i < dimension; i++) { + for(unsigned int i = prev_i; i < dimension; i++) { product = prev_product * vectorOld[i]; vectorNew[curr_dimension] += parameters[m] * product; m++; - if (n < orde) { + if(n < orde) { recur(curr_dimension, i, n+1, m, product); } } diff --git a/kernels/PolynomialA3D.cpp b/kernels/PolynomialA3D.cpp index ccec129..71485cd 100644 --- a/kernels/PolynomialA3D.cpp +++ b/kernels/PolynomialA3D.cpp @@ -14,7 +14,7 @@ #pragma mark ctors PolynomialA3D::PolynomialA3D(): - AttractorKernel(3, 3){} + AttractorKernel(3, 3) {} #pragma mark - diff --git a/kernels/Unravel3D.cpp b/kernels/Unravel3D.cpp index 103907c..cea3482 100644 --- a/kernels/Unravel3D.cpp +++ b/kernels/Unravel3D.cpp @@ -7,7 +7,7 @@ #pragma mark ctors Unravel3D::Unravel3D(): - AttractorKernel(3, 7){} + AttractorKernel(3, 7) {} #pragma mark - @@ -22,9 +22,9 @@ void Unravel3D::operator()() { const double dist = vectorNew[0]*vectorNew[0] + vectorNew[1]*vectorNew[1] + vectorNew[2]*vectorNew[2]; - if ( dist > parameters[6]*parameters[6] ) { + if(dist > parameters[6]*parameters[6]) { const double sqrtDist = std::sqrt(dist); - const double p = 1.0 - parameters[6] * ( static_cast ( sqrtDist / parameters[6] ) + 1.0 ) / sqrtDist; + const double p = 1.0 - parameters[6] * (static_cast(sqrtDist / parameters[6]) + 1.0) / sqrtDist; vectorNew[0] *= p; vectorNew[1] *= p; vectorNew[2] *= p; diff --git a/ostream_helpers.h b/ostream_helpers.h index 6a1e693..d2067c6 100644 --- a/ostream_helpers.h +++ b/ostream_helpers.h @@ -1,4 +1,4 @@ -#ifndef OSTREAM_HELPERS_HPP +#ifndef OSTREAM_HELPERS_HPP #define OSTREAM_HELPERS_HPP #include @@ -9,7 +9,7 @@ std::ostream& operator<<(std::ostream& os, AttractorKernel const& x) { const unsigned int dimension = x.getDimension(); - const double * point = x.vector(); + const double* point = x.vector(); std::copy(point, point+dimension, std::ostream_iterator(os, ", ")); return os; diff --git a/pngwriter/pngwriter.cc b/pngwriter/pngwriter.cc index bf5e269..f794fd7 100644 --- a/pngwriter/pngwriter.cc +++ b/pngwriter/pngwriter.cc @@ -10,7 +10,7 @@ // then be opened with a graphics program. // // License: GNU General Public License -// Copyright 2002, 2003, 2004, 2005, 2006, 2007, +// Copyright 2002, 2003, 2004, 2005, 2006, 2007, // 2008, 2009 Paul Blackburn // // Website: Main: http://pngwriter.sourceforge.net/ @@ -44,1874 +44,1654 @@ // Default Constructor //////////////////////////////////////////////////////////////////////////// -pngwriter::pngwriter() -{ - - filename_ = new char[255]; - textauthor_ = new char[255]; - textdescription_ = new char[255]; - texttitle_ = new char[255]; - textsoftware_ = new char[255]; - - strcpy(filename_, "out.png"); - width_ = 250; - height_ = 250; - backgroundcolour_ = 65535; - compressionlevel_ = -2; - filegamma_ = 0.5; - transformation_ = 0; - - strcpy(textauthor_, "PNGwriter Author: Paul Blackburn"); - strcpy(textdescription_, "http://pngwriter.sourceforge.net/"); - strcpy(textsoftware_, "PNGwriter: An easy to use graphics library."); - strcpy(texttitle_, "out.png"); - - int kkkk; - - bit_depth_ = 16; //Default bit depth for new images - colortype_=2; - screengamma_ = 2.2; - - graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep)); - if(graph_ == NULL) - { - std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; - } - - for (kkkk = 0; kkkk < height_; kkkk++) - { - graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte)); - if(graph_[kkkk] == NULL) - { - std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; - } - } +pngwriter::pngwriter() { - if(graph_ == NULL) - { - std::cerr << " PNGwriter::pngwriter - ERROR **: Not able to allocate memory for image." << std::endl; - } + filename_ = new char[255]; + textauthor_ = new char[255]; + textdescription_ = new char[255]; + texttitle_ = new char[255]; + textsoftware_ = new char[255]; - int tempindex; - for(int hhh = 0; hhh65535) - { - std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour greater than 65535. Setting to 65535."<65535) { + std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour greater than 65535. Setting to 65535."<65535) - { - std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour greater than 1.0. Setting to 1.0."<65535) { + std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour greater than 1.0. Setting to 1.0."<65535) - { - std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour greater than 65535. Setting to 65535."<65535) { + std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour greater than 65535. Setting to 65535."<65535) - { - std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour greater than 65535. Setting to 65535."<65535) { + std::cerr << " PNGwriter::pngwriter - WARNING **: Constructor called with background colour greater than 65535. Setting to 65535."< 65535) - { - red = 65535; - } - if(green > 65535) - { - green = 65535; - } - if(blue > 65535) - { - blue = 65535; - } - - if(red < 0) - { - red = 0; - } - if(green < 0) - { - green = 0; - } - if(blue < 0) - { - blue = 0; - } - - if((bit_depth_ == 16)) - { - // if( (height_-y >-1) && (height_-y -1) && (6*(x-1)+5<6*width_) ) - if( (y<=height_) && (y>0) && (x>0) && (x<=width_) ) - { - //graph_[height_-y][6*(x-1) + i] where i goes from 0 to 5 - tempindex= 6*x-6; - graph_[height_-y][tempindex] = (char) floor(((double)red)/256); - graph_[height_-y][tempindex+1] = (char)(red%256); - graph_[height_-y][tempindex+2] = (char) floor(((double)green)/256); - graph_[height_-y][tempindex+3] = (char)(green%256); - graph_[height_-y][tempindex+4] = (char) floor(((double)blue)/256); - graph_[height_-y][tempindex+5] = (char)(blue%256); - }; - - /* - if(!( (height_-y >-1) && (height_-y -1) && (6*(x-1)+5<6*width_) )) - { - std::cerr << " PNGwriter::plot-- Plotting out of range! " << y << " " << x << std::endl; - } - */ - } - - if((bit_depth_ == 8)) - { - // if( (height_-y >-1) && (height_-y -1) && (3*(x-1)+5<3*width_) ) - if( (y0) && (x>0) && (x-1) && (height_-y -1) && (6*(x-1)+5<6*width_) )) - { - std::cerr << " PNGwriter::plot-- Plotting out of range! " << y << " " << x << std::endl; - } - */ - } +void pngwriter::plot(int x, int y, int red, int green, int blue) { + int tempindex; + + if(red > 65535) { + red = 65535; + } + if(green > 65535) { + green = 65535; + } + if(blue > 65535) { + blue = 65535; + } + + if(red < 0) { + red = 0; + } + if(green < 0) { + green = 0; + } + if(blue < 0) { + blue = 0; + } + + if((bit_depth_ == 16)) { + // if( (height_-y >-1) && (height_-y -1) && (6*(x-1)+5<6*width_) ) + if((y<=height_) && (y>0) && (x>0) && (x<=width_)) { + //graph_[height_-y][6*(x-1) + i] where i goes from 0 to 5 + tempindex= 6*x-6; + graph_[height_-y][tempindex] = (char) floor(((double)red)/256); + graph_[height_-y][tempindex+1] = (char)(red%256); + graph_[height_-y][tempindex+2] = (char) floor(((double)green)/256); + graph_[height_-y][tempindex+3] = (char)(green%256); + graph_[height_-y][tempindex+4] = (char) floor(((double)blue)/256); + graph_[height_-y][tempindex+5] = (char)(blue%256); + }; + + /* + if(!( (height_-y >-1) && (height_-y -1) && (6*(x-1)+5<6*width_) )) + { + std::cerr << " PNGwriter::plot-- Plotting out of range! " << y << " " << x << std::endl; + } + */ + } + + if((bit_depth_ == 8)) { + // if( (height_-y >-1) && (height_-y -1) && (3*(x-1)+5<3*width_) ) + if((y0) && (x>0) && (x-1) && (height_-y -1) && (6*(x-1)+5<6*width_) )) + { + std::cerr << " PNGwriter::plot-- Plotting out of range! " << y << " " << x << std::endl; + } + */ + } }; -void pngwriter::plot(int x, int y, double red, double green, double blue) -{ - this->plot(x,y,int(red*65535),int(green*65535),int(blue*65535)); +void pngwriter::plot(int x, int y, double red, double green, double blue) { + this->plot(x,y,int(red*65535),int(green*65535),int(blue*65535)); }; /////////////////////////////////////////////////////////////// -int pngwriter::read(int x, int y, int colour) -{ - int temp1,temp2; - - if((colour !=1)&&(colour !=2)&&(colour !=3)) - { - std::cerr << " PNGwriter::read - WARNING **: Invalid argument: should be 1, 2 or 3, is " << colour << std::endl; +int pngwriter::read(int x, int y, int colour) { + int temp1,temp2; + + if((colour !=1)&&(colour !=2)&&(colour !=3)) { + std::cerr << " PNGwriter::read - WARNING **: Invalid argument: should be 1, 2 or 3, is " << colour << std::endl; + return 0; + } + + if((x>0) && (x <= (this->width_)) && (y>0) && (y <= (this->height_))) { + + if(bit_depth_ == 16) { + temp2=6*(x-1); + if(colour == 1) { + temp1 = (graph_[(height_-y)][temp2])*256 + graph_[height_-y][temp2+1]; + return temp1; + } + + if(colour == 2) { + temp1 = (graph_[height_-y][temp2+2])*256 + graph_[height_-y][temp2+3]; + return temp1; + } + + if(colour == 3) { + temp1 = (graph_[height_-y][temp2+4])*256 + graph_[height_-y][temp2+5]; + return temp1; + } + } + + if(bit_depth_ == 8) { + temp2=3*(x-1); + if(colour == 1) { + temp1 = graph_[height_-y][temp2]; + return temp1*256; + } + + if(colour == 2) { + temp1 = graph_[height_-y][temp2+1]; + return temp1*256; + } + + if(colour == 3) { + temp1 = graph_[height_-y][temp2+2]; + return temp1*256; + } + } + } else { + return 0; + } + + std::cerr << " PNGwriter::read - WARNING **: Returning 0 because of bitdepth/colour type mismatch."<< std::endl; return 0; - } - - if( ( x>0 ) && ( x <= (this->width_) ) && ( y>0 ) && ( y <= (this->height_) ) ) - { - - if(bit_depth_ == 16) - { - temp2=6*(x-1); - if(colour == 1) - { - temp1 = (graph_[(height_-y)][temp2])*256 + graph_[height_-y][temp2+1]; - return temp1; - } - - if(colour == 2) - { - temp1 = (graph_[height_-y][temp2+2])*256 + graph_[height_-y][temp2+3]; - return temp1; - } - - if(colour == 3) - { - temp1 = (graph_[height_-y][temp2+4])*256 + graph_[height_-y][temp2+5]; - return temp1; - } - } - - if(bit_depth_ == 8) - { - temp2=3*(x-1); - if(colour == 1) - { - temp1 = graph_[height_-y][temp2]; - return temp1*256; - } - - if(colour == 2) - { - temp1 = graph_[height_-y][temp2+1]; - return temp1*256; - } - - if(colour == 3) - { - temp1 = graph_[height_-y][temp2+2]; - return temp1*256; - } - } - } - else - { - return 0; - } - - std::cerr << " PNGwriter::read - WARNING **: Returning 0 because of bitdepth/colour type mismatch."<< std::endl; - return 0; } /////////////////////////////////////////////////////////////// -int pngwriter::read(int xxx, int yyy) -{ - int temp1,temp2,temp3,temp4,temp5; - - if( - ( xxx>0 ) && - ( xxx <= (this->width_) ) && - ( yyy>0 ) && - ( yyy <= (this->height_) ) - ) - { - if(bit_depth_ == 16) - { - // temp1 = (graph_[(height_-yyy)][6*(xxx-1)])*256 + graph_[height_-yyy][6*(xxx-1)+1]; - temp5=6*xxx; - temp1 = (graph_[(height_-yyy)][temp5-6])*256 + graph_[height_-yyy][temp5-5]; - temp2 = (graph_[height_-yyy][temp5-4])*256 + graph_[height_-yyy][temp5-3]; - temp3 = (graph_[height_-yyy][temp5-2])*256 + graph_[height_-yyy][temp5-1]; - temp4 = int((temp1+temp2+temp3)/3.0); - } - else if(bit_depth_ == 8) - { - // temp1 = graph_[height_-yyy][3*(xxx-1)]; - temp5 = 3*xxx; - temp1 = graph_[height_-yyy][temp5-3]; - temp2 = graph_[height_-yyy][temp5-2]; - temp3 = graph_[height_-yyy][temp5-1]; - temp4 = int((temp1+temp2+temp3)/3.0); - } - else - { - std::cerr << " PNGwriter::read - WARNING **: Invalid bit depth! Returning 0 as average value." << std::endl; - temp4 = 0; - } - - return temp4; - - } - else - { - return 0; - } +int pngwriter::read(int xxx, int yyy) { + int temp1,temp2,temp3,temp4,temp5; + + if( + (xxx>0) && + (xxx <= (this->width_)) && + (yyy>0) && + (yyy <= (this->height_)) + ) { + if(bit_depth_ == 16) { + // temp1 = (graph_[(height_-yyy)][6*(xxx-1)])*256 + graph_[height_-yyy][6*(xxx-1)+1]; + temp5=6*xxx; + temp1 = (graph_[(height_-yyy)][temp5-6])*256 + graph_[height_-yyy][temp5-5]; + temp2 = (graph_[height_-yyy][temp5-4])*256 + graph_[height_-yyy][temp5-3]; + temp3 = (graph_[height_-yyy][temp5-2])*256 + graph_[height_-yyy][temp5-1]; + temp4 = int((temp1+temp2+temp3)/3.0); + } else if(bit_depth_ == 8) { + // temp1 = graph_[height_-yyy][3*(xxx-1)]; + temp5 = 3*xxx; + temp1 = graph_[height_-yyy][temp5-3]; + temp2 = graph_[height_-yyy][temp5-2]; + temp3 = graph_[height_-yyy][temp5-1]; + temp4 = int((temp1+temp2+temp3)/3.0); + } else { + std::cerr << " PNGwriter::read - WARNING **: Invalid bit depth! Returning 0 as average value." << std::endl; + temp4 = 0; + } + + return temp4; + + } else { + return 0; + } } ///////////////////////////////////////////////////// -double pngwriter::dread(int x, int y, int colour) -{ - return double(this->read(x,y,colour))/65535.0; +double pngwriter::dread(int x, int y, int colour) { + return double(this->read(x,y,colour))/65535.0; } -double pngwriter::dread(int x, int y) -{ - return double(this->read(x,y))/65535.0; +double pngwriter::dread(int x, int y) { + return double(this->read(x,y))/65535.0; } /////////////////////////////////////////////////////// -void pngwriter::clear() -{ - int pen = 0; - int pencil = 0; - int tempindex; - - if(bit_depth_==16) - { - for(pen = 0; pen 999999999)||(index < 0)) - { - std::cerr << " PNGwriter::pngwriter_rename - ERROR **: Numerical name is out of 0 - 999 999 999 range (" << index <<")." << std::endl; - return; - } + // %[flags][width][.precision][modifiers]type + // + if((index > 999999999)||(index < 0)) { + std::cerr << " PNGwriter::pngwriter_rename - ERROR **: Numerical name is out of 0 - 999 999 999 range (" << index <<")." << std::endl; + return; + } - if( 0> sprintf(buffer, "%9.9lu.png",index)) - { - std::cerr << " PNGwriter::pngwriter_rename - ERROR **: Error creating numerical filename." << std::endl; - return; - } + if(0> sprintf(buffer, "%9.9lu.png",index)) { + std::cerr << " PNGwriter::pngwriter_rename - ERROR **: Error creating numerical filename." << std::endl; + return; + } - delete [] filename_; - delete [] texttitle_; + delete [] filename_; + delete [] texttitle_; - filename_ = new char[strlen(buffer)+1]; - texttitle_ = new char[strlen(buffer)+1]; + filename_ = new char[strlen(buffer)+1]; + texttitle_ = new char[strlen(buffer)+1]; - strcpy(filename_,buffer); - strcpy(texttitle_,buffer); + strcpy(filename_,buffer); + strcpy(texttitle_,buffer); }; /////////////////////////////////////////////////////// -void pngwriter::settext(char * title, char * author, char * description, char * software) -{ - delete [] textauthor_; - delete [] textdescription_; - delete [] texttitle_; - delete [] textsoftware_; - - textauthor_ = new char[strlen(author)+1]; - textdescription_ = new char[strlen(description)+1]; - textsoftware_ = new char[strlen(software)+1]; - texttitle_ = new char[strlen(title)+1]; - - strcpy(texttitle_, title); - strcpy(textauthor_, author); - strcpy(textdescription_, description); - strcpy(textsoftware_, software); +void pngwriter::settext(char* title, char* author, char* description, char* software) { + delete [] textauthor_; + delete [] textdescription_; + delete [] texttitle_; + delete [] textsoftware_; + + textauthor_ = new char[strlen(author)+1]; + textdescription_ = new char[strlen(description)+1]; + textsoftware_ = new char[strlen(software)+1]; + texttitle_ = new char[strlen(title)+1]; + + strcpy(texttitle_, title); + strcpy(textauthor_, author); + strcpy(textdescription_, description); + strcpy(textsoftware_, software); }; /////////////////////////////////////////////////////// -void pngwriter::settext(const char * title, const char * author, const char * description, const char * software) -{ - delete [] textauthor_; - delete [] textdescription_; - delete [] texttitle_; - delete [] textsoftware_; - - textauthor_ = new char[strlen(author)+1]; - textdescription_ = new char[strlen(description)+1]; - textsoftware_ = new char[strlen(software)+1]; - texttitle_ = new char[strlen(title)+1]; - - strcpy(texttitle_, title); - strcpy(textauthor_, author); - strcpy(textdescription_, description); - strcpy(textsoftware_, software); +void pngwriter::settext(const char* title, const char* author, const char* description, const char* software) { + delete [] textauthor_; + delete [] textdescription_; + delete [] texttitle_; + delete [] textsoftware_; + + textauthor_ = new char[strlen(author)+1]; + textdescription_ = new char[strlen(description)+1]; + textsoftware_ = new char[strlen(software)+1]; + texttitle_ = new char[strlen(title)+1]; + + strcpy(texttitle_, title); + strcpy(textauthor_, author); + strcpy(textdescription_, description); + strcpy(textsoftware_, software); }; /////////////////////////////////////////////////////// -void pngwriter::close() -{ - FILE *fp; - png_structp png_ptr; - png_infop info_ptr; - - fp = fopen(filename_, "wb"); - if( fp == NULL) - { - std::cerr << " PNGwriter::close - ERROR **: Error creating file (fopen() returned NULL pointer)." << std::endl; - perror(" PNGwriter::close - ERROR **"); - return; - } - - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - info_ptr = png_create_info_struct(png_ptr); - png_init_io(png_ptr, fp); - if(compressionlevel_ != -2) - { - png_set_compression_level(png_ptr, compressionlevel_); - } - else - { - png_set_compression_level(png_ptr, PNGWRITER_DEFAULT_COMPRESSION); - } - - png_set_IHDR(png_ptr, info_ptr, width_, height_, - bit_depth_, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - - if(filegamma_ < 1.0e-1) - { - filegamma_ = 0.5; // Modified in 0.5.4 so as to be the same as the usual gamma. - } - - png_set_gAMA(png_ptr, info_ptr, filegamma_); - - time_t gmt; - png_time mod_time; - png_text text_ptr[5]; - time(&gmt); - png_convert_from_time_t(&mod_time, gmt); - png_set_tIME(png_ptr, info_ptr, &mod_time); - text_ptr[0].key = "Title"; - text_ptr[0].text = texttitle_; - text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE; - text_ptr[1].key = "Author"; - text_ptr[1].text = textauthor_; - text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE; - text_ptr[2].key = "Description"; - text_ptr[2].text = textdescription_; - text_ptr[2].compression = PNG_TEXT_COMPRESSION_NONE; - text_ptr[3].key = "Creation Time"; - text_ptr[3].text = png_convert_to_rfc1123(png_ptr, &mod_time); - text_ptr[3].compression = PNG_TEXT_COMPRESSION_NONE; - text_ptr[4].key = "Software"; - text_ptr[4].text = textsoftware_; - text_ptr[4].compression = PNG_TEXT_COMPRESSION_NONE; - png_set_text(png_ptr, info_ptr, text_ptr, 5); - - png_write_info(png_ptr, info_ptr); - png_write_image(png_ptr, graph_); - png_write_end(png_ptr, info_ptr); - png_destroy_write_struct(&png_ptr, &info_ptr); - fclose(fp); +void pngwriter::close() { + FILE* fp; + png_structp png_ptr; + png_infop info_ptr; + + fp = fopen(filename_, "wb"); + if(fp == NULL) { + std::cerr << " PNGwriter::close - ERROR **: Error creating file (fopen() returned NULL pointer)." << std::endl; + perror(" PNGwriter::close - ERROR **"); + return; + } + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + info_ptr = png_create_info_struct(png_ptr); + png_init_io(png_ptr, fp); + if(compressionlevel_ != -2) { + png_set_compression_level(png_ptr, compressionlevel_); + } else { + png_set_compression_level(png_ptr, PNGWRITER_DEFAULT_COMPRESSION); + } + + png_set_IHDR(png_ptr, info_ptr, width_, height_, + bit_depth_, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + if(filegamma_ < 1.0e-1) { + filegamma_ = 0.5; // Modified in 0.5.4 so as to be the same as the usual gamma. + } + + png_set_gAMA(png_ptr, info_ptr, filegamma_); + + time_t gmt; + png_time mod_time; + png_text text_ptr[5]; + time(&gmt); + png_convert_from_time_t(&mod_time, gmt); + png_set_tIME(png_ptr, info_ptr, &mod_time); + text_ptr[0].key = "Title"; + text_ptr[0].text = texttitle_; + text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr[1].key = "Author"; + text_ptr[1].text = textauthor_; + text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr[2].key = "Description"; + text_ptr[2].text = textdescription_; + text_ptr[2].compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr[3].key = "Creation Time"; + text_ptr[3].text = png_convert_to_rfc1123(png_ptr, &mod_time); + text_ptr[3].compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr[4].key = "Software"; + text_ptr[4].text = textsoftware_; + text_ptr[4].compression = PNG_TEXT_COMPRESSION_NONE; + png_set_text(png_ptr, info_ptr, text_ptr, 5); + + png_write_info(png_ptr, info_ptr); + png_write_image(png_ptr, graph_); + png_write_end(png_ptr, info_ptr); + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(fp); } ////////////////////////////////////////////////////// -void pngwriter::line(int xfrom, int yfrom, int xto, int yto, int red, int green,int blue) -{ - // Bresenham Algorithm. - // - int dy = yto - yfrom; - int dx = xto - xfrom; - int stepx, stepy; - - if (dy < 0) - { - dy = -dy; stepy = -1; - } - else - { - stepy = 1; - } - - if (dx < 0) - { - dx = -dx; stepx = -1; - } - else - { - stepx = 1; - } - dy <<= 1; // dy is now 2*dy - dx <<= 1; // dx is now 2*dx - - this->plot(xfrom,yfrom,red,green,blue); - - if (dx > dy) - { - int fraction = dy - (dx >> 1); - - while (xfrom != xto) - { - if (fraction >= 0) - { - yfrom += stepy; - fraction -= dx; - } - xfrom += stepx; - fraction += dy; - this->plot(xfrom,yfrom,red,green,blue); - } - } - else - { - int fraction = dx - (dy >> 1); - while (yfrom != yto) - { - if (fraction >= 0) - { - xfrom += stepx; - fraction -= dy; - } - yfrom += stepy; - fraction += dx; - this->plot(xfrom,yfrom,red,green,blue); - } - } +void pngwriter::line(int xfrom, int yfrom, int xto, int yto, int red, int green,int blue) { + // Bresenham Algorithm. + // + int dy = yto - yfrom; + int dx = xto - xfrom; + int stepx, stepy; + + if(dy < 0) { + dy = -dy; + stepy = -1; + } else { + stepy = 1; + } + + if(dx < 0) { + dx = -dx; + stepx = -1; + } else { + stepx = 1; + } + dy <<= 1; // dy is now 2*dy + dx <<= 1; // dx is now 2*dx + + this->plot(xfrom,yfrom,red,green,blue); + + if(dx > dy) { + int fraction = dy - (dx >> 1); + + while(xfrom != xto) { + if(fraction >= 0) { + yfrom += stepy; + fraction -= dx; + } + xfrom += stepx; + fraction += dy; + this->plot(xfrom,yfrom,red,green,blue); + } + } else { + int fraction = dx - (dy >> 1); + while(yfrom != yto) { + if(fraction >= 0) { + xfrom += stepx; + fraction -= dy; + } + yfrom += stepy; + fraction += dx; + this->plot(xfrom,yfrom,red,green,blue); + } + } } -void pngwriter::line(int xfrom, int yfrom, int xto, int yto, double red, double green,double blue) -{ - this->line( xfrom, - yfrom, - xto, - yto, - int (red*65535), - int (green*65535), - int (blue*65535) - ); +void pngwriter::line(int xfrom, int yfrom, int xto, int yto, double red, double green,double blue) { + this->line(xfrom, + yfrom, + xto, + yto, + int (red*65535), + int (green*65535), + int (blue*65535) + ); } /////////////////////////////////////////////////////////////////////////////////////////// -void pngwriter::square(int xfrom, int yfrom, int xto, int yto, int red, int green, int blue) -{ - this->line(xfrom, yfrom, xfrom, yto, red, green, blue); - this->line(xto, yfrom, xto, yto, red, green, blue); - this->line(xfrom, yfrom, xto, yfrom, red, green, blue); - this->line(xfrom, yto, xto, yto, red, green, blue); +void pngwriter::square(int xfrom, int yfrom, int xto, int yto, int red, int green, int blue) { + this->line(xfrom, yfrom, xfrom, yto, red, green, blue); + this->line(xto, yfrom, xto, yto, red, green, blue); + this->line(xfrom, yfrom, xto, yfrom, red, green, blue); + this->line(xfrom, yto, xto, yto, red, green, blue); } -void pngwriter::square(int xfrom, int yfrom, int xto, int yto, double red, double green, double blue) -{ - this->square( xfrom, yfrom, xto, yto, int(red*65535), int(green*65535), int(blue*65535)); +void pngwriter::square(int xfrom, int yfrom, int xto, int yto, double red, double green, double blue) { + this->square(xfrom, yfrom, xto, yto, int(red*65535), int(green*65535), int(blue*65535)); } ////////////////////////////////////////////////////////////////////////////////////////////////// -void pngwriter::filledsquare(int xfrom, int yfrom, int xto, int yto, int red, int green, int blue) -{ - for(int caca = xfrom; caca line(caca, yfrom, caca, yto, red, green, blue); - } +void pngwriter::filledsquare(int xfrom, int yfrom, int xto, int yto, int red, int green, int blue) { + for(int caca = xfrom; caca line(caca, yfrom, caca, yto, red, green, blue); + } } -void pngwriter::filledsquare(int xfrom, int yfrom, int xto, int yto, double red, double green, double blue) -{ - this->filledsquare( xfrom, yfrom, xto, yto, int(red*65535), int(green*65535), int(blue*65535)); +void pngwriter::filledsquare(int xfrom, int yfrom, int xto, int yto, double red, double green, double blue) { + this->filledsquare(xfrom, yfrom, xto, yto, int(red*65535), int(green*65535), int(blue*65535)); } ////////////////////////////////////////////////////////////////////////////////////////////////// -void pngwriter::circle(int xcentre, int ycentre, int radius, int red, int green, int blue) -{ - int x = 0; - int y = radius; - int p = (5 - radius*4)/4; - - circle_aux(xcentre, ycentre, x, y, red, green, blue); - while (x < y) - { - x++; - if (p < 0) - { - p += 2*x+1; - } - else - { - y--; - p += 2*(x-y)+1; - } +void pngwriter::circle(int xcentre, int ycentre, int radius, int red, int green, int blue) { + int x = 0; + int y = radius; + int p = (5 - radius*4)/4; + circle_aux(xcentre, ycentre, x, y, red, green, blue); - } + while(x < y) { + x++; + if(p < 0) { + p += 2*x+1; + } else { + y--; + p += 2*(x-y)+1; + } + circle_aux(xcentre, ycentre, x, y, red, green, blue); + } } -void pngwriter::circle(int xcentre, int ycentre, int radius, double red, double green, double blue) -{ - this->circle(xcentre,ycentre,radius, int(red*65535), int(green*65535), int(blue*65535)); +void pngwriter::circle(int xcentre, int ycentre, int radius, double red, double green, double blue) { + this->circle(xcentre,ycentre,radius, int(red*65535), int(green*65535), int(blue*65535)); } //////////////////////////////////////////////////////////// -void pngwriter::circle_aux(int xcentre, int ycentre, int x, int y, int red, int green, int blue) -{ - if (x == 0) - { - this->plot( xcentre, ycentre + y, red, green, blue); - this->plot( xcentre, ycentre - y, red, green, blue); - this->plot( xcentre + y, ycentre, red, green, blue); - this->plot( xcentre - y, ycentre, red, green, blue); - } - else - if (x == y) - { - this->plot( xcentre + x, ycentre + y, red, green, blue); - this->plot( xcentre - x, ycentre + y, red, green, blue); - this->plot( xcentre + x, ycentre - y, red, green, blue); - this->plot( xcentre - x, ycentre - y, red, green, blue); - } - else - if (x < y) - { - this->plot( xcentre + x, ycentre + y, red, green, blue); - this->plot( xcentre - x, ycentre + y, red, green, blue); - this->plot( xcentre + x, ycentre - y, red, green, blue); - this->plot( xcentre - x, ycentre - y, red, green, blue); - this->plot( xcentre + y, ycentre + x, red, green, blue); - this->plot( xcentre - y, ycentre + x, red, green, blue); - this->plot( xcentre + y, ycentre - x, red, green, blue); - this->plot( xcentre - y, ycentre - x, red, green, blue); - } +void pngwriter::circle_aux(int xcentre, int ycentre, int x, int y, int red, int green, int blue) { + if(x == 0) { + this->plot(xcentre, ycentre + y, red, green, blue); + this->plot(xcentre, ycentre - y, red, green, blue); + this->plot(xcentre + y, ycentre, red, green, blue); + this->plot(xcentre - y, ycentre, red, green, blue); + } else if(x == y) { + this->plot(xcentre + x, ycentre + y, red, green, blue); + this->plot(xcentre - x, ycentre + y, red, green, blue); + this->plot(xcentre + x, ycentre - y, red, green, blue); + this->plot(xcentre - x, ycentre - y, red, green, blue); + } else if(x < y) { + this->plot(xcentre + x, ycentre + y, red, green, blue); + this->plot(xcentre - x, ycentre + y, red, green, blue); + this->plot(xcentre + x, ycentre - y, red, green, blue); + this->plot(xcentre - x, ycentre - y, red, green, blue); + this->plot(xcentre + y, ycentre + x, red, green, blue); + this->plot(xcentre - y, ycentre + x, red, green, blue); + this->plot(xcentre + y, ycentre - x, red, green, blue); + this->plot(xcentre - y, ycentre - x, red, green, blue); + } } //////////////////////////////////////////////////////////// -void pngwriter::filledcircle(int xcentre, int ycentre, int radius, int red, int green, int blue) -{ - for(int jjj = ycentre-radius; jjj< ycentre+radius+1; jjj++) - { - this->line(xcentre - int(sqrt((double)(radius*radius) - (-ycentre + jjj)*(-ycentre + jjj ))), jjj, - xcentre + int(sqrt((double)(radius*radius) - (-ycentre + jjj)*(-ycentre + jjj ))),jjj,red,green,blue); - } +void pngwriter::filledcircle(int xcentre, int ycentre, int radius, int red, int green, int blue) { + for(int jjj = ycentre-radius; jjj< ycentre+radius+1; jjj++) { + this->line(xcentre - int(sqrt((double)(radius*radius) - (-ycentre + jjj)*(-ycentre + jjj))), jjj, + xcentre + int(sqrt((double)(radius*radius) - (-ycentre + jjj)*(-ycentre + jjj))),jjj,red,green,blue); + } } -void pngwriter::filledcircle(int xcentre, int ycentre, int radius, double red, double green, double blue) -{ - this->filledcircle( xcentre, ycentre, radius, int(red*65535), int(green*65535), int(blue*65535)); +void pngwriter::filledcircle(int xcentre, int ycentre, int radius, double red, double green, double blue) { + this->filledcircle(xcentre, ycentre, radius, int(red*65535), int(green*65535), int(blue*65535)); } ////////////////Reading routines///////////////////// ///////////////////////////////////////////////// // Modified with Mikkel's patch -void pngwriter::readfromfile(char * name) -{ - FILE *fp; - png_structp png_ptr; - png_infop info_ptr; - unsigned char **image; - unsigned long width, height; - int bit_depth, color_type, interlace_type; - // png_uint_32 i; - // - fp = fopen (name,"rb"); - if (fp==NULL) - { - std::cerr << " PNGwriter::readfromfile - ERROR **: Error opening file \"" << std::flush; - std::cerr << name <readfromfile((char *)(name)); -} + color types. Note that not all combinations are legal + #define PNG_COLOR_TYPE_GRAY 0 + #define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR (2) | PNG_COLOR_MASK_PALETTE (1) ) + #define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR (2) ) + #define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR (2) | PNG_COLOR_MASK_ALPHA (4) ) + #define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA (4) ) -///////////////////////////////////////////////////////// -int pngwriter::check_if_png(char *file_name, FILE **fp) -{ - char sig[PNG_BYTES_TO_CHECK]; + aliases + #define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA + #define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA - if ( /*(*fp = fopen(file_name, "rb")) */ *fp == NULL) // Fixed 10 10 04 - { - // exit(EXIT_FAILURE); - std::cerr << " PNGwriter::check_if_png - ERROR **: Could not open file " << file_name << " to read." << std::endl; - perror(" PNGwriter::check_if_png - ERROR **"); - return 0; - } - - if (fread(sig, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK) - { - //exit(EXIT_FAILURE); - std::cerr << " PNGwriter::check_if_png - ERROR **: File " << file_name << " does not appear to be a valid PNG file." << std::endl; - perror(" PNGwriter::check_if_png - ERROR **"); - fclose(*fp); - return 0; - } - - if (png_sig_cmp( (png_bytep) sig, (png_size_t)0, PNG_BYTES_TO_CHECK) /*png_check_sig((png_bytep) sig, PNG_BYTES_TO_CHECK)*/ ) - { - std::cerr << " PNGwriter::check_if_png - ERROR **: File " << file_name << " does not appear to be a valid PNG file. png_check_sig() failed." << std::endl; - fclose(*fp); - return 0; - } - - - - return 1; //Success + These describe the color_type field in png_info. + color type masks + #define PNG_COLOR_MASK_PALETTE 1 + #define PNG_COLOR_MASK_COLOR 2 + #define PNG_COLOR_MASK_ALPHA 4 + + + */ + + + if(colortype_ !=2) { + std::cerr << " PNGwriter::readfromfile() - WARNING **: Input file is of unsupported type (bad color_type). Output will be unpredictable.\n"; + } + + screengamma_ = 2.2; + double file_gamma,screen_gamma; + screen_gamma = screengamma_; + if(png_get_gAMA(png_ptr, info_ptr, &file_gamma)) { + png_set_gamma(png_ptr,screen_gamma,file_gamma); + } else { + png_set_gamma(png_ptr, screen_gamma,0.45); + } + + filegamma_ = file_gamma; + + fclose(fp); } /////////////////////////////////////////////////////// -int pngwriter::read_png_info(FILE *fp, png_structp *png_ptr, png_infop *info_ptr) -{ - *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (*png_ptr == NULL) - { - std::cerr << " PNGwriter::read_png_info - ERROR **: Could not create read_struct." << std::endl; - fclose(fp); - return 0; - //exit(EXIT_FAILURE); - } - *info_ptr = png_create_info_struct(*png_ptr); - if (*info_ptr == NULL) - { - png_destroy_read_struct(png_ptr, (png_infopp)NULL, (png_infopp)NULL); - std::cerr << " PNGwriter::read_png_info - ERROR **: Could not create info_struct." << std::endl; - //exit(EXIT_FAILURE); - fclose(fp); - return 0; - } - if (setjmp((*png_ptr)->jmpbuf)) /*(setjmp(png_jmpbuf(*png_ptr)) )*////////////////////////////////////// - { - png_destroy_read_struct(png_ptr, info_ptr, (png_infopp)NULL); - std::cerr << " PNGwriter::read_png_info - ERROR **: This file may be a corrupted PNG file. (setjmp(*png_ptr)->jmpbf) failed)." << std::endl; - fclose(fp); - return 0; - //exit(EXIT_FAILURE); - } - png_init_io(*png_ptr, fp); - png_set_sig_bytes(*png_ptr, PNG_BYTES_TO_CHECK); - png_read_info(*png_ptr, *info_ptr); - return 1; +void pngwriter::readfromfile(const char* name) { + this->readfromfile((char *)(name)); } -//////////////////////////////////////////////////////////// -int pngwriter::read_png_image(FILE *fp, png_structp png_ptr, png_infop info_ptr, - png_bytepp *image, png_uint_32 *width, png_uint_32 *height) -{ - unsigned int i,j; +///////////////////////////////////////////////////////// +int pngwriter::check_if_png(char* file_name, FILE** fp) { + char sig[PNG_BYTES_TO_CHECK]; - *width = png_get_image_width(png_ptr, info_ptr); - *height = png_get_image_height(png_ptr, info_ptr); + if(/*(*fp = fopen(file_name, "rb")) */ *fp == NULL) { // Fixed 10 10 04 + // exit(EXIT_FAILURE); + std::cerr << " PNGwriter::check_if_png - ERROR **: Could not open file " << file_name << " to read." << std::endl; + perror(" PNGwriter::check_if_png - ERROR **"); + return 0; + } - if( width == NULL) - { - std::cerr << " PNGwriter::read_png_image - ERROR **: png_get_image_width() returned NULL pointer." << std::endl; - fclose(fp); - return 0; - } + if(fread(sig, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK) { + //exit(EXIT_FAILURE); + std::cerr << " PNGwriter::check_if_png - ERROR **: File " << file_name << " does not appear to be a valid PNG file." << std::endl; + perror(" PNGwriter::check_if_png - ERROR **"); + fclose(*fp); + return 0; + } - if( height == NULL) - { - std::cerr << " PNGwriter::read_png_image - ERROR **: png_get_image_height() returned NULL pointer." << std::endl; - fclose(fp); - return 0; - } + if(png_sig_cmp((png_bytep) sig, (png_size_t)0, PNG_BYTES_TO_CHECK) /*png_check_sig((png_bytep) sig, PNG_BYTES_TO_CHECK)*/) { + std::cerr << " PNGwriter::check_if_png - ERROR **: File " << file_name << " does not appear to be a valid PNG file. png_check_sig() failed." << std::endl; + fclose(*fp); + return 0; + } - if ((*image = (png_bytepp)malloc(*height * sizeof(png_bytep))) == NULL) - { - std::cerr << " PNGwriter::read_png_image - ERROR **: Could not allocate memory for reading image." << std::endl; - fclose(fp); - return 0; - //exit(EXIT_FAILURE); - } - for (i = 0; i < *height; i++) - { - (*image)[i] = (png_bytep)malloc(png_get_rowbytes(png_ptr, info_ptr)); - if ((*image)[i] == NULL) - { - for (j = 0; j < i; j++) free((*image)[j]); - free(*image); - fclose(fp); - std::cerr << " PNGwriter::read_png_image - ERROR **: Could not allocate memory for reading image." << std::endl; - return 0; - //exit(EXIT_FAILURE); - } - } - png_read_image(png_ptr, *image); - return 1; + + return 1; //Success +} + +/////////////////////////////////////////////////////// +int pngwriter::read_png_info(FILE* fp, png_structp* png_ptr, png_infop* info_ptr) { + *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if(*png_ptr == NULL) { + std::cerr << " PNGwriter::read_png_info - ERROR **: Could not create read_struct." << std::endl; + fclose(fp); + return 0; + //exit(EXIT_FAILURE); + } + *info_ptr = png_create_info_struct(*png_ptr); + if(*info_ptr == NULL) { + png_destroy_read_struct(png_ptr, (png_infopp)NULL, (png_infopp)NULL); + std::cerr << " PNGwriter::read_png_info - ERROR **: Could not create info_struct." << std::endl; + //exit(EXIT_FAILURE); + fclose(fp); + return 0; + } + if(setjmp((*png_ptr)->jmpbuf)) /*(setjmp(png_jmpbuf(*png_ptr)) )*/ ///////////////////////////////////// + { + png_destroy_read_struct(png_ptr, info_ptr, (png_infopp)NULL); + std::cerr << " PNGwriter::read_png_info - ERROR **: This file may be a corrupted PNG file. (setjmp(*png_ptr)->jmpbf) failed)." << std::endl; + fclose(fp); + return 0; + //exit(EXIT_FAILURE); + } + png_init_io(*png_ptr, fp); + png_set_sig_bytes(*png_ptr, PNG_BYTES_TO_CHECK); + png_read_info(*png_ptr, *info_ptr); + + return 1; +} + +//////////////////////////////////////////////////////////// +int pngwriter::read_png_image(FILE* fp, png_structp png_ptr, png_infop info_ptr, + png_bytepp* image, png_uint_32* width, png_uint_32* height) { + unsigned int i,j; + + *width = png_get_image_width(png_ptr, info_ptr); + *height = png_get_image_height(png_ptr, info_ptr); + + if(width == NULL) { + std::cerr << " PNGwriter::read_png_image - ERROR **: png_get_image_width() returned NULL pointer." << std::endl; + fclose(fp); + return 0; + } + + if(height == NULL) { + std::cerr << " PNGwriter::read_png_image - ERROR **: png_get_image_height() returned NULL pointer." << std::endl; + fclose(fp); + return 0; + } + + if((*image = (png_bytepp)malloc(*height * sizeof(png_bytep))) == NULL) { + std::cerr << " PNGwriter::read_png_image - ERROR **: Could not allocate memory for reading image." << std::endl; + fclose(fp); + return 0; + //exit(EXIT_FAILURE); + } + for(i = 0; i < *height; i++) { + (*image)[i] = (png_bytep)malloc(png_get_rowbytes(png_ptr, info_ptr)); + if((*image)[i] == NULL) { + for(j = 0; j < i; j++) free((*image)[j]); + free(*image); + fclose(fp); + std::cerr << " PNGwriter::read_png_image - ERROR **: Could not allocate memory for reading image." << std::endl; + return 0; + //exit(EXIT_FAILURE); + } + } + png_read_image(png_ptr, *image); + + return 1; } /////////////////////////////////// -int pngwriter::getheight(void) -{ - return height_; +int pngwriter::getheight(void) { + return height_; } -int pngwriter::getwidth(void) -{ - return width_; +int pngwriter::getwidth(void) { + return width_; } -int pngwriter::getbitdepth(void) -{ - return bit_depth_; +int pngwriter::getbitdepth(void) { + return bit_depth_; } -int pngwriter::getcolortype(void) -{ - return colortype_; +int pngwriter::getcolortype(void) { + return colortype_; } -double pngwriter::getgamma(void) -{ - return filegamma_; +double pngwriter::getgamma(void) { + return filegamma_; } -void pngwriter::setgamma(double gamma) -{ - filegamma_ = gamma; +void pngwriter::setgamma(double gamma) { + filegamma_ = gamma; } // The algorithms HSVtoRGB and RGBtoHSV were found at http://www.cs.rit.edu/~ncs/ // which is a page that belongs to Nan C. Schaller, though // these algorithms appear to be the work of Eugene Vishnevsky. ////////////////////////////////////////////// -void pngwriter::HSVtoRGB( double *r, double *g, double *b, double h, double s, double v ) -{ - // r,g,b values are from 0 to 1 - // h = [0,1], s = [0,1], v = [0,1] - // if s == 0, then h = -1 (undefined) - // - h = h*360.0; - - int i; - double f, p, q, t; - if( s == 0 ) - { - // achromatic (grey) - *r = *g = *b = v; - return; - } - - h /= 60; // sector 0 to 5 - i = int(floor( h )); - f = h - i; // factorial part of h - p = v * ( 1 - s ); - q = v * ( 1 - s * f ); - t = v * ( 1 - s * ( 1 - f ) ); - - switch( i ) - { - case 0: - *r = v; - *g = t; - *b = p; - break; - case 1: - *r = q; - *g = v; - *b = p; - break; - case 2: - *r = p; - *g = v; - *b = t; - break; - case 3: - *r = p; - *g = q; - *b = v; - break; - case 4: - *r = t; - *g = p; - *b = v; - break; - default: // case 5: - *r = v; - *g = p; - *b = q; - break; - } +void pngwriter::HSVtoRGB(double* r, double* g, double* b, double h, double s, double v) { + // r,g,b values are from 0 to 1 + // h = [0,1], s = [0,1], v = [0,1] + // if s == 0, then h = -1 (undefined) + // + h = h*360.0; + + int i; + double f, p, q, t; + if(s == 0) { + // achromatic (grey) + *r = *g = *b = v; + return; + } + + h /= 60; // sector 0 to 5 + i = int(floor(h)); + f = h - i; // factorial part of h + p = v * (1 - s); + q = v * (1 - s * f); + t = v * (1 - s * (1 - f)); + + switch(i) { + case 0: + *r = v; + *g = t; + *b = p; + break; + case 1: + *r = q; + *g = v; + *b = p; + break; + case 2: + *r = p; + *g = v; + *b = t; + break; + case 3: + *r = p; + *g = q; + *b = v; + break; + case 4: + *r = t; + *g = p; + *b = v; + break; + default: // case 5: + *r = v; + *g = p; + *b = q; + break; + } } -void pngwriter::RGBtoHSV( float r, float g, float b, float *h, float *s, float *v ) -{ - - float min=0.0; //These values are not used. - float max=1.0; - float delta; - - if( (r>=g)&&(r>=b) ) - { - max = r; - } - if( (g>=r)&&(g>=b) ) - { - max = g; - } - if( (b>=g)&&(b>=r) ) - { - max = b; - } - - if( (r<=g)&&(r<=b) ) - { - min = r; - } - if( (g<=r)&&(g<=b) ) - { - min = g; - } - if( (b<=g)&&(b<=r) ) - { - min = b; - } - - *v = max; // v - - delta = max - min; - - if( max != 0 ) - *s = delta / max; // s - else - { - - r = g = b = 0; // s = 0, v is undefined - *s = 0; - *h = -1; - return; - } - - if( r == max ) - *h = ( g - b ) / delta; // between yellow & magenta - else if( g == max ) - *h = 2 + ( b - r ) / delta; // between cyan & yellow - else - *h = 4 + ( r - g ) / delta; // between magenta & cyan +void pngwriter::RGBtoHSV(float r, float g, float b, float* h, float* s, float* v) { + + float min=0.0; //These values are not used. + float max=1.0; + float delta; + + if((r>=g)&&(r>=b)) { + max = r; + } + if((g>=r)&&(g>=b)) { + max = g; + } + if((b>=g)&&(b>=r)) { + max = b; + } + + if((r<=g)&&(r<=b)) { + min = r; + } + if((g<=r)&&(g<=b)) { + min = g; + } + if((b<=g)&&(b<=r)) { + min = b; + } + + *v = max; // v + + delta = max - min; + + if(max != 0) + *s = delta / max; // s + else { + + r = g = b = 0; // s = 0, v is undefined + *s = 0; + *h = -1; + return; + } + + if(r == max) + *h = (g - b) / delta; // between yellow & magenta + else if(g == max) + *h = 2 + (b - r) / delta; // between cyan & yellow + else + *h = 4 + (r - g) / delta; // between magenta & cyan - *h *= 60; // degrees - if( *h < 0 ) - *h += 360; + *h *= 60; // degrees + if(*h < 0) + *h += 360; } // ////////////////////////////////////////////////////////////////////////////////// -void pngwriter::plotHSV(int x, int y, double hue, double saturation, double value) -{ - double red,green,blue; - double *redp; - double *greenp; - double *bluep; - - redp = &red; - greenp = &green; - bluep = &blue; - - HSVtoRGB(redp,greenp,bluep,hue,saturation,value); - plot(x,y,red,green,blue); +void pngwriter::plotHSV(int x, int y, double hue, double saturation, double value) { + double red,green,blue; + double* redp; + double* greenp; + double* bluep; + + redp = &red; + greenp = &green; + bluep = &blue; + + HSVtoRGB(redp,greenp,bluep,hue,saturation,value); + plot(x,y,red,green,blue); } -void pngwriter::plotHSV(int x, int y, int hue, int saturation, int value) -{ - plotHSV(x, y, double(hue)/65535.0, double(saturation)/65535.0, double(value)/65535.0); +void pngwriter::plotHSV(int x, int y, int hue, int saturation, int value) { + plotHSV(x, y, double(hue)/65535.0, double(saturation)/65535.0, double(value)/65535.0); } // ////////////////////////////////////////////////////////////////////////////////// -double pngwriter::dreadHSV(int x, int y, int colour) -{ - if( (x>0)&&(x<=width_)&&(y>0)&&(y<=height_) ) - { +double pngwriter::dreadHSV(int x, int y, int colour) { + if((x>0)&&(x<=width_)&&(y>0)&&(y<=height_)) { - float * huep; - float * saturationp; - float * valuep; - float red,green,blue; - float hue, saturation, value; + float* huep; + float* saturationp; + float* valuep; + float red,green,blue; + float hue, saturation, value; - red = float(dread(x,y,1)); - green = float(dread(x,y,2)); - blue = float(dread(x,y,3)); + red = float(dread(x,y,1)); + green = float(dread(x,y,2)); + blue = float(dread(x,y,3)); - huep = &hue; - saturationp = &saturation; - valuep = &value; + huep = &hue; + saturationp = &saturation; + valuep = &value; - RGBtoHSV( red, green, blue, huep, saturationp, valuep ); + RGBtoHSV(red, green, blue, huep, saturationp, valuep); - if(colour == 1) - { - return double(hue)/360.0; - } + if(colour == 1) { + return double(hue)/360.0; + } - else if(colour == 2) - { - return saturation; - } + else if(colour == 2) { + return saturation; + } - else if(colour == 3) - { - return value; - } + else if(colour == 3) { + return value; + } - std::cerr << " PNGwriter::dreadHSV - ERROR **: Called with wrong colour argument: should be 1, 2 or 3; was: " << colour << "." << std::endl; - } - return 0.0; + std::cerr << " PNGwriter::dreadHSV - ERROR **: Called with wrong colour argument: should be 1, 2 or 3; was: " << colour << "." << std::endl; + } + return 0.0; } // ////////////////////////////////////////////////////////////////////////////////// -int pngwriter::readHSV(int x, int y, int colour) -{ - if( (x>0)&&(x<=width_)&&(y>0)&&(y<=height_) ) - { - - float * huep; - float * saturationp; - float * valuep; - float red,green,blue; - float hue, saturation, value; - - red = float(dread(x,y,1)); - green = float(dread(x,y,2)); - blue = float(dread(x,y,3)); - - huep = &hue; - saturationp = &saturation; - valuep = &value; - - RGBtoHSV( red, green, blue, huep, saturationp, valuep ); - - if(colour == 1) - { - return int(65535*(double(hue)/360.0)); - } - - else if(colour == 2) - { - return int(65535*saturation); - } - - else if(colour == 3) - { - return int(65535*value); - } - - std::cerr << " PNGwriter::readHSV - ERROR **: Called with wrong colour argument: should be 1, 2 or 3; was: " << colour << "." << std::endl; - return 0; - } - else - { - return 0; - } +int pngwriter::readHSV(int x, int y, int colour) { + if((x>0)&&(x<=width_)&&(y>0)&&(y<=height_)) { + + float* huep; + float* saturationp; + float* valuep; + float red,green,blue; + float hue, saturation, value; + + red = float(dread(x,y,1)); + green = float(dread(x,y,2)); + blue = float(dread(x,y,3)); + + huep = &hue; + saturationp = &saturation; + valuep = &value; + + RGBtoHSV(red, green, blue, huep, saturationp, valuep); + + if(colour == 1) { + return int(65535*(double(hue)/360.0)); + } + + else if(colour == 2) { + return int(65535*saturation); + } + + else if(colour == 3) { + return int(65535*value); + } + + std::cerr << " PNGwriter::readHSV - ERROR **: Called with wrong colour argument: should be 1, 2 or 3; was: " << colour << "." << std::endl; + return 0; + } else { + return 0; + } } -void pngwriter::setcompressionlevel(int level) -{ - if( (level < -1)||(level > 9) ) - { - std::cerr << " PNGwriter::setcompressionlevel - ERROR **: Called with wrong compression level: should be -1 to 9, was: " << level << "." << std::endl; - } - compressionlevel_ = level; +void pngwriter::setcompressionlevel(int level) { + if((level < -1)||(level > 9)) { + std::cerr << " PNGwriter::setcompressionlevel - ERROR **: Called with wrong compression level: should be -1 to 9, was: " << level << "." << std::endl; + } + compressionlevel_ = level; } // An implementation of a Bezier curve. -void pngwriter::bezier( int startPtX, int startPtY, - int startControlX, int startControlY, - int endPtX, int endPtY, - int endControlX, int endControlY, - double red, double green, double blue) -{ - - double cx = 3.0*(startControlX - startPtX); - double bx = 3.0*(endControlX - startControlX) - cx; - double ax = double(endPtX - startPtX - cx - bx); - - double cy = 3.0*(startControlY - startPtY); - double by = 3.0*(endControlY - startControlY) - cy; - double ay = double(endPtY - startPtY - cy - by); - - double x,y,newx,newy; - x = startPtX; - y = startPtY; - - for(double t = 0.0; t<=1.005; t += 0.005) - { - newx = startPtX + t*(double(cx) + t*(double(bx) + t*(double(ax)))); - newy = startPtY + t*(double(cy) + t*(double(by) + t*(double(ay)))); - this->line(int(x),int(y),int(newx),int(newy),red,green,blue); - x = newx; - y = newy; - } +void pngwriter::bezier(int startPtX, int startPtY, + int startControlX, int startControlY, + int endPtX, int endPtY, + int endControlX, int endControlY, + double red, double green, double blue) { + + double cx = 3.0*(startControlX - startPtX); + double bx = 3.0*(endControlX - startControlX) - cx; + double ax = double(endPtX - startPtX - cx - bx); + + double cy = 3.0*(startControlY - startPtY); + double by = 3.0*(endControlY - startControlY) - cy; + double ay = double(endPtY - startPtY - cy - by); + + double x,y,newx,newy; + x = startPtX; + y = startPtY; + + for(double t = 0.0; t<=1.005; t += 0.005) { + newx = startPtX + t*(double(cx) + t*(double(bx) + t*(double(ax)))); + newy = startPtY + t*(double(cy) + t*(double(by) + t*(double(ay)))); + this->line(int(x),int(y),int(newx),int(newy),red,green,blue); + x = newx; + y = newy; + } } //int version of bezier -void pngwriter::bezier( int startPtX, int startPtY, - int startControlX, int startControlY, - int endPtX, int endPtY, - int endControlX, int endControlY, - int red, int green, int blue) -{ - this->bezier( startPtX, startPtY, - startControlX, startControlY, - endPtX, endPtY, - endControlX, endControlY, - double(red)/65535.0, double(green)/65535.0, double(blue)/65535.0); +void pngwriter::bezier(int startPtX, int startPtY, + int startControlX, int startControlY, + int endPtX, int endPtY, + int endControlX, int endControlY, + int red, int green, int blue) { + this->bezier(startPtX, startPtY, + startControlX, startControlY, + endPtX, endPtY, + endControlX, endControlY, + double(red)/65535.0, double(green)/65535.0, double(blue)/65535.0); } /* @@ -1921,352 +1701,343 @@ int pngwriter::getcompressionlevel(void) } */ -double pngwriter::version(void) -{ - const char *a = "Jeramy Webb (jeramyw@gmail.com), Mike Heller (mkheller@gmail.com)"; // For their generosity ;-) - char b = a[27]; - b++; - return (PNGWRITER_VERSION); +double pngwriter::version(void) { + const char* a = "Jeramy Webb (jeramyw@gmail.com), Mike Heller (mkheller@gmail.com)"; // For their generosity ;-) + char b = a[27]; + b++; + return (PNGWRITER_VERSION); } -void pngwriter::write_png(void) -{ - this->close(); +void pngwriter::write_png(void) { + this->close(); } #ifndef NO_FREETYPE // Freetype-based text rendering functions. /////////////////////////////////////////// -void pngwriter::plot_text( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double red, double green, double blue) -{ - FT_Library library; - FT_Face face; - FT_Matrix matrix; // transformation matrix - FT_Vector pen; - - FT_UInt glyph_index; - FT_Error error; - - FT_Bool use_kerning; - FT_UInt previous = 0; - - /* Set up transformation Matrix */ - matrix.xx = (FT_Fixed)( cos(angle)*0x10000); /* It would make more sense to do this (below), but, bizzarely, */ - matrix.xy = (FT_Fixed)(-sin(angle)*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ - matrix.yx = (FT_Fixed)( sin(angle)*0x10000); // matrix.yx = - matrix.xy; - matrix.yy = (FT_Fixed)( cos(angle)*0x10000); // matrix.yy = matrix.xx; - - /* Place starting coordinates in adequate form. */ - pen.x = x_start*64 ; - pen.y = (int)(y_start/64.0); - - /*Count the length of the string */ - int num_chars = strlen(text); - - /* Initialize FT Library object */ - error = FT_Init_FreeType( &library ); - if (error) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not init Library."<< std::endl; return;} - - /* Initialize FT face object */ - error = FT_New_Face( library,face_path,0,&face ); - if ( error == FT_Err_Unknown_File_Format ) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Font was opened, but type not supported."<< std::endl; return; } else if (error){ std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not find or load font file."<< std::endl; return; } - - /* Set the Char size */ - error = FT_Set_Char_Size( face, /* handle to face object */ - 0, /* char_width in 1/64th of points */ - fontsize*64, /* char_height in 1/64th of points */ - 100, /* horizontal device resolution */ - 100 ); /* vertical device resolution */ - - /* A way of accesing the glyph directly */ - FT_GlyphSlot slot = face->glyph; // a small shortcut - - /* Does the font file support kerning? */ - use_kerning = FT_HAS_KERNING( face ); - - int n; - for ( n = 0; n < num_chars; n++ ) - { - /* Convert character code to glyph index */ - glyph_index = FT_Get_Char_Index( face, text[n] ); - - /* Retrieve kerning distance and move pen position */ - if ( use_kerning && previous&& glyph_index ) - { - FT_Vector delta; - FT_Get_Kerning( face, - previous, - glyph_index, - ft_kerning_default, //FT_KERNING_DEFAULT, - &delta ); - - /* Transform this kerning distance into rotated space */ - pen.x += (int) (((double) delta.x)*cos(angle)); - pen.y += (int) (((double) delta.x)*( sin(angle))); - } - - /* Set transform */ - FT_Set_Transform( face, &matrix, &pen ); - -/*set char size*/ - - if (error) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Set char size error." << std::endl; return;}; - - /* Retrieve glyph index from character code */ - glyph_index = FT_Get_Char_Index( face, text[n] ); - - /* Load glyph image into the slot (erase previous one) */ - error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); - if (error) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return;} - - /* Convert to an anti-aliased bitmap */ - // error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL ); - error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); - if (error) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Render glyph error." << std::endl; return;} - - /* Now, draw to our target surface */ - my_draw_bitmap( &slot->bitmap, - slot->bitmap_left, - y_start + slot->bitmap_top, - red, - green, - blue ); - - /* Advance to the next position */ - pen.x += slot->advance.x; - pen.y += slot->advance.y; - - /* record current glyph index */ - previous = glyph_index; - } - - /* Free the face and the library objects */ - FT_Done_Face ( face ); - FT_Done_FreeType( library ); +void pngwriter::plot_text(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, double red, double green, double blue) { + FT_Library library; + FT_Face face; + FT_Matrix matrix; // transformation matrix + FT_Vector pen; + + FT_UInt glyph_index; + FT_Error error; + + FT_Bool use_kerning; + FT_UInt previous = 0; + + /* Set up transformation Matrix */ + matrix.xx = (FT_Fixed)(cos(angle)*0x10000); /* It would make more sense to do this (below), but, bizzarely, */ + matrix.xy = (FT_Fixed)(-sin(angle)*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ + matrix.yx = (FT_Fixed)(sin(angle)*0x10000); // matrix.yx = - matrix.xy; + matrix.yy = (FT_Fixed)(cos(angle)*0x10000); // matrix.yy = matrix.xx; + + /* Place starting coordinates in adequate form. */ + pen.x = x_start*64 ; + pen.y = (int)(y_start/64.0); + + /*Count the length of the string */ + int num_chars = strlen(text); + + /* Initialize FT Library object */ + error = FT_Init_FreeType(&library); + if(error) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not init Library."<< std::endl; return;} + + /* Initialize FT face object */ + error = FT_New_Face(library,face_path,0,&face); + if(error == FT_Err_Unknown_File_Format) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Font was opened, but type not supported."<< std::endl; return; } else if(error) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not find or load font file."<< std::endl; return; } + + /* Set the Char size */ + error = FT_Set_Char_Size(face, /* handle to face object */ + 0, /* char_width in 1/64th of points */ + fontsize*64, /* char_height in 1/64th of points */ + 100, /* horizontal device resolution */ + 100); /* vertical device resolution */ + + /* A way of accesing the glyph directly */ + FT_GlyphSlot slot = face->glyph; // a small shortcut + + /* Does the font file support kerning? */ + use_kerning = FT_HAS_KERNING(face); + + int n; + for(n = 0; n < num_chars; n++) { + /* Convert character code to glyph index */ + glyph_index = FT_Get_Char_Index(face, text[n]); + + /* Retrieve kerning distance and move pen position */ + if(use_kerning && previous&& glyph_index) { + FT_Vector delta; + FT_Get_Kerning(face, + previous, + glyph_index, + ft_kerning_default, //FT_KERNING_DEFAULT, + &delta); + + /* Transform this kerning distance into rotated space */ + pen.x += (int)(((double) delta.x)*cos(angle)); + pen.y += (int)(((double) delta.x)*(sin(angle))); + } + + /* Set transform */ + FT_Set_Transform(face, &matrix, &pen); + + /*set char size*/ + + if(error) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Set char size error." << std::endl; return;}; + + /* Retrieve glyph index from character code */ + glyph_index = FT_Get_Char_Index(face, text[n]); + + /* Load glyph image into the slot (erase previous one) */ + error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + if(error) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return;} + + /* Convert to an anti-aliased bitmap */ + // error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL ); + error = FT_Render_Glyph(face->glyph, ft_render_mode_normal); + if(error) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Render glyph error." << std::endl; return;} + + /* Now, draw to our target surface */ + my_draw_bitmap(&slot->bitmap, + slot->bitmap_left, + y_start + slot->bitmap_top, + red, + green, + blue); + + /* Advance to the next position */ + pen.x += slot->advance.x; + pen.y += slot->advance.y; + + /* record current glyph index */ + previous = glyph_index; + } + + /* Free the face and the library objects */ + FT_Done_Face(face); + FT_Done_FreeType(library); } -void pngwriter::plot_text_utf8( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double red, double green, double blue) -{ - FT_Library library; - FT_Face face; - FT_Matrix matrix; // transformation matrix - FT_Vector pen; - - FT_UInt glyph_index; - FT_Error error; - - FT_Bool use_kerning; - FT_UInt previous = 0; - - /* Set up transformation Matrix */ - matrix.xx = (FT_Fixed)( cos(angle)*0x10000); /* It would make more sense to do this (below), but, bizzarely, */ - matrix.xy = (FT_Fixed)(-sin(angle)*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ - matrix.yx = (FT_Fixed)( sin(angle)*0x10000); // matrix.yx = - matrix.xy; - matrix.yy = (FT_Fixed)( cos(angle)*0x10000); // matrix.yy = matrix.xx; - - /* Place starting coordinates in adequate form. */ - pen.x = x_start*64 ; - pen.y = (int)(y_start/64.0); - - /*Count the length of the string */ - int num_bytes=0; - while(text[num_bytes]!=0) - { - num_bytes++; - } - - /* - std::cout << "Num bytes is: "<< num_bytes << std::endl; - */ - - //The array of ucs4 glyph indexes, which will by at most the number of bytes in the utf-8 file. - long * ucs4text; - ucs4text = new long[num_bytes+1]; - - unsigned char u,v,w,x,y,z; - - int num_chars=0; - - long iii=0; - - while(iiiglyph; // a small shortcut - - /* Does the font file support kerning? */ - use_kerning = FT_HAS_KERNING( face ); - - int n; - for ( n = 0; n < num_chars; n++ ) - { - /* Convert character code to glyph index */ - glyph_index = FT_Get_Char_Index( face, ucs4text[n] ); - - /* Retrieve kerning distance and move pen position */ - if ( use_kerning && previous&& glyph_index ) - { - FT_Vector delta; - FT_Get_Kerning( face, - previous, - glyph_index, - ft_kerning_default, //FT_KERNING_DEFAULT, - &delta ); - - /* Transform this kerning distance into rotated space */ - pen.x += (int) (((double) delta.x)*cos(angle)); - pen.y += (int) (((double) delta.x)*( sin(angle))); - } - - /* Set transform */ - FT_Set_Transform( face, &matrix, &pen ); - -/*set char size*/ - - if (error) { std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: FreeType: Set char size error." << std::endl; return;}; +void pngwriter::plot_text_utf8(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, double red, double green, double blue) { + FT_Library library; + FT_Face face; + FT_Matrix matrix; // transformation matrix + FT_Vector pen; - /* Retrieve glyph index from character code */ - glyph_index = FT_Get_Char_Index( face, ucs4text[n] ); + FT_UInt glyph_index; + FT_Error error; - /* Load glyph image into the slot (erase previous one) */ - error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); - if (error) { std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return;} + FT_Bool use_kerning; + FT_UInt previous = 0; - /* Convert to an anti-aliased bitmap */ - error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); - if (error) { std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: FreeType: Render glyph error." << std::endl; return;} + /* Set up transformation Matrix */ + matrix.xx = (FT_Fixed)(cos(angle)*0x10000); /* It would make more sense to do this (below), but, bizzarely, */ + matrix.xy = (FT_Fixed)(-sin(angle)*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ + matrix.yx = (FT_Fixed)(sin(angle)*0x10000); // matrix.yx = - matrix.xy; + matrix.yy = (FT_Fixed)(cos(angle)*0x10000); // matrix.yy = matrix.xx; - /* Now, draw to our target surface */ - my_draw_bitmap( &slot->bitmap, - slot->bitmap_left, - y_start + slot->bitmap_top, - red, - green, - blue ); + /* Place starting coordinates in adequate form. */ + pen.x = x_start*64 ; + pen.y = (int)(y_start/64.0); - /* Advance to the next position */ - pen.x += slot->advance.x; - pen.y += slot->advance.y; + /*Count the length of the string */ + int num_bytes=0; + while(text[num_bytes]!=0) { + num_bytes++; + } - /* record current glyph index */ - previous = glyph_index; - } - - /* Free the face and the library objects */ - FT_Done_Face ( face ); - FT_Done_FreeType( library ); - - delete[] ucs4text; + /* + std::cout << "Num bytes is: "<< num_bytes << std::endl; + */ + + //The array of ucs4 glyph indexes, which will by at most the number of bytes in the utf-8 file. + long* ucs4text; + ucs4text = new long[num_bytes+1]; + + unsigned char u,v,w,x,y,z; + + int num_chars=0; + + long iii=0; + + while(iiiglyph; // a small shortcut + + /* Does the font file support kerning? */ + use_kerning = FT_HAS_KERNING(face); + + int n; + for(n = 0; n < num_chars; n++) { + /* Convert character code to glyph index */ + glyph_index = FT_Get_Char_Index(face, ucs4text[n]); + + /* Retrieve kerning distance and move pen position */ + if(use_kerning && previous&& glyph_index) { + FT_Vector delta; + FT_Get_Kerning(face, + previous, + glyph_index, + ft_kerning_default, //FT_KERNING_DEFAULT, + &delta); + + /* Transform this kerning distance into rotated space */ + pen.x += (int)(((double) delta.x)*cos(angle)); + pen.y += (int)(((double) delta.x)*(sin(angle))); + } + + /* Set transform */ + FT_Set_Transform(face, &matrix, &pen); + + /*set char size*/ + + if(error) { std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: FreeType: Set char size error." << std::endl; return;}; + + /* Retrieve glyph index from character code */ + glyph_index = FT_Get_Char_Index(face, ucs4text[n]); + + /* Load glyph image into the slot (erase previous one) */ + error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + if(error) { std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return;} + + /* Convert to an anti-aliased bitmap */ + error = FT_Render_Glyph(face->glyph, ft_render_mode_normal); + if(error) { std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: FreeType: Render glyph error." << std::endl; return;} + + /* Now, draw to our target surface */ + my_draw_bitmap(&slot->bitmap, + slot->bitmap_left, + y_start + slot->bitmap_top, + red, + green, + blue); + + /* Advance to the next position */ + pen.x += slot->advance.x; + pen.y += slot->advance.y; + + /* record current glyph index */ + previous = glyph_index; + } + + /* Free the face and the library objects */ + FT_Done_Face(face); + FT_Done_FreeType(library); + + delete[] ucs4text; } -void pngwriter::plot_text( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, int red, int green, int blue) -{ - plot_text( face_path, fontsize, x_start, y_start, angle, text, ((double) red)/65535.0, ((double) green)/65535.0, ((double) blue)/65535.0 ); +void pngwriter::plot_text(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, int red, int green, int blue) { + plot_text(face_path, fontsize, x_start, y_start, angle, text, ((double) red)/65535.0, ((double) green)/65535.0, ((double) blue)/65535.0); } -void pngwriter::plot_text_utf8( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, int red, int green, int blue) -{ - plot_text_utf8( face_path, fontsize, x_start, y_start, angle, text, ((double) red)/65535.0, ((double) green)/65535.0, ((double) blue)/65535.0 ); +void pngwriter::plot_text_utf8(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, int red, int green, int blue) { + plot_text_utf8(face_path, fontsize, x_start, y_start, angle, text, ((double) red)/65535.0, ((double) green)/65535.0, ((double) blue)/65535.0); } -void pngwriter::my_draw_bitmap( FT_Bitmap * bitmap, int x, int y, double red, double green, double blue) -{ - double temp; - for(int j=1; jrows+1; j++) - { - for(int i=1; i< bitmap->width + 1; i++) - { - temp = (double)(bitmap->buffer[(j-1)*bitmap->width + (i-1)] )/255.0; - - if(temp) - { - this->plot(x + i, - y - j, - temp*red + (1-temp)*(this->dread(x+i,y-j,1)), - temp*green + (1-temp)*(this->dread(x+i,y-j,2)), - temp*blue + (1-temp)*(this->dread(x+i,y-j,3)) - ); - } - } - } +void pngwriter::my_draw_bitmap(FT_Bitmap* bitmap, int x, int y, double red, double green, double blue) { + double temp; + for(int j=1; jrows+1; j++) { + for(int i=1; i< bitmap->width + 1; i++) { + temp = (double)(bitmap->buffer[(j-1)*bitmap->width + (i-1)])/255.0; + + if(temp) { + this->plot(x + i, + y - j, + temp*red + (1-temp)*(this->dread(x+i,y-j,1)), + temp*green + (1-temp)*(this->dread(x+i,y-j,2)), + temp*blue + (1-temp)*(this->dread(x+i,y-j,3)) + ); + } + } + } } @@ -2275,1411 +2046,1277 @@ void pngwriter::my_draw_bitmap( FT_Bitmap * bitmap, int x, int y, double red, do //put in freetype section -int pngwriter::get_text_width(char * face_path, int fontsize, char * text) -{ - - FT_Library library; - FT_Face face; - FT_Matrix matrix; // transformation matrix - FT_Vector pen; - - FT_UInt glyph_index; - FT_Error error; - - FT_Bool use_kerning; - FT_UInt previous = 0; - - /* Set up transformation Matrix */ - matrix.xx = (FT_Fixed)( 1.0*0x10000); /* It would make more sense to do this (below), but, bizzarely, */ - matrix.xy = (FT_Fixed)( 0.0*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ - matrix.yx = (FT_Fixed)( 0.0*0x10000); // matrix.yx = - matrix.xy; - matrix.yy = (FT_Fixed)( 1.0*0x10000); // matrix.yy = matrix.xx; - - /* Place starting coordinates in adequate form. */ - pen.x = 0; - pen.y = 0; - - /*Count the length of the string */ - int num_chars = strlen(text); - - /* Initialize FT Library object */ - error = FT_Init_FreeType( &library ); - if (error) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Could not init Library."<< std::endl; return 0;} - - /* Initialize FT face object */ - error = FT_New_Face( library,face_path,0,&face ); - if ( error == FT_Err_Unknown_File_Format ) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Font was opened, but type not supported."<< std::endl; return 0; } else if (error){ std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Could not find or load font file." << std::endl; return 0; } - - /* Set the Char size */ - error = FT_Set_Char_Size( face, /* handle to face object */ - 0, /* char_width in 1/64th of points */ - fontsize*64, /* char_height in 1/64th of points */ - 100, /* horizontal device resolution */ - 100 ); /* vertical device resolution */ - - /* A way of accesing the glyph directly */ - FT_GlyphSlot slot = face->glyph; // a small shortcut - - /* Does the font file support kerning? */ - use_kerning = FT_HAS_KERNING( face ); - - int n; - for ( n = 0; n < num_chars; n++ ) - { - /* Convert character code to glyph index */ - glyph_index = FT_Get_Char_Index( face, text[n] ); - - /* Retrieve kerning distance and move pen position */ - if ( use_kerning && previous&& glyph_index ) - { - FT_Vector delta; - FT_Get_Kerning( face, - previous, - glyph_index, - ft_kerning_default, //FT_KERNING_DEFAULT, - &delta ); - - /* Transform this kerning distance into rotated space */ - pen.x += (int) ( delta.x); - pen.y += 0; - } - - /* Set transform */ - FT_Set_Transform( face, &matrix, &pen ); - -/*set char size*/ - - if (error) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Set char size error." << std::endl; return 0;}; - - /* Retrieve glyph index from character code */ - glyph_index = FT_Get_Char_Index( face, text[n] ); - - /* Load glyph image into the slot (erase previous one) */ - error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); - if (error) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return 0;} - - /* Convert to an anti-aliased bitmap */ - // error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL ); - error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); - if (error) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Render glyph error." << std::endl; return 0;} - - /* Now, draw to our target surface */ -/* my_draw_bitmap( &slot->bitmap, - slot->bitmap_left, - slot->bitmap_top, - red, - green, - blue ); -*/ - /* Advance to the next position */ - pen.x += slot->advance.x; +int pngwriter::get_text_width(char* face_path, int fontsize, char* text) { + + FT_Library library; + FT_Face face; + FT_Matrix matrix; // transformation matrix + FT_Vector pen; + + FT_UInt glyph_index; + FT_Error error; + + FT_Bool use_kerning; + FT_UInt previous = 0; + + /* Set up transformation Matrix */ + matrix.xx = (FT_Fixed)(1.0*0x10000); /* It would make more sense to do this (below), but, bizzarely, */ + matrix.xy = (FT_Fixed)(0.0*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ + matrix.yx = (FT_Fixed)(0.0*0x10000); // matrix.yx = - matrix.xy; + matrix.yy = (FT_Fixed)(1.0*0x10000); // matrix.yy = matrix.xx; + + /* Place starting coordinates in adequate form. */ + pen.x = 0; + pen.y = 0; + + /*Count the length of the string */ + int num_chars = strlen(text); + + /* Initialize FT Library object */ + error = FT_Init_FreeType(&library); + if(error) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Could not init Library."<< std::endl; return 0;} + + /* Initialize FT face object */ + error = FT_New_Face(library,face_path,0,&face); + if(error == FT_Err_Unknown_File_Format) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Font was opened, but type not supported."<< std::endl; return 0; } else if(error) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Could not find or load font file." << std::endl; return 0; } + + /* Set the Char size */ + error = FT_Set_Char_Size(face, /* handle to face object */ + 0, /* char_width in 1/64th of points */ + fontsize*64, /* char_height in 1/64th of points */ + 100, /* horizontal device resolution */ + 100); /* vertical device resolution */ + + /* A way of accesing the glyph directly */ + FT_GlyphSlot slot = face->glyph; // a small shortcut + + /* Does the font file support kerning? */ + use_kerning = FT_HAS_KERNING(face); + + int n; + for(n = 0; n < num_chars; n++) { + /* Convert character code to glyph index */ + glyph_index = FT_Get_Char_Index(face, text[n]); + + /* Retrieve kerning distance and move pen position */ + if(use_kerning && previous&& glyph_index) { + FT_Vector delta; + FT_Get_Kerning(face, + previous, + glyph_index, + ft_kerning_default, //FT_KERNING_DEFAULT, + &delta); + + /* Transform this kerning distance into rotated space */ + pen.x += (int)(delta.x); + pen.y += 0; + } + + /* Set transform */ + FT_Set_Transform(face, &matrix, &pen); + + /*set char size*/ + + if(error) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Set char size error." << std::endl; return 0;}; + + /* Retrieve glyph index from character code */ + glyph_index = FT_Get_Char_Index(face, text[n]); + + /* Load glyph image into the slot (erase previous one) */ + error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + if(error) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return 0;} + + /* Convert to an anti-aliased bitmap */ + // error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL ); + error = FT_Render_Glyph(face->glyph, ft_render_mode_normal); + if(error) { std::cerr << " PNGwriter::get_text_width - ERROR **: FreeType: Render glyph error." << std::endl; return 0;} + + /* Now, draw to our target surface */ + /* my_draw_bitmap( &slot->bitmap, + slot->bitmap_left, + slot->bitmap_top, + red, + green, + blue ); + */ + /* Advance to the next position */ + pen.x += slot->advance.x; // std::cout << ((double) pen.x)/64.0 << std::endl; - pen.y += slot->advance.y; - - /* record current glyph index */ - previous = glyph_index; - } - - - /* Free the face and the library objects */ - FT_Done_Face ( face ); - FT_Done_FreeType( library ); - - return (int)( ((double)pen.x)/64.0 ); -} - - -int pngwriter::get_text_width_utf8(char * face_path, int fontsize, char * text) -{ - FT_Library library; - FT_Face face; - FT_Matrix matrix; // transformation matrix - FT_Vector pen; - - FT_UInt glyph_index; - FT_Error error; - - FT_Bool use_kerning; - FT_UInt previous = 0; - - /* Set up transformation Matrix */ - matrix.xx = (FT_Fixed)( 0x10000); /* It would make more sense to do this (below), but, bizzarely, */ - matrix.xy = (FT_Fixed)( 0*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ - matrix.yx = (FT_Fixed)( 0*0x10000); // matrix.yx = - matrix.xy; - matrix.yy = (FT_Fixed)( 0x10000); // matrix.yy = matrix.xx; - - /* Place starting coordinates in adequate form. */ - pen.x = 0 ; - pen.y = 0; + pen.y += slot->advance.y; - /*Count the length of the string */ - int num_bytes=0; - while(text[num_bytes]!=0) - { - num_bytes++; - } + /* record current glyph index */ + previous = glyph_index; + } - /* - std::cout << "Num bytes is: "<< num_bytes << std::endl; - */ - //The array of ucs4 glyph indexes, which will by at most the number of bytes in the utf-8 file. - long * ucs4text; - ucs4text = new long[num_bytes+1]; + /* Free the face and the library objects */ + FT_Done_Face(face); + FT_Done_FreeType(library); - unsigned char u,v,w,x,y,z; - - int num_chars=0; - - long iii=0; - - while(iiiglyph; // a small shortcut - - /* Does the font file support kerning? */ - use_kerning = FT_HAS_KERNING( face ); - - int n; - for ( n = 0; n < num_chars; n++ ) - { - /* Convert character code to glyph index */ - glyph_index = FT_Get_Char_Index( face, ucs4text[n] ); - - /* Retrieve kerning distance and move pen position */ - if ( use_kerning && previous&& glyph_index ) - { - FT_Vector delta; - FT_Get_Kerning( face, - previous, - glyph_index, - ft_kerning_default, //FT_KERNING_DEFAULT, - &delta ); - - /* Transform this kerning distance into rotated space */ - pen.x += (int) (delta.x); - pen.y += 0; - } - - /* Set transform */ - FT_Set_Transform( face, &matrix, &pen ); - -/*set char size*/ + return (int)(((double)pen.x)/64.0); +} - if (error) { std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: FreeType: Set char size error." << std::endl; return 0;}; - /* Retrieve glyph index from character code */ - glyph_index = FT_Get_Char_Index( face, ucs4text[n] ); +int pngwriter::get_text_width_utf8(char* face_path, int fontsize, char* text) { + FT_Library library; + FT_Face face; + FT_Matrix matrix; // transformation matrix + FT_Vector pen; - /* Load glyph image into the slot (erase previous one) */ - error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); - if (error) { std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return 0;} + FT_UInt glyph_index; + FT_Error error; - /* Convert to an anti-aliased bitmap */ - error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); - if (error) { std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: FreeType: Render glyph error." << std::endl; return 0;} + FT_Bool use_kerning; + FT_UInt previous = 0; - /* Now, draw to our target surface */ -/* my_draw_bitmap( &slot->bitmap, - slot->bitmap_left, - y_start + slot->bitmap_top, - red, - green, - blue ); -*/ - /* Advance to the next position */ - pen.x += slot->advance.x; - pen.y += slot->advance.y; + /* Set up transformation Matrix */ + matrix.xx = (FT_Fixed)(0x10000); /* It would make more sense to do this (below), but, bizzarely, */ + matrix.xy = (FT_Fixed)(0*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ + matrix.yx = (FT_Fixed)(0*0x10000); // matrix.yx = - matrix.xy; + matrix.yy = (FT_Fixed)(0x10000); // matrix.yy = matrix.xx; - /* record current glyph index */ - previous = glyph_index; - } + /* Place starting coordinates in adequate form. */ + pen.x = 0 ; + pen.y = 0; - /* Free the face and the library objects */ - FT_Done_Face ( face ); - FT_Done_FreeType( library ); + /*Count the length of the string */ + int num_bytes=0; + while(text[num_bytes]!=0) { + num_bytes++; + } - delete[] ucs4text; - - return (int) (((double) pen.x)/64.0); + /* + std::cout << "Num bytes is: "<< num_bytes << std::endl; + */ + + //The array of ucs4 glyph indexes, which will by at most the number of bytes in the utf-8 file. + long* ucs4text; + ucs4text = new long[num_bytes+1]; + + unsigned char u,v,w,x,y,z; + + int num_chars=0; + + long iii=0; + + while(iiiglyph; // a small shortcut + + /* Does the font file support kerning? */ + use_kerning = FT_HAS_KERNING(face); + + int n; + for(n = 0; n < num_chars; n++) { + /* Convert character code to glyph index */ + glyph_index = FT_Get_Char_Index(face, ucs4text[n]); + + /* Retrieve kerning distance and move pen position */ + if(use_kerning && previous&& glyph_index) { + FT_Vector delta; + FT_Get_Kerning(face, + previous, + glyph_index, + ft_kerning_default, //FT_KERNING_DEFAULT, + &delta); + + /* Transform this kerning distance into rotated space */ + pen.x += (int)(delta.x); + pen.y += 0; + } + + /* Set transform */ + FT_Set_Transform(face, &matrix, &pen); + + /*set char size*/ + + if(error) { std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: FreeType: Set char size error." << std::endl; return 0;}; + + /* Retrieve glyph index from character code */ + glyph_index = FT_Get_Char_Index(face, ucs4text[n]); + + /* Load glyph image into the slot (erase previous one) */ + error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + if(error) { std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return 0;} + + /* Convert to an anti-aliased bitmap */ + error = FT_Render_Glyph(face->glyph, ft_render_mode_normal); + if(error) { std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: FreeType: Render glyph error." << std::endl; return 0;} + + /* Now, draw to our target surface */ + /* my_draw_bitmap( &slot->bitmap, + slot->bitmap_left, + y_start + slot->bitmap_top, + red, + green, + blue ); + */ + /* Advance to the next position */ + pen.x += slot->advance.x; + pen.y += slot->advance.y; + + /* record current glyph index */ + previous = glyph_index; + } + + /* Free the face and the library objects */ + FT_Done_Face(face); + FT_Done_FreeType(library); + + delete[] ucs4text; + + return (int)(((double) pen.x)/64.0); } /////////////// #endif #ifdef NO_FREETYPE -void pngwriter::plot_text( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, int red, int green, int blue) -{ - std::cerr << " PNGwriter::plot_text - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; - return; +void pngwriter::plot_text(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, int red, int green, int blue) { + std::cerr << " PNGwriter::plot_text - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; + return; } -void pngwriter::plot_text( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double red, double green, double blue) -{ - std::cerr << " PNGwriter::plot_text - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; - return; +void pngwriter::plot_text(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, double red, double green, double blue) { + std::cerr << " PNGwriter::plot_text - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; + return; } -void pngwriter::plot_text_utf8( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, int red, int green, int blue) -{ - std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; - return; +void pngwriter::plot_text_utf8(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, int red, int green, int blue) { + std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; + return; } -void pngwriter::plot_text_utf8( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double red, double green, double blue) -{ - std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; - return; +void pngwriter::plot_text_utf8(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, double red, double green, double blue) { + std::cerr << " PNGwriter::plot_text_utf8 - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; + return; } //////////// Get text width -int pngwriter::get_text_width(char * face_path, int fontsize, char * text) -{ - std::cerr << " PNGwriter::get_text_width - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; - return 0; +int pngwriter::get_text_width(char* face_path, int fontsize, char* text) { + std::cerr << " PNGwriter::get_text_width - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; + return 0; } -int pngwriter::get_text_width_utf8(char * face_path, int fontsize, char * text) -{ - std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; - return 0; +int pngwriter::get_text_width_utf8(char* face_path, int fontsize, char* text) { + std::cerr << " PNGwriter::get_text_width_utf8 - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; + return 0; } /////////////// #endif ///////////////////////////////////// -int pngwriter::bilinear_interpolation_read(double x, double y, int colour) -{ +int pngwriter::bilinear_interpolation_read(double x, double y, int colour) { - int inty, intx; - inty = (int) ceil(y); - intx = (int) ceil(x); + int inty, intx; + inty = (int) ceil(y); + intx = (int) ceil(x); - //inty = (int) floor(y) +1; - // intx = (int) floor(x) +1; - // - bool attop, atright; - attop = inty==this->height_; - atright = intx==this->width_; -/* - if( intx==this->width_ +1) - { - intx--; - // std::cout << "intx--" << std::endl; - - } - */ - /* - if(inty == this->height_ +1) - { + //inty = (int) floor(y) +1; + // intx = (int) floor(x) +1; + // + bool attop, atright; + attop = inty==this->height_; + atright = intx==this->width_; + /* + if( intx==this->width_ +1) + { + intx--; + // std::cout << "intx--" << std::endl; + + } + */ + /* + if(inty == this->height_ +1) + { inty--; // std::cout << "inty--" << std::endl; - } - */ + } + */ - if( (!attop)&&(!atright) ) - { + if((!attop)&&(!atright)) { - double f,g,f1,g1; - f = 1.0 + x - ((double) intx); - g = 1.0 + y - ((double) inty); - f1 = 1.0 - f; - g1 = 1.0 - g; + double f,g,f1,g1; + f = 1.0 + x - ((double) intx); + g = 1.0 + y - ((double) inty); + f1 = 1.0 - f; + g1 = 1.0 - g; - return (int) ( - f1*g1*this->read(intx, inty,colour) - + f*g1*this->read(intx+1,inty,colour) - +f1*g*this->read(intx,inty+1,colour) - + f*g*(this->read(intx+1,inty+1,colour)) - ); - } + return (int)( + f1*g1*this->read(intx, inty,colour) + + f*g1*this->read(intx+1,inty,colour) + +f1*g*this->read(intx,inty+1,colour) + + f*g*(this->read(intx+1,inty+1,colour)) + ); + } - if( (atright)&&(!attop)) - { + if((atright)&&(!attop)) { - double f,g,f1,g1; - f = 1.0 + x - ((double) intx); - g = 1.0 + y - ((double) inty); - f1 = 1.0 - f; - g1 = 1.0 - g; + double f,g,f1,g1; + f = 1.0 + x - ((double) intx); + g = 1.0 + y - ((double) inty); + f1 = 1.0 - f; + g1 = 1.0 - g; - return (int) ( - f1*g1*this->read(intx, inty,colour) - + f*g1*( 2*(this->read(intx,inty,colour)) - (this->read(intx-1,inty,colour)) ) - +f1*g*this->read(intx,inty+1,colour) - + f*g*(2*(this->read(intx,inty+1,colour)) - (this->read(intx-1,inty+1,colour))) - ); - } + return (int)( + f1*g1*this->read(intx, inty,colour) + + f*g1*(2*(this->read(intx,inty,colour)) - (this->read(intx-1,inty,colour))) + +f1*g*this->read(intx,inty+1,colour) + + f*g*(2*(this->read(intx,inty+1,colour)) - (this->read(intx-1,inty+1,colour))) + ); + } + + if((attop)&&(!atright)) { + double f,g,f1,g1; + f = 1.0 + x - ((double) intx); + g = 1.0 + y - ((double) inty); + f1 = 1.0 - f; + g1 = 1.0 - g; + + return (int)( + f1*g1*this->read(intx, inty,colour) + + f*g1*this->read(intx+1,inty,colour) + +f1*g*(2*(this->read(intx,inty,colour)) - this->read(intx,inty-1,colour)) + + f*g*(2*(this->read(intx+1,inty,colour)) - this->read(intx+1,inty-1,colour)) + ); + } - if((attop)&&(!atright)) - { double f,g,f1,g1; f = 1.0 + x - ((double) intx); g = 1.0 + y - ((double) inty); f1 = 1.0 - f; g1 = 1.0 - g; - return (int) ( - f1*g1*this->read(intx, inty,colour) - + f*g1*this->read(intx+1,inty,colour) - +f1*g*( 2*(this->read(intx,inty,colour)) - this->read(intx,inty-1,colour) ) - + f*g*( 2*(this->read(intx+1,inty,colour)) - this->read(intx+1,inty-1,colour)) - ); - } - - double f,g,f1,g1; - f = 1.0 + x - ((double) intx); - g = 1.0 + y - ((double) inty); - f1 = 1.0 - f; - g1 = 1.0 - g; - - return (int) ( - f1*g1*this->read(intx, inty,colour) - + f*g1*( 2*(this->read(intx,inty,colour)) - (this->read(intx-1,inty,colour)) ) - +f1*g*( 2*(this->read(intx,inty,colour)) - this->read(intx,inty-1,colour) ) - + f*g*( 2*( 2*(this->read(intx,inty,colour)) - (this->read(intx-1,inty,colour)) ) - ( 2*(this->read(intx,inty-1,colour)) - (this->read(intx-1,inty-1,colour)) )) - ); - - /* - return (int) ( - f1*g1*this->read(intx, inty,colour) - + f*g1*this->read(intx+1,inty,colour) - +f1*g*this->read(intx,inty+1,colour) - + f*g*this->read(intx+1, inty+1,colour) - ); - * */ - -}; - -double pngwriter::bilinear_interpolation_dread(double x, double y, int colour) -{ - return double(this->bilinear_interpolation_read(x,y,colour))/65535.0; -}; - -void pngwriter::plot_blend(int x, int y, double opacity, int red, int green, int blue) -{ - this->plot(x, y, - (int)( opacity*red + this->read(x,y,1)*(1.0-opacity)), - (int)( opacity*green + this->read(x,y,2)*(1.0-opacity)), - (int)( opacity*blue + this->read(x,y,3)*(1.0-opacity)) - ); -}; - -void pngwriter::plot_blend(int x, int y, double opacity, double red, double green, double blue) -{ - this->plot_blend(x, y, opacity, (int) (65535*red), (int) (65535*green), (int) (65535*blue)); -}; + return (int)( + f1*g1*this->read(intx, inty,colour) + + f*g1*(2*(this->read(intx,inty,colour)) - (this->read(intx-1,inty,colour))) + +f1*g*(2*(this->read(intx,inty,colour)) - this->read(intx,inty-1,colour)) + + f*g*(2*(2*(this->read(intx,inty,colour)) - (this->read(intx-1,inty,colour))) - (2*(this->read(intx,inty-1,colour)) - (this->read(intx-1,inty-1,colour)))) + ); -void pngwriter::invert(void) -{ - // int temp1, temp2, temp3; - double temp11, temp22, temp33; + /* + return (int) ( + f1*g1*this->read(intx, inty,colour) + + f*g1*this->read(intx+1,inty,colour) + +f1*g*this->read(intx,inty+1,colour) + + f*g*this->read(intx+1, inty+1,colour) + ); + * */ - for(int jjj = 1; jjj <= (this->height_); jjj++) - { - for(int iii = 1; iii <= (this->width_); iii++) - { - /* temp11 = (this->read(iii,jjj,1)); - temp22 = (this->read(iii,jjj,2)); - temp33 = (this->read(iii,jjj,3)); - * - this->plot(iii,jjj, - ((double)(65535 - temp11))/65535.0, - ((double)(65535 - temp22))/65535.0, - ((double)(65535 - temp33))/65535.0 - ); - * - */ - temp11 = (this->read(iii,jjj,1)); - temp22 = (this->read(iii,jjj,2)); - temp33 = (this->read(iii,jjj,3)); - - this->plot(iii,jjj, - (int)(65535 - temp11), - (int)(65535 - temp22), - (int)(65535 - temp33) - ); +}; - } - } -} +double pngwriter::bilinear_interpolation_dread(double x, double y, int colour) { + return double(this->bilinear_interpolation_read(x,y,colour))/65535.0; +}; -void pngwriter::resize(int width, int height) -{ +void pngwriter::plot_blend(int x, int y, double opacity, int red, int green, int blue) { + this->plot(x, y, + (int)(opacity*red + this->read(x,y,1)*(1.0-opacity)), + (int)(opacity*green + this->read(x,y,2)*(1.0-opacity)), + (int)(opacity*blue + this->read(x,y,3)*(1.0-opacity)) + ); +}; - for (int jjj = 0; jjj < height_; jjj++) free(graph_[jjj]); - free(graph_); +void pngwriter::plot_blend(int x, int y, double opacity, double red, double green, double blue) { + this->plot_blend(x, y, opacity, (int)(65535*red), (int)(65535*green), (int)(65535*blue)); +}; - width_ = width; - height_ = height; - backgroundcolour_ = 0; +void pngwriter::invert(void) { + // int temp1, temp2, temp3; + double temp11, temp22, temp33; + + for(int jjj = 1; jjj <= (this->height_); jjj++) { + for(int iii = 1; iii <= (this->width_); iii++) { + /* temp11 = (this->read(iii,jjj,1)); + temp22 = (this->read(iii,jjj,2)); + temp33 = (this->read(iii,jjj,3)); + * + this->plot(iii,jjj, + ((double)(65535 - temp11))/65535.0, + ((double)(65535 - temp22))/65535.0, + ((double)(65535 - temp33))/65535.0 + ); + * + */ + temp11 = (this->read(iii,jjj,1)); + temp22 = (this->read(iii,jjj,2)); + temp33 = (this->read(iii,jjj,3)); + + this->plot(iii,jjj, + (int)(65535 - temp11), + (int)(65535 - temp22), + (int)(65535 - temp33) + ); + + } + } +} - graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep)); - if(graph_ == NULL) - { - std::cerr << " PNGwriter::resize - ERROR **: Not able to allocate memory for image." << std::endl; - } +void pngwriter::resize(int width, int height) { - for (int kkkk = 0; kkkk < height_; kkkk++) - { - graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte)); - if(graph_[kkkk] == NULL) - { - std::cerr << " PNGwriter::resize - ERROR **: Not able to allocate memory for image." << std::endl; - } - } + for(int jjj = 0; jjj < height_; jjj++) free(graph_[jjj]); + free(graph_); - if(graph_ == NULL) - { - std::cerr << " PNGwriter::resize - ERROR **: Not able to allocate memory for image." << std::endl; - } + width_ = width; + height_ = height; + backgroundcolour_ = 0; - int tempindex; - for(int hhh = 0; hhhdread(xstart,ystart,1) != boundary_red) || - (this->dread(xstart,ystart,2) != boundary_green) || - (this->dread(xstart,ystart,3) != boundary_blue) - ) - && - ( - (this->dread(xstart,ystart,1) != fill_red) || - (this->dread(xstart,ystart,2) != fill_green) || - (this->dread(xstart,ystart,3) != fill_blue) - ) - && - (xstart >0)&&(xstart <= width_)&&(ystart >0)&&(ystart <= height_) - ) - { - this->plot(xstart, ystart, fill_red, fill_green, fill_blue); - boundary_fill(xstart+1, ystart, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; - boundary_fill(xstart, ystart+1, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; - boundary_fill(xstart, ystart-1, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; - boundary_fill(xstart-1, ystart, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; - } +void pngwriter::boundary_fill(int xstart, int ystart, double boundary_red,double boundary_green,double boundary_blue,double fill_red, double fill_green, double fill_blue) { + if(( + (this->dread(xstart,ystart,1) != boundary_red) || + (this->dread(xstart,ystart,2) != boundary_green) || + (this->dread(xstart,ystart,3) != boundary_blue) + ) + && + ( + (this->dread(xstart,ystart,1) != fill_red) || + (this->dread(xstart,ystart,2) != fill_green) || + (this->dread(xstart,ystart,3) != fill_blue) + ) + && + (xstart >0)&&(xstart <= width_)&&(ystart >0)&&(ystart <= height_) + ) { + this->plot(xstart, ystart, fill_red, fill_green, fill_blue); + boundary_fill(xstart+1, ystart, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; + boundary_fill(xstart, ystart+1, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; + boundary_fill(xstart, ystart-1, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; + boundary_fill(xstart-1, ystart, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; + } } //no int version needed -void pngwriter::flood_fill_internal(int xstart, int ystart, double start_red, double start_green, double start_blue, double fill_red, double fill_green, double fill_blue) -{ - if( ( - (this->dread(xstart,ystart,1) == start_red) && - (this->dread(xstart,ystart,2) == start_green) && - (this->dread(xstart,ystart,3) == start_blue) - ) - && - ( - (this->dread(xstart,ystart,1) != fill_red) || - (this->dread(xstart,ystart,2) != fill_green) || - (this->dread(xstart,ystart,3) != fill_blue) - ) - && - (xstart >0)&&(xstart <= width_)&&(ystart >0)&&(ystart <= height_) - ) - { - this->plot(xstart, ystart, fill_red, fill_green, fill_blue); - flood_fill_internal( xstart+1, ystart, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); - flood_fill_internal( xstart-1, ystart, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); - flood_fill_internal( xstart, ystart+1, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); - flood_fill_internal( xstart, ystart-1, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); - } +void pngwriter::flood_fill_internal(int xstart, int ystart, double start_red, double start_green, double start_blue, double fill_red, double fill_green, double fill_blue) { + if(( + (this->dread(xstart,ystart,1) == start_red) && + (this->dread(xstart,ystart,2) == start_green) && + (this->dread(xstart,ystart,3) == start_blue) + ) + && + ( + (this->dread(xstart,ystart,1) != fill_red) || + (this->dread(xstart,ystart,2) != fill_green) || + (this->dread(xstart,ystart,3) != fill_blue) + ) + && + (xstart >0)&&(xstart <= width_)&&(ystart >0)&&(ystart <= height_) + ) { + this->plot(xstart, ystart, fill_red, fill_green, fill_blue); + flood_fill_internal(xstart+1, ystart, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); + flood_fill_internal(xstart-1, ystart, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); + flood_fill_internal(xstart, ystart+1, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); + flood_fill_internal(xstart, ystart-1, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); + } } //int version -void pngwriter::boundary_fill(int xstart, int ystart, int boundary_red,int boundary_green,int boundary_blue,int fill_red, int fill_green, int fill_blue) -{ - - this->boundary_fill( xstart, ystart, - ((double) boundary_red)/65535.0, - ((double) boundary_green)/65535.0, - ((double) boundary_blue)/65535.0, - ((double) fill_red)/65535.0, - ((double) fill_green)/65535.0, - ((double) fill_blue)/65535.0 - ); +void pngwriter::boundary_fill(int xstart, int ystart, int boundary_red,int boundary_green,int boundary_blue,int fill_red, int fill_green, int fill_blue) { + + this->boundary_fill(xstart, ystart, + ((double) boundary_red)/65535.0, + ((double) boundary_green)/65535.0, + ((double) boundary_blue)/65535.0, + ((double) fill_red)/65535.0, + ((double) fill_green)/65535.0, + ((double) fill_blue)/65535.0 + ); } -void pngwriter::flood_fill(int xstart, int ystart, double fill_red, double fill_green, double fill_blue) -{ - flood_fill_internal( xstart, ystart, this->dread(xstart,ystart,1),this->dread(xstart,ystart,2),this->dread(xstart,ystart,3), fill_red, fill_green, fill_blue); +void pngwriter::flood_fill(int xstart, int ystart, double fill_red, double fill_green, double fill_blue) { + flood_fill_internal(xstart, ystart, this->dread(xstart,ystart,1),this->dread(xstart,ystart,2),this->dread(xstart,ystart,3), fill_red, fill_green, fill_blue); } //int version -void pngwriter::flood_fill(int xstart, int ystart, int fill_red, int fill_green, int fill_blue) -{ - this->flood_fill( xstart, ystart, - ((double) fill_red)/65535.0, - ((double) fill_green)/65535.0, - ((double) fill_blue)/65535.0 - ); +void pngwriter::flood_fill(int xstart, int ystart, int fill_red, int fill_green, int fill_blue) { + this->flood_fill(xstart, ystart, + ((double) fill_red)/65535.0, + ((double) fill_green)/65535.0, + ((double) fill_blue)/65535.0 + ); } -void pngwriter::polygon( int * points, int number_of_points, double red, double green, double blue) -{ - if( (number_of_points<1)||(points ==NULL)) - { - std::cerr << " PNGwriter::polygon - ERROR **: Number of points is zero or negative, or array is NULL." << std::endl; - return; - } +void pngwriter::polygon(int* points, int number_of_points, double red, double green, double blue) { + if((number_of_points<1)||(points ==NULL)) { + std::cerr << " PNGwriter::polygon - ERROR **: Number of points is zero or negative, or array is NULL." << std::endl; + return; + } - for(int k=0;k< number_of_points-1; k++) - { - this->line(points[2*k],points[2*k+1],points[2*k+2],points[2*k+3], red, green, blue); - } + for(int k=0; k< number_of_points-1; k++) { + this->line(points[2*k],points[2*k+1],points[2*k+2],points[2*k+3], red, green, blue); + } } //int version -void pngwriter::polygon( int * points, int number_of_points, int red, int green, int blue) -{ - this->polygon(points, number_of_points, - ((double) red)/65535.0, - ((double) green)/65535.0, - ((double) blue)/65535.0 - ); +void pngwriter::polygon(int* points, int number_of_points, int red, int green, int blue) { + this->polygon(points, number_of_points, + ((double) red)/65535.0, + ((double) green)/65535.0, + ((double) blue)/65535.0 + ); } -void pngwriter::plotCMYK(int x, int y, double cyan, double magenta, double yellow, double black) -{ -/*CMYK to RGB: - * ----------- - * red = 255 - minimum(255,((cyan/255) * (255 - black) + black)) - * green = 255 - minimum(255,((magenta/255) * (255 - black) + black)) - * blue = 255 - minimum(255,((yellow/255) * (255 - black) + black)) - * */ - - if(cyan<0.0) - { - cyan = 0.0; - } - if(magenta<0.0) - { - magenta = 0.0; - } - if(yellow<0.0) - { - yellow = 0.0; - } - if(black<0.0) - { - black = 0.0; - } - - if(cyan>1.0) - { - cyan = 1.0; - } - if(magenta>1.0) - { - magenta = 1.0; - } - if(yellow>1.0) - { - yellow = 1.0; - } - if(black>1.0) - { - black = 1.0; - } - - double red, green, blue, minr, ming, minb, iblack; - - iblack = 1.0 - black; - - minr = 1.0; - ming = 1.0; - minb = 1.0; - - if( (cyan*iblack + black)<1.0 ) - { - minr = cyan*iblack + black; - } - - if( (magenta*iblack + black)<1.0 ) - { - ming = magenta*iblack + black; - } - - if( (yellow*iblack + black)<1.0 ) - { - minb = yellow*iblack + black; - } - - red = 1.0 - minr; - green = 1.0 - ming; - blue = 1.0 - minb; - - this->plot(x,y,red, green, blue); +void pngwriter::plotCMYK(int x, int y, double cyan, double magenta, double yellow, double black) { + /*CMYK to RGB: + * ----------- + * red = 255 - minimum(255,((cyan/255) * (255 - black) + black)) + * green = 255 - minimum(255,((magenta/255) * (255 - black) + black)) + * blue = 255 - minimum(255,((yellow/255) * (255 - black) + black)) + * */ + + if(cyan<0.0) { + cyan = 0.0; + } + if(magenta<0.0) { + magenta = 0.0; + } + if(yellow<0.0) { + yellow = 0.0; + } + if(black<0.0) { + black = 0.0; + } + + if(cyan>1.0) { + cyan = 1.0; + } + if(magenta>1.0) { + magenta = 1.0; + } + if(yellow>1.0) { + yellow = 1.0; + } + if(black>1.0) { + black = 1.0; + } + + double red, green, blue, minr, ming, minb, iblack; + + iblack = 1.0 - black; + + minr = 1.0; + ming = 1.0; + minb = 1.0; + + if((cyan*iblack + black)<1.0) { + minr = cyan*iblack + black; + } + + if((magenta*iblack + black)<1.0) { + ming = magenta*iblack + black; + } + + if((yellow*iblack + black)<1.0) { + minb = yellow*iblack + black; + } + + red = 1.0 - minr; + green = 1.0 - ming; + blue = 1.0 - minb; + + this->plot(x,y,red, green, blue); } //int version -void pngwriter::plotCMYK(int x, int y, int cyan, int magenta, int yellow, int black) -{ - this->plotCMYK( x, y, - ((double) cyan)/65535.0, - ((double) magenta)/65535.0, - ((double) yellow)/65535.0, - ((double) black)/65535.0 - ); +void pngwriter::plotCMYK(int x, int y, int cyan, int magenta, int yellow, int black) { + this->plotCMYK(x, y, + ((double) cyan)/65535.0, + ((double) magenta)/65535.0, + ((double) yellow)/65535.0, + ((double) black)/65535.0 + ); } -double pngwriter::dreadCMYK(int x, int y, int colour) -{ -/* - * Black = minimum(1-Red,1-Green,1-Blue) - * Cyan = (1-Red-Black)/(1-Black) - * Magenta = (1-Green-Black)/(1-Black) - * Yellow = (1-Blue-Black)/(1-Black) - * - * */ - if((colour !=1)&&(colour !=2)&&(colour !=3)&&(colour !=4)) - { - std::cerr << " PNGwriter::dreadCMYK - WARNING **: Invalid argument: should be 1, 2, 3 or 4, is " << colour << std::endl; - return 0; - } - - double black, red, green, blue, ired, igreen, iblue, iblack; - //add error detection here - // not much to detect, really - red = this->dread(x, y, 1); - green = this->dread(x, y, 2); - blue = this->dread(x, y, 3); - - ired = 1.0 - red; - igreen = 1.0 - green; - iblue = 1.0 - blue; - - black = ired; - - //black is the mimimum of inverse RGB colours, and if they are all equal, it is the inverse of red. - if( (igreendread(x, y, 1); + green = this->dread(x, y, 2); + blue = this->dread(x, y, 3); + + ired = 1.0 - red; + igreen = 1.0 - green; + iblue = 1.0 - blue; + + black = ired; + + //black is the mimimum of inverse RGB colours, and if they are all equal, it is the inverse of red. + if((igreendread(x, y, 1); - green = this->dread(x, y, 2); - blue = this->dread(x, y, 3); - - ired = 1.0 - red; - igreen = 1.0 - green; - iblue = 1.0 - blue; - - black = ired; - - //black is the mimimum of inverse RGB colours, and if they are all equal, it is the inverse of red. - if( (igreendread(x, y, 1); + green = this->dread(x, y, 2); + blue = this->dread(x, y, 3); + + ired = 1.0 - red; + igreen = 1.0 - green; + iblue = 1.0 - blue; + + black = ired; + + //black is the mimimum of inverse RGB colours, and if they are all equal, it is the inverse of red. + if((igreenbilinear_interpolation_read(readx, ready, 1); - green = this->bilinear_interpolation_read(readx, ready, 2); - blue = this->bilinear_interpolation_read(readx, ready, 3); - temp.plot(x, y, red, green, blue); + for(int x = 1; x<= scaledw; x++) { + for(int y = 1; y <= scaledh; y++) { + readx = (2*x-1)*spacingx; + ready = (2*y-1)*spacingy; + red = this->bilinear_interpolation_read(readx, ready, 1); + green = this->bilinear_interpolation_read(readx, ready, 2); + blue = this->bilinear_interpolation_read(readx, ready, 3); + temp.plot(x, y, red, green, blue); - } - } - - // From here on, the process is the same for all scale functions. - //Get data out of temp and into this's storage. - - //Resize this instance - // Delete current storage. - for (int jjj = 0; jjj < height_; jjj++) free(graph_[jjj]); - free(graph_); - - //New image will have bit depth 16, regardless of original bit depth. - bit_depth_ = 16; - - // New width and height will be the scaled width and height - width_ = scaledw; - height_ = scaledh; - backgroundcolour_ = 0; - - graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep)); - if(graph_ == NULL) - { - std::cerr << " PNGwriter::scale_k - ERROR **: Not able to allocate memory for image." << std::endl; - } - - for (int kkkk = 0; kkkk < height_; kkkk++) - { - graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte)); - if(graph_[kkkk] == NULL) - { - std::cerr << " PNGwriter::scale_k - ERROR **: Not able to allocate memory for image." << std::endl; - } - } + } + } - if(graph_ == NULL) - { - std::cerr << " PNGwriter::scale_k - ERROR **: Not able to allocate memory for image." << std::endl; - } + // From here on, the process is the same for all scale functions. + //Get data out of temp and into this's storage. - //This instance now has a new, resized storage space. + //Resize this instance + // Delete current storage. + for(int jjj = 0; jjj < height_; jjj++) free(graph_[jjj]); + free(graph_); - //Copy the temp date into this's storage. - int tempindex; - for(int hhh = 0; hhhbilinear_interpolation_read(readx, ready, 1); - green = this->bilinear_interpolation_read(readx, ready, 2); - blue = this->bilinear_interpolation_read(readx, ready, 3); - temp.plot(x, y, red, green, blue); + for(int x = 1; x<= scaledw; x++) { + for(int y = 1; y <= scaledh; y++) { + readx = (2*x-1)*spacingx; + ready = (2*y-1)*spacingy; + red = this->bilinear_interpolation_read(readx, ready, 1); + green = this->bilinear_interpolation_read(readx, ready, 2); + blue = this->bilinear_interpolation_read(readx, ready, 3); + temp.plot(x, y, red, green, blue); - } - } - // From here on, the process is the same for all scale functions. - //Get data out of temp and into this's storage. - - //Resize this instance - // Delete current storage. - for (int jjj = 0; jjj < height_; jjj++) free(graph_[jjj]); - free(graph_); - - //New image will have bit depth 16, regardless of original bit depth. - bit_depth_ = 16; - - // New width and height will be the scaled width and height - width_ = scaledw; - height_ = scaledh; - backgroundcolour_ = 0; - - graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep)); - if(graph_ == NULL) - { - std::cerr << " PNGwriter::scale_kxky - ERROR **: Not able to allocate memory for image." << std::endl; - } - - for (int kkkk = 0; kkkk < height_; kkkk++) - { - graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte)); - if(graph_[kkkk] == NULL) - { - std::cerr << " PNGwriter::scale_kxky - ERROR **: Not able to allocate memory for image." << std::endl; - } - } + } + } + // From here on, the process is the same for all scale functions. + //Get data out of temp and into this's storage. - if(graph_ == NULL) - { - std::cerr << " PNGwriter::scale_kxky - ERROR **: Not able to allocate memory for image." << std::endl; - } + //Resize this instance + // Delete current storage. + for(int jjj = 0; jjj < height_; jjj++) free(graph_[jjj]); + free(graph_); - //This instance now has a new, resized storage space. + //New image will have bit depth 16, regardless of original bit depth. + bit_depth_ = 16; - //Copy the temp date into this's storage. - int tempindex; - for(int hhh = 0; hhhbilinear_interpolation_read(readx, ready, 1); - green = this->bilinear_interpolation_read(readx, ready, 2); - blue = this->bilinear_interpolation_read(readx, ready, 3); - temp.plot(x, y, red, green, blue); + for(int x = 1; x<= finalwidth; x++) { + for(int y = 1; y <= finalheight; y++) { + readx = (2*x-1)*spacingx; + ready = (2*y-1)*spacingy; + red = this->bilinear_interpolation_read(readx, ready, 1); + green = this->bilinear_interpolation_read(readx, ready, 2); + blue = this->bilinear_interpolation_read(readx, ready, 3); + temp.plot(x, y, red, green, blue); - } - } - - // From here on, the process is the same for all scale functions. - //Get data out of temp and into this's storage. - - //Resize this instance - // Delete current storage. - for (int jjj = 0; jjj < height_; jjj++) free(graph_[jjj]); - free(graph_); - - //New image will have bit depth 16, regardless of original bit depth. - bit_depth_ = 16; - - // New width and height will be the scaled width and height - width_ = finalwidth; - height_ = finalheight; - backgroundcolour_ = 0; - - graph_ = (png_bytepp)malloc(height_ * sizeof(png_bytep)); - if(graph_ == NULL) - { - std::cerr << " PNGwriter::scale_wh - ERROR **: Not able to allocate memory for image." << std::endl; - } - - for (int kkkk = 0; kkkk < height_; kkkk++) - { - graph_[kkkk] = (png_bytep)malloc(6*width_ * sizeof(png_byte)); - if(graph_[kkkk] == NULL) - { - std::cerr << " PNGwriter::scale_wh - ERROR **: Not able to allocate memory for image." << std::endl; - } - } + } + } - if(graph_ == NULL) - { - std::cerr << " PNGwriter::scale_wh - ERROR **: Not able to allocate memory for image." << std::endl; - } + // From here on, the process is the same for all scale functions. + //Get data out of temp and into this's storage. - //This instance now has a new, resized storage space. + //Resize this instance + // Delete current storage. + for(int jjj = 0; jjj < height_; jjj++) free(graph_[jjj]); + free(graph_); - //Copy the temp date into this's storage. - int tempindex; - for(int hhh = 0; hhhplot_blend(xfrom,yfrom,opacity, red,green,blue); - - if (dx > dy) - { - int fraction = dy - (dx >> 1); - - while (xfrom != xto) - { - if (fraction >= 0) - { - yfrom += stepy; - fraction -= dx; - } - xfrom += stepx; - fraction += dy; - this->plot_blend(xfrom,yfrom,opacity, red,green,blue); - } - } - else - { - int fraction = dx - (dy >> 1); - while (yfrom != yto) - { - if (fraction >= 0) - { - xfrom += stepx; - fraction -= dy; - } - yfrom += stepy; - fraction += dx; - this->plot_blend(xfrom,yfrom, opacity, red,green,blue); - } - } +void pngwriter::line_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue) { + // Bresenham Algorithm. + // + int dy = yto - yfrom; + int dx = xto - xfrom; + int stepx, stepy; + + if(dy < 0) { + dy = -dy; + stepy = -1; + } else { + stepy = 1; + } + + if(dx < 0) { + dx = -dx; + stepx = -1; + } else { + stepx = 1; + } + dy <<= 1; // dy is now 2*dy + dx <<= 1; // dx is now 2*dx + + this->plot_blend(xfrom,yfrom,opacity, red,green,blue); + + if(dx > dy) { + int fraction = dy - (dx >> 1); + + while(xfrom != xto) { + if(fraction >= 0) { + yfrom += stepy; + fraction -= dx; + } + xfrom += stepx; + fraction += dy; + this->plot_blend(xfrom,yfrom,opacity, red,green,blue); + } + } else { + int fraction = dx - (dy >> 1); + while(yfrom != yto) { + if(fraction >= 0) { + xfrom += stepx; + fraction -= dy; + } + yfrom += stepy; + fraction += dx; + this->plot_blend(xfrom,yfrom, opacity, red,green,blue); + } + } } -void pngwriter::line_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue) -{ - this->line_blend( xfrom, - yfrom, - xto, - yto, - opacity, - int (red*65535), - int (green*65535), - int (blue*65535) - ); +void pngwriter::line_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue) { + this->line_blend(xfrom, + yfrom, + xto, + yto, + opacity, + int (red*65535), + int (green*65535), + int (blue*65535) + ); } -void pngwriter::square_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue) -{ - this->line_blend(xfrom, yfrom, xfrom, yto, opacity, red, green, blue); - this->line_blend(xto, yfrom, xto, yto, opacity, red, green, blue); - this->line_blend(xfrom, yfrom, xto, yfrom, opacity, red, green, blue); - this->line_blend(xfrom, yto, xto, yto, opacity, red, green, blue); +void pngwriter::square_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue) { + this->line_blend(xfrom, yfrom, xfrom, yto, opacity, red, green, blue); + this->line_blend(xto, yfrom, xto, yto, opacity, red, green, blue); + this->line_blend(xfrom, yfrom, xto, yfrom, opacity, red, green, blue); + this->line_blend(xfrom, yto, xto, yto, opacity, red, green, blue); } -void pngwriter::square_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue) -{ - this->square_blend( xfrom, yfrom, xto, yto, opacity, int(red*65535), int(green*65535), int(blue*65535)); +void pngwriter::square_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue) { + this->square_blend(xfrom, yfrom, xto, yto, opacity, int(red*65535), int(green*65535), int(blue*65535)); } -void pngwriter::filledsquare_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue) -{ - for(int caca = xfrom; caca line_blend(caca, yfrom, caca, yto, opacity, red, green, blue); - } +void pngwriter::filledsquare_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue) { + for(int caca = xfrom; caca line_blend(caca, yfrom, caca, yto, opacity, red, green, blue); + } } -void pngwriter::filledsquare_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue) -{ - this->filledsquare_blend( xfrom, yfrom, xto, yto, opacity, int(red*65535), int(green*65535), int(blue*65535)); +void pngwriter::filledsquare_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue) { + this->filledsquare_blend(xfrom, yfrom, xto, yto, opacity, int(red*65535), int(green*65535), int(blue*65535)); } -void pngwriter::circle_aux_blend(int xcentre, int ycentre, int x, int y, double opacity, int red, int green, int blue) -{ - if (x == 0) - { - this->plot_blend( xcentre, ycentre + y, opacity, red, green, blue); - this->plot_blend( xcentre, ycentre - y, opacity, red, green, blue); - this->plot_blend( xcentre + y, ycentre, opacity, red, green, blue); - this->plot_blend( xcentre - y, ycentre, opacity, red, green, blue); - } - else - if (x == y) - { - this->plot_blend( xcentre + x, ycentre + y, opacity, red, green, blue); - this->plot_blend( xcentre - x, ycentre + y, opacity, red, green, blue); - this->plot_blend( xcentre + x, ycentre - y, opacity, red, green, blue); - this->plot_blend( xcentre - x, ycentre - y, opacity, red, green, blue); - } - else - if (x < y) - { - this->plot_blend( xcentre + x, ycentre + y, opacity, red, green, blue); - this->plot_blend( xcentre - x, ycentre + y, opacity, red, green, blue); - this->plot_blend( xcentre + x, ycentre - y, opacity, red, green, blue); - this->plot_blend( xcentre - x, ycentre - y, opacity, red, green, blue); - this->plot_blend( xcentre + y, ycentre + x, opacity, red, green, blue); - this->plot_blend( xcentre - y, ycentre + x, opacity, red, green, blue); - this->plot_blend( xcentre + y, ycentre - x, opacity, red, green, blue); - this->plot_blend( xcentre - y, ycentre - x, opacity, red, green, blue); - } +void pngwriter::circle_aux_blend(int xcentre, int ycentre, int x, int y, double opacity, int red, int green, int blue) { + if(x == 0) { + this->plot_blend(xcentre, ycentre + y, opacity, red, green, blue); + this->plot_blend(xcentre, ycentre - y, opacity, red, green, blue); + this->plot_blend(xcentre + y, ycentre, opacity, red, green, blue); + this->plot_blend(xcentre - y, ycentre, opacity, red, green, blue); + } else if(x == y) { + this->plot_blend(xcentre + x, ycentre + y, opacity, red, green, blue); + this->plot_blend(xcentre - x, ycentre + y, opacity, red, green, blue); + this->plot_blend(xcentre + x, ycentre - y, opacity, red, green, blue); + this->plot_blend(xcentre - x, ycentre - y, opacity, red, green, blue); + } else if(x < y) { + this->plot_blend(xcentre + x, ycentre + y, opacity, red, green, blue); + this->plot_blend(xcentre - x, ycentre + y, opacity, red, green, blue); + this->plot_blend(xcentre + x, ycentre - y, opacity, red, green, blue); + this->plot_blend(xcentre - x, ycentre - y, opacity, red, green, blue); + this->plot_blend(xcentre + y, ycentre + x, opacity, red, green, blue); + this->plot_blend(xcentre - y, ycentre + x, opacity, red, green, blue); + this->plot_blend(xcentre + y, ycentre - x, opacity, red, green, blue); + this->plot_blend(xcentre - y, ycentre - x, opacity, red, green, blue); + } } // -void pngwriter::circle_blend(int xcentre, int ycentre, int radius, double opacity, int red, int green, int blue) -{ - int x = 0; - int y = radius; - int p = (5 - radius*4)/4; - - circle_aux_blend(xcentre, ycentre, x, y, opacity, red, green, blue); - while (x < y) - { - x++; - if (p < 0) - { - p += 2*x+1; - } - else - { - y--; - p += 2*(x-y)+1; - } +void pngwriter::circle_blend(int xcentre, int ycentre, int radius, double opacity, int red, int green, int blue) { + int x = 0; + int y = radius; + int p = (5 - radius*4)/4; + circle_aux_blend(xcentre, ycentre, x, y, opacity, red, green, blue); - } + while(x < y) { + x++; + if(p < 0) { + p += 2*x+1; + } else { + y--; + p += 2*(x-y)+1; + } + circle_aux_blend(xcentre, ycentre, x, y, opacity, red, green, blue); + } } -void pngwriter::circle_blend(int xcentre, int ycentre, int radius, double opacity, double red, double green, double blue) -{ - this->circle_blend(xcentre,ycentre,radius, opacity, int(red*65535), int(green*65535), int(blue*65535)); +void pngwriter::circle_blend(int xcentre, int ycentre, int radius, double opacity, double red, double green, double blue) { + this->circle_blend(xcentre,ycentre,radius, opacity, int(red*65535), int(green*65535), int(blue*65535)); } -void pngwriter::filledcircle_blend(int xcentre, int ycentre, int radius, double opacity, int red, int green, int blue) -{ - for(int jjj = ycentre-radius; jjj< ycentre+radius+1; jjj++) - { - this->line_blend(xcentre - int(sqrt((double)(radius*radius) - (-ycentre + jjj)*(-ycentre + jjj ))), jjj, - xcentre + int(sqrt((double)(radius*radius) - (-ycentre + jjj)*(-ycentre + jjj ))),jjj, opacity, red,green,blue); - } +void pngwriter::filledcircle_blend(int xcentre, int ycentre, int radius, double opacity, int red, int green, int blue) { + for(int jjj = ycentre-radius; jjj< ycentre+radius+1; jjj++) { + this->line_blend(xcentre - int(sqrt((double)(radius*radius) - (-ycentre + jjj)*(-ycentre + jjj))), jjj, + xcentre + int(sqrt((double)(radius*radius) - (-ycentre + jjj)*(-ycentre + jjj))),jjj, opacity, red,green,blue); + } } -void pngwriter::filledcircle_blend(int xcentre, int ycentre, int radius, double opacity, double red, double green, double blue) -{ - this->filledcircle_blend( xcentre, ycentre, radius, opacity, int(red*65535), int(green*65535), int(blue*65535)); +void pngwriter::filledcircle_blend(int xcentre, int ycentre, int radius, double opacity, double red, double green, double blue) { + this->filledcircle_blend(xcentre, ycentre, radius, opacity, int(red*65535), int(green*65535), int(blue*65535)); } -void pngwriter::bezier_blend( int startPtX, int startPtY, - int startControlX, int startControlY, - int endPtX, int endPtY, - int endControlX, int endControlY, - double opacity, - double red, double green, double blue) -{ - - double cx = 3.0*(startControlX - startPtX); - double bx = 3.0*(endControlX - startControlX) - cx; - double ax = double(endPtX - startPtX - cx - bx); - - double cy = 3.0*(startControlY - startPtY); - double by = 3.0*(endControlY - startControlY) - cy; - double ay = double(endPtY - startPtY - cy - by); - - double x,y,newx,newy; - x = startPtX; - y = startPtY; - - for(double t = 0.0; t<=1.005; t += 0.005) - { - newx = startPtX + t*(double(cx) + t*(double(bx) + t*(double(ax)))); - newy = startPtY + t*(double(cy) + t*(double(by) + t*(double(ay)))); - this->line_blend(int(x),int(y),int(newx),int(newy),opacity, red,green,blue); - x = newx; - y = newy; - } +void pngwriter::bezier_blend(int startPtX, int startPtY, + int startControlX, int startControlY, + int endPtX, int endPtY, + int endControlX, int endControlY, + double opacity, + double red, double green, double blue) { + + double cx = 3.0*(startControlX - startPtX); + double bx = 3.0*(endControlX - startControlX) - cx; + double ax = double(endPtX - startPtX - cx - bx); + + double cy = 3.0*(startControlY - startPtY); + double by = 3.0*(endControlY - startControlY) - cy; + double ay = double(endPtY - startPtY - cy - by); + + double x,y,newx,newy; + x = startPtX; + y = startPtY; + + for(double t = 0.0; t<=1.005; t += 0.005) { + newx = startPtX + t*(double(cx) + t*(double(bx) + t*(double(ax)))); + newy = startPtY + t*(double(cy) + t*(double(by) + t*(double(ay)))); + this->line_blend(int(x),int(y),int(newx),int(newy),opacity, red,green,blue); + x = newx; + y = newy; + } } -void pngwriter::bezier_blend( int startPtX, int startPtY, - int startControlX, int startControlY, - int endPtX, int endPtY, - int endControlX, int endControlY, - double opacity, - int red, int green, int blue) -{ - this->bezier_blend( startPtX, startPtY, - startControlX, startControlY, - endPtX, endPtY, - endControlX, endControlY, - opacity, - double(red)/65535.0, double(green)/65535.0, double(blue)/65535.0); +void pngwriter::bezier_blend(int startPtX, int startPtY, + int startControlX, int startControlY, + int endPtX, int endPtY, + int endControlX, int endControlY, + double opacity, + int red, int green, int blue) { + this->bezier_blend(startPtX, startPtY, + startControlX, startControlY, + endPtX, endPtY, + endControlX, endControlY, + opacity, + double(red)/65535.0, double(green)/65535.0, double(blue)/65535.0); } @@ -3688,1034 +3325,946 @@ void pngwriter::bezier_blend( int startPtX, int startPtY, // Freetype-based text rendering functions. /////////////////////////////////////////// -void pngwriter::plot_text_blend( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, double red, double green, double blue) -{ - FT_Library library; - FT_Face face; - FT_Matrix matrix; // transformation matrix - FT_Vector pen; - - FT_UInt glyph_index; - FT_Error error; - - FT_Bool use_kerning; - FT_UInt previous = 0; - - /* Set up transformation Matrix */ - matrix.xx = (FT_Fixed)( cos(angle)*0x10000); /* It would make more sense to do this (below), but, bizzarely, */ - matrix.xy = (FT_Fixed)(-sin(angle)*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ - matrix.yx = (FT_Fixed)( sin(angle)*0x10000); // matrix.yx = - matrix.xy; - matrix.yy = (FT_Fixed)( cos(angle)*0x10000); // matrix.yy = matrix.xx; - - /* Place starting coordinates in adequate form. */ - pen.x = x_start*64 ; - pen.y = (int)(y_start/64.0); - - /*Count the length of the string */ - int num_chars = strlen(text); - - /* Initialize FT Library object */ - error = FT_Init_FreeType( &library ); - if (error) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Could not init Library."<< std::endl; return;} - - /* Initialize FT face object */ - error = FT_New_Face( library,face_path,0,&face ); - if ( error == FT_Err_Unknown_File_Format ) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Font was opened, but type not supported."<< std::endl; return; } else if (error){ std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not find or load font file."<< std::endl; return; } - - /* Set the Char size */ - error = FT_Set_Char_Size( face, /* handle to face object */ - 0, /* char_width in 1/64th of points */ - fontsize*64, /* char_height in 1/64th of points */ - 100, /* horizontal device resolution */ - 100 ); /* vertical device resolution */ - - /* A way of accesing the glyph directly */ - FT_GlyphSlot slot = face->glyph; // a small shortcut - - /* Does the font file support kerning? */ - use_kerning = FT_HAS_KERNING( face ); - - int n; - for ( n = 0; n < num_chars; n++ ) - { - /* Convert character code to glyph index */ - glyph_index = FT_Get_Char_Index( face, text[n] ); - - /* Retrieve kerning distance and move pen position */ - if ( use_kerning && previous&& glyph_index ) - { - FT_Vector delta; - FT_Get_Kerning( face, - previous, - glyph_index, - ft_kerning_default, //FT_KERNING_DEFAULT, - &delta ); - - /* Transform this kerning distance into rotated space */ - pen.x += (int) (((double) delta.x)*cos(angle)); - pen.y += (int) (((double) delta.x)*( sin(angle))); - } - - /* Set transform */ - FT_Set_Transform( face, &matrix, &pen ); - -/*set char size*/ - - if (error) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Set char size error." << std::endl; return;}; - - /* Retrieve glyph index from character code */ - glyph_index = FT_Get_Char_Index( face, text[n] ); - - /* Load glyph image into the slot (erase previous one) */ - error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); - if (error) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return;} - - /* Convert to an anti-aliased bitmap */ - // error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL ); - error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); - if (error) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Render glyph error." << std::endl; return;} - - /* Now, draw to our target surface */ - my_draw_bitmap_blend( &slot->bitmap, - slot->bitmap_left, - y_start + slot->bitmap_top, - opacity, - red, - green, - blue ); - - /* Advance to the next position */ - pen.x += slot->advance.x; - pen.y += slot->advance.y; - - /* record current glyph index */ - previous = glyph_index; - } - - /* Free the face and the library objects */ - FT_Done_Face ( face ); - FT_Done_FreeType( library ); +void pngwriter::plot_text_blend(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, double opacity, double red, double green, double blue) { + FT_Library library; + FT_Face face; + FT_Matrix matrix; // transformation matrix + FT_Vector pen; + + FT_UInt glyph_index; + FT_Error error; + + FT_Bool use_kerning; + FT_UInt previous = 0; + + /* Set up transformation Matrix */ + matrix.xx = (FT_Fixed)(cos(angle)*0x10000); /* It would make more sense to do this (below), but, bizzarely, */ + matrix.xy = (FT_Fixed)(-sin(angle)*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ + matrix.yx = (FT_Fixed)(sin(angle)*0x10000); // matrix.yx = - matrix.xy; + matrix.yy = (FT_Fixed)(cos(angle)*0x10000); // matrix.yy = matrix.xx; + + /* Place starting coordinates in adequate form. */ + pen.x = x_start*64 ; + pen.y = (int)(y_start/64.0); + + /*Count the length of the string */ + int num_chars = strlen(text); + + /* Initialize FT Library object */ + error = FT_Init_FreeType(&library); + if(error) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Could not init Library."<< std::endl; return;} + + /* Initialize FT face object */ + error = FT_New_Face(library,face_path,0,&face); + if(error == FT_Err_Unknown_File_Format) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Font was opened, but type not supported."<< std::endl; return; } else if(error) { std::cerr << " PNGwriter::plot_text - ERROR **: FreeType: Could not find or load font file."<< std::endl; return; } + + /* Set the Char size */ + error = FT_Set_Char_Size(face, /* handle to face object */ + 0, /* char_width in 1/64th of points */ + fontsize*64, /* char_height in 1/64th of points */ + 100, /* horizontal device resolution */ + 100); /* vertical device resolution */ + + /* A way of accesing the glyph directly */ + FT_GlyphSlot slot = face->glyph; // a small shortcut + + /* Does the font file support kerning? */ + use_kerning = FT_HAS_KERNING(face); + + int n; + for(n = 0; n < num_chars; n++) { + /* Convert character code to glyph index */ + glyph_index = FT_Get_Char_Index(face, text[n]); + + /* Retrieve kerning distance and move pen position */ + if(use_kerning && previous&& glyph_index) { + FT_Vector delta; + FT_Get_Kerning(face, + previous, + glyph_index, + ft_kerning_default, //FT_KERNING_DEFAULT, + &delta); + + /* Transform this kerning distance into rotated space */ + pen.x += (int)(((double) delta.x)*cos(angle)); + pen.y += (int)(((double) delta.x)*(sin(angle))); + } + + /* Set transform */ + FT_Set_Transform(face, &matrix, &pen); + + /*set char size*/ + + if(error) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Set char size error." << std::endl; return;}; + + /* Retrieve glyph index from character code */ + glyph_index = FT_Get_Char_Index(face, text[n]); + + /* Load glyph image into the slot (erase previous one) */ + error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + if(error) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return;} + + /* Convert to an anti-aliased bitmap */ + // error = FT_Render_Glyph( face->glyph, FT_RENDER_MODE_NORMAL ); + error = FT_Render_Glyph(face->glyph, ft_render_mode_normal); + if(error) { std::cerr << " PNGwriter::plot_text_blend - ERROR **: FreeType: Render glyph error." << std::endl; return;} + + /* Now, draw to our target surface */ + my_draw_bitmap_blend(&slot->bitmap, + slot->bitmap_left, + y_start + slot->bitmap_top, + opacity, + red, + green, + blue); + + /* Advance to the next position */ + pen.x += slot->advance.x; + pen.y += slot->advance.y; + + /* record current glyph index */ + previous = glyph_index; + } + + /* Free the face and the library objects */ + FT_Done_Face(face); + FT_Done_FreeType(library); } -void pngwriter::plot_text_utf8_blend( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, double red, double green, double blue) -{ - FT_Library library; - FT_Face face; - FT_Matrix matrix; // transformation matrix - FT_Vector pen; - - FT_UInt glyph_index; - FT_Error error; - - FT_Bool use_kerning; - FT_UInt previous = 0; - - /* Set up transformation Matrix */ - matrix.xx = (FT_Fixed)( cos(angle)*0x10000); /* It would make more sense to do this (below), but, bizzarely, */ - matrix.xy = (FT_Fixed)(-sin(angle)*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ - matrix.yx = (FT_Fixed)( sin(angle)*0x10000); // matrix.yx = - matrix.xy; - matrix.yy = (FT_Fixed)( cos(angle)*0x10000); // matrix.yy = matrix.xx; - - /* Place starting coordinates in adequate form. */ - pen.x = x_start*64 ; - pen.y = (int)(y_start/64.0); - - /*Count the length of the string */ - int num_bytes=0; - while(text[num_bytes]!=0) - { - num_bytes++; - } +void pngwriter::plot_text_utf8_blend(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, double opacity, double red, double green, double blue) { + FT_Library library; + FT_Face face; + FT_Matrix matrix; // transformation matrix + FT_Vector pen; - /* - std::cout << "Num bytes is: "<< num_bytes << std::endl; - */ + FT_UInt glyph_index; + FT_Error error; - //The array of ucs4 glyph indexes, which will by at most the number of bytes in the utf-8 file. - long * ucs4text; - ucs4text = new long[num_bytes+1]; + FT_Bool use_kerning; + FT_UInt previous = 0; - unsigned char u,v,w,x,y,z; + /* Set up transformation Matrix */ + matrix.xx = (FT_Fixed)(cos(angle)*0x10000); /* It would make more sense to do this (below), but, bizzarely, */ + matrix.xy = (FT_Fixed)(-sin(angle)*0x10000); /* if one does, FT_Load_Glyph fails consistently. */ + matrix.yx = (FT_Fixed)(sin(angle)*0x10000); // matrix.yx = - matrix.xy; + matrix.yy = (FT_Fixed)(cos(angle)*0x10000); // matrix.yy = matrix.xx; - int num_chars=0; + /* Place starting coordinates in adequate form. */ + pen.x = x_start*64 ; + pen.y = (int)(y_start/64.0); - long iii=0; + /*Count the length of the string */ + int num_bytes=0; + while(text[num_bytes]!=0) { + num_bytes++; + } - while(iiiglyph; // a small shortcut - - /* Does the font file support kerning? */ - use_kerning = FT_HAS_KERNING( face ); - - int n; - for ( n = 0; n < num_chars; n++ ) - { - /* Convert character code to glyph index */ - glyph_index = FT_Get_Char_Index( face, ucs4text[n] ); - - /* Retrieve kerning distance and move pen position */ - if ( use_kerning && previous&& glyph_index ) - { - FT_Vector delta; - FT_Get_Kerning( face, - previous, - glyph_index, - ft_kerning_default, //FT_KERNING_DEFAULT, - &delta ); - - /* Transform this kerning distance into rotated space */ - pen.x += (int) (((double) delta.x)*cos(angle)); - pen.y += (int) (((double) delta.x)*( sin(angle))); - } - - /* Set transform */ - FT_Set_Transform( face, &matrix, &pen ); - -/*set char size*/ - - if (error) { std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: FreeType: Set char size error." << std::endl; return;}; - - /* Retrieve glyph index from character code */ - glyph_index = FT_Get_Char_Index( face, ucs4text[n] ); - - /* Load glyph image into the slot (erase previous one) */ - error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT ); - if (error) { std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return;} - - /* Convert to an anti-aliased bitmap */ - error = FT_Render_Glyph( face->glyph, ft_render_mode_normal ); - if (error) { std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: FreeType: Render glyph error." << std::endl; return;} - - /* Now, draw to our target surface */ - my_draw_bitmap_blend( &slot->bitmap, - slot->bitmap_left, - y_start + slot->bitmap_top, - opacity, - red, - green, - blue ); - - /* Advance to the next position */ - pen.x += slot->advance.x; - pen.y += slot->advance.y; - - /* record current glyph index */ - previous = glyph_index; - } - - /* Free the face and the library objects */ - FT_Done_Face ( face ); - FT_Done_FreeType( library ); - - delete[] ucs4text; + /* + std::cout << "Num bytes is: "<< num_bytes << std::endl; + */ + + //The array of ucs4 glyph indexes, which will by at most the number of bytes in the utf-8 file. + long* ucs4text; + ucs4text = new long[num_bytes+1]; + + unsigned char u,v,w,x,y,z; + + int num_chars=0; + + long iii=0; + + while(iiiglyph; // a small shortcut + + /* Does the font file support kerning? */ + use_kerning = FT_HAS_KERNING(face); + + int n; + for(n = 0; n < num_chars; n++) { + /* Convert character code to glyph index */ + glyph_index = FT_Get_Char_Index(face, ucs4text[n]); + + /* Retrieve kerning distance and move pen position */ + if(use_kerning && previous&& glyph_index) { + FT_Vector delta; + FT_Get_Kerning(face, + previous, + glyph_index, + ft_kerning_default, //FT_KERNING_DEFAULT, + &delta); + + /* Transform this kerning distance into rotated space */ + pen.x += (int)(((double) delta.x)*cos(angle)); + pen.y += (int)(((double) delta.x)*(sin(angle))); + } + + /* Set transform */ + FT_Set_Transform(face, &matrix, &pen); + + /*set char size*/ + + if(error) { std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: FreeType: Set char size error." << std::endl; return;}; + + /* Retrieve glyph index from character code */ + glyph_index = FT_Get_Char_Index(face, ucs4text[n]); + + /* Load glyph image into the slot (erase previous one) */ + error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + if(error) { std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: FreeType: Could not load glyph (in loop). (FreeType error "<< std::hex << error <<")." << std::endl; return;} + + /* Convert to an anti-aliased bitmap */ + error = FT_Render_Glyph(face->glyph, ft_render_mode_normal); + if(error) { std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: FreeType: Render glyph error." << std::endl; return;} + + /* Now, draw to our target surface */ + my_draw_bitmap_blend(&slot->bitmap, + slot->bitmap_left, + y_start + slot->bitmap_top, + opacity, + red, + green, + blue); + + /* Advance to the next position */ + pen.x += slot->advance.x; + pen.y += slot->advance.y; + + /* record current glyph index */ + previous = glyph_index; + } + + /* Free the face and the library objects */ + FT_Done_Face(face); + FT_Done_FreeType(library); + + delete[] ucs4text; } -void pngwriter::plot_text_blend( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, int red, int green, int blue) -{ - plot_text_blend( face_path, fontsize, x_start, y_start, angle, text, opacity, ((double) red)/65535.0, ((double) green)/65535.0, ((double) blue)/65535.0 ); +void pngwriter::plot_text_blend(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, double opacity, int red, int green, int blue) { + plot_text_blend(face_path, fontsize, x_start, y_start, angle, text, opacity, ((double) red)/65535.0, ((double) green)/65535.0, ((double) blue)/65535.0); } -void pngwriter::plot_text_utf8_blend( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, int red, int green, int blue) -{ - plot_text_utf8_blend( face_path, fontsize, x_start, y_start, angle, text, opacity, ((double) red)/65535.0, ((double) green)/65535.0, ((double) blue)/65535.0 ); +void pngwriter::plot_text_utf8_blend(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, double opacity, int red, int green, int blue) { + plot_text_utf8_blend(face_path, fontsize, x_start, y_start, angle, text, opacity, ((double) red)/65535.0, ((double) green)/65535.0, ((double) blue)/65535.0); } -void pngwriter::my_draw_bitmap_blend( FT_Bitmap * bitmap, int x, int y, double opacity, double red, double green, double blue) -{ - double temp; - for(int j=1; jrows+1; j++) - { - for(int i=1; i< bitmap->width + 1; i++) - { - temp = (double)(bitmap->buffer[(j-1)*bitmap->width + (i-1)] )/255.0; - - if(temp) - { - this->plot_blend(x + i, - y - j, - opacity, - temp*red + (1-temp)*(this->dread(x+i,y-j,1)), - temp*green + (1-temp)*(this->dread(x+i,y-j,2)), - temp*blue + (1-temp)*(this->dread(x+i,y-j,3)) - ); - } - } - } +void pngwriter::my_draw_bitmap_blend(FT_Bitmap* bitmap, int x, int y, double opacity, double red, double green, double blue) { + double temp; + for(int j=1; jrows+1; j++) { + for(int i=1; i< bitmap->width + 1; i++) { + temp = (double)(bitmap->buffer[(j-1)*bitmap->width + (i-1)])/255.0; + + if(temp) { + this->plot_blend(x + i, + y - j, + opacity, + temp*red + (1-temp)*(this->dread(x+i,y-j,1)), + temp*green + (1-temp)*(this->dread(x+i,y-j,2)), + temp*blue + (1-temp)*(this->dread(x+i,y-j,3)) + ); + } + } + } } #endif #ifdef NO_FREETYPE -void pngwriter::plot_text_blend( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, int red, int green, int blue) -{ - std::cerr << " PNGwriter::plot_text_blend - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; - return; +void pngwriter::plot_text_blend(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, double opacity, int red, int green, int blue) { + std::cerr << " PNGwriter::plot_text_blend - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; + return; } -void pngwriter::plot_text_blend( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, double red, double green, double blue) -{ - std::cerr << " PNGwriter::plot_text_blend - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; - return; +void pngwriter::plot_text_blend(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, double opacity, double red, double green, double blue) { + std::cerr << " PNGwriter::plot_text_blend - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; + return; } -void pngwriter::plot_text_utf8_blend( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, int red, int green, int blue) -{ - std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; - return; +void pngwriter::plot_text_utf8_blend(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, double opacity, int red, int green, int blue) { + std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; + return; } -void pngwriter::plot_text_utf8_blend( char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, double red, double green, double blue) -{ - std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; - return; +void pngwriter::plot_text_utf8_blend(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, double opacity, double red, double green, double blue) { + std::cerr << " PNGwriter::plot_text_utf8_blend - ERROR **: PNGwriter was compiled without Freetype support! Recompile PNGwriter with Freetype support (once you have Freetype installed, that is. Websites: www.freetype.org and pngwriter.sourceforge.net)." << std::endl; + return; } #endif /////////////////////////// -void pngwriter::boundary_fill_blend(int xstart, int ystart, double opacity, double boundary_red,double boundary_green,double boundary_blue,double fill_red, double fill_green, double fill_blue) -{ - if( ( - (this->dread(xstart,ystart,1) != boundary_red) || - (this->dread(xstart,ystart,2) != boundary_green) || - (this->dread(xstart,ystart,3) != boundary_blue) - ) - && - ( - (this->dread(xstart,ystart,1) != fill_red) || - (this->dread(xstart,ystart,2) != fill_green) || - (this->dread(xstart,ystart,3) != fill_blue) - ) - && - (xstart >0)&&(xstart <= width_)&&(ystart >0)&&(ystart <= height_) - ) - { - this->plot_blend(xstart, ystart, opacity, fill_red, fill_green, fill_blue); - boundary_fill_blend(xstart+1, ystart, opacity, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; - boundary_fill_blend(xstart, ystart+1, opacity, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; - boundary_fill_blend(xstart, ystart-1, opacity, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; - boundary_fill_blend(xstart-1, ystart, opacity, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; - } +void pngwriter::boundary_fill_blend(int xstart, int ystart, double opacity, double boundary_red,double boundary_green,double boundary_blue,double fill_red, double fill_green, double fill_blue) { + if(( + (this->dread(xstart,ystart,1) != boundary_red) || + (this->dread(xstart,ystart,2) != boundary_green) || + (this->dread(xstart,ystart,3) != boundary_blue) + ) + && + ( + (this->dread(xstart,ystart,1) != fill_red) || + (this->dread(xstart,ystart,2) != fill_green) || + (this->dread(xstart,ystart,3) != fill_blue) + ) + && + (xstart >0)&&(xstart <= width_)&&(ystart >0)&&(ystart <= height_) + ) { + this->plot_blend(xstart, ystart, opacity, fill_red, fill_green, fill_blue); + boundary_fill_blend(xstart+1, ystart, opacity, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; + boundary_fill_blend(xstart, ystart+1, opacity, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; + boundary_fill_blend(xstart, ystart-1, opacity, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; + boundary_fill_blend(xstart-1, ystart, opacity, boundary_red, boundary_green, boundary_blue, fill_red, fill_green, fill_blue) ; + } } //no int version needed -void pngwriter::flood_fill_internal_blend(int xstart, int ystart, double opacity, double start_red, double start_green, double start_blue, double fill_red, double fill_green, double fill_blue) -{ - if( ( - (this->dread(xstart,ystart,1) == start_red) && - (this->dread(xstart,ystart,2) == start_green) && - (this->dread(xstart,ystart,3) == start_blue) - ) - && - ( - (this->dread(xstart,ystart,1) != fill_red) || - (this->dread(xstart,ystart,2) != fill_green) || - (this->dread(xstart,ystart,3) != fill_blue) - ) - && - (xstart >0)&&(xstart <= width_)&&(ystart >0)&&(ystart <= height_) - ) - { - this->plot_blend(xstart, ystart, opacity, fill_red, fill_green, fill_blue); - flood_fill_internal_blend( xstart+1, ystart, opacity, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); - flood_fill_internal_blend( xstart-1, ystart,opacity, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); - flood_fill_internal_blend( xstart, ystart+1, opacity, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); - flood_fill_internal_blend( xstart, ystart-1, opacity, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); - } +void pngwriter::flood_fill_internal_blend(int xstart, int ystart, double opacity, double start_red, double start_green, double start_blue, double fill_red, double fill_green, double fill_blue) { + if(( + (this->dread(xstart,ystart,1) == start_red) && + (this->dread(xstart,ystart,2) == start_green) && + (this->dread(xstart,ystart,3) == start_blue) + ) + && + ( + (this->dread(xstart,ystart,1) != fill_red) || + (this->dread(xstart,ystart,2) != fill_green) || + (this->dread(xstart,ystart,3) != fill_blue) + ) + && + (xstart >0)&&(xstart <= width_)&&(ystart >0)&&(ystart <= height_) + ) { + this->plot_blend(xstart, ystart, opacity, fill_red, fill_green, fill_blue); + flood_fill_internal_blend(xstart+1, ystart, opacity, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); + flood_fill_internal_blend(xstart-1, ystart,opacity, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); + flood_fill_internal_blend(xstart, ystart+1, opacity, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); + flood_fill_internal_blend(xstart, ystart-1, opacity, start_red, start_green, start_blue, fill_red, fill_green, fill_blue); + } } //int version -void pngwriter::boundary_fill_blend(int xstart, int ystart, double opacity, int boundary_red,int boundary_green,int boundary_blue,int fill_red, int fill_green, int fill_blue) -{ - - this->boundary_fill_blend( xstart, ystart, - opacity, - ((double) boundary_red)/65535.0, - ((double) boundary_green)/65535.0, - ((double) boundary_blue)/65535.0, - ((double) fill_red)/65535.0, - ((double) fill_green)/65535.0, - ((double) fill_blue)/65535.0 - ); +void pngwriter::boundary_fill_blend(int xstart, int ystart, double opacity, int boundary_red,int boundary_green,int boundary_blue,int fill_red, int fill_green, int fill_blue) { + + this->boundary_fill_blend(xstart, ystart, + opacity, + ((double) boundary_red)/65535.0, + ((double) boundary_green)/65535.0, + ((double) boundary_blue)/65535.0, + ((double) fill_red)/65535.0, + ((double) fill_green)/65535.0, + ((double) fill_blue)/65535.0 + ); } -void pngwriter::flood_fill_blend(int xstart, int ystart, double opacity, double fill_red, double fill_green, double fill_blue) -{ - flood_fill_internal_blend( xstart, ystart, opacity, this->dread(xstart,ystart,1),this->dread(xstart,ystart,2),this->dread(xstart,ystart,3), fill_red, fill_green, fill_blue); +void pngwriter::flood_fill_blend(int xstart, int ystart, double opacity, double fill_red, double fill_green, double fill_blue) { + flood_fill_internal_blend(xstart, ystart, opacity, this->dread(xstart,ystart,1),this->dread(xstart,ystart,2),this->dread(xstart,ystart,3), fill_red, fill_green, fill_blue); } //int version -void pngwriter::flood_fill_blend(int xstart, int ystart, double opacity, int fill_red, int fill_green, int fill_blue) -{ - this->flood_fill_blend( xstart, ystart, - opacity, - ((double) fill_red)/65535.0, - ((double) fill_green)/65535.0, - ((double) fill_blue)/65535.0 - ); +void pngwriter::flood_fill_blend(int xstart, int ystart, double opacity, int fill_red, int fill_green, int fill_blue) { + this->flood_fill_blend(xstart, ystart, + opacity, + ((double) fill_red)/65535.0, + ((double) fill_green)/65535.0, + ((double) fill_blue)/65535.0 + ); } -void pngwriter::polygon_blend( int * points, int number_of_points, double opacity, double red, double green, double blue) -{ - if( (number_of_points<1)||(points ==NULL)) - { - std::cerr << " PNGwriter::polygon_blend - ERROR **: Number of points is zero or negative, or array is NULL." << std::endl; - return; - } +void pngwriter::polygon_blend(int* points, int number_of_points, double opacity, double red, double green, double blue) { + if((number_of_points<1)||(points ==NULL)) { + std::cerr << " PNGwriter::polygon_blend - ERROR **: Number of points is zero or negative, or array is NULL." << std::endl; + return; + } - for(int k=0;k< number_of_points-1; k++) - { - this->line_blend(points[2*k],points[2*k+1],points[2*k+2],points[2*k+3], opacity, red, green, blue); - } + for(int k=0; k< number_of_points-1; k++) { + this->line_blend(points[2*k],points[2*k+1],points[2*k+2],points[2*k+3], opacity, red, green, blue); + } } //int version -void pngwriter::polygon_blend( int * points, int number_of_points, double opacity, int red, int green, int blue) -{ - this->polygon_blend(points, number_of_points, - opacity, - ((double) red)/65535.0, - ((double) green)/65535.0, - ((double) blue)/65535.0 - ); +void pngwriter::polygon_blend(int* points, int number_of_points, double opacity, int red, int green, int blue) { + this->polygon_blend(points, number_of_points, + opacity, + ((double) red)/65535.0, + ((double) green)/65535.0, + ((double) blue)/65535.0 + ); } -void pngwriter::plotCMYK_blend(int x, int y, double opacity, double cyan, double magenta, double yellow, double black) -{ -/*CMYK to RGB: - * ----------- - * red = 255 - minimum(255,((cyan/255) * (255 - black) + black)) - * green = 255 - minimum(255,((magenta/255) * (255 - black) + black)) - * blue = 255 - minimum(255,((yellow/255) * (255 - black) + black)) - * */ - - if(cyan<0.0) - { - cyan = 0.0; - } - if(magenta<0.0) - { - magenta = 0.0; - } - if(yellow<0.0) - { - yellow = 0.0; - } - if(black<0.0) - { - black = 0.0; - } - - if(cyan>1.0) - { - cyan = 1.0; - } - if(magenta>1.0) - { - magenta = 1.0; - } - if(yellow>1.0) - { - yellow = 1.0; - } - if(black>1.0) - { - black = 1.0; - } - - double red, green, blue, minr, ming, minb, iblack; - - iblack = 1.0 - black; - - minr = 1.0; - ming = 1.0; - minb = 1.0; - - if( (cyan*iblack + black)<1.0 ) - { - minr = cyan*iblack + black; - } - - if( (magenta*iblack + black)<1.0 ) - { - ming = magenta*iblack + black; - } - - if( (yellow*iblack + black)<1.0 ) - { - minb = yellow*iblack + black; - } - - red = 1.0 - minr; - green = 1.0 - ming; - blue = 1.0 - minb; - - this->plot_blend(x,y,opacity, red, green, blue); +void pngwriter::plotCMYK_blend(int x, int y, double opacity, double cyan, double magenta, double yellow, double black) { + /*CMYK to RGB: + * ----------- + * red = 255 - minimum(255,((cyan/255) * (255 - black) + black)) + * green = 255 - minimum(255,((magenta/255) * (255 - black) + black)) + * blue = 255 - minimum(255,((yellow/255) * (255 - black) + black)) + * */ + + if(cyan<0.0) { + cyan = 0.0; + } + if(magenta<0.0) { + magenta = 0.0; + } + if(yellow<0.0) { + yellow = 0.0; + } + if(black<0.0) { + black = 0.0; + } + + if(cyan>1.0) { + cyan = 1.0; + } + if(magenta>1.0) { + magenta = 1.0; + } + if(yellow>1.0) { + yellow = 1.0; + } + if(black>1.0) { + black = 1.0; + } + + double red, green, blue, minr, ming, minb, iblack; + + iblack = 1.0 - black; + + minr = 1.0; + ming = 1.0; + minb = 1.0; + + if((cyan*iblack + black)<1.0) { + minr = cyan*iblack + black; + } + + if((magenta*iblack + black)<1.0) { + ming = magenta*iblack + black; + } + + if((yellow*iblack + black)<1.0) { + minb = yellow*iblack + black; + } + + red = 1.0 - minr; + green = 1.0 - ming; + blue = 1.0 - minb; + + this->plot_blend(x,y,opacity, red, green, blue); } //int version -void pngwriter::plotCMYK_blend(int x, int y, double opacity, int cyan, int magenta, int yellow, int black) -{ - this->plotCMYK_blend( x, y, - opacity, - ((double) cyan)/65535.0, - ((double) magenta)/65535.0, - ((double) yellow)/65535.0, - ((double) black)/65535.0 - ); +void pngwriter::plotCMYK_blend(int x, int y, double opacity, int cyan, int magenta, int yellow, int black) { + this->plotCMYK_blend(x, y, + opacity, + ((double) cyan)/65535.0, + ((double) magenta)/65535.0, + ((double) yellow)/65535.0, + ((double) black)/65535.0 + ); } -void pngwriter::laplacian(double k, double offset) -{ - - // Create image storage. - pngwriter temp(width_,height_,0,"temp"); - - double red, green, blue; - - for(int x = 1; x <= width_; x++) - { - for(int y = 1; y <= height_; y++) - { - red = - 8.0*this->dread(x,y,1) - - ( this->dread(x+1, y-1, 1) + - this->dread(x, y-1, 1) + - this->dread(x-1, y-1, 1) + - this->dread(x-1, y, 1) + - this->dread(x+1, y, 1) + - this->dread(x+1, y+1, 1) + - this->dread(x, y+1, 1) + - this->dread(x-1, y+1, 1) ); - - green = - 8.0*this->dread(x,y,2) - - ( this->dread(x+1, y-1, 2) + - this->dread(x, y-1, 2) + - this->dread(x-1, y-1, 2) + - this->dread(x-1, y, 2) + - this->dread(x+1, y, 2) + - this->dread(x+1, y+1, 2) + - this->dread(x, y+1, 2) + - this->dread(x-1, y+1, 2)); - - blue = - 8.0*this->dread(x,y,3) - - ( this->dread(x+1, y-1, 3) + - this->dread(x, y-1, 3) + - this->dread(x-1, y-1, 3) + - this->dread(x-1, y, 3) + - this->dread(x+1, y, 3) + - this->dread(x+1, y+1, 3) + - this->dread(x, y+1, 3) + - this->dread(x-1, y+1, 3)); - - temp.plot(x,y,offset+k*red,offset+k*green,offset+k*blue); - - } - } - - for(int xx = 1; xx <= width_; xx++) - { - for(int yy = 1; yy <= height_; yy++) - { - this->plot(xx,yy, temp.read(xx,yy,1), temp.read(xx,yy,2), temp.read(xx,yy,3)); - } - } +void pngwriter::laplacian(double k, double offset) { + + // Create image storage. + pngwriter temp(width_,height_,0,"temp"); + + double red, green, blue; + + for(int x = 1; x <= width_; x++) { + for(int y = 1; y <= height_; y++) { + red = + 8.0*this->dread(x,y,1) - + (this->dread(x+1, y-1, 1) + + this->dread(x, y-1, 1) + + this->dread(x-1, y-1, 1) + + this->dread(x-1, y, 1) + + this->dread(x+1, y, 1) + + this->dread(x+1, y+1, 1) + + this->dread(x, y+1, 1) + + this->dread(x-1, y+1, 1)); + + green = + 8.0*this->dread(x,y,2) - + (this->dread(x+1, y-1, 2) + + this->dread(x, y-1, 2) + + this->dread(x-1, y-1, 2) + + this->dread(x-1, y, 2) + + this->dread(x+1, y, 2) + + this->dread(x+1, y+1, 2) + + this->dread(x, y+1, 2) + + this->dread(x-1, y+1, 2)); + + blue = + 8.0*this->dread(x,y,3) - + (this->dread(x+1, y-1, 3) + + this->dread(x, y-1, 3) + + this->dread(x-1, y-1, 3) + + this->dread(x-1, y, 3) + + this->dread(x+1, y, 3) + + this->dread(x+1, y+1, 3) + + this->dread(x, y+1, 3) + + this->dread(x-1, y+1, 3)); + + temp.plot(x,y,offset+k*red,offset+k*green,offset+k*blue); + + } + } + + for(int xx = 1; xx <= width_; xx++) { + for(int yy = 1; yy <= height_; yy++) { + this->plot(xx,yy, temp.read(xx,yy,1), temp.read(xx,yy,2), temp.read(xx,yy,3)); + } + } } // drwatop(), drawbottom() and filledtriangle() were contributed by Gurkan Sengun // ( , http://www.linuks.mine.nu/ ) -void pngwriter::drawtop(long x1,long y1,long x2,long y2,long x3, int red, int green, int blue) -{ - // This swaps x2 and x3 - // if(x2>x3) x2^=x3^=x2^=x3; - if(x2>x3) - { - x2^=x3; - x3^=x2; - x2^=x3; - } - - long posl = x1*256; - long posr = posl; - - long cl=((x2-x1)*256)/(y2-y1); - long cr=((x3-x1)*256)/(y2-y1); - - for(int y=y1; yline(posl/256, y, posr/256, y, red, green, blue); - posl+=cl; - posr+=cr; - } +void pngwriter::drawtop(long x1,long y1,long x2,long y2,long x3, int red, int green, int blue) { + // This swaps x2 and x3 + // if(x2>x3) x2^=x3^=x2^=x3; + if(x2>x3) { + x2^=x3; + x3^=x2; + x2^=x3; + } + + long posl = x1*256; + long posr = posl; + + long cl=((x2-x1)*256)/(y2-y1); + long cr=((x3-x1)*256)/(y2-y1); + + for(int y=y1; yline(posl/256, y, posr/256, y, red, green, blue); + posl+=cl; + posr+=cr; + } } // drwatop(), drawbottom() and filledtriangle() were contributed by Gurkan Sengun // ( , http://www.linuks.mine.nu/ ) -void pngwriter::drawbottom(long x1,long y1,long x2,long x3,long y3, int red, int green, int blue) -{ - //Swap x1 and x2 - //if(x1>x2) x2^=x1^=x2^=x1; - if(x1>x2) - { - x2^=x1; - x1^=x2; - x2^=x1; - } - - long posl=x1*256; - long posr=x2*256; - - long cl=((x3-x1)*256)/(y3-y1); - long cr=((x3-x2)*256)/(y3-y1); - - for(int y=y1; yline(posl/256, y, posr/256, y, red, green, blue); - - posl+=cl; - posr+=cr; - } +void pngwriter::drawbottom(long x1,long y1,long x2,long x3,long y3, int red, int green, int blue) { + //Swap x1 and x2 + //if(x1>x2) x2^=x1^=x2^=x1; + if(x1>x2) { + x2^=x1; + x1^=x2; + x2^=x1; + } + + long posl=x1*256; + long posr=x2*256; + + long cl=((x3-x1)*256)/(y3-y1); + long cr=((x3-x2)*256)/(y3-y1); + + for(int y=y1; yline(posl/256, y, posr/256, y, red, green, blue); + + posl+=cl; + posr+=cr; + } } // drwatop(), drawbottom() and filledtriangle() were contributed by Gurkan Sengun // ( , http://www.linuks.mine.nu/ ) -void pngwriter::filledtriangle(int x1,int y1,int x2,int y2,int x3,int y3, int red, int green, int blue) -{ - if((x1==x2 && x2==x3) || (y1==y2 && y2==y3)) return; - - if(y2drawtop(x1, y1, x2, y2, x3, red, green, blue); - } - else - { - if(y1==y3 || y1==y2) - { - this->drawbottom(x1, y1, x2, x3, y3, red, green, blue); - } - else - { - int new_x = x1 + (int)((double)(y2-y1)*(double)(x3-x1)/(double)(y3-y1)); - this->drawtop(x1, y1, new_x, y2, x2, red, green, blue); - this->drawbottom(x2, y2, new_x, x3, y3, red, green, blue); - } - } +void pngwriter::filledtriangle(int x1,int y1,int x2,int y2,int x3,int y3, int red, int green, int blue) { + if((x1==x2 && x2==x3) || (y1==y2 && y2==y3)) return; + + if(y2drawtop(x1, y1, x2, y2, x3, red, green, blue); + } else { + if(y1==y3 || y1==y2) { + this->drawbottom(x1, y1, x2, x3, y3, red, green, blue); + } else { + int new_x = x1 + (int)((double)(y2-y1)*(double)(x3-x1)/(double)(y3-y1)); + this->drawtop(x1, y1, new_x, y2, x2, red, green, blue); + this->drawbottom(x2, y2, new_x, x3, y3, red, green, blue); + } + } } //Double (bug found by Dave Wilks. Was: (int) red*65535, should have been (int) (red*65535). -void pngwriter::filledtriangle(int x1,int y1,int x2,int y2,int x3,int y3, double red, double green, double blue) -{ - this->filledtriangle(x1, y1, x2, y2, x3, y3, (int) (red*65535), (int) (green*65535), (int) (blue*65535)); +void pngwriter::filledtriangle(int x1,int y1,int x2,int y2,int x3,int y3, double red, double green, double blue) { + this->filledtriangle(x1, y1, x2, y2, x3, y3, (int)(red*65535), (int)(green*65535), (int)(blue*65535)); } //Blend, double. (bug found by Dave Wilks. Was: (int) red*65535, should have been (int) (red*65535). -void pngwriter::filledtriangle_blend(int x1,int y1,int x2,int y2,int x3,int y3, double opacity, double red, double green, double blue) -{ - this->filledtriangle_blend( x1, y1, x2, y2, x3, y3, opacity, (int) (red*65535), (int) (green*65535), (int) (blue*65535)); +void pngwriter::filledtriangle_blend(int x1,int y1,int x2,int y2,int x3,int y3, double opacity, double red, double green, double blue) { + this->filledtriangle_blend(x1, y1, x2, y2, x3, y3, opacity, (int)(red*65535), (int)(green*65535), (int)(blue*65535)); } //Blend, int -void pngwriter::filledtriangle_blend(int x1,int y1,int x2,int y2,int x3,int y3, double opacity, int red, int green, int blue) -{ - if((x1==x2 && x2==x3) || (y1==y2 && y2==y3)) return; +void pngwriter::filledtriangle_blend(int x1,int y1,int x2,int y2,int x3,int y3, double opacity, int red, int green, int blue) { + if((x1==x2 && x2==x3) || (y1==y2 && y2==y3)) return; - /*if(y2drawtop_blend(x1, y1, x2, y2, x3, opacity, red, green, blue); - } - else - { - if(y1==y3 || y1==y2) - { - this->drawbottom_blend(x1, y1, x2, x3, y3, opacity, red, green, blue); - } - else - { - int new_x = x1 + (int)((double)(y2-y1)*(double)(x3-x1)/(double)(y3-y1)); - this->drawtop_blend(x1, y1, new_x, y2, x2, opacity, red, green, blue); - this->drawbottom_blend(x2, y2, new_x, x3, y3, opacity, red, green, blue); } - } + */ + + if(y2drawtop_blend(x1, y1, x2, y2, x3, opacity, red, green, blue); + } else { + if(y1==y3 || y1==y2) { + this->drawbottom_blend(x1, y1, x2, x3, y3, opacity, red, green, blue); + } else { + int new_x = x1 + (int)((double)(y2-y1)*(double)(x3-x1)/(double)(y3-y1)); + this->drawtop_blend(x1, y1, new_x, y2, x2, opacity, red, green, blue); + this->drawbottom_blend(x2, y2, new_x, x3, y3, opacity, red, green, blue); + } + } } //Blend, int -void pngwriter::drawbottom_blend(long x1,long y1,long x2,long x3,long y3, double opacity, int red, int green, int blue) -{ - //Swap x1 and x2 - if(x1>x2) - { - x2^=x1; - x1^=x2; - x2^=x1; - } +void pngwriter::drawbottom_blend(long x1,long y1,long x2,long x3,long y3, double opacity, int red, int green, int blue) { + //Swap x1 and x2 + if(x1>x2) { + x2^=x1; + x1^=x2; + x2^=x1; + } - long posl=x1*256; - long posr=x2*256; + long posl=x1*256; + long posr=x2*256; - long cl=((x3-x1)*256)/(y3-y1); - long cr=((x3-x2)*256)/(y3-y1); + long cl=((x3-x1)*256)/(y3-y1); + long cr=((x3-x2)*256)/(y3-y1); - for(int y=y1; yline_blend(posl/256, y, posr/256, y, opacity, red, green, blue); + for(int y=y1; yline_blend(posl/256, y, posr/256, y, opacity, red, green, blue); - posl+=cl; - posr+=cr; - } + posl+=cl; + posr+=cr; + } } //Blend, int -void pngwriter::drawtop_blend(long x1,long y1,long x2,long y2,long x3, double opacity, int red, int green, int blue) -{ - // This swaps x2 and x3 - if(x2>x3) - { - x2^=x3; - x3^=x2; - x2^=x3; +void pngwriter::drawtop_blend(long x1,long y1,long x2,long y2,long x3, double opacity, int red, int green, int blue) { + // This swaps x2 and x3 + if(x2>x3) { + x2^=x3; + x3^=x2; + x2^=x3; + } + + long posl = x1*256; + long posr = posl; + + long cl=((x2-x1)*256)/(y2-y1); + long cr=((x3-x1)*256)/(y2-y1); + + for(int y=y1; yline_blend(posl/256, y, posr/256, y, opacity, red, green, blue); + posl+=cl; + posr+=cr; + } + } - long posl = x1*256; - long posr = posl; +void pngwriter::triangle(int x1, int y1, int x2, int y2, int x3, int y3, int red, int green, int blue) { + this->line(x1, y1, x2, y2, red, green, blue); + this->line(x2, y2, x3, y3, red, green, blue); + this->line(x3, y3, x1, y1, red, green, blue); +} - long cl=((x2-x1)*256)/(y2-y1); - long cr=((x3-x1)*256)/(y2-y1); +void pngwriter::triangle(int x1, int y1, int x2, int y2, int x3, int y3, double red, double green, double blue) { - for(int y=y1; yline_blend(posl/256, y, posr/256, y, opacity, red, green, blue); - posl+=cl; - posr+=cr; - } + this->line(x1, y1, x2, y2, ((int)65535*red), ((int)65535*green), ((int)65535*blue)); + this->line(x2, y2, x3, y3, ((int)65535*red), ((int)65535*green), ((int)65535*blue)); + this->line(x3, y3, x1, y1, ((int)65535*red), ((int)65535*green), ((int)65535*blue)); } -void pngwriter::triangle(int x1, int y1, int x2, int y2, int x3, int y3, int red, int green, int blue) -{ - this->line(x1, y1, x2, y2, red, green, blue); - this->line(x2, y2, x3, y3, red, green, blue); - this->line(x3, y3, x1, y1, red, green, blue); -} -void pngwriter::triangle(int x1, int y1, int x2, int y2, int x3, int y3, double red, double green, double blue) -{ - - this->line(x1, y1, x2, y2, ((int)65535*red), ((int)65535*green), ((int)65535*blue)); - this->line(x2, y2, x3, y3, ((int)65535*red), ((int)65535*green), ((int)65535*blue)); - this->line(x3, y3, x1, y1, ((int)65535*red), ((int)65535*green), ((int)65535*blue)); - -} +void pngwriter::arrow(int x1,int y1,int x2,int y2,int size, double head_angle, double red, double green, double blue) { + this->line(x1, y1, x2, y2, red, green, blue); + // double th = 3.141592653589793 + (head_angle)*3.141592653589793/180.0; //degrees + double th = 3.141592653589793 + head_angle; + double costh = cos(th); + double sinth = sin(th); + double t1, t2, r; + t1 = ((x2-x1)*costh - (y2-y1)*sinth); + t2 = ((x2-x1)*sinth + (y2-y1)*costh); + r = sqrt(t1*t1 + t2*t2); -void pngwriter::arrow( int x1,int y1,int x2,int y2,int size, double head_angle, double red, double green, double blue) -{ + double advancex = size*t1/r; + double advancey = size*t2/r; + this->line(x2, y2, int(x2 + advancex), int(y2 + advancey), red, green, blue); + t1 = (x2-x1)*costh + (y2-y1)*sinth; + t2 = (y2-y1)*costh - (x2-x1)*sinth; - this->line(x1, y1, x2, y2, red, green, blue); - // double th = 3.141592653589793 + (head_angle)*3.141592653589793/180.0; //degrees - double th = 3.141592653589793 + head_angle; - double costh = cos(th); - double sinth = sin(th); - double t1, t2, r; - t1 = ((x2-x1)*costh - (y2-y1)*sinth); - t2 = ((x2-x1)*sinth + (y2-y1)*costh); - r = sqrt(t1*t1 + t2*t2); - - double advancex = size*t1/r; - double advancey = size*t2/r; - this->line(x2, y2, int(x2 + advancex), int(y2 + advancey), red, green, blue); - t1 = (x2-x1)*costh + (y2-y1)*sinth; - t2 = (y2-y1)*costh - (x2-x1)*sinth; - - advancex = size*t1/r; - advancey = size*t2/r; - this->line(x2, y2, int(x2 + advancex), int(y2 + advancey), red, green, blue); + advancex = size*t1/r; + advancey = size*t2/r; + this->line(x2, y2, int(x2 + advancex), int(y2 + advancey), red, green, blue); } - -void pngwriter::filledarrow( int x1,int y1,int x2,int y2,int size, double head_angle, double red, double green, double blue) -{ - int p1x, p2x, p3x, p1y, p2y, p3y; - - this->line(x1, y1, x2, y2, red, green, blue); - double th = 3.141592653589793 + head_angle; - double costh = cos(th); - double sinth = sin(th); - double t11, t12, t21, t22, r1, r2; - t11 = ((x2-x1)*costh - (y2-y1)*sinth); - t21 = ((x2-x1)*sinth + (y2-y1)*costh); - t12 = (x2-x1)*costh + (y2-y1)*sinth; - t22 = (y2-y1)*costh - (x2-x1)*sinth; - - r1 = sqrt(t11*t11 + t21*t21); - r2 = sqrt(t12*t12 + t22*t22); - - double advancex1 = size*t11/r1; - double advancey1 = size*t21/r1; - double advancex2 = size*t12/r2; - double advancey2 = size*t22/r2; - - p1x = x2; - p1y = y2; - - p2x = int(x2 + advancex1); - p2y = int(y2 + advancey1); - - p3x = int(x2 + advancex2); - p3y = int(y2 + advancey2); - - - this->filledtriangle( p1x, p1y, p2x, p2y, p3x, p3y, red, green, blue); - + +void pngwriter::filledarrow(int x1,int y1,int x2,int y2,int size, double head_angle, double red, double green, double blue) { + int p1x, p2x, p3x, p1y, p2y, p3y; + + this->line(x1, y1, x2, y2, red, green, blue); + double th = 3.141592653589793 + head_angle; + double costh = cos(th); + double sinth = sin(th); + double t11, t12, t21, t22, r1, r2; + t11 = ((x2-x1)*costh - (y2-y1)*sinth); + t21 = ((x2-x1)*sinth + (y2-y1)*costh); + t12 = (x2-x1)*costh + (y2-y1)*sinth; + t22 = (y2-y1)*costh - (x2-x1)*sinth; + + r1 = sqrt(t11*t11 + t21*t21); + r2 = sqrt(t12*t12 + t22*t22); + + double advancex1 = size*t11/r1; + double advancey1 = size*t21/r1; + double advancex2 = size*t12/r2; + double advancey2 = size*t22/r2; + + p1x = x2; + p1y = y2; + + p2x = int(x2 + advancex1); + p2y = int(y2 + advancey1); + + p3x = int(x2 + advancex2); + p3y = int(y2 + advancey2); + + + this->filledtriangle(p1x, p1y, p2x, p2y, p3x, p3y, red, green, blue); + } -void pngwriter::arrow( int x1,int y1,int x2,int y2,int size, double head_angle, int red, int green, int blue) -{ - this->arrow( x1, y1, x2, y2, size, head_angle, (double (red))/65535.0, (double (green))/65535.0, (double (blue))/65535.0 ); +void pngwriter::arrow(int x1,int y1,int x2,int y2,int size, double head_angle, int red, int green, int blue) { + this->arrow(x1, y1, x2, y2, size, head_angle, (double(red))/65535.0, (double(green))/65535.0, (double(blue))/65535.0); } -void pngwriter::filledarrow( int x1,int y1,int x2,int y2,int size, double head_angle, int red, int green, int blue) -{ - this->filledarrow( x1, y1, x2, y2, size, head_angle, (double (red))/65535.0, (double (green))/65535.0, (double (blue))/65535.0 ); +void pngwriter::filledarrow(int x1,int y1,int x2,int y2,int size, double head_angle, int red, int green, int blue) { + this->filledarrow(x1, y1, x2, y2, size, head_angle, (double(red))/65535.0, (double(green))/65535.0, (double(blue))/65535.0); } -void pngwriter::cross( int x, int y, int xwidth, int yheight, int red, int green, int blue) -{ - this->line(int(x - xwidth/2.0), y, int(x + xwidth/2.0), y, red, green, blue); - this->line(x, int(y - yheight/2.0), x, int(y + yheight/2.0), red, green, blue); +void pngwriter::cross(int x, int y, int xwidth, int yheight, int red, int green, int blue) { + this->line(int(x - xwidth/2.0), y, int(x + xwidth/2.0), y, red, green, blue); + this->line(x, int(y - yheight/2.0), x, int(y + yheight/2.0), red, green, blue); } -void pngwriter::maltesecross( int x, int y, int xwidth, int yheight, int x_bar_height, int y_bar_width, int red, int green, int blue) -{ - this->line(int(x - xwidth/2.0), y, int(x + xwidth/2.0), y, red, green, blue); - this->line(x, int(y - yheight/2.0), x, int(y + yheight/2.0), red, green, blue); - // Bars on ends of vertical line - this->line(int(x - y_bar_width/2.0), int(y + yheight/2.0), int(x + y_bar_width/2.0), int(y + yheight/2.0), red, green, blue); - this->line(int(x - y_bar_width/2.0), int(y - yheight/2.0), int(x + y_bar_width/2.0), int(y - yheight/2.0), red, green, blue); - // Bars on ends of horizontal line. - this->line(int(x - xwidth/2.0), int(y - x_bar_height/2.0), int(x - xwidth/2.0), int(y + x_bar_height/2.0), red, green, blue); - this->line(int(x + xwidth/2.0), int(y - x_bar_height/2.0), int(x + xwidth/2.0), int(y + x_bar_height/2.0), red, green, blue); +void pngwriter::maltesecross(int x, int y, int xwidth, int yheight, int x_bar_height, int y_bar_width, int red, int green, int blue) { + this->line(int(x - xwidth/2.0), y, int(x + xwidth/2.0), y, red, green, blue); + this->line(x, int(y - yheight/2.0), x, int(y + yheight/2.0), red, green, blue); + // Bars on ends of vertical line + this->line(int(x - y_bar_width/2.0), int(y + yheight/2.0), int(x + y_bar_width/2.0), int(y + yheight/2.0), red, green, blue); + this->line(int(x - y_bar_width/2.0), int(y - yheight/2.0), int(x + y_bar_width/2.0), int(y - yheight/2.0), red, green, blue); + // Bars on ends of horizontal line. + this->line(int(x - xwidth/2.0), int(y - x_bar_height/2.0), int(x - xwidth/2.0), int(y + x_bar_height/2.0), red, green, blue); + this->line(int(x + xwidth/2.0), int(y - x_bar_height/2.0), int(x + xwidth/2.0), int(y + x_bar_height/2.0), red, green, blue); } -void pngwriter::cross( int x, int y, int xwidth, int yheight, double red, double green, double blue) -{ - this->cross( x, y, xwidth, yheight, int(65535*red), int(65535*green), int(65535*blue)); +void pngwriter::cross(int x, int y, int xwidth, int yheight, double red, double green, double blue) { + this->cross(x, y, xwidth, yheight, int(65535*red), int(65535*green), int(65535*blue)); } -void pngwriter::maltesecross( int x, int y, int xwidth, int yheight, int x_bar_height, int y_bar_width, double red, double green, double blue) -{ - this->maltesecross( x, y, xwidth, yheight, x_bar_height, y_bar_width, int(65535*red), int(65535*green), int(65535*blue)); +void pngwriter::maltesecross(int x, int y, int xwidth, int yheight, int x_bar_height, int y_bar_width, double red, double green, double blue) { + this->maltesecross(x, y, xwidth, yheight, x_bar_height, y_bar_width, int(65535*red), int(65535*green), int(65535*blue)); } -void pngwriter::filleddiamond( int x, int y, int width, int height, int red, int green, int blue) -{ - this->filledtriangle( int(x - width/2.0), y, x, y, x, int(y + height/2.0), red, green, blue); - this->filledtriangle( int(x + width/2.0), y, x, y, x, int(y + height/2.0), red, green, blue); - this->filledtriangle( int(x - width/2.0), y, x, y, x, int(y - height/2.0), red, green, blue); - this->filledtriangle( int(x + width/2.0), y, x, y, x, int(y - height/2.0), red, green, blue); +void pngwriter::filleddiamond(int x, int y, int width, int height, int red, int green, int blue) { + this->filledtriangle(int(x - width/2.0), y, x, y, x, int(y + height/2.0), red, green, blue); + this->filledtriangle(int(x + width/2.0), y, x, y, x, int(y + height/2.0), red, green, blue); + this->filledtriangle(int(x - width/2.0), y, x, y, x, int(y - height/2.0), red, green, blue); + this->filledtriangle(int(x + width/2.0), y, x, y, x, int(y - height/2.0), red, green, blue); } -void pngwriter::diamond( int x, int y, int width, int height, int red, int green, int blue) -{ - this->line( int(x - width/2.0), y, x, int(y + height/2.0), red, green, blue); - this->line( int(x + width/2.0), y, x, int(y + height/2.0), red, green, blue); - this->line( int(x - width/2.0), y, x, int(y - height/2.0), red, green, blue); - this->line( int(x + width/2.0), y, x, int(y - height/2.0), red, green, blue); +void pngwriter::diamond(int x, int y, int width, int height, int red, int green, int blue) { + this->line(int(x - width/2.0), y, x, int(y + height/2.0), red, green, blue); + this->line(int(x + width/2.0), y, x, int(y + height/2.0), red, green, blue); + this->line(int(x - width/2.0), y, x, int(y - height/2.0), red, green, blue); + this->line(int(x + width/2.0), y, x, int(y - height/2.0), red, green, blue); } -void pngwriter::filleddiamond( int x, int y, int width, int height, double red, double green, double blue) -{ - this->filleddiamond( x, y, width, height, int(red*65535), int(green*65535), int(blue*65535) ); +void pngwriter::filleddiamond(int x, int y, int width, int height, double red, double green, double blue) { + this->filleddiamond(x, y, width, height, int(red*65535), int(green*65535), int(blue*65535)); } -void pngwriter::diamond( int x, int y, int width, int height, double red, double green, double blue) -{ - this->diamond( x, y, width, height, int(red*65535), int(green*65535), int(blue*65535) ); +void pngwriter::diamond(int x, int y, int width, int height, double red, double green, double blue) { + this->diamond(x, y, width, height, int(red*65535), int(green*65535), int(blue*65535)); } diff --git a/pngwriter/pngwriter.h b/pngwriter/pngwriter.h index 9a2269b..19c588f 100644 --- a/pngwriter/pngwriter.h +++ b/pngwriter/pngwriter.h @@ -90,654 +90,653 @@ using namespace std; #define PNG_BYTES_TO_CHECK (4) #define PNGWRITER_DEFAULT_COMPRESSION (6) -class pngwriter -{ - private: - - char * filename_; - char * textauthor_; - char * textdescription_; - char * texttitle_; - char * textsoftware_; - - - - int height_; - int width_; - int backgroundcolour_; - int bit_depth_; - int rowbytes_; - int colortype_; - int compressionlevel_; - bool transformation_; // Required by Mikkel's patch - - unsigned char * * graph_; - double filegamma_; - double screengamma_; - void circle_aux(int xcentre, int ycentre, int x, int y, int red, int green, int blue); - void circle_aux_blend(int xcentre, int ycentre, int x, int y, double opacity, int red, int green, int blue); - int check_if_png(char *file_name, FILE **fp); - int read_png_info(FILE *fp, png_structp *png_ptr, png_infop *info_ptr); - int read_png_image(FILE *fp, png_structp png_ptr, png_infop info_ptr, - png_bytepp *image, png_uint_32 *width, png_uint_32 *height); - void flood_fill_internal( int xstart, int ystart, double start_red, double start_green, double start_blue, double fill_red, double fill_green, double fill_blue); - void flood_fill_internal_blend( int xstart, int ystart, double opacity, double start_red, double start_green, double start_blue, double fill_red, double fill_green, double fill_blue); +class pngwriter { +private: + + char* filename_; + char* textauthor_; + char* textdescription_; + char* texttitle_; + char* textsoftware_; + + + + int height_; + int width_; + int backgroundcolour_; + int bit_depth_; + int rowbytes_; + int colortype_; + int compressionlevel_; + bool transformation_; // Required by Mikkel's patch + + unsigned char * * graph_; + double filegamma_; + double screengamma_; + void circle_aux(int xcentre, int ycentre, int x, int y, int red, int green, int blue); + void circle_aux_blend(int xcentre, int ycentre, int x, int y, double opacity, int red, int green, int blue); + int check_if_png(char* file_name, FILE** fp); + int read_png_info(FILE* fp, png_structp* png_ptr, png_infop* info_ptr); + int read_png_image(FILE* fp, png_structp png_ptr, png_infop info_ptr, + png_bytepp* image, png_uint_32* width, png_uint_32* height); + void flood_fill_internal(int xstart, int ystart, double start_red, double start_green, double start_blue, double fill_red, double fill_green, double fill_blue); + void flood_fill_internal_blend(int xstart, int ystart, double opacity, double start_red, double start_green, double start_blue, double fill_red, double fill_green, double fill_blue); #ifndef NO_FREETYPE - void my_draw_bitmap( FT_Bitmap * bitmap, int x, int y, double red, double green, double blue); - void my_draw_bitmap_blend( FT_Bitmap * bitmap, int x, int y,double opacity, double red, double green, double blue); + void my_draw_bitmap(FT_Bitmap* bitmap, int x, int y, double red, double green, double blue); + void my_draw_bitmap_blend(FT_Bitmap* bitmap, int x, int y,double opacity, double red, double green, double blue); #endif - /* The algorithms HSVtoRGB and RGBtoHSV were found at http://www.cs.rit.edu/~ncs/ - * which is a page that belongs to Nan C. Schaller, though - * these algorithms appear to be the work of Eugene Vishnevsky. - * */ - void HSVtoRGB( double *r, double *g, double *b, double h, double s, double v ); - void RGBtoHSV( float r, float g, float b, float *h, float *s, float *v ); - - /* drwatop(), drawbottom() and filledtriangle() were contributed by Gurkan Sengun - * ( , http://www.linuks.mine.nu/ ) - * */ - void drawtop(long x1,long y1,long x2,long y2,long x3, int red, int green, int blue); - void drawbottom(long x1,long y1,long x2,long x3,long y3, int red, int green, int blue); - void drawbottom_blend(long x1,long y1,long x2,long x3,long y3, double opacity, int red, int green, int blue); - void drawtop_blend(long x1,long y1,long x2,long y2,long x3, double opacity, int red, int green, int blue); - - public: - - /* General Notes - * It is important to remember that all functions that accept an argument of type "const char *" will also - * accept "char *", this is done so you can have a changing filename (to make many PNG images in series - * with a different name, for example), and to allow you to use string type objects which can be easily - * turned into const char * (if theString is an object of type string, then it can be used as a const char * - * by saying theString.c_str()). - * It is also important to remember that whenever a function has a colour coeffiecient as its argument, - * that argument can be either an int from 0 to 65535 or a double from 0.0 to 1.0. - * It is important to make sure that you are calling the function with the type that you want. - * Remember that 1 is an int, while 1.0 is a double, and will thus determine what version of the function - * will be used. Similarly, do not make the mistake of calling for example plot(x, y, 0.0, 0.0, 65535), - * because - * there is no plot(int, int, double, double, int). - * Also, please note that plot() and read() (and the functions that use them internally) - * are protected against entering, for example, a colour coefficient that is over 65535 - * or over 1.0. Similarly, they are protected against negative coefficients. read() will return 0 - * when called outside the image range. This is actually useful as zero-padding should you need it. - * */ - - /* Compilation - * A typical compilation would look like this: - * - * g++ my_program.cc -o my_program freetype-config --cflags \ - * -I/usr/local/include -L/usr/local/lib -lpng -lpngwriter -lz -lfreetype - * - * If you did not compile PNGwriter with FreeType support, then remove the - * FreeType-related flags and add -DNO_FREETYPE above. - * */ - - /* Constructor - * The constructor requires the width and the height of the image, the background colour for the - * image and the filename of the file (a pointer or simple "myfile.png"). The background colour - * can only be initialized to a shade of grey (once the object has been created you can do whatever - * you want, though), because generally one wants either a white (65535 or 1.0) or a black (0 or 0.0) - * background to start with. - * The default constructor creates a PNGwriter instance that is 250x250, white background, - * and filename "out.png". - * Tip: The filename can be given as easily as: - * pngwriter mypng(300, 300, 0.0, "myfile.png"); - * Tip: If you are going to create a PNGwriter instance for reading in a file that already exists, - * then width and height can be 1 pixel, and the size will be automatically adjusted once you use - * readfromfile(). - * */ - pngwriter(); - pngwriter(const pngwriter &rhs); - pngwriter(int width, int height, int backgroundcolour, char * filename); - pngwriter(int width, int height, double backgroundcolour, char * filename); - pngwriter(int width, int height, int backgroundcolour, const char * filename); - pngwriter(int width, int height, double backgroundcolour, const char * filename); - - /* Destructor - * */ - ~pngwriter(); - - /* Assignment Operator - * */ - pngwriter & operator = (const pngwriter & rhs); - - /* Plot - * With this function a pixel at coordinates (x, y) can be set to the desired colour. - * The pixels are numbered starting from (1, 1) and go to (width, height). - * As with most functions in PNGwriter, it has been overloaded to accept either int arguments - * for the colour coefficients, or those of type double. If they are of type int, - * they go from 0 to 65535. If they are of type double, they go from 0.0 to 1.0. - * Tip: To plot using red, then specify plot(x, y, 1.0, 0.0, 0.0). To make pink, - * just add a constant value to all three coefficients, like this: - * plot(x, y, 1.0, 0.4, 0.4). - * Tip: If nothing is being plotted to your PNG file, make sure that you remember - * to close() the instance before your program is finished, and that the x and y position - * is actually within the bounds of your image. If either is not, then PNGwriter will - * not complain-- it is up to you to check for this! - * Tip: If you try to plot with a colour coefficient out of range, a maximum or minimum - * coefficient will be assumed, according to the given coefficient. For example, attempting - * to plot plot(x, y, 1.0,-0.2,3.7) will set the green coefficient to 0 and the red coefficient - * to 1.0. - * */ - void plot(int x, int y, int red, int green, int blue); - void plot(int x, int y, double red, double green, double blue); - - /* Plot HSV - * With this function a pixel at coordinates (x, y) can be set to the desired colour, - * but with the colour coefficients given in the Hue, Saturation, Value colourspace. - * This has the advantage that one can determine the colour that will be plotted with - * only one parameter, the Hue. The colour coefficients must go from 0 to 65535 and - * be of type int, or be of type double and go from 0.0 to 1.0. - * */ - void plotHSV(int x, int y, double hue, double saturation, double value); - void plotHSV(int x, int y, int hue, int saturation, int value); - - /* Read - * With this function we find out what colour the pixel (x, y) is. If "colour" is 1, - * it will return the red coefficient, if it is set to 2, the green one, and if - * it set to 3, the blue colour coefficient will be returned, - * and this returned value will be of type int and be between 0 and 65535. - * Note that if you call read() on a pixel outside the image range, the value returned - * will be 0. - * */ - int read(int x, int y, int colour); - - /* Read, Average - * Same as the above, only that the average of the three colour coefficients is returned. - */ - int read(int x, int y); - - /* dRead - * With this function we find out what colour the pixel (x, y) is. If "colour" is 1, - * it will return the red coefficient, if it is set to 2, the green one, and if - * it set to 3, the blue colour coefficient will be returned, - * and this returned value will be of type double and be between 0.0 and 1.0. - * Note that if you call dread() outside the image range, the value returned will be 0.0 - * */ - double dread(int x, int y, int colour); - - /* dRead, Average - * Same as the above, only that the average of the three colour coefficients is returned. - */ - double dread(int x, int y); - - /* Read HSV - * With this function we find out what colour the pixel (x, y) is, but in the Hue, - * Saturation, Value colourspace. If "colour" is 1, - * it will return the Hue coefficient, if it is set to 2, the Saturation one, and if - * it set to 3, the Value colour coefficient will be returned, and this returned - * value will be of type int and be between 0 and 65535. Important: If you attempt - * to read the Hue of a pixel that is a shade of grey, the value returned will be - * nonsensical or even NaN. This is just the way the RGB -> HSV algorithm works: - * the Hue of grey is not defined. You might want to check whether the pixel - * you are reading is grey before attempting a readHSV(). - * Tip: This is especially useful for categorizing sections of the image according - * to their colour. - * */ - int readHSV(int x, int y, int colour); - - /* dRead HSV - * With this function we find out what colour the pixel (x, y) is, but in the Hue, - * Saturation, Value colourspace. If "colour" is 1, - * it will return the Hue coefficient, if it is set to 2, the Saturation one, and if - * it set to 3, the Value colour coefficient will be returned, - * and this returned value will be of type double and be between 0.0 and 1.0. - * */ - double dreadHSV(int x, int y, int colour); - - /* Clear - * The whole image is set to black. - * */ - void clear(void); - - /* Close - * Close the instance of the class, and write the image to disk. - * Tip: If you do not call this function before your program ends, no image - * will be written to disk. - * */ - void close(void); - - /* Rename - * To rename the file once an instance of pngwriter has been created. - * Useful for assigning names to files based upon their content. - * Tip: This is as easy as calling pngwriter_rename("newname.png") - * If the argument is a long unsigned int, for example 77, the filename will be changed to - * 0000000077.png - * Tip: Use this to create sequences of images for movie generation. - * */ - void pngwriter_rename(char * newname); - void pngwriter_rename(const char * newname); - void pngwriter_rename(long unsigned int index); - - /* Figures - * These functions draw basic shapes. Available in both int and double versions. - * The line functions use the fast Bresenham algorithm. Despite the name, - * the square functions draw rectangles. The circle functions use a fast - * integer math algorithm. The filled circle functions make use of sqrt(). - * */ - void line(int xfrom, int yfrom, int xto, int yto, int red, int green,int blue); - void line(int xfrom, int yfrom, int xto, int yto, double red, double green,double blue); - - void triangle(int x1, int y1, int x2, int y2, int x3, int y3, int red, int green, int blue); - void triangle(int x1, int y1, int x2, int y2, int x3, int y3, double red, double green, double blue); - - void square(int xfrom, int yfrom, int xto, int yto, int red, int green,int blue); - void square(int xfrom, int yfrom, int xto, int yto, double red, double green,double blue); - - void filledsquare(int xfrom, int yfrom, int xto, int yto, int red, int green,int blue); - void filledsquare(int xfrom, int yfrom, int xto, int yto, double red, double green,double blue); - - void circle(int xcentre, int ycentre, int radius, int red, int green, int blue); - void circle(int xcentre, int ycentre, int radius, double red, double green, double blue); - - void filledcircle(int xcentre, int ycentre, int radius, int red, int green, int blue); - void filledcircle(int xcentre, int ycentre, int radius, double red, double green, double blue); - - - /* Read From File - * Open the existing PNG image, and copy it into this instance of the class. It is important to mention - * that PNG variants are supported. Very generally speaking, most PNG files can now be read (as of version 0.5.4), - * but if they have an alpha channel it will be completely stripped. If the PNG file uses GIF-style transparency - * (where one colour is chosen to be transparent), PNGwriter will not read the image properly, but will not - * complain. Also, if any ancillary chunks are included in the PNG file (chroma, filter, etc.), it will render - * with a slightly different tonality. For the vast majority of PNGs, this should not be an issue. Note: - * If you read an 8-bit PNG, the internal representation of that instance of PNGwriter will be 8-bit (PNG - * files of less than 8 bits will be upscaled to 8 bits). To convert it to 16-bit, just loop over all pixels, - * reading them into a new instance of PNGwriter. New instances of PNGwriter are 16-bit by default. - * */ - - void readfromfile(char * name); - void readfromfile(const char * name); - - /* Get Height - * When you open a PNG with readfromfile() you can find out its height with this function. - * */ - int getheight(void); - - /* Get Width - * When you open a PNG with readfromfile() you can find out its width with this function. - * */ - int getwidth(void); - - /* Set Compression Level - * Set the compression level that will be used for the image. -1 is to use the default, - * 0 is none, 9 is best compression. - * Remember that this will affect how long it will take to close() the image. A value of 2 or 3 - * is good enough for regular use, but for storage or transmission you might want to take the time - * to set it at 9. - * */ - void setcompressionlevel(int level); - - /* Get Bit Depth - * When you open a PNG with readfromfile() you can find out its bit depth with this function. - * Mostly for troubleshooting uses. - * */ - int getbitdepth(void); - - /* Get Colour Type - * When you open a PNG with readfromfile() you can find out its colour type (libpng categorizes - * different styles of image data with this number). - * Mostly for troubleshooting uses. - * */ - int getcolortype(void); - - /* Set Gamma Coeff - * Set the image's gamma (file gamma) coefficient. This is experimental, but use it if your image's colours seem too bright - * or too dark. The default value of 0.5 should be fine. The standard disclaimer about Mac and PC gamma - * settings applies. - * */ - void setgamma(double gamma); - - - /* Get Gamma Coeff - * Get the image's gamma coefficient. This is experimental. - * */ - double getgamma(void); - - /* Bezier Curve - * (After Frenchman Pierre BŽzier from Regie Renault) - * A collection of formulae for describing curved lines - * and surfaces, first used in 1972 to model automobile surfaces. - * (from the The Free On-line Dictionary of Computing) - * See http://www.moshplant.com/direct-or/bezier/ for one of many - * available descriptions of bezier curves. - * There are four points used to define the curve: the two endpoints - * of the curve are called the anchor points, while the other points, - * which define the actual curvature, are called handles or control points. - * Moving the handles lets you modify the shape of the curve. - * */ - - void bezier( int startPtX, int startPtY, - int startControlX, int startControlY, - int endPtX, int endPtY, - int endControlX, int endControlY, - double red, double green, double blue); - - void bezier( int startPtX, int startPtY, - int startControlX, int startControlY, - int endPtX, int endPtY, - int endControlX, int endControlY, - int red, int green, int blue); - - /* Set Text - * Sets the text information in the PNG header. If it is not called, the default is used. - */ - void settext(char * title, char * author, char * description, char * software); - void settext(const char * title, const char * author, const char * description, const char * software); - - - /* Version Number - * Returns the PNGwriter version number. - */ - static double version(void); - - /* Write PNG - * Writes the PNG image to disk. You can still change the PNGwriter instance after this. - * Tip: This is exactly the same as close(), but easier to remember. - * Tip: To make a sequence of images using only one instance of PNGwriter, alter the image, change its name, - * write_png(), then alter the image, change its name, write_png(), etc. - */ - void write_png(void); - - /* Plot Text - * Uses the Freetype2 library to set text in the image. face_path is the file path to a - * TrueType font file (.ttf) (FreeType2 can also handle other types). fontsize specifices the approximate - * height of the rendered font in pixels. x_start and y_start specify the placement of the - * lower, left corner of the text string. angle is the text angle in radians. text is the text to be rendered. - * The colour coordinates can be doubles from 0.0 to 1.0 or ints from 0 to 65535. - * Tip: PNGwriter installs a few fonts in /usr/local/share/pngwriter/fonts to get you started. - * Tip: Remember to add -DNO_FREETYPE to your compilation flags if PNGwriter was compiled without FreeType support. - * */ - void plot_text(char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double red, double green, double blue); - void plot_text(char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, int red, int green, int blue); - - - /* Plot UTF-8 Text - * Same as the above, but the text to be plotted is encoded in UTF-8. Why would you want this? To be able to plot - * all characters available in a large TrueType font, for example: for rendering Japenese, Chinese and other - * languages not restricted to the standard 128 character ASCII space. - * Tip: The quickest way to get a string into UTF-8 is to write it in an adequate text editor, and save it as a file - * in UTF-8 encoding, which can then be read in in binary mode. - * */ - void plot_text_utf8(char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double red, double green, double blue); - void plot_text_utf8(char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, int red, int green, int blue); - - - /* Bilinear Interpolation of Image - * Given a floating point coordinate (x from 0.0 to width, y from 0.0 to height), - * this function will return the interpolated colour intensity specified by - * colour (where red = 1, green = 2, blue = 3). - * bilinear_interpolate_read() returns an int from 0 to 65535, and - * bilinear_interpolate_dread() returns a double from 0.0 to 1.0. - * Tip: Especially useful for enlarging an image. - * */ - int bilinear_interpolation_read(double x, double y, int colour); - double bilinear_interpolation_dread(double x, double y, int colour); - - /* Plot Blend - * Plots the colour given by red, green blue, but blended with the existing pixel - * value at that position. opacity is a double that goes from 0.0 to 1.0. - * 0.0 will not change the pixel at all, and 1.0 will plot the given colour. - * Anything in between will be a blend of both pixel levels. Please note: This is neither + /* The algorithms HSVtoRGB and RGBtoHSV were found at http://www.cs.rit.edu/~ncs/ + * which is a page that belongs to Nan C. Schaller, though + * these algorithms appear to be the work of Eugene Vishnevsky. + * */ + void HSVtoRGB(double* r, double* g, double* b, double h, double s, double v); + void RGBtoHSV(float r, float g, float b, float* h, float* s, float* v); + + /* drwatop(), drawbottom() and filledtriangle() were contributed by Gurkan Sengun + * ( , http://www.linuks.mine.nu/ ) + * */ + void drawtop(long x1,long y1,long x2,long y2,long x3, int red, int green, int blue); + void drawbottom(long x1,long y1,long x2,long x3,long y3, int red, int green, int blue); + void drawbottom_blend(long x1,long y1,long x2,long x3,long y3, double opacity, int red, int green, int blue); + void drawtop_blend(long x1,long y1,long x2,long y2,long x3, double opacity, int red, int green, int blue); + +public: + + /* General Notes + * It is important to remember that all functions that accept an argument of type "const char *" will also + * accept "char *", this is done so you can have a changing filename (to make many PNG images in series + * with a different name, for example), and to allow you to use string type objects which can be easily + * turned into const char * (if theString is an object of type string, then it can be used as a const char * + * by saying theString.c_str()). + * It is also important to remember that whenever a function has a colour coeffiecient as its argument, + * that argument can be either an int from 0 to 65535 or a double from 0.0 to 1.0. + * It is important to make sure that you are calling the function with the type that you want. + * Remember that 1 is an int, while 1.0 is a double, and will thus determine what version of the function + * will be used. Similarly, do not make the mistake of calling for example plot(x, y, 0.0, 0.0, 65535), + * because + * there is no plot(int, int, double, double, int). + * Also, please note that plot() and read() (and the functions that use them internally) + * are protected against entering, for example, a colour coefficient that is over 65535 + * or over 1.0. Similarly, they are protected against negative coefficients. read() will return 0 + * when called outside the image range. This is actually useful as zero-padding should you need it. + * */ + + /* Compilation + * A typical compilation would look like this: + * + * g++ my_program.cc -o my_program freetype-config --cflags \ + * -I/usr/local/include -L/usr/local/lib -lpng -lpngwriter -lz -lfreetype + * + * If you did not compile PNGwriter with FreeType support, then remove the + * FreeType-related flags and add -DNO_FREETYPE above. + * */ + + /* Constructor + * The constructor requires the width and the height of the image, the background colour for the + * image and the filename of the file (a pointer or simple "myfile.png"). The background colour + * can only be initialized to a shade of grey (once the object has been created you can do whatever + * you want, though), because generally one wants either a white (65535 or 1.0) or a black (0 or 0.0) + * background to start with. + * The default constructor creates a PNGwriter instance that is 250x250, white background, + * and filename "out.png". + * Tip: The filename can be given as easily as: + * pngwriter mypng(300, 300, 0.0, "myfile.png"); + * Tip: If you are going to create a PNGwriter instance for reading in a file that already exists, + * then width and height can be 1 pixel, and the size will be automatically adjusted once you use + * readfromfile(). + * */ + pngwriter(); + pngwriter(const pngwriter& rhs); + pngwriter(int width, int height, int backgroundcolour, char* filename); + pngwriter(int width, int height, double backgroundcolour, char* filename); + pngwriter(int width, int height, int backgroundcolour, const char* filename); + pngwriter(int width, int height, double backgroundcolour, const char* filename); + + /* Destructor + * */ + ~pngwriter(); + + /* Assignment Operator + * */ + pngwriter& operator = (const pngwriter& rhs); + + /* Plot + * With this function a pixel at coordinates (x, y) can be set to the desired colour. + * The pixels are numbered starting from (1, 1) and go to (width, height). + * As with most functions in PNGwriter, it has been overloaded to accept either int arguments + * for the colour coefficients, or those of type double. If they are of type int, + * they go from 0 to 65535. If they are of type double, they go from 0.0 to 1.0. + * Tip: To plot using red, then specify plot(x, y, 1.0, 0.0, 0.0). To make pink, + * just add a constant value to all three coefficients, like this: + * plot(x, y, 1.0, 0.4, 0.4). + * Tip: If nothing is being plotted to your PNG file, make sure that you remember + * to close() the instance before your program is finished, and that the x and y position + * is actually within the bounds of your image. If either is not, then PNGwriter will + * not complain-- it is up to you to check for this! + * Tip: If you try to plot with a colour coefficient out of range, a maximum or minimum + * coefficient will be assumed, according to the given coefficient. For example, attempting + * to plot plot(x, y, 1.0,-0.2,3.7) will set the green coefficient to 0 and the red coefficient + * to 1.0. + * */ + void plot(int x, int y, int red, int green, int blue); + void plot(int x, int y, double red, double green, double blue); + + /* Plot HSV + * With this function a pixel at coordinates (x, y) can be set to the desired colour, + * but with the colour coefficients given in the Hue, Saturation, Value colourspace. + * This has the advantage that one can determine the colour that will be plotted with + * only one parameter, the Hue. The colour coefficients must go from 0 to 65535 and + * be of type int, or be of type double and go from 0.0 to 1.0. + * */ + void plotHSV(int x, int y, double hue, double saturation, double value); + void plotHSV(int x, int y, int hue, int saturation, int value); + + /* Read + * With this function we find out what colour the pixel (x, y) is. If "colour" is 1, + * it will return the red coefficient, if it is set to 2, the green one, and if + * it set to 3, the blue colour coefficient will be returned, + * and this returned value will be of type int and be between 0 and 65535. + * Note that if you call read() on a pixel outside the image range, the value returned + * will be 0. + * */ + int read(int x, int y, int colour); + + /* Read, Average + * Same as the above, only that the average of the three colour coefficients is returned. + */ + int read(int x, int y); + + /* dRead + * With this function we find out what colour the pixel (x, y) is. If "colour" is 1, + * it will return the red coefficient, if it is set to 2, the green one, and if + * it set to 3, the blue colour coefficient will be returned, + * and this returned value will be of type double and be between 0.0 and 1.0. + * Note that if you call dread() outside the image range, the value returned will be 0.0 + * */ + double dread(int x, int y, int colour); + + /* dRead, Average + * Same as the above, only that the average of the three colour coefficients is returned. + */ + double dread(int x, int y); + + /* Read HSV + * With this function we find out what colour the pixel (x, y) is, but in the Hue, + * Saturation, Value colourspace. If "colour" is 1, + * it will return the Hue coefficient, if it is set to 2, the Saturation one, and if + * it set to 3, the Value colour coefficient will be returned, and this returned + * value will be of type int and be between 0 and 65535. Important: If you attempt + * to read the Hue of a pixel that is a shade of grey, the value returned will be + * nonsensical or even NaN. This is just the way the RGB -> HSV algorithm works: + * the Hue of grey is not defined. You might want to check whether the pixel + * you are reading is grey before attempting a readHSV(). + * Tip: This is especially useful for categorizing sections of the image according + * to their colour. + * */ + int readHSV(int x, int y, int colour); + + /* dRead HSV + * With this function we find out what colour the pixel (x, y) is, but in the Hue, + * Saturation, Value colourspace. If "colour" is 1, + * it will return the Hue coefficient, if it is set to 2, the Saturation one, and if + * it set to 3, the Value colour coefficient will be returned, + * and this returned value will be of type double and be between 0.0 and 1.0. + * */ + double dreadHSV(int x, int y, int colour); + + /* Clear + * The whole image is set to black. + * */ + void clear(void); + + /* Close + * Close the instance of the class, and write the image to disk. + * Tip: If you do not call this function before your program ends, no image + * will be written to disk. + * */ + void close(void); + + /* Rename + * To rename the file once an instance of pngwriter has been created. + * Useful for assigning names to files based upon their content. + * Tip: This is as easy as calling pngwriter_rename("newname.png") + * If the argument is a long unsigned int, for example 77, the filename will be changed to + * 0000000077.png + * Tip: Use this to create sequences of images for movie generation. + * */ + void pngwriter_rename(char* newname); + void pngwriter_rename(const char* newname); + void pngwriter_rename(long unsigned int index); + + /* Figures + * These functions draw basic shapes. Available in both int and double versions. + * The line functions use the fast Bresenham algorithm. Despite the name, + * the square functions draw rectangles. The circle functions use a fast + * integer math algorithm. The filled circle functions make use of sqrt(). + * */ + void line(int xfrom, int yfrom, int xto, int yto, int red, int green,int blue); + void line(int xfrom, int yfrom, int xto, int yto, double red, double green,double blue); + + void triangle(int x1, int y1, int x2, int y2, int x3, int y3, int red, int green, int blue); + void triangle(int x1, int y1, int x2, int y2, int x3, int y3, double red, double green, double blue); + + void square(int xfrom, int yfrom, int xto, int yto, int red, int green,int blue); + void square(int xfrom, int yfrom, int xto, int yto, double red, double green,double blue); + + void filledsquare(int xfrom, int yfrom, int xto, int yto, int red, int green,int blue); + void filledsquare(int xfrom, int yfrom, int xto, int yto, double red, double green,double blue); + + void circle(int xcentre, int ycentre, int radius, int red, int green, int blue); + void circle(int xcentre, int ycentre, int radius, double red, double green, double blue); + + void filledcircle(int xcentre, int ycentre, int radius, int red, int green, int blue); + void filledcircle(int xcentre, int ycentre, int radius, double red, double green, double blue); + + + /* Read From File + * Open the existing PNG image, and copy it into this instance of the class. It is important to mention + * that PNG variants are supported. Very generally speaking, most PNG files can now be read (as of version 0.5.4), + * but if they have an alpha channel it will be completely stripped. If the PNG file uses GIF-style transparency + * (where one colour is chosen to be transparent), PNGwriter will not read the image properly, but will not + * complain. Also, if any ancillary chunks are included in the PNG file (chroma, filter, etc.), it will render + * with a slightly different tonality. For the vast majority of PNGs, this should not be an issue. Note: + * If you read an 8-bit PNG, the internal representation of that instance of PNGwriter will be 8-bit (PNG + * files of less than 8 bits will be upscaled to 8 bits). To convert it to 16-bit, just loop over all pixels, + * reading them into a new instance of PNGwriter. New instances of PNGwriter are 16-bit by default. + * */ + + void readfromfile(char* name); + void readfromfile(const char* name); + + /* Get Height + * When you open a PNG with readfromfile() you can find out its height with this function. + * */ + int getheight(void); + + /* Get Width + * When you open a PNG with readfromfile() you can find out its width with this function. + * */ + int getwidth(void); + + /* Set Compression Level + * Set the compression level that will be used for the image. -1 is to use the default, + * 0 is none, 9 is best compression. + * Remember that this will affect how long it will take to close() the image. A value of 2 or 3 + * is good enough for regular use, but for storage or transmission you might want to take the time + * to set it at 9. + * */ + void setcompressionlevel(int level); + + /* Get Bit Depth + * When you open a PNG with readfromfile() you can find out its bit depth with this function. + * Mostly for troubleshooting uses. + * */ + int getbitdepth(void); + + /* Get Colour Type + * When you open a PNG with readfromfile() you can find out its colour type (libpng categorizes + * different styles of image data with this number). + * Mostly for troubleshooting uses. + * */ + int getcolortype(void); + + /* Set Gamma Coeff + * Set the image's gamma (file gamma) coefficient. This is experimental, but use it if your image's colours seem too bright + * or too dark. The default value of 0.5 should be fine. The standard disclaimer about Mac and PC gamma + * settings applies. + * */ + void setgamma(double gamma); + + + /* Get Gamma Coeff + * Get the image's gamma coefficient. This is experimental. + * */ + double getgamma(void); + + /* Bezier Curve + * (After Frenchman Pierre BŽzier from Regie Renault) + * A collection of formulae for describing curved lines + * and surfaces, first used in 1972 to model automobile surfaces. + * (from the The Free On-line Dictionary of Computing) + * See http://www.moshplant.com/direct-or/bezier/ for one of many + * available descriptions of bezier curves. + * There are four points used to define the curve: the two endpoints + * of the curve are called the anchor points, while the other points, + * which define the actual curvature, are called handles or control points. + * Moving the handles lets you modify the shape of the curve. + * */ + + void bezier(int startPtX, int startPtY, + int startControlX, int startControlY, + int endPtX, int endPtY, + int endControlX, int endControlY, + double red, double green, double blue); + + void bezier(int startPtX, int startPtY, + int startControlX, int startControlY, + int endPtX, int endPtY, + int endControlX, int endControlY, + int red, int green, int blue); + + /* Set Text + * Sets the text information in the PNG header. If it is not called, the default is used. + */ + void settext(char* title, char* author, char* description, char* software); + void settext(const char* title, const char* author, const char* description, const char* software); + + + /* Version Number + * Returns the PNGwriter version number. + */ + static double version(void); + + /* Write PNG + * Writes the PNG image to disk. You can still change the PNGwriter instance after this. + * Tip: This is exactly the same as close(), but easier to remember. + * Tip: To make a sequence of images using only one instance of PNGwriter, alter the image, change its name, + * write_png(), then alter the image, change its name, write_png(), etc. + */ + void write_png(void); + + /* Plot Text + * Uses the Freetype2 library to set text in the image. face_path is the file path to a + * TrueType font file (.ttf) (FreeType2 can also handle other types). fontsize specifices the approximate + * height of the rendered font in pixels. x_start and y_start specify the placement of the + * lower, left corner of the text string. angle is the text angle in radians. text is the text to be rendered. + * The colour coordinates can be doubles from 0.0 to 1.0 or ints from 0 to 65535. + * Tip: PNGwriter installs a few fonts in /usr/local/share/pngwriter/fonts to get you started. + * Tip: Remember to add -DNO_FREETYPE to your compilation flags if PNGwriter was compiled without FreeType support. + * */ + void plot_text(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, double red, double green, double blue); + void plot_text(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, int red, int green, int blue); + + + /* Plot UTF-8 Text + * Same as the above, but the text to be plotted is encoded in UTF-8. Why would you want this? To be able to plot + * all characters available in a large TrueType font, for example: for rendering Japenese, Chinese and other + * languages not restricted to the standard 128 character ASCII space. + * Tip: The quickest way to get a string into UTF-8 is to write it in an adequate text editor, and save it as a file + * in UTF-8 encoding, which can then be read in in binary mode. + * */ + void plot_text_utf8(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, double red, double green, double blue); + void plot_text_utf8(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, int red, int green, int blue); + + + /* Bilinear Interpolation of Image + * Given a floating point coordinate (x from 0.0 to width, y from 0.0 to height), + * this function will return the interpolated colour intensity specified by + * colour (where red = 1, green = 2, blue = 3). + * bilinear_interpolate_read() returns an int from 0 to 65535, and + * bilinear_interpolate_dread() returns a double from 0.0 to 1.0. + * Tip: Especially useful for enlarging an image. + * */ + int bilinear_interpolation_read(double x, double y, int colour); + double bilinear_interpolation_dread(double x, double y, int colour); + + /* Plot Blend + * Plots the colour given by red, green blue, but blended with the existing pixel + * value at that position. opacity is a double that goes from 0.0 to 1.0. + * 0.0 will not change the pixel at all, and 1.0 will plot the given colour. + * Anything in between will be a blend of both pixel levels. Please note: This is neither * alpha channel nor PNG transparency chunk support. This merely blends the plotted pixels. - * */ - - void plot_blend(int x, int y, double opacity, int red, int green, int blue); - void plot_blend(int x, int y, double opacity, double red, double green, double blue); - - - /* Invert - * Inverts the image in RGB colourspace. - * */ - void invert(void); - - /* Resize Image - * Resizes the PNGwriter instance. Note: All image data is set to black (this is - * a resizing, not a scaling, of the image). - * */ - void resize(int width, int height); - - /* Boundary Fill - * All pixels adjacent to the start pixel will be filled with the fill colour, until the boundary colour is encountered. - * For example, calling boundary_fill() with the boundary colour set to red, on a pixel somewhere inside a red circle, - * will fill the entire circle with the desired fill colour. If, on the other hand, the circle is not the boundary colour, - * the rest of the image will be filled. - * The colour components are either doubles from 0.0 to 1.0 or ints from 0 to 65535. - * */ - void boundary_fill(int xstart, int ystart, double boundary_red,double boundary_green,double boundary_blue,double fill_red, double fill_green, double fill_blue) ; - void boundary_fill(int xstart, int ystart, int boundary_red,int boundary_green,int boundary_blue,int fill_red, int fill_green, int fill_blue) ; - - /* Flood Fill - * All pixels adjacent to the start pixel will be filled with the fill colour, if they are the same colour as the - * start pixel. For example, calling flood_fill() somewhere in the interior of a solid blue rectangle will colour - * the entire rectangle the fill colour. The colour components are either doubles from 0.0 to 1.0 or ints from 0 to 65535. - * */ - void flood_fill(int xstart, int ystart, double fill_red, double fill_green, double fill_blue) ; - void flood_fill(int xstart, int ystart, int fill_red, int fill_green, int fill_blue) ; - - /* Polygon - * This function takes an array of integer values containing the coordinates of the vertexes of a polygon. - * Note that if you want a closed polygon, you must repeat the first point's coordinates for the last point. - * It also requires the number of points contained in the array. For example, if you wish to plot a triangle, - * the array will contain 6 elements, and the number of points is 3. Be very careful about this; if you specify the wrong number - * of points, your program will either segfault or produce points at nonsensical coordinates. - * The colour components are either doubles from 0.0 to 1.0 or ints from 0 to 65535. - * */ - void polygon(int * points, int number_of_points, double red, double green, double blue); - void polygon(int * points, int number_of_points, int red, int green, int blue); - - /* Plot CMYK - * Plot a point in the Cyan, Magenta, Yellow, Black colourspace. Please note that this colourspace is - * lossy, i.e. it cannot reproduce all colours on screen that RGB can. The difference, however, is - * barely noticeable. The algorithm used is a standard one. The colour components are either - * doubles from 0.0 to 1.0 or ints from 0 to 65535. - * */ - void plotCMYK(int x, int y, double cyan, double magenta, double yellow, double black); - void plotCMYK(int x, int y, int cyan, int magenta, int yellow, int black); - - /* Read CMYK, Double version - * Get a pixel in the Cyan, Magenta, Yellow, Black colourspace. if 'colour' is 1, the Cyan component will be returned - * as a double from 0.0 to 1.0. If 'colour is 2, the Magenta colour component will be returned, and so on, up to 4. - * */ - double dreadCMYK(int x, int y, int colour); - - /* Read CMYK - * Same as the above, but the colour components returned are an int from 0 to 65535. - * */ - int readCMYK(int x, int y, int colour); - - /* Scale Proportional - * Scale the image using bilinear interpolation. If k is greater than 1.0, the image will be enlarged. - * If k is less than 1.0, the image will be shrunk. Negative or null values of k are not allowed. - * The image will be resized and the previous content will be replaced by the scaled image. - * Tip: use getheight() and getwidth() to find out the new width and height of the scaled image. - * Note: After scaling, all images will have a bit depth of 16, even if the original image had - * a bit depth of 8. - * */ - void scale_k(double k); - - /* Scale Non-Proportional - * Scale the image using bilinear interpolation, with different horizontal and vertical scale factors. - * */ - void scale_kxky(double kx, double ky); - - /* Scale To Target Width and Height - * Scale the image in such a way as to meet the target width and height. - * Tip: if you want to keep the image proportional, scale_k() might be more appropriate. - * */ - void scale_wh(int finalwidth, int finalheight); - - - /* Blended Functions - * All these functions are identical to their non-blended types. They take an extra argument, opacity, which is - * a double from 0.0 to 1.0 and represents how much of the original pixel value is retained when plotting the - * new pixel. In other words, if opacity is 0.7, then after plotting, the new pixel will be 30% of the - * original colour the pixel was, and 70% of the new colour, whatever that may be. As usual, each function - * is available in int or double versions. Please note: This is neither alpha channel nor PNG transparency chunk support. This merely blends the plotted pixels. - * */ - - // Start Blended Functions - - void plotHSV_blend(int x, int y, double opacity, double hue, double saturation, double value); - void plotHSV_blend(int x, int y, double opacity, int hue, int saturation, int value); - - void line_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue); - void line_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue); - - void square_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue); - void square_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue); - - void filledsquare_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue); - void filledsquare_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue); - - void circle_blend(int xcentre, int ycentre, int radius, double opacity, int red, int green, int blue); - void circle_blend(int xcentre, int ycentre, int radius, double opacity, double red, double green, double blue); - - void filledcircle_blend(int xcentre, int ycentre, int radius, double opacity, int red, int green, int blue); - void filledcircle_blend(int xcentre, int ycentre, int radius, double opacity, double red, double green, double blue); - - void bezier_blend( int startPtX, int startPtY, - int startControlX, int startControlY, - int endPtX, int endPtY, - int endControlX, int endControlY, - double opacity, - double red, double green, double blue); - - void bezier_blend( int startPtX, int startPtY, - int startControlX, int startControlY, - int endPtX, int endPtY, - int endControlX, int endControlY, - double opacity, - int red, int green, int blue); - - void plot_text_blend(char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, double red, double green, double blue); - void plot_text_blend(char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, int red, int green, int blue); - - void plot_text_utf8_blend(char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, double red, double green, double blue); - void plot_text_utf8_blend(char * face_path, int fontsize, int x_start, int y_start, double angle, char * text, double opacity, int red, int green, int blue); - - void boundary_fill_blend(int xstart, int ystart, double opacity, double boundary_red,double boundary_green,double boundary_blue,double fill_red, double fill_green, double fill_blue) ; - void boundary_fill_blend(int xstart, int ystart, double opacity, int boundary_red,int boundary_green,int boundary_blue,int fill_red, int fill_green, int fill_blue) ; - - void flood_fill_blend(int xstart, int ystart, double opacity, double fill_red, double fill_green, double fill_blue) ; - void flood_fill_blend(int xstart, int ystart, double opacity, int fill_red, int fill_green, int fill_blue) ; - - void polygon_blend(int * points, int number_of_points, double opacity, double red, double green, double blue); - void polygon_blend(int * points, int number_of_points, double opacity, int red, int green, int blue); - - void plotCMYK_blend(int x, int y, double opacity, double cyan, double magenta, double yellow, double black); - void plotCMYK_blend(int x, int y, double opacity, int cyan, int magenta, int yellow, int black); - - // End of Blended Functions - - /* Laplacian - * This function applies a discrete laplacian to the image, multiplied by a constant factor. - * The kernel used in this case is: - * 1.0 1.0 1.0 - * 1.0 -8.0 1.0 - * 1.0 1.0 1.0 - * Basically, this works as an edge detector. The current pixel is assigned the sum of all neighbouring - * pixels, multiplied by the corresponding kernel element. For example, imagine a pixel and its 8 neighbours: - * 1.0 1.0 0.0 0.0 - * 1.0 ->1.0<- 0.0 0.0 - * 1.0 1.0 0.0 0.0 - * This represents a border between white and black, black is on the right. Applying the laplacian to - * the pixel specified above pixel gives: - * 1.0*1.0 + 1.0*1.0 + 0.0*1.0 + - * 1.0*1.0 + 1.0*-8.0 + 0.0*1.0 + - * 1.0*1.0 + 1.0*1.0 + 0.0*1.0 = -3.0 - * Applying this to the pixel to the right of the pixel considered previously, we get a sum of 3.0. - * That is, after passing over an edge, we get a high value for the pixel adjacent to the edge. Since - * PNGwriter limits the colour components if they are off-scale, and the result of the laplacian - * may be negative, a scale factor and an offset value are included. This might be useful for - * keeping things within range or for bringing out more detail in the edge detection. The - * final pixel value will be given by: - * final value = laplacian(original pixel)*k + offset - * Tip: Try a value of 1.0 for k to start with, and then experiment with other values. - * */ - void laplacian(double k, double offset); - - /* Filled Triangle - * Draws the triangle specified by the three pairs of points in the colour specified - * by the colour coefficients. The colour components are either doubles from 0.0 to - * 1.0 or ints from 0 to 65535. - * */ - void filledtriangle(int x1,int y1,int x2,int y2,int x3,int y3, int red, int green, int blue); - void filledtriangle(int x1,int y1,int x2,int y2,int x3,int y3, double red, double green, double blue); - - /* Filled Triangle, Blended - * Draws the triangle specified by the three pairs of points in the colour specified - * by the colour coefficients, and blended with the background. See the description for Blended Functions. - * The colour components are either doubles from 0.0 to 1.0 or ints from 0 to 65535. - * */ - void filledtriangle_blend(int x1,int y1,int x2,int y2,int x3,int y3, double opacity, int red, int green, int blue); - void filledtriangle_blend(int x1,int y1,int x2,int y2,int x3,int y3, double opacity, double red, double green, double blue); - - /* Arrow, Filled Arrow - * Plots an arrow from (x1, y1) to (x2, y2) with the arrowhead at the second point, given the size in pixels - * and the angle in radians of the arrowhead. The plotted arrow consists of one main line, and two smaller - * lines originating from the second point. Filled Arrow plots the same, but the arrowhead is a solid triangle. - * Tip: An angle of 10 to 30 degrees looks OK. - * */ - - void arrow( int x1,int y1,int x2,int y2,int size, double head_angle, double red, double green, double blue); - void arrow( int x1,int y1,int x2,int y2,int size, double head_angle, int red, int green, int blue); - - void filledarrow( int x1,int y1,int x2,int y2,int size, double head_angle, double red, double green, double blue); - void filledarrow( int x1,int y1,int x2,int y2,int size, double head_angle, int red, int green, int blue); - - /* Cross, Maltese Cross - * Plots a simple cross at x, y, with the specified height and width, and in the specified colour. - * Maltese cross plots a cross, as before, but adds bars at the end of each arm of the cross. - * The size of these bars is specified with x_bar_height and y_bar_width. - * The cross will look something like this: - * - * ----- <-- ( y_bar_width) - * | - * | - * |-------| <-- ( x_bar_height ) - * | - * | - * ----- - * */ - - void cross( int x, int y, int xwidth, int yheight, double red, double green, double blue); - void cross( int x, int y, int xwidth, int yheight, int red, int green, int blue); - - void maltesecross( int x, int y, int xwidth, int yheight, int x_bar_height, int y_bar_width, double red, double green, double blue); - void maltesecross( int x, int y, int xwidth, int yheight, int x_bar_height, int y_bar_width, int red, int green, int blue); - - /* Diamond and filled diamond - * Plots a diamond shape, given the x, y position, the width and height, and the colour. - * Filled diamond plots a filled diamond. - * */ - - void filleddiamond( int x, int y, int width, int height, int red, int green, int blue); - void diamond(int x, int y, int width, int height, int red, int green, int blue); - - void filleddiamond( int x, int y, int width, int height, double red, double green, double blue); - void diamond(int x, int y, int width, int height, double red, double green, double blue); - - /* Get Text Width, Get Text Width UTF8 - * Returns the approximate width, in pixels, of the specified *unrotated* text. It is calculated by adding - * each letter's width and kerning value (as specified in the TTF file). Note that this will not - * give the position of the farthest pixel, but it will give a pretty good idea of what area the - * text will occupy. Tip: The text, when plotted unrotated, will fit approximately in a box with its lower left corner at - * (x_start, y_start) and upper right at (x_start + width, y_start + size), where width is given by get_text_width() - * and size is the specified size of the text to be plotted. Tip: Text plotted at position - * (x_start, y_start), rotated with a given 'angle', and of a given 'size' - * whose width is 'width', will fit approximately inside a rectangle whose corners are at - * 1 (x_start, y_start) - * 2 (x_start + width*cos(angle), y_start + width*sin(angle)) - * 3 (x_start + width*cos(angle) - size*sin(angle), y_start + width*sin(angle) + size*cos(angle)) - * 4 (x_start - size*sin(angle), y_start + size*cos(angle)) - * */ - - int get_text_width(char * face_path, int fontsize, char * text); - - int get_text_width_utf8(char * face_path, int fontsize, char * text); + * */ + + void plot_blend(int x, int y, double opacity, int red, int green, int blue); + void plot_blend(int x, int y, double opacity, double red, double green, double blue); + + + /* Invert + * Inverts the image in RGB colourspace. + * */ + void invert(void); + + /* Resize Image + * Resizes the PNGwriter instance. Note: All image data is set to black (this is + * a resizing, not a scaling, of the image). + * */ + void resize(int width, int height); + + /* Boundary Fill + * All pixels adjacent to the start pixel will be filled with the fill colour, until the boundary colour is encountered. + * For example, calling boundary_fill() with the boundary colour set to red, on a pixel somewhere inside a red circle, + * will fill the entire circle with the desired fill colour. If, on the other hand, the circle is not the boundary colour, + * the rest of the image will be filled. + * The colour components are either doubles from 0.0 to 1.0 or ints from 0 to 65535. + * */ + void boundary_fill(int xstart, int ystart, double boundary_red,double boundary_green,double boundary_blue,double fill_red, double fill_green, double fill_blue) ; + void boundary_fill(int xstart, int ystart, int boundary_red,int boundary_green,int boundary_blue,int fill_red, int fill_green, int fill_blue) ; + + /* Flood Fill + * All pixels adjacent to the start pixel will be filled with the fill colour, if they are the same colour as the + * start pixel. For example, calling flood_fill() somewhere in the interior of a solid blue rectangle will colour + * the entire rectangle the fill colour. The colour components are either doubles from 0.0 to 1.0 or ints from 0 to 65535. + * */ + void flood_fill(int xstart, int ystart, double fill_red, double fill_green, double fill_blue) ; + void flood_fill(int xstart, int ystart, int fill_red, int fill_green, int fill_blue) ; + + /* Polygon + * This function takes an array of integer values containing the coordinates of the vertexes of a polygon. + * Note that if you want a closed polygon, you must repeat the first point's coordinates for the last point. + * It also requires the number of points contained in the array. For example, if you wish to plot a triangle, + * the array will contain 6 elements, and the number of points is 3. Be very careful about this; if you specify the wrong number + * of points, your program will either segfault or produce points at nonsensical coordinates. + * The colour components are either doubles from 0.0 to 1.0 or ints from 0 to 65535. + * */ + void polygon(int* points, int number_of_points, double red, double green, double blue); + void polygon(int* points, int number_of_points, int red, int green, int blue); + + /* Plot CMYK + * Plot a point in the Cyan, Magenta, Yellow, Black colourspace. Please note that this colourspace is + * lossy, i.e. it cannot reproduce all colours on screen that RGB can. The difference, however, is + * barely noticeable. The algorithm used is a standard one. The colour components are either + * doubles from 0.0 to 1.0 or ints from 0 to 65535. + * */ + void plotCMYK(int x, int y, double cyan, double magenta, double yellow, double black); + void plotCMYK(int x, int y, int cyan, int magenta, int yellow, int black); + + /* Read CMYK, Double version + * Get a pixel in the Cyan, Magenta, Yellow, Black colourspace. if 'colour' is 1, the Cyan component will be returned + * as a double from 0.0 to 1.0. If 'colour is 2, the Magenta colour component will be returned, and so on, up to 4. + * */ + double dreadCMYK(int x, int y, int colour); + + /* Read CMYK + * Same as the above, but the colour components returned are an int from 0 to 65535. + * */ + int readCMYK(int x, int y, int colour); + + /* Scale Proportional + * Scale the image using bilinear interpolation. If k is greater than 1.0, the image will be enlarged. + * If k is less than 1.0, the image will be shrunk. Negative or null values of k are not allowed. + * The image will be resized and the previous content will be replaced by the scaled image. + * Tip: use getheight() and getwidth() to find out the new width and height of the scaled image. + * Note: After scaling, all images will have a bit depth of 16, even if the original image had + * a bit depth of 8. + * */ + void scale_k(double k); + + /* Scale Non-Proportional + * Scale the image using bilinear interpolation, with different horizontal and vertical scale factors. + * */ + void scale_kxky(double kx, double ky); + + /* Scale To Target Width and Height + * Scale the image in such a way as to meet the target width and height. + * Tip: if you want to keep the image proportional, scale_k() might be more appropriate. + * */ + void scale_wh(int finalwidth, int finalheight); + + + /* Blended Functions + * All these functions are identical to their non-blended types. They take an extra argument, opacity, which is + * a double from 0.0 to 1.0 and represents how much of the original pixel value is retained when plotting the + * new pixel. In other words, if opacity is 0.7, then after plotting, the new pixel will be 30% of the + * original colour the pixel was, and 70% of the new colour, whatever that may be. As usual, each function + * is available in int or double versions. Please note: This is neither alpha channel nor PNG transparency chunk support. This merely blends the plotted pixels. + * */ + + // Start Blended Functions + + void plotHSV_blend(int x, int y, double opacity, double hue, double saturation, double value); + void plotHSV_blend(int x, int y, double opacity, int hue, int saturation, int value); + + void line_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue); + void line_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue); + + void square_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue); + void square_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue); + + void filledsquare_blend(int xfrom, int yfrom, int xto, int yto, double opacity, int red, int green,int blue); + void filledsquare_blend(int xfrom, int yfrom, int xto, int yto, double opacity, double red, double green,double blue); + + void circle_blend(int xcentre, int ycentre, int radius, double opacity, int red, int green, int blue); + void circle_blend(int xcentre, int ycentre, int radius, double opacity, double red, double green, double blue); + + void filledcircle_blend(int xcentre, int ycentre, int radius, double opacity, int red, int green, int blue); + void filledcircle_blend(int xcentre, int ycentre, int radius, double opacity, double red, double green, double blue); + + void bezier_blend(int startPtX, int startPtY, + int startControlX, int startControlY, + int endPtX, int endPtY, + int endControlX, int endControlY, + double opacity, + double red, double green, double blue); + + void bezier_blend(int startPtX, int startPtY, + int startControlX, int startControlY, + int endPtX, int endPtY, + int endControlX, int endControlY, + double opacity, + int red, int green, int blue); + + void plot_text_blend(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, double opacity, double red, double green, double blue); + void plot_text_blend(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, double opacity, int red, int green, int blue); + + void plot_text_utf8_blend(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, double opacity, double red, double green, double blue); + void plot_text_utf8_blend(char* face_path, int fontsize, int x_start, int y_start, double angle, char* text, double opacity, int red, int green, int blue); + + void boundary_fill_blend(int xstart, int ystart, double opacity, double boundary_red,double boundary_green,double boundary_blue,double fill_red, double fill_green, double fill_blue) ; + void boundary_fill_blend(int xstart, int ystart, double opacity, int boundary_red,int boundary_green,int boundary_blue,int fill_red, int fill_green, int fill_blue) ; + + void flood_fill_blend(int xstart, int ystart, double opacity, double fill_red, double fill_green, double fill_blue) ; + void flood_fill_blend(int xstart, int ystart, double opacity, int fill_red, int fill_green, int fill_blue) ; + + void polygon_blend(int* points, int number_of_points, double opacity, double red, double green, double blue); + void polygon_blend(int* points, int number_of_points, double opacity, int red, int green, int blue); + + void plotCMYK_blend(int x, int y, double opacity, double cyan, double magenta, double yellow, double black); + void plotCMYK_blend(int x, int y, double opacity, int cyan, int magenta, int yellow, int black); + + // End of Blended Functions + + /* Laplacian + * This function applies a discrete laplacian to the image, multiplied by a constant factor. + * The kernel used in this case is: + * 1.0 1.0 1.0 + * 1.0 -8.0 1.0 + * 1.0 1.0 1.0 + * Basically, this works as an edge detector. The current pixel is assigned the sum of all neighbouring + * pixels, multiplied by the corresponding kernel element. For example, imagine a pixel and its 8 neighbours: + * 1.0 1.0 0.0 0.0 + * 1.0 ->1.0<- 0.0 0.0 + * 1.0 1.0 0.0 0.0 + * This represents a border between white and black, black is on the right. Applying the laplacian to + * the pixel specified above pixel gives: + * 1.0*1.0 + 1.0*1.0 + 0.0*1.0 + + * 1.0*1.0 + 1.0*-8.0 + 0.0*1.0 + + * 1.0*1.0 + 1.0*1.0 + 0.0*1.0 = -3.0 + * Applying this to the pixel to the right of the pixel considered previously, we get a sum of 3.0. + * That is, after passing over an edge, we get a high value for the pixel adjacent to the edge. Since + * PNGwriter limits the colour components if they are off-scale, and the result of the laplacian + * may be negative, a scale factor and an offset value are included. This might be useful for + * keeping things within range or for bringing out more detail in the edge detection. The + * final pixel value will be given by: + * final value = laplacian(original pixel)*k + offset + * Tip: Try a value of 1.0 for k to start with, and then experiment with other values. + * */ + void laplacian(double k, double offset); + + /* Filled Triangle + * Draws the triangle specified by the three pairs of points in the colour specified + * by the colour coefficients. The colour components are either doubles from 0.0 to + * 1.0 or ints from 0 to 65535. + * */ + void filledtriangle(int x1,int y1,int x2,int y2,int x3,int y3, int red, int green, int blue); + void filledtriangle(int x1,int y1,int x2,int y2,int x3,int y3, double red, double green, double blue); + + /* Filled Triangle, Blended + * Draws the triangle specified by the three pairs of points in the colour specified + * by the colour coefficients, and blended with the background. See the description for Blended Functions. + * The colour components are either doubles from 0.0 to 1.0 or ints from 0 to 65535. + * */ + void filledtriangle_blend(int x1,int y1,int x2,int y2,int x3,int y3, double opacity, int red, int green, int blue); + void filledtriangle_blend(int x1,int y1,int x2,int y2,int x3,int y3, double opacity, double red, double green, double blue); + + /* Arrow, Filled Arrow + * Plots an arrow from (x1, y1) to (x2, y2) with the arrowhead at the second point, given the size in pixels + * and the angle in radians of the arrowhead. The plotted arrow consists of one main line, and two smaller + * lines originating from the second point. Filled Arrow plots the same, but the arrowhead is a solid triangle. + * Tip: An angle of 10 to 30 degrees looks OK. + * */ + + void arrow(int x1,int y1,int x2,int y2,int size, double head_angle, double red, double green, double blue); + void arrow(int x1,int y1,int x2,int y2,int size, double head_angle, int red, int green, int blue); + + void filledarrow(int x1,int y1,int x2,int y2,int size, double head_angle, double red, double green, double blue); + void filledarrow(int x1,int y1,int x2,int y2,int size, double head_angle, int red, int green, int blue); + + /* Cross, Maltese Cross + * Plots a simple cross at x, y, with the specified height and width, and in the specified colour. + * Maltese cross plots a cross, as before, but adds bars at the end of each arm of the cross. + * The size of these bars is specified with x_bar_height and y_bar_width. + * The cross will look something like this: + * + * ----- <-- ( y_bar_width) + * | + * | + * |-------| <-- ( x_bar_height ) + * | + * | + * ----- + * */ + + void cross(int x, int y, int xwidth, int yheight, double red, double green, double blue); + void cross(int x, int y, int xwidth, int yheight, int red, int green, int blue); + + void maltesecross(int x, int y, int xwidth, int yheight, int x_bar_height, int y_bar_width, double red, double green, double blue); + void maltesecross(int x, int y, int xwidth, int yheight, int x_bar_height, int y_bar_width, int red, int green, int blue); + + /* Diamond and filled diamond + * Plots a diamond shape, given the x, y position, the width and height, and the colour. + * Filled diamond plots a filled diamond. + * */ + + void filleddiamond(int x, int y, int width, int height, int red, int green, int blue); + void diamond(int x, int y, int width, int height, int red, int green, int blue); + + void filleddiamond(int x, int y, int width, int height, double red, double green, double blue); + void diamond(int x, int y, int width, int height, double red, double green, double blue); + + /* Get Text Width, Get Text Width UTF8 + * Returns the approximate width, in pixels, of the specified *unrotated* text. It is calculated by adding + * each letter's width and kerning value (as specified in the TTF file). Note that this will not + * give the position of the farthest pixel, but it will give a pretty good idea of what area the + * text will occupy. Tip: The text, when plotted unrotated, will fit approximately in a box with its lower left corner at + * (x_start, y_start) and upper right at (x_start + width, y_start + size), where width is given by get_text_width() + * and size is the specified size of the text to be plotted. Tip: Text plotted at position + * (x_start, y_start), rotated with a given 'angle', and of a given 'size' + * whose width is 'width', will fit approximately inside a rectangle whose corners are at + * 1 (x_start, y_start) + * 2 (x_start + width*cos(angle), y_start + width*sin(angle)) + * 3 (x_start + width*cos(angle) - size*sin(angle), y_start + width*sin(angle) + size*cos(angle)) + * 4 (x_start - size*sin(angle), y_start + size*cos(angle)) + * */ + + int get_text_width(char* face_path, int fontsize, char* text); + + int get_text_width_utf8(char* face_path, int fontsize, char* text); }; diff --git a/projectors/Normalizer.cpp b/projectors/Normalizer.cpp index 3fca94f..8e69977 100644 --- a/projectors/Normalizer.cpp +++ b/projectors/Normalizer.cpp @@ -9,7 +9,7 @@ Normalizer::Normalizer(unsigned int dimension) : Projector(dimension, dimension) try { allocate(); - } catch (std::exception& e) { + } catch(std::exception& e) { LogError("Couldn't construct Normalizer (Projector): %s\n", e.what()); deallocate(); } @@ -23,13 +23,13 @@ Normalizer::~Normalizer() { deallocate(); } -void Normalizer::allocate(){ +void Normalizer::allocate() { range_min = new double[outputDimension]; range_max = new double[outputDimension]; offset = new double[outputDimension]; } -void Normalizer::deallocate(){ +void Normalizer::deallocate() { delete[] range_min; range_min = 0; delete[] range_max; @@ -41,12 +41,12 @@ void Normalizer::deallocate(){ #pragma mark - #pragma mark plot -void Normalizer::project(const double * point) { - for ( unsigned int i = 0; i < inputDimension; ++i ) { +void Normalizer::project(const double* point) { + for(unsigned int i = 0; i < inputDimension; ++i) { projectedPoint[0] = point[0]*factor + offset[0]; } - if(!ready){ + if(!ready) { static unsigned int state = 0; switch(state) { @@ -70,16 +70,16 @@ void Normalizer::project(const double * point) { #pragma mark setting up void Normalizer::init_range() { - for ( unsigned int i = 0; i < outputDimension; i++ ) { + for(unsigned int i = 0; i < outputDimension; i++) { range_min[i] = range_max[i] = projectedPoint[i]; } } void Normalizer::update_range() { - for ( unsigned int i = 0; i < outputDimension; i++ ) { - if ( projectedPoint[i] < range_min[i] ) { + for(unsigned int i = 0; i < outputDimension; i++) { + if(projectedPoint[i] < range_min[i]) { range_min[i] = projectedPoint[i]; - } else if ( projectedPoint[i] > range_max[i] ) { + } else if(projectedPoint[i] > range_max[i]) { range_max[i] = projectedPoint[i]; } } @@ -87,16 +87,16 @@ void Normalizer::update_range() { void Normalizer::finish_range() { factor = 2.0 / (range_max[0] - range_min[0]); - for ( unsigned int i = 1; i < outputDimension; i++ ) { + for(unsigned int i = 1; i < outputDimension; i++) { double dist = range_max[i] - range_min[i]; - if ( factor * dist > 2.0 ) { + if(factor * dist > 2.0) { factor = 2.0 / dist; //teh_size = canvas->size[i]; LogDebug("Crap for dimension %d\n", i); } } - for ( unsigned int i = 0; i < outputDimension; i++ ) { + for(unsigned int i = 0; i < outputDimension; i++) { offset[i] = -0.5*factor*(range_min[i] + range_max[i]); } } diff --git a/projectors/Projection.cpp b/projectors/Projection.cpp index 959c8dd..3dcb660 100644 --- a/projectors/Projection.cpp +++ b/projectors/Projection.cpp @@ -1,10 +1,10 @@ #include "Projection.hpp" -Projection::Projection(unsigned int inputDimension, unsigned int outputDimension) : Projector(inputDimension, outputDimension){ +Projection::Projection(unsigned int inputDimension, unsigned int outputDimension) : Projector(inputDimension, outputDimension) { } -void Projection::project(const double* point){ - for ( unsigned int i = 0; i < inputDimension; ++i){ +void Projection::project(const double* point) { + for(unsigned int i = 0; i < inputDimension; ++i) { projectedPoint[i] = point[i]; } } diff --git a/stfu/stf.cpp b/stfu/stf.cpp index 4c71ce4..97a6f8b 100644 --- a/stfu/stf.cpp +++ b/stfu/stf.cpp @@ -1,275 +1,275 @@ -/* -Copyright (c) 2009 Maurice Bos and Nick Overdijk -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The names of the authors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -- Maurice Bos (maurice@bosbyte.nl) -- Nick Overdijk (nick@dotsimplicity.net) - -*/ - -#include -#include -#include -#include -#include - -#include "stf.hpp" - -namespace stfu{ - - std::ostream &operator<< (std::ostream &out, const node &root) { - root.write(out); - return out; - } - - bool operator<< (const char *filename, const node &root){ - return root.write(filename); - } - - bool operator<< (std::ofstream &out, const node &root) { - return root.write(out); - } - - bool operator>> (std::istream &in, node &root) { - return root.read(in); - } - - bool operator>> (const char *filename, node &root) { - return root.read(filename); - } - - const std::string &node::getValue(const std::string &name, size_t index) const throw (std::out_of_range) { - return get_indexed(values, name, index); - } - - /*Function is const, but shouldn't be called on const objects since it returns a nonconst-reference to a member*/ - std::string &node::getValue(const std::string &name, size_t index) throw (std::out_of_range) { - return get_indexed(values, name, index); - } - - std::string &node::addValue(const std::string &name) { - return values.insert(std::pair(name, std::string()))->second; - } - - std::string &node::value(const std::string &name, size_t index) { - try { - return getValue(name, index); - } catch (std::out_of_range &e) { - //it doesn't exist: create it - return addValue(name); - } - } - - void node::removeValue(const std::string &name, size_t index) throw (std::out_of_range) { - values.erase(get_indexed_it(values, name, index)); - return; - } - - void node::renameValue(const std::string &oldName, const std::string &newName, size_t index) { - addValue(newName) = value(oldName, index); - removeValue(oldName, index); - } - - - const node &node::getChild(const std::string &name, size_t index) const throw (std::out_of_range) { - return get_indexed(children, name, index); - } - - node &node::getChild(const std::string &name, size_t index) throw (std::out_of_range) { - return get_indexed(children, name, index); - } - - node &node::addChild(const std::string &name) { - return children.insert(std::pair(name, node()))->second; - } - - node &node::addChild(const std::string &name, node &newNode) { - return children.insert(std::pair(name, newNode))->second; - } - - node &node::child(const std::string &name, size_t index) { - //if there's no such child, add one - try { - return getChild(name, index); - } catch (std::out_of_range &e) { - //it doesn't exist: create it - return addChild(name); - } - } - - void node::renameChild(const std::string &oldName, const std::string &newName, size_t index) { - node copy = child(oldName, index); - removeChild(oldName, index); - addChild(newName) = copy; - } - - void node::removeChild(const std::string &name, size_t index) throw (std::out_of_range) { - children.erase(get_indexed_it(children, name, index)); - return; - } - - bool node::read(const char *filename) { - std::ifstream f(filename); - - if (!f.good()) return false; - - bool success = read(f); - f.close(); - - return success; - } - - bool node::read(std::istream &in) { - while (1) { - in >> std::ws; //Skip whitespace - - //if end of node is reached, return - if (in.peek() == '}') { - in.ignore(); - return true; - } - - if (in.eof()) { - return true; //End of the file is reached - } - - std::string name; - char type; // '{' or '"' - streamRead(in, name, ':'); //Read name (all chars before ':') - type = streamSkip(in,"\"{"); //Skip everything until '{' or '"' - - switch (type) { - - //in case of value - case '"': { - std::string value; - while (1) { - if (streamRead(in, value, '"') == 0) { //Read to the closing-" - return false; - } - if (in.peek() == '"') { - in.ignore(); - value += '"'; - continue; - } else { - break; - } - } - this->values.insert(std::pair(name, value)); - break; - } - - //in case of child - case '{': { - node sub; - if (!sub.read(in)) { //Recursively read the subnode - return false; - } - this->children.insert(std::pair(name,sub)); - break; - } - - default: - return false; - } - } - } - - /*Writes to a file using it's overloaded self*/ - bool node::write(const char *filename) const { - std::ofstream f(filename); - - if (!f.good()) { - return false; - } - - bool success = write(f); - f.close(); - - return success; - } - - // TODO (Nick#1#): Make write() not put unnamed values on a new line, children are okay. - bool node::write(std::ostream &out, size_t depth, std::string indent) const { - std::string indentation; - for (size_t i = 0; i < depth; i++) { - indentation += indent; - } - - for (std::multimap::const_iterator value_it = values.begin(); value_it != values.end(); value_it++) { - //Escape all the '"' by adding a second '"' - std::string value(value_it->second); - size_t found = value.find('"'); - - //while there are more ", insert second "s - while (found != value.npos) { - value.insert(found, 1, '"'); - found = value.find('"', found+2); - } - out << indentation << value_it->first << ": \"" << value << '"' << std::endl; - } - - for (std::multimap::const_iterator child_it = children.begin(); child_it != children.end(); child_it++) { - out << indentation << child_it->first << ": {" << std::endl; - child_it->second.write(out, depth+1); - out << indentation << '}' << std::endl; - } - - return true; - } - - char node::streamSkip(std::istream &in, const std::string &delimiters) { - char cur; - - //Return if the current char is part of delimiters[] - while (in >> std::noskipws >> cur) { - if (delimiters.find_first_of(cur) != delimiters.npos) return cur; - } - return 0; - } - - char node::streamRead(std::istream &in, std::string &out, const std::string &delimiters) { - char cur; - - //Return if the current char is part of delimiters[] - while (in >> std::noskipws >> cur) { - if (delimiters.find(cur) != delimiters.npos) return cur; - out += cur; - } - return 0; - } - - char node::streamRead(std::istream &in, std::string &out, const char delimiter) { - char cur; - - //Return if the current char is delimiter - while (in >> std::noskipws >> cur) { - if (delimiter == cur) return cur; - out += cur; - } - return 0; - } - -} +/* +Copyright (c) 2009 Maurice Bos and Nick Overdijk +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * The names of the authors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +- Maurice Bos (maurice@bosbyte.nl) +- Nick Overdijk (nick@dotsimplicity.net) + +*/ + +#include +#include +#include +#include +#include + +#include "stf.hpp" + +namespace stfu { + +std::ostream& operator<< (std::ostream& out, const node& root) { + root.write(out); + return out; +} + +bool operator<< (const char* filename, const node& root) { + return root.write(filename); +} + +bool operator<< (std::ofstream& out, const node& root) { + return root.write(out); +} + +bool operator>> (std::istream& in, node& root) { + return root.read(in); +} + +bool operator>> (const char* filename, node& root) { + return root.read(filename); +} + +const std::string& node::getValue(const std::string& name, size_t index) const throw(std::out_of_range) { + return get_indexed(values, name, index); +} + +/*Function is const, but shouldn't be called on const objects since it returns a nonconst-reference to a member*/ +std::string& node::getValue(const std::string& name, size_t index) throw(std::out_of_range) { + return get_indexed(values, name, index); +} + +std::string& node::addValue(const std::string& name) { + return values.insert(std::pair(name, std::string()))->second; +} + +std::string& node::value(const std::string& name, size_t index) { + try { + return getValue(name, index); + } catch(std::out_of_range& e) { + //it doesn't exist: create it + return addValue(name); + } +} + +void node::removeValue(const std::string& name, size_t index) throw(std::out_of_range) { + values.erase(get_indexed_it(values, name, index)); + return; +} + +void node::renameValue(const std::string& oldName, const std::string& newName, size_t index) { + addValue(newName) = value(oldName, index); + removeValue(oldName, index); +} + + +const node& node::getChild(const std::string& name, size_t index) const throw(std::out_of_range) { + return get_indexed(children, name, index); +} + +node& node::getChild(const std::string& name, size_t index) throw(std::out_of_range) { + return get_indexed(children, name, index); +} + +node& node::addChild(const std::string& name) { + return children.insert(std::pair(name, node()))->second; +} + +node& node::addChild(const std::string& name, node& newNode) { + return children.insert(std::pair(name, newNode))->second; +} + +node& node::child(const std::string& name, size_t index) { + //if there's no such child, add one + try { + return getChild(name, index); + } catch(std::out_of_range& e) { + //it doesn't exist: create it + return addChild(name); + } +} + +void node::renameChild(const std::string& oldName, const std::string& newName, size_t index) { + node copy = child(oldName, index); + removeChild(oldName, index); + addChild(newName) = copy; +} + +void node::removeChild(const std::string& name, size_t index) throw(std::out_of_range) { + children.erase(get_indexed_it(children, name, index)); + return; +} + +bool node::read(const char* filename) { + std::ifstream f(filename); + + if(!f.good()) return false; + + bool success = read(f); + f.close(); + + return success; +} + +bool node::read(std::istream& in) { + while(1) { + in >> std::ws; //Skip whitespace + + //if end of node is reached, return + if(in.peek() == '}') { + in.ignore(); + return true; + } + + if(in.eof()) { + return true; //End of the file is reached + } + + std::string name; + char type; // '{' or '"' + streamRead(in, name, ':'); //Read name (all chars before ':') + type = streamSkip(in,"\"{"); //Skip everything until '{' or '"' + + switch(type) { + + //in case of value + case '"': { + std::string value; + while(1) { + if(streamRead(in, value, '"') == 0) { //Read to the closing-" + return false; + } + if(in.peek() == '"') { + in.ignore(); + value += '"'; + continue; + } else { + break; + } + } + this->values.insert(std::pair(name, value)); + break; + } + + //in case of child + case '{': { + node sub; + if(!sub.read(in)) { //Recursively read the subnode + return false; + } + this->children.insert(std::pair(name,sub)); + break; + } + + default: + return false; + } + } +} + +/*Writes to a file using it's overloaded self*/ +bool node::write(const char* filename) const { + std::ofstream f(filename); + + if(!f.good()) { + return false; + } + + bool success = write(f); + f.close(); + + return success; +} + +// TODO (Nick#1#): Make write() not put unnamed values on a new line, children are okay. +bool node::write(std::ostream& out, size_t depth, std::string indent) const { + std::string indentation; + for(size_t i = 0; i < depth; i++) { + indentation += indent; + } + + for(std::multimap::const_iterator value_it = values.begin(); value_it != values.end(); value_it++) { + //Escape all the '"' by adding a second '"' + std::string value(value_it->second); + size_t found = value.find('"'); + + //while there are more ", insert second "s + while(found != value.npos) { + value.insert(found, 1, '"'); + found = value.find('"', found+2); + } + out << indentation << value_it->first << ": \"" << value << '"' << std::endl; + } + + for(std::multimap::const_iterator child_it = children.begin(); child_it != children.end(); child_it++) { + out << indentation << child_it->first << ": {" << std::endl; + child_it->second.write(out, depth+1); + out << indentation << '}' << std::endl; + } + + return true; +} + +char node::streamSkip(std::istream& in, const std::string& delimiters) { + char cur; + + //Return if the current char is part of delimiters[] + while(in >> std::noskipws >> cur) { + if(delimiters.find_first_of(cur) != delimiters.npos) return cur; + } + return 0; +} + +char node::streamRead(std::istream& in, std::string& out, const std::string& delimiters) { + char cur; + + //Return if the current char is part of delimiters[] + while(in >> std::noskipws >> cur) { + if(delimiters.find(cur) != delimiters.npos) return cur; + out += cur; + } + return 0; +} + +char node::streamRead(std::istream& in, std::string& out, const char delimiter) { + char cur; + + //Return if the current char is delimiter + while(in >> std::noskipws >> cur) { + if(delimiter == cur) return cur; + out += cur; + } + return 0; +} + +} diff --git a/stfu/stf.hpp b/stfu/stf.hpp index 090aa57..f19f4f9 100644 --- a/stfu/stf.hpp +++ b/stfu/stf.hpp @@ -1,359 +1,359 @@ -/* -Copyright (c) 2009 Maurice Bos and Nick Overdijk -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * The names of the authors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -- Maurice Bos (maurice@bosbyte.nl) -- Nick Overdijk (nick@dotsimplicity.net) - -*/ - -#include -#include -#include -#include -#include - -#ifndef STFU_HPP -#define STFU_HPP - -namespace stfu { - - const static std::string not_found("search->No such child/value"); - - /*! \class node - * \brief A node in an STF tree. - * \author Maurice Bos - * \author Nick Overdijk - * \version 1.0 - * \date 2009-04-25 - * - * When you read an STF file through a node (with read() for example), this node will be the root node, without a name. See the examples for more information. - */ - class node { - - /** Overloaded ostream's operator<< */ - friend std::ostream &operator<< (std::ostream &out, const node &root); - - /** Returns whether it was succesful or not*/ - friend bool operator<< (std::ofstream &out, const node &root); - - /** Acts like write(), but looks like this: "filename" << node */ - friend bool operator<< (const char *filename, const node &root); - - /** Overloaded istream's operator>> */ - friend bool operator>> (std::istream &in, node &root); - - /** Acts like read(), but looks like this: "filename" >> node */ - friend bool operator>> (const char *filename, node &root); - - public: - //@{ - /** The values and children belonging to this node. To add, remove, do whatever: you CAN use these variables directly. To use indexing, use the member functions below*/ - std::multimap values; - std::multimap children; - //@} - - /** - Clears the whole node recursively. - */ - void clear() { - values.clear(); - children.clear(); - } - /** - Gets the std::string value from a variable - \param name The name of the value you wish to retrieve - \param index If there are more values with the same name, they are indexed. Here you can supply its indexnumber. - \return The retrieved value - */ - std::string &value(const std::string &name, size_t index = 0); - - /** - Same as value(), but for unnamed values - \note same as value("", index) - \param index If there are more unnamed values, they are indexed. Here you can supply its indexnumber. - \return Same as value - */ - std::string &value(size_t index){ - return value("", index); - } - - /** - Creates and adds a value. - \param name The name of the value to be created - \return A reference to the value of the created value. - */ - std::string &addValue(const std::string &name = ""); - - /** - Const function for const objects to get a value. It's NOT possible to call value() on constant objects for value() isn't const. - \param name Name of the value to be retrieved - \param index If there are > 1 values with the same name, they are indexed. Here you can supply an indexnumber. - \return Returns a const std::string& to the value of value with the name and index specified - */ - const std::string &getValue(const std::string &name, size_t index) const throw (std::out_of_range); - - /** - Same as getValue() const, but for unnamed values - \note same as getValue("", index) const - \param index If there are > 1 unnamed values, they are indexed. Here you can supply an indexnumber. - \return Returns a const std::string& to the value of value with the name and index specified - */ - const std::string &getValue(size_t index) const throw (std::out_of_range){ - return getValue("", index); - } - - /** - Same as getValue() const, but for non-const objects. The returned std::string& can safely be modified. - \param name Name of the value to be retrieved - \param index If there are > 1 values with the same name, they are indexed. Here you can supply an indexnumber. - \return Returns a std::string& to the value of value with the name and index specified - */ - std::string &getValue(const std::string &name, size_t index = 0) throw (std::out_of_range); - - /** - Same as getValue(), but for unnamed values - \note same as getValue("", index) - \param index If there are > 1 unnamed values, they are indexed. Here you can supply an indexnumber. - \return Returns a std::string& to the value of value with the name and index specified - */ - std::string &getValue(size_t index) throw (std::out_of_range){ - return getValue("", index); - } - - /** - Removes a value. Surprise huh? - \param name Name of the value to be removed - \param index If there are > 1 values with the same name, they are indexed. Here you can supply an indexnumber. - */ - void removeValue(const std::string &name, size_t index = 0) throw (std::out_of_range); - - /** - Removes an unnamed value. - \note same as removeValue("", index); - \param index If there are > 1 unnamed values, they are indexed. Here you can supply an indexnumber. - */ - void removeValue(size_t index) throw (std::out_of_range){ - removeValue("", index); - } - - /** - Renames a value. - \param oldName Name of the value to be renamed - \param newName The name that the oldName-value should have - \param index If there are > 1 values with the same name, they are indexed. Here you can supply an indexnumber. - */ - void renameValue(const std::string &oldName, const std::string &newName, size_t index = 0); - - /** - Changes, adds or retrieves node - \param name The name of the child you wish to retrieve, change or add. - \param index If there are > 1 children with the same name, they are indexed. Here you can supply an indexnumber. - \return The retrieved node - - If this index number is > the number of variables with that name, a new variable with that name is created with index = current number of same name variables + 1. - So say you have 4 variables named "tree", you call child("tree", 10), another tree gets made with index 5, NOT 10. - */ - node &child(const std::string &name, size_t index = 0); - - /** - Same as child(), but for unnamed children. - \note same as child("", index) - \param index If there are > 1 unnamed children, they are indexed. Here you can supply an indexnumber. - \return The retrieved node - */ - node &child(size_t index = 0){ - return child("", index); - } - - /** - Guarranteed to add a child - \param name Name for the child - \return A reference to the created node - */ - node &addChild(const std::string &name = ""); - - /** - As addChild(name), but copies data from newChild as well. - \param name Name for the child - \param newChild Data to copy from the child. - \return A reference to the created node - */ - node &addChild(const std::string &name, node &newChild); - - /** - As addChild(name, newChild), but without name, for unnamed children - \note same as addChild("", newChild); - \param newChild Data to copy from the child. - \return A reference to the created node - */ - node &addChild(node &newChild){ - return addChild("", newChild); - } - - /** - Const function for const objects to get a node. It's NOT possible to call child() for this, for child() isn't const. - \param name Name of the child to be retrieved - \param index If there are > 1 children with the same name, they are indexed. Here you can supply an indexnumber. - \return Returns a const node& to the node with the name and index specified - */ - const node &getChild(const std::string &name, size_t index = 0) const throw (std::out_of_range); - - /** - Const function for const objects to get an unnamed const node&. - \note same as getChild("", index) const; - \param index If there are > 1 unnamed children, they are indexed. Here you can supply an indexnumber. - \return Returns a const node& to the node with the name and index specified - */ - const node &getChild(size_t index = 0) const throw (std::out_of_range){ - return getChild("", index); - } - - /** - Same as getChild() const, but for non-const objects. The returned child & can be modified - \param name Name of the child to be retrieved - \param index If there are > 1 children with the same name, they are indexed. Here you can supply an indexnumber. - \return Returns a node& to the node with the name and index specified - */ - node &getChild(const std::string &name, size_t index = 0) throw (std::out_of_range); - - /** - Same as getChild() const, but for non-const objects. - \note same as getChild("", index); - \param index If there are > 1 unnamed children, they are indexed. Here you can supply an indexnumber. - \return Returns a node& to the node with the name and index specified - */ - node &getChild(size_t index = 0) throw (std::out_of_range){ - return getChild("", index); - } - - /** - Removes a child. Surprise huh? - \param name Name of the child to be removed - \param index If there are > 1 children with the same name, they are indexed. Here you can supply an indexnumber. - */ - void removeChild(const std::string &name, size_t index = 0) throw (std::out_of_range); - - /** - As removeChild() for unnamed children. - \param index If there are > 1 unnamed children, they are indexed. Here you can supply an indexnumber. - */ - void removeChild(size_t index = 0) throw (std::out_of_range){ - removeChild("", index); - } - - /** - Renames a child. - \param oldName Name of the child to be renamed - \param newName The name that the oldName-child should have - \param index If there are > 1 children with the same name, they are indexed. Here you can supply an indexnumber. - */ - void renameChild(const std::string &oldName, const std::string &newName, size_t index = 0); - - - /** - Reads the STF from an istream - - \return Returns whether it was succesful - */ - bool read(std::istream &in); - - /** - Reads the STF from a file - - \return Returns whether it was succesful - */ - bool read(const char *filename); - - /** - Writes the STF to an ostream with optional indentation - \param out ostream to write to - \param depth how much indentation to start with - \param indent What std::string to use as indenation - \return Returns whether it was succesful - */ - bool write(std::ostream &out, size_t depth = 0, std::string indent = "\t") const; - - /** - Writes to a file. Simply first opens a file and passes that ostream to itself. - \param filename File to write to - \return Returns whether it was succesful - */ - bool write(const char *filename) const; - - private: - char streamRead(std::istream &in,std::string &out, const std::string &delim); - char streamRead(std::istream &in, std::string &out, const char delim); - char streamSkip(std::istream &in, const std::string &delim); - - /* - returns a T2&, not a const T2&. The functions getValue/getChild make sure this will be done correctly for const objects - this function can NOT use get_indexed_it, because that function can't be const: - const_iterators can not be transformed into iterators, and the iterator is needed for erase(), which wants an iterator. - */ - template - T2& get_indexed(const std::multimap &container, const T1 &key, size_t index = 0) const throw (std::out_of_range) { - size_t count = container.count(key); - - if (count != 0 && count-1 >= index) { - typename std::multimap::const_iterator it = container.find(key); - while (index--) it++; - return const_cast(it->second); - } else { - throw std::out_of_range((std::string)"get_indexed->"+"Element " + key + "doesn't exist!"); - } - } - -// template -// typename multimap::iterator get_indexed_it(multimap &container, const T1 &key, size_t index = 0) throw (out_of_range) { -// size_t count = container.count(key); -// -// if (count != 0 && count-1 >= index) { -// typename multimap::iterator it = container.find(key); -// while (index--) it++; -// return it; -// } else { -// throw out_of_range((std::string)"get_indexed_it->"+"Element " + key + "doesn't exist!"); -// } -// } - - template - typename Container::iterator get_indexed_it(Container& container, const T& key, size_t index = 0) - throw (std::out_of_range) { - typename Container::iterator it = container.find(key); - while (index-- && it != container.end() && it->first==key) it++; - if (it == container.end()) throw std::out_of_range("get_indexed_it(Container&, const T&, size_t)"); - return it; - } - }; - - typedef std::pair value; - typedef std::pair child; - - typedef std::multimap::iterator valueiterator; - typedef std::multimap::iterator childiterator; -} - -#endif // STFU_HPP +/* +Copyright (c) 2009 Maurice Bos and Nick Overdijk +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * The names of the authors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +- Maurice Bos (maurice@bosbyte.nl) +- Nick Overdijk (nick@dotsimplicity.net) + +*/ + +#include +#include +#include +#include +#include + +#ifndef STFU_HPP +#define STFU_HPP + +namespace stfu { + +const static std::string not_found("search->No such child/value"); + +/*! \class node + * \brief A node in an STF tree. + * \author Maurice Bos + * \author Nick Overdijk + * \version 1.0 + * \date 2009-04-25 + * + * When you read an STF file through a node (with read() for example), this node will be the root node, without a name. See the examples for more information. + */ +class node { + + /** Overloaded ostream's operator<< */ + friend std::ostream& operator<< (std::ostream& out, const node& root); + + /** Returns whether it was succesful or not*/ + friend bool operator<< (std::ofstream& out, const node& root); + + /** Acts like write(), but looks like this: "filename" << node */ + friend bool operator<< (const char* filename, const node& root); + + /** Overloaded istream's operator>> */ + friend bool operator>> (std::istream& in, node& root); + + /** Acts like read(), but looks like this: "filename" >> node */ + friend bool operator>> (const char* filename, node& root); + +public: + //@{ + /** The values and children belonging to this node. To add, remove, do whatever: you CAN use these variables directly. To use indexing, use the member functions below*/ + std::multimap values; + std::multimap children; + //@} + + /** + Clears the whole node recursively. + */ + void clear() { + values.clear(); + children.clear(); + } + /** + Gets the std::string value from a variable + \param name The name of the value you wish to retrieve + \param index If there are more values with the same name, they are indexed. Here you can supply its indexnumber. + \return The retrieved value + */ + std::string& value(const std::string& name, size_t index = 0); + + /** + Same as value(), but for unnamed values + \note same as value("", index) + \param index If there are more unnamed values, they are indexed. Here you can supply its indexnumber. + \return Same as value + */ + std::string& value(size_t index) { + return value("", index); + } + + /** + Creates and adds a value. + \param name The name of the value to be created + \return A reference to the value of the created value. + */ + std::string& addValue(const std::string& name = ""); + + /** + Const function for const objects to get a value. It's NOT possible to call value() on constant objects for value() isn't const. + \param name Name of the value to be retrieved + \param index If there are > 1 values with the same name, they are indexed. Here you can supply an indexnumber. + \return Returns a const std::string& to the value of value with the name and index specified + */ + const std::string& getValue(const std::string& name, size_t index) const throw(std::out_of_range); + + /** + Same as getValue() const, but for unnamed values + \note same as getValue("", index) const + \param index If there are > 1 unnamed values, they are indexed. Here you can supply an indexnumber. + \return Returns a const std::string& to the value of value with the name and index specified + */ + const std::string& getValue(size_t index) const throw(std::out_of_range) { + return getValue("", index); + } + + /** + Same as getValue() const, but for non-const objects. The returned std::string& can safely be modified. + \param name Name of the value to be retrieved + \param index If there are > 1 values with the same name, they are indexed. Here you can supply an indexnumber. + \return Returns a std::string& to the value of value with the name and index specified + */ + std::string& getValue(const std::string& name, size_t index = 0) throw(std::out_of_range); + + /** + Same as getValue(), but for unnamed values + \note same as getValue("", index) + \param index If there are > 1 unnamed values, they are indexed. Here you can supply an indexnumber. + \return Returns a std::string& to the value of value with the name and index specified + */ + std::string& getValue(size_t index) throw(std::out_of_range) { + return getValue("", index); + } + + /** + Removes a value. Surprise huh? + \param name Name of the value to be removed + \param index If there are > 1 values with the same name, they are indexed. Here you can supply an indexnumber. + */ + void removeValue(const std::string& name, size_t index = 0) throw(std::out_of_range); + + /** + Removes an unnamed value. + \note same as removeValue("", index); + \param index If there are > 1 unnamed values, they are indexed. Here you can supply an indexnumber. + */ + void removeValue(size_t index) throw(std::out_of_range) { + removeValue("", index); + } + + /** + Renames a value. + \param oldName Name of the value to be renamed + \param newName The name that the oldName-value should have + \param index If there are > 1 values with the same name, they are indexed. Here you can supply an indexnumber. + */ + void renameValue(const std::string& oldName, const std::string& newName, size_t index = 0); + + /** + Changes, adds or retrieves node + \param name The name of the child you wish to retrieve, change or add. + \param index If there are > 1 children with the same name, they are indexed. Here you can supply an indexnumber. + \return The retrieved node + + If this index number is > the number of variables with that name, a new variable with that name is created with index = current number of same name variables + 1. + So say you have 4 variables named "tree", you call child("tree", 10), another tree gets made with index 5, NOT 10. + */ + node& child(const std::string& name, size_t index = 0); + + /** + Same as child(), but for unnamed children. + \note same as child("", index) + \param index If there are > 1 unnamed children, they are indexed. Here you can supply an indexnumber. + \return The retrieved node + */ + node& child(size_t index = 0) { + return child("", index); + } + + /** + Guarranteed to add a child + \param name Name for the child + \return A reference to the created node + */ + node& addChild(const std::string& name = ""); + + /** + As addChild(name), but copies data from newChild as well. + \param name Name for the child + \param newChild Data to copy from the child. + \return A reference to the created node + */ + node& addChild(const std::string& name, node& newChild); + + /** + As addChild(name, newChild), but without name, for unnamed children + \note same as addChild("", newChild); + \param newChild Data to copy from the child. + \return A reference to the created node + */ + node& addChild(node& newChild) { + return addChild("", newChild); + } + + /** + Const function for const objects to get a node. It's NOT possible to call child() for this, for child() isn't const. + \param name Name of the child to be retrieved + \param index If there are > 1 children with the same name, they are indexed. Here you can supply an indexnumber. + \return Returns a const node& to the node with the name and index specified + */ + const node& getChild(const std::string& name, size_t index = 0) const throw(std::out_of_range); + + /** + Const function for const objects to get an unnamed const node&. + \note same as getChild("", index) const; + \param index If there are > 1 unnamed children, they are indexed. Here you can supply an indexnumber. + \return Returns a const node& to the node with the name and index specified + */ + const node& getChild(size_t index = 0) const throw(std::out_of_range) { + return getChild("", index); + } + + /** + Same as getChild() const, but for non-const objects. The returned child & can be modified + \param name Name of the child to be retrieved + \param index If there are > 1 children with the same name, they are indexed. Here you can supply an indexnumber. + \return Returns a node& to the node with the name and index specified + */ + node& getChild(const std::string& name, size_t index = 0) throw(std::out_of_range); + + /** + Same as getChild() const, but for non-const objects. + \note same as getChild("", index); + \param index If there are > 1 unnamed children, they are indexed. Here you can supply an indexnumber. + \return Returns a node& to the node with the name and index specified + */ + node& getChild(size_t index = 0) throw(std::out_of_range) { + return getChild("", index); + } + + /** + Removes a child. Surprise huh? + \param name Name of the child to be removed + \param index If there are > 1 children with the same name, they are indexed. Here you can supply an indexnumber. + */ + void removeChild(const std::string& name, size_t index = 0) throw(std::out_of_range); + + /** + As removeChild() for unnamed children. + \param index If there are > 1 unnamed children, they are indexed. Here you can supply an indexnumber. + */ + void removeChild(size_t index = 0) throw(std::out_of_range) { + removeChild("", index); + } + + /** + Renames a child. + \param oldName Name of the child to be renamed + \param newName The name that the oldName-child should have + \param index If there are > 1 children with the same name, they are indexed. Here you can supply an indexnumber. + */ + void renameChild(const std::string& oldName, const std::string& newName, size_t index = 0); + + + /** + Reads the STF from an istream + + \return Returns whether it was succesful + */ + bool read(std::istream& in); + + /** + Reads the STF from a file + + \return Returns whether it was succesful + */ + bool read(const char* filename); + + /** + Writes the STF to an ostream with optional indentation + \param out ostream to write to + \param depth how much indentation to start with + \param indent What std::string to use as indenation + \return Returns whether it was succesful + */ + bool write(std::ostream& out, size_t depth = 0, std::string indent = "\t") const; + + /** + Writes to a file. Simply first opens a file and passes that ostream to itself. + \param filename File to write to + \return Returns whether it was succesful + */ + bool write(const char* filename) const; + +private: + char streamRead(std::istream& in,std::string& out, const std::string& delim); + char streamRead(std::istream& in, std::string& out, const char delim); + char streamSkip(std::istream& in, const std::string& delim); + + /* + returns a T2&, not a const T2&. The functions getValue/getChild make sure this will be done correctly for const objects + this function can NOT use get_indexed_it, because that function can't be const: + const_iterators can not be transformed into iterators, and the iterator is needed for erase(), which wants an iterator. + */ + template + T2& get_indexed(const std::multimap &container, const T1& key, size_t index = 0) const throw(std::out_of_range) { + size_t count = container.count(key); + + if(count != 0 && count-1 >= index) { + typename std::multimap::const_iterator it = container.find(key); + while(index--) it++; + return const_cast(it->second); + } else { + throw std::out_of_range((std::string)"get_indexed->"+"Element " + key + "doesn't exist!"); + } + } + +// template +// typename multimap::iterator get_indexed_it(multimap &container, const T1 &key, size_t index = 0) throw (out_of_range) { +// size_t count = container.count(key); +// +// if (count != 0 && count-1 >= index) { +// typename multimap::iterator it = container.find(key); +// while (index--) it++; +// return it; +// } else { +// throw out_of_range((std::string)"get_indexed_it->"+"Element " + key + "doesn't exist!"); +// } +// } + + template + typename Container::iterator get_indexed_it(Container& container, const T& key, size_t index = 0) + throw(std::out_of_range) { + typename Container::iterator it = container.find(key); + while(index-- && it != container.end() && it->first==key) it++; + if(it == container.end()) throw std::out_of_range("get_indexed_it(Container&, const T&, size_t)"); + return it; + } +}; + +typedef std::pair value; +typedef std::pair child; + +typedef std::multimap::iterator valueiterator; +typedef std::multimap::iterator childiterator; +} + +#endif // STFU_HPP