Jochen: Rekursive Funktion liefert ungewünschtes Ergebnis

Hallo Forum,

ausgehend von dieser Aufgabenstellung wollte ich den Code in eine schöne Funktion ausgliedern.

Hier nochmal die Aufgabe:

Suche ein Image der Größe 842 x 532 von unten nach oben (bis zur y-Grenze 500) nach dem ersten freien Raum ab, der 150px hoch ist.

Hier die Funktion:

function suche_freiraum($line = 842,$img2) {
    $freiraum = $failed = 0;
    $fp = fopen($_SERVER['DOCUMENT_ROOT']."/tmp/pixel.txt",'a+');
    for($myY = $line;$myY > 500;$myY--) {
        for($myX = 0;$myX < 530;$myX++) {
            $pixel = $img2->getImagePixelColor($myX,$myY);
            $colors = $pixel->getColorAsString();
            if($colors != "srgba(255,255,255,0)" && $colors != "srgb(255,255,255)") {   // wenn kein weißes Pixel
                $failed++;
            }
        }
        // Line zuende und failed noch auf 0 ?
        if($failed == 0) {
            $freiraum++;
            fwrite($fp,"line ".$myY.": all white. Freiraum = ".$freiraum."\n");
        } else {
            fwrite($fp,"line ".$myY.": failed\n");
            suche_freiraum($myY-1,$img2);
        }
        if($freiraum == 150) {
            fclose($fp);
            return $myY;
        }
    }
    fclose($fp);
    return 0; // kein Freiraum gefunden
}

Funktioniert sehr gut, wenn das Image innerhalb der untersten 150px komplett weiß ist.

Aber wenn innerhalb der untersten 150px nicht alles weiß ist, dann merke ich, dass da noch ein Fehler in der Funktion steckt.

Denn dann erhalte ich sowas hier: (sorry für den langen Text, aber ansonsten erkennt man das Schema des fehlers vielleicht nicht).

Erkennt jemand, wo es in der Funktion hakt?

Jochen

line 842: all white. Freiraum = 1
line 841: all white. Freiraum = 2
line 840: all white. Freiraum = 3
line 839: all white. Freiraum = 4
line 838: all white. Freiraum = 5
line 837: all white. Freiraum = 6
line 836: all white. Freiraum = 7
line 835: all white. Freiraum = 8
line 834: all white. Freiraum = 9
line 833: all white. Freiraum = 10
line 832: all white. Freiraum = 11
line 831: all white. Freiraum = 12
line 830: all white. Freiraum = 13
line 829: all white. Freiraum = 14
line 828: all white. Freiraum = 15
line 827: all white. Freiraum = 16
line 826: all white. Freiraum = 17
line 825: all white. Freiraum = 18
line 824: all white. Freiraum = 19
line 823: all white. Freiraum = 20
line 822: all white. Freiraum = 21
line 821: all white. Freiraum = 22
line 820: all white. Freiraum = 23
line 819: all white. Freiraum = 24
line 818: all white. Freiraum = 25
line 817: all white. Freiraum = 26
line 816: all white. Freiraum = 27
line 815: all white. Freiraum = 28
line 814: all white. Freiraum = 29
line 813: all white. Freiraum = 30
line 812: all white. Freiraum = 31
line 811: all white. Freiraum = 32
line 810: all white. Freiraum = 33
line 809: all white. Freiraum = 34
line 808: all white. Freiraum = 35
line 807: all white. Freiraum = 36
line 806: all white. Freiraum = 37
line 805: all white. Freiraum = 38
line 804: all white. Freiraum = 39
line 803: all white. Freiraum = 40
line 802: all white. Freiraum = 41
line 801: all white. Freiraum = 42
line 800: all white. Freiraum = 43
line 799: all white. Freiraum = 44
line 798: all white. Freiraum = 45
line 797: all white. Freiraum = 46
line 796: all white. Freiraum = 47
line 795: all white. Freiraum = 48
line 794: all white. Freiraum = 49
line 793: all white. Freiraum = 50
line 792: all white. Freiraum = 51
line 791: all white. Freiraum = 52
line 790: all white. Freiraum = 53
line 789: failed
line 788: failed
line 787: failed
line 786: failed
line 785: failed
line 784: failed
line 783: failed
line 782: failed
line 781: failed
line 780: all white. Freiraum = 1
line 779: all white. Freiraum = 2
line 778: failed
line 777: failed
line 776: failed
line 775: failed
line 774: failed
line 773: failed
line 772: failed
line 771: failed
line 770: failed
line 769: failed
line 768: all white. Freiraum = 1
line 767: all white. Freiraum = 2
line 766: all white. Freiraum = 3
line 765: failed
line 764: failed
line 763: failed
line 762: failed
line 761: failed
line 760: failed
line 759: failed
line 758: failed
line 757: all white. Freiraum = 1
line 756: all white. Freiraum = 2
line 755: all white. Freiraum = 3
line 754: all white. Freiraum = 4
line 753: all white. Freiraum = 5
line 752: all white. Freiraum = 6
line 751: all white. Freiraum = 7
line 750: all white. Freiraum = 8
line 749: all white. Freiraum = 9
line 748: all white. Freiraum = 10
line 747: all white. Freiraum = 11
line 746: all white. Freiraum = 12
line 745: all white. Freiraum = 13
line 744: all white. Freiraum = 14
line 743: all white. Freiraum = 15
line 742: all white. Freiraum = 16
line 741: all white. Freiraum = 17
line 740: all white. Freiraum = 18
line 739: all white. Freiraum = 19
line 738: all white. Freiraum = 20
line 737: all white. Freiraum = 21
line 736: all white. Freiraum = 22
line 735: all white. Freiraum = 23
line 734: all white. Freiraum = 24
line 733: all white. Freiraum = 25
line 732: all white. Freiraum = 26
line 731: all white. Freiraum = 27
line 730: all white. Freiraum = 28
line 729: all white. Freiraum = 29
line 728: all white. Freiraum = 30
line 727: all white. Freiraum = 31
line 726: all white. Freiraum = 32
line 725: all white. Freiraum = 33
line 724: all white. Freiraum = 34
line 723: all white. Freiraum = 35
line 722: all white. Freiraum = 36
line 721: all white. Freiraum = 37
line 720: all white. Freiraum = 38
line 719: all white. Freiraum = 39
line 718: all white. Freiraum = 40
line 717: all white. Freiraum = 41
line 716: all white. Freiraum = 42
line 715: all white. Freiraum = 43
line 714: all white. Freiraum = 44
line 713: all white. Freiraum = 45
line 712: all white. Freiraum = 46
line 711: all white. Freiraum = 47
line 710: all white. Freiraum = 48
line 709: all white. Freiraum = 49
line 708: all white. Freiraum = 50
line 707: all white. Freiraum = 51
line 706: all white. Freiraum = 52
line 705: all white. Freiraum = 53
line 704: all white. Freiraum = 54
line 703: all white. Freiraum = 55
line 702: all white. Freiraum = 56
line 701: all white. Freiraum = 57
line 700: all white. Freiraum = 58
line 699: all white. Freiraum = 59
line 698: all white. Freiraum = 60
line 697: all white. Freiraum = 61
line 696: all white. Freiraum = 62
line 695: all white. Freiraum = 63
line 694: all white. Freiraum = 64
line 693: all white. Freiraum = 65
line 692: all white. Freiraum = 66
line 691: all white. Freiraum = 67
line 690: all white. Freiraum = 68
line 689: all white. Freiraum = 69
line 688: all white. Freiraum = 70
line 687: all white. Freiraum = 71
line 686: all white. Freiraum = 72
line 685: all white. Freiraum = 73
line 684: all white. Freiraum = 74
line 683: all white. Freiraum = 75
line 682: all white. Freiraum = 76
line 681: all white. Freiraum = 77
line 680: all white. Freiraum = 78
line 679: all white. Freiraum = 79
line 678: all white. Freiraum = 80
line 677: all white. Freiraum = 81
line 676: all white. Freiraum = 82
line 675: all white. Freiraum = 83
line 674: all white. Freiraum = 84
line 673: all white. Freiraum = 85
line 672: all white. Freiraum = 86
line 671: all white. Freiraum = 87
line 670: all white. Freiraum = 88
line 669: all white. Freiraum = 89
line 668: all white. Freiraum = 90
line 667: all white. Freiraum = 91
line 666: all white. Freiraum = 92
line 665: all white. Freiraum = 93
line 664: all white. Freiraum = 94
line 663: all white. Freiraum = 95
line 662: all white. Freiraum = 96
line 661: all white. Freiraum = 97
line 660: all white. Freiraum = 98
line 659: all white. Freiraum = 99
line 658: all white. Freiraum = 100
line 657: all white. Freiraum = 101
line 656: all white. Freiraum = 102
line 655: all white. Freiraum = 103
line 654: all white. Freiraum = 104
line 653: all white. Freiraum = 105
line 652: all white. Freiraum = 106
line 651: all white. Freiraum = 107
line 650: all white. Freiraum = 108
line 649: all white. Freiraum = 109
line 648: all white. Freiraum = 110
line 647: all white. Freiraum = 111
line 646: all white. Freiraum = 112
line 645: all white. Freiraum = 113
line 644: all white. Freiraum = 114
line 643: all white. Freiraum = 115
line 642: all white. Freiraum = 116
line 641: all white. Freiraum = 117
line 640: all white. Freiraum = 118
line 639: all white. Freiraum = 119
line 638: all white. Freiraum = 120
line 637: all white. Freiraum = 121
line 636: all white. Freiraum = 122
line 635: all white. Freiraum = 123
line 634: all white. Freiraum = 124
line 633: all white. Freiraum = 125
line 632: all white. Freiraum = 126
line 631: all white. Freiraum = 127
line 630: all white. Freiraum = 128
line 629: all white. Freiraum = 129
line 628: all white. Freiraum = 130
line 627: all white. Freiraum = 131
line 626: all white. Freiraum = 132
line 625: all white. Freiraum = 133
line 624: all white. Freiraum = 134
line 623: all white. Freiraum = 135
line 622: all white. Freiraum = 136
line 621: all white. Freiraum = 137
line 620: all white. Freiraum = 138
line 619: all white. Freiraum = 139
line 618: all white. Freiraum = 140
line 617: all white. Freiraum = 141
line 616: all white. Freiraum = 142
line 615: all white. Freiraum = 143
line 614: all white. Freiraum = 144
line 613: all white. Freiraum = 145
line 612: all white. Freiraum = 146
line 611: all white. Freiraum = 147
line 610: all white. Freiraum = 148
line 609: all white. Freiraum = 149
line 608: all white. Freiraum = 150
line 757: failed
line 756: all white. Freiraum = 1
line 755: all white. Freiraum = 2
line 754: all white. Freiraum = 3
usw.
usw.
usw.
  1. Hallo Jochen,

    Grundlehren der Informatik:

    • nichts wächst so schnell wie exponentiell
    • nichts geht so schnell schief wie rekursiv

    Du kannst deine Logik entweder iterativ (Schleife über $myY) oder rekursiv programmieren. Du tust aber beides.

    Solange Du weiße Zeilen findest, zählst Du myY herunter. Okay. Aber sobald Du eine Zeile mit Farbe drin hast, rufst Du Dich rekursiv auf. Kehrt die Rekursion zurück, machst Du da weiter, wo Du in die Rekursion eingestiegen bist, deswegen der Sprung zurück zur 757.

    Da Du für jeden 'failed' eine Rekursion einleitest, bist Du hier schon auf Rekursionslevel 27. Irgendwann kommst Du da raus, dann gibt's einen Sprung zurück zur 758, dann zur 759, und jedesmal läuft der ganze Klumpatsch von vorn los. Ackermann lässt grüßen, fürchte ich.

    Du willst einen weißen Streifen finden, der

    • möglichst hoch oben ist
    • hoch genug ist

    Richtig? In dem Fall solltest Du von oben nach unten suchen. Keine Rekursion, einfach nur $myY von oben nach unten marschieren lassen.

    Wenn Du eine nichtweiße Zeile findest:

    • setze $freiraum auf 0
    • setze $whiteStart auf $myY + 1

    Wenn Du eine weiße Zeile findest:

    • erhöhe $freiraum um 1
    • ist $freiraum >= 150, brich die Schleife ab.

    Hinter der Schleife prüfe, ob $freiraum >= 150 ist. Wenn ja, zeichne das Logo ab y=$whiteStart.

    Ob getImagePixelColor und getColorAsString eine effiziente Methode zur pixelweisen Prüfung sind, weiß ich nicht, dazu habe ich von Imagick zu wenig Ahnung. Unter .net wäre das der Performance-Todesstoß, DA habe ich Erfahrung...

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Ob getImagePixelColor und getColorAsString eine effiziente Methode zur pixelweisen Prüfung sind, weiß ich nicht,

      Natürlich ist das „teuer“. 530*500 = 265000. Wenn das jeder so „effektiv“ macht brauchen wir noch lange die Kohlekraftwerke…

      Zudem wird die Methode vorhersagbar versagen

      • Wenn das gelieferte PDF das Ergebnis eines Scans ist. Denn dann reicht ein falsches, nicht perfekt weises (255,255,255,0) - Pixel und davon wird es viele geben: Staubkörner, naseweise Obstfliegen und dergleichen.
      • Ergo auch wenn das gelieferte PDF eine Hintergrundfarbe hat.
      • Wenn das gelieferte PDF in der einen oder anderen Form gegen diese Art des Auslesens geschützt ist.
      1. Hallo Willi,

        Natürlich ist das „teuer“. 530*500 = 265000. Wenn das jeder so „effektiv“ macht brauchen wir noch lange die Kohlekraftwerke…

        Geht "RatzFatz". 😉

        Zudem wird die Methode vorhersagbar versagen

        Da ist allerdings was dran.

        • Wenn das gelieferte PDF das Ergebnis eines Scans ist. Denn dann reicht ein falsches, nicht perfekt weises (255,255,255,0) - Pixel und davon wird es viele geben: Staubkörner, naseweise Obstfliegen und dergleichen.
        • Ergo auch wenn das gelieferte PDF eine Hintergrundfarbe hat.
        • Wenn das gelieferte PDF in der einen oder anderen Form gegen diese Art des Auslesens geschützt ist.

        Macht aber trotzdem Spaß und ich lerne etwas dabei.
        Also gibts doch gar nichts auszusetzen (was Du auch nicht getan hast, Deine Anmerkungen zum Thema nehme ich gerne an).

        Jochen

      2. Hallo Raketenwilli,

        das Bild wird, wenn ich das richtig verstund, aus der letzten Seite des PDF gerendert. D.h. sozusagen gedruckt. Bei einem "Screen-only" PDF mag das dann versagen. Aber wenn die Bitmap erstmal da ist, ist der PDF Schutz für die Weißraumsuche erstmal irrelevant.

        Eine Hintergrundfarbe im PDF oder Scan-Artefakte - dagegen kann man sich wohl nicht wehren. Aber solange die im Anwendungskontext nicht vorhanden sind, ist's wohl wurscht.

        Was wäre denn performanter als diese Pixelermittlung? Ein pixelRegionIterator? Und IsSimilar (oder IsPixelSimilar) statt auslesen des Farbwertes als String? Ich kann's hier nicht probieren…

        Rolf

        --
        sumpsi - posui - obstruxi
        1. Hallo Rolf,

          Was wäre denn performanter als diese Pixelermittlung?

          Die ist performant genug.

          20.12.2022 12:35:47.902900: line 842: all white. Freiraum = 1
          20.12.2022 12:35:47.905400: line 841: all white. Freiraum = 2
          20.12.2022 12:35:47.907400: line 840: all white. Freiraum = 3
          20.12.2022 12:35:47.909200: line 839: all white. Freiraum = 4
          20.12.2022 12:35:47.910900: line 838: all white. Freiraum = 5
          20.12.2022 12:35:47.914300: line 837: all white. Freiraum = 6
          20.12.2022 12:35:47.917300: line 836: all white. Freiraum = 7
          20.12.2022 12:35:47.919400: line 835: all white. Freiraum = 8
          20.12.2022 12:35:47.921200: line 834: all white. Freiraum = 9
          20.12.2022 12:35:47.922800: line 833: all white. Freiraum = 10
          20.12.2022 12:35:47.924500: line 832: all white. Freiraum = 11
          20.12.2022 12:35:47.926300: line 831: all white. Freiraum = 12
          20.12.2022 12:35:47.927900: line 830: all white. Freiraum = 13
          20.12.2022 12:35:47.931500: line 829: all white. Freiraum = 14
          20.12.2022 12:35:47.933900: line 828: all white. Freiraum = 15
          20.12.2022 12:35:47.935600: line 827: all white. Freiraum = 16
          20.12.2022 12:35:47.937300: line 826: all white. Freiraum = 17
          20.12.2022 12:35:47.938900: line 825: all white. Freiraum = 18
          20.12.2022 12:35:47.940600: line 824: all white. Freiraum = 19
          20.12.2022 12:35:47.942200: line 823: all white. Freiraum = 20
          20.12.2022 12:35:47.943900: line 822: all white. Freiraum = 21
          20.12.2022 12:35:47.946600: line 821: all white. Freiraum = 22
          20.12.2022 12:35:47.948600: line 820: all white. Freiraum = 23
          20.12.2022 12:35:47.950500: line 819: all white. Freiraum = 24
          20.12.2022 12:35:47.952200: line 818: all white. Freiraum = 25
          20.12.2022 12:35:47.953900: line 817: all white. Freiraum = 26
          20.12.2022 12:35:47.955500: line 816: all white. Freiraum = 27
          20.12.2022 12:35:47.957200: line 815: all white. Freiraum = 28
          20.12.2022 12:35:47.958900: line 814: all white. Freiraum = 29
          20.12.2022 12:35:47.960600: line 813: all white. Freiraum = 30
          20.12.2022 12:35:47.962800: line 812: all white. Freiraum = 31
          20.12.2022 12:35:47.965500: line 811: all white. Freiraum = 32
          20.12.2022 12:35:47.967500: line 810: all white. Freiraum = 33
          20.12.2022 12:35:47.969400: line 809: all white. Freiraum = 34
          20.12.2022 12:35:47.971100: line 808: all white. Freiraum = 35
          20.12.2022 12:35:47.972900: line 807: all white. Freiraum = 36
          20.12.2022 12:35:47.974500: line 806: all white. Freiraum = 37
          20.12.2022 12:35:47.976200: line 805: all white. Freiraum = 38
          20.12.2022 12:35:47.977800: line 804: failed
          20.12.2022 12:35:47.980400: line 803: failed
          20.12.2022 12:35:47.982100: line 802: failed
          20.12.2022 12:35:47.983800: line 801: failed
          20.12.2022 12:35:47.985400: line 800: failed
          20.12.2022 12:35:47.987200: line 799: failed
          20.12.2022 12:35:47.989000: line 798: failed
          20.12.2022 12:35:47.990900: line 797: failed
          20.12.2022 12:35:47.992600: line 796: failed
          20.12.2022 12:35:47.994200: line 795: all white. Freiraum = 1
          20.12.2022 12:35:47.996900: line 794: all white. Freiraum = 2
          20.12.2022 12:35:47.999000: line 793: all white. Freiraum = 3
          20.12.2022 12:35:48.000700: line 792: all white. Freiraum = 4
          20.12.2022 12:35:48.002600: line 791: all white. Freiraum = 5
          20.12.2022 12:35:48.005700: line 790: all white. Freiraum = 6
          20.12.2022 12:35:48.007400: line 789: all white. Freiraum = 7
          20.12.2022 12:35:48.009100: line 788: all white. Freiraum = 8
          20.12.2022 12:35:48.011600: line 787: all white. Freiraum = 9
          20.12.2022 12:35:48.015100: line 786: all white. Freiraum = 10
          20.12.2022 12:35:48.017100: line 785: all white. Freiraum = 11
          20.12.2022 12:35:48.019000: line 784: all white. Freiraum = 12
          20.12.2022 12:35:48.020700: line 783: all white. Freiraum = 13
          20.12.2022 12:35:48.022500: line 782: all white. Freiraum = 14
          20.12.2022 12:35:48.024600: line 781: all white. Freiraum = 15
          20.12.2022 12:35:48.026300: line 780: all white. Freiraum = 16
          20.12.2022 12:35:48.028300: line 779: all white. Freiraum = 17
          20.12.2022 12:35:48.031500: line 778: all white. Freiraum = 18
          20.12.2022 12:35:48.033400: line 777: all white. Freiraum = 19
          20.12.2022 12:35:48.035200: line 776: all white. Freiraum = 20
          20.12.2022 12:35:48.036900: line 775: all white. Freiraum = 21
          20.12.2022 12:35:48.038600: line 774: all white. Freiraum = 22
          20.12.2022 12:35:48.040200: line 773: all white. Freiraum = 23
          20.12.2022 12:35:48.041900: line 772: all white. Freiraum = 24
          20.12.2022 12:35:48.043500: line 771: all white. Freiraum = 25
          20.12.2022 12:35:48.045700: line 770: all white. Freiraum = 26
          20.12.2022 12:35:48.048800: line 769: all white. Freiraum = 27
          20.12.2022 12:35:48.051300: line 768: all white. Freiraum = 28
          20.12.2022 12:35:48.053000: line 767: all white. Freiraum = 29
          20.12.2022 12:35:48.054600: line 766: all white. Freiraum = 30
          20.12.2022 12:35:48.056300: line 765: all white. Freiraum = 31
          20.12.2022 12:35:48.058000: line 764: all white. Freiraum = 32
          20.12.2022 12:35:48.059600: line 763: all white. Freiraum = 33
          20.12.2022 12:35:48.061300: line 762: all white. Freiraum = 34
          20.12.2022 12:35:48.064500: line 761: all white. Freiraum = 35
          20.12.2022 12:35:48.066500: line 760: all white. Freiraum = 36
          20.12.2022 12:35:48.068200: line 759: all white. Freiraum = 37
          20.12.2022 12:35:48.069900: line 758: all white. Freiraum = 38
          20.12.2022 12:35:48.071500: line 757: all white. Freiraum = 39
          20.12.2022 12:35:48.073200: line 756: all white. Freiraum = 40
          20.12.2022 12:35:48.074800: line 755: all white. Freiraum = 41
          20.12.2022 12:35:48.076500: line 754: all white. Freiraum = 42
          20.12.2022 12:35:48.078300: line 753: all white. Freiraum = 43
          20.12.2022 12:35:48.080800: line 752: all white. Freiraum = 44
          20.12.2022 12:35:48.082500: line 751: all white. Freiraum = 45
          20.12.2022 12:35:48.084100: line 750: all white. Freiraum = 46
          20.12.2022 12:35:48.085800: line 749: all white. Freiraum = 47
          20.12.2022 12:35:48.087600: line 748: all white. Freiraum = 48
          20.12.2022 12:35:48.089300: line 747: all white. Freiraum = 49
          20.12.2022 12:35:48.091000: line 746: all white. Freiraum = 50
          ...
          20.12.2022 12:35:48.276900: line 647: all white. Freiraum = 149
          20.12.2022 12:35:48.279000: line 646: all white. Freiraum = 150
          
          1. Hallo Rolf,

            Was wäre denn performanter als diese Pixelermittlung?

            Die ist performant genug.

            Am längsten benötigt sie, wenn genügend weiß im Bild ist, aber es dennoch zu wenig Freiraum gibt, oder?

            Edit: Nein, eigentlich ist das egal. Hauptsache, es gibt keinen Freiraum, dann braucht die Pixelermittlung am längsten. Man könnte sie sogar beschleunihgen, indem man die zeile sofort abbricht, nachdem das erste nicht weiße Pixel gefunden wurde.

            Hab ich ein PDF genommen, wo das passt:

            20.12.2022 12:41:41.290200: line 842: all white. Freiraum = 1
            ...
            20.12.2022 12:41:41.910800: line 501: failed
            

            Knapp über einer halben Sekunde Arbeit, das ist ok.

            Jochen

            1. Hallo Jochen,

              indem man die Zeile sofort abbricht, nachdem das erste nicht weiße Pixel gefunden wurde.

              Das solltest Du auf jeden Fall tun.

              Knapp über einer halben Sekunde Arbeit, das ist ok.

              Nein, das ist für einen Webserver eine halbe Ewigkeit. Vorher hast Du ja auch noch das Bild generiert.

              Hast Du mal den PixelRegionIterator und isPixelSimilar ausprobiert?

                                                        // x  y   width height
              $areaIterator = $img->getPixelRegionIterator(0, 500, 530, 342);
              $white = new ImagickPixel("#ffffff");
              
              foreach ($areaIterator as $row => $rowIterator) {
                  foreach ($rowIterator as $pixel) {
                      if ($pixel->IsPixelSimilar($white, 0.01)) {
                      // "weiß genug"
                      }
                      else {
                      // nicht weiß
                      }
                  }
                  // Warum auch immer Imagick das so will, aber es gehört zum Mantra
                  // des Iterators, ihn nach jedem Lauf eines Zeileninterators zu 
                  // resynchronisieren
                  $areaIterator->syncIterator();
              }
              

              Der Wert 0.01 bei isPixelSimilar ist der Unschärfewert für den Vergleich. Imagick bestimmt den Abstand zweier Farben im RGB Farbwürfel (also Differenz rot zum Quadrat, Differenz grün zum Quadrat, Differenz blau zum Quadrat, aufsummieren, Wurzel ziehen). Wobei die Farbwerte nicht von 0 bis 255 gehen, sondern auf 0 bis 1 skaliert werden.

              Der Unterschied zwischen "rgb(255,255,255)" und "rgb(254,254,254)" ist

              $$\displaystyle \sqrt{ \Big( \frac{1}{255} \Big) ^ 2 + \Big( \frac{1}{255} \Big) ^ 2 + \Big( \frac{1}{255} \Big) ^ 2 }   = \sqrt{3} \cdot \frac{1}{255}   \approx 0{,}0068 $$

              das habe ich großzügig zu 0,01 aufgerundet. Wie Transparenz sich auswirkt, weiß ich nicht.

              Rolf

              --
              sumpsi - posui - obstruxi
              1. Hallo,

                Der Wert 0.01 bei isPixelSimilar ist der Unschärfewert für den Vergleich.

                der ist meines Erachtens zu klein gewählt. Aber ich würde auch nicht pixelweise vorgehen, sondern aus Blöcken zu, sagen wir mal, 4x4 Pixeln den Mittelwert bilden und den dann gegen eine Schwelle prüfen. Dann dürfen auch mal ein oder zwei dunkle Pixel dazwischen sein, wie sie bei schmuddeligen Scannern oft auftreten. Dass das den Rechenaufwand weiter hochtreibt, ist mir klar.

                Wie Transparenz sich auswirkt, weiß ich nicht.

                Die würde ich bei einer aus einem PDF gerenderten Grafik auch nicht erwarten.

                Einen schönen Tag noch
                 Martin

                --
                Falls ihr euch wundert, warum ihr zur Zeit so schlecht aus der Wohnung kommt:
                Das ist so, weil Weihnachten vor der Tür steht. 🎄 🎄 🎄
                1. Wie Transparenz sich auswirkt, weiß ich nicht.

                  Die würde ich bei einer aus einem PDF gerenderten Grafik auch nicht erwarten.

                  Ich hingegen durchaus. Ebenso wie Farbräume. CMYK 0,0,0,0 ist durchaus was Anderes als RGB 255,255,255. Analog ist es dann mit Transparenzen. Soweit der OP in seiner kontrollierten Umgebung unterwegs ist: so what, ok.

                  Soweit die Fragestellung des OP aber als allgemeingültig betrachtet werden soll, müssten Farbräume und Transparenzen dringend berücksichtigt werden.

                  Transparent kann je nach Kontext eine völlig andere Bedeutung haben, als das schneeweiß, was Dir Dein PDF-Viewer auf dem Screen zeigt. Schneeweiß je nach Leuchtkraft der Dioden. Schmuddelgrau tut's auch 😉

    2. Hallo Rolf,

      Du willst einen weißen Streifen finden, der

      • möglichst hoch oben ist
      • hoch genug ist

      Richtig?

      Nicht ganz richtig.
      Ich will einen weißen Streifen finden, der

      • möglichst weit unten ist
      • hoch genug ist

      So gehts (nur iterativ):

      function suche_freiraum($line = 842,$img2) {
          $freiraum = $failed = 0;
          $fp = fopen($_SERVER['DOCUMENT_ROOT']."/tmp/pixel.txt",'a+');
          for($myY = $line;$myY > 500;$myY--) {
              for($myX = 0;$myX < 530;$myX++) {
                  $pixel = $img2->getImagePixelColor($myX,$myY);
                  $colors = $pixel->getColorAsString();
                  if($colors != "srgba(255,255,255,0)" && $colors != "srgb(255,255,255)") {   // wenn kein weißes Pixel
                      $failed++;
                  }
              }
              // Line zuende und failed noch auf 0 ?
              if($failed == 0) {
                  $freiraum++;
                  fwrite($fp,"line ".$myY.": all white. Freiraum = ".$freiraum."\n");
              } else {
                  fwrite($fp,"line ".$myY.": failed\n");
                  $freiraum = 0;
                  $failed = 0;
              }
              if($freiraum == 150) {
                  fclose($fp);
                  return $myY;
              }
          }
          fclose($fp);
          return 0; // kein Freiraum gefunden
      }
      

      Jochen

  2. Moin Jochen,

    function suche_freiraum($line = 842,$img2) {
        $freiraum = $failed = 0;
        $fp = fopen($_SERVER['DOCUMENT_ROOT']."/tmp/pixel.txt",'a+');
    

    Hier wird die genannte Datei zum Anhängen geöffnet.

        for($myY = $line;$myY > 500;$myY--) {
            // Line zuende und failed noch auf 0 ?
                fwrite($fp,"line ".$myY.": failed\n");
                suche_freiraum($myY-1,$img2);
    

    Hier wird über die Rekursion diese Datei noch einmal zum Anhängen geöffnet.

            if($freiraum == 150) {
                fclose($fp);
                return $myY;
            }
        }
        fclose($fp);
        return 0; // kein Freiraum gefunden
    }
    

    Hier sind beide fclose hintereinander zu sehen – auf die gleichen Dateizeiger! Das sieht irgendwie falsch aus.

    Viele Grüße
    Robert

    1. Hallo Robert,

      nein, das ist unproblematisch weil hinter jedem fclose ein return steht. Er kommt also nie zum anderen fclose. Und da dieses File eh nur dem Debugging dient, wird es vermutlich demnächst eh aus dem Code fliegen.

      Aber - es wurde ja von Jochen schon angesprochen, dass es sinnvoll sei, Schleifen abzubrechen wenn ihre weitere Ausführung nichts mehr bringt. Das gilt für die Pixel in einer Zeile genau wie für die Suche über die Rows.

      Ich gehe jetzt mal von der iterativen Version ohne die kaputte Rekursion aus. Hier kann man mit dem Level-Parameter von Break bzw. Continue die Lesbarkeit großartig versauen, aber dafür den Code auch kräftig eindampfen:

      function suche_freiraum($line = 842,$img2) {
          $freiraum = 0;
          for ($myY = $line;$myY > 500;$myY--) {
              for ($myX = 0;$myX < 530;$myX++) {
                  ...
                  if ( /* Pixel bei (myX,myY) ist nicht weiß */ )
                     $freiraum = 0;
                     // Überspringe den Rest des myX UND myY-Durchlaufs!
                     continue 2;       
                  }
              }
      
              // Hier geht's nur hin wenn die Zeile weiß ist.
              if(++$freiraum == 150) {
                  return $myY;
              }
          }
          return 0;
      }
      

      Rolf

      --
      sumpsi - posui - obstruxi
      1. Hallo Rolf,

        // Überspringe den Rest des myX UND myY-Durchlaufs!
        continue 2;
        }

        PhP-Storm meldet: Cannot break/continue 2 level(s) und markiert es als Fehler.

        Edit: Missverständnis, Du meintest so:

        function suche_freiraum($line = 842,$img2)
        {
            $freiraum = $failed = 0;
            $fp = fopen($_SERVER['DOCUMENT_ROOT']."/tmp/pixel.txt",'a+');
            for($myY = $line;$myY > 500;$myY--) {
                for($myX = 0;$myX < 530;$myX++) {
                    $pixel = $img2->getImagePixelColor($myX,$myY);
                    $colors = $pixel->getColorAsString();
                    if($colors != "srgba(255,255,255,0)" && $colors != "srgb(255,255,255)") {   // wenn kein weißes Pixel
                        $failed++;
                        $freiraum = 0;
        //              $now = DateTime::createFromFormat('U.u',microtime(true));
        //              fwrite($fp,$now->format("d.m.Y H:i:s.u").": ");
        //              fwrite($fp,"line ".$myY.": failed\n");                
                        continue 2;
                    }
                }
                $freiraum++;
        //            $now = DateTime::createFromFormat('U.u',microtime(true));
        //            fwrite($fp,$now->format("d.m.Y H:i:s.u").": ");
        //            fwrite($fp,"line ".$myY.": all white. Freiraum = ".$freiraum."\n");
                if($freiraum == 125) {
                    fclose($fp);
                    return $myY;
                }
            }
            fclose($fp);
            return 0; // kein Freiraum gefunden
        }
        

        Jochen

        1. Bringt Einiges:

          20.12.2022 17:12:46.036000: line 842: all white. Freiraum = 1
          20.12.2022 17:12:46.037700: line 841: all white. Freiraum = 2
          20.12.2022 17:12:46.040400: line 840: all white. Freiraum = 3
          ...
          20.12.2022 17:12:46.256100: line 501: failed
          

          Zeitbedarf auf etwa 2/10 Sek geschrumpft. 👍

          Jochen