OSDN Git Service

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