Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

/home/landauf/painter/miniproject/image/imagergba.cpp

Go to the documentation of this file.
00001 //
00002 //    Title: imagergba.cc
00003 //  Created: Tue Oct  2 19:03:11 2001
00004 //   Author: Tim Weyrich <weyrich@inf.ethz.ch>
00005 //
00006 // copyright (c) 2001--2003, Computer Graphics Laboratory, ETH Zuerich
00007 //
00008 
00009 #include <stdlib.h>
00010 #include <string.h>
00011 #include <assert.h>
00012 #include <iostream>
00013 #include <math.h>
00014 
00015 #include "imagergba.h"
00016 #include "clip.h"
00017 
00018 #include <tiff.h>
00019 #include <tiffio.h>
00020 
00021 #define  HAVE_BIGENDIAN  (*(unsigned short *)"12" == 0x3132)
00022 
00023 #define  SWAP_UINT32(x)  (( ((unsigned long)(x) << 24) |  ((((unsigned long)(x)) & 0x0000ff00UL) <<  8) |  ((((unsigned long)(x)) & 0x00ff0000UL) >>  8) |  ( ((unsigned long)(x)) >> 24)))
00024 /*
00025 Rgba::Rgba(unsigned char _r, unsigned char _g, unsigned char _b, unsigned char _a)
00026 {
00027     r = _r;
00028     g = _g;
00029     b = _b;
00030     a = _a;
00031 }
00032 
00033 void Rgba::set(unsigned char _r, unsigned char _g, unsigned char _b, unsigned char _a)
00034 {
00035     r = _r;
00036     g = _g;
00037     b = _b;
00038     a = _a;
00039 }*/
00040 
00042 
00043 ImageRGBA  *imageRgbaNew(int width, int height)
00051 {
00052   ImageRGBA  *result = NULL;
00053   
00054   assert(width >= 0);
00055   assert(height >= 0);
00056 
00057   result = (ImageRGBA *)malloc(sizeof(ImageRGBA));
00058   result->width = width;
00059   result->height = height;
00060   result->bytesPerPixel = 4;
00061   result->data = (Rgba *)malloc(width * height * sizeof(Rgba));
00062 
00063   return result;
00064 }
00065 
00066 void  imageRgbaFree(ImageRGBA *img)
00073 {
00074   assert(img->bytesPerPixel == sizeof(Rgba));
00075   delete img->data;
00076   delete img;
00077 }
00078 
00079 // ----------------------------------------------------------------------------
00080 
00081 ImageRGBA  *imageRgbaClone(const ImageRGBA *img)
00088 {
00089   assert(img->bytesPerPixel == sizeof(Rgba));
00090   
00091   ImageRGBA  *result = imageRgbaNew(img->width, img->height);
00092 
00093   if (result)
00094     memcpy(result->data, img->data, img->width * img->height * sizeof(Rgba));
00095   
00096   return result;
00097 }
00098 
00099 
00100 // ----------------------------------------------------------------------------
00101 
00102 void  imageRgbaCopy(const ImageRGBA *src, const ImageRGBA *dest)
00109 {
00110   assert(src->height == dest->height && src->width == dest->width);
00111   
00112   memcpy(dest->data, src->data, src->width * src->height * sizeof(Rgba));
00113  
00114 }
00115 
00117 
00118 void  imageRgbaClear(ImageRGBA *img)
00125 {
00126   assert(img->bytesPerPixel == sizeof(Rgba));
00127   imageRgbaSet(img, 255, 255, 255, 255);
00128 }
00129 
00130 void  imageRgbaSet(ImageRGBA *img,
00131                    unsigned r, unsigned g, unsigned b, unsigned a)
00136 {
00137   assert(img->bytesPerPixel == sizeof(Rgba));
00138   
00139   Rgba   val = {r, g, b, a};
00140   Rgba  *p, *e = img->data + img->width * img->height;
00141 
00142   for (p=img->data; p<e; *p++=val);
00143 }
00144 
00145 void imageRgbaSetArea(ImageRGBA *img, int x0, int y0, int x1, int y1, Rgba color)
00146 {
00147     for (int y = y0; y < y1; y++)
00148     {
00149         for (int x = x0; x < x1; x++)
00150         {
00151             img->data[x + img->width * y] = color;
00152         }
00153     }
00154 }
00155 
00157 
00158 ImageRGBA  *imageRgbaReadTIFF(const char *fname)
00167 {
00168   TIFF  *tif;
00169   if ((tif = TIFFOpen(fname, "r")) != NULL)
00170     {
00171       ImageRGBA  *result = NULL;
00172       uint32      width, height;
00173 
00174       TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
00175       TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
00176       
00177       if ((result = imageRgbaNew(width, height)) != NULL)
00178         {
00179           if (TIFFReadRGBAImage(tif, result->width, result->height, (uint32 *)result->data, 0))
00180             { /* success -- flip image and eventually twiddle bytes
00181                  (watch out: I'm doing dirty tricks, assuming a
00182                  special memory layout of struct Rgba) */
00183               unsigned long  *p, *q, temp;
00184               int             c;
00185               
00186               if (HAVE_BIGENDIAN)
00187                 {
00188                   for (p=(unsigned long *)result->data,
00189                          q=(unsigned long *)result->data+(result->height-1)*result->width;
00190                        p < q;
00191                        p+=result->width, q-=result->width)
00192                     for (c=result->width-1; c>=0; c--)
00193                       {
00194                         temp=p[c];
00195                         p[c]=SWAP_UINT32(q[c]);
00196                         q[c]=SWAP_UINT32(temp);
00197                       }
00198                   
00199                   if (p == q)
00200                     for (c=result->width-1; c>=0; c--)
00201                       { p[c]=SWAP_UINT32(p[c]); }
00202                 }
00203               else
00204                 {
00205                   unsigned long  *p, *q, temp;
00206                   int             c;
00207                   for (p=(unsigned long *)result->data,
00208                          q=(unsigned long *)result->data+(result->height-1)*result->width;
00209                        p < q;
00210                        p+=result->width, q-=result->width)
00211                     for (c=result->width-1; c>=0; c--)
00212                       {
00213                         temp=p[c];
00214                         p[c]=q[c];
00215                         q[c]=temp;
00216                       }
00217                 }
00218             }
00219           else
00220             {
00221               imageRgbaFree(result);
00222 //              TIFFClose(tif);
00223               result = NULL;
00224             }
00225         }
00226 
00227       TIFFClose(tif);
00228       return result;
00229     }
00230   
00231   return NULL;
00232 }
00233 
00234 int  imageRgbaWriteTIFF(const char *fname, const ImageRGBA *img)
00244 {
00245   assert(img->bytesPerPixel == sizeof(Rgba));
00246   
00247   TIFF  *tif;
00248   if ((tif = TIFFOpen(fname, "w")) != NULL)
00249     {
00250       int  y;
00251 
00252       TIFFSetField(tif, TIFFTAG_SUBFILETYPE, 0);
00253       TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, img->width);
00254       TIFFSetField(tif, TIFFTAG_IMAGELENGTH, img->height);
00255       TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 4);
00256       TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8, 8, 8, 8);
00257       TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_PACKBITS);
00258       TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
00259       TIFFSetField(tif, TIFFTAG_DOCUMENTNAME, fname);
00260       TIFFSetField(tif, TIFFTAG_IMAGEDESCRIPTION, "Created With My Personal Painter Application :-)");
00261       TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
00262       TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 64);
00263       TIFFSetField(tif, TIFFTAG_XRESOLUTION, 75.0);
00264       TIFFSetField(tif, TIFFTAG_YRESOLUTION, 75.0);
00265       TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
00266       TIFFSetField(tif, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
00267 
00268       for (y=0; y<img->height; y++)
00269         if (TIFFWriteScanline(tif, img->data+y*img->width, y, 0) < 0)
00270           break;
00271 
00272       if (y < img->height)
00273         {
00274           //cerr << "Error while writing to TIFF file." << endl;
00275           TIFFClose(tif);
00276           return 1;
00277         }
00278       else
00279         {
00280           TIFFClose(tif);
00281           return 0;
00282         }
00283     }
00284   else
00285     //cerr << "Couldn't open `" << fname << "' for writing." << endl;
00286   
00287   return 1;
00288 }
00289 
00291 
00292 void  imageRgbaDrawLine (ImageRGBA *img, int x0, int y0, int x1, int y1, Rgba colorValue, int lx0, int ly0, int lx1, int ly1)
00293 {
00294   if (lx1 == -1)
00295     lx1 = img->width;
00296   if (ly1 == -1)
00297     ly1 = img->height;
00298     
00299   // clip line
00300   {
00301     float  x[2] = {(float)x0, (float)x1};
00302     float  y[2] = {(float)y0, (float)y1};
00303 
00304     if (clip(x, y, 0, 0, (float)img->width-1, (float)img->height-1) == 2)
00305       return;
00306 
00307     x0 = (int)floor(x[0] + 0.5);
00308     y0 = (int)floor(y[0] + 0.5);
00309     x1 = (int)floor(x[1] + 0.5);
00310     y1 = (int)floor(y[1] + 0.5);
00311   }
00312   
00313   // starting point of line
00314   int x = x0, y = y0;
00315 
00316   // direction of line
00317   int dx = x1-x0, dy = y1-y0;
00318 
00319   // increment or decrement depending on direction of line
00320   int sx = (dx > 0 ? 1 : (dx < 0 ? -1 : 0));
00321   int sy = (dy > 0 ? 1 : (dy < 0 ? -1 : 0));
00322 
00323   // decision parameters for voxel selection
00324   if ( dx < 0 ) dx = -dx;
00325   if ( dy < 0 ) dy = -dy;
00326   int ax = 2*dx, ay = 2*dy;
00327   int decx, decy;
00328 
00329   // determine largest direction component, single-step related variable
00330   int max = dx, var = 0;
00331   if ( dy > max ) { var = 1; }
00332 
00333   // traverse Bresenham line
00334   switch ( var )
00335     {
00336     case 0:  // single-step in x-direction
00337       for (decy=ay-dx; ; x += sx, decy += ay)
00338         {
00339           // process pixel
00340           if (x >= lx0 && x <= lx1 && y >= ly0 && y <= ly1)
00341               img->data[x + y*img->width] = colorValue;
00342 
00343           // take Bresenham step
00344           if ( x == x1 ) break;
00345           if ( decy >= 0 ) { decy -= ax; y += sy; }
00346         }
00347       break;
00348     case 1:  // single-step in y-direction
00349       for (decx=ax-dy; ; y += sy, decx += ax)
00350         {
00351           // process pixel
00352           if (x >= lx0 && x <= lx1 && y >= ly0 && y <= ly1)
00353               img->data[x + y*img->width] = colorValue;
00354 
00355           // take Bresenham step
00356           if ( y == y1 ) break;
00357           if ( decx >= 0 ) { decx -= ay; x += sx; }
00358         }
00359       break;
00360     }
00361 }
00362 
00364 
00365 void  imageRgbaInvertLine(ImageRGBA *img, int x0, int y0, int x1, int y1, int lx0, int ly0, int lx1, int ly1)
00366 {
00367   if (lx1 == -1)
00368     lx1 = img->width;
00369   if (ly1 == -1)
00370     ly1 = img->height;
00371     
00372   // clip line
00373   {
00374     float  x[2] = {(float)x0, (float)x1};
00375     float  y[2] = {(float)y0, (float)y1};
00376 
00377     if (clip(x, y, 0.0f, 0.0f, (float)(img->width-1), (float)(img->height-1)) == 2)
00378       return;
00379 
00380     x0 = (int)floor(x[0] + 0.5);
00381     y0 = (int)floor(y[0] + 0.5);
00382     x1 = (int)floor(x[1] + 0.5);
00383     y1 = (int)floor(y[1] + 0.5);
00384   }
00385   
00386   // starting point of line
00387   int x = x0, y = y0;
00388 
00389   // direction of line
00390   int dx = x1-x0, dy = y1-y0;
00391 
00392   // increment or decrement depending on direction of line
00393   int sx = (dx > 0 ? 1 : (dx < 0 ? -1 : 0));
00394   int sy = (dy > 0 ? 1 : (dy < 0 ? -1 : 0));
00395 
00396   // decision parameters for voxel selection
00397   if ( dx < 0 ) dx = -dx;
00398   if ( dy < 0 ) dy = -dy;
00399   int ax = 2*dx, ay = 2*dy;
00400   int decx, decy;
00401 
00402   // determine largest direction component, single-step related variable
00403   int max = dx, var = 0;
00404   if ( dy > max ) { var = 1; }
00405 
00406   // traverse Bresenham line
00407   switch ( var )
00408     {
00409     case 0:  // single-step in x-direction
00410       for (decy=ay-dx; ; x += sx, decy += ay)
00411         {
00412           // process pixel
00413           if (x >= lx0 && x <= lx1 && y >= ly0 && y <= ly1)
00414           {
00415               img->data[x + y*img->width].r = 255 - img->data[x + y*img->width].r;
00416               img->data[x + y*img->width].g = 255 - img->data[x + y*img->width].g;
00417               img->data[x + y*img->width].b = 255 - img->data[x + y*img->width].b;
00418           }
00419 
00420           // take Bresenham step
00421           if ( x == x1 ) break;
00422           if ( decy >= 0 ) { decy -= ax; y += sy; }
00423         }
00424       break;
00425     case 1:  // single-step in y-direction
00426       for (decx=ax-dy; ; y += sy, decx += ax)
00427         {
00428           // process pixel
00429           if (x >= lx0 && x <= lx1 && y >= ly0 && y <= ly1)
00430           {
00431               img->data[x + y*img->width].r = 255 - img->data[x + y*img->width].r;
00432               img->data[x + y*img->width].g = 255 - img->data[x + y*img->width].g;
00433               img->data[x + y*img->width].b = 255 - img->data[x + y*img->width].b;
00434           }
00435 
00436           // take Bresenham step
00437           if ( y == y1 ) break;
00438           if ( decx >= 0 ) { decx -= ay; x += sx; }
00439         }
00440       break;
00441     }
00442 }
00443 
00445 
00446 void imageRgbaDrawHorizontalAreaLine(ImageRGBA *img, int x0, int x1, int y, int colorOffset)
00447 {
00448     char color;
00449     int location;
00450     for (int x = x1; x >= x0; x--)
00451     {
00452         if ((colorOffset % 8) < 4)
00453             color = 0;
00454         else
00455             color = 255;
00456         
00457         location = x + img->width * y;
00458         img->data[location].r = color;
00459         img->data[location].g = color;
00460         img->data[location].b = color;
00461         img->data[location].a = 255;
00462         colorOffset++;
00463     }
00464 }
00465 
00466 void imageRgbaDrawVerticalAreaLine(ImageRGBA *img, int y0, int y1, int x, int colorOffset)
00467 {
00468     char color;
00469     int location;
00470     for (int y = y1; y >= y0; y--)
00471     {
00472         if ((colorOffset % 8) < 4)
00473             color = 0;
00474         else
00475             color = 255;
00476 
00477         location = x + img->width * y;
00478         img->data[location].r = color;
00479         img->data[location].g = color;
00480         img->data[location].b = color;
00481         img->data[location].a = 255;
00482         colorOffset++;
00483     }
00484 }
00485 
00487 
00488 /* draw ellipse incrementally using Bresenham's algorithm */
00489 void  imageRgbaDrawEllipse(ImageRGBA *img, int cx, int cy, int halfaxis_x, int halfaxis_y, Rgba colorValue, int lx0, int ly0, int lx1, int ly1)
00490 {
00491     if (lx1 == -1)
00492         lx1 = img->width;
00493     if (ly1 == -1)
00494         ly1 = img->height;
00495         
00496         halfaxis_x = abs(halfaxis_x);
00497 
00498         /* intermediate terms to speed up loop */
00499         long t1 = halfaxis_x*halfaxis_x, t2 = t1<<1, t3 = t2<<1;
00500         long t4 = halfaxis_y*halfaxis_y, t5 = t4<<1, t6 = t5<<1;
00501         long t7 = halfaxis_x*t5, t8 = t7<<1, t9 = 0L;
00502         long d1 = t2 - t7 + (t4>>1);    /* error terms */
00503         long d2 = (t1>>1) - t8 + t5;
00504 
00505         int x = halfaxis_x, y = 0;      /* ellipse points */
00506 
00507         while (d2 < 0)                  /* til slope = -1 */
00508         {
00509                 /* draw 4 points using symmetry */
00510         if ((cx + x) >= lx0 && (cx + x) <= lx1 && (cy + y) >= ly0 && (cy + y) <= ly1)
00511             imageRgbaDrawPoint(img, cx + x, cy + y, colorValue);
00512         if ((cx + x) >= lx0 && (cx + x) <= lx1 && (cy - y) >= ly0 && (cy - y) <= ly1)
00513             imageRgbaDrawPoint(img, cx + x, cy - y, colorValue);
00514         if ((cx - x) >= lx0 && (cx - x) <= lx1 && (cy + y) >= ly0 && (cy + y) <= ly1)
00515             imageRgbaDrawPoint(img, cx - x, cy + y, colorValue);
00516         if ((cx - x) >= lx0 && (cx - x) <= lx1 && (cy - y) >= ly0 && (cy - y) <= ly1)
00517             imageRgbaDrawPoint(img, cx - x, cy - y, colorValue);
00518 
00519                 y++;            /* always move up here */
00520                 t9 += t3;       
00521                 if (d1 < 0)     /* move straight up */
00522                 {
00523                         d1 += t9 + t2;
00524                         d2 += t9;
00525                 }
00526                 else            /* move up and left */
00527                 {
00528                         x--;
00529                         t8 -= t6;
00530                         d1 += t9 + t2 - t8;
00531                         d2 += t9 + t5 - t8;
00532                 }
00533         }
00534 
00535         while (x >= 0)                          /* rest of top right quadrant */
00536         {
00537                 /* draw 4 points using symmetry */
00538         if ((cx + x) >= lx0 && (cx + x) <= lx1 && (cy + y) >= ly0 && (cy + y) <= ly1)
00539             imageRgbaDrawPoint(img, cx + x, cy + y, colorValue);
00540         if ((cx + x) >= lx0 && (cx + x) <= lx1 && (cy - y) >= ly0 && (cy - y) <= ly1)
00541             imageRgbaDrawPoint(img, cx + x, cy - y, colorValue);
00542         if ((cx - x) >= lx0 && (cx - x) <= lx1 && (cy + y) >= ly0 && (cy + y) <= ly1)
00543             imageRgbaDrawPoint(img, cx - x, cy + y, colorValue);
00544         if ((cx - x) >= lx0 && (cx - x) <= lx1 && (cy - y) >= ly0 && (cy - y) <= ly1)
00545             imageRgbaDrawPoint(img, cx - x, cy - y, colorValue);
00546 
00547                 x--;            /* always move left here */
00548                 t8 -= t6;       
00549                 if (d2 < 0)     /* move up and left */
00550                 {
00551                         y++;
00552                         t9 += t3;
00553                         d2 += t9 + t5 - t8;
00554                 }
00555                 else            /* move straight left */
00556                         d2 += t5 - t8;
00557         } 
00558 }
00559 
00561 
00562 /* draw ellipse incrementally using Bresenham's algorithm */
00563 void  imageRgbaInvertEllipse(ImageRGBA *img, int cx, int cy, int halfaxis_x, int halfaxis_y)
00564 {
00565         halfaxis_x = abs(halfaxis_x);
00566         
00567         /* intermediate terms to speed up loop */
00568         long t1 = halfaxis_x*halfaxis_x, t2 = t1<<1, t3 = t2<<1;
00569         long t4 = halfaxis_y*halfaxis_y, t5 = t4<<1, t6 = t5<<1;
00570         long t7 = halfaxis_x*t5, t8 = t7<<1, t9 = 0L;
00571         long d1 = t2 - t7 + (t4>>1);    /* error terms */
00572         long d2 = (t1>>1) - t8 + t5;
00573 
00574         int x = halfaxis_x, y = 0;      /* ellipse points */
00575 
00576         while (d2 < 0)                  /* til slope = -1 */
00577         {
00578                 /* draw 4 points using symmetry */
00579                 imageRgbaDrawInvertedPoint(img, cx + x, cy + y);
00580             imageRgbaDrawInvertedPoint(img, cx + x, cy - y);
00581             imageRgbaDrawInvertedPoint(img, cx - x, cy + y);
00582             imageRgbaDrawInvertedPoint(img, cx - x, cy - y);
00583 
00584                 y++;            /* always move up here */
00585                 t9 += t3;       
00586                 if (d1 < 0)     /* move straight up */
00587                 {
00588                         d1 += t9 + t2;
00589                         d2 += t9;
00590                 }
00591                 else            /* move up and left */
00592                 {
00593                         x--;
00594                         t8 -= t6;
00595                         d1 += t9 + t2 - t8;
00596                         d2 += t9 + t5 - t8;
00597                 }
00598         }
00599 
00600         while (x >= 0)                          /* rest of top right quadrant */
00601         {
00602                 /* draw 4 points using symmetry */
00603                 imageRgbaDrawInvertedPoint(img, cx + x, cy + y);
00604             imageRgbaDrawInvertedPoint(img, cx + x, cy - y);
00605             imageRgbaDrawInvertedPoint(img, cx - x, cy + y);
00606             imageRgbaDrawInvertedPoint(img, cx - x, cy - y);
00607 
00608                 x--;            /* always move left here */
00609                 t8 -= t6;       
00610                 if (d2 < 0)     /* move up and left */
00611                 {
00612                         y++;
00613                         t9 += t3;
00614                         d2 += t9 + t5 - t8;
00615                 }
00616                 else            /* move straight left */
00617                         d2 += t5 - t8;
00618         } 
00619 }
00620 
00622 
00623 inline void  imageRgbaDrawPoint(ImageRGBA *img, int x, int y, Rgba colorValue)
00624 {
00625         // process pixel
00626         if (x >= 0 && y >= 0 && x < img->width && y < img->height) {    
00627         img->data[x + y*img->width] = colorValue;
00628         }
00629 }
00630 
00632 
00633 inline void  imageRgbaDrawInvertedPoint(ImageRGBA *img, int x, int y)
00634 {
00635         // process pixel
00636         if (x >= 0 && y >= 0 && x < img->width && y < img->height) {    
00637         img->data[x + y*img->width].r = 255 - img->data[x + y*img->width].r;
00638         img->data[x + y*img->width].g = 255 - img->data[x + y*img->width].g;
00639         img->data[x + y*img->width].b = 255 - img->data[x + y*img->width].b;
00640         }
00641 }
00642 
00644 // Interpolates between the 4 surrounding pixels
00646 
00647 Rgba imageRgbaInterpolate(ImageRGBA *img, float x, float y)
00648 {
00649     const int w = img->width;
00650     const int h = img->height;
00651     int ix, iy, iix, iiy;
00652     float fx, fy, dfx, dfy;
00653     
00654     if (x < 0)
00655         x = 0;
00656     if (y < 0)
00657         y = 0;
00658     if (y > (h-1))
00659         y = h-1;
00660     if (x > (w-1))
00661         x = w-1;
00662 
00663     ix = int(x);
00664     iy = int(y);
00665     
00666     iix = ix + 1;
00667     iiy = iy + 1;
00668     if (iix > (w-1))
00669         iix = 0;
00670     if (iiy > (h-1))
00671         iiy = 0;
00672 
00673     fx = x - ix;
00674     fy = y - iy;
00675     dfx = 1 - fx;
00676     dfy = 1 - fy;
00677         
00678     Rgba interpolated;
00679     Rgba top, bottom;
00680     Rgba topleft, topright, bottomleft, bottomright;
00681 
00682     topleft = img->data[ix + w*iy];
00683     topright = img->data[iix + w*iy];
00684     bottomleft = img->data[ix + w*iiy];
00685     bottomright = img->data[iix + w*iiy];
00686 
00687     top.r = int(dfx*topleft.r + fx*topright.r);
00688     top.g = int(dfx*topleft.g + fx*topright.g);
00689     top.b = int(dfx*topleft.b + fx*topright.b);
00690 //    top.a = int(dfx*topleft.a + fx*topright.a);
00691 
00692     bottom.r = int(dfx*bottomleft.r + fx*bottomright.r);
00693     bottom.g = int(dfx*bottomleft.g + fx*bottomright.g);
00694     bottom.b = int(dfx*bottomleft.b + fx*bottomright.b);
00695 //    bottom.a = int(dfx*bottomleft.a + fx*bottomright.a);
00696 
00697     interpolated.r = int(dfy*top.r + fy*bottom.r);
00698     interpolated.g = int(dfy*top.g + fy*bottom.g);
00699     interpolated.b = int(dfy*top.b + fy*bottom.b);
00700 //    interpolated.a = int(dfy*top.a + fy*bottom.a);
00701     interpolated.a = 255;
00702 
00703     return interpolated;
00704 }
00705 
00706 int imageRgbaInterpolateSubImage(ImageRGBA *img, float x, float y, int w, int h, int offset)
00707 {
00708     int ix, iy, iix, iiy;
00709     float fx, fy, dfx, dfy;
00710     
00711     ix = int(x);
00712     iy = int(y);
00713     
00714     if (ix < 0)
00715     {
00716         ix += w;
00717         x += w;
00718     }
00719     if (iy < 0)
00720     {
00721         iy += h;
00722         y += h;
00723     }
00724     if (ix > (w-1))
00725     {
00726         ix -= w;
00727         x -= w;
00728     }
00729     if (iy > (h-1))
00730     {
00731         iy -= h;
00732         y -= h;
00733     }
00734 
00735 
00736     fx = x - ix;
00737     fy = y - iy;
00738     dfx = 1 - fx;
00739     dfy = 1 - fy;
00740     
00741     iix = ix + 1;
00742     iiy = iy + 1;
00743     if (iix > (w-1))
00744         iix -= w;
00745     if (iiy > (h-1))
00746         iiy -= h;
00747         
00748         
00749     int interpolated;
00750     int top, bottom;
00751     int topleft, topright, bottomleft, bottomright;
00752 
00753     topleft = img->data[offset + ix + w*iy].r;
00754     topright = img->data[offset + iix + w*iy].r;
00755     bottomleft = img->data[offset + ix + w*iiy].r;
00756     bottomright = img->data[offset + iix + w*iiy].r;
00757 
00758     top = int(dfx*topleft + fx*topright);
00759     bottom = int(dfx*bottomleft + fx*bottomright);
00760 
00761     interpolated = int(dfy*top + fy*bottom);
00762 
00763     return interpolated;
00764 }
00765 
00766 Rgba imageRgbaInterpolateColors(float x, float y, Rgba topleft, Rgba topright, Rgba bottomleft, Rgba bottomright)
00767 {
00768     int ix, iy;
00769     float fx, fy, dfx, dfy;
00770     
00771     ix = int(x);
00772     iy = int(y);
00773     fx = x - ix;
00774     fy = y - iy;
00775     dfx = 1 - fx;
00776     dfy = 1 - fy;
00777         
00778     Rgba interpolated;
00779     Rgba top, bottom;
00780 
00781     top.r = int(dfx*topleft.r + fx*topright.r);
00782     top.g = int(dfx*topleft.g + fx*topright.g);
00783     top.b = int(dfx*topleft.b + fx*topright.b);
00784 //    top.a = int(dfx*topleft.a + fx*topright.a);
00785 
00786     bottom.r = int(dfx*bottomleft.r + fx*bottomright.r);
00787     bottom.g = int(dfx*bottomleft.g + fx*bottomright.g);
00788     bottom.b = int(dfx*bottomleft.b + fx*bottomright.b);
00789 //    bottom.a = int(dfx*bottomleft.a + fx*bottomright.a);
00790 
00791     interpolated.r = int(dfy*top.r + fy*bottom.r);
00792     interpolated.g = int(dfy*top.g + fy*bottom.g);
00793     interpolated.b = int(dfy*top.b + fy*bottom.b);
00794 //    interpolated.a = int(dfy*top.a + fy*bottom.a);
00795     interpolated.a = 255;
00796 
00797     return interpolated;
00798 }
00799 
00800 
00802 // Convertes from RGB mode to HSV mode
00803 //   -> http://de.wikipedia.org/wiki/HSV-Farbraum
00805 
00806 Hsva RGBtoHSV(Rgba RGBColor)
00807 {
00808     // R, G, B: red, green, blue
00809     // H, S, V: hue, saturation, value
00810     // MAX = max(R, G, B)
00811     // MIN = min(R, G, B)
00812     
00813     float R, G, B, MAX, MIN;
00814     Hsva HSVColor;
00815     
00816     R = RGBColor.r / 255.0;
00817     G = RGBColor.g / 255.0;
00818     B = RGBColor.b / 255.0;
00819     
00820     MAX = R;
00821     if (G > MAX)
00822         MAX = G;
00823     if (B > MAX)
00824         MAX = B;
00825                   
00826     MIN = R;
00827     if (G < MIN)
00828         MIN = G;
00829     if (B < MIN)
00830         MIN = B;
00831         
00832     // let's transform RGB -> HSV:
00833     if (MAX != MIN)
00834     {
00835         if (MAX == R)
00836             HSVColor.h = (0.0 + (G - B) / (MAX - MIN)) * 60.0;
00837         if (MAX == G)
00838             HSVColor.h = (2.0 + (B - R) / (MAX - MIN)) * 60.0;
00839         if (MAX == B)
00840             HSVColor.h = (4.0 + (R - G) / (MAX - MIN)) * 60.0;
00841     }
00842             
00843     if (MAX > 0)                    
00844         HSVColor.s = (MAX - MIN) / MAX;
00845         
00846     HSVColor.v = MAX;
00847     
00848     HSVColor.a = RGBColor.a;
00849     return HSVColor;
00850 }
00851 
00852 Rgba HSVtoRGB(Hsva HSVColor)
00853 {
00854     // http://de.wikipedia.org/wiki/HSV-Farbraum
00855     
00856     float Hi, f, p, q, t;
00857     Rgba RGBColor;
00858     
00859     // roger, now transform it back:
00860     Hi = int(fmod(HSVColor.h / 60.0, 6));
00861     f = (HSVColor.h / 60.0) - Hi;
00862     p = HSVColor.v * (1.0 - HSVColor.s);
00863     q = HSVColor.v * (1.0 - (HSVColor.s * f));
00864     t = HSVColor.v * (1.0 - (HSVColor.s * (1.0 - f)));
00865         
00866     if (Hi == 0)
00867     {
00868         RGBColor.r = int(HSVColor.v * 255);
00869         RGBColor.g = int(t * 255);
00870         RGBColor.b = int(p * 255);
00871     }
00872     else if (Hi == 1)
00873     {
00874         RGBColor.r = int(q * 255);
00875         RGBColor.g = int(HSVColor.v * 255);
00876         RGBColor.b = int(p * 255);
00877     }
00878     else if (Hi == 2)
00879     {
00880         RGBColor.r = int(p * 255);
00881         RGBColor.g = int(HSVColor.v * 255);
00882         RGBColor.b = int(t * 255);
00883     }
00884     else if (Hi == 3)
00885     {
00886         RGBColor.r = int(p * 255);
00887         RGBColor.g = int(q * 255);
00888         RGBColor.b = int(HSVColor.v * 255);
00889     }
00890     else if (Hi == 4)
00891     {
00892         RGBColor.r = int(t * 255);
00893         RGBColor.g = int(p * 255);
00894         RGBColor.b = int(HSVColor.v * 255);
00895     }
00896     else if (Hi == 5)
00897     {
00898         RGBColor.r = int(HSVColor.v * 255);
00899         RGBColor.g = int(p * 255);
00900         RGBColor.b = int(q * 255);
00901     }
00902     
00903     RGBColor.a = HSVColor.a;
00904     return RGBColor;
00905 }
00906 
00908 // Gaussian Blur
00910 void gaussian(ImageRGBA *img, ImageRGBA *temp2, int lowAreaX, int lowAreaY, int highAreaX, int highAreaY, float value1, int mode, unsigned char calc)
00911 {
00912     int loops = 1;
00913     float oldValue1 = value1;
00914     ImageRGBA *swap;
00915 
00916     if (mode == 2)
00917         loops = int(oldValue1);
00918     for (int l = 0; l < loops; l++)
00919     {
00920         if (l > 0)
00921             value1 = int(exp((l*-l)/oldValue1) * oldValue1);
00922         
00923         if (value1 > 0)
00924         {
00925             horizontal_blur(img, temp2, lowAreaX, lowAreaY, highAreaX, highAreaY, value1, mode, calc);
00926 
00927             swap = img;
00928             img = temp2;
00929             temp2 = swap;
00930     
00931             vertical_blur(img, temp2, lowAreaX, lowAreaY, highAreaX, highAreaY, value1, mode, calc);
00932         }
00933         swap = img;
00934         img = temp2;
00935         temp2 = swap;
00936     }
00937 }
00938 
00939 void horizontal_blur(ImageRGBA *img, ImageRGBA *temp2, int lowAreaX, int lowAreaY, int highAreaX, int highAreaY, float value1, int mode, unsigned char calc)
00940 {
00941     int mx, location, count = 0;
00942     int R = 0, G = 0, B = 0, A = 0;
00943 
00944     for (int _y = lowAreaY; _y <= highAreaY; _y++)
00945     {
00946         for (int _x = lowAreaX; _x <= highAreaX; _x++)
00947         {
00948             if (_x == lowAreaX)
00949             {
00950                 R = 0;
00951                 G = 0;
00952                 B = 0;
00953                 A = 0;
00954                 count = 0;
00955                 for (int x = 0; x <= int(value1); x++)
00956                 {
00957                     mx = _x + x;
00958                     
00959                     if (mx < lowAreaX) { mx = lowAreaX; }
00960                     if (mx > highAreaX)
00961                         break;
00962                     
00963                     if (_y > highAreaY)
00964                         break;
00965                     if (!(_y < lowAreaY))
00966                     {
00967     
00968                         count++;
00969                         location = mx + img->width * _y;
00970                         
00971                         R += temp2->data[location].r;
00972                         G += temp2->data[location].g;
00973                         B += temp2->data[location].b;
00974                         A += temp2->data[location].a;
00975                     }
00976                 }
00977             }
00978             else
00979             {
00980                 if ((_x - int(value1)) > lowAreaX)
00981                 {
00982                     if (_y > highAreaY)
00983                         break;
00984                     if (!(_y < lowAreaY))
00985                     {
00986                         count--;
00987                         location = (_x - int(value1) - 1) + img->width * _y;
00988                         
00989                         R -= temp2->data[location].r;
00990                         G -= temp2->data[location].g;
00991                         B -= temp2->data[location].b;
00992                         A -= temp2->data[location].a;
00993                     }
00994                 }
00995                 if ((_x + int(value1)) <= highAreaX)
00996                 {
00997                     if (_y > highAreaY)
00998                         break;
00999                     if (!(_y < lowAreaY))
01000                     {
01001                         count++;
01002                         location = (_x + int(value1)) + img->width * _y;
01003                         
01004                         R += temp2->data[location].r;
01005                         G += temp2->data[location].g;
01006                         B += temp2->data[location].b;
01007                         A += temp2->data[location].a;
01008                     }
01009                 }
01010             }
01011             if (count != 0)
01012             {
01013                 int location = _x + img->width * _y;
01014                 int _R = (R / count);
01015                 int _G = (G / count);
01016                 int _B = (B / count);
01017                 int _A = (A / count);
01018                 if (calc == 2)
01019                 {
01020                     _R = int(((float)_A / 255 * _R) + ((float)img->data[location].a / 255 * img->data[location].r));
01021                     _G = int(((float)_A / 255 * _G) + ((float)img->data[location].a / 255 * img->data[location].g));
01022                     _B = int(((float)_A / 255 * _B) + ((float)img->data[location].a / 255 * img->data[location].b));
01023                     _A = _A + img->data[location].a;
01024                     _R = int((float)_R / ((float)_A / 255));
01025                     _G = int((float)_G / ((float)_A / 255));
01026                     _B = int((float)_B / ((float)_A / 255));
01027                     _A = int((float)_A);
01028                 }                
01029 
01030                 if (_R < 0) { _R = 0; }
01031                 if (_G < 0) { _G = 0; }
01032                 if (_B < 0) { _B = 0; }
01033                 if (_A < 0) { _A = 0; }
01034                 if (_R > 255) { _R = 255; }
01035                 if (_G > 255) { _G = 255; }
01036                 if (_B > 255) { _B = 255; }
01037                 if (_A > 255) { _A = 255; }
01038                 img->data[location] = (Rgba){_R, _G, _B, _A};
01039             }
01040         }
01041     }
01042 }
01043 
01044 void vertical_blur(ImageRGBA *img, ImageRGBA *temp2, int lowAreaX, int lowAreaY, int highAreaX, int highAreaY, float value1, int mode, unsigned char calc)
01045 {
01046     int my, location, count = 0;
01047     int R = 0, G = 0, B = 0, A = 0;
01048 
01049     for (int _x = lowAreaX; _x <= highAreaX; _x++)
01050     {
01051         for (int _y = lowAreaY; _y <= highAreaY; _y++)
01052         {
01053             if (_y == lowAreaY)
01054             {
01055                 R = 0;
01056                 G = 0;
01057                 B = 0;
01058                 A = 0;
01059                 count = 0;
01060                 for (int y = 0; y <= int(value1); y++)
01061                 {
01062                     my = _y + y;
01063                     
01064                     if (my < lowAreaY) { my = lowAreaY; }
01065                     if (my > highAreaY)
01066                         break;
01067                     
01068                     if (_x > highAreaX)
01069                         break;
01070                     if (!(_x < lowAreaX))
01071                     {
01072     
01073                         count++;
01074                         location = _x + img->width * my;
01075                         
01076                         R += temp2->data[location].r;
01077                         G += temp2->data[location].g;
01078                         B += temp2->data[location].b;
01079                         A += temp2->data[location].a;
01080                     }
01081                 }
01082             }
01083             else
01084             {
01085                 if ((_y - int(value1)) > lowAreaY)
01086                 {
01087                     if (_x > highAreaX)
01088                         break;
01089                     if (!(_x < lowAreaX))
01090                     {
01091                         count--;
01092                         location = _x + img->width * (_y - int(value1) - 1);
01093                         
01094                         R -= temp2->data[location].r;
01095                         G -= temp2->data[location].g;
01096                         B -= temp2->data[location].b;
01097                         A -= temp2->data[location].a;
01098                     }
01099                 }
01100                 if ((_y + int(value1)) <= highAreaY)
01101                 {
01102                     if (_x > highAreaX)
01103                         break;
01104                     if (!(_x < lowAreaX))
01105                     {
01106                         count++;
01107                         location = _x + img->width * (_y + int(value1));
01108                         
01109                         R += temp2->data[location].r;
01110                         G += temp2->data[location].g;
01111                         B += temp2->data[location].b;
01112                         A += temp2->data[location].a;
01113                     }
01114                 }
01115             }
01116             if (count != 0)
01117             {
01118                 int location = _x + img->width * _y;
01119                 int _R = (R / count);
01120                 int _G = (G / count);
01121                 int _B = (B / count);
01122                 int _A = (A / count);
01123                 if (calc == 2)
01124                 {
01125                     _R = int(((float)_A / 255 * _R) + ((float)img->data[location].a / 255 * img->data[location].r));
01126                     _G = int(((float)_A / 255 * _G) + ((float)img->data[location].a / 255 * img->data[location].g));
01127                     _B = int(((float)_A / 255 * _B) + ((float)img->data[location].a / 255 * img->data[location].b));
01128                     _A = _A + img->data[location].a;
01129                     _R = int((float)_R / ((float)_A / 255));
01130                     _G = int((float)_G / ((float)_A / 255));
01131                     _B = int((float)_B / ((float)_A / 255));
01132                     _A = int((float)_A);
01133                 }
01134                 
01135                 if (_R < 0) { _R = 0; }
01136                 if (_G < 0) { _G = 0; }
01137                 if (_B < 0) { _B = 0; }
01138                 if (_A < 0) { _A = 0; }
01139                 if (_R > 255) { _R = 255; }
01140                 if (_G > 255) { _G = 255; }
01141                 if (_B > 255) { _B = 255; }
01142                 if (_A > 255) { _A = 255; }
01143                 img->data[location] = (Rgba){_R, _G, _B, _A};
01144             }
01145         }
01146     }
01147 }
01148 
01149 void motion_blur(ImageRGBA *img, ImageRGBA *temp2, int lowAreaX, int lowAreaY, int highAreaX, int highAreaY, float value1, float value2, int mode, unsigned char calc)
01150 {
01151     int maxdist, maxdistX, maxdistY;
01152     int newX, newY, maxY, location;
01153     int oldX, oldY;
01154     int R = 0, G = 0, B = 0, A = 0, count = 0;
01155     float angle = value2 * M_PI / 180 - M_PI / 2;
01156 //    imageRgbaSetArea(img, lowAreaX, lowAreaY, highAreaX+1, highAreaY+1, (Rgba){0, 0, 0, 0});
01157 
01158     for (int x = lowAreaX - 1; x <= highAreaX + 1; x++)
01159     {
01160         if (x == lowAreaX - 1 && angle < 0)
01161             maxY = highAreaY + 1;
01162         else if (x == highAreaX + 1 && angle > 0)
01163             maxY = highAreaY + 1;
01164         else
01165             maxY = lowAreaY - 1;
01166             
01167         for (int y = lowAreaY - 1; y <= maxY; y++)
01168         {
01169             R = 0;
01170             G = 0;
01171             B = 0;
01172             A = 0;
01173             count = 0;
01174             if (angle < 0)
01175                 maxdistX = (highAreaX - x + 10);
01176             else if (angle > 0)
01177                 maxdistX = x + 10;
01178             else
01179                 maxdistX = highAreaX + 10;
01180             if (maxdistX > (highAreaX + 10))
01181                 maxdistX = highAreaX + 10;
01182             else if (maxdist < (-(highAreaX + 10)))
01183                 maxdist = -(highAreaX + 10);
01184             maxdistY = int(maxdistX / tan(angle)+10);
01185             if (maxdistY > (highAreaY + 10))
01186                 maxdistY = highAreaY + 10;
01187             else if (maxdistY < (-(highAreaY + 10)))
01188                 maxdistY = -(highAreaY + 10);
01189             maxdist = int(sqrt(maxdistX*maxdistX + maxdistY*maxdistY)+1);
01190             for (int dist = int(-value1); dist < maxdist; dist++)
01191             {
01192                 // remove
01193                 if ((dist - value1) >= 0)
01194                 {
01195                     newX = int(x - sin(angle)*(dist-value1));
01196                     newY = int(y + cos(angle)*(dist-value1));
01197                     if (newX >= lowAreaX && newX <= highAreaX && newY >= lowAreaY && newY <= highAreaY)
01198                     {
01199                         location = newX + img->width * newY;
01200                         R -= temp2->data[location].r;
01201                         G -= temp2->data[location].g;
01202                         B -= temp2->data[location].b;
01203                         A -= temp2->data[location].a;
01204                         count--;
01205                     }
01206                 }
01207                 // add
01208                 newX = int(x - sin(angle)*(dist+value1));
01209                 newY = int(y + cos(angle)*(dist+value1));
01210                 if (newX >= lowAreaX && newX <= highAreaX && newY >= lowAreaY && newY <= highAreaY)
01211                 {
01212                     location = newX + img->width * newY;
01213                     R += temp2->data[location].r;
01214                     G += temp2->data[location].g;
01215                     B += temp2->data[location].b;
01216                     A += temp2->data[location].a;
01217                     count++;
01218                 }
01219                 // draw
01220                 if (dist >= 0)
01221                 {
01222                     newX = int(x - sin(angle)*dist);
01223                     newY = int(y + cos(angle)*dist);
01224                     if (oldX != newX || oldY != newY)
01225                     {
01226                         if (newX >= lowAreaX && newX <= highAreaX && newY >= lowAreaY && newY <= highAreaY)
01227                         {
01228                             location = newX + img->width * newY;
01229                             if (count != 0)
01230                             {
01231                                 int _R = (R / count);
01232                                 int _G = (G / count);
01233                                 int _B = (B / count);
01234                                 int _A = (A / count);
01235                                 if (calc == 2)
01236                                 {
01237                                     _R = int(((float)_A / 255 * _R) + ((float)img->data[location].a / 255 * img->data[location].r));
01238                                     _G = int(((float)_A / 255 * _G) + ((float)img->data[location].a / 255 * img->data[location].g));
01239                                     _B = int(((float)_A / 255 * _B) + ((float)img->data[location].a / 255 * img->data[location].b));
01240                                     _A = _A + img->data[location].a;
01241                                     _R = int((float)_R * ((float)255 / _A));
01242                                     _G = int((float)_G * ((float)255 / _A));
01243                                     _B = int((float)_B * ((float)255 / _A));
01244                                     _A = int((float)_A);
01245                                 }
01246                                 
01247                                 if (_R < 0) { _R = 0; }
01248                                 if (_G < 0) { _G = 0; }
01249                                 if (_B < 0) { _B = 0; }
01250                                 if (_A < 0) { _A = 0; }
01251                                 if (_R > 255) { _R = 255; }
01252                                 if (_G > 255) { _G = 255; }
01253                                 if (_B > 255) { _B = 255; }
01254                                 if (_A > 255) { _A = 255; }
01255                                 img->data[location] = (Rgba){_R, _G, _B, _A};
01256                             }
01257                         }
01258                     }
01259                     oldX = newX;
01260                     oldY = newY;
01261                 }
01262             }
01263         }
01264     }
01265 }
01266 
01267 void holdHighest(int *stack, int numElements, int newElement)
01268 {
01269     int hold;
01270     for (int i = 0; i < numElements; i++)
01271     {
01272         if (newElement > stack[i])
01273         {
01274             hold = stack[i];
01275             stack[i] = newElement;
01276             holdHighest(stack, numElements, hold);
01277             break;
01278         }
01279     }
01280 }

Generated on Mon Jan 30 09:13:03 2006 for Painter Framework by doxygen1.2.18