00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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;
00640 unsigned charsPerPixel;
00641 unsigned charsPerRow;
00642 unsigned maxComponentValue;
00643 ComponentSpecifier components;
00644 string comment;
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