# Verlustbehaftete Kompression



## Java-Wichtel (10. Jan 2014)

Ich habe in meinem Modul Multimediagrundlagen das Thema
"Verlustbehaftete Kompression mit der DCT (Discrete Cosinus Transformation)"
und bei 2 Aufgaben habe ich Probleme:

Implementieren Sie die Discrete Cosinus Transformation (DCT) nach der folgenden Formel:







Implementieren Sie eine Klasse DCT , die eine Methode compute enthält, welche eine Matrix von 8x8 int Wertem erhält und für diese die DCT Matrix errechnet.

Mein Problem ist, diese Formel hatte ich noch nie in meinem ganzen Leben gesehen und es wurde in der Vorlesung auch nicht näher auf sie eingegangen. Ich weiß nicht, wie man diese Formel in Java umsetzen soll. Ich konnte mir bei den Summenzeichen nur vorstellen, dass man eine geschachtelte For-Schleife benötigt und das wars leider auch schon.

Unten hab ich meinen Quelltext gepostet, der aber fehlerhaft ist. 
In Zeile 19 steht meine Fehlerhafte Java-DCT-Formel.



```
public class DCT {

	private static double[][] m1 = {{107, 109, 115, 107, 113, 115, 115, 113},
							{24, 24, 24, 8, 16, 8, 16, 20},
							{16, 24, 16, 16, 24, 16, 15, 24},
							{16, 28, 16, 16, 28, 16, 24, 32},
							{16, 28, 24, 24, 28, 24, 24, 36},
							{24, 28, 24, 24, 28, 24, 24, 28},
							{16, 20, 16, 16, 28, 16, 24, 32},
							{8, 12, 8, 8, 8, 8, 8, 8}};
		
	public static void compute(double[][] m)
	{			
			
			for (int i = 0; i < m.length; i++)
			{
				for (int j = 0; j < m[i].length; j++)
				{
					System.out.print((Math.sqrt(2))/ 4 * (Math.cos( ((2*(m[i][0]) + 1)*(Math.sqrt(2))*Math.PI)/16) * Math.cos( ((2*(m[0][j]) + 1)*(Math.sqrt(2))*Math.PI)/16)) + "   ");
				}
				System.out.println("\n");
			}	
	}
	
	public static void main(String[] args) {

		compute(m1);
	}

}
```


----------



## libero (10. Jan 2014)

Nun ja, Du must als erstes zwei äußere Schleife programmieren um die Werte für F(u,v) zu berechnen.
Dabei werden für u und v die Werte aus Deiner 8x8-Matrix verwendet. In deinem Fall also laufen die beiden äußeren Schleifen also von 0..8.
Dann mußt Du den Term 1/4 C(u)*C(v) berechnen, nach der Formel welche für C(u) und C(v) angegeben wurde.
Dann brauchst Du wieder zwei innere Schleifen um die beiden Summen auszurechen. Die Schleifen laufen hierbei von 0..7. In den beiden inneren Schleifen berechnest Du dann die komplexen cos-Ausdrücke.

Du solltest dir auf jeden Fall Hilfsmethoden erstellen, um die einzelnen Ausdrücke auszurechnen.
Außerdem wäre eine Klasse für das Berechnen von komplexen Zahlen empfehlenswert.
(Divide et impera...)

In den Schleifen hast du dann nur noch einfache Methoden-Aufrufe durchzuführen,
was dein Programm ungemein vereinfacht und lesbarer macht.

Auch würde ich die berechneten Werte wieder in einer neuen transformierten 8x8-Matrix abspeichern.
So kannst Du am Ende die Ursprungs-Matrix und die transformierte Matrix (DCT) ausgeben.
Auch wieder in einer eigenen Methode.


*Gruß,

libero
*


----------



## Java-Wichtel (14. Jan 2014)

Danke für deinen Tipp. Nachdem ich herausgefunden habe, wie man die Formel
in Java schreibt, bin ich jetzt auf die Lösung gekommen.



Spoiler





```
public class DCT 
{ 
	private static int[][] MATRIX1 = {{107, 109, 115, 107, 113, 115, 115, 113},
							   {24, 24, 24, 8, 16, 8, 16, 20},
							   {16, 24, 16, 16, 24, 16, 16, 24},
							   {16, 28, 16, 16, 28, 16, 24, 32},
							   {16, 28, 24, 24, 32, 24, 24, 36},
							   {24, 28, 24, 24, 28, 24, 24, 28},
							   {16, 20, 16, 16, 28, 16, 24, 32},
							   {8, 12, 8, 8, 8, 8, 8, 8}};
			
	public static void compute (int[][] input)
	{
		int [][] output = new int [8][8];

		for (int u = 0; u < 8; u++) {

			for (int v = 0; v < 8; v++) { 
				double summe = 0.0; 
			for (int j = 0; j < 8; j++) {

				for(int k = 0; k < 8; k++) { 
					summe += Math.cos(((2*j+1)*u*Math.PI/(16.0)))*Math.cos(((2*k+1)*v*Math.PI/(16.0)))*input[j][k]; 
				}
			} 

			output[u][v] = (int) Math.round(summe * 0.25 * c(u) * c(v));
			}
		}
		for (int i = 0; i < 8; i++) {
			for (int j = 0; j < 8; j++) {
				System.out.print(output[i][j] + "  ");
			}
			System.out.println();
		}
	} 

	public static double c(int parameter){
		if(parameter == 0) { 
			return 1/Math.sqrt(2.0); 
		} else {
			return 1; 
		}
	} 

	public static void main (String [] args){ 
		new DCT(); 
		compute(MATRIX1);
	}[/SPOILER]
```


----------

