image.H

00001 /*
00002  * This file is part of the "Archon" framework.
00003  * (http://files3d.sourceforge.net)
00004  *
00005  * Copyright © 2002 by Kristian Spangsege and Brian Kristiansen.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and
00008  * its documentation under the terms of the GNU General Public License is
00009  * hereby granted. No representations are made about the suitability of
00010  * this software for any purpose. It is provided "as is" without express
00011  * or implied warranty. See the GNU General Public License
00012  * (http://www.gnu.org/copyleft/gpl.html) for more details.
00013  *
00014  * The characters in this file are ISO8859-1 encoded.
00015  *
00016  * The documentation in this file is in "Doxygen" style
00017  * (http://www.doxygen.org).
00018  */
00019 
00020 #ifndef ARCHON_UTILITIES_IMAGE_H
00021 #define ARCHON_UTILITIES_IMAGE_H
00022 
00023 #include <stdio.h>
00024 #include <string.h>
00025 #include <string>
00026 
00027 #include <archon/util/exception.H>
00028 #include <archon/util/logger.H>
00029 #include <archon/util/stream.H>
00030 #include <archon/util/text.H>
00031 #include <archon/util/muta_ref.H>
00032 #include <archon/util/file.H>
00033 
00034 namespace Archon
00035 {
00036   namespace Utilities
00037   {
00038     using namespace std;
00039 
00143     struct Image
00144     {
00145       static const string PNG;  
00146       static const string TIFF; 
00147       static const string PNM;  
00148       static const string JPEG; 
00149       static const string GIF;  
00150 
00154       operator bool() const { return r; }
00155 
00156       enum ComponentSpecifier
00157       {
00158         components_l    = 1, 
00159         components_la   = 2, 
00160         components_rgb  = 3, 
00161         components_rgba = 4  
00162       };
00163 
00171       Image() {}
00172 
00176       Image(unsigned width, unsigned height,
00177             ComponentSpecifier components = components_rgba,
00178             unsigned bitsPerComponent = 8,
00179             string comment = "");
00180 
00181       unsigned getWidth()             const { return r->width;             }
00182       unsigned getHeight()            const { return r->height;            }
00183       unsigned getBitsPerComponent()  const { return r->bitsPerComponent;  }
00184       unsigned getCharsPerPixel()     const { return r->charsPerPixel;     }
00185       unsigned getCharsPerRow()       const { return r->charsPerRow;       }
00186       unsigned getMaxComponentValue() const { return r->maxComponentValue; }
00187 
00188       ComponentSpecifier getComponentSpecifier() const { return r->components; }
00189 
00195       string getComment() const { return r->comment; }
00196 
00202       void setComment(string c)
00203       {
00204         r.mutate(); r->comment = c;
00205       }
00206 
00207       const char *getPixelBuffer() const
00208       {
00209         return r->getPixelBuffer();
00210       }
00211 
00212       char *getPixelBuffer()
00213       {
00214         r.leak();
00215         return r->getPixelBuffer();
00216       }
00217 
00218       const char *getPixelPtr(int x, int y) const
00219       {
00220         return r->getPixelPtr(x, y);
00221       }
00222 
00223       char *getPixelPtr(int x, int y)
00224       {
00225         r.leak();
00226         return r->getPixelPtr(x, y);
00227       }
00228 
00229       void getPixel(int x, int y, unsigned &l) const
00230       {
00231         r->getPixel(x, y, l);
00232       }
00233 
00234       void setPixel(int x, int y, unsigned l)
00235       {
00236         r.mutate();
00237         r->setPixel(x, y, l);
00238       }
00239 
00240       void getPixel(int x, int y, unsigned &l, unsigned &a) const
00241       {
00242         r->getPixel(x, y, l, a);
00243       }
00244 
00245       void setPixel(int x, int y, unsigned l, unsigned a)
00246       {
00247         r.mutate();
00248         r->setPixel(x, y, l, a);
00249       }
00250 
00251       void getPixel(int x, int y, unsigned &r, unsigned &g, unsigned &b) const
00252       {
00253         this->r->getPixel(x, y, r, g, b);
00254       }
00255 
00256       void setPixel(int x, int y, unsigned r, unsigned g, unsigned b)
00257       {
00258         this->r.mutate();
00259         this->r->setPixel(x, y, r, g, b);
00260       }
00261 
00262       void getPixel(int x, int y, unsigned &r, unsigned &g,
00263                     unsigned &b, unsigned &a) const
00264       {
00265         this->r->getPixel(x, y, r, g, b, a);
00266       }
00267 
00268       void setPixel(int x, int y, unsigned r, unsigned g,
00269                     unsigned b, unsigned a)
00270       {
00271         this->r.mutate();
00272         this->r->setPixel(x, y, r, g, b, a);
00273       }
00274 
00275       void getPixel(int x, int y, double &l) const
00276       {
00277         r->getPixel(x, y, l);
00278       }
00279 
00280       void setPixel(int x, int y, double l)
00281       {
00282         r.mutate();
00283         r->setPixel(x, y, l);
00284       }
00285 
00286       void getPixel(int x, int y, double &l, double &a) const
00287       {
00288         r->getPixel(x, y, l, a);
00289       }
00290 
00291       void setPixel(int x, int y, double l, double a)
00292       {
00293         r.mutate();
00294         r->setPixel(x, y, l, a);
00295       }
00296 
00297       void getPixel(int x, int y, double &r, double &g, double &b) const
00298       {
00299         this->r->getPixel(x, y, r, g, b);
00300       }
00301 
00302       void setPixel(int x, int y, double r, double g, double b)
00303       {
00304         this->r.mutate();
00305         this->r->setPixel(x, y, r, g, b);
00306       }
00307 
00308       void getPixel(int x, int y, double &r, double &g,
00309                     double &b, double &a) const
00310       {
00311         this->r->getPixel(x, y, r, g, b, a);
00312       }
00313 
00314       void setPixel(int x, int y, double r, double g, double b, double a)
00315       {
00316         this->r.mutate();
00317         this->r->setPixel(x, y, r, g, b, a);
00318       }
00319 
00324       void swap(Image &i) { std::swap(r, i.r); }
00325 
00326       struct ImageException: virtual Exception {};
00327 
00331       struct UnknownFormatException: ImageException
00332       {
00333         UnknownFormatException(string l, string m): Exception(l, m) {}
00334       };
00335 
00340       struct InvalidFormatException: ImageException
00341       {
00342         InvalidFormatException(string l, string m): Exception(l, m) {}
00343       };
00344 
00345       struct ProgressTracker
00346       {
00347         virtual void progress(double fraction) throw() = 0;
00348         virtual ~ProgressTracker() {}
00349       };
00350 
00360       struct Format
00361       {
00368         virtual string getSpecifier() const = 0;
00369 
00374         virtual bool checkSignature(Ref<Stream::Reader>) const = 0;
00375 
00383         virtual bool checkSuffix(string suffix) const = 0;
00384 
00385         virtual Image load(Ref<Stream::Reader>, ProgressTracker *, Logger *) const
00386           throw(InvalidFormatException, IOException, UnexpectedException) = 0;
00387 
00388         virtual void save(Image, Ref<Stream::Writer>, ProgressTracker *, Logger *) const
00389           throw(IOException, UnexpectedException) = 0;
00390 
00394         virtual ~Format() {}
00395 
00396       protected:
00406         char *getPixelBufferNoLeak(const Image &i) const
00407         {
00408           return const_cast<char *>(i.getPixelBuffer());
00409         }
00410       };
00411 
00415       struct Context
00416       {
00417         virtual size_t getNumberOfFormats() const = 0;
00418         virtual const Format *getFormat(size_t index) const = 0;
00419 
00423         static const Context *get();
00424 
00428         virtual ~Context() {}
00429       };
00430 
00452       Image(Ref<Stream::Reader> r,
00453             string sourceName, string formatSpecifier = "",
00454             Logger *l = Logger::get(), const Context *c = 0)
00455         throw(UnknownFormatException, InvalidFormatException,
00456               IOException, UnexpectedException)
00457       {
00458         _load(r, sourceName, formatSpecifier, 0, l, c);
00459       }
00460 
00482       explicit Image(string filePath, string formatSpecifier = "",
00483                      Logger *l = Logger::get(), const Context *c = 0)
00484         throw(UnknownFormatException, InvalidFormatException,
00485               IOException, UnexpectedException)
00486       {
00487         _load(Stream::makeFileReader(filePath),
00488               File::nameOf(filePath), formatSpecifier, 0, l, c);
00489       }
00490 
00518       void load(Ref<Stream::Reader> r,
00519                 string sourceName, string formatSpecifier = "",
00520                 ProgressTracker *t = 0, Logger *l = Logger::get(),
00521                 const Context *c = 0)
00522         throw(UnknownFormatException, InvalidFormatException,
00523               IOException, UnexpectedException)
00524       {
00525         _load(r, sourceName, formatSpecifier, t, l, c);
00526       }
00527 
00553       void load(string filePath, string formatSpecifier = "",
00554                 ProgressTracker *t = 0, Logger *l = Logger::get(),
00555                 const Context *c = 0)
00556         throw(UnknownFormatException, InvalidFormatException,
00557               IOException, UnexpectedException)
00558       {
00559         _load(Stream::makeFileReader(filePath),
00560               File::nameOf(filePath), formatSpecifier, t, l, c);
00561       }
00562 
00581       void save(Ref<Stream::Writer> w,
00582                 string targetName, string formatSpecifier = "",
00583                 ProgressTracker *t = 0, Logger *l = Logger::get(),
00584                 const Context *c = 0) const
00585         throw(UnknownFormatException, IOException, UnexpectedException)
00586       {
00587         if(!r) ARCHON_THROW1(StateException, "Null image");
00588         _save(w, targetName, formatSpecifier, t, l, c);
00589       }
00590 
00609       void save(string filePath, string formatSpecifier = "",
00610                 ProgressTracker *t = 0, Logger *l = Logger::get(),
00611                 const Context *c = 0) const
00612         throw(UnknownFormatException, IOException, UnexpectedException)
00613       {
00614         if(!r) ARCHON_THROW1(StateException, "Null image");
00615         _save(Stream::makeFileWriter(filePath),
00616               File::nameOf(filePath), formatSpecifier, t, l, c);
00617       }
00618 
00619     private:
00620       struct Rep: MutaRefObjectBase
00621       {
00622         Rep(unsigned width, unsigned height,
00623             unsigned bitsPerComponent,
00624             unsigned charsPerPixel,
00625             unsigned charsPerRow,
00626             unsigned maxComponentValue,
00627             ComponentSpecifier components,
00628             string comment):
00629           width(width), height(height),
00630           bitsPerComponent(bitsPerComponent),
00631           charsPerPixel(charsPerPixel),
00632           charsPerRow(charsPerRow),
00633           maxComponentValue(maxComponentValue),
00634           components(components),
00635           comment(comment) {}
00636 
00637         unsigned width;
00638         unsigned height;
00639         unsigned bitsPerComponent;       // 1, 2, 4, 8, 16
00640         unsigned charsPerPixel;
00641         unsigned charsPerRow;
00642         unsigned maxComponentValue;
00643         ComponentSpecifier components;
00644         string comment; // UTF-8
00645 
00646         Rep *refClone() const;
00647         void refDelete() throw();
00648 
00649         char *getPixelBuffer()
00650         {
00651           return reinterpret_cast<char *>(this+1);
00652         }
00653 
00654         char *getPixelPtr(int x, int y)
00655         {
00656           return getPixelBuffer() + y*charsPerRow + x*charsPerPixel;
00657         }
00658 
00659         unsigned getComponent(char *pixel, unsigned component);
00660         void setComponent(char *pixel, unsigned component, unsigned v);
00661 
00662         void getPixel(int x, int y, unsigned &l);
00663         void setPixel(int x, int y, unsigned l);
00664         void getPixel(int x, int y, unsigned &l, unsigned &a);
00665         void setPixel(int x, int y, unsigned l, unsigned a);
00666         void getPixel(int x, int y, unsigned &r, unsigned &g, unsigned &b);
00667         void setPixel(int x, int y, unsigned r, unsigned g, unsigned b);
00668         void getPixel(int x, int y, unsigned &r, unsigned &g,
00669                       unsigned &b, unsigned &a);
00670         void setPixel(int x, int y, unsigned r, unsigned g,
00671                       unsigned b, unsigned a);
00672 
00673         double toFloat(unsigned v)
00674         {
00675           return double(v)/maxComponentValue;
00676         }
00677 
00678         unsigned fromFloat(double v)
00679         {
00680           if(v<0) v=0;
00681           else if(v>1) v=1;
00682           return unsigned(v*maxComponentValue+0.5);
00683         }
00684 
00685         void getPixel(int x, int y, double &l)
00686         {
00687           unsigned _l;
00688           getPixel(x, y, _l);
00689           l = toFloat(_l);
00690         }
00691 
00692         void setPixel(int x, int y, double l)
00693         {
00694           setPixel(x, y, fromFloat(l));
00695         }
00696 
00697         void getPixel(int x, int y, double &l, double &a)
00698         {
00699           unsigned _l, _a;
00700           getPixel(x, y, _l, _a);
00701           l = toFloat(_l);
00702           a = toFloat(_a);
00703         }
00704 
00705         void setPixel(int x, int y, double l, double a)
00706         {
00707           setPixel(x, y, fromFloat(l), fromFloat(a));
00708         }
00709 
00710         void getPixel(int x, int y, double &r, double &g, double &b)
00711         {
00712           unsigned _r, _g, _b;
00713           getPixel(x, y, _r, _g, _b);
00714           r = toFloat(_r);
00715           g = toFloat(_g);
00716           b = toFloat(_b);
00717         }
00718 
00719         void setPixel(int x, int y, double r, double g, double b)
00720         {
00721           setPixel(x, y, fromFloat(r), fromFloat(g), fromFloat(b));
00722         }
00723 
00724         void getPixel(int x, int y, double &r, double &g,
00725                       double &b, double &a)
00726         {
00727           unsigned _r, _g, _b, _a;
00728           getPixel(x, y, _r, _g, _b, _a);
00729           r = toFloat(_r);
00730           g = toFloat(_g);
00731           b = toFloat(_b);
00732           a = toFloat(_a);
00733         }
00734 
00735         void setPixel(int x, int y, double r, double g, double b, double a)
00736         {
00737           setPixel(x, y, fromFloat(r), fromFloat(g), fromFloat(b), fromFloat(a));
00738         }
00739       };
00740 
00741       MutaRef<Rep> r;
00742 
00743       void _load(Ref<Stream::Reader>,
00744                  string sourceName, string formatSpecifier,
00745                  ProgressTracker *, Logger *, const Context *)
00746         throw(UnknownFormatException, InvalidFormatException,
00747               IOException, UnexpectedException);
00748 
00749       void _save(Ref<Stream::Writer>,
00750                  string targetName, string formatSpecifier,
00751                  ProgressTracker *, Logger *, const Context *) const
00752         throw(UnknownFormatException, IOException, UnexpectedException);
00753     };
00754   }
00755 }
00756 
00757 #endif // ARCHON_UTILITIES_IMAGE_H

Generated on Sun Jul 30 22:55:44 2006 for Archon by  doxygen 1.4.4