OSDN Git Service

parallel
[psychlops/cpp.git] / psychlops / core / graphic / psychlops_g_image.cpp
1 /*
2  *  psychlops_g_image.cpp
3  *  Psychlops Standard Library (Universal)
4  *
5  *  Last Modified 2006/01/04 by Kenchi HOSOKAWA
6  *  (C) 2006 Kenchi HOSOKAWA, Kazushi MARUYA and Takao SATO
7  */
8
9
10 #include <stdlib.h>
11 #include <Math.h>
12 #include <string.h>
13 #include <iostream>
14 #include <string>
15
16 #define PSYCHLOPS_WINDOW_API_PLATFORM
17 #include "../../platform/psychlops_platform_selector.h"
18 #include "../ApplicationInterfaces/psychlops_app_info.h"
19 #include "../devices/psychlops_io_file.h"
20 #include "../math/psychlops_math.h"
21
22 #include "psychlops_g_fundamental.h"
23 #include "psychlops_g_color.h"
24 #include "psychlops_g_module.h"
25 #include "psychlops_g_shape.h"
26 #include "psychlops_g_canvas.h"
27 #include "psychlops_g_image.h"
28
29 #include "../../extension/FileFormat/PNG/psychlops_g_PNG_bridge.h"
30 #include "../../extension/FileFormat/OpenCV/psychlops_g_OPENCV_bridge.h"
31
32
33 namespace Psychlops {
34
35         ImageCache_::ImageCache_() : id(0), dirty(false) {}
36         ImageCache_::ImageCache_(APIImageCache* id__, bool dirty__) : id(id__), dirty(dirty__) {}
37
38         const int Image::PixCompSize_[3] = { 1, 3, 4 };
39         const int Image::PixPrecSize_[2] = { sizeof(unsigned char), sizeof(float) };
40         int Image::lineBytesAlingnment_ = AppState::ImageByteAlignment;
41
42
43         Image& Image::operator =(const Image &source) {
44                 memcpy(this, &source, sizeof(*this));
45                 return *this;
46         }
47         Image::Image(const Image &readimage){}
48         Image::Image(const Image &readimage, bool dummt) {
49                 initPointersNull();
50                 from(readimage);
51         }
52
53
54
55         ////////        Construst and Destruct  ////////
56
57         Image::Image() {
58                 initPointersNull();
59         }
60
61         Image::Image(std::string filename) {
62                 initPointersNull();
63                 load(filename);
64         }
65         Image::Image(const char * filename) {
66                 initPointersNull();
67                 load(filename);
68         }
69         Image::Image(long x, long y, PixelComponentsCnt pixcomp, PixelComponentsPrecision pixprec) {
70                 initPointersNull();
71                 set(x, y, pixcomp, pixprec);
72         }
73         Image::Image(long x, long y, PixelComponentsPrecision pixprec) {
74                 initPointersNull();
75                 set(x, y, RGB, pixprec);
76         }
77         Image::Image(Rectangle rectangle, PixelComponentsCnt pixcomp, PixelComponentsPrecision pixprec) {
78                 initPointersNull();
79                 set(rectangle, pixcomp, pixprec);
80         }
81         Image::Image(Rectangle rectangle, PixelComponentsPrecision pixprec) {
82                 initPointersNull();
83                 set(rectangle, RGB, pixprec);
84         }
85
86         void Image::setWithoutClear(bool y)
87         {
88                 setWithoutClear_ = y;
89         }
90         bool Image::setWithoutClear_ = false; // OK?
91
92         void Image::set(long x, long y, PixelComponentsPrecision pixprec) {
93                 set(x, y, RGB, pixprec);
94         }
95         void Image::set(Rectangle rectangle, PixelComponentsCnt pixcomp, PixelComponentsPrecision pixprec) {
96                 set((long)rectangle.getWidth(), (long)rectangle.getHeight(), pixcomp, pixprec);
97         }
98         void Image::set(Rectangle rectangle, PixelComponentsPrecision pixprec) {
99                 set(rectangle, RGB, pixprec);
100         }
101         void Image::initPointersNull() {
102                 have_instance_ = false;
103                 //quickened_ = false;
104                 bitmapub_ = NULL;
105                 bitmapf_ = NULL;
106                 width_ = 0;
107                 height_ = 0;
108                 pixcomp_ = RGB;
109                 pixprec_ = BYTE;
110         }
111
112
113         Image::~Image(void) {
114                 release();
115         }
116         void Image::release(){
117                 if(have_instance_) {
118                         if(!caches.empty()) {
119                                 std::vector<DrawableWithCache*> tmp;
120                                 for(CacheID::iterator i=caches.begin(); i!=caches.end(); i++) tmp.push_back(i->first);
121                                 for(int i=0; i<tmp.size(); i++) tmp[i]->uncacheImage(*this);
122                         }
123                         delete api_;
124                         releasebitmap();
125                         have_instance_ = false;
126                 }
127         }
128         void Image::releasebitmap() {
129                 if(have_instance_) {
130                         switch(pixprec_) {
131                                 case BYTE:
132                                         if(bitmapub_ != NULL) delete [] bitmapub_;
133                                         break;
134                                 case FLOAT:
135                                         if(bitmapf_  != NULL) delete [] bitmapf_;
136                                         break;
137                         }
138                 }
139                 initPointersNull();
140         }
141         bool Image::hasInstance() const {
142                 return have_instance_;
143         }
144
145         Image& Image::cache(DrawableWithCache &target) {
146                 target.cacheImage(*this);
147                 return *this;
148         }
149         Image& Image::uncache(DrawableWithCache &target) {
150                 target.uncacheImage(*this);
151                 return *this;
152         }
153
154         Image Image::dup() const {
155                 return Image(*this, true);
156         }
157         Image Image::duplicate() const {
158                 return Image(*this, true);
159         }
160         Image& Image::convert(PixelComponentsCnt pixcompcntval) {
161                 if(!have_instance_) throw Exception(typeid(*this), "Memory Error", "Image had not allocated.");
162                 if(pixcomp_==pixcompcntval) {
163                         return *this;
164                 } else {
165                         Image *tmp = new Image;
166                         tmp->from(*this);
167                         release();
168                         set(tmp->width_, tmp->height_, pixcompcntval, tmp->pixprec_);
169                         targetarea_ = tmp->targetarea_;
170                         localarea_ = tmp->localarea_;
171                         unsigned char *p = bitmapub_;
172                         float *pf = bitmapf_;
173                         double r, g, b, a;
174                         if(pixprec_==BYTE) {
175                                 for(int y=height_-1; y>=0; y--) {
176                                         for(int x=0; x<width_; x++) {
177                                                 tmp->getPix(x,y).get(r, g, b, a);
178                                                 *(p++) = (unsigned char)(r*255.0+.5);
179                                                 if(pixcomp_==RGB||pixcomp_==RGBA) *(p++) = (unsigned char)(g*255.0+.5);
180                                                 if(pixcomp_==RGB||pixcomp_==RGBA) *(p++) = (unsigned char)(b*255.0+.5);
181                                                 if(pixcomp_==RGBA) { *(p++) = (unsigned char)(a*255.0+.5); }
182                                         }
183                                 }
184                         } else {
185                                 for(int y=height_-1; y>=0; y--) {
186                                         for(int x=0; x<width_; x++) {
187                                                 tmp->getPix(x,y).get(r, g, b, a);
188                                                 *(pf++) = r;
189                                                 if(pixcomp_==RGB||pixcomp_==RGBA) *(pf++) = g;
190                                                 if(pixcomp_==RGB||pixcomp_==RGBA) *(pf++) = b;
191                                                 if(pixcomp_==RGBA) { *(pf++) = a; }
192                                         }
193                                 }
194                         }
195                         //if(tmp->quickened_) quicken();
196                         delete tmp;
197                 }
198                 return *this;
199         }
200         Image& Image::convertColorCalibration(bool on_off) {
201                 Color col;
202                 double r, g, b, a;
203                 if(!have_instance_) throw Exception(typeid(*this), "Memory Error", "Image had not allocated.");
204                 Image *tmp = new Image;
205                 tmp->from(*this);
206                 release();
207                 set(tmp->width_, tmp->height_, tmp->pixcomp_, tmp->pixprec_);
208                 targetarea_ = tmp->targetarea_;
209                 localarea_ = tmp->localarea_;
210                 if(on_off) {
211                         for(int y=0; y<height_; y++) {
212                                 for(int x=0; x<width_; x++) {
213                                         col = getPix(x, y);
214                                         r = col.Red;
215                                         g = col.Green;
216                                         b = col.Blue;
217                                         a = col.Alpha;
218                                         col.set(r, g, b, a);
219                                         tmp->pix_direct(x, y, col);
220                                 }
221                         }
222                 } else {
223                         for(int y=0; y<height_; y++) {
224                                 for(int x=0; x<width_; x++) {
225                                         getPix(x, y).get(r,g,b,a);
226                                         col.Red   = r;
227                                         col.Green = g;
228                                         col.Blue  = b;
229                                         col.Alpha = a;
230                                         tmp->pix_direct(x, y, col);
231                                 }
232                         }
233                 }
234                 //if(tmp->quickened_) quicken();
235                 delete tmp;
236
237                 return *this;
238         }
239
240
241         ////////        Drawing ////////
242 /*
243 void Image::pix_ub_bits_mono_(int ix, int iy, double lum) {
244         int x = ix, y = iy;
245         if(0>x || x>width_-1 || y<0 || y>height_-1) throw Exception(typeid(Image), "Out Of Bound Exception", "Specified coordinate is out of bound.");
246         int offset = y*lineValue_ + x*PixCompSize_[pixcomp_];
247         unsigned char *p = bitmapub_ + offset;
248         unsigned short wordlum = (unsigned short)(lum*65535);
249         *(p) = (unsigned char)(wordlum>>8);
250         *(++p) = (unsigned char)(wordlum&255);
251         *(++p) = (unsigned char)0;
252 }
253 */
254         Image& Image::alpha(const double a)
255         {
256                 for(int y=0; y<getHeight(); y++)
257                         for(int x=0; x<getWidth(); x++)
258                                 alpha(x,y,a);
259                 return *this;
260         }
261         Image& Image::alpha(const Matrix &a)
262         {
263                 if(getWidth()!=a.getCols() || getHeight()!=a.getRows() || pixcomp_!=Image::RGBA)
264                         throw Exception(typeid(*this), "Format Error", "Matrix sizes are defferent to Image");
265                 for(int y=0; y<getHeight(); y++)
266                         for(int x=0; x<getWidth(); x++)
267                                 alpha(x,y,a(y+1,x+1));
268                 return *this;
269         }
270         Image& Image::clear(const Color &col) {
271                 //* classic routine
272                 //for(int y=0; y<height_; y++) {
273                 //      for(int x=0; x<width_; x++) {
274                 //              pix_direct_(*this,x,y,col);
275
276                 int x, y;
277                 int yl = 0;
278                 unsigned char* pb;
279                 float* pf;
280                 pix_raw(0, getHeight()-1, col);
281
282                 if(pixprec_ == Image::BYTE) {
283                         if(pixcomp_ == Image::GRAY) {
284                                 pb = bitmapub_;
285                                 for(x=0; x<width_; x++) {
286                                         (*pb++) = *(bitmapub_);
287                                 }
288                         } else if(pixcomp_ == Image::RGB) {
289                                 pb = bitmapub_;
290                                 for(x=0; x<width_; x++) {
291                                         (*pb++) = *(bitmapub_);
292                                         (*pb++) = *(bitmapub_+1);
293                                         (*pb++) = *(bitmapub_+2);
294                                 }
295                         } else if(pixcomp_ == Image::RGBA) {
296                                 pb = bitmapub_;
297                                 for(x=0; x<width_; x++) {
298                                         (*pb++) = *(bitmapub_);
299                                         (*pb++) = *(bitmapub_+1);
300                                         (*pb++) = *(bitmapub_+2);
301                                         (*pb++) = *(bitmapub_+3);
302                                 }
303                         }
304                         for(y=1; y<height_; y++) {
305                                 yl = y*lineValue_;
306                                 pb = bitmapub_ + yl;
307                                 memcpy(pb, bitmapub_, lineValue_);
308                         }
309                 } else if(pixprec_ == Image::FLOAT) {
310                         if(pixcomp_ == Image::GRAY) {
311                                 pf = bitmapf_;
312                                 for(x=0; x<width_; x++) {
313                                         (*pf++) = *(bitmapf_);
314                                 }
315                         } else if(pixcomp_ == Image::RGB) {
316                                 pf = bitmapf_;
317                                 for(x=0; x<width_; x++) {
318                                         (*pf++) = *(bitmapf_);
319                                         (*pf++) = *(bitmapf_+1);
320                                         (*pf++) = *(bitmapf_+2);
321                                 }
322                         } else if(pixcomp_ == Image::RGBA) {
323                                 pf = bitmapf_;
324                                 for(x=0; x<width_; x++) {
325                                         (*pf++) = *(bitmapf_);
326                                         (*pf++) = *(bitmapf_+1);
327                                         (*pf++) = *(bitmapf_+2);
328                                         (*pf++) = *(bitmapf_+3);
329                                 }
330                         }
331                         for(y=1; y<height_; y++) {
332                                 yl = y*lineValue_;
333                                 pf = bitmapf_ + yl;
334                                 memcpy(pf, bitmapf_, lineBytes_);
335                         }
336                 }
337                 return *this;
338         }
339 /*      Image& Image::alpha(const int x, const int iy, const double a) {
340                 Color col(0,0,0,a);
341                 pix(x, iy, col);
342                 return *this;
343         }
344         Image& Image::pix(const double x, const double y, const Color &col) {
345                 pix(Math::round(x), Math::round(y), col);
346                 return *this;
347         }
348         Image& Image::pix(const Point &po, const Color &col) {
349                 pix(Math::round(po.x), Math::round(po.y), col);
350                 return *this;
351         }
352  */
353         void Image::rect(const Rectangle &rectangle, const Color &col) {
354                 Rectangle filledrect(rectangle);
355                 filledrect.cripped(area_);
356                 int t = Math::round(filledrect.top);
357                 int b = Math::round(filledrect.bottom);
358                 int l = Math::round(filledrect.left);
359                 int r = Math::round(filledrect.right);
360                 for(int y=t; y<=b; y++) {
361                         for(int x=l; x<=r; x++) {
362                                 pix(x,y,col);
363                         }
364                 }
365         }
366         void Image::line(const double x1, const double y1, const double x2, const double y2, const Color &col) {
367                 int begin, end, tbegin, ax, ay;
368                 double obegin;
369                 if(x1-x2!=0) {
370                         double slope = (y1-y2)/(x1-x2);
371                         if(slope<1 && slope>-1) {
372                                 if(x1<x2) {
373                                         tbegin = begin = Math::round(x1);
374                                         end =  Math::round(x2);
375                                         obegin = y1;
376                                 } else {
377                                         tbegin = begin = Math::round(x2);
378                                         end =  Math::round(x1);
379                                         obegin = y2;
380                                 }
381                                 begin = ( begin<0 ? 0 : begin );
382                                 end = ( end>width_-1 ? width_-1 : end );
383                                 for(int x=begin; x<=end; x++) {
384                                         ay = Math::round((x-tbegin)*slope + obegin);
385                                         if(-1<x && x<width_ && -1 <ay && ay<height_ ) pix(x, ay, col);
386                                 }
387                         } else {
388                                 if(y1<y2) {
389                                         tbegin = begin = Math::round(y1);
390                                         end =  Math::round(y2);
391                                         obegin = x1;
392                                 } else {
393                                         tbegin = begin = Math::round(y2);
394                                         end =  Math::round(y1);
395                                         obegin = x2;
396                                 }
397                                 begin = ( begin<0 ? 0 : begin );
398                                 end = ( end>height_-1 ? height_-1 : end );
399                                 for(int y=begin; y<=end; y++) {
400                                         ax = Math::round((y-tbegin)/slope + obegin);
401                                         if(-1<ax && ax<width_ && -1<y && y<height_ ) pix(ax, y, col);
402                                 }
403                         }
404                 } else {
405                                 if(y1<y2) {
406                                         tbegin = begin = Math::round(y1);
407                                         end =  Math::round(y2);
408                                         obegin = x1;
409                                 } else {
410                                         tbegin = begin = Math::round(y2);
411                                         end =  Math::round(y1);
412                                         obegin = x2;
413                                 }
414                                 begin = ( begin<0 ? 0 : begin );
415                                 end = ( end>height_-1 ? height_-1 : end );
416                                 ax = Math::round(obegin);
417                                 for(int y=begin; y<=end; y++) {
418                                         if(-1<ax && ax<width_ && -1<y && y<height_ ) pix(ax, y, col);
419                                 }
420                 }
421         }
422         void Image::line(const Point &po1, const Point &po2, const Color &col) {
423                 line(po1.x, po1.y, po2.x, po2.y, col);
424         }
425         void Image::ellipse(const Rectangle &rect, const Color &col) {
426                 double center_x = rect.getCenter().x;
427                 double center_y = rect.getCenter().y;
428                 double radius = rect.getHeight() / 2.0;
429                 double aspect_ratio = rect.getWidth() / rect.getHeight();
430                 double tmp;
431                 int l, t, r, b;
432                 t = ( rect.top < 0 ? 0 : Math::round(rect.top) );
433                 b = ( rect.bottom > height_-1 ? height_-1 : Math::round(rect.bottom) );
434                 for(int y=t; y<=b; y++) {
435                         tmp = ( (y-center_y)/radius );
436                         l = Math::round( center_x - aspect_ratio * ( radius * sqrt(1-(tmp*tmp)) ) );
437                         r = Math::round( ( center_x - l ) + center_x );
438                         l = ( l < 0 ? 0 : l );
439                         r = ( r > width_-1 ? width_-1 : r );
440                         for(int x=l; x<=r; x++) {
441                                 pix(x,y,col);
442                         }
443                 }
444         }
445         //  obsolete
446                 void Image::oval(const Rectangle &rect, const Color &col) {
447                         ellipse(rect, col);
448                 }
449                 void Image::fillRect(const Rectangle &rectangle, const Color &col) {
450                         rect(rectangle, col);
451                 }
452 /*              void Image::msg(Letters &letters, int x, int y, const Color &col) {
453                         api_->drawLetters(letters, x, y,col.Red,col.Blue,col.Green,col.Alpha,0,0);
454                 }
455 */
456
457         Image& Image::draw(double left, double top, Drawable &target) {
458                 target.image(*this, left, top);
459                 return *this;
460         }
461         Image& Image::draw(Drawable &target)  {
462                 target.image(*this);
463                 return *this;
464         }
465         Image& Image::draw(double alpha, Drawable &target)  {
466                 target.image(*this, alpha);
467                 return *this;
468         }
469         // obsolete
470                 void Image::display(double x, double y) {
471                         draw(x, y);
472                 }
473                 void Image::display() {
474                         draw(targetarea_.left, targetarea_.top);
475                 }
476
477
478         Image::PartialView::PartialView(Image *src, const Rectangle &d_source)
479         {
480                 img = src;
481                 source = d_source;
482                 target.set(source.getWidth(), source.getHeight());
483         }
484         Image::PartialView& Image::PartialView::set(double width, double height)
485         {
486                 target.set(width, height);
487                 return *this;
488         }
489         Image::PartialView::~PartialView()
490         {
491         }
492         const Point Image::PartialView::getDatum() const
493         {
494                 return target.getDatum();
495         }
496         Image::PartialView& Image::PartialView::setDatum(const Point &p)
497         {
498                 target.setDatum(p);
499                 return *this;
500         }
501         Image::PartialView& Image::PartialView::centering(const Point &p)
502         {
503                 target.centering(p);
504                 return *this;
505         }
506         Image::PartialView& Image::PartialView::draw(Drawable &target_)
507         {
508                 target_.image(*img, target, source);
509                 return *this;
510         }
511         Image::PartialView Image::operator ()(const Rectangle &view)
512         {
513                 PartialView tmp(this, view);
514                 return tmp;
515         }
516
517
518
519
520         // get bitmap properties
521         const void * Image::getBitmapPtr() const {
522                 if(!have_instance_) Exception(typeid(*this), "Memory Error", "The Image does not have bitmap instance.");
523                 switch(pixprec_) {
524                         case BYTE:
525                                 return (void *)bitmapub_;
526                                 break;
527                         case FLOAT:
528                                 return (void *)bitmapf_;
529                                 break;
530                         default:
531                                 break;
532                 }
533                 return NULL;
534         }
535
536
537         // Coordinate
538         const Point Image::getDatum() const {
539                 return targetarea_.getDatum();
540         }
541         Image& Image::setDatum(const Point& p) {
542                 targetarea_.setDatum(p);
543                 return *this;
544         }
545         Image& Image::centering(const Drawable& target) {
546                 targetarea_.centering(target);
547                 return *this;
548         }
549         Image& Image::centering(const Figure& fig) {
550                 targetarea_.centering(fig);
551                 return *this;
552         }
553         Image& Image::centering(const Point& p) {
554                 targetarea_.centering(p);
555                 return *this;
556         }
557         Image& Image::centering(const double x, const double y, const double z) {
558                 targetarea_.centering(x, y, z);
559                 return *this;
560         }
561         Image& Image::move_to(const double x, const double y, const double z) {
562                 targetarea_.move_to(x, y, z);
563                 return *this;
564         }
565         Image& Image::shift(const double x, const double y, const double z) {
566                 targetarea_.shift(x, y, z);
567                 return *this;
568         }
569         int Image::getWidth() const {   return width_; }
570         int Image::getHeight() const {  return height_; }
571         double Image::getHcenter() const { return width_/2 - 0.5; }
572         double Image::getVcenter() const { return height_/2 - 0.5; }
573         const Point Image::getCenter() const {
574                 Point po(getHcenter(), getVcenter());
575                 return po;
576         }
577         double Image::getTop() const { return targetarea_.top; }
578         double Image::getLeft() const { return targetarea_.left; }
579         double Image::getBottom() const { return targetarea_.bottom; }
580         double Image::getRight() const { return targetarea_.right; }
581
582
583         float* Image::getFloatPrt() { return bitmapf_; }
584         unsigned char* Image::getElementPtr() { return bitmapub_; }
585         int Image::getPixBytes() { return pixBytes_; }
586         int Image::getLineBytes() { return lineBytes_; }
587         int Image::getBitmapBytes() { return bitmapBytes_; }
588         int Image::getLineNumber() { return lineValue_; }
589         int Image::getElementNumber() { return bitmapValue_; }
590         const Image::PixelComponentsCnt Image::getComponentKind() const { return pixcomp_; }\r
591         const Image::PixelComponentsPrecision Image::getPrecisionKind() const { return pixprec_; }
592
593         //// Special Utilities
594
595         void Image::to(const Rectangle &source__, Image &other, const Rectangle target__) const {
596                 Rectangle source = source__, target = target__;
597                 source.clipped_by(area_);
598                 target.clipped_by(other.area_);
599                 if(source.getWidth()!=target.getWidth() || source.getHeight()!=target.getHeight())
600                         throw new Exception("Image.to: source area does not match target area.");
601                 int sl = (int)source.getLeft(), st=(int)source.getTop(), tl=(int)target.getLeft(), tt=(int)target.getTop();
602                 for(int y=0; y<source.getHeight(); y++)
603                         for(int x=0; x<source.getWidth(); x++)
604                                 other.pix_direct(x+tl,y+tt, getPix(x+sl,y+st));
605         }
606         void Image::to(const Rectangle &source__, Image &other) const {
607                 Rectangle source = source__;
608                 source.clipped_by(area_);
609                 other.release();
610                 other.set(source, pixcomp_, pixprec_);
611                 for(int y=0; y<other.getHeight(); y++)
612                         for(int x=0; x<other.getWidth(); x++)
613                                 other.pix_direct(x,y, getPix((int)(source.getLeft())+x, (int)(source.getTop())+y));
614 /*
615                 int vbase = getHeight() - source.getTop();
616                 for(int i=0; i<other.getHeight(); i++) {
617                         memcpy(other.bitmapub_+(other.getHeight()-i-1)*(lineBytes_),
618                                    bitmapub_+(vbase-i-1)*(lineBytes_)+(size_t)(source.getLeft()),
619                                    pixBytes_*other.getWidth());
620                 }
621 */      }
622
623
624
625         void Image::load(std::string filename) {
626                 IMAGE_FORMATS::IMAGE_FORMAT *loader;
627                 if(have_instance_) {
628                         release();
629                 }
630                 std::string::size_type extention_index = filename.find_last_of('.');
631                 if(extention_index==std::string::npos) throw Exception(typeid(*this), "File Type Error", "Specified image type is not supported.*..");
632                 std::string file_extension = filename.substr(extention_index+1);\r
633                 IMAGE_FORMATS::FILE_EXT ext = IMAGE_FORMATS::getImageFileFormatFromExt(file_extension);\r
634                 if(ext==IMAGE_FORMATS::PNG) {
635                         loader = new IMAGE_FORMATS::PNG_BRIDGE;
636                         loader->load(File::decodePath(filename).c_str(), this);
637                         delete loader;
638                 } else if(ext==IMAGE_FORMATS::JPG) {
639                         loader = new IMAGE_FORMATS::OPENCV_BRIDGE;
640                         loader->load(File::decodePath(filename).c_str(), this);
641                         delete loader;
642                 } else if(ext==IMAGE_FORMATS::TIFF) {
643                         loader = new IMAGE_FORMATS::OPENCV_BRIDGE;
644                         loader->load(File::decodePath(filename).c_str(), this);
645                         delete loader;
646                 } else {
647                         throw Exception(typeid(*this), "File Type Error", "Specified image type is not supported.");
648                 }
649                 switch(Color::getCalibrationMode()) {
650                         case Color::SOFTWARE_GAMMA_VALUE:
651                         case Color::SOFTWARE_TABLE:
652                                 convertColorCalibration(true);
653                                 break;
654                         default:
655                                 break;
656                 }
657         }
658         void Image::load(const char * filename) {
659                 load(std::string(filename));
660         }
661         void Image::save(std::string filename) {
662                 IMAGE_FORMATS::IMAGE_FORMAT *loader;
663                 if(!have_instance_) {
664                         throw Exception(typeid(*this), "Memory Error", "Image does not have its instance.");
665                 }
666
667                 Color col;
668                 double r, g, b, a;
669                 Image *tmp;
670                 switch(Color::getCalibrationMode()) {
671                         case Color::SOFTWARE_GAMMA_VALUE:
672                         case Color::SOFTWARE_TABLE:
673                                 tmp = new Image(width_, height_, pixcomp_, pixprec_);
674                                 for(int y=0; y<height_; y++) {
675                                         for(int x=0; x<width_; x++) {
676                                                 col = getPix(x, y);
677                                                 col.get(r, g, b, a);
678                                                 col.Red = r;
679                                                 col.Green = g;
680                                                 col.Blue = b;
681                                                 col.Alpha = a;
682                                                 tmp->pix_direct(x, y, col);
683                                         }
684                                 }
685                                 break;
686                         default:
687                                 tmp = this;
688                                 break;
689                 }
690
691                 std::string::size_type extention_index = filename.find_last_of('.');
692                 if(extention_index==std::string::npos) throw Exception(typeid(*this), "File Type Error", "Specified image type is not supported.");
693                 std::string file_extension = filename.substr(extention_index+1);\r
694                 IMAGE_FORMATS::FILE_EXT ext = IMAGE_FORMATS::getImageFileFormatFromExt(file_extension);
695                 if(ext==IMAGE_FORMATS::PNG) {
696                         loader = new IMAGE_FORMATS::PNG_BRIDGE;
697                         loader->save(File::decodePath(filename).c_str(), tmp);
698                         delete loader;
699                 } else if(ext==IMAGE_FORMATS::JPG) {
700                         loader = new IMAGE_FORMATS::OPENCV_BRIDGE;
701                         loader->save(File::decodePath(filename).c_str(), tmp);
702                         delete loader;
703                 } else if(ext==IMAGE_FORMATS::TIFF) {
704                         loader = new IMAGE_FORMATS::OPENCV_BRIDGE;
705                         loader->save(File::decodePath(filename).c_str(), tmp);
706                         delete loader;
707                 } else {
708                         throw Exception(typeid(*this), "File Type Error", "Specified image type is not supported.");
709                 }
710                 if(tmp != this) delete tmp;
711         }
712         void Image::save(const char * filename) {
713                 save(std::string(filename));
714         }
715
716         void Image::from(const Matrix &mtx) {
717                 Color colour;
718                 if(getWidth()!=mtx.getCols() || getHeight()!=mtx.getRows() || pixcomp_!=Image::GRAY) {
719                         //if (have_instance_==false) set(mtx.getCols(),mtx.getRows(), GRAY);
720                         //else throw Exception(typeid(*this), "Memory Error", "Image has been allocated.");
721                         release();
722                         set(mtx.getCols(),mtx.getRows(), GRAY);
723                 }
724                 int rowmax = mtx.getRows();
725                 int colmax = mtx.getCols();
726                 for(int row=1; row<=rowmax; row++) {
727                         for(int col=1; col<=colmax; col++) {
728                                 //colour.set(mtx(row,col));
729                                 pix_direct(col-1,row-1,mtx(row,col));
730                         }
731                 }
732         }
733         void Image::from(const Matrix &r, const Matrix &g, const Matrix &b) {
734                 Color colour;
735                 if(r.getRows()!=g.getRows() || r.getRows()!=b.getRows()) throw Exception(typeid(*this), "Format Error", "Matrix sizes are defferent between each color.");
736                 if(r.getCols()!=g.getCols() || r.getCols()!=b.getCols()) throw Exception(typeid(*this), "Format Error", "Matrix sizes are defferent between each color.");
737                 if(getWidth()!=r.getCols() || getHeight()!=r.getRows() || pixcomp_!=Image::RGB) {
738                         //if (have_instance_==false) set(r.getCols(),r.getRows(), RGB);
739                         //else throw Exception(typeid(*this), "Memory Error", "Image has been allocated.");
740                         release();
741                         set(r.getCols(),r.getRows(), RGB);
742                 }
743                 int rowmax = r.getRows();
744                 int colmax = r.getCols();
745                 for(int row=1; row<=rowmax; row++) {
746                         for(int col=1; col<=colmax; col++) {
747                                 //colour.set(r(row,col), g(row,col), b(row,col));
748                                 pix_direct(col-1,row-1,r(row,col), g(row,col), b(row,col),1.0);
749                         }
750                 }
751         }
752         void Image::from(const Matrix &r, const Matrix &g, const Matrix &b, const Matrix &a) {
753                 Color colour;
754                 if(r.getRows()!=g.getRows() || r.getRows()!=b.getRows() || r.getRows()!=a.getRows()) throw Exception(typeid(*this), "Format Error", "Matrix sizes are defferent between each color.");
755                 if(r.getCols()!=g.getCols() || r.getCols()!=b.getCols() || r.getCols()!=a.getCols()) throw Exception(typeid(*this), "Format Error", "Matrix sizes are defferent between each color.");
756                 if(getWidth()!=r.getCols() || getHeight()!=r.getRows() || pixcomp_!=Image::RGBA) {
757                         //if (have_instance_==false) set(r.getCols(),r.getRows(), RGBA);
758                         //else throw Exception(typeid(*this), "Memory Error", "Image has been allocated.");
759                         release();
760                         set(r.getCols(),r.getRows(), RGBA);
761                 }
762                 int rowmax = r.getRows();
763                 int colmax = r.getCols();
764                 for(int row=1; row<=rowmax; row++) {
765                         for(int col=1; col<=colmax; col++) {
766                                 //colour.set(r(row,col), g(row,col), b(row,col), a(row,col));
767                                 pix_direct(col-1,row-1,r(row,col), g(row,col), b(row,col), a(row,col));
768                         }
769                 }
770         }
771
772         void Image::to(Matrix &mtx) const {
773                 to(Point(0,0), getWidth(), getHeight(), mtx);
774         }
775         void Image::to(Point p, const Rectangle &rect, Matrix &gray) const {
776                 to(Point(0,0), (int)rect.getWidth(), (int)rect.getHeight(), gray);
777         }
778         void Image::to(const Interval &horiz, const Interval &vert, Matrix &gray) const {
779                 to(Point(horiz.int_floor(0), vert.int_floor(0)),
780                    horiz.int_ceil(getWidth())-horiz.int_floor(0), vert.int_ceil(getHeight())-vert.int_floor(0),
781                    gray);
782         }
783         void Image::to(Point p, int width_, int height_, Matrix &mtx) const {
784                 Color colour;
785                 double r, g, b, a;
786                 double width  = width_+p.x<getWidth()   ? width_  : getWidth()-p.x;
787                 double height = height_+p.y<getHeight() ? height_ : getHeight()-p.y;
788                 if(pixcomp_!=GRAY) throw Exception(typeid(*this), "Argument Error", "Color types of Image(GRAY) and Matrix were not matched.");
789                 if(!have_instance_) throw Exception(typeid(*this), "Memory Error", "Image had not allocated.");
790                 if(width!=mtx.getCols() || height!=mtx.getRows()) { mtx.release(); mtx.set((int)height, (int)width); }
791                 int rowmax = mtx.getRows(), colmax = mtx.getCols();
792                 for(int row=1; row<=rowmax; row++) {
793                         for(int col=1; col<=colmax; col++) {
794                                 colour = getPix((int)(p.x)+col-1, (int)(p.y)+row-1);
795                                 colour.get(r,g,b,a);
796                                 mtx(row,col) = r;
797                         }
798                 }
799         }
800
801         void Image::to(Matrix &r, Matrix &g, Matrix &b) const {
802                 to(Point(0,0), getWidth(), getHeight(), r, g, b);
803         }
804         void Image::to(Point p, const Rectangle &rect, Matrix &r, Matrix &g, Matrix &b) const {
805                 to(Point(0,0), (int)rect.getWidth(), (int)rect.getHeight(), r, g, b);
806         }
807         void Image::to(const Interval &horiz, const Interval &vert, Matrix &r, Matrix &g, Matrix &b) const {
808                 to(Point(horiz.int_floor(0), vert.int_floor(0)),
809                    horiz.int_ceil(getWidth())-horiz.int_floor(0), vert.int_ceil(getHeight())-vert.int_floor(0),
810                    r, g, b);
811         }
812         void Image::to(Point p, int width_, int height_, Matrix &r, Matrix &g, Matrix &b) const {
813                 Color colour;
814                 double rr, gg, bb, aa;
815                 double width  = width_+p.x<getWidth()   ? width_  : getWidth()-p.x;
816                 double height = height_+p.y<getHeight() ? height_ : getHeight()-p.y;
817                 if(pixcomp_!=RGB) throw Exception(typeid(*this), "Argument Error", "Color types of Image(RGB) and Matrix were not matched.");
818                 if(!have_instance_) throw Exception(typeid(*this), "Memory Error", "Image had not allocated.");
819                 if(r.getRows()!=g.getRows() || r.getRows()!=b.getRows()) throw Exception(typeid(*this), "Format Error", "Matrix sizes are defferent between each color.");
820                 if(r.getCols()!=g.getCols() || r.getCols()!=b.getCols()) throw Exception(typeid(*this), "Format Error", "Matrix sizes are defferent between each color.");
821                 if(width!=r.getCols() || height!=r.getRows()) { r.release(); r.set((int)height, (int)width); }
822                 if(width!=g.getCols() || height!=g.getRows()) { g.release(); g.set((int)height, (int)width); }
823                 if(width!=b.getCols() || height!=b.getRows()) { b.release(); b.set((int)height, (int)width); }
824                 int rowmax = r.getRows(), colmax = r.getCols();
825                 for(int row=1; row<=rowmax; row++) {
826                         for(int col=1; col<=colmax; col++) {
827                                 colour = getPix((int)(p.x)+col-1, (int)(p.y)+row-1);
828                                 colour.get(rr,gg,bb,aa);
829                                 r(row,col) = rr;
830                                 g(row,col) = gg;
831                                 b(row,col) = bb;
832                         }
833                 }
834         }
835
836         void Image::to(Matrix &r, Matrix &g, Matrix &b, Matrix &a) const {
837                 to(Point(0,0), getWidth(), getHeight(), r, g, b, a);
838         }
839         void Image::to(Point p, const Rectangle &rect, Matrix &r, Matrix &g, Matrix &b, Matrix &a) const {
840                 to(Point(0,0), (int)rect.getWidth(), (int)rect.getHeight(), r, g, b, a);
841         }
842         void Image::to(const Interval &horiz, const Interval &vert, Matrix &r, Matrix &g, Matrix &b, Matrix &a) const {
843                 to(Point(horiz.int_floor(0), vert.int_floor(0)),
844                    horiz.int_ceil(getWidth())-horiz.int_floor(0), vert.int_ceil(getHeight())-vert.int_floor(0),
845                    r, g, b, a);
846         }
847         void Image::to(Point p, int width_, int height_, Matrix &r, Matrix &g, Matrix &b, Matrix &a) const {
848                 Color colour;
849                 double rr, gg, bb, aa;
850                 double width  = width_+p.x<getWidth()   ? width_  : getWidth()-p.x;
851                 double height = height_+p.y<getHeight() ? height_ : getHeight()-p.y;
852                 if(pixcomp_!=RGBA) throw Exception(typeid(*this), "Argument Error", "Color types of Image(RGBA) and Matrix were not matched.");
853                 if(!have_instance_) throw Exception(typeid(*this), "Memory Error", "Image had not allocated.");
854                 if(r.getRows()!=g.getRows() || r.getRows()!=b.getRows() || r.getRows()!=a.getRows()) throw Exception(typeid(*this), "Format Error", "Matrix sizes are defferent between each color.");
855                 if(r.getCols()!=g.getCols() || r.getCols()!=b.getCols() || r.getCols()!=a.getCols()) throw Exception(typeid(*this), "Format Error", "Matrix sizes are defferent between each color.");
856                 if(width!=r.getCols() || height!=r.getRows()) { r.release(); r.set((int)height, (int)width); }
857                 if(width!=g.getCols() || height!=g.getRows()) { g.release(); g.set((int)height, (int)width); }
858                 if(width!=b.getCols() || height!=b.getRows()) { b.release(); b.set((int)height, (int)width); }
859                 if(width!=a.getCols() || height!=a.getRows()) { a.release(); a.set((int)height, (int)width); }
860                 int rowmax = r.getRows(), colmax = r.getCols();
861                 for(int row=1; row<=rowmax; row++) {
862                         for(int col=1; col<=colmax; col++) {
863                                 colour = getPix((int)(p.x)+col-1, (int)(p.y)+row-1);
864                                 colour.get(rr,gg,bb,aa);
865                                 r(row,col) =  rr;
866                                 g(row,col) =  gg;
867                                 b(row,col) =  bb;
868                                 a(row,col) =  aa;
869                         }
870                 }
871         }
872
873                 //test
874                 Image & Image::operator -=(Image &rhs) {
875                         if(pixcomp_!=rhs.pixcomp_) throw Exception(typeid(*this), "Format Error", "Difference must be resolved between same format Images.");
876                         if(pixprec_!=rhs.pixprec_) throw Exception(typeid(*this), "Format Error", "Difference must be resolved between same format Images.");
877                         if(width_!=rhs.width_) throw Exception(typeid(*this), "Format Error", "Difference must be resolved between same format Images.");
878                         if(height_!=rhs.height_) throw Exception(typeid(*this), "Format Error", "Difference must be resolved between same format Images.");
879
880                         unsigned char *pb=bitmapub_, *qb=rhs.bitmapub_;
881                         float *pf=bitmapf_, *qf=bitmapf_;
882
883                         switch(pixprec_) {
884                                 case BYTE:
885                                         for(int i=0; i<bitmapValue_; i++) {
886                                                 pb[i] -= qb[i];
887                                                 if(pb[i]<0) pb[i] = -pb[i];
888                                                 if(pb[i]>15) pb[i]=256; else pb[i]*=16;
889                                         }
890                                         break;
891                                 case FLOAT:
892                                         for(int i=0; i<bitmapValue_; i++) {
893                                                 pf[i] -= qf[i];
894                                                 if(pf[i]<0) pf[i] = -pf[i];
895                                                 if(pf[i]>15) pf[i]=256; else pf[i]*=16;
896                                         }
897                                         break;
898                         }
899                         return *this;
900                 }
901
902 namespace IMAGE_FORMATS {\r
903 \r
904         FILE_EXT getImageFileFormatFromExt(const std::string &s) {\r
905                 std::string ext = s;\r
906                 std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);\r
907                 if(ext=="png") {\r
908                         return PNG;\r
909                 } else if(ext=="jpg") {\r
910                         return JPG;\r
911                 } else if(ext=="jpeg") {\r
912                         return JPG;\r
913                 } else if(ext=="jp2") {\r
914                         return JP2;\r
915                 } else if(ext=="tiff") {\r
916                         return TIFF;\r
917                 } else if(ext=="cvmat") {\r
918                         return CVMAT_TXT;\r
919                 } else if(ext=="mat") {\r
920                         return MATLAB_MAT;\r
921                 } else {\r
922                         return UNKNOWN;\r
923                 }\r
924         }\r
925 \r
926
927         IMAGE_FORMAT::~IMAGE_FORMAT() {
928         }
929         void IMAGE_FORMAT::readTargetMemoryAlignment(Image *target) {
930                 target_bitmap_ub_ = target->bitmapub_;
931                 target_bytes_per_line_ = target->lineBytes_;
932                 pix_components_ = target->pixcomp_;
933                 pix_precision_ = target->pixprec_;
934         }
935 }
936
937 }       /*      <- namespace Psycholops         */
938