Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/obrador/DCT.java


1   // This class incorporates quality scaling as implemented in the JPEG-6a
2   // library.
3   
4   /*
5   * DCT - A Java implementation of the Discreet Cosine Transform
6   */
7   package com.obrador;
8   
9   class DCT
10  {
11      //~ Instance fields ////////////////////////////////////////////////////////
12  
13      public Object[] Divisors = new Object[2];
14  
15      /**
16       * DCT Block Size - default 8
17       */
18      public int N = 8;
19      public double[] DivisorsChrominance = new double[N * N];
20      public double[] DivisorsLuminance = new double[N * N];
21      public Object[] quantum = new Object[2];
22  
23      /**
24       * Quantitization Matrix for chrominance.
25       */
26      public int[] quantum_chrominance = new int[N * N];
27  
28      /**
29       * Quantitization Matrix for luminace.
30       */
31      public int[] quantum_luminance = new int[N * N];
32  
33      /**
34       * Image Quality (0-100) - default 80 (good image / good compression)
35       */
36      public int QUALITY = 80;
37  
38      //~ Constructors ///////////////////////////////////////////////////////////
39  
40      /**
41       * Constructs a new DCT object. Initializes the cosine transform matrix
42       * these are used when computing the DCT and it's inverse. This also
43       * initializes the run length counters and the ZigZag sequence. Note that
44       * the image quality can be worse than 25 however the image will be
45       * extemely pixelated, usually to a block size of N.
46       *
47       * @param QUALITY The quality of the image (0 worst - 100 best)
48       *
49       */
50      public DCT(int QUALITY)
51      {
52          initMatrix(QUALITY);
53      }
54  
55      //~ Methods ////////////////////////////////////////////////////////////////
56  
57      /*
58       * This method preforms a DCT on a block of image data using the AAN
59       * method as implemented in the IJG Jpeg-6a library.
60       */
61      public double[][] forwardDCT(float[][] input)
62      {
63          double[][] output = new double[N][N];
64          double tmp0;
65          double tmp1;
66          double tmp2;
67          double tmp3;
68          double tmp4;
69          double tmp5;
70          double tmp6;
71          double tmp7;
72          double tmp10;
73          double tmp11;
74          double tmp12;
75          double tmp13;
76          double z1;
77          double z2;
78          double z3;
79          double z4;
80          double z5;
81          double z11;
82          double z13;
83          int i;
84          int j;
85  
86          // Subtracts 128 from the input values
87          for (i = 0; i < 8; i++)
88          {
89              for (j = 0; j < 8; j++)
90              {
91                  output[i][j] = ((double) input[i][j] - (double) 128.0);
92  
93                  //                        input[i][j] -= 128;
94              }
95          }
96  
97          for (i = 0; i < 8; i++)
98          {
99              tmp0 = output[i][0] + output[i][7];
100             tmp7 = output[i][0] - output[i][7];
101             tmp1 = output[i][1] + output[i][6];
102             tmp6 = output[i][1] - output[i][6];
103             tmp2 = output[i][2] + output[i][5];
104             tmp5 = output[i][2] - output[i][5];
105             tmp3 = output[i][3] + output[i][4];
106             tmp4 = output[i][3] - output[i][4];
107 
108             tmp10 = tmp0 + tmp3;
109             tmp13 = tmp0 - tmp3;
110             tmp11 = tmp1 + tmp2;
111             tmp12 = tmp1 - tmp2;
112 
113             output[i][0] = tmp10 + tmp11;
114             output[i][4] = tmp10 - tmp11;
115 
116             z1 = (tmp12 + tmp13) * (double) 0.707106781;
117             output[i][2] = tmp13 + z1;
118             output[i][6] = tmp13 - z1;
119 
120             tmp10 = tmp4 + tmp5;
121             tmp11 = tmp5 + tmp6;
122             tmp12 = tmp6 + tmp7;
123 
124             z5 = (tmp10 - tmp12) * (double) 0.382683433;
125             z2 = (((double) 0.541196100) * tmp10) + z5;
126             z4 = (((double) 1.306562965) * tmp12) + z5;
127             z3 = tmp11 * ((double) 0.707106781);
128 
129             z11 = tmp7 + z3;
130             z13 = tmp7 - z3;
131 
132             output[i][5] = z13 + z2;
133             output[i][3] = z13 - z2;
134             output[i][1] = z11 + z4;
135             output[i][7] = z11 - z4;
136         }
137 
138         for (i = 0; i < 8; i++)
139         {
140             tmp0 = output[0][i] + output[7][i];
141             tmp7 = output[0][i] - output[7][i];
142             tmp1 = output[1][i] + output[6][i];
143             tmp6 = output[1][i] - output[6][i];
144             tmp2 = output[2][i] + output[5][i];
145             tmp5 = output[2][i] - output[5][i];
146             tmp3 = output[3][i] + output[4][i];
147             tmp4 = output[3][i] - output[4][i];
148 
149             tmp10 = tmp0 + tmp3;
150             tmp13 = tmp0 - tmp3;
151             tmp11 = tmp1 + tmp2;
152             tmp12 = tmp1 - tmp2;
153 
154             output[0][i] = tmp10 + tmp11;
155             output[4][i] = tmp10 - tmp11;
156 
157             z1 = (tmp12 + tmp13) * (double) 0.707106781;
158             output[2][i] = tmp13 + z1;
159             output[6][i] = tmp13 - z1;
160 
161             tmp10 = tmp4 + tmp5;
162             tmp11 = tmp5 + tmp6;
163             tmp12 = tmp6 + tmp7;
164 
165             z5 = (tmp10 - tmp12) * (double) 0.382683433;
166             z2 = (((double) 0.541196100) * tmp10) + z5;
167             z4 = (((double) 1.306562965) * tmp12) + z5;
168             z3 = tmp11 * ((double) 0.707106781);
169 
170             z11 = tmp7 + z3;
171             z13 = tmp7 - z3;
172 
173             output[5][i] = z13 + z2;
174             output[3][i] = z13 - z2;
175             output[1][i] = z11 + z4;
176             output[7][i] = z11 - z4;
177         }
178 
179         return output;
180     }
181 
182     /*
183      * This method preforms forward DCT on a block of image data using
184      * the literal method specified for a 2-D Discrete Cosine Transform.
185      * It is included as a curiosity and can give you an idea of the
186      * difference in the compression result (the resulting image quality)
187      * by comparing its output to the output of the AAN method below.
188      * It is ridiculously inefficient.
189      */
190 
191     // For now the final output is unusable.  The associated quantization step
192     // needs some tweaking.  If you get this part working, please let me know.
193     public double[][] forwardDCTExtreme(float[][] input)
194     {
195         double[][] output = new double[N][N];
196         double tmp0;
197         double tmp1;
198         double tmp2;
199         double tmp3;
200         double tmp4;
201         double tmp5;
202         double tmp6;
203         double tmp7;
204         double tmp10;
205         double tmp11;
206         double tmp12;
207         double tmp13;
208         double z1;
209         double z2;
210         double z3;
211         double z4;
212         double z5;
213         double z11;
214         double z13;
215         int i;
216         int j;
217         int v;
218         int u;
219         int x;
220         int y;
221 
222         for (v = 0; v < 8; v++)
223         {
224             for (u = 0; u < 8; u++)
225             {
226                 for (x = 0; x < 8; x++)
227                 {
228                     for (y = 0; y < 8; y++)
229                     {
230                         output[v][u] += (((double) input[x][y]) * Math.cos(((double) ((2 * x) +
231                             1) * (double) u * Math.PI) / (double) 16) * Math.cos(((double) ((2 * y) +
232                             1) * (double) v * Math.PI) / (double) 16));
233                     }
234                 }
235 
236                 output[v][u] *= ((double) (0.25) * ((u == 0)
237                 ? ((double) 1.0 / Math.sqrt(2)) : (double) 1.0) * ((v == 0)
238                 ? ((double) 1.0 / Math.sqrt(2)) : (double) 1.0));
239             }
240         }
241 
242         return output;
243     }
244 
245     /*
246     * This method quantitizes data and rounds it to the nearest integer.
247     */
248     public int[] quantizeBlock(double[][] inputData, int code)
249     {
250         int[] outputData = new int[N * N];
251         int i;
252         int j;
253         int index;
254         index = 0;
255 
256         for (i = 0; i < 8; i++)
257         {
258             for (j = 0; j < 8; j++)
259             {
260                 // The second line results in significantly better compression.
261                 outputData[index] = (int) (Math.round(inputData[i][j] * (((double[]) (Divisors[code]))[index])));
262 
263                 //                        outputData[index] = (int)(((inputData[i][j] * (((double[]) (Divisors[code]))[index])) + 16384.5) -16384);
264                 index++;
265             }
266         }
267 
268         return outputData;
269     }
270 
271     /*
272     * This is the method for quantizing a block DCT'ed with forwardDCTExtreme
273     * This method quantitizes data and rounds it to the nearest integer.
274     */
275     public int[] quantizeBlockExtreme(double[][] inputData, int code)
276     {
277         int[] outputData = new int[N * N];
278         int i;
279         int j;
280         int index;
281         index = 0;
282 
283         for (i = 0; i < 8; i++)
284         {
285             for (j = 0; j < 8; j++)
286             {
287                 outputData[index] = (int) (Math.round(inputData[i][j] / (double) (((int[]) (quantum[code]))[index])));
288                 index++;
289             }
290         }
291 
292         return outputData;
293     }
294 
295     /*
296      * This method sets up the quantization matrix for luminance and
297      * chrominance using the Quality parameter.
298      */
299     private void initMatrix(int quality)
300     {
301         double[] AANscaleFactor = 
302         {
303             1.0, 1.387039845, 1.306562965, 1.175875602, 1.0, 0.785694958,
304             0.541196100, 0.275899379
305         };
306         int i;
307         int j;
308         int index;
309         int Quality;
310         int temp;
311 
312         // converting quality setting to that specified in the jpeg_quality_scaling
313         // method in the IJG Jpeg-6a C libraries
314         Quality = quality;
315 
316         if (Quality <= 0)
317         {
318             Quality = 1;
319         }
320 
321         if (Quality > 100)
322         {
323             Quality = 100;
324         }
325 
326         if (Quality < 50)
327         {
328             Quality = 5000 / Quality;
329         }
330         else
331         {
332             Quality = 200 - (Quality * 2);
333         }
334 
335         // Creating the luminance matrix
336         quantum_luminance[0] = 16;
337         quantum_luminance[1] = 11;
338         quantum_luminance[2] = 10;
339         quantum_luminance[3] = 16;
340         quantum_luminance[4] = 24;
341         quantum_luminance[5] = 40;
342         quantum_luminance[6] = 51;
343         quantum_luminance[7] = 61;
344         quantum_luminance[8] = 12;
345         quantum_luminance[9] = 12;
346         quantum_luminance[10] = 14;
347         quantum_luminance[11] = 19;
348         quantum_luminance[12] = 26;
349         quantum_luminance[13] = 58;
350         quantum_luminance[14] = 60;
351         quantum_luminance[15] = 55;
352         quantum_luminance[16] = 14;
353         quantum_luminance[17] = 13;
354         quantum_luminance[18] = 16;
355         quantum_luminance[19] = 24;
356         quantum_luminance[20] = 40;
357         quantum_luminance[21] = 57;
358         quantum_luminance[22] = 69;
359         quantum_luminance[23] = 56;
360         quantum_luminance[24] = 14;
361         quantum_luminance[25] = 17;
362         quantum_luminance[26] = 22;
363         quantum_luminance[27] = 29;
364         quantum_luminance[28] = 51;
365         quantum_luminance[29] = 87;
366         quantum_luminance[30] = 80;
367         quantum_luminance[31] = 62;
368         quantum_luminance[32] = 18;
369         quantum_luminance[33] = 22;
370         quantum_luminance[34] = 37;
371         quantum_luminance[35] = 56;
372         quantum_luminance[36] = 68;
373         quantum_luminance[37] = 109;
374         quantum_luminance[38] = 103;
375         quantum_luminance[39] = 77;
376         quantum_luminance[40] = 24;
377         quantum_luminance[41] = 35;
378         quantum_luminance[42] = 55;
379         quantum_luminance[43] = 64;
380         quantum_luminance[44] = 81;
381         quantum_luminance[45] = 104;
382         quantum_luminance[46] = 113;
383         quantum_luminance[47] = 92;
384         quantum_luminance[48] = 49;
385         quantum_luminance[49] = 64;
386         quantum_luminance[50] = 78;
387         quantum_luminance[51] = 87;
388         quantum_luminance[52] = 103;
389         quantum_luminance[53] = 121;
390         quantum_luminance[54] = 120;
391         quantum_luminance[55] = 101;
392         quantum_luminance[56] = 72;
393         quantum_luminance[57] = 92;
394         quantum_luminance[58] = 95;
395         quantum_luminance[59] = 98;
396         quantum_luminance[60] = 112;
397         quantum_luminance[61] = 100;
398         quantum_luminance[62] = 103;
399         quantum_luminance[63] = 99;
400 
401         for (j = 0; j < 64; j++)
402         {
403             temp = ((quantum_luminance[j] * Quality) + 50) / 100;
404 
405             if (temp <= 0)
406             {
407                 temp = 1;
408             }
409 
410             if (temp > 255)
411             {
412                 temp = 255;
413             }
414 
415             quantum_luminance[j] = temp;
416         }
417 
418         index = 0;
419 
420         for (i = 0; i < 8; i++)
421         {
422             for (j = 0; j < 8; j++)
423             {
424                 // The divisors for the LL&M method (the slow integer method used in
425                 // jpeg 6a library).  This method is currently (04/04/98) incompletely
426                 // implemented.
427                 //                        DivisorsLuminance[index] = ((double) quantum_luminance[index]) << 3;
428                 // The divisors for the AAN method (the float method used in jpeg 6a library.
429                 DivisorsLuminance[index] = (double) ((double) 1.0 / ((double) quantum_luminance[index] * AANscaleFactor[i] * AANscaleFactor[j] * (double) 8.0));
430                 index++;
431             }
432         }
433 
434         // Creating the chrominance matrix
435         quantum_chrominance[0] = 17;
436         quantum_chrominance[1] = 18;
437         quantum_chrominance[2] = 24;
438         quantum_chrominance[3] = 47;
439         quantum_chrominance[4] = 99;
440         quantum_chrominance[5] = 99;
441         quantum_chrominance[6] = 99;
442         quantum_chrominance[7] = 99;
443         quantum_chrominance[8] = 18;
444         quantum_chrominance[9] = 21;
445         quantum_chrominance[10] = 26;
446         quantum_chrominance[11] = 66;
447         quantum_chrominance[12] = 99;
448         quantum_chrominance[13] = 99;
449         quantum_chrominance[14] = 99;
450         quantum_chrominance[15] = 99;
451         quantum_chrominance[16] = 24;
452         quantum_chrominance[17] = 26;
453         quantum_chrominance[18] = 56;
454         quantum_chrominance[19] = 99;
455         quantum_chrominance[20] = 99;
456         quantum_chrominance[21] = 99;
457         quantum_chrominance[22] = 99;
458         quantum_chrominance[23] = 99;
459         quantum_chrominance[24] = 47;
460         quantum_chrominance[25] = 66;
461         quantum_chrominance[26] = 99;
462         quantum_chrominance[27] = 99;
463         quantum_chrominance[28] = 99;
464         quantum_chrominance[29] = 99;
465         quantum_chrominance[30] = 99;
466         quantum_chrominance[31] = 99;
467         quantum_chrominance[32] = 99;
468         quantum_chrominance[33] = 99;
469         quantum_chrominance[34] = 99;
470         quantum_chrominance[35] = 99;
471         quantum_chrominance[36] = 99;
472         quantum_chrominance[37] = 99;
473         quantum_chrominance[38] = 99;
474         quantum_chrominance[39] = 99;
475         quantum_chrominance[40] = 99;
476         quantum_chrominance[41] = 99;
477         quantum_chrominance[42] = 99;
478         quantum_chrominance[43] = 99;
479         quantum_chrominance[44] = 99;
480         quantum_chrominance[45] = 99;
481         quantum_chrominance[46] = 99;
482         quantum_chrominance[47] = 99;
483         quantum_chrominance[48] = 99;
484         quantum_chrominance[49] = 99;
485         quantum_chrominance[50] = 99;
486         quantum_chrominance[51] = 99;
487         quantum_chrominance[52] = 99;
488         quantum_chrominance[53] = 99;
489         quantum_chrominance[54] = 99;
490         quantum_chrominance[55] = 99;
491         quantum_chrominance[56] = 99;
492         quantum_chrominance[57] = 99;
493         quantum_chrominance[58] = 99;
494         quantum_chrominance[59] = 99;
495         quantum_chrominance[60] = 99;
496         quantum_chrominance[61] = 99;
497         quantum_chrominance[62] = 99;
498         quantum_chrominance[63] = 99;
499 
500         for (j = 0; j < 64; j++)
501         {
502             temp = ((quantum_chrominance[j] * Quality) + 50) / 100;
503 
504             if (temp <= 0)
505             {
506                 temp = 1;
507             }
508 
509             if (temp >= 255)
510             {
511                 temp = 255;
512             }
513 
514             quantum_chrominance[j] = temp;
515         }
516 
517         index = 0;
518 
519         for (i = 0; i < 8; i++)
520         {
521             for (j = 0; j < 8; j++)
522             {
523                 // The divisors for the LL&M method (the slow integer method used in
524                 // jpeg 6a library).  This method is currently (04/04/98) incompletely
525                 // implemented.
526                 //                        DivisorsChrominance[index] = ((double) quantum_chrominance[index]) << 3;
527                 // The divisors for the AAN method (the float method used in jpeg 6a library.
528                 DivisorsChrominance[index] = (double) ((double) 1.0 / ((double) quantum_chrominance[index] * AANscaleFactor[i] * AANscaleFactor[j] * (double) 8.0));
529                 index++;
530             }
531         }
532 
533         // quantum and Divisors are objects used to hold the appropriate matices
534         quantum[0] = quantum_luminance;
535         Divisors[0] = DivisorsLuminance;
536         quantum[1] = quantum_chrominance;
537         Divisors[1] = DivisorsChrominance;
538     }
539 }
540 ///////////////////////////////////////////////////////////////////////////////
541 //  END OF FILE.
542 ///////////////////////////////////////////////////////////////////////////////