image.cpp

00001 /*
00002  *  This file is part of the KDE libraries
00003  *  Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be>
00004  *
00005  *  This library is free software; you can redistribute it and/or
00006  *  modify it under the terms of the GNU Library General Public
00007  *  License version 2 as published by the Free Software Foundation.
00008  *
00009  *  This library is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  *  Library General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU Library General Public License
00015  *  along with this library; see the file COPYING.LIB.  If not, write to
00016  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  *  Boston, MA 02110-1301, USA.
00018  **/
00019 
00020 #include <qimage.h>
00021 #include <math.h>
00022 
00023 void
00024 mult(float a[3][3], /* I - First matrix */
00025      float b[3][3], /* I - Second matrix */
00026      float c[3][3]) /* I - Destination matrix */
00027 {
00028   int   x, y;       /* Looping vars */
00029   float temp[3][3]; /* Temporary matrix */
00030 
00031 
00032  /*
00033   * Multiply a and b, putting the result in temp...
00034   */
00035 
00036   for (y = 0; y < 3; y ++)
00037     for (x = 0; x < 3; x ++)
00038       temp[y][x] = b[y][0] * a[0][x] +
00039                    b[y][1] * a[1][x] +
00040                    b[y][2] * a[2][x];
00041 
00042  /*
00043   * Copy temp to c (that way c can be a pointer to a or b).
00044   */
00045 
00046   memcpy(c, temp, sizeof(temp));
00047 }
00048 
00049 void
00050 saturate(float mat[3][3],   /* I - Matrix to append to */
00051          float sat)     /* I - Desired color saturation */
00052 {
00053   float smat[3][3];     /* Saturation matrix */
00054 
00055 
00056   smat[0][0] = (1.0 - sat) * 0.3086 + sat;
00057   smat[0][1] = (1.0 - sat) * 0.3086;
00058   smat[0][2] = (1.0 - sat) * 0.3086;
00059   smat[1][0] = (1.0 - sat) * 0.6094;
00060   smat[1][1] = (1.0 - sat) * 0.6094 + sat;
00061   smat[1][2] = (1.0 - sat) * 0.6094;
00062   smat[2][0] = (1.0 - sat) * 0.0820;
00063   smat[2][1] = (1.0 - sat) * 0.0820;
00064   smat[2][2] = (1.0 - sat) * 0.0820 + sat;
00065 
00066   mult(smat, mat, mat);
00067 }
00068 
00069 void
00070 xform(float mat[3][3],  /* I - Matrix */
00071       float x,      /* I - Input X coordinate */
00072       float y,      /* I - Input Y coordinate */
00073       float z,      /* I - Input Z coordinate */
00074       float *tx,    /* O - Output X coordinate */
00075       float *ty,    /* O - Output Y coordinate */
00076       float *tz)    /* O - Output Z coordinate */
00077 {
00078   *tx = x * mat[0][0] + y * mat[1][0] + z * mat[2][0];
00079   *ty = x * mat[0][1] + y * mat[1][1] + z * mat[2][1];
00080   *tz = x * mat[0][2] + y * mat[1][2] + z * mat[2][2];
00081 }
00082 
00083 void
00084 xrotate(float mat[3][3],    /* I - Matrix */
00085         float rs,       /* I - Rotation angle sine */
00086         float rc)       /* I - Rotation angle cosine */
00087 {
00088   float rmat[3][3];     /* I - Rotation matrix */
00089 
00090 
00091   rmat[0][0] = 1.0;
00092   rmat[0][1] = 0.0;
00093   rmat[0][2] = 0.0;
00094 
00095   rmat[1][0] = 0.0;
00096   rmat[1][1] = rc;
00097   rmat[1][2] = rs;
00098 
00099   rmat[2][0] = 0.0;
00100   rmat[2][1] = -rs;
00101   rmat[2][2] = rc;
00102 
00103   mult(rmat, mat, mat);
00104 }
00105 
00106 void
00107 yrotate(float mat[3][3],    /* I - Matrix */
00108         float rs,       /* I - Rotation angle sine */
00109         float rc)       /* I - Rotation angle cosine */
00110 {
00111   float rmat[3][3];     /* I - Rotation matrix */
00112 
00113 
00114   rmat[0][0] = rc;
00115   rmat[0][1] = 0.0;
00116   rmat[0][2] = -rs;
00117 
00118   rmat[1][0] = 0.0;
00119   rmat[1][1] = 1.0;
00120   rmat[1][2] = 0.0;
00121 
00122   rmat[2][0] = rs;
00123   rmat[2][1] = 0.0;
00124   rmat[2][2] = rc;
00125 
00126   mult(rmat,mat,mat);
00127 }
00128 
00129 void
00130 zrotate(float mat[3][3],    /* I - Matrix */
00131         float rs,       /* I - Rotation angle sine */
00132         float rc)       /* I - Rotation angle cosine */
00133 {
00134   float rmat[3][3];     /* I - Rotation matrix */
00135 
00136 
00137   rmat[0][0] = rc;
00138   rmat[0][1] = rs;
00139   rmat[0][2] = 0.0;
00140 
00141   rmat[1][0] = -rs;
00142   rmat[1][1] = rc;
00143   rmat[1][2] = 0.0;
00144 
00145   rmat[2][0] = 0.0;
00146   rmat[2][1] = 0.0;
00147   rmat[2][2] = 1.0;
00148 
00149   mult(rmat,mat,mat);
00150 }
00151 
00152 void
00153 zshear(float mat[3][3], /* I - Matrix */
00154        float dx,    /* I - X shear */
00155        float dy)    /* I - Y shear */
00156 {
00157   float smat[3][3]; /* Shear matrix */
00158 
00159 
00160   smat[0][0] = 1.0;
00161   smat[0][1] = 0.0;
00162   smat[0][2] = dx;
00163 
00164   smat[1][0] = 0.0;
00165   smat[1][1] = 1.0;
00166   smat[1][2] = dy;
00167 
00168   smat[2][0] = 0.0;
00169   smat[2][1] = 0.0;
00170   smat[2][2] = 1.0;
00171 
00172   mult(smat, mat, mat);
00173 }
00174 
00175 void
00176 huerotate(float mat[3][3],  /* I - Matrix to append to */
00177           float rot)        /* I - Hue rotation in degrees */
00178 {
00179   float hmat[3][3] = {{1.0,0.0,0.0},{0.0,1.0,0.0},{0.0,0.0,1.0}};       /* Hue matrix */
00180   float lx, ly, lz;     /* Luminance vector */
00181   float xrs, xrc;       /* X rotation sine/cosine */
00182   float yrs, yrc;       /* Y rotation sine/cosine */
00183   float zrs, zrc;       /* Z rotation sine/cosine */
00184   float zsx, zsy;       /* Z shear x/y */
00185 
00186 
00187  /*
00188   * Rotate the gray vector into positive Z...
00189   */
00190 
00191   xrs = M_SQRT1_2;
00192   xrc = M_SQRT1_2;
00193   xrotate(hmat,xrs,xrc);
00194 
00195   yrs = -1.0 / sqrt(3.0);
00196   yrc = -M_SQRT2 * yrs;
00197   yrotate(hmat,yrs,yrc);
00198 
00199  /*
00200   * Shear the space to make the luminance plane horizontal...
00201   */
00202 
00203   xform(hmat, 0.3086, 0.6094, 0.0820, &lx, &ly, &lz);
00204   zsx = lx / lz;
00205   zsy = ly / lz;
00206   zshear(hmat, zsx, zsy);
00207 
00208  /*
00209   * Rotate the hue...
00210   */
00211 
00212   zrs = sin(rot * M_PI / 180.0);
00213   zrc = cos(rot * M_PI / 180.0);
00214 
00215   zrotate(hmat, zrs, zrc);
00216 
00217  /*
00218   * Unshear the space to put the luminance plane back...
00219   */
00220 
00221   zshear(hmat, -zsx, -zsy);
00222 
00223  /*
00224   * Rotate the gray vector back into place...
00225   */
00226 
00227   yrotate(hmat, -yrs, yrc);
00228   xrotate(hmat, -xrs, xrc);
00229 
00230  /*
00231   * Append it to the current matrix...
00232   */
00233 
00234   mult(hmat, mat, mat);
00235 }
00236 
00237 void
00238 bright(float mat[3][3],
00239        float scale)
00240 {
00241   for (int i=0;i<3;i++)
00242     for (int j=0;j<3;j++)
00243       mat[i][j] *= scale;
00244 }
00245 
00246 //----------------------------------------------------------------------------------------------------
00247 
00248 QImage convertImage(const QImage& image, int hue, int saturation, int brightness, int gamma)
00249 {
00250     float   mat[3][3] = {{1.0,0.0,0.0},{0.0,1.0,0.0},{0.0,0.0,1.0}};
00251     int lut[3][3][256];
00252     QRgb    c;
00253     int r,g,b,v,r2,g2,b2;
00254     float   gam = 1.0/(float(gamma)/1000.0);
00255     QImage  img(image);
00256 
00257     saturate(mat,saturation*0.01);
00258     huerotate(mat,(float)hue);
00259     bright(mat,brightness*0.01);
00260     for (int i = 0; i < 3; i ++)
00261       for (int j = 0; j < 3; j ++)
00262         for (int k = 0; k < 256; k ++)
00263         lut[i][j][k] = (int)(mat[i][j] * k + 0.5);
00264     
00265     img.detach();
00266     for (int i=0;i<image.width();i++)
00267        for (int j=0;j<image.height();j++)
00268        {
00269         c = image.pixel(i,j);
00270         r = qRed(c);
00271         g = qGreen(c);
00272         b = qBlue(c);
00273 
00274         v = lut[0][0][r] + lut[1][0][g] + lut[2][0][b];
00275         if (gamma != 1000) v = (int)rint(pow(v,gam));
00276         if (v < 0) r2 = 0;
00277         else if (v > 255) r2 = 255;
00278         else r2 = v;
00279 
00280         v = lut[0][1][r] + lut[1][1][g] + lut[2][1][b];
00281         if (gamma != 1000) v = (int)rint(pow(v,gam));
00282         if (v < 0) g2 = 0;
00283         else if (v > 255) g2 = 255;
00284         else g2 = v;
00285 
00286         v = lut[0][2][r] + lut[1][2][g] + lut[2][2][b];
00287         if (gamma != 1000) v = (int)rint(pow(v,gam));
00288         if (v < 0) b2 = 0;
00289         else if (v > 255) b2 = 255;
00290         else b2 = v;
00291 
00292         img.setPixel(i,j,qRgb(r2,g2,b2));
00293        }
00294     return img;
00295 }
KDE Home | KDE Accessibility Home | Description of Access Keys