Java-Code?

1 Antwort

Naja, du nimmst dir das Array und tauschst jeweils das erste mit dem letzten Element, dann das zweite mit dem vorletzen und so weiter, bis du in der Mitte des Arrays ankommst.

Ich würde der Einfachheit halber eine Methode schreiben, die einfach ein Array spiegeln kann und die dann in die beiden gefragten Methoden einbauen.

Die Methode horizontalSpiegeln ist etwas verwirrend, weil wenn man das Bild an der horizontalen Achse spiegelt, werden oben und unten vertauscht, was ich eher als "vertikal Spiegeln" ansehen würde.

Mathematik2000 
Fragesteller
 20.12.2022, 10:49
 public void horizontalSpiegeln()
    {
        for (int y = 0; y < _hoehe/2; y++)
        {
            for (int x = 0; x < _breite; x++)
            {
                short i = _bilddaten[y][x];//jeden Bildpunkt mit short-Wert speichern
                _bilddaten[y][x] = _bilddaten[_hoehe - y-1][x];//untere Teil des Bildes der oberen Hälfte zuweisen 
                _bilddaten[_hoehe - y-1][x] = i;//erste Hälfte des Original-Bildes,der unteren Teil zuweisen
            }
        }
        zeichneBild();


    }

public void punktpiegeln()
    {
        for (int y = 0; y < _hoehe/2; y++)
        {
            for (int x = 0; x < _breite; x++)
            {
                short i = _bilddaten[y][x];
                _bilddaten[y][x] = _bilddaten[_hoehe-y-1][_breite-x-1];
                _bilddaten[_hoehe-y-1][_breite-x-1] = i;
            }
        }
        zeichneBild(); 


    }
1
daCypher  20.12.2022, 12:02
@Mathematik2000

Ja, sehr gut 👍. Du machst es etwas anders als erwartet, aber das Ergebnis stimmt.

Bei dem Namen punktSpiegeln ist dir das S verloren gegangen, mach das noch rein, bevor du die Aufgabe zurückschickst.

Bei horizontalSpiegeln hätte ich immer die ganze Zeile getauscht und nicht jeden Pixel einzeln:

public void horizontalSpiegeln() {
    for (int y = 0; y < _hoehe / 2; y++) {
        var tempZeile = _bilddaten[y];
        _bilddaten[y] = _bilddaten[_hoehe - y - 1];
        _bilddaten[_hoehe - y - 1] = tempZeile;
    }
    zeichneBild();
}

allerdings wäre "tempZeile" dann ein Array und Arrays sind ja nicht erlaubt (auch wenn ich glaube, dass der Lehrer damit meinte, dass man das Ergebnis nicht in ein neues Array speichern soll, und nicht dass gar keine Arrays erlaubt sind)

0
Mathematik2000 
Fragesteller
 20.12.2022, 12:07
@daCypher

Wie kann ich diese Methode schreiben, verstehe ich nicht:

Implementieren Sie die Operation weichzeichnen. Das Weichzeichnen wird erreicht, in- dem der Mittelwert der acht umgebenden Bildpunkte des jeweils betrachteten Bildpunkts errechnet wird und dieser Mittelwert dann den neuen Wert dieses Bildpunktes bildet. Achten Sie auf Randbedingungen!

Warum wäre eine „in place“-Lösung hier problematisch?

0
daCypher  20.12.2022, 12:10
@Mathematik2000

Hab ich unter den originalen Kommentar geschrieben. Wenn du die Antwort nicht siehst, musst du auf "Weitere Kommentare zur Antwort anzeigen" klicken.

0
Mathematik2000 
Fragesteller
 20.12.2022, 12:39
@Mathematik2000

Wie kann ich die Methode spot schreiben?

Implementieren Sie die Operation spot, die ein Scheinwerferlicht projiziert. Am einfachsten ist ein Scheinwerferlicht, das exakt von oben auf unser Bild scheint und einen runden Kegel wirft. Sie können aber auch eine andere Lichtkegelform wählen.

/**
     * Erzeuge bei diesem Bild einen Spot mit Radius r, Mittelpunkt x0,y0 und
     * Beleuchtungsintensitaet i. Ausserhalb von r nimmt die Ausleuchtung linear ab.
     * Wie im wirklichen Leben...
     * 
     * @param xo
     *            x-Koordinate des Mittelpunktes
     * @param yo
     *            y-Koordinate des Mittelpunktes
     * @param r
     *            Radius
     * @param i
     *            Beleuchtungsintesitaet
     */
    public void spot(int x0, int y0, int r, short i)
{
0
daCypher  20.12.2022, 13:23
@Mathematik2000

Hui, jetzt wird's etwas komplizierter. Da nicht nur die Pixel innerhalb des Spots beleuchtet werden sollen, sondern es außerhalb des Spots linear abnimmt (mit welchem Faktor?) würde ich jeden Pixel durchgehen und den Abstand zum Mittelpunkt des Spots berechnen (Satz des Pythagoras. Die Funktion für die Wurzel findest du unter Math.sqrt(). Die Betragsfunktion ist Math.abs()).

Wenn der Abstand kleiner/gleich r ist, dann wird i dazuaddiert, ansonsten wird je nach Abstand etwas weniger als i dazuaddiert.

0
Mathematik2000 
Fragesteller
 20.12.2022, 13:27
@daCypher

schwer zu vertstehen. Können Sie vielleicht den Code mit Erklärung schreiben? Ich komme mit dieser Aufgabe nicht zurecht.

0
daCypher  20.12.2022, 14:00
@Mathematik2000

Ich probiere es mal. Ob das Ergebnis stimmt, kann ich nicht sagen, weil ich meine Tests einfach mit einem kleinen Array mache und kein Bild daraus zeichnen lasse.

public void spot(int x0, int y0, int r, short i)
{
    // Jeden Pixel durchgehen
    for (int y = 0; y<_hoehe; y++) {
        for (int x = 0; x<_breite; x++) {
            /*
                * h = horizontaler Abstand
                * v = vertikaler Abstand
                * Abstand = Wurzel(h²+v²)
                */
            double h = Math.abs(x-x0);
            double v = Math.abs(y-y0);
            double abstand = Math.sqrt((h*h)+(v*v));

            // Berechnen, wie viel heller der Pixel gemacht werden soll
            int gain;

            // Gucken, ob der Pixel im Spot ist
            if (abstand <= r) {
                gain = i;
            } else {
                // Ansonsten einen linearen Gradienten berechnen
                // Ich nehme jetzt einfach mal eine Helligkeit von 5 pro Pixel Abstand zum Spotrand
                gain = (int)((-5.0 * (abstand-r))+i);

                // Wenn der Pixel so weit weg ist, dass ein negatives Ergebnis rauskommt, soll er natürlich nicht verändert werden
                gain = Math.max(gain, 0);
            }
            // auf den Pixel anwenden
            _bilddaten[y][x] += gain;
        }
    }
    zeichneBild();
}
0
Mathematik2000 
Fragesteller
 20.12.2022, 10:58

Wie kann ich diese Methode schreiben, verstehe ich nicht:

Implementieren Sie die Operation weichzeichnen. Das Weichzeichnen wird erreicht, in- dem der Mittelwert der acht umgebenden Bildpunkte des jeweils betrachteten Bildpunkts errechnet wird und dieser Mittelwert dann den neuen Wert dieses Bildpunktes bildet. Achten Sie auf Randbedingungen!

Warum wäre eine „in place“-Lösung hier problematisch?

0
daCypher  20.12.2022, 12:07
@Mathematik2000

Bei der Aufgabe musst du wie eben zwei Schleifen machen, damit du jeden Pixel durchgehst (diesmal über die gesamte Höhe und Breite) und in den Schleifen nochmal zwei Schleifen, mit denen du jeweils von -1 bis +1 Pixel gehst und den Mittelwert der Pixel bildest. An den Rändern und Ecken musst du aufpassen, dass du nur Pixel abfragst, die auch existieren. Wenn du ganz oben links bist, kannst du natürlich nicht den Pixel links daneben abfragen.

Und in-Place geht natürlich nicht, weil wenn du einen Pixel weichzeichnest, können die umliegenden Pixel nicht mehr auf den Originalwert zugreifen und kriegen ein falsches Ergebnis.

0
Mathematik2000 
Fragesteller
 20.12.2022, 12:32
@daCypher
public void weichzeichnen()
    {
       
       int a=0;
        short[][] _kopie = new short[_hoehe][_breite];
         
        for (int y=1;y<_hoehe-1;y++)
        {
            for (int x=1;x<_breite-1;x++)
            {
               
                a=(_bilddaten[y+1][x+1]+_bilddaten[y-1][x-1]+_bilddaten[y+1][x-1]+_bilddaten[y-1][x+1]+_bilddaten[y][x+1]+_bilddaten[y][x-1]+_bilddaten[y+1][x]+_bilddaten[y-1][x])/8;
                _kopie[y][x]=(short)a;                
            }
        }
        _bilddaten=_kopie;
        zeichneBild();
    }
0
daCypher  20.12.2022, 13:14
@Mathematik2000

Wie gesagt, ich würde eher noch zwei zusätzliche Schleifen einbauen, die jeweils von -1 bis +1 gehen. Da kannst du dann auch einstellen, dass sie am Rand z.B. nur von 0 bis 1 oder -1 bis 0 gehen sollen und dann halt zählen, wie viele Pixel summiert wurden.

public void weichzeichnen()
{
    short[][] _kopie = new short[_hoehe][_breite];
    for (int y = 0; y < _hoehe; y++)
    {
        for (int x = 0; x < _breite; x++)
        {
            int sum = 0; // Summe der Pixelwerte
            int count = 0; // Anzahl der Pixelwerte (normalerweise 8, am Rand 5, in den Ecken 3)
            // Delta-Y Schleife von -1 bis +1 (Am Rand nur ab/bis 0)
            for (int dy = (y>0?-1:0); dy <= (y<_hoehe-1?1:0); dy++) {
                // Delta-X Schleife von -1 bis +1 (Am Rand nur ab/bis 0)
                for (int dx = (x>0?-1:0); dx <= (x<_breite-1?1:0); dx++) {
                    // Eigenen Pixelwert ignorieren
                    if (dy != 0 || dx != 0) {
                        sum += _bilddaten[y + dy][x + dx];
                        count++;
                    }
                }
            }
            _kopie[y][x] = (short) (sum/count);
        }
    }
    _bilddaten = _kopie;
    zeichneBild();
}
0
daCypher  20.12.2022, 13:40
@Mathematik2000

Ich kann kein Bild einfügen, um das zu verdeutlichen. In der Mitte des Bildes hast du halt 8 Pixel um jeden Pixel rum (3 Zeilen mal 3 Spalten minus den mittleren Pixel). Am Rand fehlt eine Zeile/Spalte, wodurch es nur noch 2*3-1 Pixel sind und in einer Ecke fehlt eine Zeile und eine Spalte. Also 2*2-1 Pixel. Und dann gibt es theoretisch noch Sonderfälle, wenn das Bild nur einen Pixel hoch oder breit ist.

1