Source for gnu.javax.imageio.jpeg.DCT

   1: /* DCT.java --
   2:    Copyright (C)  2005  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: package gnu.javax.imageio.jpeg;
  39: 
  40: /**
  41:  * Discrete Cosine Transformations.
  42:  */
  43: public class DCT
  44: {
  45: 
  46:   /**
  47:    * Cosine matrix
  48:    */
  49:   public double c[][] = new double[8][8];
  50: 
  51:   /**
  52:    * Transformed cosine matrix
  53:    */
  54:   public double cT[][] = new double[8][8];
  55: 
  56:   public DCT()
  57:   {
  58:     initMatrix();
  59:   }
  60: 
  61:   /**
  62:    * Figure A.3.3 IDCT, Cu Cv on A-5 of the ISO DIS 10918-1. Requirements and
  63:    * Guidelines.
  64:    *
  65:    * @param u
  66:    * @return
  67:    */
  68:   public static double C(int u)
  69:   {
  70:     return ((u == 0) ? (double) 1 / (double) Math.sqrt((double) 2)
  71:                      : (double) 1);
  72:   }
  73: 
  74:   /**
  75:    * Initialize matrix values for the fast_idct function
  76:    */
  77:   private void initMatrix()
  78:   {
  79:     for (int j = 0; j < 8; j++)
  80:       {
  81:         double nn = (double) (8);
  82:         c[0][j] = 1.0 / Math.sqrt(nn);
  83:         cT[j][0] = c[0][j];
  84:       }
  85:     for (int i = 1; i < 8; i++)
  86:       {
  87:       for (int j = 0; j < 8; j++)
  88:         {
  89:           double jj = (double) j;
  90:           double ii = (double) i;
  91:           c[i][j] =
  92:             Math.sqrt(2.0 / 8.0)
  93:             * Math.cos(((2.0 * jj + 1.0) * ii * Math.PI) / (2.0 * 8.0));
  94:           cT[j][i] = c[i][j];
  95:         }
  96:       }
  97:   }
  98: 
  99:   /**
 100:    * slow_idct - Figure A.3.3 IDCT (informative) on A-5 of the ISO DIS
 101:    * 10918-1. Requirements and Guidelines. This is a slow IDCT, there are
 102:    * better algorithms to use, it's fairly expensive with processor speed.
 103:    *
 104:    * @param matrix
 105:    * @return
 106:    */
 107:   public static double[][] slow_idct(double[][] matrix)
 108:   {
 109:     double[][] output = new double[matrix.length][matrix.length];
 110:     for (int y = 0; y < 8; y++)
 111:       {
 112:         for (int x = 0; x < 8; x++)
 113:           {
 114:             double val = 0;
 115:             for (double v = 0; v < 8; v++)
 116:               {
 117:                 double innerloop = 0;
 118:                 for (double u = 0; u < 8; u++)
 119:                   innerloop += (DCT.C((int) u) / (double) 2)
 120:                            * matrix[(int) v][(int) u]
 121:                            * Math.cos((2 * x + 1) * u * Math.PI / (double) 16)
 122:                            * Math.cos((2 * y + 1) * v * Math.PI / (double) 16);
 123:                 val += (DCT.C((int) v) / (double) 2) * innerloop;
 124:               }
 125:             output[y][x] = (val + 128);
 126:           }
 127:       }
 128:     return (output);
 129:   }
 130: 
 131:   public static float[][] slow_fdct(float[][] value)
 132:   {
 133:     float[][] buffer = new float[8][8];
 134: 
 135:     for (int u = 0; u < 8; u++)
 136:       {
 137:         for (int v = 0; v < 8; v++)
 138:           {
 139:             buffer[u][v] =
 140:               (float) (1 / 4) * (float) C((int) u) * (float) C((int) v);
 141:             float innerval = 0;
 142:             for (int x = 0; x < 8; x++)
 143:               {
 144:                 for (int y = 0; y < 8; y++)
 145:                   {
 146:                     innerval += value[y][x]
 147:                                   * Math.cos(((2 * x + 1) * u * Math.PI) / 16)
 148:                                   * Math.cos(((2 * y + 1) * v * Math.PI) / 16);
 149:                   }
 150:               }
 151:             buffer[u][v] *= innerval;
 152:           }
 153:       }
 154:     return (buffer);
 155:   }
 156: 
 157:   public float[][] fast_fdct(float[][] input)
 158:   {
 159:     float output[][] = new float[8][8];
 160:     double temp[][] = new double[8][8];
 161:     double temp1;
 162:     int i;
 163:     int j;
 164:     int k;
 165: 
 166:     for (i = 0; i < 8; i++)
 167:       {
 168:         for (j = 0; j < 8; j++)
 169:           {
 170:             temp[i][j] = 0.0;
 171:             for (k = 0; k < 8; k++)
 172:               {
 173:                 temp[i][j] += (((int) (input[i][k]) - 128) * cT[k][j]);
 174:               }
 175:           }
 176:       }
 177: 
 178:     for (i = 0; i < 8; i++)
 179:       {
 180:         for (j = 0; j < 8; j++)
 181:           {
 182:             temp1 = 0.0;
 183: 
 184:             for (k = 0; k < 8; k++)
 185:               {
 186:                 temp1 += (c[i][k] * temp[k][j]);
 187:               }
 188: 
 189:             output[i][j] = (int) Math.round(temp1) * 8;
 190:           }
 191:       }
 192: 
 193:     return output;
 194:   }
 195: 
 196:   /**
 197:    * fast_idct - Figure A.3.3 IDCT (informative) on A-5 of the ISO DIS
 198:    * 10918-1. Requires and Guidelines. This is a fast IDCT, it much more
 199:    * effecient and only inaccurate at about 1/1000th of a percent of values
 200:    * analyzed. Cannot be static because initMatrix must run before any
 201:    * fast_idct values can be computed.
 202:    *
 203:    * @param input
 204:    * @return
 205:    */
 206:   public double[][] fast_idct(double[][] input)
 207:   {
 208:     double output[][] = new double[8][8];
 209:     double temp[][] = new double[8][8];
 210:     double temp1;
 211:     int i, j, k;
 212:     for (i = 0; i < 8; i++)
 213:       {
 214:         for (j = 0; j < 8; j++)
 215:           {
 216:             temp[i][j] = 0.0;
 217:             for (k = 0; k < 8; k++)
 218:               {
 219:                 temp[i][j] += input[i][k] * c[k][j];
 220:               }
 221:           }
 222:       }
 223:     for (i = 0; i < 8; i++)
 224:       {
 225:         for (j = 0; j < 8; j++)
 226:           {
 227:             temp1 = 0.0;
 228:             for (k = 0; k < 8; k++)
 229:               temp1 += cT[i][k] * temp[k][j];
 230:             temp1 += 128.0;
 231:             if (temp1 < 0)
 232:               output[i][j] = 0;
 233:             else if (temp1 > 255)
 234:               output[i][j] = 255;
 235:             else
 236:               output[i][j] = (int) Math.round(temp1);
 237:           }
 238:       }
 239:     return output;
 240:   }
 241: 
 242:   public double[][] idj_fast_fdct(float input[][])
 243:   {
 244:     double output[][] = new double[8][8];
 245:     double tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
 246:     double tmp10, tmp11, tmp12, tmp13;
 247:     double z1, z2, z3, z4, z5, z11, z13;
 248:     int i;
 249:     int j;
 250: 
 251:     // Subtracts 128 from the input values
 252:     for (i = 0; i < 8; i++)
 253:       {
 254:         for (j = 0; j < 8; j++)
 255:           {
 256:             output[i][j] = ((double) input[i][j] - (double) 128.0);
 257:             //                        input[i][j] -= 128;
 258: 
 259:           }
 260:       }
 261: 
 262:     for (i = 0; i < 8; i++)
 263:       {
 264:         tmp0 = output[i][0] + output[i][7];
 265:         tmp7 = output[i][0] - output[i][7];
 266:         tmp1 = output[i][1] + output[i][6];
 267:         tmp6 = output[i][1] - output[i][6];
 268:         tmp2 = output[i][2] + output[i][5];
 269:         tmp5 = output[i][2] - output[i][5];
 270:         tmp3 = output[i][3] + output[i][4];
 271:         tmp4 = output[i][3] - output[i][4];
 272: 
 273:         tmp10 = tmp0 + tmp3;
 274:         tmp13 = tmp0 - tmp3;
 275:         tmp11 = tmp1 + tmp2;
 276:         tmp12 = tmp1 - tmp2;
 277: 
 278:         output[i][0] = tmp10 + tmp11;
 279:         output[i][4] = tmp10 - tmp11;
 280: 
 281:         z1 = (tmp12 + tmp13) * (double) 0.707106781;
 282:         output[i][2] = tmp13 + z1;
 283:         output[i][6] = tmp13 - z1;
 284: 
 285:         tmp10 = tmp4 + tmp5;
 286:         tmp11 = tmp5 + tmp6;
 287:         tmp12 = tmp6 + tmp7;
 288: 
 289:         z5 = (tmp10 - tmp12) * (double) 0.382683433;
 290:         z2 = ((double) 0.541196100) * tmp10 + z5;
 291:         z4 = ((double) 1.306562965) * tmp12 + z5;
 292:         z3 = tmp11 * ((double) 0.707106781);
 293: 
 294:         z11 = tmp7 + z3;
 295:         z13 = tmp7 - z3;
 296: 
 297:         output[i][5] = z13 + z2;
 298:         output[i][3] = z13 - z2;
 299:         output[i][1] = z11 + z4;
 300:         output[i][7] = z11 - z4;
 301:       }
 302: 
 303:     for (i = 0; i < 8; i++)
 304:       {
 305:         tmp0 = output[0][i] + output[7][i];
 306:         tmp7 = output[0][i] - output[7][i];
 307:         tmp1 = output[1][i] + output[6][i];
 308:         tmp6 = output[1][i] - output[6][i];
 309:         tmp2 = output[2][i] + output[5][i];
 310:         tmp5 = output[2][i] - output[5][i];
 311:         tmp3 = output[3][i] + output[4][i];
 312:         tmp4 = output[3][i] - output[4][i];
 313: 
 314:         tmp10 = tmp0 + tmp3;
 315:         tmp13 = tmp0 - tmp3;
 316:         tmp11 = tmp1 + tmp2;
 317:         tmp12 = tmp1 - tmp2;
 318: 
 319:         output[0][i] = tmp10 + tmp11;
 320:         output[4][i] = tmp10 - tmp11;
 321: 
 322:         z1 = (tmp12 + tmp13) * (double) 0.707106781;
 323:         output[2][i] = tmp13 + z1;
 324:         output[6][i] = tmp13 - z1;
 325: 
 326:         tmp10 = tmp4 + tmp5;
 327:         tmp11 = tmp5 + tmp6;
 328:         tmp12 = tmp6 + tmp7;
 329: 
 330:         z5 = (tmp10 - tmp12) * (double) 0.382683433;
 331:         z2 = ((double) 0.541196100) * tmp10 + z5;
 332:         z4 = ((double) 1.306562965) * tmp12 + z5;
 333:         z3 = tmp11 * ((double) 0.707106781);
 334: 
 335:         z11 = tmp7 + z3;
 336:         z13 = tmp7 - z3;
 337: 
 338:         output[5][i] = z13 + z2;
 339:         output[3][i] = z13 - z2;
 340:         output[1][i] = z11 + z4;
 341:         output[7][i] = z11 - z4;
 342:       }
 343: 
 344:     return output;
 345:   }
 346: 
 347: }