OSDN Git Service

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